diff options
Diffstat (limited to 'drivers/net/wireless/atmel_cs.c')
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 156 |
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 | ||
94 | static void atmel_config(dev_link_t *link); | 94 | static void atmel_config(dev_link_t *link); |
95 | static void atmel_release(dev_link_t *link); | 95 | static void atmel_release(dev_link_t *link); |
96 | static 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 | ||
105 | static dev_link_t *atmel_attach(void); | 103 | static void atmel_detach(struct pcmcia_device *p_dev); |
106 | static 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 | |||
121 | static 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 | ||
133 | static 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 | ||
174 | static dev_link_t *atmel_attach(void) | 155 | static 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 | ||
240 | static void atmel_detach(dev_link_t *link) | 212 | static 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 | /*====================================================================== | 440 | static 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 | ||
492 | static int atmel_event(event_t event, int priority, | 454 | static 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 | ||
590 | static int atmel_cs_init(void) | 525 | static int atmel_cs_init(void) |
@@ -595,7 +530,6 @@ static int atmel_cs_init(void) | |||
595 | static void atmel_cs_cleanup(void) | 530 | static 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 | /* |