Pull xpc-disengage into release branch
[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 = kmalloc(sizeof(*info), GFP_KERNEL);
120     if (!info) return NULL;
121     memset(info, 0, sizeof(*info));
122     link = &info->link; link->priv = info;
123
124     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
125     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
126     link->io.IOAddrLines = 3;
127     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
128     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
129     link->conf.Attributes = CONF_ENABLE_IRQ;
130     link->conf.Vcc = 50;
131     link->conf.IntType = INT_MEMORY_AND_IO;
132     
133     /* Register with Card Services */
134     link->next = dev_list;
135     dev_list = link;
136     client_reg.dev_info = &dev_info;
137     client_reg.Version = 0x0210;
138     client_reg.event_callback_args.client_data = link;
139     ret = pcmcia_register_client(&link->handle, &client_reg);
140     if (ret != CS_SUCCESS) {
141         cs_error(link->handle, RegisterClient, ret);
142         ide_detach(link);
143         return NULL;
144     }
145     
146     return link;
147 } /* ide_attach */
148
149 /*======================================================================
150
151     This deletes a driver "instance".  The device is de-registered
152     with Card Services.  If it has been released, all local data
153     structures are freed.  Otherwise, the structures will be freed
154     when the device is released.
155
156 ======================================================================*/
157
158 static void ide_detach(dev_link_t *link)
159 {
160     dev_link_t **linkp;
161     int ret;
162
163     DEBUG(0, "ide_detach(0x%p)\n", link);
164     
165     /* Locate device structure */
166     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
167         if (*linkp == link) break;
168     if (*linkp == NULL)
169         return;
170
171     if (link->state & DEV_CONFIG)
172         ide_release(link);
173     
174     if (link->handle) {
175         ret = pcmcia_deregister_client(link->handle);
176         if (ret != CS_SUCCESS)
177             cs_error(link->handle, DeregisterClient, ret);
178     }
179     
180     /* Unlink, free device structure */
181     *linkp = link->next;
182     kfree(link->priv);
183     
184 } /* ide_detach */
185
186 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq)
187 {
188     hw_regs_t hw;
189     memset(&hw, 0, sizeof(hw));
190     ide_init_hwif_ports(&hw, io, ctl, NULL);
191     hw.irq = irq;
192     hw.chipset = ide_pci;
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 = kmalloc(sizeof(*stk), GFP_KERNEL);
225     if (!stk) goto err_mem;
226     memset(stk, 0, sizeof(*stk));
227     cfg = &stk->parse.cftable_entry;
228
229     tuple.TupleData = (cisdata_t *)&stk->buf;
230     tuple.TupleOffset = 0;
231     tuple.TupleDataMax = 255;
232     tuple.Attributes = 0;
233     tuple.DesiredTuple = CISTPL_CONFIG;
234     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
235     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
236     CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
237     link->conf.ConfigBase = stk->parse.config.base;
238     link->conf.Present = stk->parse.config.rmask[0];
239
240     tuple.DesiredTuple = CISTPL_MANFID;
241     if (!pcmcia_get_first_tuple(handle, &tuple) &&
242         !pcmcia_get_tuple_data(handle, &tuple) &&
243         !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
244         is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
245                   ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
246                    (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
247
248     /* Configure card */
249     link->state |= DEV_CONFIG;
250
251     /* Not sure if this is right... look up the current Vcc */
252     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
253     link->conf.Vcc = stk->conf.Vcc;
254
255     pass = io_base = ctl_base = 0;
256     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
257     tuple.Attributes = 0;
258     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
259     while (1) {
260         if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
261         if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
262
263         /* Check for matching Vcc, unless we're desperate */
264         if (!pass) {
265             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
266                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
267                     goto next_entry;
268             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
269                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
270                     goto next_entry;
271             }
272         }
273
274         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
275             link->conf.Vpp1 = link->conf.Vpp2 =
276                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
277         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
278             link->conf.Vpp1 = link->conf.Vpp2 =
279                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
280
281         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
282             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
283             link->conf.ConfigIndex = cfg->index;
284             link->io.BasePort1 = io->win[0].base;
285             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
286             if (!(io->flags & CISTPL_IO_16BIT))
287                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
288             if (io->nwin == 2) {
289                 link->io.NumPorts1 = 8;
290                 link->io.BasePort2 = io->win[1].base;
291                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
292                 if (pcmcia_request_io(link->handle, &link->io) != 0)
293                         goto next_entry;
294                 io_base = link->io.BasePort1;
295                 ctl_base = link->io.BasePort2;
296             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
297                 link->io.NumPorts1 = io->win[0].len;
298                 link->io.NumPorts2 = 0;
299                 if (pcmcia_request_io(link->handle, &link->io) != 0)
300                         goto next_entry;
301                 io_base = link->io.BasePort1;
302                 ctl_base = link->io.BasePort1 + 0x0e;
303             } else goto next_entry;
304             /* If we've got this far, we're done */
305             break;
306         }
307
308     next_entry:
309         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
310             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
311         if (pass) {
312             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
313         } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
314             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
315             memset(&stk->dflt, 0, sizeof(stk->dflt));
316             pass++;
317         }
318     }
319
320     CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
321     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
322
323     /* disable drive interrupts during IDE probe */
324     outb(0x02, ctl_base);
325
326     /* special setup for KXLC005 card */
327     if (is_kme)
328         outb(0x81, ctl_base+1);
329
330     /* retry registration in case device is still spinning up */
331     for (hd = -1, i = 0; i < 10; i++) {
332         hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
333         if (hd >= 0) break;
334         if (link->io.NumPorts1 == 0x20) {
335             outb(0x02, ctl_base + 0x10);
336             hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
337                                 link->irq.AssignedIRQ);
338             if (hd >= 0) {
339                 io_base += 0x10;
340                 ctl_base += 0x10;
341                 break;
342             }
343         }
344         msleep(100);
345     }
346
347     if (hd < 0) {
348         printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
349                ", irq %u failed\n", io_base, ctl_base,
350                link->irq.AssignedIRQ);
351         goto failed;
352     }
353
354     info->ndev = 1;
355     sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
356     info->node.major = ide_major[hd];
357     info->node.minor = 0;
358     info->hd = hd;
359     link->dev = &info->node;
360     printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
361            info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
362            link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
363
364     link->state &= ~DEV_CONFIG_PENDING;
365     kfree(stk);
366     return;
367
368 err_mem:
369     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
370     goto failed;
371
372 cs_failed:
373     cs_error(link->handle, last_fn, last_ret);
374 failed:
375     kfree(stk);
376     ide_release(link);
377     link->state &= ~DEV_CONFIG_PENDING;
378 } /* ide_config */
379
380 /*======================================================================
381
382     After a card is removed, ide_release() will unregister the net
383     device, and release the PCMCIA configuration.  If the device is
384     still open, this will be postponed until it is closed.
385     
386 ======================================================================*/
387
388 void ide_release(dev_link_t *link)
389 {
390     ide_info_t *info = link->priv;
391     
392     DEBUG(0, "ide_release(0x%p)\n", link);
393
394     if (info->ndev) {
395         /* FIXME: if this fails we need to queue the cleanup somehow
396            -- need to investigate the required PCMCIA magic */
397         ide_unregister(info->hd);
398     }
399     info->ndev = 0;
400     link->dev = NULL;
401     
402     pcmcia_release_configuration(link->handle);
403     pcmcia_release_io(link->handle, &link->io);
404     pcmcia_release_irq(link->handle, &link->irq);
405     
406     link->state &= ~DEV_CONFIG;
407
408 } /* ide_release */
409
410 /*======================================================================
411
412     The card status event handler.  Mostly, this schedules other
413     stuff to run after an event is received.  A CARD_REMOVAL event
414     also sets some flags to discourage the ide drivers from
415     talking to the ports.
416     
417 ======================================================================*/
418
419 int ide_event(event_t event, int priority,
420               event_callback_args_t *args)
421 {
422     dev_link_t *link = args->client_data;
423
424     DEBUG(1, "ide_event(0x%06x)\n", event);
425     
426     switch (event) {
427     case CS_EVENT_CARD_REMOVAL:
428         link->state &= ~DEV_PRESENT;
429         if (link->state & DEV_CONFIG)
430                 ide_release(link);
431         break;
432     case CS_EVENT_CARD_INSERTION:
433         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
434         ide_config(link);
435         break;
436     case CS_EVENT_PM_SUSPEND:
437         link->state |= DEV_SUSPEND;
438         /* Fall through... */
439     case CS_EVENT_RESET_PHYSICAL:
440         if (link->state & DEV_CONFIG)
441             pcmcia_release_configuration(link->handle);
442         break;
443     case CS_EVENT_PM_RESUME:
444         link->state &= ~DEV_SUSPEND;
445         /* Fall through... */
446     case CS_EVENT_CARD_RESET:
447         if (DEV_OK(link))
448             pcmcia_request_configuration(link->handle, &link->conf);
449         break;
450     }
451     return 0;
452 } /* ide_event */
453
454 static struct pcmcia_device_id ide_ids[] = {
455         PCMCIA_DEVICE_FUNC_ID(4),
456         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
457         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
458         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
459         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
460         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
461         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
462         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar */
463         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
464         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
465         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
466         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
467         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
468         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
469         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
470         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
471         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
472         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
473         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
474         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
475         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
476         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
477         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
478         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
479         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
480         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
481         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
482         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
483         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
484         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
485         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
486         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
487         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
488         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
489         PCMCIA_DEVICE_NULL,
490 };
491 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
492
493 static struct pcmcia_driver ide_cs_driver = {
494         .owner          = THIS_MODULE,
495         .drv            = {
496                 .name   = "ide-cs",
497         },
498         .attach         = ide_attach,
499         .event          = ide_event,
500         .detach         = ide_detach,
501         .id_table       = ide_ids,
502 };
503
504 static int __init init_ide_cs(void)
505 {
506         return pcmcia_register_driver(&ide_cs_driver);
507 }
508
509 static void __exit exit_ide_cs(void)
510 {
511         pcmcia_unregister_driver(&ide_cs_driver);
512         BUG_ON(dev_list != NULL);
513 }
514
515 late_initcall(init_ide_cs);
516 module_exit(exit_ide_cs);