1 /*** -*- linux-c -*- **********************************************************
2 
3      Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
4 
5         Copyright 2000-2001 ATMEL Corporation.
6         Copyright 2003 Simon Kelley.
7 
8     This code was developed from version 2.1.1 of the Atmel drivers,
9     released by Atmel corp. under the GPL in December 2002. It also
10     includes code from the Linux aironet drivers (C) Benjamin Reed,
11     and the Linux PCMCIA package, (C) David Hinds.
12 
13     For all queries about this code, please contact the current author,
14     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
15 
16     This program is free software; you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20 
21     This software is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24     GNU General Public License for more details.
25 
26     You should have received a copy of the GNU General Public License
27     along with Atmel wireless lan drivers; if not, write to the Free Software
28     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 
30 ******************************************************************************/
31 
32 #include <linux/config.h>
33 #ifdef __IN_PCMCIA_PACKAGE__
34 #include <pcmcia/k_compat.h>
35 #endif
36 #include <linux/init.h>
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #include <linux/ptrace.h>
40 #include <linux/slab.h>
41 #include <linux/string.h>
42 #include <linux/netdevice.h>
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/ds.h>
50 #include <pcmcia/ciscode.h>
51 
52 #include <asm/io.h>
53 #include <asm/system.h>
54 #include <linux/wireless.h>
55 #include <linux/802_11.h>
56 
57 
58 /*
59    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
60    you do not define PCMCIA_DEBUG at all, all the debug code will be
61    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
62    be present but disabled -- but it can then be enabled for specific
63    modules at load time with a 'pc_debug=#' option to insmod.
64 */
65 #ifdef PCMCIA_DEBUG
66 static int pc_debug = PCMCIA_DEBUG;
67 MODULE_PARM(pc_debug, "i");
68 static char *version = "$Revision: 1.2 $";
69 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
70 #else
71 #define DEBUG(n, args...)
72 #endif
73 
74 /*====================================================================*/
75 
76 /* Parameters that can be set with 'insmod' */
77 
78 /* The old way: bit map of interrupts to choose from */
79 /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
80 static u_int irq_mask = 0xdeb8;
81 /* Newer, simpler way of listing specific interrupts */
82 static int irq_list[4] = { -1 };
83 
84 MODULE_AUTHOR("Simon Kelley");
85 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
86 MODULE_LICENSE("GPL");
87 MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
88 MODULE_PARM(irq_mask, "i");
89 MODULE_PARM(irq_list, "1-4i");
90 
91 /*====================================================================*/
92 
93 /*
94    The event() function is this driver's Card Services event handler.
95    It will be called by Card Services when an appropriate card status
96    event is received.  The config() and release() entry points are
97    used to configure or release a socket, in response to card
98    insertion and ejection events.  They are invoked from the atmel_cs
99    event handler.
100 */
101 
102 struct net_device *init_atmel_card(int, int, char *, int,
103 				    int (*present_func)(void *), void * );
104 void stop_atmel_card( struct net_device *, int );
105 int reset_atmel_card( struct net_device * );
106 
107 static void atmel_config(dev_link_t *link);
108 static void atmel_release(dev_link_t *link);
109 static int atmel_event(event_t event, int priority,
110 		       event_callback_args_t *args);
111 
112 /*
113    The attach() and detach() entry points are used to create and destroy
114    "instances" of the driver, where each instance represents everything
115    needed to manage one actual PCMCIA card.
116 */
117 
118 static dev_link_t *atmel_attach(void);
119 static void atmel_detach(dev_link_t *);
120 
121 /*
122    You'll also need to prototype all the functions that will actually
123    be used to talk to your device.  See 'pcmem_cs' for a good example
124    of a fully self-sufficient driver; the other drivers rely more or
125    less on other parts of the kernel.
126 */
127 
128 /*
129    The dev_info variable is the "key" that is used to match up this
130    device driver with appropriate cards, through the card configuration
131    database.
132 */
133 
134 static dev_info_t dev_info = "atmel_cs";
135 
136 /*
137    A linked list of "instances" of the  atmelnet device.  Each actual
138    PCMCIA card corresponds to one device instance, and is described
139    by one dev_link_t structure (defined in ds.h).
140 
141    You may not want to use a linked list for this -- for example, the
142    memory card driver uses an array of dev_link_t pointers, where minor
143    device numbers are used to derive the corresponding array index.
144 */
145 
146 static dev_link_t *dev_list = NULL;
147 
148 /*
149    A dev_link_t structure has fields for most things that are needed
150    to keep track of a socket, but there will usually be some device
151    specific information that also needs to be kept track of.  The
152    'priv' pointer in a dev_link_t structure can be used to point to
153    a device-specific private data structure, like this.
154 
155    A driver needs to provide a dev_node_t structure for each device
156    on a card.  In some cases, there is only one device per card (for
157    example, ethernet cards, modems).  In other cases, there may be
158    many actual or logical devices (SCSI adapters, memory cards with
159    multiple partitions).  The dev_node_t structures need to be kept
160    in a linked list starting at the 'dev' field of a dev_link_t
161    structure.  We allocate them in the card's private data structure,
162    because they generally shouldn't be allocated dynamically.
163 
164    In this case, we also provide a flag to indicate if a device is
165    "stopped" due to a power management event, or card ejection.  The
166    device IO routines can use a flag like this to throttle IO to a
167    card that is not ready to accept it.
168 */
169 
170 typedef struct local_info_t {
171 	dev_node_t	node;
172 	struct net_device *eth_dev;
173 } local_info_t;
174 
175 /*====================================================================*/
176 
cs_error(client_handle_t handle,int func,int ret)177 static void cs_error(client_handle_t handle, int func, int ret)
178 {
179 	error_info_t err = { func, ret };
180 	CardServices(ReportError, handle, &err);
181 }
182 
183 /*======================================================================
184 
185   atmel_attach() creates an "instance" of the driver, allocating
186   local data structures for one device.  The device is registered
187   with Card Services.
188 
189   The dev_link structure is initialized, but we don't actually
190   configure the card at this point -- we wait until we receive a
191   card insertion event.
192 
193   ======================================================================*/
194 
atmel_attach(void)195 static dev_link_t *atmel_attach(void)
196 {
197 	client_reg_t client_reg;
198 	dev_link_t *link;
199 	local_info_t *local;
200 	int ret, i;
201 
202 	DEBUG(0, "atmel_attach()\n");
203 
204 	/* Initialize the dev_link_t structure */
205 	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
206 	if (!link) {
207 		printk(KERN_ERR "atmel_cs: no memory for new device\n");
208 		return NULL;
209 	}
210 	memset(link, 0, sizeof(struct dev_link_t));
211 
212 	/* Interrupt setup */
213 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
214 	link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
215 	if (irq_list[0] == -1)
216 		link->irq.IRQInfo2 = irq_mask;
217 	else
218 		for (i = 0; i < 4; i++)
219 			link->irq.IRQInfo2 |= 1 << irq_list[i];
220 	link->irq.Handler = NULL;
221 
222 	/*
223 	  General socket configuration defaults can go here.  In this
224 	  client, we assume very little, and rely on the CIS for almost
225 	  everything.  In most clients, many details (i.e., number, sizes,
226 	  and attributes of IO windows) are fixed by the nature of the
227 	  device, and can be hard-wired here.
228 	*/
229 	link->conf.Attributes = 0;
230 	link->conf.Vcc = 50;
231 	link->conf.IntType = INT_MEMORY_AND_IO;
232 
233 	/* Allocate space for private device-specific data */
234 	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
235 	if (!local) {
236 		printk(KERN_ERR "atmel_cs: no memory for new device\n");
237 		kfree (link);
238 		return NULL;
239 	}
240 	memset(local, 0, sizeof(local_info_t));
241 	link->priv = local;
242 
243 	/* Register with Card Services */
244 	link->next = dev_list;
245 	dev_list = link;
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 = &atmel_event;
253 	client_reg.Version = 0x0210;
254 	client_reg.event_callback_args.client_data = link;
255 	ret = CardServices(RegisterClient, &link->handle, &client_reg);
256 	if (ret != 0) {
257 		cs_error(link->handle, RegisterClient, ret);
258 		atmel_detach(link);
259 		return NULL;
260 	}
261 
262 	return link;
263 } /* atmel_attach */
264 
265 /*======================================================================
266 
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.
271 
272   ======================================================================*/
273 
atmel_detach(dev_link_t * link)274 static void atmel_detach(dev_link_t *link)
275 {
276 	dev_link_t **linkp;
277 
278 	DEBUG(0, "atmel_detach(0x%p)\n", link);
279 
280 	/* Locate device structure */
281 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
282 		if (*linkp == link) break;
283 	if (*linkp == NULL)
284 		return;
285 
286 	if (link->state & DEV_CONFIG)
287 		atmel_release(link);
288 
289 	/* Break the link with Card Services */
290 	if (link->handle)
291 		CardServices(DeregisterClient, link->handle);
292 
293 	/* Unlink device structure, free pieces */
294 	*linkp = link->next;
295 	if (link->priv)
296 		kfree(link->priv);
297 	kfree(link);
298 }
299 
300 /*======================================================================
301 
302   atmel_config() is scheduled to run after a CARD_INSERTION event
303   is received, to configure the PCMCIA socket, and to make the
304   device available to the system.
305 
306   ======================================================================*/
307 
308 #define CS_CHECK(fn, args...) \
309 while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
310 
311 #define CFG_CHECK(fn, args...) \
312 if (CardServices(fn, args) != 0) goto next_entry
313 
314 /* Call-back function to interrogate PCMCIA-specific information
315    about the current existance of the card */
card_present(void * arg)316 static int card_present(void *arg)
317 {
318 	dev_link_t *link = (dev_link_t *)arg;
319 	if (link->state & DEV_SUSPEND)
320 		return 0;
321 	else if (link->state & DEV_PRESENT)
322 		return 1;
323 
324 	return 0;
325 }
326 
327 /* list of cards we know about and their firmware requirements.
328    Go either by Manfid or version strings.
329    Cards not in this list will need a firmware parameter to the module
330    in all probability. Note that the SMC 2632 V2 and V3 have the same
331    manfids, so we ignore those and use the version1 strings. */
332 
333 static struct {
334 	int manf, card;
335 	char *ver1;
336 	char *firmware;
337 	char *name;
338 } card_table[] = {
339 	{ 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d.bin", "Actiontec 802CAT1" },
340 	{ 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502.bin", "NoName-RFMD" },
341 	{ 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d.bin", "NoName-revD" },
342 	{ 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e.bin", "NoName-revE" },
343 	{ 0, 0, "ATMEL/AT76C504", "atmel_at76c504.bin", "NoName-504" },
344 	{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com.bin", "3com 3CRWE62092B" },
345 	{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com.bin", "3com 3CRSHPW_96" },
346 	{ 0, 0, "SMC/2632W-V2", "atmel_at76c502.bin", "SMC 2632W-V2" },
347         { 0, 0, "SMC/2632W", "atmel_at76c502d.bin", "SMC 2632W-V3" },
348 	{ 0xd601, 0x0007, NULL, "atmel_at76c502.bin", "Sitecom WLAN-011"}, /* suspect - from a usenet posting. */
349 	{ 0x01bf, 0x3302, NULL, "atmel_at76c502d.bin", "Belkin F5D6060u"},  /*    "        "  "    "      "     */
350 	{ 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502.bin", "BT Voyager 1020"},
351         { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502.bin", "Siemens Gigaset PC Card II" },
352 	{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e.bin", "CNet CNWLC-811ARL" }
353 };
354 
atmel_config(dev_link_t * link)355 static void atmel_config(dev_link_t *link)
356 {
357 	client_handle_t handle;
358 	tuple_t tuple;
359 	cisparse_t parse;
360 	local_info_t *dev;
361 	int last_fn, last_ret;
362 	u_char buf[64];
363 	int card_index = -1, done = 0;
364 
365 	handle = link->handle;
366 	dev = link->priv;
367 
368 	DEBUG(0, "atmel_config(0x%p)\n", link);
369 
370 	tuple.Attributes = 0;
371 	tuple.TupleData = buf;
372 	tuple.TupleDataMax = sizeof(buf);
373 	tuple.TupleOffset = 0;
374 
375 	tuple.DesiredTuple = CISTPL_MANFID;
376 	if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
377 		int i;
378 		cistpl_manfid_t *manfid;
379 		CS_CHECK(GetTupleData, handle, &tuple);
380 		CS_CHECK(ParseTuple, handle, &tuple, &parse);
381 		manfid = &(parse.manfid);
382 		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
383 			if (!card_table[i].ver1 &&
384 			    manfid->manf == card_table[i].manf &&
385 			    manfid->card == card_table[i].card) {
386 				card_index = i;
387 				done = 1;
388 			}
389 		}
390 	}
391 
392 	tuple.DesiredTuple = CISTPL_VERS_1;
393 	if (!done && (CardServices(GetFirstTuple, handle, &tuple) == 0)) {
394 		int i, j, k;
395 		cistpl_vers_1_t *ver1;
396 		CS_CHECK(GetTupleData, handle, &tuple);
397 		CS_CHECK(ParseTuple, handle, &tuple, &parse);
398 		ver1 = &(parse.version_1);
399 
400 		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
401 			for (j = 0; j < ver1->ns; j++) {
402 				char *p = card_table[i].ver1;
403 				char *q = &ver1->str[ver1->ofs[j]];
404 				if (!p)
405 					goto mismatch;
406 				for (k = 0; k < j; k++) {
407 					while ((*p != '\0') && (*p != '/')) p++;
408 					if (*p == '\0') {
409 					  if (*q != '\0')
410 						goto mismatch;
411 					} else
412 					  p++;
413 				}
414 				while((*q != '\0') && (*p != '\0') &&
415 				      (*p != '/') && (*p == *q)) p++, q++;
416 				if (((*p != '\0') && *p != '/') || *q != '\0')
417 					goto mismatch;
418 			}
419 			card_index = i;
420 			break;	/* done */
421 
422 		mismatch:
423 			j = 0; /* dummy stmt to shut up compiler */
424 		}
425 	}
426 
427 	/*
428 	  This reads the card's CONFIG tuple to find its configuration
429 	  registers.
430 	*/
431 	tuple.DesiredTuple = CISTPL_CONFIG;
432 	CS_CHECK(GetFirstTuple, handle, &tuple);
433 	CS_CHECK(GetTupleData, handle, &tuple);
434 	CS_CHECK(ParseTuple, handle, &tuple, &parse);
435 	link->conf.ConfigBase = parse.config.base;
436 	link->conf.Present = parse.config.rmask[0];
437 
438 	/* Configure card */
439 	link->state |= DEV_CONFIG;
440 
441 	/*
442 	  In this loop, we scan the CIS for configuration table entries,
443 	  each of which describes a valid card configuration, including
444 	  voltage, IO window, memory window, and interrupt settings.
445 
446 	  We make no assumptions about the card to be configured: we use
447 	  just the information available in the CIS.  In an ideal world,
448 	  this would work for any PCMCIA card, but it requires a complete
449 	  and accurate CIS.  In practice, a driver usually "knows" most of
450 	  these things without consulting the CIS, and most client drivers
451 	  will only use the CIS to fill in implementation-defined details.
452 	*/
453 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
454 	CS_CHECK(GetFirstTuple, handle, &tuple);
455 	while (1) {
456 		cistpl_cftable_entry_t dflt = { 0 };
457 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
458 		CFG_CHECK(GetTupleData, handle, &tuple);
459 		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
460 
461 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
462 		if (cfg->index == 0) goto next_entry;
463 		link->conf.ConfigIndex = cfg->index;
464 
465 		/* Does this card need audio output? */
466 		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
467 			link->conf.Attributes |= CONF_ENABLE_SPKR;
468 			link->conf.Status = CCSR_AUDIO_ENA;
469 		}
470 
471 		/* Use power settings for Vcc and Vpp if present */
472 		/*  Note that the CIS values need to be rescaled */
473 		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
474 			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
475 		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
476 			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
477 
478 		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
479 			link->conf.Vpp1 = link->conf.Vpp2 =
480 				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
481 		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
482 			link->conf.Vpp1 = link->conf.Vpp2 =
483 				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
484 
485 		/* Do we need to allocate an interrupt? */
486 		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
487 			link->conf.Attributes |= CONF_ENABLE_IRQ;
488 
489 		/* IO window settings */
490 		link->io.NumPorts1 = link->io.NumPorts2 = 0;
491 		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
492 			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
493 			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
494 			if (!(io->flags & CISTPL_IO_8BIT))
495 				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
496 			if (!(io->flags & CISTPL_IO_16BIT))
497 				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
498 			link->io.BasePort1 = io->win[0].base;
499 			link->io.NumPorts1 = io->win[0].len;
500 			if (io->nwin > 1) {
501 				link->io.Attributes2 = link->io.Attributes1;
502 				link->io.BasePort2 = io->win[1].base;
503 				link->io.NumPorts2 = io->win[1].len;
504 			}
505 		}
506 
507 		/* This reserves IO space but doesn't actually enable it */
508 		CFG_CHECK(RequestIO, link->handle, &link->io);
509 		/* If we got this far, we're cool! */
510 		break;
511 
512 	next_entry:
513 		CS_CHECK(GetNextTuple, handle, &tuple);
514 	}
515 
516 	/*
517 	  Allocate an interrupt line.  Note that this does not assign a
518 	  handler to the interrupt, unless the 'Handler' member of the
519 	  irq structure is initialized.
520 	*/
521 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
522 		CS_CHECK(RequestIRQ, link->handle, &link->irq);
523 
524 	/*
525 	  This actually configures the PCMCIA socket -- setting up
526 	  the I/O windows and the interrupt mapping, and putting the
527 	  card and host interface into "Memory and IO" mode.
528 	*/
529 	CS_CHECK(RequestConfiguration, link->handle, &link->conf);
530 
531 	if (link->irq.AssignedIRQ == 0) {
532 		printk(KERN_ALERT
533 		       "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
534 		goto cs_failed;
535 	}
536 
537 	((local_info_t*)link->priv)->eth_dev =
538 		init_atmel_card(link->irq.AssignedIRQ,
539 				link->io.BasePort1,
540 				card_index == -1 ? NULL :  card_table[card_index].firmware,
541 				card_index == -1 ? 0 : (card_table[card_index].manf == MANFID_3COM),
542 				card_present,
543 				link);
544 	if (!((local_info_t*)link->priv)->eth_dev)
545 		goto cs_failed;
546 
547 	/*
548 	  At this point, the dev_node_t structure(s) need to be
549 	  initialized and arranged in a linked list at link->dev.
550 	*/
551 	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
552 	dev->node.major = dev->node.minor = 0;
553 	link->dev = &dev->node;
554 
555 	/* Finally, report what we've done */
556 	printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
557 	       dev->node.dev_name,
558 	       card_index == -1 ? "" :  card_table[card_index].name,
559 	       card_index == -1 ? "" : " ",
560 	       link->conf.ConfigIndex,
561 	       link->conf.Vcc/10, link->conf.Vcc%10);
562 	if (link->conf.Vpp1)
563 		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
564 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
565 		printk(", irq %d", link->irq.AssignedIRQ);
566 	if (link->io.NumPorts1)
567 		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
568 		       link->io.BasePort1+link->io.NumPorts1-1);
569 	if (link->io.NumPorts2)
570 		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
571 		       link->io.BasePort2+link->io.NumPorts2-1);
572 	printk("\n");
573 
574 	link->state &= ~DEV_CONFIG_PENDING;
575 	return;
576 
577  cs_failed:
578 	cs_error(link->handle, last_fn, last_ret);
579 	atmel_release(link);
580 }
581 
582 /*======================================================================
583 
584   After a card is removed, atmel_release() will unregister the
585   device, and release the PCMCIA configuration.  If the device is
586   still open, this will be postponed until it is closed.
587 
588   ======================================================================*/
589 
atmel_release(dev_link_t * link)590 static void atmel_release(dev_link_t *link)
591 {
592 	struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
593 
594 	DEBUG(0, "atmel_release(0x%p)\n", link);
595 
596 	/* Unlink the device chain */
597 	link->dev = NULL;
598 
599 	if (dev)
600 		stop_atmel_card(dev, 0);
601 	((local_info_t*)link->priv)->eth_dev = 0;
602 
603 	/* Don't bother checking to see if these succeed or not */
604 	CardServices(ReleaseConfiguration, link->handle);
605 	if (link->io.NumPorts1)
606 		CardServices(ReleaseIO, link->handle, &link->io);
607 	if (link->irq.AssignedIRQ)
608 		CardServices(ReleaseIRQ, link->handle, &link->irq);
609 	link->state &= ~DEV_CONFIG;
610 }
611 
612 /*======================================================================
613 
614   The card status event handler.  Mostly, this schedules other
615   stuff to run after an event is received.
616 
617   When a CARD_REMOVAL event is received, we immediately set a
618   private flag to block future accesses to this device.  All the
619   functions that actually access the device should check this flag
620   to make sure the card is still present.
621 
622   ======================================================================*/
623 
atmel_event(event_t event,int priority,event_callback_args_t * args)624 static int atmel_event(event_t event, int priority,
625 		      event_callback_args_t *args)
626 {
627 	dev_link_t *link = args->client_data;
628 	local_info_t *local = link->priv;
629 
630 	DEBUG(1, "atmel_event(0x%06x)\n", event);
631 
632 	switch (event) {
633 	case CS_EVENT_CARD_REMOVAL:
634 		link->state &= ~DEV_PRESENT;
635 		if (link->state & DEV_CONFIG) {
636 			netif_device_detach(local->eth_dev);
637 			atmel_release(link);
638 		}
639 		break;
640 	case CS_EVENT_CARD_INSERTION:
641 		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
642 		atmel_config(link);
643 		break;
644 	case CS_EVENT_PM_SUSPEND:
645 		link->state |= DEV_SUSPEND;
646 		/* Fall through... */
647 	case CS_EVENT_RESET_PHYSICAL:
648 		if (link->state & DEV_CONFIG) {
649 			netif_device_detach(local->eth_dev);
650 			CardServices(ReleaseConfiguration, link->handle);
651 		}
652 		break;
653 	case CS_EVENT_PM_RESUME:
654 		link->state &= ~DEV_SUSPEND;
655 		/* Fall through... */
656 	case CS_EVENT_CARD_RESET:
657 		if (link->state & DEV_CONFIG) {
658 			CardServices(RequestConfiguration, link->handle, &link->conf);
659 			reset_atmel_card(local->eth_dev);
660 			netif_device_attach(local->eth_dev);
661 		}
662 		break;
663 	}
664 	return 0;
665 } /* atmel_event */
666 
atmel_cs_init(void)667 static int atmel_cs_init(void)
668 {
669 	servinfo_t serv;
670 	DEBUG(0, "%s\n", version);
671 	CardServices(GetCardServicesInfo, &serv);
672 	if (serv.Revision != CS_RELEASE_CODE) {
673 		printk(KERN_NOTICE "atmel_cs: Card Services release "
674 		       "does not match!\n");
675 		return -1;
676 	}
677 	register_pcmcia_driver(&dev_info, &atmel_attach, &atmel_detach);
678         return 0;
679 }
680 
atmel_cs_cleanup(void)681 static void atmel_cs_cleanup(void)
682 {
683         unregister_pcmcia_driver(&dev_info);
684 
685         /* XXX: this really needs to move into generic code.. */
686         while (dev_list != NULL) {
687                 if (dev_list->state & DEV_CONFIG)
688                         atmel_release(dev_list);
689                 atmel_detach(dev_list);
690         }
691 }
692 
693 /*
694     This program is free software; you can redistribute it and/or
695     modify it under the terms of the GNU General Public License
696     as published by the Free Software Foundation; either version 2
697     of the License, or (at your option) any later version.
698 
699     This program is distributed in the hope that it will be useful,
700     but WITHOUT ANY WARRANTY; without even the implied warranty of
701     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
702     GNU General Public License for more details.
703 
704     In addition:
705 
706     Redistribution and use in source and binary forms, with or without
707     modification, are permitted provided that the following conditions
708     are met:
709 
710     1. Redistributions of source code must retain the above copyright
711        notice, this list of conditions and the following disclaimer.
712     2. Redistributions in binary form must reproduce the above copyright
713        notice, this list of conditions and the following disclaimer in the
714        documentation and/or other materials provided with the distribution.
715     3. The name of the author may not be used to endorse or promote
716        products derived from this software without specific prior written
717        permission.
718 
719     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
720     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
721     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
722     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
723     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
724     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
725     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
726     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
727     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
728     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
729     POSSIBILITY OF SUCH DAMAGE.
730 */
731 
732 module_init(atmel_cs_init);
733 module_exit(atmel_cs_cleanup);
734