PM / Sleep: Add more wakeup source initialization routines
[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/cistpl.h>
47 #include <pcmcia/ds.h>
48 #include <pcmcia/cisreg.h>
49 #include <pcmcia/ciscode.h>
50
51 #define DRV_NAME "ide-cs"
52
53 /*====================================================================*/
54
55 /* Module parameters */
56
57 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
58 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
59 MODULE_LICENSE("Dual MPL/GPL");
60
61 /*====================================================================*/
62
63 typedef struct ide_info_t {
64         struct pcmcia_device    *p_dev;
65         struct ide_host         *host;
66         int                     ndev;
67 } ide_info_t;
68
69 static void ide_release(struct pcmcia_device *);
70 static int ide_config(struct pcmcia_device *);
71
72 static void ide_detach(struct pcmcia_device *p_dev);
73
74 static int ide_probe(struct pcmcia_device *link)
75 {
76     ide_info_t *info;
77
78     dev_dbg(&link->dev, "ide_attach()\n");
79
80     /* Create new ide device */
81     info = kzalloc(sizeof(*info), GFP_KERNEL);
82     if (!info)
83         return -ENOMEM;
84
85     info->p_dev = link;
86     link->priv = info;
87
88     link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
89             CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
90
91     return ide_config(link);
92 } /* ide_attach */
93
94 static void ide_detach(struct pcmcia_device *link)
95 {
96     ide_info_t *info = link->priv;
97
98     dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
99
100     ide_release(link);
101
102     kfree(info);
103 } /* ide_detach */
104
105 static const struct ide_port_ops idecs_port_ops = {
106         .quirkproc              = ide_undecoded_slave,
107 };
108
109 static const struct ide_port_info idecs_port_info = {
110         .port_ops               = &idecs_port_ops,
111         .host_flags             = IDE_HFLAG_NO_DMA,
112         .irq_flags              = IRQF_SHARED,
113         .chipset                = ide_pci,
114 };
115
116 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
117                                 unsigned long irq, struct pcmcia_device *handle)
118 {
119     struct ide_host *host;
120     ide_hwif_t *hwif;
121     int i, rc;
122     struct ide_hw hw, *hws[] = { &hw };
123
124     if (!request_region(io, 8, DRV_NAME)) {
125         printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
126                         DRV_NAME, io, io + 7);
127         return NULL;
128     }
129
130     if (!request_region(ctl, 1, DRV_NAME)) {
131         printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
132                         DRV_NAME, ctl);
133         release_region(io, 8);
134         return NULL;
135     }
136
137     memset(&hw, 0, sizeof(hw));
138     ide_std_init_ports(&hw, io, ctl);
139     hw.irq = irq;
140     hw.dev = &handle->dev;
141
142     rc = ide_host_add(&idecs_port_info, hws, 1, &host);
143     if (rc)
144         goto out_release;
145
146     hwif = host->ports[0];
147
148     if (hwif->present)
149         return host;
150
151     /* retry registration in case device is still spinning up */
152     for (i = 0; i < 10; i++) {
153         msleep(100);
154         ide_port_scan(hwif);
155         if (hwif->present)
156             return host;
157     }
158
159     return host;
160
161 out_release:
162     release_region(ctl, 1);
163     release_region(io, 8);
164     return NULL;
165 }
166
167 static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
168 {
169         int *is_kme = priv_data;
170
171         if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
172                 pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
173                 pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
174         }
175         pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
176         pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
177
178         if (pdev->resource[1]->end) {
179                 pdev->resource[0]->end = 8;
180                 pdev->resource[1]->end = (*is_kme) ? 2 : 1;
181         } else {
182                 if (pdev->resource[0]->end < 16)
183                         return -ENODEV;
184         }
185
186         return pcmcia_request_io(pdev);
187 }
188
189 static int ide_config(struct pcmcia_device *link)
190 {
191     ide_info_t *info = link->priv;
192     int ret = 0, is_kme = 0;
193     unsigned long io_base, ctl_base;
194     struct ide_host *host;
195
196     dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
197
198     is_kme = ((link->manf_id == MANFID_KME) &&
199               ((link->card_id == PRODID_KME_KXLC005_A) ||
200                (link->card_id == PRODID_KME_KXLC005_B)));
201
202     if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
203             link->config_flags &= ~CONF_AUTO_CHECK_VCC;
204             if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
205                     goto failed; /* No suitable config found */
206     }
207     io_base = link->resource[0]->start;
208     if (link->resource[1]->end)
209             ctl_base = link->resource[1]->start;
210     else
211             ctl_base = link->resource[0]->start + 0x0e;
212
213     if (!link->irq)
214             goto failed;
215
216     ret = pcmcia_enable_device(link);
217     if (ret)
218             goto failed;
219
220     /* disable drive interrupts during IDE probe */
221     outb(0x02, ctl_base);
222
223     /* special setup for KXLC005 card */
224     if (is_kme)
225         outb(0x81, ctl_base+1);
226
227      host = idecs_register(io_base, ctl_base, link->irq, link);
228      if (host == NULL && resource_size(link->resource[0]) == 0x20) {
229             outb(0x02, ctl_base + 0x10);
230             host = idecs_register(io_base + 0x10, ctl_base + 0x10,
231                                   link->irq, link);
232     }
233
234     if (host == NULL)
235         goto failed;
236
237     info->ndev = 1;
238     info->host = host;
239     dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
240             'a' + host->ports[0]->index * 2,
241             link->vpp / 10, link->vpp % 10);
242
243     return 0;
244
245 failed:
246     ide_release(link);
247     return -ENODEV;
248 } /* ide_config */
249
250 static void ide_release(struct pcmcia_device *link)
251 {
252     ide_info_t *info = link->priv;
253     struct ide_host *host = info->host;
254
255     dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
256
257     if (info->ndev) {
258         ide_hwif_t *hwif = host->ports[0];
259         unsigned long data_addr, ctl_addr;
260
261         data_addr = hwif->io_ports.data_addr;
262         ctl_addr = hwif->io_ports.ctl_addr;
263
264         ide_host_remove(host);
265         info->ndev = 0;
266
267         release_region(ctl_addr, 1);
268         release_region(data_addr, 8);
269     }
270
271     pcmcia_disable_device(link);
272 } /* ide_release */
273
274
275 static const struct pcmcia_device_id ide_ids[] = {
276         PCMCIA_DEVICE_FUNC_ID(4),
277         PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
278         PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
279         PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
280         PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
281         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
282         PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
283         PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
284         PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
285         PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
286         PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
287         PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
288         PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
289         PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
290         PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
291         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
292         PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
293         PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
294         PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
295         PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
296         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
297         PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
298         PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
299         PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
300         PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
301         PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
302         PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
303         PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
304         PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
305         PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
306         PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
307         PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
308         PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
309         PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
310         PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
311         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
312         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
313         PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
314         PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
315         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
316         PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
317         PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
318         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
319         PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
320         PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
321         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
322         PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
323         PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
324         PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
325         PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
326         PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
327         PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
328         PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
329         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
330         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
331         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
332         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
333         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
334         PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
335         PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
336         PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
337         PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
338         PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
339         PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
340         PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
341         PCMCIA_DEVICE_NULL,
342 };
343 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
344
345 static struct pcmcia_driver ide_cs_driver = {
346         .owner          = THIS_MODULE,
347         .name           = "ide-cs",
348         .probe          = ide_probe,
349         .remove         = ide_detach,
350         .id_table       = ide_ids,
351 };
352
353 static int __init init_ide_cs(void)
354 {
355         return pcmcia_register_driver(&ide_cs_driver);
356 }
357
358 static void __exit exit_ide_cs(void)
359 {
360         pcmcia_unregister_driver(&ide_cs_driver);
361 }
362
363 late_initcall(init_ide_cs);
364 module_exit(exit_ide_cs);