cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vrc4171_card.c (17477B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
      4 *
      5 * Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
      6 */
      7#include <linux/init.h>
      8#include <linux/ioport.h>
      9#include <linux/interrupt.h>
     10#include <linux/module.h>
     11#include <linux/spinlock.h>
     12#include <linux/types.h>
     13#include <linux/platform_device.h>
     14
     15#include <asm/io.h>
     16
     17#include <pcmcia/ss.h>
     18
     19#include "i82365.h"
     20
     21MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
     22MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
     23MODULE_LICENSE("GPL");
     24
     25#define CARD_MAX_SLOTS		2
     26#define CARD_SLOTA		0
     27#define CARD_SLOTB		1
     28#define CARD_SLOTB_OFFSET	0x40
     29
     30#define CARD_MEM_START		0x10000000
     31#define CARD_MEM_END		0x13ffffff
     32#define CARD_MAX_MEM_OFFSET	0x3ffffff
     33#define CARD_MAX_MEM_SPEED	1000
     34
     35#define CARD_CONTROLLER_INDEX	0x03e0
     36#define CARD_CONTROLLER_DATA	0x03e1
     37 /* Power register */
     38  #define VPP_GET_VCC		0x01
     39  #define POWER_ENABLE		0x10
     40 #define CARD_VOLTAGE_SENSE	0x1f
     41  #define VCC_3VORXV_CAPABLE	0x00
     42  #define VCC_XV_ONLY		0x01
     43  #define VCC_3V_CAPABLE	0x02
     44  #define VCC_5V_ONLY		0x03
     45 #define CARD_VOLTAGE_SELECT	0x2f
     46  #define VCC_3V		0x01
     47  #define VCC_5V		0x00
     48  #define VCC_XV		0x02
     49  #define VCC_STATUS_3V		0x02
     50  #define VCC_STATUS_5V		0x01
     51  #define VCC_STATUS_XV		0x03
     52 #define GLOBAL_CONTROL		0x1e
     53  #define EXWRBK		0x04
     54  #define IRQPM_EN		0x08
     55  #define CLRPMIRQ		0x10
     56
     57#define INTERRUPT_STATUS	0x05fa
     58 #define IRQ_A			0x02
     59 #define IRQ_B			0x04
     60
     61#define CONFIGURATION1		0x05fe
     62 #define SLOTB_CONFIG		0xc000
     63 #define SLOTB_NONE		0x0000
     64 #define SLOTB_PCCARD		0x4000
     65 #define SLOTB_CF		0x8000
     66 #define SLOTB_FLASHROM		0xc000
     67
     68#define CARD_CONTROLLER_START	CARD_CONTROLLER_INDEX
     69#define CARD_CONTROLLER_END	CARD_CONTROLLER_DATA
     70
     71#define IO_MAX_MAPS	2
     72#define MEM_MAX_MAPS	5
     73
     74enum vrc4171_slot {
     75	SLOT_PROBE = 0,
     76	SLOT_NOPROBE_IO,
     77	SLOT_NOPROBE_MEM,
     78	SLOT_NOPROBE_ALL,
     79	SLOT_INITIALIZED,
     80};
     81
     82enum vrc4171_slotb {
     83	SLOTB_IS_NONE,
     84	SLOTB_IS_PCCARD,
     85	SLOTB_IS_CF,
     86	SLOTB_IS_FLASHROM,
     87};
     88
     89struct vrc4171_socket {
     90	enum vrc4171_slot slot;
     91	struct pcmcia_socket pcmcia_socket;
     92	char name[24];
     93	int csc_irq;
     94	int io_irq;
     95	spinlock_t lock;
     96};
     97
     98static struct vrc4171_socket vrc4171_sockets[CARD_MAX_SLOTS];
     99static enum vrc4171_slotb vrc4171_slotb = SLOTB_IS_NONE;
    100static char vrc4171_card_name[] = "NEC VRC4171 Card Controller";
    101static unsigned int vrc4171_irq;
    102static uint16_t vrc4171_irq_mask = 0xdeb8;
    103
    104static struct resource vrc4171_card_resource[3] = {
    105	{	.name		= vrc4171_card_name,
    106		.start		= CARD_CONTROLLER_START,
    107		.end		= CARD_CONTROLLER_END,
    108		.flags		= IORESOURCE_IO,	},
    109	{	.name		= vrc4171_card_name,
    110		.start		= INTERRUPT_STATUS,
    111		.end		= INTERRUPT_STATUS,
    112		.flags		= IORESOURCE_IO,	},
    113	{	.name		= vrc4171_card_name,
    114		.start		= CONFIGURATION1,
    115		.end		= CONFIGURATION1,
    116		.flags		= IORESOURCE_IO,	},
    117};
    118
    119static struct platform_device vrc4171_card_device = {
    120	.name		= vrc4171_card_name,
    121	.id		= 0,
    122	.num_resources	= 3,
    123	.resource	= vrc4171_card_resource,
    124};
    125
    126static inline uint16_t vrc4171_get_irq_status(void)
    127{
    128	return inw(INTERRUPT_STATUS);
    129}
    130
    131static inline void vrc4171_set_multifunction_pin(enum vrc4171_slotb config)
    132{
    133	uint16_t config1;
    134
    135	config1 = inw(CONFIGURATION1);
    136	config1 &= ~SLOTB_CONFIG;
    137
    138	switch (config) {
    139	case SLOTB_IS_NONE:
    140		config1 |= SLOTB_NONE;
    141		break;
    142	case SLOTB_IS_PCCARD:
    143		config1 |= SLOTB_PCCARD;
    144		break;
    145	case SLOTB_IS_CF:
    146		config1 |= SLOTB_CF;
    147		break;
    148	case SLOTB_IS_FLASHROM:
    149		config1 |= SLOTB_FLASHROM;
    150		break;
    151	default:
    152		break;
    153	}
    154
    155	outw(config1, CONFIGURATION1);
    156}
    157
    158static inline uint8_t exca_read_byte(int slot, uint8_t index)
    159{
    160	if (slot == CARD_SLOTB)
    161		index += CARD_SLOTB_OFFSET;
    162
    163	outb(index, CARD_CONTROLLER_INDEX);
    164	return inb(CARD_CONTROLLER_DATA);
    165}
    166
    167static inline uint16_t exca_read_word(int slot, uint8_t index)
    168{
    169	uint16_t data;
    170
    171	if (slot == CARD_SLOTB)
    172		index += CARD_SLOTB_OFFSET;
    173
    174	outb(index++, CARD_CONTROLLER_INDEX);
    175	data = inb(CARD_CONTROLLER_DATA);
    176
    177	outb(index, CARD_CONTROLLER_INDEX);
    178	data |= ((uint16_t)inb(CARD_CONTROLLER_DATA)) << 8;
    179
    180	return data;
    181}
    182
    183static inline uint8_t exca_write_byte(int slot, uint8_t index, uint8_t data)
    184{
    185	if (slot == CARD_SLOTB)
    186		index += CARD_SLOTB_OFFSET;
    187
    188	outb(index, CARD_CONTROLLER_INDEX);
    189	outb(data, CARD_CONTROLLER_DATA);
    190
    191	return data;
    192}
    193
    194static inline uint16_t exca_write_word(int slot, uint8_t index, uint16_t data)
    195{
    196	if (slot == CARD_SLOTB)
    197		index += CARD_SLOTB_OFFSET;
    198
    199	outb(index++, CARD_CONTROLLER_INDEX);
    200	outb(data, CARD_CONTROLLER_DATA);
    201
    202	outb(index, CARD_CONTROLLER_INDEX);
    203	outb((uint8_t)(data >> 8), CARD_CONTROLLER_DATA);
    204
    205	return data;
    206}
    207
    208static inline int search_nonuse_irq(void)
    209{
    210	int i;
    211
    212	for (i = 0; i < 16; i++) {
    213		if (vrc4171_irq_mask & (1 << i)) {
    214			vrc4171_irq_mask &= ~(1 << i);
    215			return i;
    216		}
    217	}
    218
    219	return -1;
    220}
    221
    222static int pccard_init(struct pcmcia_socket *sock)
    223{
    224	struct vrc4171_socket *socket;
    225	unsigned int slot;
    226
    227	sock->features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS;
    228	sock->irq_mask = 0;
    229	sock->map_size = 0x1000;
    230	sock->pci_irq = vrc4171_irq;
    231
    232	slot = sock->sock;
    233	socket = &vrc4171_sockets[slot];
    234	socket->csc_irq = search_nonuse_irq();
    235	socket->io_irq = search_nonuse_irq();
    236	spin_lock_init(&socket->lock);
    237
    238	return 0;
    239}
    240
    241static int pccard_get_status(struct pcmcia_socket *sock, u_int *value)
    242{
    243	unsigned int slot;
    244	uint8_t status, sense;
    245	u_int val = 0;
    246
    247	if (sock == NULL || sock->sock >= CARD_MAX_SLOTS || value == NULL)
    248		return -EINVAL;
    249
    250	slot = sock->sock;
    251
    252	status = exca_read_byte(slot, I365_STATUS);
    253	if (exca_read_byte(slot, I365_INTCTL) & I365_PC_IOCARD) {
    254		if (status & I365_CS_STSCHG)
    255			val |= SS_STSCHG;
    256	} else {
    257		if (!(status & I365_CS_BVD1))
    258			val |= SS_BATDEAD;
    259		else if ((status & (I365_CS_BVD1 | I365_CS_BVD2)) == I365_CS_BVD1)
    260			val |= SS_BATWARN;
    261	}
    262	if ((status & I365_CS_DETECT) == I365_CS_DETECT)
    263		val |= SS_DETECT;
    264	if (status & I365_CS_WRPROT)
    265		val |= SS_WRPROT;
    266	if (status & I365_CS_READY)
    267		val |= SS_READY;
    268	if (status & I365_CS_POWERON)
    269		val |= SS_POWERON;
    270
    271	sense = exca_read_byte(slot, CARD_VOLTAGE_SENSE);
    272	switch (sense) {
    273	case VCC_3VORXV_CAPABLE:
    274		val |= SS_3VCARD | SS_XVCARD;
    275		break;
    276	case VCC_XV_ONLY:
    277		val |= SS_XVCARD;
    278		break;
    279	case VCC_3V_CAPABLE:
    280		val |= SS_3VCARD;
    281		break;
    282	default:
    283		/* 5V only */
    284		break;
    285	}
    286
    287	*value = val;
    288
    289	return 0;
    290}
    291
    292static inline uint8_t set_Vcc_value(u_char Vcc)
    293{
    294	switch (Vcc) {
    295	case 33:
    296		return VCC_3V;
    297	case 50:
    298		return VCC_5V;
    299	}
    300
    301	/* Small voltage is chosen for safety. */
    302	return VCC_3V;
    303}
    304
    305static int pccard_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
    306{
    307	struct vrc4171_socket *socket;
    308	unsigned int slot;
    309	uint8_t voltage, power, control, cscint;
    310
    311	if (sock == NULL || sock->sock >= CARD_MAX_SLOTS ||
    312	    (state->Vpp != state->Vcc && state->Vpp != 0) ||
    313	    (state->Vcc != 50 && state->Vcc != 33 && state->Vcc != 0))
    314		return -EINVAL;
    315
    316	slot = sock->sock;
    317	socket = &vrc4171_sockets[slot];
    318
    319	spin_lock_irq(&socket->lock);
    320
    321	voltage = set_Vcc_value(state->Vcc);
    322	exca_write_byte(slot, CARD_VOLTAGE_SELECT, voltage);
    323
    324	power = POWER_ENABLE;
    325	if (state->Vpp == state->Vcc)
    326		power |= VPP_GET_VCC;
    327	if (state->flags & SS_OUTPUT_ENA)
    328		power |= I365_PWR_OUT;
    329	exca_write_byte(slot, I365_POWER, power);
    330
    331	control = 0;
    332	if (state->io_irq != 0)
    333		control |= socket->io_irq;
    334	if (state->flags & SS_IOCARD)
    335		control |= I365_PC_IOCARD;
    336	if (state->flags & SS_RESET)
    337		control	&= ~I365_PC_RESET;
    338	else
    339		control |= I365_PC_RESET;
    340	exca_write_byte(slot, I365_INTCTL, control);
    341
    342        cscint = 0;
    343        exca_write_byte(slot, I365_CSCINT, cscint);
    344	exca_read_byte(slot, I365_CSC);	/* clear CardStatus change */
    345	if (state->csc_mask != 0)
    346		cscint |= socket->csc_irq << 8;
    347	if (state->flags & SS_IOCARD) {
    348		if (state->csc_mask & SS_STSCHG)
    349			cscint |= I365_CSC_STSCHG;
    350	} else {
    351		if (state->csc_mask & SS_BATDEAD)
    352			cscint |= I365_CSC_BVD1;
    353		if (state->csc_mask & SS_BATWARN)
    354			cscint |= I365_CSC_BVD2;
    355	}
    356	if (state->csc_mask & SS_READY)
    357		cscint |= I365_CSC_READY;
    358	if (state->csc_mask & SS_DETECT)
    359		cscint |= I365_CSC_DETECT;
    360        exca_write_byte(slot, I365_CSCINT, cscint);
    361
    362	spin_unlock_irq(&socket->lock);
    363
    364	return 0;
    365}
    366
    367static int pccard_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
    368{
    369	unsigned int slot;
    370	uint8_t ioctl, addrwin;
    371	u_char map;
    372
    373	if (sock == NULL || sock->sock >= CARD_MAX_SLOTS ||
    374	    io == NULL || io->map >= IO_MAX_MAPS ||
    375	    io->start > 0xffff || io->stop > 0xffff || io->start > io->stop)
    376		return -EINVAL;
    377
    378	slot = sock->sock;
    379	map = io->map;
    380
    381	addrwin = exca_read_byte(slot, I365_ADDRWIN);
    382	if (addrwin & I365_ENA_IO(map)) {
    383		addrwin &= ~I365_ENA_IO(map);
    384		exca_write_byte(slot, I365_ADDRWIN, addrwin);
    385	}
    386
    387	exca_write_word(slot, I365_IO(map)+I365_W_START, io->start);
    388	exca_write_word(slot, I365_IO(map)+I365_W_STOP, io->stop);
    389
    390	ioctl = 0;
    391	if (io->speed > 0)
    392		ioctl |= I365_IOCTL_WAIT(map);
    393	if (io->flags & MAP_16BIT)
    394		ioctl |= I365_IOCTL_16BIT(map);
    395	if (io->flags & MAP_AUTOSZ)
    396		ioctl |= I365_IOCTL_IOCS16(map);
    397	if (io->flags & MAP_0WS)
    398		ioctl |= I365_IOCTL_0WS(map);
    399	exca_write_byte(slot, I365_IOCTL, ioctl);
    400
    401	if (io->flags & MAP_ACTIVE) {
    402		addrwin |= I365_ENA_IO(map);
    403		exca_write_byte(slot, I365_ADDRWIN, addrwin);
    404	}
    405
    406	return 0;
    407}
    408
    409static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
    410{
    411	unsigned int slot;
    412	uint16_t start, stop, offset;
    413	uint8_t addrwin;
    414	u_char map;
    415
    416	if (sock == NULL || sock->sock >= CARD_MAX_SLOTS ||
    417	    mem == NULL || mem->map >= MEM_MAX_MAPS ||
    418	    mem->res->start < CARD_MEM_START || mem->res->start > CARD_MEM_END ||
    419	    mem->res->end < CARD_MEM_START || mem->res->end > CARD_MEM_END ||
    420	    mem->res->start > mem->res->end ||
    421	    mem->card_start > CARD_MAX_MEM_OFFSET ||
    422	    mem->speed > CARD_MAX_MEM_SPEED)
    423		return -EINVAL;
    424
    425	slot = sock->sock;
    426	map = mem->map;
    427
    428	addrwin = exca_read_byte(slot, I365_ADDRWIN);
    429	if (addrwin & I365_ENA_MEM(map)) {
    430		addrwin &= ~I365_ENA_MEM(map);
    431		exca_write_byte(slot, I365_ADDRWIN, addrwin);
    432	}
    433
    434	start = (mem->res->start >> 12) & 0x3fff;
    435	if (mem->flags & MAP_16BIT)
    436		start |= I365_MEM_16BIT;
    437	exca_write_word(slot, I365_MEM(map)+I365_W_START, start);
    438
    439	stop = (mem->res->end >> 12) & 0x3fff;
    440	switch (mem->speed) {
    441	case 0:
    442		break;
    443	case 1:
    444		stop |= I365_MEM_WS0;
    445		break;
    446	case 2:
    447		stop |= I365_MEM_WS1;
    448		break;
    449	default:
    450		stop |= I365_MEM_WS0 | I365_MEM_WS1;
    451		break;
    452	}
    453	exca_write_word(slot, I365_MEM(map)+I365_W_STOP, stop);
    454
    455	offset = (mem->card_start >> 12) & 0x3fff;
    456	if (mem->flags & MAP_ATTRIB)
    457		offset |= I365_MEM_REG;
    458	if (mem->flags & MAP_WRPROT)
    459		offset |= I365_MEM_WRPROT;
    460	exca_write_word(slot, I365_MEM(map)+I365_W_OFF, offset);
    461
    462	if (mem->flags & MAP_ACTIVE) {
    463		addrwin |= I365_ENA_MEM(map);
    464		exca_write_byte(slot, I365_ADDRWIN, addrwin);
    465	}
    466
    467	return 0;
    468}
    469
    470static struct pccard_operations vrc4171_pccard_operations = {
    471	.init			= pccard_init,
    472	.get_status		= pccard_get_status,
    473	.set_socket		= pccard_set_socket,
    474	.set_io_map		= pccard_set_io_map,
    475	.set_mem_map		= pccard_set_mem_map,
    476};
    477
    478static inline unsigned int get_events(int slot)
    479{
    480	unsigned int events = 0;
    481	uint8_t status, csc;
    482
    483	status = exca_read_byte(slot, I365_STATUS);
    484	csc = exca_read_byte(slot, I365_CSC);
    485
    486	if (exca_read_byte(slot, I365_INTCTL) & I365_PC_IOCARD) {
    487		if ((csc & I365_CSC_STSCHG) && (status & I365_CS_STSCHG))
    488			events |= SS_STSCHG;
    489	} else {
    490		if (csc & (I365_CSC_BVD1 | I365_CSC_BVD2)) {
    491			if (!(status & I365_CS_BVD1))
    492				events |= SS_BATDEAD;
    493			else if ((status & (I365_CS_BVD1 | I365_CS_BVD2)) == I365_CS_BVD1)
    494				events |= SS_BATWARN;
    495		}
    496	}
    497	if ((csc & I365_CSC_READY) && (status & I365_CS_READY))
    498		events |= SS_READY;
    499	if ((csc & I365_CSC_DETECT) && ((status & I365_CS_DETECT) == I365_CS_DETECT))
    500		events |= SS_DETECT;
    501
    502	return events;
    503}
    504
    505static irqreturn_t pccard_interrupt(int irq, void *dev_id)
    506{
    507	struct vrc4171_socket *socket;
    508	unsigned int events;
    509	irqreturn_t retval = IRQ_NONE;
    510	uint16_t status;
    511
    512	status = vrc4171_get_irq_status();
    513	if (status & IRQ_A) {
    514		socket = &vrc4171_sockets[CARD_SLOTA];
    515		if (socket->slot == SLOT_INITIALIZED) {
    516			if (status & (1 << socket->csc_irq)) {
    517				events = get_events(CARD_SLOTA);
    518				if (events != 0) {
    519					pcmcia_parse_events(&socket->pcmcia_socket, events);
    520					retval = IRQ_HANDLED;
    521				}
    522			}
    523		}
    524	}
    525
    526	if (status & IRQ_B) {
    527		socket = &vrc4171_sockets[CARD_SLOTB];
    528		if (socket->slot == SLOT_INITIALIZED) {
    529			if (status & (1 << socket->csc_irq)) {
    530				events = get_events(CARD_SLOTB);
    531				if (events != 0) {
    532					pcmcia_parse_events(&socket->pcmcia_socket, events);
    533					retval = IRQ_HANDLED;
    534				}
    535			}
    536		}
    537	}
    538
    539	return retval;
    540}
    541
    542static inline void reserve_using_irq(int slot)
    543{
    544	unsigned int irq;
    545
    546	irq = exca_read_byte(slot, I365_INTCTL);
    547	irq &= 0x0f;
    548	vrc4171_irq_mask &= ~(1 << irq);
    549
    550	irq = exca_read_byte(slot, I365_CSCINT);
    551	irq = (irq & 0xf0) >> 4;
    552	vrc4171_irq_mask &= ~(1 << irq);
    553}
    554
    555static int vrc4171_add_sockets(void)
    556{
    557	struct vrc4171_socket *socket;
    558	int slot, retval;
    559
    560	for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
    561		if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
    562			continue;
    563
    564		socket = &vrc4171_sockets[slot];
    565		if (socket->slot != SLOT_PROBE) {
    566			uint8_t addrwin;
    567
    568			switch (socket->slot) {
    569			case SLOT_NOPROBE_MEM:
    570				addrwin = exca_read_byte(slot, I365_ADDRWIN);
    571				addrwin &= 0x1f;
    572				exca_write_byte(slot, I365_ADDRWIN, addrwin);
    573				break;
    574			case SLOT_NOPROBE_IO:
    575				addrwin = exca_read_byte(slot, I365_ADDRWIN);
    576				addrwin &= 0xc0;
    577				exca_write_byte(slot, I365_ADDRWIN, addrwin);
    578				break;
    579			default:
    580				break;
    581			}
    582
    583			reserve_using_irq(slot);
    584			continue;
    585		}
    586
    587		sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
    588		socket->pcmcia_socket.dev.parent = &vrc4171_card_device.dev;
    589		socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
    590		socket->pcmcia_socket.owner = THIS_MODULE;
    591
    592		retval = pcmcia_register_socket(&socket->pcmcia_socket);
    593		if (retval < 0)
    594			return retval;
    595
    596		exca_write_byte(slot, I365_ADDRWIN, 0);
    597		exca_write_byte(slot, GLOBAL_CONTROL, 0);
    598
    599		socket->slot = SLOT_INITIALIZED;
    600	}
    601
    602	return 0;
    603}
    604
    605static void vrc4171_remove_sockets(void)
    606{
    607	struct vrc4171_socket *socket;
    608	int slot;
    609
    610	for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
    611		if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
    612			continue;
    613
    614		socket = &vrc4171_sockets[slot];
    615		if (socket->slot == SLOT_INITIALIZED)
    616			pcmcia_unregister_socket(&socket->pcmcia_socket);
    617
    618		socket->slot = SLOT_PROBE;
    619	}
    620}
    621
    622static int vrc4171_card_setup(char *options)
    623{
    624	if (options == NULL || *options == '\0')
    625		return 1;
    626
    627	if (strncmp(options, "irq:", 4) == 0) {
    628		int irq;
    629		options += 4;
    630		irq = simple_strtoul(options, &options, 0);
    631		if (irq >= 0 && irq < nr_irqs)
    632			vrc4171_irq = irq;
    633
    634		if (*options != ',')
    635			return 1;
    636		options++;
    637	}
    638
    639	if (strncmp(options, "slota:", 6) == 0) {
    640		options += 6;
    641		if (*options != '\0') {
    642			if (strncmp(options, "memnoprobe", 10) == 0) {
    643				vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_MEM;
    644				options += 10;
    645			} else if (strncmp(options, "ionoprobe", 9) == 0) {
    646				vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_IO;
    647				options += 9;
    648			} else if ( strncmp(options, "noprobe", 7) == 0) {
    649				vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_ALL;
    650				options += 7;
    651			}
    652
    653			if (*options != ',')
    654				return 1;
    655			options++;
    656		} else
    657			return 1;
    658
    659	}
    660
    661	if (strncmp(options, "slotb:", 6) == 0) {
    662		options += 6;
    663		if (*options != '\0') {
    664			if (strncmp(options, "pccard", 6) == 0) {
    665				vrc4171_slotb = SLOTB_IS_PCCARD;
    666				options += 6;
    667			} else if (strncmp(options, "cf", 2) == 0) {
    668				vrc4171_slotb = SLOTB_IS_CF;
    669				options += 2;
    670			} else if (strncmp(options, "flashrom", 8) == 0) {
    671				vrc4171_slotb = SLOTB_IS_FLASHROM;
    672				options += 8;
    673			} else if (strncmp(options, "none", 4) == 0) {
    674				vrc4171_slotb = SLOTB_IS_NONE;
    675				options += 4;
    676			}
    677
    678			if (*options != ',')
    679				return 1;
    680			options++;
    681
    682			if (strncmp(options, "memnoprobe", 10) == 0)
    683				vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_MEM;
    684			if (strncmp(options, "ionoprobe", 9) == 0)
    685				vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_IO;
    686			if (strncmp(options, "noprobe", 7) == 0)
    687				vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_ALL;
    688		}
    689	}
    690
    691	return 1;
    692}
    693
    694__setup("vrc4171_card=", vrc4171_card_setup);
    695
    696static struct platform_driver vrc4171_card_driver = {
    697	.driver = {
    698		.name		= vrc4171_card_name,
    699	},
    700};
    701
    702static int vrc4171_card_init(void)
    703{
    704	int retval;
    705
    706	retval = platform_driver_register(&vrc4171_card_driver);
    707	if (retval < 0)
    708		return retval;
    709
    710	retval = platform_device_register(&vrc4171_card_device);
    711	if (retval < 0) {
    712		platform_driver_unregister(&vrc4171_card_driver);
    713		return retval;
    714	}
    715
    716	vrc4171_set_multifunction_pin(vrc4171_slotb);
    717
    718	retval = vrc4171_add_sockets();
    719	if (retval == 0)
    720		retval = request_irq(vrc4171_irq, pccard_interrupt, IRQF_SHARED,
    721		                     vrc4171_card_name, vrc4171_sockets);
    722
    723	if (retval < 0) {
    724		vrc4171_remove_sockets();
    725		platform_device_unregister(&vrc4171_card_device);
    726		platform_driver_unregister(&vrc4171_card_driver);
    727		return retval;
    728	}
    729
    730	printk(KERN_INFO "%s, connected to IRQ %d\n",
    731		vrc4171_card_driver.driver.name, vrc4171_irq);
    732
    733	return 0;
    734}
    735
    736static void vrc4171_card_exit(void)
    737{
    738	free_irq(vrc4171_irq, vrc4171_sockets);
    739	vrc4171_remove_sockets();
    740	platform_device_unregister(&vrc4171_card_device);
    741	platform_driver_unregister(&vrc4171_card_driver);
    742}
    743
    744module_init(vrc4171_card_init);
    745module_exit(vrc4171_card_exit);