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