1 /*======================================================================
3 A driver for PCMCIA IDE/ATA disk cards
5 ide_cs.c 1.26 1999/11/16 02:10:49
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 which
23 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/hdreg.h>
44 #include <linux/major.h>
45 #include <linux/ide.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>
58 static int pc_debug = PCMCIA_DEBUG;
59 MODULE_PARM(pc_debug, "i");
60 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61 static char *version =
62 "ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)";
64 #define DEBUG(n, args...)
67 /*====================================================================*/
69 /* Parameters that can be set with 'insmod' */
71 /* Bit map of interrupts to choose from */
72 static u_int irq_mask = 0xdeb8;
73 static int irq_list[4] = { -1 };
75 MODULE_PARM(irq_mask, "i");
76 MODULE_PARM(irq_list, "1-4i");
78 MODULE_LICENSE("GPL");
81 /*====================================================================*/
83 static const char ide_major[] = {
84 IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
86 IDE4_MAJOR, IDE5_MAJOR
90 typedef struct ide_info_t {
95 struct tq_struct rel_task;
98 static void ide_config(dev_link_t *link);
99 static void ide_release(void *arg);
100 static int ide_event(event_t event, int priority,
101 event_callback_args_t *args);
103 static dev_info_t dev_info = "ide-cs";
105 static dev_link_t *ide_attach(void);
106 static void ide_detach(dev_link_t *);
108 static dev_link_t *dev_list = NULL;
110 /*====================================================================*/
112 static void cs_error(client_handle_t handle, int func, int ret)
114 error_info_t err = { func, ret };
115 CardServices(ReportError, handle, &err);
118 /*======================================================================
120 ide_attach() creates an "instance" of the driver, allocating
121 local data structures for one device. The device is registered
124 ======================================================================*/
126 static dev_link_t *ide_attach(void)
130 client_reg_t client_reg;
133 DEBUG(0, "ide_attach()\n");
135 /* Create new ide device */
136 info = kmalloc(sizeof(*info), GFP_KERNEL);
137 if (!info) return NULL;
138 memset(info, 0, sizeof(*info));
139 link = &info->link; link->priv = info;
140 INIT_TQUEUE(&info->rel_task, ide_release, link);
142 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
143 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
144 link->io.IOAddrLines = 3;
145 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
146 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
147 if (irq_list[0] == -1)
148 link->irq.IRQInfo2 = irq_mask;
150 for (i = 0; i < 4; i++)
151 link->irq.IRQInfo2 |= 1 << irq_list[i];
152 link->conf.Attributes = CONF_ENABLE_IRQ;
154 link->conf.IntType = INT_MEMORY_AND_IO;
156 /* Register with Card Services */
157 link->next = dev_list;
159 client_reg.dev_info = &dev_info;
160 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
161 client_reg.EventMask =
162 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
163 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
164 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
165 client_reg.event_handler = &ide_event;
166 client_reg.Version = 0x0210;
167 client_reg.event_callback_args.client_data = link;
168 ret = CardServices(RegisterClient, &link->handle, &client_reg);
169 if (ret != CS_SUCCESS) {
170 cs_error(link->handle, RegisterClient, ret);
178 /*======================================================================
180 This deletes a driver "instance". The device is de-registered
181 with Card Services. If it has been released, all local data
182 structures are freed. Otherwise, the structures will be freed
183 when the device is released.
185 ======================================================================*/
187 static void ide_detach(dev_link_t *link)
190 ide_info_t *info = link->priv;
193 DEBUG(0, "ide_detach(0x%p)\n", link);
195 /* Locate device structure */
196 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
197 if (*linkp == link) break;
201 if (link->state & DEV_CONFIG) {
202 schedule_task(&info->rel_task);
203 flush_scheduled_tasks();
207 ret = CardServices(DeregisterClient, link->handle);
208 if (ret != CS_SUCCESS)
209 cs_error(link->handle, DeregisterClient, ret);
212 /* Unlink, free device structure */
218 /*======================================================================
220 ide_config() is scheduled to run after a CARD_INSERTION event
221 is received, to configure the PCMCIA socket, and to make the
222 ide device available to the system.
224 ======================================================================*/
226 #define CS_CHECK(fn, args...) \
227 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
229 #define CFG_CHECK(fn, args...) \
230 if (CardServices(fn, args) != 0) goto next_entry
232 int idecs_register (int arg1, int arg2, int irq)
235 ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
237 hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */
238 return ide_register_hw(&hw, NULL);
241 void ide_config(dev_link_t *link)
243 client_handle_t handle = link->handle;
244 ide_info_t *info = link->priv;
249 cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
250 cistpl_cftable_entry_t dflt = { 0 };
251 int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base;
253 DEBUG(0, "ide_config(0x%p)\n", link);
255 tuple.TupleData = (cisdata_t *)buf;
256 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
257 tuple.Attributes = 0;
258 tuple.DesiredTuple = CISTPL_CONFIG;
259 CS_CHECK(GetFirstTuple, handle, &tuple);
260 CS_CHECK(GetTupleData, handle, &tuple);
261 CS_CHECK(ParseTuple, handle, &tuple, &parse);
262 link->conf.ConfigBase = parse.config.base;
263 link->conf.Present = parse.config.rmask[0];
266 link->state |= DEV_CONFIG;
268 /* Not sure if this is right... look up the current Vcc */
269 CS_CHECK(GetConfigurationInfo, handle, &conf);
270 link->conf.Vcc = conf.Vcc;
272 pass = io_base = ctl_base = 0;
273 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
274 tuple.Attributes = 0;
275 CS_CHECK(GetFirstTuple, handle, &tuple);
277 CFG_CHECK(GetTupleData, handle, &tuple);
278 CFG_CHECK(ParseTuple, handle, &tuple, &parse);
280 /* Check for matching Vcc, unless we're desperate */
282 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
283 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
285 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
286 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
291 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
292 link->conf.Vpp1 = link->conf.Vpp2 =
293 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
294 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
295 link->conf.Vpp1 = link->conf.Vpp2 =
296 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
298 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
299 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
300 link->conf.ConfigIndex = cfg->index;
301 link->io.BasePort1 = io->win[0].base;
302 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
303 if (!(io->flags & CISTPL_IO_16BIT))
304 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
306 link->io.NumPorts1 = 8;
307 link->io.BasePort2 = io->win[1].base;
308 link->io.NumPorts2 = 1;
309 CFG_CHECK(RequestIO, link->handle, &link->io);
310 io_base = link->io.BasePort1;
311 ctl_base = link->io.BasePort2;
312 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
313 link->io.NumPorts1 = io->win[0].len;
314 link->io.NumPorts2 = 0;
315 CFG_CHECK(RequestIO, link->handle, &link->io);
316 io_base = link->io.BasePort1;
317 ctl_base = link->io.BasePort1+0x0e;
318 } else goto next_entry;
319 /* If we've got this far, we're done */
324 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
326 CS_CHECK(GetNextTuple, handle, &tuple);
327 } else if (CardServices(GetNextTuple, handle, &tuple) != 0) {
328 CS_CHECK(GetFirstTuple, handle, &tuple);
329 memset(&dflt, 0, sizeof(dflt));
334 CS_CHECK(RequestIRQ, handle, &link->irq);
335 CS_CHECK(RequestConfiguration, handle, &link->conf);
337 /* deal with brain dead IDE resource management */
338 release_region(link->io.BasePort1, link->io.NumPorts1);
339 if (link->io.NumPorts2)
340 release_region(link->io.BasePort2, link->io.NumPorts2);
342 outb(0x02, ctl_base); // Set nIEN = disable device interrupts
344 /* retry registration in case device is still spinning up */
345 for (i = 0; i < 10; i++) {
347 outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */
348 hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
350 if (link->io.NumPorts1 == 0x20) {
352 outb(0x02, ctl_base+0x10);
353 hd = idecs_register(io_base+0x10, ctl_base+0x10,
354 link->irq.AssignedIRQ);
356 io_base += 0x10; ctl_base += 0x10;
360 __set_current_state(TASK_UNINTERRUPTIBLE);
361 schedule_timeout(HZ/10);
365 printk(KERN_NOTICE "ide_cs: ide_register() at 0x%03x & 0x%03x"
366 ", irq %u failed\n", io_base, ctl_base,
367 link->irq.AssignedIRQ);
373 sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2));
374 info->node.major = ide_major[hd];
375 info->node.minor = 0;
377 link->dev = &info->node;
378 printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
379 info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10,
380 link->conf.Vpp1/10, link->conf.Vpp1%10);
382 link->state &= ~DEV_CONFIG_PENDING;
386 cs_error(link->handle, last_fn, last_ret);
392 /*======================================================================
394 After a card is removed, ide_release() will unregister the net
395 device, and release the PCMCIA configuration. If the device is
396 still open, this will be postponed until it is closed.
398 ======================================================================*/
400 static void ide_release(void *arg)
402 dev_link_t *link = arg;
403 ide_info_t *info = link->priv;
405 if (!(link->state & DEV_CONFIG))
408 DEBUG(0, "ide_do_release(0x%p)\n", link);
411 /* FIXME: if this fails we need to queue the cleanup somehow
412 -- need to investigate the required PCMCIA magic */
413 ide_unregister(info->hd);
417 request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs");
418 if (link->io.NumPorts2)
419 request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs");
424 CardServices(ReleaseConfiguration, link->handle);
425 CardServices(ReleaseIO, link->handle, &link->io);
426 CardServices(ReleaseIRQ, link->handle, &link->irq);
428 link->state &= ~DEV_CONFIG;
432 /*======================================================================
434 The card status event handler. Mostly, this schedules other
435 stuff to run after an event is received. A CARD_REMOVAL event
436 also sets some flags to discourage the ide drivers from
437 talking to the ports.
439 ======================================================================*/
441 int ide_event(event_t event, int priority,
442 event_callback_args_t *args)
444 dev_link_t *link = args->client_data;
445 ide_info_t *info = link->priv;
447 DEBUG(1, "ide_event(0x%06x)\n", event);
450 case CS_EVENT_CARD_REMOVAL:
451 link->state &= ~DEV_PRESENT;
452 if (link->state & DEV_CONFIG)
453 schedule_task(&info->rel_task);
455 case CS_EVENT_CARD_INSERTION:
456 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
459 case CS_EVENT_PM_SUSPEND:
460 link->state |= DEV_SUSPEND;
461 /* Fall through... */
462 case CS_EVENT_RESET_PHYSICAL:
463 if (link->state & DEV_CONFIG)
464 CardServices(ReleaseConfiguration, link->handle);
466 case CS_EVENT_PM_RESUME:
467 link->state &= ~DEV_SUSPEND;
468 /* Fall through... */
469 case CS_EVENT_CARD_RESET:
471 CardServices(RequestConfiguration, link->handle, &link->conf);
477 /*====================================================================*/
479 static int __init init_ide_cs(void)
482 DEBUG(0, "%s\n", version);
483 CardServices(GetCardServicesInfo, &serv);
484 if (serv.Revision != CS_RELEASE_CODE) {
485 printk(KERN_NOTICE "ide_cs: Card Services release "
486 "does not match!\n");
489 register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
493 static void __exit exit_ide_cs(void)
495 DEBUG(0, "ide_cs: unloading\n");
496 unregister_pccard_driver(&dev_info);
497 while (dev_list != NULL)
498 ide_detach(dev_list);
501 module_init(init_ide_cs);
502 module_exit(exit_ide_cs);