]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/ide/legacy/ide-cs.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-fixes-2.6
[linux-2.6.git] / drivers / ide / legacy / ide-cs.c
1 /*======================================================================
2
3     A driver for PCMCIA IDE/ATA disk cards
4
5     The contents of this file are subject to the Mozilla Public
6     License Version 1.1 (the "License"); you may not use this file
7     except in compliance with the License. You may obtain a copy of
8     the License at http://www.mozilla.org/MPL/
9
10     Software distributed under the License is distributed on an "AS
11     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12     implied. See the License for the specific language governing
13     rights and limitations under the License.
14
15     The initial developer of the original code is David A. Hinds
16     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
17     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
18
19     Alternatively, the contents of this file may be used under the
20     terms of the GNU General Public License version 2 (the "GPL"), in
21     which case the provisions of the GPL are applicable instead of the
22     above.  If you wish to allow the use of your version of this file
23     only under the terms of the GPL and not to allow others to use
24     your version of this file under the MPL, indicate your decision
25     by deleting the provisions above and replace them with the notice
26     and other provisions required by the GPL.  If you do not delete
27     the provisions above, a recipient may use your version of this
28     file under either the MPL or the GPL.
29
30 ======================================================================*/
31
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/ptrace.h>
36 #include <linux/slab.h>
37 #include <linux/string.h>
38 #include <linux/timer.h>
39 #include <linux/ioport.h>
40 #include <linux/ide.h>
41 #include <linux/hdreg.h>
42 #include <linux/major.h>
43 #include <linux/delay.h>
44 #include <asm/io.h>
45 #include <asm/system.h>
46
47 #include <pcmcia/cs_types.h>
48 #include <pcmcia/cs.h>
49 #include <pcmcia/cistpl.h>
50 #include <pcmcia/ds.h>
51 #include <pcmcia/cisreg.h>
52 #include <pcmcia/ciscode.h>
53
54 #define DRV_NAME "ide-cs"
55
56 /*====================================================================*/
57
58 /* Module parameters */
59
60 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
61 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
62 MODULE_LICENSE("Dual MPL/GPL");
63
64 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
65
66 #ifdef CONFIG_PCMCIA_DEBUG
67 INT_MODULE_PARM(pc_debug, 0);
68 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
69 #else
70 #define DEBUG(n, args...)
71 #endif
72
73 /*====================================================================*/
74
75 typedef struct ide_info_t {
76         struct pcmcia_device    *p_dev;
77         ide_hwif_t              *hwif;
78     int         ndev;
79     dev_node_t  node;
80 } ide_info_t;
81
82 static void ide_release(struct pcmcia_device *);
83 static int ide_config(struct pcmcia_device *);
84
85 static void ide_detach(struct pcmcia_device *p_dev);
86
87
88
89
90 /*======================================================================
91
92     ide_attach() creates an "instance" of the driver, allocating
93     local data structures for one device.  The device is registered
94     with Card Services.
95
96 ======================================================================*/
97
98 static int ide_probe(struct pcmcia_device *link)
99 {
100     ide_info_t *info;
101
102     DEBUG(0, "ide_attach()\n");
103
104     /* Create new ide device */
105     info = kzalloc(sizeof(*info), GFP_KERNEL);
106     if (!info)
107         return -ENOMEM;
108
109     info->p_dev = link;
110     link->priv = info;
111
112     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
113     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
114     link->io.IOAddrLines = 3;
115     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
116     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
117     link->conf.Attributes = CONF_ENABLE_IRQ;
118     link->conf.IntType = INT_MEMORY_AND_IO;
119
120     return ide_config(link);
121 } /* ide_attach */
122
123 /*======================================================================
124
125     This deletes a driver "instance".  The device is de-registered
126     with Card Services.  If it has been released, all local data
127     structures are freed.  Otherwise, the structures will be freed
128     when the device is released.
129
130 ======================================================================*/
131
132 static void ide_detach(struct pcmcia_device *link)
133 {
134     ide_info_t *info = link->priv;
135     ide_hwif_t *hwif = info->hwif;
136     unsigned long data_addr, ctl_addr;
137
138     DEBUG(0, "ide_detach(0x%p)\n", link);
139
140     data_addr = hwif->io_ports.data_addr;
141     ctl_addr  = hwif->io_ports.ctl_addr;
142
143     ide_release(link);
144
145     release_region(ctl_addr, 1);
146     release_region(data_addr, 8);
147
148     kfree(info);
149 } /* ide_detach */
150
151 static const struct ide_port_ops idecs_port_ops = {
152         .quirkproc              = ide_undecoded_slave,
153 };
154
155 static const struct ide_port_info idecs_port_info = {
156         .port_ops               = &idecs_port_ops,
157         .host_flags             = IDE_HFLAG_NO_DMA,
158 };
159
160 static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
161                                 unsigned long irq, struct pcmcia_device *handle)
162 {
163     ide_hwif_t *hwif;
164     hw_regs_t hw;
165     int i;
166     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
167
168     if (!request_region(io, 8, DRV_NAME)) {
169         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
170                         DRV_NAME, io, io + 7);
171         return NULL;
172     }
173
174     if (!request_region(ctl, 1, DRV_NAME)) {
175         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
176                         DRV_NAME, ctl);
177         release_region(io, 8);
178         return NULL;
179     }
180
181     memset(&hw, 0, sizeof(hw));
182     ide_std_init_ports(&hw, io, ctl);
183     hw.irq = irq;
184     hw.chipset = ide_pci;
185     hw.dev = &handle->dev;
186
187     hwif = ide_find_port();
188     if (hwif == NULL)
189         goto out_release;
190
191     i = hwif->index;
192
193     ide_init_port_hw(hwif, &hw);
194
195     idx[0] = i;
196
197     ide_device_add(idx, &idecs_port_info);
198
199     if (hwif->present)
200         return hwif;
201
202     /* retry registration in case device is still spinning up */
203     for (i = 0; i < 10; i++) {
204         msleep(100);
205         ide_port_scan(hwif);
206         if (hwif->present)
207             return hwif;
208     }
209
210     return hwif;
211
212 out_release:
213     release_region(ctl, 1);
214     release_region(io, 8);
215     return NULL;
216 }
217
218 /*======================================================================
219
220     ide_config() is scheduled to run after a CARD_INSERTION event
221     is received, to configure the PCMCIA socket, and to make the
222     ide device available to the system.
223
224 ======================================================================*/
225
226 #define CS_CHECK(fn, ret) \
227 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
228
229 static int ide_config(struct pcmcia_device *link)
230 {
231     ide_info_t *info = link->priv;
232     tuple_t tuple;
233     struct {
234         u_short         buf[128];
235         cisparse_t      parse;
236         config_info_t   conf;
237         cistpl_cftable_entry_t dflt;
238     } *stk = NULL;
239     cistpl_cftable_entry_t *cfg;
240     int pass, last_ret = 0, last_fn = 0, is_kme = 0;
241     unsigned long io_base, ctl_base;
242     ide_hwif_t *hwif;
243
244     DEBUG(0, "ide_config(0x%p)\n", link);
245
246     stk = kzalloc(sizeof(*stk), GFP_KERNEL);
247     if (!stk) goto err_mem;
248     cfg = &stk->parse.cftable_entry;
249
250     tuple.TupleData = (cisdata_t *)&stk->buf;
251     tuple.TupleOffset = 0;
252     tuple.TupleDataMax = 255;
253     tuple.Attributes = 0;
254
255     is_kme = ((link->manf_id == MANFID_KME) &&
256               ((link->card_id == PRODID_KME_KXLC005_A) ||
257                (link->card_id == PRODID_KME_KXLC005_B)));
258
259     /* Not sure if this is right... look up the current Vcc */
260     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
261
262     pass = io_base = ctl_base = 0;
263     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
264     tuple.Attributes = 0;
265     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
266     while (1) {
267         if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
268         if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
269
270         /* Check for matching Vcc, unless we're desperate */
271         if (!pass) {
272             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
273                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
274                     goto next_entry;
275             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
276                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
277                     goto next_entry;
278             }
279         }
280
281         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
282             link->conf.Vpp =
283                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
284         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
285             link->conf.Vpp =
286                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
287
288         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
289             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
290             link->conf.ConfigIndex = cfg->index;
291             link->io.BasePort1 = io->win[0].base;
292             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
293             if (!(io->flags & CISTPL_IO_16BIT))
294                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
295             if (io->nwin == 2) {
296                 link->io.NumPorts1 = 8;
297                 link->io.BasePort2 = io->win[1].base;
298                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
299                 if (pcmcia_request_io(link, &link->io) != 0)
300                         goto next_entry;
301                 io_base = link->io.BasePort1;
302                 ctl_base = link->io.BasePort2;
303             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
304                 link->io.NumPorts1 = io->win[0].len;
305                 link->io.NumPorts2 = 0;
306                 if (pcmcia_request_io(link, &link->io) != 0)
307                         goto next_entry;
308                 io_base = link->io.BasePort1;
309                 ctl_base = link->io.BasePort1 + 0x0e;
310             } else goto next_entry;
311             /* If we've got this far, we're done */
312             break;
313         }
314
315     next_entry:
316         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
317             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
318         if (pass) {
319             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
320         } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
321             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
322             memset(&stk->dflt, 0, sizeof(stk->dflt));
323             pass++;
324         }
325     }
326
327     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
328     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
329
330     /* disable drive interrupts during IDE probe */
331     outb(0x02, ctl_base);
332
333     /* special setup for KXLC005 card */
334     if (is_kme)
335         outb(0x81, ctl_base+1);
336
337      hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
338      if (hwif == NULL && link->io.NumPorts1 == 0x20) {
339             outb(0x02, ctl_base + 0x10);
340             hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
341                                   link->irq.AssignedIRQ, link);
342     }
343
344     if (hwif == NULL)
345         goto failed;
346
347     info->ndev = 1;
348     sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
349     info->node.major = hwif->major;
350     info->node.minor = 0;
351     info->hwif = hwif;
352     link->dev_node = &info->node;
353     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
354            info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
355
356     kfree(stk);
357     return 0;
358
359 err_mem:
360     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
361     goto failed;
362
363 cs_failed:
364     cs_error(link, last_fn, last_ret);
365 failed:
366     kfree(stk);
367     ide_release(link);
368     return -ENODEV;
369 } /* ide_config */
370
371 /*======================================================================
372
373     After a card is removed, ide_release() will unregister the net
374     device, and release the PCMCIA configuration.  If the device is
375     still open, this will be postponed until it is closed.
376
377 ======================================================================*/
378
379 static void ide_release(struct pcmcia_device *link)
380 {
381     ide_info_t *info = link->priv;
382     ide_hwif_t *hwif = info->hwif;
383
384     DEBUG(0, "ide_release(0x%p)\n", link);
385
386     if (info->ndev) {
387         /* FIXME: if this fails we need to queue the cleanup somehow
388            -- need to investigate the required PCMCIA magic */
389         ide_unregister(hwif);
390     }
391     info->ndev = 0;
392
393     pcmcia_disable_device(link);
394 } /* ide_release */
395
396
397 /*======================================================================
398
399     The card status event handler.  Mostly, this schedules other
400     stuff to run after an event is received.  A CARD_REMOVAL event
401     also sets some flags to discourage the ide drivers from
402     talking to the ports.
403
404 ======================================================================*/
405
406 static struct pcmcia_device_id ide_ids[] = {
407         PCMCIA_DEVICE_FUNC_ID(4),
408         PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
409         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
410         PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
411         PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
412         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
413         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
414         PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
415         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
416         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
417         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
418         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
419         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
420         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
421         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
422         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
423         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
424         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
425         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
426         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
427         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
428         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
429         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
430         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
431         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
432         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
433         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
434         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
435         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
436         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
437         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
438         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
439         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
440         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
441         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
442         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
443         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
444         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
445         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
446         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
447         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
448         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
449         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
450         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
451         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
452         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
453         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
454         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
455         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
456         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
457         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
458         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
459         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
460         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
461         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
462         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
463         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
464         PCMCIA_DEVICE_NULL,
465 };
466 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
467
468 static struct pcmcia_driver ide_cs_driver = {
469         .owner          = THIS_MODULE,
470         .drv            = {
471                 .name   = "ide-cs",
472         },
473         .probe          = ide_probe,
474         .remove         = ide_detach,
475         .id_table       = ide_ids,
476 };
477
478 static int __init init_ide_cs(void)
479 {
480         return pcmcia_register_driver(&ide_cs_driver);
481 }
482
483 static void __exit exit_ide_cs(void)
484 {
485         pcmcia_unregister_driver(&ide_cs_driver);
486 }
487
488 late_initcall(init_ide_cs);
489 module_exit(exit_ide_cs);