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>
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>
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)";
63 #define DEBUG(n, args...)
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
,
82 IDE4_MAJOR
, IDE5_MAJOR
86 typedef struct 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
119 ======================================================================*/
121 static dev_link_t
*ide_attach(void)
125 client_reg_t client_reg
;
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
;
146 for (i
= 0; i
< 4; i
++)
147 link
->irq
.IRQInfo2
|= 1 << irq_list
[i
];
148 link
->conf
.Attributes
= CONF_ENABLE_IRQ
;
150 link
->conf
.IntType
= INT_MEMORY_AND_IO
;
152 /* Register with Card Services */
153 link
->next
= dev_list
;
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
);
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
)
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;
196 del_timer(&link
->release
);
197 if (link
->state
& DEV_CONFIG
)
198 ide_release((u_long
)link
);
201 ret
= CardServices(DeregisterClient
, link
->handle
);
202 if (ret
!= CS_SUCCESS
)
203 cs_error(link
->handle
, DeregisterClient
, ret
);
206 /* Unlink, free device structure */
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
;
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];
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
);
262 CFG_CHECK(GetTupleData
, handle
, &tuple
);
263 CFG_CHECK(ParseTuple
, handle
, &tuple
, &parse
);
265 /* Check for matching Vcc, unless we're desperate */
267 if (cfg
->vcc
.present
& (1<<CISTPL_POWER_VNOM
)) {
268 if (conf
.Vcc
!= cfg
->vcc
.param
[CISTPL_POWER_VNOM
]/10000)
270 } else if (dflt
.vcc
.present
& (1<<CISTPL_POWER_VNOM
)) {
271 if (conf
.Vcc
!= dflt
.vcc
.param
[CISTPL_POWER_VNOM
]/10000)
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
;
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 */
309 if (cfg
->flags
& CISTPL_CFTABLE_DEFAULT
) dflt
= *cfg
;
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
));
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
);
331 if (link
->io
.NumPorts1
== 0x20) {
332 hd
= ide_register(io_base
+0x10, ctl_base
+0x10,
333 link
->irq
.AssignedIRQ
);
335 io_base
+= 0x10; ctl_base
+= 0x10;
339 __set_current_state(TASK_UNINTERRUPTIBLE
);
340 schedule_timeout(HZ
/10);
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
);
352 sprintf(info
->node
.dev_name
, "hd%c", 'a'+(hd
*2));
353 info
->node
.major
= ide_major
[hd
];
354 info
->node
.minor
= 0;
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
;
365 cs_error(link
->handle
, last_fn
, last_ret
);
367 ide_release((u_long
)link
);
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
);
387 ide_unregister(info
->hd
);
393 CardServices(ReleaseConfiguration
, link
->handle
);
394 CardServices(ReleaseIO
, link
->handle
, &link
->io
);
395 CardServices(ReleaseIRQ
, link
->handle
, &link
->irq
);
397 link
->state
&= ~DEV_CONFIG
;
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
);
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);
423 case CS_EVENT_CARD_INSERTION
:
424 link
->state
|= DEV_PRESENT
| DEV_CONFIG_PENDING
;
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
);
434 case CS_EVENT_PM_RESUME
:
435 link
->state
&= ~DEV_SUSPEND
;
436 /* Fall through... */
437 case CS_EVENT_CARD_RESET
:
439 CardServices(RequestConfiguration
, link
->handle
, &link
->conf
);
445 /*====================================================================*/
447 static int __init
init_ide_cs(void)
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");
457 register_pccard_driver(&dev_info
, &ide_attach
, &ide_detach
);
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
);