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 /* retry registration in case device is still spinning up */
343 for (i = 0; i < 10; i++) {
345 outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */
346 hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
348 if (link->io.NumPorts1 == 0x20) {
350 outb(0x02, ctl_base+0x10);
351 hd = idecs_register(io_base+0x10, ctl_base+0x10,
352 link->irq.AssignedIRQ);
354 io_base += 0x10; ctl_base += 0x10;
358 __set_current_state(TASK_UNINTERRUPTIBLE);
359 schedule_timeout(HZ/10);
363 printk(KERN_NOTICE "ide_cs: ide_register() at 0x%03x & 0x%03x"
364 ", irq %u failed\n", io_base, ctl_base,
365 link->irq.AssignedIRQ);
371 sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2));
372 info->node.major = ide_major[hd];
373 info->node.minor = 0;
375 link->dev = &info->node;
376 printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
377 info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10,
378 link->conf.Vpp1/10, link->conf.Vpp1%10);
380 link->state &= ~DEV_CONFIG_PENDING;
384 cs_error(link->handle, last_fn, last_ret);
390 /*======================================================================
392 After a card is removed, ide_release() will unregister the net
393 device, and release the PCMCIA configuration. If the device is
394 still open, this will be postponed until it is closed.
396 ======================================================================*/
398 static void ide_release(void *arg)
400 dev_link_t *link = arg;
401 ide_info_t *info = link->priv;
403 if (!(link->state & DEV_CONFIG))
406 DEBUG(0, "ide_do_release(0x%p)\n", link);
409 /* FIXME: if this fails we need to queue the cleanup somehow
410 -- need to investigate the required PCMCIA magic */
411 ide_unregister(info->hd);
415 request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs");
416 if (link->io.NumPorts2)
417 request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs");
422 CardServices(ReleaseConfiguration, link->handle);
423 CardServices(ReleaseIO, link->handle, &link->io);
424 CardServices(ReleaseIRQ, link->handle, &link->irq);
426 link->state &= ~DEV_CONFIG;
430 /*======================================================================
432 The card status event handler. Mostly, this schedules other
433 stuff to run after an event is received. A CARD_REMOVAL event
434 also sets some flags to discourage the ide drivers from
435 talking to the ports.
437 ======================================================================*/
439 int ide_event(event_t event, int priority,
440 event_callback_args_t *args)
442 dev_link_t *link = args->client_data;
443 ide_info_t *info = link->priv;
445 DEBUG(1, "ide_event(0x%06x)\n", event);
448 case CS_EVENT_CARD_REMOVAL:
449 link->state &= ~DEV_PRESENT;
450 if (link->state & DEV_CONFIG)
451 schedule_task(&info->rel_task);
453 case CS_EVENT_CARD_INSERTION:
454 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
457 case CS_EVENT_PM_SUSPEND:
458 link->state |= DEV_SUSPEND;
459 /* Fall through... */
460 case CS_EVENT_RESET_PHYSICAL:
461 if (link->state & DEV_CONFIG)
462 CardServices(ReleaseConfiguration, link->handle);
464 case CS_EVENT_PM_RESUME:
465 link->state &= ~DEV_SUSPEND;
466 /* Fall through... */
467 case CS_EVENT_CARD_RESET:
469 CardServices(RequestConfiguration, link->handle, &link->conf);
475 /*====================================================================*/
477 static int __init init_ide_cs(void)
480 DEBUG(0, "%s\n", version);
481 CardServices(GetCardServicesInfo, &serv);
482 if (serv.Revision != CS_RELEASE_CODE) {
483 printk(KERN_NOTICE "ide_cs: Card Services release "
484 "does not match!\n");
487 register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
491 static void __exit exit_ide_cs(void)
493 DEBUG(0, "ide_cs: unloading\n");
494 unregister_pccard_driver(&dev_info);
495 while (dev_list != NULL)
496 ide_detach(dev_list);
499 module_init(init_ide_cs);
500 module_exit(exit_ide_cs);