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