Root/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
45#include <pcmcia/cistpl.h>
46#include <pcmcia/ds.h>
47#include <pcmcia/cisreg.h>
48#include <pcmcia/ciscode.h>
49
50#define DRV_NAME "ide-cs"
51
52/*====================================================================*/
53
54/* Module parameters */
55
56MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
57MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
58MODULE_LICENSE("Dual MPL/GPL");
59
60/*====================================================================*/
61
62typedef struct ide_info_t {
63    struct pcmcia_device *p_dev;
64    struct ide_host *host;
65    int ndev;
66} ide_info_t;
67
68static void ide_release(struct pcmcia_device *);
69static int ide_config(struct pcmcia_device *);
70
71static void ide_detach(struct pcmcia_device *p_dev);
72
73static int ide_probe(struct pcmcia_device *link)
74{
75    ide_info_t *info;
76
77    dev_dbg(&link->dev, "ide_attach()\n");
78
79    /* Create new ide device */
80    info = kzalloc(sizeof(*info), GFP_KERNEL);
81    if (!info)
82    return -ENOMEM;
83
84    info->p_dev = link;
85    link->priv = info;
86
87    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
88        CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
89
90    return ide_config(link);
91} /* ide_attach */
92
93static void ide_detach(struct pcmcia_device *link)
94{
95    ide_info_t *info = link->priv;
96
97    dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
98
99    ide_release(link);
100
101    kfree(info);
102} /* ide_detach */
103
104static const struct ide_port_ops idecs_port_ops = {
105    .quirkproc = ide_undecoded_slave,
106};
107
108static const struct ide_port_info idecs_port_info = {
109    .port_ops = &idecs_port_ops,
110    .host_flags = IDE_HFLAG_NO_DMA,
111    .irq_flags = IRQF_SHARED,
112    .chipset = ide_pci,
113};
114
115static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
116                unsigned long irq, struct pcmcia_device *handle)
117{
118    struct ide_host *host;
119    ide_hwif_t *hwif;
120    int i, rc;
121    struct ide_hw hw, *hws[] = { &hw };
122
123    if (!request_region(io, 8, DRV_NAME)) {
124    printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
125            DRV_NAME, io, io + 7);
126    return NULL;
127    }
128
129    if (!request_region(ctl, 1, DRV_NAME)) {
130    printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
131            DRV_NAME, ctl);
132    release_region(io, 8);
133    return NULL;
134    }
135
136    memset(&hw, 0, sizeof(hw));
137    ide_std_init_ports(&hw, io, ctl);
138    hw.irq = irq;
139    hw.dev = &handle->dev;
140
141    rc = ide_host_add(&idecs_port_info, hws, 1, &host);
142    if (rc)
143    goto out_release;
144
145    hwif = host->ports[0];
146
147    if (hwif->present)
148    return host;
149
150    /* retry registration in case device is still spinning up */
151    for (i = 0; i < 10; i++) {
152    msleep(100);
153    ide_port_scan(hwif);
154    if (hwif->present)
155        return host;
156    }
157
158    return host;
159
160out_release:
161    release_region(ctl, 1);
162    release_region(io, 8);
163    return NULL;
164}
165
166static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
167{
168    int *is_kme = priv_data;
169
170    if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH)
171        != 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
189static 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
245failed:
246    ide_release(link);
247    return -ENODEV;
248} /* ide_config */
249
250static 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
275static 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};
343MODULE_DEVICE_TABLE(pcmcia, ide_ids);
344
345static 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
353static int __init init_ide_cs(void)
354{
355    return pcmcia_register_driver(&ide_cs_driver);
356}
357
358static void __exit exit_ide_cs(void)
359{
360    pcmcia_unregister_driver(&ide_cs_driver);
361}
362
363late_initcall(init_ide_cs);
364module_exit(exit_ide_cs);
365

Archive Download this file



interactive