skeleton.c
来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 696 行 · 第 1/2 页
C
696 行
** Remove one of the device instances managed by this driver.* Search the list for the given instance, * check our flags for a waiting timer'd release call* call release* Deregister the instance with Card Services* (netdevice) unregister the network device.* unlink the instance from the list* free the link, priv, and priv->priv memory* Note: the dev_list variable is a driver scoped static used to* maintain a list of device instances managed by this* driver.** Arguments:* link ptr to the instance to detach** Returns: * nothing** Side effects:* the link structure is gone, the netdevice is gone** Call context:* Might be interrupt, don't block.----------------------------------------------------------------*/#if 0void wlanskel_detach(dev_link_t *link){ dev_link_t **linkp; UINT32 flags; wlandevice_t *wlandev; DBFENTER; /* Locate device structure */ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { if (*linkp == link) break; } if (*linkp != NULL) { /* Get rid of any timer'd release call */ save_flags(flags); cli(); if (link->state & DEV_RELEASE_PENDING) { del_timer(&link->release); link->state &= ~DEV_RELEASE_PENDING; } restore_flags(flags); /* If link says we're still config'd, call release */ if (link->state & DEV_CONFIG) { wlanskel_release((u_long)link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; } } /* Tell Card Services we're not around any more */ if (link->handle) { CardServices(DeregisterClient, link->handle); } /* Unlink device structure, free bits */ *linkp = link->next; if ( link->priv != NULL ) { wlandev = (wlandevice_t*)link->priv; if (link->dev != NULL) { unregister_wlandev(wlandev); } wlan_unsetup(wlandev); if (wlandev->priv) { kfree_s(wlandev->priv, sizeof(skelpriv_t)); } kfree_s(link->priv, sizeof(wlandevice_t)); } kfree_s(link, sizeof(struct dev_link_t)); } DBFEXIT; return;}#endif/*----------------------------------------------------------------* wlanskel_config** Half of the config/release pair. Usually called in response to* a card insertion event. At this point, we _know_ there's some* physical device present. That means we can start poking around* at the CIS and at any device specific config data we want.** Note the gotos and the macros. I recoded this once without* them, and it got incredibly ugly. It's actually simpler with* them.** Arguments:* link the dev_link_t structure created in attach that * represents this device instance.** Returns: * nothing** Side effects:* Resources (irq, io, mem) are allocated* The pcmcia dev_link->node->name is set* (For netcards) The device structure is finished and,* most importantly, registered. This means that there* is now a _named_ device that can be configured from* userland.** Call context:* May be called from a timer. Don't block!----------------------------------------------------------------*/#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failedvoid wlanskel_config(dev_link_t *link){ client_handle_t handle; wlandevice_t *wlandev; skelpriv_t *skelpriv; #if 0 int last_fn; int last_ret; tuple_t tuple; cisparse_t parse; UINT16 buf[32]; int i; int j; int ioaddr; char *cardname; #endif DBFENTER; handle = link->handle; wlandev = (wlandevice_t*)link->priv; /* Initialize the CIS parse */ #if 0 tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, handle, &tuple); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, handle, &tuple, &parse); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; #endif /* Configure card */ link->state |= DEV_CONFIG; #if 0 for (i = j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { cs_error(link->handle, RequestIO, i); goto failed; } CS_CHECK(RequestIRQ, link->handle, &link->irq); CS_CHECK(RequestConfiguration, link->handle, &link->conf); #endif wlandev->irq = 0; /* link->irq.AssignedIRQ; */ wlandev->iobase = 0; /* link->io.BasePort1; */ /* Register the network device and get assigned a name */ if (register_wlandev(wlandev) != 0) { WLAN_LOG_NOTICE0("wlanskel_cs: register_wlandev() failed.\n"); goto failed; } link->state &= ~DEV_CONFIG_PENDING; skelpriv = (skelpriv_t*)wlandev->priv; /* collect the device priv ptr */ link->dev = &skelpriv->node; /* now pcmcia knows the device name */ /* Any device custom config/query stuff should be done here */ /* For a netdevice, we should at least grab the mac address */ return;#if 0cs_failed: cs_error(link->handle, last_fn, last_ret);#endiffailed: wlanskel_release((UINT32)link); return;}/*----------------------------------------------------------------* wlanskel_release** Half of the config/release pair. Usually called in response to * a card ejection event. Checks to make sure no higher layers* are still (or think they are) using the card via the link->open* field. ** NOTE: Don't forget to increment the link->open variable in the * device_open method, and decrement it in the device_close * method.** Arguments:* arg a generic 32 bit variable...we assume it's a * ptr to a dev_link.** Returns: * nothing** Side effects:* All resources should be released after this function* executes and finds the device !open.** Call context:* Possibly in a timer context. Don't do anything that'll* block.----------------------------------------------------------------*/void wlanskel_release(UINT32 arg){ dev_link_t *link = (dev_link_t *)arg; DBFENTER; if (link->open) { WLAN_LOG_DEBUG1(1, "wlanskel_cs: release postponed, '%s' still open\n", link->dev->dev_name); link->state |= DEV_STALE_CONFIG; return; } /* CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); if (link->win) { iounmap((void *)(dev->mem_start - 0x800)); CardServices(ReleaseWindow, link->win); } */ link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); DBFEXIT;}/*----------------------------------------------------------------* init_module** Module initialization routine, called once at module load time.* This one simulates some of the pcmcia calls.** Arguments:* none** Returns: * 0 - success * ~0 - failure, module is unloaded.** Side effects:* TODO: define** Call context:* process thread (insmod or modprobe)----------------------------------------------------------------*/int init_module(void){ int result = 0; dev_link_t *link; DBFENTER; WLAN_LOG_NOTICE1("%s Loaded\n", version); WLAN_LOG_NOTICE1("dev_info is: %s\n", dev_info); /* register_driver( &dev_info, &wlanskel_attach, &wlanskel_detach */ /* simulated with call to wlanskel_attach */ if ((link = wlanskel_attach()) == NULL ) { result = 1; } else { /* After attach finishes, pcmcia-cs usually calls */ /* the wlanskel_event function signaling an INSERT */ /* event This results in a call to the driver defined*/ /* wlanskel_config function. We'll just call it. */ wlanskel_config(link); } DBFEXIT; return result;}/*----------------------------------------------------------------* cleanup_module** Called at module unload time. This is our last chance to* clean up after ourselves.** Arguments:* none** Returns: * nothing** Side effects:* TODO: define** Call context:* process thread*----------------------------------------------------------------*/void cleanup_module(void){ dev_link_t *link = dev_list; wlandevice_t *wlandev = (wlandevice_t *)link->priv; DBFENTER; if (link->dev != NULL) { unregister_wlandev(wlandev); } wlan_unsetup(wlandev); if (wlandev->priv) { kfree_s(wlandev->priv, sizeof(skelpriv_t)); } kfree_s(wlandev, sizeof(wlandevice_t)); kfree_s(link, sizeof(struct dev_link_t)); printk(KERN_NOTICE "%s Unloaded\n", version); DBFEXIT; return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?