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