]> err.no Git - linux-2.6/blob - drivers/ide/legacy/ide-cs.c
ide-cs: fix probing and add warm-plug support
[linux-2.6] / drivers / ide / legacy / ide-cs.c
1 /*======================================================================
2
3     A driver for PCMCIA IDE/ATA disk cards
4
5     The contents of this file are subject to the Mozilla Public
6     License Version 1.1 (the "License"); you may not use this file
7     except in compliance with the License. You may obtain a copy of
8     the License at http://www.mozilla.org/MPL/
9
10     Software distributed under the License is distributed on an "AS
11     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12     implied. See the License for the specific language governing
13     rights and limitations under the License.
14
15     The initial developer of the original code is David A. Hinds
16     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
17     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
18
19     Alternatively, the contents of this file may be used under the
20     terms of the GNU General Public License version 2 (the "GPL"), in
21     which case the provisions of the GPL are applicable instead of the
22     above.  If you wish to allow the use of your version of this file
23     only under the terms of the GPL and not to allow others to use
24     your version of this file under the MPL, indicate your decision
25     by deleting the provisions above and replace them with the notice
26     and other provisions required by the GPL.  If you do not delete
27     the provisions above, a recipient may use your version of this
28     file under either the MPL or the GPL.
29
30 ======================================================================*/
31
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/ptrace.h>
36 #include <linux/slab.h>
37 #include <linux/string.h>
38 #include <linux/timer.h>
39 #include <linux/ioport.h>
40 #include <linux/ide.h>
41 #include <linux/hdreg.h>
42 #include <linux/major.h>
43 #include <linux/delay.h>
44 #include <asm/io.h>
45 #include <asm/system.h>
46
47 #include <pcmcia/cs_types.h>
48 #include <pcmcia/cs.h>
49 #include <pcmcia/cistpl.h>
50 #include <pcmcia/ds.h>
51 #include <pcmcia/cisreg.h>
52 #include <pcmcia/ciscode.h>
53
54 #define DRV_NAME "ide-cs"
55
56 /*====================================================================*/
57
58 /* Module parameters */
59
60 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
61 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
62 MODULE_LICENSE("Dual MPL/GPL");
63
64 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
65
66 #ifdef PCMCIA_DEBUG
67 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
68 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
69 static char *version =
70 "ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
71 #else
72 #define DEBUG(n, args...)
73 #endif
74
75 /*====================================================================*/
76
77 typedef struct ide_info_t {
78         struct pcmcia_device    *p_dev;
79         ide_hwif_t              *hwif;
80     int         ndev;
81     dev_node_t  node;
82 } ide_info_t;
83
84 static void ide_release(struct pcmcia_device *);
85 static int ide_config(struct pcmcia_device *);
86
87 static void ide_detach(struct pcmcia_device *p_dev);
88
89
90
91
92 /*======================================================================
93
94     ide_attach() creates an "instance" of the driver, allocating
95     local data structures for one device.  The device is registered
96     with Card Services.
97
98 ======================================================================*/
99
100 static int ide_probe(struct pcmcia_device *link)
101 {
102     ide_info_t *info;
103
104     DEBUG(0, "ide_attach()\n");
105
106     /* Create new ide device */
107     info = kzalloc(sizeof(*info), GFP_KERNEL);
108     if (!info)
109         return -ENOMEM;
110
111     info->p_dev = link;
112     link->priv = info;
113
114     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
115     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
116     link->io.IOAddrLines = 3;
117     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
118     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
119     link->conf.Attributes = CONF_ENABLE_IRQ;
120     link->conf.IntType = INT_MEMORY_AND_IO;
121
122     return ide_config(link);
123 } /* ide_attach */
124
125 /*======================================================================
126
127     This deletes a driver "instance".  The device is de-registered
128     with Card Services.  If it has been released, all local data
129     structures are freed.  Otherwise, the structures will be freed
130     when the device is released.
131
132 ======================================================================*/
133
134 static void ide_detach(struct pcmcia_device *link)
135 {
136     ide_info_t *info = link->priv;
137     ide_hwif_t *hwif = info->hwif;
138
139     DEBUG(0, "ide_detach(0x%p)\n", link);
140
141     ide_release(link);
142
143     release_region(hwif->io_ports.ctl_addr, 1);
144     release_region(hwif->io_ports.data_addr, 8);
145
146     kfree(info);
147 } /* ide_detach */
148
149 static const struct ide_port_ops idecs_port_ops = {
150         .quirkproc              = ide_undecoded_slave,
151 };
152
153 static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
154                                 unsigned long irq, struct pcmcia_device *handle)
155 {
156     ide_hwif_t *hwif;
157     hw_regs_t hw;
158     int i;
159     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
160
161     if (!request_region(io, 8, DRV_NAME)) {
162         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
163                         DRV_NAME, io, io + 7);
164         return NULL;
165     }
166
167     if (!request_region(ctl, 1, DRV_NAME)) {
168         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
169                         DRV_NAME, ctl);
170         release_region(io, 8);
171         return NULL;
172     }
173
174     memset(&hw, 0, sizeof(hw));
175     ide_std_init_ports(&hw, io, ctl);
176     hw.irq = irq;
177     hw.chipset = ide_pci;
178     hw.dev = &handle->dev;
179
180     hwif = ide_find_port();
181     if (hwif == NULL)
182         goto out_release;
183
184     i = hwif->index;
185
186     ide_init_port_data(hwif, i);
187     ide_init_port_hw(hwif, &hw);
188     hwif->port_ops = &idecs_port_ops;
189
190     idx[0] = i;
191
192     ide_device_add(idx, NULL);
193
194     if (hwif->present)
195         return hwif;
196
197     /* retry registration in case device is still spinning up */
198     for (i = 0; i < 10; i++) {
199         msleep(100);
200         ide_port_scan(hwif);
201         if (hwif->present)
202             return hwif;
203     }
204
205     return hwif;
206
207 out_release:
208     release_region(ctl, 1);
209     release_region(io, 8);
210     return NULL;
211 }
212
213 /*======================================================================
214
215     ide_config() is scheduled to run after a CARD_INSERTION event
216     is received, to configure the PCMCIA socket, and to make the
217     ide device available to the system.
218
219 ======================================================================*/
220
221 #define CS_CHECK(fn, ret) \
222 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
223
224 static int ide_config(struct pcmcia_device *link)
225 {
226     ide_info_t *info = link->priv;
227     tuple_t tuple;
228     struct {
229         u_short         buf[128];
230         cisparse_t      parse;
231         config_info_t   conf;
232         cistpl_cftable_entry_t dflt;
233     } *stk = NULL;
234     cistpl_cftable_entry_t *cfg;
235     int pass, last_ret = 0, last_fn = 0, is_kme = 0;
236     unsigned long io_base, ctl_base;
237     ide_hwif_t *hwif;
238
239     DEBUG(0, "ide_config(0x%p)\n", link);
240
241     stk = kzalloc(sizeof(*stk), GFP_KERNEL);
242     if (!stk) goto err_mem;
243     cfg = &stk->parse.cftable_entry;
244
245     tuple.TupleData = (cisdata_t *)&stk->buf;
246     tuple.TupleOffset = 0;
247     tuple.TupleDataMax = 255;
248     tuple.Attributes = 0;
249
250     is_kme = ((link->manf_id == MANFID_KME) &&
251               ((link->card_id == PRODID_KME_KXLC005_A) ||
252                (link->card_id == PRODID_KME_KXLC005_B)));
253
254     /* Not sure if this is right... look up the current Vcc */
255     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
256
257     pass = io_base = ctl_base = 0;
258     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
259     tuple.Attributes = 0;
260     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
261     while (1) {
262         if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
263         if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
264
265         /* Check for matching Vcc, unless we're desperate */
266         if (!pass) {
267             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
268                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
269                     goto next_entry;
270             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
271                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
272                     goto next_entry;
273             }
274         }
275
276         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
277             link->conf.Vpp =
278                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
279         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
280             link->conf.Vpp =
281                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
282
283         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
284             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
285             link->conf.ConfigIndex = cfg->index;
286             link->io.BasePort1 = io->win[0].base;
287             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
288             if (!(io->flags & CISTPL_IO_16BIT))
289                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
290             if (io->nwin == 2) {
291                 link->io.NumPorts1 = 8;
292                 link->io.BasePort2 = io->win[1].base;
293                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
294                 if (pcmcia_request_io(link, &link->io) != 0)
295                         goto next_entry;
296                 io_base = link->io.BasePort1;
297                 ctl_base = link->io.BasePort2;
298             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
299                 link->io.NumPorts1 = io->win[0].len;
300                 link->io.NumPorts2 = 0;
301                 if (pcmcia_request_io(link, &link->io) != 0)
302                         goto next_entry;
303                 io_base = link->io.BasePort1;
304                 ctl_base = link->io.BasePort1 + 0x0e;
305             } else goto next_entry;
306             /* If we've got this far, we're done */
307             break;
308         }
309
310     next_entry:
311         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
312             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
313         if (pass) {
314             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
315         } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
316             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
317             memset(&stk->dflt, 0, sizeof(stk->dflt));
318             pass++;
319         }
320     }
321
322     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
323     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
324
325     /* disable drive interrupts during IDE probe */
326     outb(0x02, ctl_base);
327
328     /* special setup for KXLC005 card */
329     if (is_kme)
330         outb(0x81, ctl_base+1);
331
332      hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
333      if (hwif == NULL && link->io.NumPorts1 == 0x20) {
334             outb(0x02, ctl_base + 0x10);
335             hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
336                                   link->irq.AssignedIRQ, link);
337     }
338
339     if (hwif == NULL)
340         goto failed;
341
342     info->ndev = 1;
343     sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
344     info->node.major = hwif->major;
345     info->node.minor = 0;
346     info->hwif = hwif;
347     link->dev_node = &info->node;
348     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
349            info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
350
351     kfree(stk);
352     return 0;
353
354 err_mem:
355     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
356     goto failed;
357
358 cs_failed:
359     cs_error(link, last_fn, last_ret);
360 failed:
361     kfree(stk);
362     ide_release(link);
363     return -ENODEV;
364 } /* ide_config */
365
366 /*======================================================================
367
368     After a card is removed, ide_release() will unregister the net
369     device, and release the PCMCIA configuration.  If the device is
370     still open, this will be postponed until it is closed.
371
372 ======================================================================*/
373
374 void ide_release(struct pcmcia_device *link)
375 {
376     ide_info_t *info = link->priv;
377     ide_hwif_t *hwif = info->hwif;
378
379     DEBUG(0, "ide_release(0x%p)\n", link);
380
381     if (info->ndev) {
382         /* FIXME: if this fails we need to queue the cleanup somehow
383            -- need to investigate the required PCMCIA magic */
384         ide_unregister(hwif);
385     }
386     info->ndev = 0;
387
388     pcmcia_disable_device(link);
389 } /* ide_release */
390
391
392 /*======================================================================
393
394     The card status event handler.  Mostly, this schedules other
395     stuff to run after an event is received.  A CARD_REMOVAL event
396     also sets some flags to discourage the ide drivers from
397     talking to the ports.
398
399 ======================================================================*/
400
401 static struct pcmcia_device_id ide_ids[] = {
402         PCMCIA_DEVICE_FUNC_ID(4),
403         PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
404         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
405         PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
406         PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
407         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
408         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
409         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
410         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
411         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
412         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
413         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
414         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
415         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
416         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
417         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
418         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
419         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
420         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
421         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
422         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
423         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
424         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
425         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
426         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
427         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
428         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
429         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
430         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
431         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
432         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
433         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
434         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
435         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
436         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
437         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
438         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
439         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
440         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
441         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
442         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
443         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
444         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
445         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
446         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
447         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
448         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
449         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
450         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
451         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
452         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
453         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
454         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
455         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
456         PCMCIA_DEVICE_NULL,
457 };
458 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
459
460 static struct pcmcia_driver ide_cs_driver = {
461         .owner          = THIS_MODULE,
462         .drv            = {
463                 .name   = "ide-cs",
464         },
465         .probe          = ide_probe,
466         .remove         = ide_detach,
467         .id_table       = ide_ids,
468 };
469
470 static int __init init_ide_cs(void)
471 {
472         return pcmcia_register_driver(&ide_cs_driver);
473 }
474
475 static void __exit exit_ide_cs(void)
476 {
477         pcmcia_unregister_driver(&ide_cs_driver);
478 }
479
480 late_initcall(init_ide_cs);
481 module_exit(exit_ide_cs);