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