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