]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/ide/ide-cs.c
Merge branch 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6.git] / drivers / ide / 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/major.h>
42 #include <linux/delay.h>
43 #include <asm/io.h>
44 #include <asm/system.h>
45
46 #include <pcmcia/cs_types.h>
47 #include <pcmcia/cs.h>
48 #include <pcmcia/cistpl.h>
49 #include <pcmcia/ds.h>
50 #include <pcmcia/cisreg.h>
51 #include <pcmcia/ciscode.h>
52
53 #define DRV_NAME "ide-cs"
54
55 /*====================================================================*/
56
57 /* Module parameters */
58
59 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
60 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
61 MODULE_LICENSE("Dual MPL/GPL");
62
63 /*====================================================================*/
64
65 typedef struct ide_info_t {
66         struct pcmcia_device    *p_dev;
67         struct ide_host         *host;
68     int         ndev;
69     dev_node_t  node;
70 } ide_info_t;
71
72 static void ide_release(struct pcmcia_device *);
73 static int ide_config(struct pcmcia_device *);
74
75 static void ide_detach(struct pcmcia_device *p_dev);
76
77
78
79
80 /*======================================================================
81
82     ide_attach() creates an "instance" of the driver, allocating
83     local data structures for one device.  The device is registered
84     with Card Services.
85
86 ======================================================================*/
87
88 static int ide_probe(struct pcmcia_device *link)
89 {
90     ide_info_t *info;
91
92     dev_dbg(&link->dev, "ide_attach()\n");
93
94     /* Create new ide device */
95     info = kzalloc(sizeof(*info), GFP_KERNEL);
96     if (!info)
97         return -ENOMEM;
98
99     info->p_dev = link;
100     link->priv = info;
101
102     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
103     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
104     link->io.IOAddrLines = 3;
105     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
106     link->conf.Attributes = CONF_ENABLE_IRQ;
107     link->conf.IntType = INT_MEMORY_AND_IO;
108
109     return ide_config(link);
110 } /* ide_attach */
111
112 /*======================================================================
113
114     This deletes a driver "instance".  The device is de-registered
115     with Card Services.  If it has been released, all local data
116     structures are freed.  Otherwise, the structures will be freed
117     when the device is released.
118
119 ======================================================================*/
120
121 static void ide_detach(struct pcmcia_device *link)
122 {
123     ide_info_t *info = link->priv;
124     ide_hwif_t *hwif = info->host->ports[0];
125     unsigned long data_addr, ctl_addr;
126
127     dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
128
129     data_addr = hwif->io_ports.data_addr;
130     ctl_addr  = hwif->io_ports.ctl_addr;
131
132     ide_release(link);
133
134     release_region(ctl_addr, 1);
135     release_region(data_addr, 8);
136
137     kfree(info);
138 } /* ide_detach */
139
140 static const struct ide_port_ops idecs_port_ops = {
141         .quirkproc              = ide_undecoded_slave,
142 };
143
144 static const struct ide_port_info idecs_port_info = {
145         .port_ops               = &idecs_port_ops,
146         .host_flags             = IDE_HFLAG_NO_DMA,
147         .irq_flags              = IRQF_SHARED,
148         .chipset                = ide_pci,
149 };
150
151 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
152                                 unsigned long irq, struct pcmcia_device *handle)
153 {
154     struct ide_host *host;
155     ide_hwif_t *hwif;
156     int i, rc;
157     struct ide_hw hw, *hws[] = { &hw };
158
159     if (!request_region(io, 8, DRV_NAME)) {
160         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
161                         DRV_NAME, io, io + 7);
162         return NULL;
163     }
164
165     if (!request_region(ctl, 1, DRV_NAME)) {
166         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
167                         DRV_NAME, ctl);
168         release_region(io, 8);
169         return NULL;
170     }
171
172     memset(&hw, 0, sizeof(hw));
173     ide_std_init_ports(&hw, io, ctl);
174     hw.irq = irq;
175     hw.dev = &handle->dev;
176
177     rc = ide_host_add(&idecs_port_info, hws, 1, &host);
178     if (rc)
179         goto out_release;
180
181     hwif = host->ports[0];
182
183     if (hwif->present)
184         return host;
185
186     /* retry registration in case device is still spinning up */
187     for (i = 0; i < 10; i++) {
188         msleep(100);
189         ide_port_scan(hwif);
190         if (hwif->present)
191             return host;
192     }
193
194     return host;
195
196 out_release:
197     release_region(ctl, 1);
198     release_region(io, 8);
199     return NULL;
200 }
201
202 /*======================================================================
203
204     ide_config() is scheduled to run after a CARD_INSERTION event
205     is received, to configure the PCMCIA socket, and to make the
206     ide device available to the system.
207
208 ======================================================================*/
209
210 struct pcmcia_config_check {
211         unsigned long ctl_base;
212         int skip_vcc;
213         int is_kme;
214 };
215
216 static int pcmcia_check_one_config(struct pcmcia_device *pdev,
217                                    cistpl_cftable_entry_t *cfg,
218                                    cistpl_cftable_entry_t *dflt,
219                                    unsigned int vcc,
220                                    void *priv_data)
221 {
222         struct pcmcia_config_check *stk = priv_data;
223
224         /* Check for matching Vcc, unless we're desperate */
225         if (!stk->skip_vcc) {
226                 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
227                         if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
228                                 return -ENODEV;
229                 } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
230                         if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
231                                 return -ENODEV;
232                 }
233         }
234
235         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
236                 pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
237         else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
238                 pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
239
240         if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
241                 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
242                 pdev->conf.ConfigIndex = cfg->index;
243                 pdev->io.BasePort1 = io->win[0].base;
244                 pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
245                 if (!(io->flags & CISTPL_IO_16BIT))
246                         pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
247                 if (io->nwin == 2) {
248                         pdev->io.NumPorts1 = 8;
249                         pdev->io.BasePort2 = io->win[1].base;
250                         pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
251                         if (pcmcia_request_io(pdev, &pdev->io) != 0)
252                                 return -ENODEV;
253                         stk->ctl_base = pdev->io.BasePort2;
254                 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
255                         pdev->io.NumPorts1 = io->win[0].len;
256                         pdev->io.NumPorts2 = 0;
257                         if (pcmcia_request_io(pdev, &pdev->io) != 0)
258                                 return -ENODEV;
259                         stk->ctl_base = pdev->io.BasePort1 + 0x0e;
260                 } else
261                         return -ENODEV;
262                 /* If we've got this far, we're done */
263                 return 0;
264         }
265         return -ENODEV;
266 }
267
268 static int ide_config(struct pcmcia_device *link)
269 {
270     ide_info_t *info = link->priv;
271     struct pcmcia_config_check *stk = NULL;
272     int ret = 0, is_kme = 0;
273     unsigned long io_base, ctl_base;
274     struct ide_host *host;
275
276     dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
277
278     is_kme = ((link->manf_id == MANFID_KME) &&
279               ((link->card_id == PRODID_KME_KXLC005_A) ||
280                (link->card_id == PRODID_KME_KXLC005_B)));
281
282     stk = kzalloc(sizeof(*stk), GFP_KERNEL);
283     if (!stk)
284             goto err_mem;
285     stk->is_kme = is_kme;
286     stk->skip_vcc = io_base = ctl_base = 0;
287
288     if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
289             stk->skip_vcc = 1;
290             if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
291                     goto failed; /* No suitable config found */
292     }
293     io_base = link->io.BasePort1;
294     ctl_base = stk->ctl_base;
295
296     ret = pcmcia_request_irq(link, &link->irq);
297     if (ret)
298             goto failed;
299     ret = pcmcia_request_configuration(link, &link->conf);
300     if (ret)
301             goto failed;
302
303     /* disable drive interrupts during IDE probe */
304     outb(0x02, ctl_base);
305
306     /* special setup for KXLC005 card */
307     if (is_kme)
308         outb(0x81, ctl_base+1);
309
310      host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
311      if (host == NULL && link->io.NumPorts1 == 0x20) {
312             outb(0x02, ctl_base + 0x10);
313             host = idecs_register(io_base + 0x10, ctl_base + 0x10,
314                                   link->irq.AssignedIRQ, link);
315     }
316
317     if (host == NULL)
318         goto failed;
319
320     info->ndev = 1;
321     sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
322     info->node.major = host->ports[0]->major;
323     info->node.minor = 0;
324     info->host = host;
325     link->dev_node = &info->node;
326     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
327            info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
328
329     kfree(stk);
330     return 0;
331
332 err_mem:
333     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
334     goto failed;
335
336 failed:
337     kfree(stk);
338     ide_release(link);
339     return -ENODEV;
340 } /* ide_config */
341
342 /*======================================================================
343
344     After a card is removed, ide_release() will unregister the net
345     device, and release the PCMCIA configuration.  If the device is
346     still open, this will be postponed until it is closed.
347
348 ======================================================================*/
349
350 static void ide_release(struct pcmcia_device *link)
351 {
352     ide_info_t *info = link->priv;
353     struct ide_host *host = info->host;
354
355     dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
356
357     if (info->ndev)
358         /* FIXME: if this fails we need to queue the cleanup somehow
359            -- need to investigate the required PCMCIA magic */
360         ide_host_remove(host);
361
362     info->ndev = 0;
363
364     pcmcia_disable_device(link);
365 } /* ide_release */
366
367
368 /*======================================================================
369
370     The card status event handler.  Mostly, this schedules other
371     stuff to run after an event is received.  A CARD_REMOVAL event
372     also sets some flags to discourage the ide drivers from
373     talking to the ports.
374
375 ======================================================================*/
376
377 static struct pcmcia_device_id ide_ids[] = {
378         PCMCIA_DEVICE_FUNC_ID(4),
379         PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
380         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
381         PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
382         PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
383         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
384         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
385         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
386         PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
387         PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
388         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
389         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
390         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
391         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
392         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
393         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
394         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
395         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
396         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
397         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
398         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
399         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
400         PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
401         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
402         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
403         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
404         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
405         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
406         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
407         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
408         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
409         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
410         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
411         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
412         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
413         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
414         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
415         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
416         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
417         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
418         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
419         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
420         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
421         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
422         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
423         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
424         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
425         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
426         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
427         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
428         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
429         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
430         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
431         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
432         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
433         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
434         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
435         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
436         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
437         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
438         PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
439         PCMCIA_DEVICE_NULL,
440 };
441 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
442
443 static struct pcmcia_driver ide_cs_driver = {
444         .owner          = THIS_MODULE,
445         .drv            = {
446                 .name   = "ide-cs",
447         },
448         .probe          = ide_probe,
449         .remove         = ide_detach,
450         .id_table       = ide_ids,
451 };
452
453 static int __init init_ide_cs(void)
454 {
455         return pcmcia_register_driver(&ide_cs_driver);
456 }
457
458 static void __exit exit_ide_cs(void)
459 {
460         pcmcia_unregister_driver(&ide_cs_driver);
461 }
462
463 late_initcall(init_ide_cs);
464 module_exit(exit_ide_cs);