ide-cs.c 15.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
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

Linus Torvalds's avatar
Linus Torvalds committed
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>
Linus Torvalds's avatar
Linus Torvalds committed
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"

Linus Torvalds's avatar
Linus Torvalds committed
55
56
57
58
59
60
61
62
63
64
/*====================================================================*/

/* Module parameters */

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

#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)

Larry Finger's avatar
Larry Finger committed
65
66
#ifdef CONFIG_PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, 0);
Linus Torvalds's avatar
Linus Torvalds committed
67
68
69
70
71
72
73
74
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
#else
#define DEBUG(n, args...)
#endif

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

typedef struct ide_info_t {
75
	struct pcmcia_device	*p_dev;
76
	struct ide_host		*host;
Linus Torvalds's avatar
Linus Torvalds committed
77
78
79
80
    int		ndev;
    dev_node_t	node;
} ide_info_t;

81
static void ide_release(struct pcmcia_device *);
82
static int ide_config(struct pcmcia_device *);
Linus Torvalds's avatar
Linus Torvalds committed
83

84
static void ide_detach(struct pcmcia_device *p_dev);
Linus Torvalds's avatar
Linus Torvalds committed
85

86
87


Linus Torvalds's avatar
Linus Torvalds committed
88
89
90
91
92
93
94
95
96

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

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

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

97
static int ide_probe(struct pcmcia_device *link)
Linus Torvalds's avatar
Linus Torvalds committed
98
99
{
    ide_info_t *info;
100

Linus Torvalds's avatar
Linus Torvalds committed
101
102
103
    DEBUG(0, "ide_attach()\n");

    /* Create new ide device */
104
    info = kzalloc(sizeof(*info), GFP_KERNEL);
105
106
    if (!info)
	return -ENOMEM;
107

108
    info->p_dev = link;
109
    link->priv = info;
Linus Torvalds's avatar
Linus Torvalds committed
110
111
112
113

    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
    link->io.IOAddrLines = 3;
114
    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
Linus Torvalds's avatar
Linus Torvalds committed
115
116
117
    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
    link->conf.Attributes = CONF_ENABLE_IRQ;
    link->conf.IntType = INT_MEMORY_AND_IO;
118

119
    return ide_config(link);
Linus Torvalds's avatar
Linus Torvalds committed
120
121
122
123
124
125
126
127
128
129
130
} /* 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.

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

131
static void ide_detach(struct pcmcia_device *link)
Linus Torvalds's avatar
Linus Torvalds committed
132
{
133
    ide_info_t *info = link->priv;
134
    ide_hwif_t *hwif = info->host->ports[0];
135
    unsigned long data_addr, ctl_addr;
136

Linus Torvalds's avatar
Linus Torvalds committed
137
138
    DEBUG(0, "ide_detach(0x%p)\n", link);

139
140
141
    data_addr = hwif->io_ports.data_addr;
    ctl_addr  = hwif->io_ports.ctl_addr;

142
    ide_release(link);
143

144
145
    release_region(ctl_addr, 1);
    release_region(data_addr, 8);
146
147

    kfree(info);
Linus Torvalds's avatar
Linus Torvalds committed
148
149
} /* ide_detach */

150
151
152
153
static const struct ide_port_ops idecs_port_ops = {
	.quirkproc		= ide_undecoded_slave,
};

154
155
156
static const struct ide_port_info idecs_port_info = {
	.port_ops		= &idecs_port_ops,
	.host_flags		= IDE_HFLAG_NO_DMA,
157
	.irq_flags		= IRQF_SHARED,
158
	.chipset		= ide_pci,
159
160
};

161
static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
162
				unsigned long irq, struct pcmcia_device *handle)
Linus Torvalds's avatar
Linus Torvalds committed
163
{
164
    struct ide_host *host;
165
    ide_hwif_t *hwif;
166
    int i, rc;
167
    struct ide_hw hw, *hws[] = { &hw };
168

169
170
171
172
173
174
175
176
177
178
179
180
181
    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;
    }

