📄 com20020_cs.c
字号:
DEBUG(0, "com20020_detach(0x%p)\n", link); /* Locate device structure */ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) if (*linkp == link) break; if (*linkp == NULL) return; dev = info->dev; if (link->state & DEV_CONFIG) { com20020_release((u_long)link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; } } if (link->handle) CardServices(DeregisterClient, link->handle); /* Unlink device structure, free bits */ DEBUG(1,"unlinking...\n"); *linkp = link->next; if (link->priv) { dev = info->dev; if (dev) { if (info->dev_configured) { DEBUG(1,"unregister...\n"); if (netif_running(dev)) dev->stop(dev); /* * this is necessary because we register our IRQ separately * from card services. */ if (dev->irq) free_irq(dev->irq, dev); /* ...but I/O ports are done automatically by card services */ unregister_netdev(dev); MOD_DEC_USE_COUNT; } DEBUG(1,"kfree...\n"); kfree(dev->priv); kfree(dev); } DEBUG(1,"kfree2...\n"); kfree(info); } DEBUG(1,"kfree3...\n"); kfree(link);} /* com20020_detach *//*====================================================================== com20020_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the device available to the system.======================================================================*/#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failedstatic void com20020_config(dev_link_t *link){ struct arcnet_local *lp; client_handle_t handle; tuple_t tuple; cisparse_t parse; com20020_dev_t *info; struct net_device *dev; int i, last_ret, last_fn; u_char buf[64]; int ioaddr; handle = link->handle; info = link->priv; dev = info->dev; DEBUG(1,"config...\n"); DEBUG(0, "com20020_config(0x%p)\n", link); tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, handle, &tuple); CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, handle, &tuple, &parse); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; strcpy(info->node.dev_name, dev->name); DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); i = !CS_SUCCESS; if (!link->io.BasePort1) { for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) break; } } else i = CardServices(RequestIO, link->handle, &link->io); if (i != CS_SUCCESS) { DEBUG(1,"arcnet: requestIO failed totally!\n"); goto failed; } ioaddr = dev->base_addr = link->io.BasePort1; DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr); DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", link->irq.AssignedIRQ, link->irq.IRQInfo1, link->irq.IRQInfo2); i = CardServices(RequestIRQ, link->handle, &link->irq); if (i != CS_SUCCESS) { DEBUG(1,"arcnet: requestIRQ failed totally!\n"); goto failed; } dev->irq = link->irq.AssignedIRQ; CS_CHECK(RequestConfiguration, link->handle, &link->conf); if (com20020_check(dev)) { regdump(dev); goto failed; } MOD_INC_USE_COUNT; lp = dev->priv; lp->card_name = "PCMCIA COM20020"; lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ i = com20020_found(dev, 0); if (i != 0) { DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); goto failed; } info->dev_configured = 1; link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", dev->name, dev->base_addr, dev->irq); return;cs_failed: cs_error(link->handle, last_fn, last_ret);failed: DEBUG(1,"com20020_config failed...\n"); com20020_release((u_long)link);} /* com20020_config *//*====================================================================== After a card is removed, com20020_release() will unregister the net device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed.======================================================================*/static void com20020_release(u_long arg){ dev_link_t *link = (dev_link_t *)arg; DEBUG(1,"release...\n"); DEBUG(0, "com20020_release(0x%p)\n", link); if (link->open) { DEBUG(1,"postpone...\n"); DEBUG(1, "com20020_cs: release postponed, device stll open\n"); link->state |= DEV_STALE_CONFIG; return; } CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);} /* com20020_release *//*====================================================================== The card status event handler. Mostly, this schedules other stuff to run after an event is received. A CARD_REMOVAL event also sets some flags to discourage the net drivers from trying to talk to the card any more.======================================================================*/static int com20020_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; DEBUG(1, "com20020_event(0x%06x)\n", event); switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { netif_device_detach(dev); link->release.expires = jiffies + HZ/20; link->state |= DEV_RELEASE_PENDING; add_timer(&link->release); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT; com20020_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { netif_device_detach(dev); } CardServices(ReleaseConfiguration, link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { int ioaddr = dev->base_addr; struct arcnet_local *lp = (struct arcnet_local *)dev->priv; ARCRESET; } } break; } return 0;} /* com20020_event *//*====================================================================*/static int __init init_com20020_cs(void){ servinfo_t serv; DEBUG(0, "%s\n", VERSION); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "com20020_cs: Card Services release " "does not match!\n"); return -1; } register_pccard_driver(&dev_info, &com20020_attach, &com20020_detach); return 0;}static void __exit exit_com20020_cs(void){ DEBUG(0, "com20020_cs: unloading\n"); unregister_pccard_driver(&dev_info); while (dev_list != NULL) com20020_detach(dev_list);}module_init(init_com20020_cs);module_exit(exit_com20020_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -