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