Linus Torvalds's avatar
Linus Torvalds committed
182
    memset(&hw, 0, sizeof(hw));
183
    ide_std_init_ports(&hw, io, ctl);
Linus Torvalds's avatar
Linus Torvalds committed
184
    hw.irq = irq;
185
    hw.dev = &handle->dev;
186

187
    rc = ide_host_add(&idecs_port_info, hws, 1, &host);
188
    if (rc)
189
	goto out_release;
190

191
    hwif = host->ports[0];
192

193
    if (hwif->present)
194
	return host;
195

196
197
198
199
200
    /* retry registration in case device is still spinning up */
    for (i = 0; i < 10; i++) {
	msleep(100);
	ide_port_scan(hwif);
	if (hwif->present)
201
	    return host;
202
203
    }

204
    return host;
205

206
207
208
209
out_release:
    release_region(ctl, 1);
    release_region(io, 8);
    return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
210
211
212
213
214
215
216
217
218
219
220
221
222
}

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

    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.

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

#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)

223
224
225
226
227
228
229
230
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,
231
				   cistpl_cftable_entry_t *dflt,
232
				   unsigned int vcc,
233
234
235
236
237
238
239
				   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)) {
240
			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
241
242
				return -ENODEV;
		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
243
			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
244
				return -ENODEV;
245
246
247
248
249
		}
	}

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

253
254
	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
255
256
257
258
259
260
261
262
263
264
		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)
265
				return -ENODEV;
266
267
268
269
270
			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)
271
				return -ENODEV;
272
273
			stk->ctl_base = pdev->io.BasePort1 + 0x0e;
		} else
274
			return -ENODEV;
275
276
277
278
279
280
		/* If we've got this far, we're done */
		return 0;
	}
	return -ENODEV;
}

281
static int ide_config(struct pcmcia_device *link)
Linus Torvalds's avatar
Linus Torvalds committed
282
283
{
    ide_info_t *info = link->priv;
284
285
    struct pcmcia_config_check *stk = NULL;
    int last_ret = 0, last_fn = 0, is_kme = 0;
286
    unsigned long io_base, ctl_base;
287
    struct ide_host *host;
Linus Torvalds's avatar
Linus Torvalds committed
288
289
290

    DEBUG(0, "ide_config(0x%p)\n", link);

291
292
293
    is_kme = ((link->manf_id == MANFID_KME) &&
	      ((link->card_id == PRODID_KME_KXLC005_A) ||
	       (link->card_id == PRODID_KME_KXLC005_B)));
Linus Torvalds's avatar
Linus Torvalds committed
294

295
296
297
298
299
    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
    if (!stk)
	    goto err_mem;
    stk->is_kme = is_kme;
    stk->skip_vcc = io_base = ctl_base = 0;
300

301
302
303
304
    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 */
Linus Torvalds's avatar
Linus Torvalds committed
305
    }
306
307
    io_base = link->io.BasePort1;
    ctl_base = stk->ctl_base;
Linus Torvalds's avatar
Linus Torvalds committed
308

309
310
    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
Linus Torvalds's avatar
Linus Torvalds committed
311
312

    /* disable drive interrupts during IDE probe */
313
    outb(0x02, ctl_base);
Linus Torvalds's avatar
Linus Torvalds committed
314
315
316

    /* special setup for KXLC005 card */
    if (is_kme)
317
	outb(0x81, ctl_base+1);
Linus Torvalds's avatar
Linus Torvalds committed
318

319
320
     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
     if (host == NULL && link->io.NumPorts1 == 0x20) {
321
	    outb(0x02, ctl_base + 0x10);
322
	    host = idecs_register(io_base + 0x10, ctl_base + 0x10,
323
				  link->irq.AssignedIRQ, link);
Linus Torvalds's avatar
Linus Torvalds committed
324
325
    }

326
    if (host == NULL)
Linus Torvalds's avatar
Linus Torvalds committed
327
328
329
	goto failed;

    info->ndev = 1;
330
331
    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
    info->node.major = host->ports[0]->major;
