File: /usr/src/linux/drivers/net/pcmcia/aironet4500_cs.c
1 /*
2 * Aironet 4500 Pcmcia driver
3 *
4 * Elmer Joandi, Januar 1999
5 * Copyright Elmer Joandi, all rights restricted
6 *
7 *
8 * Revision 0.1 ,started 30.12.1998
9 *
10 *
11 */
12
13 static const char *awc_version =
14 "aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
15
16
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/ptrace.h>
22 #include <linux/slab.h>
23 #include <linux/string.h>
24 #include <linux/timer.h>
25 #include <linux/interrupt.h>
26 #include <linux/in.h>
27 #include <asm/io.h>
28 #include <asm/system.h>
29 #include <asm/bitops.h>
30
31 #include <linux/netdevice.h>
32 #include <linux/etherdevice.h>
33 #include <linux/skbuff.h>
34 #include <linux/if_arp.h>
35 #include <linux/ioport.h>
36
37
38 #include <pcmcia/version.h>
39 #include <pcmcia/cs_types.h>
40 #include <pcmcia/cs.h>
41 #include <pcmcia/cistpl.h>
42 #include <pcmcia/cisreg.h>
43 #include <pcmcia/ciscode.h>
44 #if LINUX_VERSION_CODE < 0x20300
45 #ifdef MODULE
46 #include <pcmcia/k_compat.h>
47 #endif
48 #endif
49 #include <pcmcia/ds.h>
50
51 #include "../aironet4500.h"
52
53
54 static u_int irq_mask = 0x5eF8;
55 static int awc_ports[] = {0x140,0x100,0xc0, 0x80 };
56 #if LINUX_VERSION_CODE > 0x20100
57 MODULE_PARM(irq_mask, "i");
58
59 #endif
60
61
62 #define RUN_AT(x) (jiffies+(x))
63
64 #ifdef PCMCIA_DEBUG
65 static int pc_debug = PCMCIA_DEBUG;
66 MODULE_PARM(pc_debug, "i");
67 #define PC_DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
68 static char *version =
69 "aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
70 #else
71 #define PC_DEBUG(n, args...)
72 #endif
73
74 /* Index of functions. */
75
76 static dev_info_t dev_info = "aironet4500_cs";
77
78 static dev_link_t *awc_attach(void);
79 static void awc_detach(dev_link_t *);
80 static void awc_release(u_long arg);
81 static int awc_event(event_t event, int priority,
82 event_callback_args_t *args);
83
84 static dev_link_t *dev_list;
85
86 static void cs_error(client_handle_t handle, int func, int ret)
87 {
88 #if CS_RELEASE_CODE < 0x2911
89 CardServices(ReportError, dev_info, (void *)func, (void *)ret);
90 #else
91 error_info_t err = { func, ret };
92 CardServices(ReportError, handle, &err);
93 #endif
94 }
95
96 #define CFG_CHECK(fn, args...) if (CardServices(fn, args) != 0) goto next_entry
97
98 static void flush_stale_links(void)
99 {
100 dev_link_t *link, *next;
101 for (link = dev_list; link; link = next) {
102 next = link->next;
103 if (link->state & DEV_STALE_LINK)
104 awc_detach(link);
105 }
106 }
107
108
109 /*
110 We never need to do anything when a awc device is "initialized"
111 by the net software, because we only register already-found cards.
112 */
113
114 static int awc_pcmcia_init(struct net_device *dev)
115 {
116 return awc_init(dev);
117
118 }
119
120 static int awc_pcmcia_open(struct net_device *dev)
121 {
122 dev_link_t *link;
123 int status;
124
125 for (link = dev_list; link; link = link->next)
126 if (link->priv == dev) break;
127 if (!DEV_OK(link))
128 return -ENODEV;
129
130 status = awc_open(dev);
131
132 if (!status )
133 link->open++;
134
135 return status;
136 }
137
138 static int awc_pcmcia_close(struct net_device *dev)
139 {
140 // int ioaddr = dev->base_addr;
141 dev_link_t *link;
142 int ret;
143
144 for (link = dev_list; link; link = link->next)
145 if (link->priv == dev) break;
146 if (link == NULL)
147 return -ENODEV;
148
149 PC_DEBUG(2, "%s: closing device.\n", dev->name);
150
151 link->open--;
152 ret = awc_close(dev);
153
154 if (link->state & DEV_STALE_CONFIG) {
155 link->release.expires = RUN_AT( HZ/20 );
156 link->state |= DEV_RELEASE_PENDING;
157 add_timer(&link->release);
158 }
159 return ret;
160 }
161
162 /*
163 awc_attach() creates an "instance" of the driver, allocating
164 local data structures for one device. The device is registered
165 with Card Services.
166 */
167
168 static dev_link_t *awc_attach(void)
169 {
170 client_reg_t client_reg;
171 dev_link_t *link = NULL;
172 struct net_device *dev = NULL;
173 int ret;
174
175 PC_DEBUG(0, "awc_attach()\n");
176 flush_stale_links();
177
178 /* Create the PC card device object. */
179 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
180 if (!link)
181 return NULL;
182 memset(link, 0, sizeof(struct dev_link_t));
183
184 link->dev = kmalloc(sizeof(struct dev_node_t), GFP_KERNEL);
185 if (!link->dev) {
186 kfree(link);
187 return NULL;
188 }
189
190 memset(link->dev, 0, sizeof(struct dev_node_t));
191
192 link->release.function = &awc_release;
193 link->release.data = (u_long)link;
194 // link->io.NumPorts1 = 32;
195 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
196 // link->io.IOAddrLines = 5;
197 link->irq.Attributes = IRQ_HANDLE_PRESENT ; // |IRQ_TYPE_EXCLUSIVE ;
198 link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
199 link->irq.IRQInfo2 = irq_mask;
200 link->irq.Handler = &awc_interrupt;
201 link->conf.Attributes = CONF_ENABLE_IRQ;
202 link->conf.Vcc = 50;
203 link->conf.IntType = INT_MEMORY_AND_IO;
204 link->conf.ConfigIndex = 1;
205 link->conf.Present = PRESENT_OPTION;
206
207 /* Create the network device object. */
208
209 dev = kmalloc(sizeof(struct net_device ), GFP_KERNEL);
210 // dev = init_etherdev(0, sizeof(struct awc_private) );
211 if (!dev ) {
212 printk(KERN_CRIT "out of mem on dev alloc \n");
213 kfree(link->dev);
214 kfree(link);
215 return NULL;
216 };
217 memset(dev,0,sizeof(struct net_device));
218 dev->priv = kmalloc(sizeof(struct awc_private), GFP_KERNEL);
219 if (!dev->priv ) {printk(KERN_CRIT "out of mem on dev priv alloc \n"); return NULL;};
220 memset(dev->priv,0,sizeof(struct awc_private));
221
222 // link->dev->minor = dev->minor;
223 // link->dev->major = dev->major;
224
225 /* The 4500-specific entries in the device structure. */
226
227 // dev->tx_queue_len = tx_queue_len;
228
229 dev->hard_start_xmit = &awc_start_xmit;
230 // dev->set_config = &awc_config_misiganes,aga mitte awc_config;
231 dev->get_stats = &awc_get_stats;
232 // dev->set_multicast_list = &awc_set_multicast_list;
233
234 strcpy(dev->name, ((struct awc_private *)dev->priv)->node.dev_name);
235
236 ether_setup(dev);
237
238 dev->init = &awc_pcmcia_init;
239 dev->open = &awc_pcmcia_open;
240 dev->stop = &awc_pcmcia_close;
241
242 link->priv = dev;
243 #if CS_RELEASE_CODE > 0x2911
244 link->irq.Instance = dev;
245 #endif
246
247 /* Register with Card Services */
248 link->next = dev_list;
249 dev_list = link;
250
251
252 client_reg.dev_info = &dev_info;
253 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
254 client_reg.EventMask =
255 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
256 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
257 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
258 client_reg.event_handler = &awc_event;
259 client_reg.Version = 0x0210;
260 client_reg.event_callback_args.client_data = link;
261 ret = CardServices(RegisterClient, &link->handle, &client_reg);
262 if (ret != 0) {
263 cs_error(link->handle, RegisterClient, ret);
264 awc_detach(link);
265 return NULL;
266 }
267
268 return link;
269 } /* awc_attach */
270
271 /*
272
273 This deletes a driver "instance". The device is de-registered
274 with Card Services. If it has been released, all local data
275 structures are freed. Otherwise, the structures will be freed
276 when the device is released.
277
278 */
279
280 static void awc_detach(dev_link_t *link)
281 {
282 dev_link_t **linkp;
283 long flags;
284 int i=0;
285
286 DEBUG(0, "awc_detach(0x%p)\n", link);
287
288 /* Locate device structure */
289 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
290 if (*linkp == link) break;
291 if (*linkp == NULL)
292 return;
293
294 save_flags(flags);
295 cli();
296 if (link->state & DEV_RELEASE_PENDING) {
297 del_timer(&link->release);
298 link->state &= ~DEV_RELEASE_PENDING;
299 }
300 restore_flags(flags);
301
302 if (link->state & DEV_CONFIG) {
303 awc_release((u_long)link);
304 if (link->state & DEV_STALE_CONFIG) {
305 link->state |= DEV_STALE_LINK;
306 return;
307 }
308 }
309
310 if (link->handle)
311 CardServices(DeregisterClient, link->handle);
312
313 /* Unlink device structure, free bits */
314 *linkp = link->next;
315
316 i=0;
317 while ( i < MAX_AWCS) {
318 if (!aironet4500_devices[i])
319 {i++; continue;}
320 if (aironet4500_devices[i] == link->priv){
321 if (awc_proc_unset_fun)
322 awc_proc_unset_fun(i);
323
324 aironet4500_devices[i]=0;
325 }
326 i++;
327 }
328
329 if (link->priv) {
330 //struct net_device *dev = link->priv;
331 // dam dam damn mif (dev->priv)
332 // kfree(dev->priv);
333 kfree(link->priv);
334 }
335 kfree(link->dev);
336 kfree(link);
337
338 } /* awc_detach */
339
340 /*
341
342 awc_pcmcia_config() is scheduled to run after a CARD_INSERTION event
343 is received, to configure the PCMCIA socket, and to make the
344 ethernet device available to the system.
345
346 */
347
348 #define CS_CHECK(fn, args...) \
349 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
350
351 static void awc_pcmcia_config(dev_link_t *link)
352 {
353 client_handle_t handle;
354 struct net_device *dev;
355 struct awc_private *lp;
356 tuple_t tuple;
357 int ii;
358 cisparse_t parse;
359 u_short buf[64];
360 int last_fn, last_ret, i = 0;
361 // int ioaddr;
362 u16 *phys_addr;
363 int retval;
364
365 handle = link->handle;
366 dev = link->priv;
367 phys_addr = (u16 *)dev->dev_addr;
368
369 PC_DEBUG(0, "awc_pcmcia_config(0x%p)\n", link);
370
371 tuple.Attributes = 0;
372 tuple.DesiredTuple = CISTPL_CONFIG;
373 CS_CHECK(GetFirstTuple, handle, &tuple);
374 tuple.TupleData = (cisdata_t *)buf;
375 tuple.TupleDataMax = 64;
376 tuple.TupleOffset = 0;
377 CS_CHECK(GetTupleData, handle, &tuple);
378 CS_CHECK(ParseTuple, handle, &tuple, &parse);
379 link->conf.ConfigBase = parse.config.base;
380 link->conf.Present = parse.config.rmask[0];
381
382
383 /* Configure card */
384 link->state |= DEV_CONFIG;
385
386 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
387 CS_CHECK(GetFirstTuple, handle, &tuple);
388
389 while (1) {
390 cistpl_cftable_entry_t dflt = { 0 };
391 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
392 CFG_CHECK(GetTupleData, handle, &tuple);
393 CFG_CHECK(ParseTuple, handle, &tuple, &parse);
394
395 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
396 if (cfg->index == 0) goto next_entry;
397 link->conf.ConfigIndex = cfg->index;
398
399 /* Use power settings for Vcc and Vpp if present */
400 /* Note that the CIS values need to be rescaled */
401 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
402 link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
403 else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
404 link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
405
406 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
407 link->conf.Vpp1 = link->conf.Vpp2 =
408 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
409 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
410 link->conf.Vpp1 = link->conf.Vpp2 =
411 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
412
413 /* Do we need to allocate an interrupt? */
414 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
415 link->conf.Attributes |= CONF_ENABLE_IRQ;
416
417 /* IO window settings */
418 link->io.NumPorts1 = link->io.NumPorts2 = 0;
419 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
420 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
421 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
422 if (!(io->flags & CISTPL_IO_8BIT))
423 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
424 if (!(io->flags & CISTPL_IO_16BIT)) {
425
426 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
427 printk(KERN_CRIT "8-bit IO not supported on this aironet 4500 driver \n");
428 }
429 link->io.BasePort1 = io->win[0].base;
430
431 link->io.NumPorts1 = io->win[0].len;
432 if (io->nwin > 1) {
433 link->io.Attributes2 = link->io.Attributes1;
434 link->io.BasePort2 = io->win[1].base;
435 link->io.NumPorts2 = io->win[1].len;
436 }
437 }
438 ii = 0;
439 last_fn = RequestIO;
440 while ((last_ret = CardServices(RequestIO, link->handle, &link->io)) ){
441
442 if (ii > 4)
443 goto cs_failed;
444 link->io.BasePort1 = awc_ports[ii];
445 ii++;
446 };
447
448
449 break;
450
451 next_entry:
452 if (CardServices(GetNextTuple, handle, &tuple))
453 break;
454 }
455
456 if (link->conf.Attributes & CONF_ENABLE_IRQ){
457
458 ii = 0; last_fn = RequestIRQ;
459 while ((last_ret = CardServices(RequestIRQ, link->handle, &link->irq)) ){
460
461 ii++;
462 while (!(irq_mask & (1 << ii) ) && ii < 15)
463 ii++;
464 link->irq.IRQInfo2 = 1 << ii;
465
466 if(ii > 15)
467 goto cs_failed;
468 printk("trying irq %d , mask %x \n",ii, link->irq.IRQInfo2);
469
470 };
471 }
472
473 CS_CHECK(RequestConfiguration, link->handle, &link->conf);
474
475
476 dev->irq = link->irq.AssignedIRQ;
477 dev->base_addr = link->io.BasePort1;
478
479
480 awc_private_init( dev);
481
482
483
484 retval = register_netdev(dev);
485 if (retval != 0) {
486 printk(KERN_NOTICE "awc_cs: register_netdev() failed for dev %x retval %x\n",(unsigned int)dev,retval);
487 goto failed;
488 }
489
490 if(awc_pcmcia_init(dev)) goto failed;
491
492 i=0;
493 while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
494 if (!aironet4500_devices[i]){
495 aironet4500_devices[i]=dev;
496 if (awc_proc_set_fun)
497 awc_proc_set_fun(i);
498 }
499
500
501 link->state &= ~DEV_CONFIG_PENDING;
502
503 lp = (struct awc_private *)dev->priv;
504
505 DEBUG(1,"pcmcia config complete on port %x \n",(unsigned int)dev->base_addr);
506
507 return;
508
509 cs_failed:
510 cs_error(link->handle, last_fn, last_ret);
511 link->dev=NULL;
512 failed:
513
514 awc_release((u_long)link);
515 return;
516
517 } /* awc_pcmcia_config */
518
519 /*
520 After a card is removed, awc_release() will unregister the net
521 device, and release the PCMCIA configuration. If the device is
522 still open, this will be postponed until it is closed.
523
524 */
525
526 static void awc_release(u_long arg)
527 {
528 dev_link_t *link = (dev_link_t *)arg;
529 struct net_device *dev = link->priv;
530
531 DEBUG(0, "awc_release(0x%p)\n", link);
532
533 if (link->open) {
534 DEBUG(1, "awc_cs: release postponed, '%s' still open\n",
535 link->dev->dev_name);
536 link->state |= DEV_STALE_CONFIG;
537 return;
538 }
539
540 CardServices(ReleaseConfiguration, link->handle);
541 CardServices(ReleaseIO, link->handle, &link->io);
542 CardServices(ReleaseIRQ, link->handle, &link->irq);
543
544 CardServices(ReleaseWindow, link->win);
545 if (link->dev)
546 unregister_netdev(dev);
547 // link->dev = NULL;
548
549 link->state &= ~DEV_CONFIG;
550 if (link->state & DEV_STALE_LINK)
551 awc_detach(link);
552
553 } /* awc_release */
554
555 /*
556
557 The card status event handler. Mostly, this schedules other
558 stuff to run after an event is received. A CARD_REMOVAL event
559 also sets some flags to discourage the net drivers from trying
560 to talk to the card any more.
561 */
562
563 static int awc_event(event_t event, int priority,
564 event_callback_args_t *args)
565 {
566 dev_link_t *link = args->client_data;
567 struct net_device *dev = link->priv;
568
569 PC_DEBUG(1, "awc_event(0x%06x)\n", event);
570
571 switch (event) {
572 case CS_EVENT_CARD_REMOVAL:
573 link->state &= ~DEV_PRESENT;
574 if (link->state & DEV_CONFIG) {
575 netif_device_detach(dev);
576 link->release.expires = RUN_AT( HZ/20 );
577 add_timer(&link->release);
578 }
579 break;
580 case CS_EVENT_CARD_INSERTION:
581 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
582 awc_pcmcia_config(link);
583 break;
584 case CS_EVENT_PM_SUSPEND:
585 link->state |= DEV_SUSPEND;
586 /* Fall through... */
587 case CS_EVENT_RESET_PHYSICAL:
588 if (link->state & DEV_CONFIG) {
589 if (link->open)
590 netif_device_detach(dev);
591
592 CardServices(ReleaseConfiguration, link->handle);
593 }
594 break;
595 case CS_EVENT_PM_RESUME:
596 link->state &= ~DEV_SUSPEND;
597 /* Fall through... */
598 case CS_EVENT_CARD_RESET:
599 if (link->state & DEV_CONFIG) {
600 CardServices(RequestConfiguration, link->handle, &link->conf);
601 if (link->open) {
602 // awc_reset(dev);
603 netif_device_attach(dev);
604 }
605 }
606 break;
607 }
608 return 0;
609 } /* awc_event */
610
611
612
613 static int __init aironet_cs_init(void)
614 {
615 servinfo_t serv;
616
617 /* Always emit the version, before any failure. */
618 printk(KERN_INFO"%s", awc_version);
619 PC_DEBUG(0, "%s\n", version);
620 CardServices(GetCardServicesInfo, &serv);
621 if (serv.Revision != CS_RELEASE_CODE) {
622 printk(KERN_NOTICE "awc_cs: Card Services release "
623 "does not match!\n");
624 return -1;
625 }
626 register_pcmcia_driver(&dev_info, &awc_attach, &awc_detach);
627 return 0;
628 }
629
630 static void __exit aironet_cs_exit(void)
631 {
632 DEBUG(0, "awc_cs: unloading %c ",'\n');
633 unregister_pcmcia_driver(&dev_info);
634
635 while (dev_list != NULL) {
636 if (dev_list->state & DEV_CONFIG)
637 awc_release((u_long)dev_list);
638 awc_detach(dev_list);
639 }
640
641 // while (dev_list != NULL)
642 // awc_detach(dev_list);
643 }
644
645 module_init(aironet_cs_init);
646 module_exit(aironet_cs_exit);
647
648