upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.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 <linux/delay.h>
47 #include <asm/io.h>
48 #include <asm/system.h>
49
50 #include <pcmcia/version.h>
51 #include <pcmcia/cs_types.h>
52 #include <pcmcia/cs.h>
53 #include <pcmcia/cistpl.h>
54 #include <pcmcia/ds.h>
55 #include <pcmcia/cisreg.h>
56 #include <pcmcia/ciscode.h>
57
58 /*====================================================================*/
59
60 /* Module parameters */
61
62 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
63 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
64 MODULE_LICENSE("Dual MPL/GPL");
65
66 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
67
68 /* Bit map of interrupts to choose from */
69 INT_MODULE_PARM(irq_mask, 0xdeb8);
70 static int irq_list[4] = { -1 };
71 MODULE_PARM(irq_list, "1-4i");
72
73 #ifdef PCMCIA_DEBUG
74 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
75 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
76 static char *version =
77 "ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
78 #else
79 #define DEBUG(n, args...)
80 #endif
81
82 /*====================================================================*/
83
84 static const char ide_major[] = {
85     IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
86     IDE4_MAJOR, IDE5_MAJOR
87 };
88
89 typedef struct ide_info_t {
90     dev_link_t  link;
91     int         ndev;
92     dev_node_t  node;
93     int         hd;
94     ide_hwif_t *hwif;
95 } ide_info_t;
96
97 static void ide_release(dev_link_t *);
98 static int ide_event(event_t event, int priority,
99                      event_callback_args_t *args);
100
101 static dev_info_t dev_info = "ide-cs";
102
103 static dev_link_t *ide_attach(void);
104 static void ide_detach(dev_link_t *);
105
106 static dev_link_t *dev_list = NULL;
107
108 /*======================================================================
109
110     ide_attach() creates an "instance" of the driver, allocating
111     local data structures for one device.  The device is registered
112     with Card Services.
113
114 ======================================================================*/
115
116 static dev_link_t *ide_attach(void)
117 {
118     ide_info_t *info;
119     dev_link_t *link;
120     client_reg_t client_reg;
121     int i, ret;
122     
123     DEBUG(0, "ide_attach()\n");
124
125     /* Create new ide device */
126     info = kmalloc(sizeof(*info), GFP_KERNEL);
127     if (!info) return NULL;
128     memset(info, 0, sizeof(*info));
129     link = &info->link; link->priv = info;
130
131     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
132     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
133     link->io.IOAddrLines = 3;
134     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
135     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
136     if (irq_list[0] == -1)
137         link->irq.IRQInfo2 = irq_mask;
138     else
139         for (i = 0; i < 4; i++)
140             link->irq.IRQInfo2 |= 1 << irq_list[i];
141     link->conf.Attributes = CONF_ENABLE_IRQ;
142     link->conf.Vcc = 50;
143     link->conf.IntType = INT_MEMORY_AND_IO;
144     
145     /* Register with Card Services */
146     link->next = dev_list;
147     dev_list = link;
148     client_reg.dev_info = &dev_info;
149     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
150     client_reg.EventMask =
151         CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
152         CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
153         CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
154     client_reg.event_handler = &ide_event;
155     client_reg.Version = 0x0210;
156     client_reg.event_callback_args.client_data = link;
157     ret = pcmcia_register_client(&link->handle, &client_reg);
158     if (ret != CS_SUCCESS) {
159         cs_error(link->handle, RegisterClient, ret);
160         ide_detach(link);
161         return NULL;
162     }
163     
164     return link;
165 } /* ide_attach */
166
167 /*======================================================================
168
169     This deletes a driver "instance".  The device is de-registered
170     with Card Services.  If it has been released, all local data
171     structures are freed.  Otherwise, the structures will be freed
172     when the device is released.
173
174 ======================================================================*/
175
176 static void ide_detach(dev_link_t *link)
177 {
178     dev_link_t **linkp;
179     int ret;
180
181     DEBUG(0, "ide_detach(0x%p)\n", link);
182     
183     /* Locate device structure */
184     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
185         if (*linkp == link) break;
186     if (*linkp == NULL)
187         return;
188
189     if (link->state & DEV_CONFIG)
190         ide_release(link);
191     
192     if (link->handle) {
193         ret = pcmcia_deregister_client(link->handle);
194         if (ret != CS_SUCCESS)
195             cs_error(link->handle, DeregisterClient, ret);
196     }
197     
198     /* Unlink, free device structure */
199     *linkp = link->next;
200     kfree(link->priv);
201     
202 } /* ide_detach */
203
204 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, ide_hwif_t **hwif)
205 {
206     hw_regs_t hw;
207     memset(&hw, 0, sizeof(hw));
208     ide_init_hwif_ports(&hw, io, ctl, NULL);
209     hw.irq = irq;
210     hw.chipset = ide_pci;
211     return ide_register_hw_with_fixup(&hw, hwif, ide_undecoded_slave);
212 }
213
214 /*======================================================================
215
216     ide_config() is scheduled to run after a CARD_INSERTION event
217     is received, to configure the PCMCIA socket, and to make the
218     ide device available to the system.
219
220 ======================================================================*/
221
222 #define CS_CHECK(fn, ret) \
223 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
224
225 void ide_config(dev_link_t *link)
226 {
227     client_handle_t handle = link->handle;
228     ide_info_t *info = link->priv;
229     ide_hwif_t *hwif;
230     tuple_t tuple;
231     struct {
232         u_short         buf[128];
233         cisparse_t      parse;
234         config_info_t   conf;
235         cistpl_cftable_entry_t dflt;
236     } *stk = NULL;
237     cistpl_cftable_entry_t *cfg;
238     int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
239     unsigned long io_base, ctl_base;
240
241     DEBUG(0, "ide_config(0x%p)\n", link);
242
243     stk = kmalloc(sizeof(*stk), GFP_KERNEL);
244     if (!stk) goto err_mem;
245     memset(stk, 0, sizeof(*stk));
246     cfg = &stk->parse.cftable_entry;
247
248     tuple.TupleData = (cisdata_t *)&stk->buf;
249     tuple.TupleOffset = 0;
250     tuple.TupleDataMax = 255;
251     tuple.Attributes = 0;
252     tuple.DesiredTuple = CISTPL_CONFIG;
253     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
254     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
255     CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
256     link->conf.ConfigBase = stk->parse.config.base;
257     link->conf.Present = stk->parse.config.rmask[0];
258
259     tuple.DesiredTuple = CISTPL_MANFID;
260     if (!pcmcia_get_first_tuple(handle, &tuple) &&
261         !pcmcia_get_tuple_data(handle, &tuple) &&
262         !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
263         is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
264                   ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
265                    (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
266
267     /* Configure card */
268     link->state |= DEV_CONFIG;
269
270     /* Not sure if this is right... look up the current Vcc */
271     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
272     link->conf.Vcc = stk->conf.Vcc;
273
274     pass = io_base = ctl_base = 0;
275     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
276     tuple.Attributes = 0;
277     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
278     while (1) {
279         if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
280         if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
281
282         /* Check for matching Vcc, unless we're desperate */
283         if (!pass) {
284             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
285                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
286                     goto next_entry;
287             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
288                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
289                     goto next_entry;
290             }
291         }
292
293         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
294             link->conf.Vpp1 = link->conf.Vpp2 =
295                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
296         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
297             link->conf.Vpp1 = link->conf.Vpp2 =
298                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
299
300         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
301             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
302             link->conf.ConfigIndex = cfg->index;
303             link->io.BasePort1 = io->win[0].base;
304             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
305             if (!(io->flags & CISTPL_IO_16BIT))
306                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
307             if (io->nwin == 2) {
308                 link->io.NumPorts1 = 8;
309                 link->io.BasePort2 = io->win[1].base;
310                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
311                 if (pcmcia_request_io(link->handle, &link->io) != 0)
312                         goto next_entry;
313                 io_base = link->io.BasePort1;
314                 ctl_base = link->io.BasePort2;
315             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
316                 link->io.NumPorts1 = io->win[0].len;
317                 link->io.NumPorts2 = 0;
318                 if (pcmcia_request_io(link->handle, &link->io) != 0)
319                         goto next_entry;
320                 io_base = link->io.BasePort1;
321                 ctl_base = link->io.BasePort1 + 0x0e;
322             } else goto next_entry;
323             /* If we've got this far, we're done */
324             break;
325         }
326
327     next_entry:
328         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
329             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
330         if (pass) {
331             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
332         } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
333             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
334             memset(&stk->dflt, 0, sizeof(stk->dflt));
335             pass++;
336         }
337     }
338
339     CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
340     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
341
342     /* disable drive interrupts during IDE probe */
343     outb(0x02, ctl_base);
344
345     /* special setup for KXLC005 card */
346     if (is_kme)
347         outb(0x81, ctl_base+1);
348
349     /* retry registration in case device is still spinning up 
350     
351        FIXME: now handled by IDE layer... ?? */
352        
353     for (hd = -1, i = 0; i < 10; i++) {
354         hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, &hwif);
355         if (hd >= 0) break;
356         if (link->io.NumPorts1 == 0x20) {
357             outb(0x02, ctl_base + 0x10);
358             hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
359                                 link->irq.AssignedIRQ, &hwif);
360             if (hd >= 0) {
361                 io_base += 0x10;
362                 ctl_base += 0x10;
363                 break;
364             }
365         }
366         msleep(100);
367     }
368
369     if (hd < 0) {
370         printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
371                ", irq %u failed\n", io_base, ctl_base,
372                link->irq.AssignedIRQ);
373         goto failed;
374     }
375
376     info->ndev = 1;
377     sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
378     info->node.major = ide_major[hd];
379     info->node.minor = 0;
380     info->hd = hd;
381     info->hwif = hwif;
382     link->dev = &info->node;
383     printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
384            info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
385            link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
386
387     link->state &= ~DEV_CONFIG_PENDING;
388     kfree(stk);
389     return;
390
391 err_mem:
392     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
393     goto failed;
394
395 cs_failed:
396     cs_error(link->handle, last_fn, last_ret);
397 failed:
398     kfree(stk);
399     ide_release(link);
400     link->state &= ~DEV_CONFIG_PENDING;
401 } /* ide_config */
402
403 /*======================================================================
404
405     After a card is removed, ide_release() will unregister the net
406     device, and release the PCMCIA configuration.  If the device is
407     still open, this will be postponed until it is closed.
408     
409 ======================================================================*/
410
411 void ide_release(dev_link_t *link)
412 {
413     ide_info_t *info = link->priv;
414     
415     DEBUG(0, "ide_release(0x%p)\n", link);
416
417     if (info->ndev) {
418         /* Wait for the interface to cease to be busy */
419         while(ide_unregister_hwif(info->hwif) < 0) {
420                 removed_hwif_iops(info->hwif);
421                 msleep(1000);
422         }
423     }
424     info->ndev = 0;
425     link->dev = NULL;
426     
427     pcmcia_release_configuration(link->handle);
428     pcmcia_release_io(link->handle, &link->io);
429     pcmcia_release_irq(link->handle, &link->irq);
430     
431     link->state &= ~DEV_CONFIG;
432
433 } /* ide_release */
434
435 /*======================================================================
436
437     The card status event handler.  Mostly, this schedules other
438     stuff to run after an event is received.  A CARD_REMOVAL event
439     also sets some flags to discourage the ide drivers from
440     talking to the ports.
441     
442 ======================================================================*/
443
444 int ide_event(event_t event, int priority,
445               event_callback_args_t *args)
446 {
447     dev_link_t *link = args->client_data;
448
449     DEBUG(1, "ide_event(0x%06x)\n", event);
450     
451     switch (event) {
452     case CS_EVENT_CARD_REMOVAL:
453         link->state &= ~DEV_PRESENT;
454         if (link->state & DEV_CONFIG)
455                 ide_release(link);
456         break;
457     case CS_EVENT_CARD_INSERTION:
458         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
459         ide_config(link);
460         break;
461     case CS_EVENT_PM_SUSPEND:
462         link->state |= DEV_SUSPEND;
463         /* Fall through... */
464     case CS_EVENT_RESET_PHYSICAL:
465         if (link->state & DEV_CONFIG)
466             pcmcia_release_configuration(link->handle);
467         break;
468     case CS_EVENT_PM_RESUME:
469         link->state &= ~DEV_SUSPEND;
470         /* Fall through... */
471     case CS_EVENT_CARD_RESET:
472         if (DEV_OK(link))
473             pcmcia_request_configuration(link->handle, &link->conf);
474         break;
475     }
476     return 0;
477 } /* ide_event */
478
479 static struct pcmcia_driver ide_cs_driver = {
480         .owner          = THIS_MODULE,
481         .drv            = {
482                 .name   = "ide-cs",
483         },
484         .attach         = ide_attach,
485         .detach         = ide_detach,
486 };
487
488 static int __init init_ide_cs(void)
489 {
490         return pcmcia_register_driver(&ide_cs_driver);
491 }
492
493 static void __exit exit_ide_cs(void)
494 {
495         pcmcia_unregister_driver(&ide_cs_driver);
496         while (dev_list != NULL)
497                 ide_detach(dev_list);
498 }
499
500 module_init(init_ide_cs);
501 module_exit(exit_ide_cs);