Merge /spare/repo/linux-2.6/
[pandora-kernel.git] / 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 <asm/io.h>
47 #include <asm/system.h>
48
49 #include <pcmcia/cs_types.h>
50 #include <pcmcia/cs.h>
51 #include <pcmcia/cistpl.h>
52 #include <pcmcia/ds.h>
53 #include <pcmcia/cisreg.h>
54 #include <pcmcia/ciscode.h>
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 static const char ide_major[] = {
78     IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
79     IDE4_MAJOR, IDE5_MAJOR
80 };
81
82 typedef struct ide_info_t {
83     dev_link_t  link;
84     int         ndev;
85     dev_node_t  node;
86     int         hd;
87 } ide_info_t;
88
89 static void ide_release(dev_link_t *);
90 static int ide_event(event_t event, int priority,
91                      event_callback_args_t *args);
92
93 static dev_info_t dev_info = "ide-cs";
94
95 static dev_link_t *ide_attach(void);
96 static void ide_detach(dev_link_t *);
97
98 static dev_link_t *dev_list = NULL;
99
100 /*======================================================================
101
102     ide_attach() creates an "instance" of the driver, allocating
103     local data structures for one device.  The device is registered
104     with Card Services.
105
106 ======================================================================*/
107
108 static dev_link_t *ide_attach(void)
109 {
110     ide_info_t *info;
111     dev_link_t *link;
112     client_reg_t client_reg;
113     int ret;
114     
115     DEBUG(0, "ide_attach()\n");
116
117     /* Create new ide device */
118     info = kmalloc(sizeof(*info), GFP_KERNEL);
119     if (!info) return NULL;
120     memset(info, 0, sizeof(*info));
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)
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     return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
193 }
194
195 /*======================================================================
196
197     ide_config() is scheduled to run after a CARD_INSERTION event
198     is received, to configure the PCMCIA socket, and to make the
199     ide device available to the system.
200
201 ======================================================================*/
202
203 #define CS_CHECK(fn, ret) \
204 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
205
206 static void ide_config(dev_link_t *link)
207 {
208     client_handle_t handle = link->handle;
209     ide_info_t *info = link->priv;
210     tuple_t tuple;
211     struct {
212         u_short         buf[128];
213         cisparse_t      parse;
214         config_info_t   conf;
215         cistpl_cftable_entry_t dflt;
216     } *stk = NULL;
217     cistpl_cftable_entry_t *cfg;
218     int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
219     unsigned long io_base, ctl_base;
220
221     DEBUG(0, "ide_config(0x%p)\n", link);
222
223     stk = kmalloc(sizeof(*stk), GFP_KERNEL);
224     if (!stk) goto err_mem;
225     memset(stk, 0, sizeof(*stk));
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);
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);
337             if (hd >= 0) {
338                 io_base += 0x10;
339                 ctl_base += 0x10;
340                 break;
341             }
342         }
343         __set_current_state(TASK_UNINTERRUPTIBLE);
344         schedule_timeout(HZ/10);
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(0x00a4, 0x002d),
458         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
459         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
460         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
461         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
462         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
463         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
464         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
465         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
466         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
467         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
468         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
469         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
470         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
471         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
472         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
473         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
474         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
475         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
476         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
477         PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79),
478         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
479         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
480         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
481         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
482         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
483         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
484         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
485         PCMCIA_DEVICE_NULL,
486 };
487 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
488
489 static struct pcmcia_driver ide_cs_driver = {
490         .owner          = THIS_MODULE,
491         .drv            = {
492                 .name   = "ide-cs",
493         },
494         .attach         = ide_attach,
495         .event          = ide_event,
496         .detach         = ide_detach,
497         .id_table       = ide_ids,
498 };
499
500 static int __init init_ide_cs(void)
501 {
502         return pcmcia_register_driver(&ide_cs_driver);
503 }
504
505 static void __exit exit_ide_cs(void)
506 {
507         pcmcia_unregister_driver(&ide_cs_driver);
508         BUG_ON(dev_list != NULL);
509 }
510
511 late_initcall(init_ide_cs);
512 module_exit(exit_ide_cs);