1 /*======================================================================
3 A driver for PCMCIA IDE/ATA disk cards
5 ide-cs.c 1.3 2002/10/26 05:45:31
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in
23 which case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/init.h>
37 #include <linux/sched.h>
38 #include <linux/ptrace.h>
39 #include <linux/slab.h>
40 #include <linux/string.h>
41 #include <linux/timer.h>
42 #include <linux/ioport.h>
43 #include <linux/ide.h>
44 #include <linux/hdreg.h>
45 #include <linux/major.h>
46 #include <linux/delay.h>
48 #include <asm/system.h>
50 #include <pcmcia/version.h>
51 #include <pcmcia/cs_types.h>
52 #include <pcmcia/cs.h>
53 #include <pcmcia/cistpl.h>
54 #include <pcmcia/ds.h>
55 #include <pcmcia/cisreg.h>
56 #include <pcmcia/ciscode.h>
58 /*====================================================================*/
60 /* Module parameters */
62 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
63 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
64 MODULE_LICENSE("Dual MPL/GPL");
66 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
68 /* Bit map of interrupts to choose from */
69 INT_MODULE_PARM(irq_mask, 0xdeb8);
70 static int irq_list[4] = { -1 };
71 MODULE_PARM(irq_list, "1-4i");
74 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
75 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
76 static char *version =
77 "ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
79 #define DEBUG(n, args...)
82 /*====================================================================*/
84 static const char ide_major[] = {
85 IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
86 IDE4_MAJOR, IDE5_MAJOR
89 typedef struct ide_info_t {
97 static void ide_release(dev_link_t *);
98 static int ide_event(event_t event, int priority,
99 event_callback_args_t *args);
101 static dev_info_t dev_info = "ide-cs";
103 static dev_link_t *ide_attach(void);
104 static void ide_detach(dev_link_t *);
106 static dev_link_t *dev_list = NULL;
108 /*======================================================================
110 ide_attach() creates an "instance" of the driver, allocating
111 local data structures for one device. The device is registered
114 ======================================================================*/
116 static dev_link_t *ide_attach(void)
120 client_reg_t client_reg;
123 DEBUG(0, "ide_attach()\n");
125 /* Create new ide device */
126 info = kmalloc(sizeof(*info), GFP_KERNEL);
127 if (!info) return NULL;
128 memset(info, 0, sizeof(*info));
129 link = &info->link; link->priv = info;
131 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
132 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
133 link->io.IOAddrLines = 3;
134 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
135 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
136 if (irq_list[0] == -1)
137 link->irq.IRQInfo2 = irq_mask;
139 for (i = 0; i < 4; i++)
140 link->irq.IRQInfo2 |= 1 << irq_list[i];
141 link->conf.Attributes = CONF_ENABLE_IRQ;
143 link->conf.IntType = INT_MEMORY_AND_IO;
145 /* Register with Card Services */
146 link->next = dev_list;
148 client_reg.dev_info = &dev_info;
149 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
150 client_reg.EventMask =
151 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
152 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
153 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
154 client_reg.event_handler = &ide_event;
155 client_reg.Version = 0x0210;
156 client_reg.event_callback_args.client_data = link;
157 ret = pcmcia_register_client(&link->handle, &client_reg);
158 if (ret != CS_SUCCESS) {
159 cs_error(link->handle, RegisterClient, ret);
167 /*======================================================================
169 This deletes a driver "instance". The device is de-registered
170 with Card Services. If it has been released, all local data
171 structures are freed. Otherwise, the structures will be freed
172 when the device is released.
174 ======================================================================*/
176 static void ide_detach(dev_link_t *link)
181 DEBUG(0, "ide_detach(0x%p)\n", link);
183 /* Locate device structure */
184 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
185 if (*linkp == link) break;
189 if (link->state & DEV_CONFIG)
193 ret = pcmcia_deregister_client(link->handle);
194 if (ret != CS_SUCCESS)
195 cs_error(link->handle, DeregisterClient, ret);
198 /* Unlink, free device structure */
204 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, ide_hwif_t **hwif)
207 memset(&hw, 0, sizeof(hw));
208 ide_init_hwif_ports(&hw, io, ctl, NULL);
210 hw.chipset = ide_pci;
211 return ide_register_hw_with_fixup(&hw, hwif, ide_undecoded_slave);
214 /*======================================================================
216 ide_config() is scheduled to run after a CARD_INSERTION event
217 is received, to configure the PCMCIA socket, and to make the
218 ide device available to the system.
220 ======================================================================*/
222 #define CS_CHECK(fn, ret) \
223 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
225 void ide_config(dev_link_t *link)
227 client_handle_t handle = link->handle;
228 ide_info_t *info = link->priv;
235 cistpl_cftable_entry_t dflt;
237 cistpl_cftable_entry_t *cfg;
238 int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
239 unsigned long io_base, ctl_base;
241 DEBUG(0, "ide_config(0x%p)\n", link);
243 stk = kmalloc(sizeof(*stk), GFP_KERNEL);
244 if (!stk) goto err_mem;
245 memset(stk, 0, sizeof(*stk));
246 cfg = &stk->parse.cftable_entry;
248 tuple.TupleData = (cisdata_t *)&stk->buf;
249 tuple.TupleOffset = 0;
250 tuple.TupleDataMax = 255;
251 tuple.Attributes = 0;
252 tuple.DesiredTuple = CISTPL_CONFIG;
253 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
254 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
255 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
256 link->conf.ConfigBase = stk->parse.config.base;
257 link->conf.Present = stk->parse.config.rmask[0];
259 tuple.DesiredTuple = CISTPL_MANFID;
260 if (!pcmcia_get_first_tuple(handle, &tuple) &&
261 !pcmcia_get_tuple_data(handle, &tuple) &&
262 !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
263 is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
264 ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
265 (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
268 link->state |= DEV_CONFIG;
270 /* Not sure if this is right... look up the current Vcc */
271 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
272 link->conf.Vcc = stk->conf.Vcc;
274 pass = io_base = ctl_base = 0;
275 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
276 tuple.Attributes = 0;
277 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
279 if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
280 if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
282 /* Check for matching Vcc, unless we're desperate */
284 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
285 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
287 } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
288 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
293 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
294 link->conf.Vpp1 = link->conf.Vpp2 =
295 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
296 else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
297 link->conf.Vpp1 = link->conf.Vpp2 =
298 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
300 if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
301 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
302 link->conf.ConfigIndex = cfg->index;
303 link->io.BasePort1 = io->win[0].base;
304 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
305 if (!(io->flags & CISTPL_IO_16BIT))
306 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
308 link->io.NumPorts1 = 8;
309 link->io.BasePort2 = io->win[1].base;
310 link->io.NumPorts2 = (is_kme) ? 2 : 1;
311 if (pcmcia_request_io(link->handle, &link->io) != 0)
313 io_base = link->io.BasePort1;
314 ctl_base = link->io.BasePort2;
315 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
316 link->io.NumPorts1 = io->win[0].len;
317 link->io.NumPorts2 = 0;
318 if (pcmcia_request_io(link->handle, &link->io) != 0)
320 io_base = link->io.BasePort1;
321 ctl_base = link->io.BasePort1 + 0x0e;
322 } else goto next_entry;
323 /* If we've got this far, we're done */
328 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
329 memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
331 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
332 } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
333 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
334 memset(&stk->dflt, 0, sizeof(stk->dflt));
339 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
340 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
342 /* disable drive interrupts during IDE probe */
343 outb(0x02, ctl_base);
345 /* special setup for KXLC005 card */
347 outb(0x81, ctl_base+1);
349 /* retry registration in case device is still spinning up
351 FIXME: now handled by IDE layer... ?? */
353 for (hd = -1, i = 0; i < 10; i++) {
354 hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, &hwif);
356 if (link->io.NumPorts1 == 0x20) {
357 outb(0x02, ctl_base + 0x10);
358 hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
359 link->irq.AssignedIRQ, &hwif);
370 printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
371 ", irq %u failed\n", io_base, ctl_base,
372 link->irq.AssignedIRQ);
377 sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
378 info->node.major = ide_major[hd];
379 info->node.minor = 0;
382 link->dev = &info->node;
383 printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
384 info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
385 link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
387 link->state &= ~DEV_CONFIG_PENDING;
392 printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
396 cs_error(link->handle, last_fn, last_ret);
400 link->state &= ~DEV_CONFIG_PENDING;
403 /*======================================================================
405 After a card is removed, ide_release() will unregister the net
406 device, and release the PCMCIA configuration. If the device is
407 still open, this will be postponed until it is closed.
409 ======================================================================*/
411 void ide_release(dev_link_t *link)
413 ide_info_t *info = link->priv;
415 DEBUG(0, "ide_release(0x%p)\n", link);
418 /* Wait for the interface to cease to be busy */
419 while(ide_unregister_hwif(info->hwif) < 0) {
420 removed_hwif_iops(info->hwif);
427 pcmcia_release_configuration(link->handle);
428 pcmcia_release_io(link->handle, &link->io);
429 pcmcia_release_irq(link->handle, &link->irq);
431 link->state &= ~DEV_CONFIG;
435 /*======================================================================
437 The card status event handler. Mostly, this schedules other
438 stuff to run after an event is received. A CARD_REMOVAL event
439 also sets some flags to discourage the ide drivers from
440 talking to the ports.
442 ======================================================================*/
444 int ide_event(event_t event, int priority,
445 event_callback_args_t *args)
447 dev_link_t *link = args->client_data;
449 DEBUG(1, "ide_event(0x%06x)\n", event);
452 case CS_EVENT_CARD_REMOVAL:
453 link->state &= ~DEV_PRESENT;
454 if (link->state & DEV_CONFIG)
457 case CS_EVENT_CARD_INSERTION:
458 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
461 case CS_EVENT_PM_SUSPEND:
462 link->state |= DEV_SUSPEND;
463 /* Fall through... */
464 case CS_EVENT_RESET_PHYSICAL:
465 if (link->state & DEV_CONFIG)
466 pcmcia_release_configuration(link->handle);
468 case CS_EVENT_PM_RESUME:
469 link->state &= ~DEV_SUSPEND;
470 /* Fall through... */
471 case CS_EVENT_CARD_RESET:
473 pcmcia_request_configuration(link->handle, &link->conf);
479 static struct pcmcia_driver ide_cs_driver = {
480 .owner = THIS_MODULE,
484 .attach = ide_attach,
485 .detach = ide_detach,
488 static int __init init_ide_cs(void)
490 return pcmcia_register_driver(&ide_cs_driver);
493 static void __exit exit_ide_cs(void)
495 pcmcia_unregister_driver(&ide_cs_driver);
496 while (dev_list != NULL)
497 ide_detach(dev_list);
500 module_init(init_ide_cs);
501 module_exit(exit_ide_cs);