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