Linus Torvalds's avatar
Linus Torvalds committed
332
    info->node.minor = 0;
333
    info->host = host;
334
    link->dev_node = &info->node;
335
336
    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
	   info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
Linus Torvalds's avatar
Linus Torvalds committed
337
338

    kfree(stk);
339
    return 0;
Linus Torvalds's avatar
Linus Torvalds committed
340
341
342
343
344
345

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

cs_failed:
346
    cs_error(link, last_fn, last_ret);
Linus Torvalds's avatar
Linus Torvalds committed
347
348
349
failed:
    kfree(stk);
    ide_release(link);
350
    return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
351
352
353
354
355
356
357
} /* 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.
358

Linus Torvalds's avatar
Linus Torvalds committed
359
360
======================================================================*/

361
static void ide_release(struct pcmcia_device *link)
Linus Torvalds's avatar
Linus Torvalds committed
362
363
{
    ide_info_t *info = link->priv;
364
    struct ide_host *host = info->host;
365

Linus Torvalds's avatar
Linus Torvalds committed
366
367
    DEBUG(0, "ide_release(0x%p)\n", link);

368
    if (info->ndev)
Linus Torvalds's avatar
Linus Torvalds committed
369
370
	/* FIXME: if this fails we need to queue the cleanup somehow
	   -- need to investigate the required PCMCIA magic */
371
372
	ide_host_remove(host);

Linus Torvalds's avatar
Linus Torvalds committed
373
374
    info->ndev = 0;

375
    pcmcia_disable_device(link);
Linus Torvalds's avatar
Linus Torvalds committed
376
377
} /* ide_release */

378

Linus Torvalds's avatar
Linus Torvalds committed
379
380
381
382
383
384
/*======================================================================

    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.
385

Linus Torvalds's avatar
Linus Torvalds committed
386
387
======================================================================*/

388
389
static struct pcmcia_device_id ide_ids[] = {
	PCMCIA_DEVICE_FUNC_ID(4),
390
	PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),	/* Corsair */
391
	PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),	/* Hitachi */
Magnus Damm's avatar
Magnus Damm committed
392
393
	PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),	/* I-O Data CFA */
	PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),	/* Mitsubishi CFA */
394
	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
395
	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
Magnus Damm's avatar
Magnus Damm committed
396
	PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),	/* SanDisk CFA */
397
	PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),	/* Kingston */
398
	PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), 	/* TI emulated */
399
	PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),	/* Toshiba */
400
	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
401
	PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),	/* Samsung */
402
	PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),	/* Hitachi */
403
	PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
Magnus Damm's avatar
Magnus Damm committed
404
405
	PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),	/* Viking CFA */
	PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),	/* Lexar, Viking CFA */
406
407
408
409
410
	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),
411
	PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
412
413
414
	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),
Komuro's avatar
Komuro committed
415
	PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
416
417
418
	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),
419
420
	PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
	PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
421
	PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
422
	PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
423
	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
424
	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
425
426
427
428
	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),
Matt Reimer's avatar
Matt Reimer committed
429
	PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
430
	PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
431
	PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
432
433
434
	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),
435
436
437
	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),
438
	PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
439
	PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
440
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
441
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
442
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
443
	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
444
	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
445
	PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
446
	PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
447
	PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
448
	PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
Marc Pignat's avatar
Marc Pignat committed
449
	PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
450
451
452
453
	PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, ide_ids);

Linus Torvalds's avatar
Linus Torvalds committed
454
455
456
457
458
static struct pcmcia_driver ide_cs_driver = {
	.owner		= THIS_MODULE,
	.drv		= {
		.name	= "ide-cs",
	},
459
	.probe		= ide_probe,
460
	.remove		= ide_detach,
461
	.id_table       = ide_ids,
Linus Torvalds's avatar
Linus Torvalds committed
462
463
464
465
466
467
468
469
470
471
472
473
};

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);
}

474
late_initcall(init_ide_cs);
Linus Torvalds's avatar
Linus Torvalds committed
475
module_exit(exit_ide_cs);