Merge git://git.infradead.org/mtd-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 <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         struct pcmcia_device    *p_dev;
85     int         ndev;
86     dev_node_t  node;
87     int         hd;
88 } ide_info_t;
89
90 static void ide_release(struct pcmcia_device *);
91 static int ide_config(struct pcmcia_device *);
92
93 static void ide_detach(struct pcmcia_device *p_dev);
94
95
96
97
98 /*======================================================================
99
100     ide_attach() creates an "instance" of the driver, allocating
101     local data structures for one device.  The device is registered
102     with Card Services.
103
104 ======================================================================*/
105
106 static int ide_probe(struct pcmcia_device *link)
107 {
108     ide_info_t *info;
109
110     DEBUG(0, "ide_attach()\n");
111
112     /* Create new ide device */
113     info = kzalloc(sizeof(*info), GFP_KERNEL);
114     if (!info)
115         return -ENOMEM;
116
117     info->p_dev = link;
118     link->priv = info;
119
120     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
121     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
122     link->io.IOAddrLines = 3;
123     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
124     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
125     link->conf.Attributes = CONF_ENABLE_IRQ;
126     link->conf.IntType = INT_MEMORY_AND_IO;
127
128     return ide_config(link);
129 } /* ide_attach */
130
131 /*======================================================================
132
133     This deletes a driver "instance".  The device is de-registered
134     with Card Services.  If it has been released, all local data
135     structures are freed.  Otherwise, the structures will be freed
136     when the device is released.
137
138 ======================================================================*/
139
140 static void ide_detach(struct pcmcia_device *link)
141 {
142     DEBUG(0, "ide_detach(0x%p)\n", link);
143
144     ide_release(link);
145
146     kfree(link->priv);
147 } /* ide_detach */
148
149 static void idecs_mmio_fixup(ide_hwif_t *hwif)
150 {
151         default_hwif_mmiops(hwif);
152         hwif->mmio = 2;
153
154         ide_undecoded_slave(hwif);
155 }
156
157 static int idecs_register(unsigned long io, unsigned long ctl,
158         unsigned long irq, struct pcmcia_device *handle, int is_mmio)
159 {
160     hw_regs_t hw;
161     memset(&hw, 0, sizeof(hw));
162     ide_init_hwif_ports(&hw, io, ctl, NULL);
163     hw.irq = irq;
164     hw.chipset = ide_pci;
165     hw.dev = &handle->dev;
166
167     if(is_mmio)
168         return ide_register_hw_with_fixup(&hw, NULL, idecs_mmio_fixup);
169     else
170         return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
171 }
172
173 void outb_io(unsigned char value, unsigned long port) {
174         outb(value, port);
175 }
176
177 void outb_mem(unsigned char value, unsigned long port) {
178         writeb(value, (void __iomem *) port);
179 }
180
181 /*======================================================================
182
183     ide_config() is scheduled to run after a CARD_INSERTION event
184     is received, to configure the PCMCIA socket, and to make the
185     ide device available to the system.
186
187 ======================================================================*/
188
189 #define CS_CHECK(fn, ret) \
190 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
191
192 static int ide_config(struct pcmcia_device *link)
193 {
194     ide_info_t *info = link->priv;
195     tuple_t tuple;
196     struct {
197         u_short         buf[128];
198         cisparse_t      parse;
199         config_info_t   conf;
200         cistpl_cftable_entry_t dflt;
201     } *stk = NULL;
202     cistpl_cftable_entry_t *cfg;
203     int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
204     unsigned long io_base, ctl_base, is_mmio, try_slave;
205     void (*my_outb)(unsigned char, unsigned long);
206
207     DEBUG(0, "ide_config(0x%p)\n", link);
208
209     stk = kzalloc(sizeof(*stk), GFP_KERNEL);
210     if (!stk) goto err_mem;
211     cfg = &stk->parse.cftable_entry;
212
213     tuple.TupleData = (cisdata_t *)&stk->buf;
214     tuple.TupleOffset = 0;
215     tuple.TupleDataMax = 255;
216     tuple.Attributes = 0;
217     tuple.DesiredTuple = CISTPL_CONFIG;
218     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
219     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
220     CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
221     link->conf.ConfigBase = stk->parse.config.base;
222     link->conf.Present = stk->parse.config.rmask[0];
223
224     tuple.DesiredTuple = CISTPL_MANFID;
225     if (!pcmcia_get_first_tuple(link, &tuple) &&
226         !pcmcia_get_tuple_data(link, &tuple) &&
227         !pcmcia_parse_tuple(link, &tuple, &stk->parse))
228         is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
229                   ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
230                    (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
231
232     /* Not sure if this is right... look up the current Vcc */
233     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
234
235     pass = io_base = ctl_base = is_mmio = try_slave = 0;
236     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
237     tuple.Attributes = 0;
238     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
239     while (1) {
240         if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
241         if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
242
243         /* Check for matching Vcc, unless we're desperate */
244         if (!pass) {
245             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
246                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
247                     goto next_entry;
248             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
249                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
250                     goto next_entry;
251             }
252         }
253
254         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
255             link->conf.Vpp =
256                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
257         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
258             link->conf.Vpp =
259                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
260
261         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
262             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
263             link->conf.ConfigIndex = cfg->index;
264             link->io.BasePort1 = io->win[0].base;
265             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
266             if (!(io->flags & CISTPL_IO_16BIT))
267                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
268             if (io->nwin == 2) {
269                 link->io.NumPorts1 = 8;
270                 link->io.BasePort2 = io->win[1].base;
271                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
272                 if (pcmcia_request_io(link, &link->io) != 0)
273                         goto next_entry;
274                 io_base = link->io.BasePort1;
275                 ctl_base = link->io.BasePort2;
276             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
277                 link->io.NumPorts1 = io->win[0].len;
278                 link->io.NumPorts2 = 0;
279                 if (pcmcia_request_io(link, &link->io) != 0)
280                         goto next_entry;
281                 io_base = link->io.BasePort1;
282                 ctl_base = link->io.BasePort1 + 0x0e;
283
284                 if (io->win[0].len >= 0x20)
285                         try_slave = 1;
286
287             } else goto next_entry;
288             /* If we've got this far, we're done */
289             break;
290         }
291
292         if ((cfg->mem.nwin > 0) || (stk->dflt.mem.nwin > 0)) {
293             win_req_t req;
294             memreq_t map;
295             cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &stk->dflt.mem;
296
297             if (mem->win[0].len < 16)
298                 goto next_entry;
299
300             req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
301             req.Attributes |= WIN_ENABLE;
302             req.Base = mem->win[0].host_addr;
303             req.Size = 0;
304
305             req.AccessSpeed = 0;
306             if (pcmcia_request_window(&link, &req, &link->win) != 0)
307                 goto next_entry;
308             map.Page = 0; map.CardOffset = mem->win[0].card_addr;
309             if (pcmcia_map_mem_page(link->win, &map) != 0)
310                 goto next_entry;
311
312             io_base = (unsigned long) ioremap(req.Base, req.Size);
313             ctl_base = io_base + 0x0e;
314             is_mmio = 1;
315
316             if (mem->win[0].len >= 0x20)
317                 try_slave = 1;
318
319             break;
320         }
321
322     next_entry:
323         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
324             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
325         if (pass) {
326             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
327         } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
328             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
329             memset(&stk->dflt, 0, sizeof(stk->dflt));
330             pass++;
331         }
332     }
333
334     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
335     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
336
337     if(is_mmio)
338         my_outb = outb_mem;
339     else
340         my_outb = outb_io;
341
342     /* disable drive interrupts during IDE probe */
343     my_outb(0x02, ctl_base);
344
345     /* special setup for KXLC005 card */
346     if (is_kme)
347         my_outb(0x81, ctl_base+1);
348
349     /* retry registration in case device is still spinning up */
350     for (hd = -1, i = 0; i < 10; i++) {
351         hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link, is_mmio);
352         if (hd >= 0) break;
353         if (try_slave) {
354             my_outb(0x02, ctl_base + 0x10);
355             hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
356                                 link->irq.AssignedIRQ, link, is_mmio);
357             if (hd >= 0) {
358                 io_base += 0x10;
359                 ctl_base += 0x10;
360                 break;
361             }
362         }
363         msleep(100);
364     }
365
366     if (hd < 0) {
367         printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
368                ", irq %u failed\n", io_base, ctl_base,
369                link->irq.AssignedIRQ);
370         goto failed;
371     }
372
373     info->ndev = 1;
374     sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
375     info->node.major = ide_major[hd];
376     info->node.minor = 0;
377     info->hd = hd;
378     link->dev_node = &info->node;
379     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
380            info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
381
382     kfree(stk);
383     return 0;
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, last_fn, last_ret);
391 failed:
392     kfree(stk);
393     ide_release(link);
394     return -ENODEV;
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(struct pcmcia_device *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
418     pcmcia_disable_device(link);
419 } /* ide_release */
420
421
422 /*======================================================================
423
424     The card status event handler.  Mostly, this schedules other
425     stuff to run after an event is received.  A CARD_REMOVAL event
426     also sets some flags to discourage the ide drivers from
427     talking to the ports.
428     
429 ======================================================================*/
430
431 static struct pcmcia_device_id ide_ids[] = {
432         PCMCIA_DEVICE_FUNC_ID(4),
433         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
434         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
435         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
436         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
437         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
438         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
439         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
440         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
441         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar */
442         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
443         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
444         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
445         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
446         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
447         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
448         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
449         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
450         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
451         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
452         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
453         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
454         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
455         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
456         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
457         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
458         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
459         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
460         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
461         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
462         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
463         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
464         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
465         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
466         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
467         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
468         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
469         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
470         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
471         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
472         PCMCIA_DEVICE_NULL,
473 };
474 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
475
476 static struct pcmcia_driver ide_cs_driver = {
477         .owner          = THIS_MODULE,
478         .drv            = {
479                 .name   = "ide-cs",
480         },
481         .probe          = ide_probe,
482         .remove         = ide_detach,
483         .id_table       = ide_ids,
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 }
495
496 late_initcall(init_ide_cs);
497 module_exit(exit_ide_cs);