]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ide/legacy/ide-cs.c
8b8b20d869157b3dbcb03ae8cea3bb23c45d4763
[linux-2.6-omap-h63xx.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 /*static char *version =
70 "ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";*/
71 #else
72 #define DEBUG(n, args...)
73 #endif
74
75 /*====================================================================*/
76
77 typedef struct ide_info_t {
78         struct pcmcia_device    *p_dev;
79         ide_hwif_t              *hwif;
80     int         ndev;
81     dev_node_t  node;
82 } ide_info_t;
83
84 static void ide_release(struct pcmcia_device *);
85 static int ide_config(struct pcmcia_device *);
86
87 static void ide_detach(struct pcmcia_device *p_dev);
88
89
90
91
92 /*======================================================================
93
94     ide_attach() creates an "instance" of the driver, allocating
95     local data structures for one device.  The device is registered
96     with Card Services.
97
98 ======================================================================*/
99
100 static int ide_probe(struct pcmcia_device *link)
101 {
102     ide_info_t *info;
103
104     DEBUG(0, "ide_attach()\n");
105
106     /* Create new ide device */
107     info = kzalloc(sizeof(*info), GFP_KERNEL);
108     if (!info)
109         return -ENOMEM;
110
111     info->p_dev = link;
112     link->priv = info;
113
114     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
115     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
116     link->io.IOAddrLines = 3;
117     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
118     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
119     link->conf.Attributes = CONF_ENABLE_IRQ;
120     link->conf.IntType = INT_MEMORY_AND_IO;
121
122     return ide_config(link);
123 } /* ide_attach */
124
125 /*======================================================================
126
127     This deletes a driver "instance".  The device is de-registered
128     with Card Services.  If it has been released, all local data
129     structures are freed.  Otherwise, the structures will be freed
130     when the device is released.
131
132 ======================================================================*/
133
134 static void ide_detach(struct pcmcia_device *link)
135 {
136     ide_info_t *info = link->priv;
137     ide_hwif_t *hwif = info->hwif;
138
139     DEBUG(0, "ide_detach(0x%p)\n", link);
140
141     ide_release(link);
142
143     release_region(hwif->io_ports.ctl_addr, 1);
144     release_region(hwif->io_ports.data_addr, 8);
145
146     kfree(info);
147 } /* ide_detach */
148
149 static const struct ide_port_ops idecs_port_ops = {
150         .quirkproc              = ide_undecoded_slave,
151 };
152
153 static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
154                                 unsigned long irq, struct pcmcia_device *handle)
155 {
156     ide_hwif_t *hwif;
157     hw_regs_t hw;
158     int i;
159     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
160
161     if (!request_region(io, 8, DRV_NAME)) {
162         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
163                         DRV_NAME, io, io + 7);
164         return NULL;
165     }
166
167     if (!request_region(ctl, 1, DRV_NAME)) {
168         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
169                         DRV_NAME, ctl);
170         release_region(io, 8);
171         return NULL;
172     }
173
174     memset(&hw, 0, sizeof(hw));
175     ide_std_init_ports(&hw, io, ctl);
176     hw.irq = irq;
177     hw.chipset = ide_pci;
178     hw.dev = &handle->dev;
179
180     hwif = ide_find_port();
181     if (hwif == NULL)
182         goto out_release;
183
184     i = hwif->index;
185
186     ide_init_port_data(hwif, i);
187     ide_init_port_hw(hwif, &hw);
188     hwif->port_ops = &idecs_port_ops;
189
190     idx[0] = i;
191
192     ide_device_add(idx, NULL);
193
194     if (hwif->present)
195         return hwif;
196
197 out_release:
198     release_region(ctl, 1);
199     release_region(io, 8);
200     return NULL;
201 }
202
203 /*======================================================================
204
205     ide_config() is scheduled to run after a CARD_INSERTION event
206     is received, to configure the PCMCIA socket, and to make the
207     ide device available to the system.
208
209 ======================================================================*/
210
211 #define CS_CHECK(fn, ret) \
212 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
213
214 static int ide_config(struct pcmcia_device *link)
215 {
216     ide_info_t *info = link->priv;
217     tuple_t tuple;
218     struct {
219         u_short         buf[128];
220         cisparse_t      parse;
221         config_info_t   conf;
222         cistpl_cftable_entry_t dflt;
223     } *stk = NULL;
224     cistpl_cftable_entry_t *cfg;
225     int i, pass, last_ret = 0, last_fn = 0, is_kme = 0;
226     unsigned long io_base, ctl_base;
227     ide_hwif_t *hwif;
228
229     DEBUG(0, "ide_config(0x%p)\n", link);
230
231     stk = kzalloc(sizeof(*stk), GFP_KERNEL);
232     if (!stk) goto err_mem;
233     cfg = &stk->parse.cftable_entry;
234
235     tuple.TupleData = (cisdata_t *)&stk->buf;
236     tuple.TupleOffset = 0;
237     tuple.TupleDataMax = 255;
238     tuple.Attributes = 0;
239
240     is_kme = ((link->manf_id == MANFID_KME) &&
241               ((link->card_id == PRODID_KME_KXLC005_A) ||
242                (link->card_id == PRODID_KME_KXLC005_B)));
243
244     /* Not sure if this is right... look up the current Vcc */
245     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
246
247     pass = io_base = ctl_base = 0;
248     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
249     tuple.Attributes = 0;
250     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
251     while (1) {
252         if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
253         if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
254
255         /* Check for matching Vcc, unless we're desperate */
256         if (!pass) {
257             if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
258                 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
259                     goto next_entry;
260             } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
261                 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
262                     goto next_entry;
263             }
264         }
265
266         if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
267             link->conf.Vpp =
268                 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
269         else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
270             link->conf.Vpp =
271                 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
272
273         if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
274             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
275             link->conf.ConfigIndex = cfg->index;
276             link->io.BasePort1 = io->win[0].base;
277             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
278             if (!(io->flags & CISTPL_IO_16BIT))
279                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
280             if (io->nwin == 2) {
281                 link->io.NumPorts1 = 8;
282                 link->io.BasePort2 = io->win[1].base;
283                 link->io.NumPorts2 = (is_kme) ? 2 : 1;
284                 if (pcmcia_request_io(link, &link->io) != 0)
285                         goto next_entry;
286                 io_base = link->io.BasePort1;
287                 ctl_base = link->io.BasePort2;
288             } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
289                 link->io.NumPorts1 = io->win[0].len;
290                 link->io.NumPorts2 = 0;
291                 if (pcmcia_request_io(link, &link->io) != 0)
292                         goto next_entry;
293                 io_base = link->io.BasePort1;
294                 ctl_base = link->io.BasePort1 + 0x0e;
295             } else goto next_entry;
296             /* If we've got this far, we're done */
297             break;
298         }
299
300     next_entry:
301         if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
302             memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
303         if (pass) {
304             CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
305         } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
306             CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
307             memset(&stk->dflt, 0, sizeof(stk->dflt));
308             pass++;
309         }
310     }
311
312     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
313     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
314
315     /* disable drive interrupts during IDE probe */
316     outb(0x02, ctl_base);
317
318     /* special setup for KXLC005 card */
319     if (is_kme)
320         outb(0x81, ctl_base+1);
321
322     /* retry registration in case device is still spinning up */
323     for (i = 0; i < 10; i++) {
324         hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
325         if (hwif)
326             break;
327         if (link->io.NumPorts1 == 0x20) {
328             outb(0x02, ctl_base + 0x10);
329             hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
330                                   link->irq.AssignedIRQ, link);
331             if (hwif) {
332                 io_base += 0x10;
333                 ctl_base += 0x10;
334                 break;
335             }
336         }
337         msleep(100);
338     }
339
340     if (hwif == NULL) {
341         printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
342                ", irq %u failed\n", io_base, ctl_base,
343                link->irq.AssignedIRQ);
344         goto failed;
345     }
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 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(0x0098, 0x0000),        /* Toshiba */
415         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
416         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
417         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
418         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
419         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
420         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
421         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
422         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
423         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
424         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
425         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
426         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
427         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
428         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
429         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
430         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
431         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
432         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
433         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
434         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
435         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
436         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
437         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
438         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
439         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
440         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
441         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
442         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
443         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
444         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
445         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
446         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
447         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
448         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
449         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
450         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
451         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
452         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
453         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
454         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
455         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
456         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
457         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
458         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
459         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
460         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
461         PCMCIA_DEVICE_NULL,
462 };
463 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
464
465 static struct pcmcia_driver ide_cs_driver = {
466         .owner          = THIS_MODULE,
467         .drv            = {
468                 .name   = "ide-cs",
469         },
470         .probe          = ide_probe,
471         .remove         = ide_detach,
472         .id_table       = ide_ids,
473 };
474
475 static int __init init_ide_cs(void)
476 {
477         return pcmcia_register_driver(&ide_cs_driver);
478 }
479
480 static void __exit exit_ide_cs(void)
481 {
482         pcmcia_unregister_driver(&ide_cs_driver);
483 }
484
485 late_initcall(init_ide_cs);
486 module_exit(exit_ide_cs);