Make HZ_TO_STD macro name lowercase.
[linux-2.6/linux-mips.git] / drivers / ide / ide-cs.c
bloba7619eb8d941242565e9d02fe64dc452428b08bc
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 <dhinds@pcmcia.sourceforge.org>. 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 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/malloc.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>
46 #include <asm/io.h>
47 #include <asm/system.h>
49 #include <pcmcia/version.h>
50 #include <pcmcia/cs_types.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/cistpl.h>
53 #include <pcmcia/ds.h>
54 #include <pcmcia/cisreg.h>
56 #ifdef PCMCIA_DEBUG
57 static int pc_debug = PCMCIA_DEBUG;
58 MODULE_PARM(pc_debug, "i");
59 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
60 static char *version =
61 "ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)";
62 #else
63 #define DEBUG(n, args...)
64 #endif
66 /*====================================================================*/
68 /* Parameters that can be set with 'insmod' */
70 /* Bit map of interrupts to choose from */
71 static u_int irq_mask = 0xdeb8;
72 static int irq_list[4] = { -1 };
74 MODULE_PARM(irq_mask, "i");
75 MODULE_PARM(irq_list, "1-4i");
77 /*====================================================================*/
79 static const char ide_major[] = {
80 IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
81 #ifdef IDE4_MAJOR
82 IDE4_MAJOR, IDE5_MAJOR
83 #endif
86 typedef struct ide_info_t {
87 dev_link_t link;
88 int ndev;
89 dev_node_t node;
90 int hd;
91 } ide_info_t;
93 static void ide_config(dev_link_t *link);
94 static void ide_release(u_long arg);
95 static int ide_event(event_t event, int priority,
96 event_callback_args_t *args);
98 static dev_info_t dev_info = "ide_cs";
100 static dev_link_t *ide_attach(void);
101 static void ide_detach(dev_link_t *);
103 static dev_link_t *dev_list = NULL;
105 /*====================================================================*/
107 static void cs_error(client_handle_t handle, int func, int ret)
109 error_info_t err = { func, ret };
110 CardServices(ReportError, handle, &err);
113 /*======================================================================
115 ide_attach() creates an "instance" of the driver, allocating
116 local data structures for one device. The device is registered
117 with Card Services.
119 ======================================================================*/
121 static dev_link_t *ide_attach(void)
123 ide_info_t *info;
124 dev_link_t *link;
125 client_reg_t client_reg;
126 int i, ret;
128 DEBUG(0, "ide_attach()\n");
130 /* Create new ide device */
131 info = kmalloc(sizeof(*info), GFP_KERNEL);
132 if (!info) return NULL;
133 memset(info, 0, sizeof(*info));
134 link = &info->link; link->priv = info;
136 link->release.function = &ide_release;
137 link->release.data = (u_long)link;
138 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
139 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
140 link->io.IOAddrLines = 3;
141 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
142 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
143 if (irq_list[0] == -1)
144 link->irq.IRQInfo2 = irq_mask;
145 else
146 for (i = 0; i < 4; i++)
147 link->irq.IRQInfo2 |= 1 << irq_list[i];
148 link->conf.Attributes = CONF_ENABLE_IRQ;
149 link->conf.Vcc = 50;
150 link->conf.IntType = INT_MEMORY_AND_IO;
152 /* Register with Card Services */
153 link->next = dev_list;
154 dev_list = link;
155 client_reg.dev_info = &dev_info;
156 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
157 client_reg.EventMask =
158 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
159 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
160 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
161 client_reg.event_handler = &ide_event;
162 client_reg.Version = 0x0210;
163 client_reg.event_callback_args.client_data = link;
164 ret = CardServices(RegisterClient, &link->handle, &client_reg);
165 if (ret != CS_SUCCESS) {
166 cs_error(link->handle, RegisterClient, ret);
167 ide_detach(link);
168 return NULL;
171 return link;
172 } /* ide_attach */
174 /*======================================================================
176 This deletes a driver "instance". The device is de-registered
177 with Card Services. If it has been released, all local data
178 structures are freed. Otherwise, the structures will be freed
179 when the device is released.
181 ======================================================================*/
183 static void ide_detach(dev_link_t *link)
185 dev_link_t **linkp;
186 int ret;
188 DEBUG(0, "ide_detach(0x%p)\n", link);
190 /* Locate device structure */
191 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
192 if (*linkp == link) break;
193 if (*linkp == NULL)
194 return;
196 del_timer(&link->release);
197 if (link->state & DEV_CONFIG)
198 ide_release((u_long)link);
200 if (link->handle) {
201 ret = CardServices(DeregisterClient, link->handle);
202 if (ret != CS_SUCCESS)
203 cs_error(link->handle, DeregisterClient, ret);
206 /* Unlink, free device structure */
207 *linkp = link->next;
208 kfree(link->priv);
210 } /* ide_detach */
212 /*======================================================================
214 ide_config() is scheduled to run after a CARD_INSERTION event
215 is received, to configure the PCMCIA socket, and to make the
216 ide device available to the system.
218 ======================================================================*/
220 #define CS_CHECK(fn, args...) \
221 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
223 #define CFG_CHECK(fn, args...) \
224 if (CardServices(fn, args) != 0) goto next_entry
226 void ide_config(dev_link_t *link)
228 client_handle_t handle = link->handle;
229 ide_info_t *info = link->priv;
230 tuple_t tuple;
231 u_short buf[128];
232 cisparse_t parse;
233 config_info_t conf;
234 cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
235 cistpl_cftable_entry_t dflt = { 0 };
236 int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base;
238 DEBUG(0, "ide_config(0x%p)\n", link);
240 tuple.TupleData = (cisdata_t *)buf;
241 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
242 tuple.Attributes = 0;
243 tuple.DesiredTuple = CISTPL_CONFIG;
244 CS_CHECK(GetFirstTuple, handle, &tuple);
245 CS_CHECK(GetTupleData, handle, &tuple);
246 CS_CHECK(ParseTuple, handle, &tuple, &parse);
247 link->conf.ConfigBase = parse.config.base;
248 link->conf.Present = parse.config.rmask[0];
250 /* Configure card */
251 link->state |= DEV_CONFIG;
253 /* Not sure if this is right... look up the current Vcc */
254 CS_CHECK(GetConfigurationInfo, handle, &conf);
255 link->conf.Vcc = conf.Vcc;
257 pass = io_base = ctl_base = 0;
258 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
259 tuple.Attributes = 0;
260 CS_CHECK(GetFirstTuple, handle, &tuple);
261 while (1) {
262 CFG_CHECK(GetTupleData, handle, &tuple);
263 CFG_CHECK(ParseTuple, handle, &tuple, &parse);
265 /* Check for matching Vcc, unless we're desperate */
266 if (!pass) {
267 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
268 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
269 goto next_entry;
270 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
271 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
272 goto next_entry;
276 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
277 link->conf.Vpp1 = link->conf.Vpp2 =
278 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
279 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
280 link->conf.Vpp1 = link->conf.Vpp2 =
281 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
283 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
284 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
285 link->conf.ConfigIndex = cfg->index;
286 link->io.BasePort1 = io->win[0].base;
287 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
288 if (!(io->flags & CISTPL_IO_16BIT))
289 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
290 if (io->nwin == 2) {
291 link->io.NumPorts1 = 8;
292 link->io.BasePort2 = io->win[1].base;
293 link->io.NumPorts2 = 1;
294 CFG_CHECK(RequestIO, link->handle, &link->io);
295 io_base = link->io.BasePort1;
296 ctl_base = link->io.BasePort2;
297 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
298 link->io.NumPorts1 = io->win[0].len;
299 link->io.NumPorts2 = 0;
300 CFG_CHECK(RequestIO, link->handle, &link->io);
301 io_base = link->io.BasePort1;
302 ctl_base = link->io.BasePort1+0x0e;
303 } else goto next_entry;
304 /* If we've got this far, we're done */
305 break;
308 next_entry:
309 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
310 if (pass) {
311 CS_CHECK(GetNextTuple, handle, &tuple);
312 } else if (CardServices(GetNextTuple, handle, &tuple) != 0) {
313 CS_CHECK(GetFirstTuple, handle, &tuple);
314 memset(&dflt, 0, sizeof(dflt));
315 pass++;
319 CS_CHECK(RequestIRQ, handle, &link->irq);
320 CS_CHECK(RequestConfiguration, handle, &link->conf);
322 /* deal with brain dead IDE resource management */
323 release_region(link->io.BasePort1, link->io.NumPorts1);
324 if (link->io.NumPorts2)
325 release_region(link->io.BasePort2, link->io.NumPorts2);
327 /* retry registration in case device is still spinning up */
328 for (i = 0; i < 10; i++) {
329 hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ);
330 if (hd >= 0) break;
331 if (link->io.NumPorts1 == 0x20) {
332 hd = ide_register(io_base+0x10, ctl_base+0x10,
333 link->irq.AssignedIRQ);
334 if (hd >= 0) {
335 io_base += 0x10; ctl_base += 0x10;
336 break;
339 __set_current_state(TASK_UNINTERRUPTIBLE);
340 schedule_timeout(HZ/10);
343 if (hd < 0) {
344 printk(KERN_NOTICE "ide_cs: ide_register() at 0x%3x & 0x%3x"
345 ", irq %u failed\n", io_base, ctl_base,
346 link->irq.AssignedIRQ);
347 goto failed;
350 MOD_INC_USE_COUNT;
351 info->ndev = 1;
352 sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2));
353 info->node.major = ide_major[hd];
354 info->node.minor = 0;
355 info->hd = hd;
356 link->dev = &info->node;
357 printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
358 info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10,
359 link->conf.Vpp1/10, link->conf.Vpp1%10);
361 link->state &= ~DEV_CONFIG_PENDING;
362 return;
364 cs_failed:
365 cs_error(link->handle, last_fn, last_ret);
366 failed:
367 ide_release((u_long)link);
369 } /* ide_config */
371 /*======================================================================
373 After a card is removed, ide_release() will unregister the net
374 device, and release the PCMCIA configuration. If the device is
375 still open, this will be postponed until it is closed.
377 ======================================================================*/
379 void ide_release(u_long arg)
381 dev_link_t *link = (dev_link_t *)arg;
382 ide_info_t *info = link->priv;
384 DEBUG(0, "ide_release(0x%p)\n", link);
386 if (info->ndev) {
387 ide_unregister(info->hd);
388 MOD_DEC_USE_COUNT;
390 info->ndev = 0;
391 link->dev = NULL;
393 CardServices(ReleaseConfiguration, link->handle);
394 CardServices(ReleaseIO, link->handle, &link->io);
395 CardServices(ReleaseIRQ, link->handle, &link->irq);
397 link->state &= ~DEV_CONFIG;
399 } /* ide_release */
401 /*======================================================================
403 The card status event handler. Mostly, this schedules other
404 stuff to run after an event is received. A CARD_REMOVAL event
405 also sets some flags to discourage the ide drivers from
406 talking to the ports.
408 ======================================================================*/
410 int ide_event(event_t event, int priority,
411 event_callback_args_t *args)
413 dev_link_t *link = args->client_data;
415 DEBUG(1, "ide_event(0x%06x)\n", event);
417 switch (event) {
418 case CS_EVENT_CARD_REMOVAL:
419 link->state &= ~DEV_PRESENT;
420 if (link->state & DEV_CONFIG)
421 mod_timer(&link->release, jiffies + HZ/20);
422 break;
423 case CS_EVENT_CARD_INSERTION:
424 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
425 ide_config(link);
426 break;
427 case CS_EVENT_PM_SUSPEND:
428 link->state |= DEV_SUSPEND;
429 /* Fall through... */
430 case CS_EVENT_RESET_PHYSICAL:
431 if (link->state & DEV_CONFIG)
432 CardServices(ReleaseConfiguration, link->handle);
433 break;
434 case CS_EVENT_PM_RESUME:
435 link->state &= ~DEV_SUSPEND;
436 /* Fall through... */
437 case CS_EVENT_CARD_RESET:
438 if (DEV_OK(link))
439 CardServices(RequestConfiguration, link->handle, &link->conf);
440 break;
442 return 0;
443 } /* ide_event */
445 /*====================================================================*/
447 static int __init init_ide_cs(void)
449 servinfo_t serv;
450 DEBUG(0, "%s\n", version);
451 CardServices(GetCardServicesInfo, &serv);
452 if (serv.Revision != CS_RELEASE_CODE) {
453 printk(KERN_NOTICE "ide_cs: Card Services release "
454 "does not match!\n");
455 return -1;
457 register_pccard_driver(&dev_info, &ide_attach, &ide_detach);
458 return 0;
461 static void __exit exit_ide_cs(void)
463 DEBUG(0, "ide_cs: unloading\n");
464 unregister_pccard_driver(&dev_info);
465 while (dev_list != NULL)
466 ide_detach(dev_list);
469 module_init(init_ide_cs);
470 module_exit(exit_ide_cs);