aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/atmel_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/atmel_cs.c')
-rw-r--r--drivers/net/wireless/atmel_cs.c156
1 files changed, 45 insertions, 111 deletions
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 17d1fd90f832..d6f4a5a3e55a 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -93,8 +93,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
93 93
94static void atmel_config(dev_link_t *link); 94static void atmel_config(dev_link_t *link);
95static void atmel_release(dev_link_t *link); 95static void atmel_release(dev_link_t *link);
96static int atmel_event(event_t event, int priority,
97 event_callback_args_t *args);
98 96
99/* 97/*
100 The attach() and detach() entry points are used to create and destroy 98 The attach() and detach() entry points are used to create and destroy
@@ -102,8 +100,7 @@ static int atmel_event(event_t event, int priority,
102 needed to manage one actual PCMCIA card. 100 needed to manage one actual PCMCIA card.
103*/ 101*/
104 102
105static dev_link_t *atmel_attach(void); 103static void atmel_detach(struct pcmcia_device *p_dev);
106static void atmel_detach(dev_link_t *);
107 104
108/* 105/*
109 You'll also need to prototype all the functions that will actually 106 You'll also need to prototype all the functions that will actually
@@ -113,14 +110,6 @@ static void atmel_detach(dev_link_t *);
113*/ 110*/
114 111
115/* 112/*
116 The dev_info variable is the "key" that is used to match up this
117 device driver with appropriate cards, through the card configuration
118 database.
119*/
120
121static dev_info_t dev_info = "atmel_cs";
122
123/*
124 A linked list of "instances" of the atmelnet device. Each actual 113 A linked list of "instances" of the atmelnet device. Each actual
125 PCMCIA card corresponds to one device instance, and is described 114 PCMCIA card corresponds to one device instance, and is described
126 by one dev_link_t structure (defined in ds.h). 115 by one dev_link_t structure (defined in ds.h).
@@ -130,15 +119,7 @@ static dev_info_t dev_info = "atmel_cs";
130 device numbers are used to derive the corresponding array index. 119 device numbers are used to derive the corresponding array index.
131*/ 120*/
132 121
133static dev_link_t *dev_list = NULL;
134
135/* 122/*
136 A dev_link_t structure has fields for most things that are needed
137 to keep track of a socket, but there will usually be some device
138 specific information that also needs to be kept track of. The
139 'priv' pointer in a dev_link_t structure can be used to point to
140 a device-specific private data structure, like this.
141
142 A driver needs to provide a dev_node_t structure for each device 123 A driver needs to provide a dev_node_t structure for each device
143 on a card. In some cases, there is only one device per card (for 124 on a card. In some cases, there is only one device per card (for
144 example, ethernet cards, modems). In other cases, there may be 125 example, ethernet cards, modems). In other cases, there may be
@@ -171,27 +152,25 @@ typedef struct local_info_t {
171 152
172 ======================================================================*/ 153 ======================================================================*/
173 154
174static dev_link_t *atmel_attach(void) 155static int atmel_attach(struct pcmcia_device *p_dev)
175{ 156{
176 client_reg_t client_reg;
177 dev_link_t *link; 157 dev_link_t *link;
178 local_info_t *local; 158 local_info_t *local;
179 int ret; 159
180
181 DEBUG(0, "atmel_attach()\n"); 160 DEBUG(0, "atmel_attach()\n");
182 161
183 /* Initialize the dev_link_t structure */ 162 /* Initialize the dev_link_t structure */
184 link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); 163 link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
185 if (!link) { 164 if (!link) {
186 printk(KERN_ERR "atmel_cs: no memory for new device\n"); 165 printk(KERN_ERR "atmel_cs: no memory for new device\n");
187 return NULL; 166 return -ENOMEM;
188 } 167 }
189 168
190 /* Interrupt setup */ 169 /* Interrupt setup */
191 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 170 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
192 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 171 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
193 link->irq.Handler = NULL; 172 link->irq.Handler = NULL;
194 173
195 /* 174 /*
196 General socket configuration defaults can go here. In this 175 General socket configuration defaults can go here. In this
197 client, we assume very little, and rely on the CIS for almost 176 client, we assume very little, and rely on the CIS for almost
@@ -202,30 +181,23 @@ static dev_link_t *atmel_attach(void)
202 link->conf.Attributes = 0; 181 link->conf.Attributes = 0;
203 link->conf.Vcc = 50; 182 link->conf.Vcc = 50;
204 link->conf.IntType = INT_MEMORY_AND_IO; 183 link->conf.IntType = INT_MEMORY_AND_IO;
205 184
206 /* Allocate space for private device-specific data */ 185 /* Allocate space for private device-specific data */
207 local = kzalloc(sizeof(local_info_t), GFP_KERNEL); 186 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
208 if (!local) { 187 if (!local) {
209 printk(KERN_ERR "atmel_cs: no memory for new device\n"); 188 printk(KERN_ERR "atmel_cs: no memory for new device\n");
210 kfree (link); 189 kfree (link);
211 return NULL; 190 return -ENOMEM;
212 } 191 }
213 link->priv = local; 192 link->priv = local;
214 193
215 /* Register with Card Services */ 194 link->handle = p_dev;
216 link->next = dev_list; 195 p_dev->instance = link;
217 dev_list = link; 196
218 client_reg.dev_info = &dev_info; 197 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
219 client_reg.Version = 0x0210; 198 atmel_config(link);
220 client_reg.event_callback_args.client_data = link; 199
221 ret = pcmcia_register_client(&link->handle, &client_reg); 200 return 0;
222 if (ret != 0) {
223 cs_error(link->handle, RegisterClient, ret);
224 atmel_detach(link);
225 return NULL;
226 }
227
228 return link;
229} /* atmel_attach */ 201} /* atmel_attach */
230 202
231/*====================================================================== 203/*======================================================================
@@ -237,27 +209,15 @@ static dev_link_t *atmel_attach(void)
237 209
238 ======================================================================*/ 210 ======================================================================*/
239 211
240static void atmel_detach(dev_link_t *link) 212static void atmel_detach(struct pcmcia_device *p_dev)
241{ 213{
242 dev_link_t **linkp; 214 dev_link_t *link = dev_to_instance(p_dev);
243 215
244 DEBUG(0, "atmel_detach(0x%p)\n", link); 216 DEBUG(0, "atmel_detach(0x%p)\n", link);
245
246 /* Locate device structure */
247 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
248 if (*linkp == link) break;
249 if (*linkp == NULL)
250 return;
251 217
252 if (link->state & DEV_CONFIG) 218 if (link->state & DEV_CONFIG)
253 atmel_release(link); 219 atmel_release(link);
254
255 /* Break the link with Card Services */
256 if (link->handle)
257 pcmcia_deregister_client(link->handle);
258 220
259 /* Unlink device structure, free pieces */
260 *linkp = link->next;
261 kfree(link->priv); 221 kfree(link->priv);
262 kfree(link); 222 kfree(link);
263} 223}
@@ -477,60 +437,34 @@ static void atmel_release(dev_link_t *link)
477 link->state &= ~DEV_CONFIG; 437 link->state &= ~DEV_CONFIG;
478} 438}
479 439
480/*====================================================================== 440static int atmel_suspend(struct pcmcia_device *dev)
481 441{
482 The card status event handler. Mostly, this schedules other 442 dev_link_t *link = dev_to_instance(dev);
483 stuff to run after an event is received. 443 local_info_t *local = link->priv;
484 444
485 When a CARD_REMOVAL event is received, we immediately set a 445 link->state |= DEV_SUSPEND;
486 private flag to block future accesses to this device. All the 446 if (link->state & DEV_CONFIG) {
487 functions that actually access the device should check this flag 447 netif_device_detach(local->eth_dev);
488 to make sure the card is still present. 448 pcmcia_release_configuration(link->handle);
489 449 }
490 ======================================================================*/ 450
451 return 0;
452}
491 453
492static int atmel_event(event_t event, int priority, 454static int atmel_resume(struct pcmcia_device *dev)
493 event_callback_args_t *args)
494{ 455{
495 dev_link_t *link = args->client_data; 456 dev_link_t *link = dev_to_instance(dev);
496 local_info_t *local = link->priv; 457 local_info_t *local = link->priv;
497 458
498 DEBUG(1, "atmel_event(0x%06x)\n", event); 459 link->state &= ~DEV_SUSPEND;
499 460 if (link->state & DEV_CONFIG) {
500 switch (event) { 461 pcmcia_request_configuration(link->handle, &link->conf);
501 case CS_EVENT_CARD_REMOVAL: 462 atmel_open(local->eth_dev);
502 link->state &= ~DEV_PRESENT; 463 netif_device_attach(local->eth_dev);
503 if (link->state & DEV_CONFIG) {
504 netif_device_detach(local->eth_dev);
505 atmel_release(link);
506 }
507 break;
508 case CS_EVENT_CARD_INSERTION:
509 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
510 atmel_config(link);
511 break;
512 case CS_EVENT_PM_SUSPEND:
513 link->state |= DEV_SUSPEND;
514 /* Fall through... */
515 case CS_EVENT_RESET_PHYSICAL:
516 if (link->state & DEV_CONFIG) {
517 netif_device_detach(local->eth_dev);
518 pcmcia_release_configuration(link->handle);
519 }
520 break;
521 case CS_EVENT_PM_RESUME:
522 link->state &= ~DEV_SUSPEND;
523 /* Fall through... */
524 case CS_EVENT_CARD_RESET:
525 if (link->state & DEV_CONFIG) {
526 pcmcia_request_configuration(link->handle, &link->conf);
527 atmel_open(local->eth_dev);
528 netif_device_attach(local->eth_dev);
529 }
530 break;
531 } 464 }
465
532 return 0; 466 return 0;
533} /* atmel_event */ 467}
534 468
535/*====================================================================*/ 469/*====================================================================*/
536/* We use the driver_info field to store the correct firmware type for a card. */ 470/* We use the driver_info field to store the correct firmware type for a card. */
@@ -581,10 +515,11 @@ static struct pcmcia_driver atmel_driver = {
581 .drv = { 515 .drv = {
582 .name = "atmel_cs", 516 .name = "atmel_cs",
583 }, 517 },
584 .attach = atmel_attach, 518 .probe = atmel_attach,
585 .event = atmel_event, 519 .remove = atmel_detach,
586 .detach = atmel_detach,
587 .id_table = atmel_ids, 520 .id_table = atmel_ids,
521 .suspend = atmel_suspend,
522 .resume = atmel_resume,
588}; 523};
589 524
590static int atmel_cs_init(void) 525static int atmel_cs_init(void)
@@ -595,7 +530,6 @@ static int atmel_cs_init(void)
595static void atmel_cs_cleanup(void) 530static void atmel_cs_cleanup(void)
596{ 531{
597 pcmcia_unregister_driver(&atmel_driver); 532 pcmcia_unregister_driver(&atmel_driver);
598 BUG_ON(dev_list != NULL);
599} 533}
600 534
601/* 535/*