2 * Aironet 4500 Pcmcia driver
4 * Elmer Joandi, Januar 1999
5 * Copyright Elmer Joandi, all rights restricted
8 * Revision 0.1 ,started 30.12.1998
13 static const char *awc_version
=
14 "aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
17 #include <linux/module.h>
18 //#include <pcmcia/config.h>
20 #include <linux/kernel.h>
21 #include <linux/sched.h>
22 #include <linux/ptrace.h>
23 #include <linux/malloc.h>
24 #include <linux/string.h>
25 #include <linux/timer.h>
26 #include <linux/interrupt.h>
29 #include <asm/system.h>
30 #include <asm/bitops.h>
32 #include <linux/netdevice.h>
33 #include <linux/etherdevice.h>
34 #include <linux/skbuff.h>
35 #include <linux/if_arp.h>
36 #include <linux/ioport.h>
39 #include <pcmcia/version.h>
40 #include <pcmcia/cs_types.h>
41 #include <pcmcia/cs.h>
42 #include <pcmcia/cistpl.h>
43 #include <pcmcia/cisreg.h>
44 #include <pcmcia/ciscode.h>
45 #if LINUX_VERSION_CODE < 0x20300
47 #include <pcmcia/k_compat.h>
50 #include <pcmcia/ds.h>
52 #include "../aironet4500.h"
55 static u_int irq_mask
= 0x5eF8;
56 static int awc_ports
[] = {0x140,0x100,0xc0, 0x80 };
57 #if LINUX_VERSION_CODE > 0x20100
58 MODULE_PARM(irq_mask
, "i");
63 #define RUN_AT(x) (jiffies+(x))
66 static int pc_debug
= PCMCIA_DEBUG
;
67 MODULE_PARM(pc_debug
, "i");
68 #define PC_DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
69 static char *version
=
70 "aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
72 #define PC_DEBUG(n, args...)
75 /* Index of functions. */
77 static dev_info_t dev_info
= "aironet4500_cs";
79 static dev_link_t
*awc_attach(void);
80 static void awc_detach(dev_link_t
*);
81 static void awc_release(u_long arg
);
82 static int awc_event(event_t event
, int priority
,
83 event_callback_args_t
*args
);
85 static dev_link_t
*dev_list
= NULL
;
87 static void cs_error(client_handle_t handle
, int func
, int ret
)
89 #if CS_RELEASE_CODE < 0x2911
90 CardServices(ReportError
, dev_info
, (void *)func
, (void *)ret
);
92 error_info_t err
= { func
, ret
};
93 CardServices(ReportError
, handle
, &err
);
97 #define CFG_CHECK(fn, args...) if (CardServices(fn, args) != 0) goto next_entry
99 static void flush_stale_links(void)
101 dev_link_t
*link
, *next
;
102 for (link
= dev_list
; link
; link
= next
) {
104 if (link
->state
& DEV_STALE_LINK
)
111 We never need to do anything when a awc device is "initialized"
112 by the net software, because we only register already-found cards.
115 static int awc_pcmcia_init(struct net_device
*dev
)
117 return awc_init(dev
);
121 static int awc_pcmcia_open(struct net_device
*dev
)
126 for (link
= dev_list
; link
; link
= link
->next
)
127 if (link
->priv
== dev
) break;
131 status
= awc_open(dev
);
139 static int awc_pcmcia_close(struct net_device
*dev
)
141 // int ioaddr = dev->base_addr;
145 for (link
= dev_list
; link
; link
= link
->next
)
146 if (link
->priv
== dev
) break;
150 PC_DEBUG(2, "%s: closing device.\n", dev
->name
);
153 ret
= awc_close(dev
);
155 if (link
->state
& DEV_STALE_CONFIG
) {
156 link
->release
.expires
= RUN_AT( HZ
/20 );
157 link
->state
|= DEV_RELEASE_PENDING
;
158 add_timer(&link
->release
);
164 awc_attach() creates an "instance" of the driver, allocating
165 local data structures for one device. The device is registered
169 static dev_link_t
*awc_attach(void)
171 client_reg_t client_reg
;
172 dev_link_t
*link
= NULL
;
173 struct net_device
*dev
= NULL
;
176 PC_DEBUG(0, "awc_attach()\n");
179 /* Create the PC card device object. */
180 link
= kmalloc(sizeof(struct dev_link_t
), GFP_KERNEL
);
181 memset(link
, 0, sizeof(struct dev_link_t
));
182 link
->dev
= kmalloc(sizeof(struct dev_node_t
), GFP_KERNEL
);
183 memset(link
->dev
, 0, sizeof(struct dev_node_t
));
185 link
->release
.function
= &awc_release
;
186 link
->release
.data
= (u_long
)link
;
187 // link->io.NumPorts1 = 32;
188 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_16
;
189 // link->io.IOAddrLines = 5;
190 link
->irq
.Attributes
= IRQ_HANDLE_PRESENT
; // |IRQ_TYPE_EXCLUSIVE ;
191 link
->irq
.IRQInfo1
= IRQ_INFO2_VALID
|IRQ_LEVEL_ID
;
192 link
->irq
.IRQInfo2
= irq_mask
;
193 link
->irq
.Handler
= &awc_interrupt
;
194 link
->conf
.Attributes
= CONF_ENABLE_IRQ
;
196 link
->conf
.IntType
= INT_MEMORY_AND_IO
;
197 link
->conf
.ConfigIndex
= 1;
198 link
->conf
.Present
= PRESENT_OPTION
;
200 /* Create the network device object. */
202 dev
= kmalloc(sizeof(struct net_device
), GFP_KERNEL
);
203 memset(dev
,0,sizeof(struct net_device
));
204 // dev = init_etherdev(0, sizeof(struct awc_private) );
206 printk(KERN_CRIT
"out of mem on dev alloc \n");
211 dev
->priv
= kmalloc(sizeof(struct awc_private
), GFP_KERNEL
);
212 if (!dev
->priv
) {printk(KERN_CRIT
"out of mem on dev priv alloc \n"); return NULL
;};
213 memset(dev
->priv
,0,sizeof(struct awc_private
));
215 // link->dev->minor = dev->minor;
216 // link->dev->major = dev->major;
218 /* The 4500-specific entries in the device structure. */
220 // dev->tx_queue_len = tx_queue_len;
222 dev
->hard_start_xmit
= &awc_start_xmit
;
223 // dev->set_config = &awc_config_misiganes,aga mitte awc_config;
224 dev
->get_stats
= &awc_get_stats
;
225 // dev->set_multicast_list = &awc_set_multicast_list;
229 dev
->name
= ((struct awc_private
*)dev
->priv
)->node
.dev_name
;
231 dev
->init
= &awc_pcmcia_init
;
232 dev
->open
= &awc_pcmcia_open
;
233 dev
->stop
= &awc_pcmcia_close
;
234 netif_start_queue (dev
);
237 #if CS_RELEASE_CODE > 0x2911
238 link
->irq
.Instance
= dev
;
241 /* Register with Card Services */
242 link
->next
= dev_list
;
246 client_reg
.dev_info
= &dev_info
;
247 client_reg
.Attributes
= INFO_IO_CLIENT
| INFO_CARD_SHARE
;
248 client_reg
.EventMask
=
249 CS_EVENT_CARD_INSERTION
| CS_EVENT_CARD_REMOVAL
|
250 CS_EVENT_RESET_PHYSICAL
| CS_EVENT_CARD_RESET
|
251 CS_EVENT_PM_SUSPEND
| CS_EVENT_PM_RESUME
;
252 client_reg
.event_handler
= &awc_event
;
253 client_reg
.Version
= 0x0210;
254 client_reg
.event_callback_args
.client_data
= link
;
255 ret
= CardServices(RegisterClient
, &link
->handle
, &client_reg
);
257 cs_error(link
->handle
, RegisterClient
, ret
);
267 This deletes a driver "instance". The device is de-registered
268 with Card Services. If it has been released, all local data
269 structures are freed. Otherwise, the structures will be freed
270 when the device is released.
274 static void awc_detach(dev_link_t
*link
)
280 DEBUG(0, "awc_detach(0x%p)\n", link
);
282 /* Locate device structure */
283 for (linkp
= &dev_list
; *linkp
; linkp
= &(*linkp
)->next
)
284 if (*linkp
== link
) break;
290 if (link
->state
& DEV_RELEASE_PENDING
) {
291 del_timer(&link
->release
);
292 link
->state
&= ~DEV_RELEASE_PENDING
;
294 restore_flags(flags
);
296 if (link
->state
& DEV_CONFIG
) {
297 awc_release((u_long
)link
);
298 if (link
->state
& DEV_STALE_CONFIG
) {
299 link
->state
|= DEV_STALE_LINK
;
305 CardServices(DeregisterClient
, link
->handle
);
307 /* Unlink device structure, free bits */
311 while ( i
< MAX_AWCS
) {
312 if (!aironet4500_devices
[i
])
314 if (aironet4500_devices
[i
] == link
->priv
){
315 if (awc_proc_unset_fun
)
316 awc_proc_unset_fun(i
);
318 aironet4500_devices
[i
]=0;
324 //struct net_device *dev = link->priv;
325 // dam dam damn mif (dev->priv)
326 // kfree_s(dev->priv, sizeof(struct awc_private));
327 kfree_s(link
->priv
, sizeof(struct net_device
));
329 kfree_s(link
->dev
, sizeof(struct dev_node_t
));
330 kfree_s(link
, sizeof(struct dev_link_t
));
336 awc_pcmcia_config() is scheduled to run after a CARD_INSERTION event
337 is received, to configure the PCMCIA socket, and to make the
338 ethernet device available to the system.
342 #define CS_CHECK(fn, args...) \
343 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
345 static void awc_pcmcia_config(dev_link_t
*link
)
347 client_handle_t handle
;
348 struct net_device
*dev
;
349 struct awc_private
*lp
;
354 int last_fn
, last_ret
, i
= 0;
359 handle
= link
->handle
;
361 phys_addr
= (u16
*)dev
->dev_addr
;
363 PC_DEBUG(0, "awc_pcmcia_config(0x%p)\n", link
);
365 tuple
.Attributes
= 0;
366 tuple
.DesiredTuple
= CISTPL_CONFIG
;
367 CS_CHECK(GetFirstTuple
, handle
, &tuple
);
368 tuple
.TupleData
= (cisdata_t
*)buf
;
369 tuple
.TupleDataMax
= 64;
370 tuple
.TupleOffset
= 0;
371 CS_CHECK(GetTupleData
, handle
, &tuple
);
372 CS_CHECK(ParseTuple
, handle
, &tuple
, &parse
);
373 link
->conf
.ConfigBase
= parse
.config
.base
;
374 link
->conf
.Present
= parse
.config
.rmask
[0];
378 link
->state
|= DEV_CONFIG
;
380 tuple
.DesiredTuple
= CISTPL_CFTABLE_ENTRY
;
381 CS_CHECK(GetFirstTuple
, handle
, &tuple
);
384 cistpl_cftable_entry_t dflt
= { 0 };
385 cistpl_cftable_entry_t
*cfg
= &(parse
.cftable_entry
);
386 CFG_CHECK(GetTupleData
, handle
, &tuple
);
387 CFG_CHECK(ParseTuple
, handle
, &tuple
, &parse
);
389 if (cfg
->flags
& CISTPL_CFTABLE_DEFAULT
) dflt
= *cfg
;
390 if (cfg
->index
== 0) goto next_entry
;
391 link
->conf
.ConfigIndex
= cfg
->index
;
393 /* Use power settings for Vcc and Vpp if present */
394 /* Note that the CIS values need to be rescaled */
395 if (cfg
->vcc
.present
& (1<<CISTPL_POWER_VNOM
))
396 link
->conf
.Vcc
= cfg
->vcc
.param
[CISTPL_POWER_VNOM
]/10000;
397 else if (dflt
.vcc
.present
& (1<<CISTPL_POWER_VNOM
))
398 link
->conf
.Vcc
= dflt
.vcc
.param
[CISTPL_POWER_VNOM
]/10000;
400 if (cfg
->vpp1
.present
& (1<<CISTPL_POWER_VNOM
))
401 link
->conf
.Vpp1
= link
->conf
.Vpp2
=
402 cfg
->vpp1
.param
[CISTPL_POWER_VNOM
]/10000;
403 else if (dflt
.vpp1
.present
& (1<<CISTPL_POWER_VNOM
))
404 link
->conf
.Vpp1
= link
->conf
.Vpp2
=
405 dflt
.vpp1
.param
[CISTPL_POWER_VNOM
]/10000;
407 /* Do we need to allocate an interrupt? */
408 if (cfg
->irq
.IRQInfo1
|| dflt
.irq
.IRQInfo1
)
409 link
->conf
.Attributes
|= CONF_ENABLE_IRQ
;
411 /* IO window settings */
412 link
->io
.NumPorts1
= link
->io
.NumPorts2
= 0;
413 if ((cfg
->io
.nwin
> 0) || (dflt
.io
.nwin
> 0)) {
414 cistpl_io_t
*io
= (cfg
->io
.nwin
) ? &cfg
->io
: &dflt
.io
;
415 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_AUTO
;
416 if (!(io
->flags
& CISTPL_IO_8BIT
))
417 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_16
;
418 if (!(io
->flags
& CISTPL_IO_16BIT
)) {
420 link
->io
.Attributes1
= IO_DATA_PATH_WIDTH_8
;
421 printk(KERN_CRIT
"8-bit IO not supported on this aironet 4500 driver \n");
423 link
->io
.BasePort1
= io
->win
[0].base
;
425 link
->io
.NumPorts1
= io
->win
[0].len
;
427 link
->io
.Attributes2
= link
->io
.Attributes1
;
428 link
->io
.BasePort2
= io
->win
[1].base
;
429 link
->io
.NumPorts2
= io
->win
[1].len
;
434 while ((last_ret
= CardServices(RequestIO
, link
->handle
, &link
->io
)) ){
438 link
->io
.BasePort1
= awc_ports
[ii
];
446 if (CardServices(GetNextTuple
, handle
, &tuple
))
450 if (link
->conf
.Attributes
& CONF_ENABLE_IRQ
){
452 ii
= 0; last_fn
= RequestIRQ
;
453 while ((last_ret
= CardServices(RequestIRQ
, link
->handle
, &link
->irq
)) ){
456 while (!(irq_mask
& (1 << ii
) ) && ii
< 15)
458 link
->irq
.IRQInfo2
= 1 << ii
;
462 printk("trying irq %d , mask %x \n",ii
, link
->irq
.IRQInfo2
);
467 CS_CHECK(RequestConfiguration
, link
->handle
, &link
->conf
);
470 dev
->irq
= link
->irq
.AssignedIRQ
;
471 dev
->base_addr
= link
->io
.BasePort1
;
474 awc_private_init( dev
);
478 retval
= register_netdev(dev
);
480 printk(KERN_NOTICE
"awc_cs: register_netdev() failed for dev %x retval %x\n",(unsigned int)dev
,retval
);
484 if(awc_pcmcia_init(dev
)) goto failed
;
487 while (aironet4500_devices
[i
] && i
< MAX_AWCS
-1) i
++;
488 if (!aironet4500_devices
[i
]){
489 aironet4500_devices
[i
]=dev
;
490 if (awc_proc_set_fun
)
495 link
->state
&= ~DEV_CONFIG_PENDING
;
497 lp
= (struct awc_private
*)dev
->priv
;
499 DEBUG(1,"pcmcia config complete on port %x \n",(unsigned int)dev
->base_addr
);
504 cs_error(link
->handle
, last_fn
, last_ret
);
508 awc_release((u_long
)link
);
511 } /* awc_pcmcia_config */
514 After a card is removed, awc_release() will unregister the net
515 device, and release the PCMCIA configuration. If the device is
516 still open, this will be postponed until it is closed.
520 static void awc_release(u_long arg
)
522 dev_link_t
*link
= (dev_link_t
*)arg
;
523 struct net_device
*dev
= link
->priv
;
525 DEBUG(0, "awc_release(0x%p)\n", link
);
528 DEBUG(1, "awc_cs: release postponed, '%s' still open\n",
529 link
->dev
->dev_name
);
530 link
->state
|= DEV_STALE_CONFIG
;
534 CardServices(ReleaseConfiguration
, link
->handle
);
535 CardServices(ReleaseIO
, link
->handle
, &link
->io
);
536 CardServices(ReleaseIRQ
, link
->handle
, &link
->irq
);
538 CardServices(ReleaseWindow
, link
->win
);
540 unregister_netdev(dev
);
543 link
->state
&= ~DEV_CONFIG
;
544 if (link
->state
& DEV_STALE_LINK
)
551 The card status event handler. Mostly, this schedules other
552 stuff to run after an event is received. A CARD_REMOVAL event
553 also sets some flags to discourage the net drivers from trying
554 to talk to the card any more.
557 static int awc_event(event_t event
, int priority
,
558 event_callback_args_t
*args
)
560 dev_link_t
*link
= args
->client_data
;
561 struct net_device
*dev
= link
->priv
;
563 PC_DEBUG(1, "awc_event(0x%06x)\n", event
);
566 case CS_EVENT_CARD_REMOVAL
:
567 link
->state
&= ~DEV_PRESENT
;
568 if (link
->state
& DEV_CONFIG
) {
569 netif_device_detach(dev
);
570 link
->release
.expires
= RUN_AT( HZ
/20 );
571 add_timer(&link
->release
);
574 case CS_EVENT_CARD_INSERTION
:
575 link
->state
|= DEV_PRESENT
| DEV_CONFIG_PENDING
;
576 awc_pcmcia_config(link
);
578 case CS_EVENT_PM_SUSPEND
:
579 link
->state
|= DEV_SUSPEND
;
580 /* Fall through... */
581 case CS_EVENT_RESET_PHYSICAL
:
582 if (link
->state
& DEV_CONFIG
) {
584 netif_device_detach(dev
);
586 CardServices(ReleaseConfiguration
, link
->handle
);
589 case CS_EVENT_PM_RESUME
:
590 link
->state
&= ~DEV_SUSPEND
;
591 /* Fall through... */
592 case CS_EVENT_CARD_RESET
:
593 if (link
->state
& DEV_CONFIG
) {
594 CardServices(RequestConfiguration
, link
->handle
, &link
->conf
);
597 netif_device_attach(dev
);
607 int init_module(void)
611 /* Always emit the version, before any failure. */
612 printk(KERN_INFO
"%s", awc_version
);
613 PC_DEBUG(0, "%s\n", version
);
614 CardServices(GetCardServicesInfo
, &serv
);
615 if (serv
.Revision
!= CS_RELEASE_CODE
) {
616 printk(KERN_NOTICE
"awc_cs: Card Services release "
617 "does not match!\n");
620 register_pcmcia_driver(&dev_info
, &awc_attach
, &awc_detach
);
624 void cleanup_module(void)
626 DEBUG(0, "awc_cs: unloading %c ",'\n');
627 unregister_pcmcia_driver(&dev_info
);
629 while (dev_list
!= NULL
) {
630 if (dev_list
->state
& DEV_CONFIG
)
631 awc_release((u_long
)dev_list
);
632 awc_detach(dev_list
);
635 // while (dev_list != NULL)
636 // awc_detach(dev_list);