diff options
Diffstat (limited to 'drivers/net/pcmcia/com20020_cs.c')
-rw-r--r-- | drivers/net/pcmcia/com20020_cs.c | 142 |
1 files changed, 45 insertions, 97 deletions
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index b9355d9498a3..2827a48ea37c 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL"); | |||
120 | 120 | ||
121 | static void com20020_config(dev_link_t *link); | 121 | static void com20020_config(dev_link_t *link); |
122 | static void com20020_release(dev_link_t *link); | 122 | static void com20020_release(dev_link_t *link); |
123 | static int com20020_event(event_t event, int priority, | ||
124 | event_callback_args_t *args); | ||
125 | 123 | ||
126 | static dev_info_t dev_info = "com20020_cs"; | 124 | static void com20020_detach(struct pcmcia_device *p_dev); |
127 | |||
128 | static dev_link_t *com20020_attach(void); | ||
129 | static void com20020_detach(dev_link_t *); | ||
130 | |||
131 | static dev_link_t *dev_list; | ||
132 | 125 | ||
133 | /*====================================================================*/ | 126 | /*====================================================================*/ |
134 | 127 | ||
@@ -145,21 +138,19 @@ typedef struct com20020_dev_t { | |||
145 | 138 | ||
146 | ======================================================================*/ | 139 | ======================================================================*/ |
147 | 140 | ||
148 | static dev_link_t *com20020_attach(void) | 141 | static int com20020_attach(struct pcmcia_device *p_dev) |
149 | { | 142 | { |
150 | client_reg_t client_reg; | ||
151 | dev_link_t *link; | 143 | dev_link_t *link; |
152 | com20020_dev_t *info; | 144 | com20020_dev_t *info; |
153 | struct net_device *dev; | 145 | struct net_device *dev; |
154 | int ret; | ||
155 | struct arcnet_local *lp; | 146 | struct arcnet_local *lp; |
156 | 147 | ||
157 | DEBUG(0, "com20020_attach()\n"); | 148 | DEBUG(0, "com20020_attach()\n"); |
158 | 149 | ||
159 | /* Create new network device */ | 150 | /* Create new network device */ |
160 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 151 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
161 | if (!link) | 152 | if (!link) |
162 | return NULL; | 153 | return -ENOMEM; |
163 | 154 | ||
164 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); | 155 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); |
165 | if (!info) | 156 | if (!info) |
@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void) | |||
191 | link->conf.IntType = INT_MEMORY_AND_IO; | 182 | link->conf.IntType = INT_MEMORY_AND_IO; |
192 | link->conf.Present = PRESENT_OPTION; | 183 | link->conf.Present = PRESENT_OPTION; |
193 | 184 | ||
194 | |||
195 | link->irq.Instance = info->dev = dev; | 185 | link->irq.Instance = info->dev = dev; |
196 | link->priv = info; | 186 | link->priv = info; |
197 | 187 | ||
198 | /* Register with Card Services */ | 188 | link->state |= DEV_PRESENT; |
199 | link->next = dev_list; | 189 | com20020_config(link); |
200 | dev_list = link; | ||
201 | client_reg.dev_info = &dev_info; | ||
202 | client_reg.Version = 0x0210; | ||
203 | client_reg.event_callback_args.client_data = link; | ||
204 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
205 | if (ret != 0) { | ||
206 | cs_error(link->handle, RegisterClient, ret); | ||
207 | com20020_detach(link); | ||
208 | return NULL; | ||
209 | } | ||
210 | 190 | ||
211 | return link; | 191 | return 0; |
212 | 192 | ||
213 | fail_alloc_dev: | 193 | fail_alloc_dev: |
214 | kfree(info); | 194 | kfree(info); |
215 | fail_alloc_info: | 195 | fail_alloc_info: |
216 | kfree(link); | 196 | kfree(link); |
217 | return NULL; | 197 | return -ENOMEM; |
218 | } /* com20020_attach */ | 198 | } /* com20020_attach */ |
219 | 199 | ||
220 | /*====================================================================== | 200 | /*====================================================================== |
@@ -226,29 +206,21 @@ fail_alloc_info: | |||
226 | 206 | ||
227 | ======================================================================*/ | 207 | ======================================================================*/ |
228 | 208 | ||
229 | static void com20020_detach(dev_link_t *link) | 209 | static void com20020_detach(struct pcmcia_device *p_dev) |
230 | { | 210 | { |
211 | dev_link_t *link = dev_to_instance(p_dev); | ||
231 | struct com20020_dev_t *info = link->priv; | 212 | struct com20020_dev_t *info = link->priv; |
232 | dev_link_t **linkp; | 213 | struct net_device *dev = info->dev; |
233 | struct net_device *dev; | 214 | |
234 | |||
235 | DEBUG(1,"detach...\n"); | 215 | DEBUG(1,"detach...\n"); |
236 | 216 | ||
237 | DEBUG(0, "com20020_detach(0x%p)\n", link); | 217 | DEBUG(0, "com20020_detach(0x%p)\n", link); |
238 | 218 | ||
239 | /* Locate device structure */ | ||
240 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
241 | if (*linkp == link) break; | ||
242 | if (*linkp == NULL) | ||
243 | return; | ||
244 | |||
245 | dev = info->dev; | ||
246 | |||
247 | if (link->dev) { | 219 | if (link->dev) { |
248 | DEBUG(1,"unregister...\n"); | 220 | DEBUG(1,"unregister...\n"); |
249 | 221 | ||
250 | unregister_netdev(dev); | 222 | unregister_netdev(dev); |
251 | 223 | ||
252 | /* | 224 | /* |
253 | * this is necessary because we register our IRQ separately | 225 | * this is necessary because we register our IRQ separately |
254 | * from card services. | 226 | * from card services. |
@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link) | |||
260 | if (link->state & DEV_CONFIG) | 232 | if (link->state & DEV_CONFIG) |
261 | com20020_release(link); | 233 | com20020_release(link); |
262 | 234 | ||
263 | if (link->handle) | ||
264 | pcmcia_deregister_client(link->handle); | ||
265 | |||
266 | /* Unlink device structure, free bits */ | 235 | /* Unlink device structure, free bits */ |
267 | DEBUG(1,"unlinking...\n"); | 236 | DEBUG(1,"unlinking...\n"); |
268 | *linkp = link->next; | ||
269 | if (link->priv) | 237 | if (link->priv) |
270 | { | 238 | { |
271 | dev = info->dev; | 239 | dev = info->dev; |
@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link) | |||
421 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); | 389 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); |
422 | } | 390 | } |
423 | 391 | ||
424 | /*====================================================================== | 392 | static int com20020_suspend(struct pcmcia_device *p_dev) |
393 | { | ||
394 | dev_link_t *link = dev_to_instance(p_dev); | ||
395 | com20020_dev_t *info = link->priv; | ||
396 | struct net_device *dev = info->dev; | ||
425 | 397 | ||
426 | The card status event handler. Mostly, this schedules other | 398 | link->state |= DEV_SUSPEND; |
427 | stuff to run after an event is received. A CARD_REMOVAL event | 399 | if (link->state & DEV_CONFIG) { |
428 | also sets some flags to discourage the net drivers from trying | 400 | if (link->open) { |
429 | to talk to the card any more. | 401 | netif_device_detach(dev); |
402 | } | ||
403 | pcmcia_release_configuration(link->handle); | ||
404 | } | ||
430 | 405 | ||
431 | ======================================================================*/ | 406 | return 0; |
407 | } | ||
432 | 408 | ||
433 | static int com20020_event(event_t event, int priority, | 409 | static int com20020_resume(struct pcmcia_device *p_dev) |
434 | event_callback_args_t *args) | ||
435 | { | 410 | { |
436 | dev_link_t *link = args->client_data; | 411 | dev_link_t *link = dev_to_instance(p_dev); |
437 | com20020_dev_t *info = link->priv; | 412 | com20020_dev_t *info = link->priv; |
438 | struct net_device *dev = info->dev; | 413 | struct net_device *dev = info->dev; |
439 | 414 | ||
440 | DEBUG(1, "com20020_event(0x%06x)\n", event); | 415 | link->state &= ~DEV_SUSPEND; |
441 | |||
442 | switch (event) { | ||
443 | case CS_EVENT_CARD_REMOVAL: | ||
444 | link->state &= ~DEV_PRESENT; | ||
445 | if (link->state & DEV_CONFIG) | ||
446 | netif_device_detach(dev); | ||
447 | break; | ||
448 | case CS_EVENT_CARD_INSERTION: | ||
449 | link->state |= DEV_PRESENT; | ||
450 | com20020_config(link); | ||
451 | break; | ||
452 | case CS_EVENT_PM_SUSPEND: | ||
453 | link->state |= DEV_SUSPEND; | ||
454 | /* Fall through... */ | ||
455 | case CS_EVENT_RESET_PHYSICAL: | ||
456 | if (link->state & DEV_CONFIG) { | ||
457 | if (link->open) { | ||
458 | netif_device_detach(dev); | ||
459 | } | ||
460 | pcmcia_release_configuration(link->handle); | ||
461 | } | ||
462 | break; | ||
463 | case CS_EVENT_PM_RESUME: | ||
464 | link->state &= ~DEV_SUSPEND; | ||
465 | /* Fall through... */ | ||
466 | case CS_EVENT_CARD_RESET: | ||
467 | if (link->state & DEV_CONFIG) { | 416 | if (link->state & DEV_CONFIG) { |
468 | pcmcia_request_configuration(link->handle, &link->conf); | 417 | pcmcia_request_configuration(link->handle, &link->conf); |
469 | if (link->open) { | 418 | if (link->open) { |
470 | int ioaddr = dev->base_addr; | 419 | int ioaddr = dev->base_addr; |
471 | struct arcnet_local *lp = dev->priv; | 420 | struct arcnet_local *lp = dev->priv; |
472 | ARCRESET; | 421 | ARCRESET; |
473 | } | 422 | } |
474 | } | 423 | } |
475 | break; | 424 | |
476 | } | 425 | return 0; |
477 | return 0; | 426 | } |
478 | } /* com20020_event */ | ||
479 | 427 | ||
480 | static struct pcmcia_device_id com20020_ids[] = { | 428 | static struct pcmcia_device_id com20020_ids[] = { |
481 | PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), | 429 | PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), |
@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = { | |||
488 | .drv = { | 436 | .drv = { |
489 | .name = "com20020_cs", | 437 | .name = "com20020_cs", |
490 | }, | 438 | }, |
491 | .attach = com20020_attach, | 439 | .probe = com20020_attach, |
492 | .event = com20020_event, | 440 | .remove = com20020_detach, |
493 | .detach = com20020_detach, | ||
494 | .id_table = com20020_ids, | 441 | .id_table = com20020_ids, |
442 | .suspend = com20020_suspend, | ||
443 | .resume = com20020_resume, | ||
495 | }; | 444 | }; |
496 | 445 | ||
497 | static int __init init_com20020_cs(void) | 446 | static int __init init_com20020_cs(void) |
@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void) | |||
502 | static void __exit exit_com20020_cs(void) | 451 | static void __exit exit_com20020_cs(void) |
503 | { | 452 | { |
504 | pcmcia_unregister_driver(&com20020_cs_driver); | 453 | pcmcia_unregister_driver(&com20020_cs_driver); |
505 | BUG_ON(dev_list != NULL); | ||
506 | } | 454 | } |
507 | 455 | ||
508 | module_init(init_com20020_cs); | 456 | module_init(init_com20020_cs); |