aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pcmcia/com20020_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/pcmcia/com20020_cs.c')
-rw-r--r--drivers/net/pcmcia/com20020_cs.c142
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
121static void com20020_config(dev_link_t *link); 121static void com20020_config(dev_link_t *link);
122static void com20020_release(dev_link_t *link); 122static void com20020_release(dev_link_t *link);
123static int com20020_event(event_t event, int priority,
124 event_callback_args_t *args);
125 123
126static dev_info_t dev_info = "com20020_cs"; 124static void com20020_detach(struct pcmcia_device *p_dev);
127
128static dev_link_t *com20020_attach(void);
129static void com20020_detach(dev_link_t *);
130
131static 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
148static dev_link_t *com20020_attach(void) 141static 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
213fail_alloc_dev: 193fail_alloc_dev:
214 kfree(info); 194 kfree(info);
215fail_alloc_info: 195fail_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
229static void com20020_detach(dev_link_t *link) 209static 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/*====================================================================== 392static 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
433static int com20020_event(event_t event, int priority, 409static 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
480static struct pcmcia_device_id com20020_ids[] = { 428static 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
497static int __init init_com20020_cs(void) 446static int __init init_com20020_cs(void)
@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void)
502static void __exit exit_com20020_cs(void) 451static 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
508module_init(init_com20020_cs); 456module_init(init_com20020_cs);