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