ide-cs.c 15.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*======================================================================

    A driver for PCMCIA IDE/ATA disk cards

    The contents of this file are subject to the Mozilla Public
    License Version 1.1 (the "License"); you may not use this file
    except in compliance with the License. You may obtain a copy of
    the License at http://www.mozilla.org/MPL/

    Software distributed under the License is distributed on an "AS
    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
    implied. See the License for the specific language governing
    rights and limitations under the License.

    The initial developer of the original code is David A. Hinds
    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.

    Alternatively, the contents of this file may be used under the
    terms of the GNU General Public License version 2 (the "GPL"), in
    which case the provisions of the GPL are applicable instead of the
    above.  If you wish to allow the use of your version of this file
    only under the terms of the GPL and not to allow others to use
    your version of this file under the MPL, indicate your decision
    by deleting the provisions above and replace them with the notice
    and other provisions required by the GPL.  If you do not delete
    the provisions above, a recipient may use your version of this
    file under either the MPL or the GPL.
29

L
Linus Torvalds 已提交
30 31 32 33 34 35 36 37 38 39 40 41
======================================================================*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/ide.h>
#include <linux/major.h>
42
#include <linux/delay.h>
L
Linus Torvalds 已提交
43 44 45 46 47 48 49 50 51 52
#include <asm/io.h>
#include <asm/system.h>

#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>

53 54
#define DRV_NAME "ide-cs"

L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62 63 64 65
/*====================================================================*/

/* Module parameters */

MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
MODULE_LICENSE("Dual MPL/GPL");

/*====================================================================*/

typedef struct ide_info_t {
66
	struct pcmcia_device	*p_dev;
67
	struct ide_host		*host;
L
Linus Torvalds 已提交
68 69 70 71
    int		ndev;
    dev_node_t	node;
} ide_info_t;

72
static void ide_release(struct pcmcia_device *);
73
static int ide_config(struct pcmcia_device *);
L
Linus Torvalds 已提交
74

75
static void ide_detach(struct pcmcia_device *p_dev);
L
Linus Torvalds 已提交
76

77 78


L
Linus Torvalds 已提交
79 80 81 82 83 84 85 86 87

/*======================================================================

    ide_attach() creates an "instance" of the driver, allocating
    local data structures for one device.  The device is registered
    with Card Services.

======================================================================*/

88
static int ide_probe(struct pcmcia_device *link)
L
Linus Torvalds 已提交
89 90
{
    ide_info_t *info;
91

92
    dev_dbg(&link->dev, "ide_attach()\n");
L
Linus Torvalds 已提交
93 94

    /* Create new ide device */
95
    info = kzalloc(sizeof(*info), GFP_KERNEL);
96 97
    if (!info)
	return -ENOMEM;
98

99
    info->p_dev = link;
100
    link->priv = info;
L
Linus Torvalds 已提交
101 102 103 104

    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
    link->io.IOAddrLines = 3;
105
    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
L
Linus Torvalds 已提交
106 107
    link->conf.Attributes = CONF_ENABLE_IRQ;
    link->conf.IntType = INT_MEMORY_AND_IO;
108

109
    return ide_config(link);
L
Linus Torvalds 已提交
110 111 112 113 114 115 116 117 118 119 120
} /* ide_attach */

/*======================================================================

    This deletes a driver "instance".  The device is de-registered
    with Card Services.  If it has been released, all local data
    structures are freed.  Otherwise, the structures will be freed
    when the device is released.

======================================================================*/

121
static void ide_detach(struct pcmcia_device *link)
L
Linus Torvalds 已提交
122
{
123 124
    ide_info_t *info = link->priv;

125
    dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
L
Linus Torvalds 已提交
126

127
    ide_release(link);
128

129
    kfree(info);
L
Linus Torvalds 已提交
130 131
} /* ide_detach */

132 133 134 135
static const struct ide_port_ops idecs_port_ops = {
	.quirkproc		= ide_undecoded_slave,
};

136 137 138
static const struct ide_port_info idecs_port_info = {
	.port_ops		= &idecs_port_ops,
	.host_flags		= IDE_HFLAG_NO_DMA,
139
	.irq_flags		= IRQF_SHARED,
140
	.chipset		= ide_pci,
141 142
};

143
static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
144
				unsigned long irq, struct pcmcia_device *handle)
L
Linus Torvalds 已提交
145
{
146
    struct ide_host *host;
147
    ide_hwif_t *hwif;
148
    int i, rc;
149
    struct ide_hw hw, *hws[] = { &hw };
150

151 152 153 154 155 156 157 158 159 160 161 162 163
    if (!request_region(io, 8, DRV_NAME)) {
	printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
			DRV_NAME, io, io + 7);
	return NULL;
    }

    if (!request_region(ctl, 1, DRV_NAME)) {
	printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
			DRV_NAME, ctl);
	release_region(io, 8);
	return NULL;
    }

L
Linus Torvalds 已提交
164
    memset(&hw, 0, sizeof(hw));
165
    ide_std_init_ports(&hw, io, ctl);
L
Linus Torvalds 已提交
166
    hw.irq = irq;
167
    hw.dev = &handle->dev;
168

169
    rc = ide_host_add(&idecs_port_info, hws, 1, &host);
170
    if (rc)
171
	goto out_release;
172

173
    hwif = host->ports[0];
174

175
    if (hwif->present)
176
	return host;
177

178 179 180 181 182
    /* retry registration in case device is still spinning up */
    for (i = 0; i < 10; i++) {
	msleep(100);
	ide_port_scan(hwif);
	if (hwif->present)
183
	    return host;
184 185
    }

186
    return host;
187

188 189 190 191
out_release:
    release_region(ctl, 1);
    release_region(io, 8);
    return NULL;
L
Linus Torvalds 已提交
192 193 194 195 196 197 198 199 200 201
}

/*======================================================================

    ide_config() is scheduled to run after a CARD_INSERTION event
    is received, to configure the PCMCIA socket, and to make the
    ide device available to the system.

======================================================================*/

202 203 204 205 206 207 208 209
struct pcmcia_config_check {
	unsigned long ctl_base;
	int skip_vcc;
	int is_kme;
};

static int pcmcia_check_one_config(struct pcmcia_device *pdev,
				   cistpl_cftable_entry_t *cfg,
210
				   cistpl_cftable_entry_t *dflt,
211
				   unsigned int vcc,
212 213 214 215 216 217 218
				   void *priv_data)
{
	struct pcmcia_config_check *stk = priv_data;

	/* Check for matching Vcc, unless we're desperate */
	if (!stk->skip_vcc) {
		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
219
			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
220 221
				return -ENODEV;
		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
222
			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
223
				return -ENODEV;
224 225 226 227 228
		}
	}

	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
		pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
229 230
	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
		pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
231

232 233
	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
234 235 236 237 238 239 240 241 242 243
		pdev->conf.ConfigIndex = cfg->index;
		pdev->io.BasePort1 = io->win[0].base;
		pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
		if (!(io->flags & CISTPL_IO_16BIT))
			pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
		if (io->nwin == 2) {
			pdev->io.NumPorts1 = 8;
			pdev->io.BasePort2 = io->win[1].base;
			pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
			if (pcmcia_request_io(pdev, &pdev->io) != 0)
244
				return -ENODEV;
245 246 247 248 249
			stk->ctl_base = pdev->io.BasePort2;
		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
			pdev->io.NumPorts1 = io->win[0].len;
			pdev->io.NumPorts2 = 0;
			if (pcmcia_request_io(pdev, &pdev->io) != 0)
250
				return -ENODEV;
251 252
			stk->ctl_base = pdev->io.BasePort1 + 0x0e;
		} else
253
			return -ENODEV;
254 255 256 257 258 259
		/* If we've got this far, we're done */
		return 0;
	}
	return -ENODEV;
}

260
static int ide_config(struct pcmcia_device *link)
L
Linus Torvalds 已提交
261 262
{
    ide_info_t *info = link->priv;
263
    struct pcmcia_config_check *stk = NULL;
264
    int ret = 0, is_kme = 0;
265
    unsigned long io_base, ctl_base;
266
    struct ide_host *host;
L
Linus Torvalds 已提交
267

268
    dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
L
Linus Torvalds 已提交
269

270 271 272
    is_kme = ((link->manf_id == MANFID_KME) &&
	      ((link->card_id == PRODID_KME_KXLC005_A) ||
	       (link->card_id == PRODID_KME_KXLC005_B)));
L
Linus Torvalds 已提交
273

274 275 276 277 278
    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
    if (!stk)
	    goto err_mem;
    stk->is_kme = is_kme;
    stk->skip_vcc = io_base = ctl_base = 0;
279

280 281 282 283
    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
	    stk->skip_vcc = 1;
	    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
		    goto failed; /* No suitable config found */
L
Linus Torvalds 已提交
284
    }
285 286
    io_base = link->io.BasePort1;
    ctl_base = stk->ctl_base;
L
Linus Torvalds 已提交
287

288 289 290 291 292 293
    ret = pcmcia_request_irq(link, &link->irq);
    if (ret)
	    goto failed;
    ret = pcmcia_request_configuration(link, &link->conf);
    if (ret)
	    goto failed;
L
Linus Torvalds 已提交
294 295

    /* disable drive interrupts during IDE probe */
296
    outb(0x02, ctl_base);
L
Linus Torvalds 已提交
297 298 299

    /* special setup for KXLC005 card */
    if (is_kme)
300
	outb(0x81, ctl_base+1);
L
Linus Torvalds 已提交
301

302 303
     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
     if (host == NULL && link->io.NumPorts1 == 0x20) {
304
	    outb(0x02, ctl_base + 0x10);
305
	    host = idecs_register(io_base + 0x10, ctl_base + 0x10,
306
				  link->irq.AssignedIRQ, link);
L
Linus Torvalds 已提交
307 308
    }

309
    if (host == NULL)
L
Linus Torvalds 已提交
310 311 312
	goto failed;

    info->ndev = 1;
313 314
    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
    info->node.major = host->ports[0]->major;
L
Linus Torvalds 已提交
315
    info->node.minor = 0;
316
    info->host = host;
317
    link->dev_node = &info->node;
318 319
    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
	   info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
L
Linus Torvalds 已提交
320 321

    kfree(stk);
322
    return 0;
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330

err_mem:
    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
    goto failed;

failed:
    kfree(stk);
    ide_release(link);
331
    return -ENODEV;
L
Linus Torvalds 已提交
332 333 334 335 336 337 338
} /* ide_config */

/*======================================================================

    After a card is removed, ide_release() will unregister the net
    device, and release the PCMCIA configuration.  If the device is
    still open, this will be postponed until it is closed.
339

L
Linus Torvalds 已提交
340 341
======================================================================*/

L
Larry Finger 已提交
342
static void ide_release(struct pcmcia_device *link)
L
Linus Torvalds 已提交
343 344
{
    ide_info_t *info = link->priv;
345
    struct ide_host *host = info->host;
346

347
    dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
L
Linus Torvalds 已提交
348

349 350 351 352 353 354 355
    if (info->ndev) {
	ide_hwif_t *hwif = host->ports[0];
	unsigned long data_addr, ctl_addr;

	data_addr = hwif->io_ports.data_addr;
	ctl_addr = hwif->io_ports.ctl_addr;

356
	ide_host_remove(host);
357
	info->ndev = 0;
358

359 360 361
	release_region(ctl_addr, 1);
	release_region(data_addr, 8);
    }
L
Linus Torvalds 已提交
362

363
    pcmcia_disable_device(link);
L
Linus Torvalds 已提交
364 365
} /* ide_release */

366

L
Linus Torvalds 已提交
367 368 369 370 371 372
/*======================================================================

    The card status event handler.  Mostly, this schedules other
    stuff to run after an event is received.  A CARD_REMOVAL event
    also sets some flags to discourage the ide drivers from
    talking to the ports.
373

L
Linus Torvalds 已提交
374 375
======================================================================*/

376 377
static struct pcmcia_device_id ide_ids[] = {
	PCMCIA_DEVICE_FUNC_ID(4),
378
	PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),	/* Corsair */
379
	PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),	/* Hitachi */
M
Magnus Damm 已提交
380 381
	PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),	/* I-O Data CFA */
	PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),	/* Mitsubishi CFA */
382
	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
383
	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
M
Magnus Damm 已提交
384
	PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),	/* SanDisk CFA */
385
	PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),	/* Kingston */
386
	PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), 	/* TI emulated */
387
	PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),	/* Toshiba */
388
	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
389
	PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),	/* Samsung */
390
	PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),	/* Hitachi */
391
	PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
M
Magnus Damm 已提交
392 393
	PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),	/* Viking CFA */
	PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),	/* Lexar, Viking CFA */
394 395 396 397 398
	PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
	PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
W
Wolfram Sang 已提交
399
	PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
400 401 402
	PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
	PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
	PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
K
Komuro 已提交
403
	PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
404 405 406
	PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
	PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
	PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
407 408
	PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
	PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
409
	PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
410
	PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
411
	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
412 413
	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17),
	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
414
	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
415 416 417 418
	PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
	PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
M
Matt Reimer 已提交
419
	PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
420
	PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
421
	PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
422 423 424
	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
	PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
425 426 427
	PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
	PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
428
	PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
429
	PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
430
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
431
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
432
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
433
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
434 435
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d),
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
436
	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
437
	PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
438
	PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
439
	PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
440
	PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
M
Marc Pignat 已提交
441
	PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
442 443 444 445
	PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, ide_ids);

L
Linus Torvalds 已提交
446 447 448 449 450
static struct pcmcia_driver ide_cs_driver = {
	.owner		= THIS_MODULE,
	.drv		= {
		.name	= "ide-cs",
	},
451
	.probe		= ide_probe,
452
	.remove		= ide_detach,
453
	.id_table       = ide_ids,
L
Linus Torvalds 已提交
454 455 456 457 458 459 460 461 462 463 464 465
};

static int __init init_ide_cs(void)
{
	return pcmcia_register_driver(&ide_cs_driver);
}

static void __exit exit_ide_cs(void)
{
	pcmcia_unregister_driver(&ide_cs_driver);
}

466
late_initcall(init_ide_cs);
L
Linus Torvalds 已提交
467
module_exit(exit_ide_cs);