📄 am930di.c
字号:
/* am930_di.c : Handles the PCMCIA "device instance" functions* --------------------------------------------------------------------** Linux WLAN ** The contents of this file are subject to the Mozilla Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.mozilla.org/MPL/** Software distributed under the License is distributed on an "AS* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The initial developer of the original code is Mark S. Mathews* <mark@absoval.com>. Portions created by Mark S. Mathews* are Copyright (C) 1998 AbsoluteValue Software, Inc. All Rights Reserved.* * --------------------------------------------------------------------** The author may be reached as mark@absoval.com, or C/O AbsoluteValue* Software Inc., P.O. Box 941149, Maitland, FL, 32794-1149** Thanks to David Hinds, Donald Becker, and the rest of the Linux* developers worldwide for making all of this possible.** --------------------------------------------------------------------** PCMCIA "device Instance" ** The functions in this file are responsible for dealing with the* life of a PCMCIA card. This involves dealing with the PCMCIA elements* of the card itself and dealing with socket, driver, and card services.**/#if defined(__LINUX_WLAN__)/* The following prevents "kernel_version" from being set in this file. */#define __NO_VERSION__/* PCMCIA headers generated during PCMCIA package installation */#include <pcmcia/config.h>#include <pcmcia/k_compat.h>/* Module related headers, non-module drivers should not include */#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>/* Ethernet and network includes */#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>/* Standard driver includes */#include <linux/delay.h>#include <linux/types.h>#include <linux/fcntl.h>#include <asm/system.h>#include <asm/io.h>#include <linux/ptrace.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/timer.h>#include <asm/bitops.h>#include <linux/errno.h>/* Card and Driver services includes */#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include <pcmcia/cisreg.h>#endif/* Local Includes */#include <wlan/version.h>#include <wlan/wlan_compat.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include "am930di.h"#include "am930llc.h"#include "am930mac.h"#include "am930hw.h"#if (LINUX_VERSION_CODE < VERSION(2,2,0))# define ioremap_nocache ioremap#endif/*================================================================*//* Local macros *//*================================================================*//* Local prototypes */static void am930DI_interrupt (int irq, void * dev_id, struct pt_regs *regs );static int am930DI_config(dev_link_t *instance, UINT32 *pMemBase);static int am930DI_deconfig(dev_link_t *instance);/*================================================================*//* Local statics (lifetime not scope) *//* Driver name, must match the name in the PCMCIA database */dev_info_t am930_driver_name = "am930_cs";/*----------------------------------------------------------------* am930DI_construct** Device constructor, contains alot of the code commonly found * in other pcmcia driver's "attach" function.** The function first allocates an "instance" structure, then * zeros it. Then the RegisterClient Card Services call is * set up and done. Note that we register for ALL of the * Card Services events at this point. Therefore, the event* handler must be coded to deal with ALL of them.** returns: nothing----------------------------------------------------------------*/dev_link_t* am930DI_construct(void){ dev_link_t *instance; client_reg_t client_reg; int ret = 0; DBFENTER; /* Allocate the instance */ instance = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if ( instance != NULL ) { /* zero the instance members */ memset(instance, 0, sizeof(struct dev_link_t)); /* remaining initialization of instance will be done */ /* in the config function */ /*---------- Register with Card Services ---------------------*/ /* Set up the client registration function */ client_reg.dev_info = &am930_driver_name; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = /* client services */ CS_EVENT_REGISTRATION_COMPLETE | /* host battery */ CS_EVENT_BATTERY_LOW | CS_EVENT_BATTERY_DEAD | /* insertion/removal */ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | /* reset */ CS_EVENT_RESET_REQUEST | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_RESET_COMPLETE | /* power management */ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME ; client_reg.event_handler = &am930DI_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = instance; /* allocate the device node */ instance->dev = kmalloc( sizeof(dev_node_t), GFP_KERNEL ); if ( instance->dev == NULL ) { WLAN_LOG_ERROR0("dev_node_t allocation failed!\n"); am930DI_destruct( instance ); instance = NULL; } else { memset( instance->dev, 0, sizeof(dev_node_t) ); ret = CardServices(RegisterClient, &instance->handle, &client_reg); if (ret != 0) { am930_drvr_cs_error(instance->handle, RegisterClient, ret); kfree_s( instance->dev, sizeof(struct dev_node_t)); kfree_s( instance, sizeof(struct dev_link_t)); instance = NULL; } } } DBFEXIT; return instance;} /*----------------------------------------------------------------* am930DI_destruct** Destructor for the device instance object. This function * roughly corresponds to the "xxx_release" function described for* pcmcia drivers.** This function first check to see if the Linux device corresponding* to this pcmcia device instance is still open,* if so, then we mark the instance as having a STALE configuration* and bail, hoping that this function will be called again later.* If the device is not open (closed? ;-) ), 1st we call the* call the destructors of the subobjects, then we call the * deconfig method to release all of the resources allocated when* this instance was configured. Then, we check to see if the* driver object's detach function wants to be called (indicated* by STALE_LINK) and if so, call it. After the detach function is* called, the structure representing this instance no longer exists* and should not be referenced.** returns: nothing----------------------------------------------------------------*/void am930DI_destruct(dev_link_t *instance){ DBFENTER; if ( instance->open ) { WLAN_LOG_DEBUG1(2, "inst 0x%x still open, destruct (release) deferred.\n", (UINT)instance); instance->state |= DEV_STALE_CONFIG; } else { am930mac_t *mac; /* Destroy the subobjects */ mac = (am930mac_t*)instance->priv; if ( mac != NULL ) { am930mac_destruct(mac); } am930DI_deconfig(instance); /* check to see if drvr_detach has been called previously and expects to be called again. */ if ( instance->state & DEV_STALE_LINK ) { am930_drvr_detach(instance); } if (instance->dev != NULL ) { kfree_s( instance->dev, sizeof(dev_node_t)); instance->dev = NULL; } /* instance memory is kfree'd in am930cs_detach */ } DBFEXIT; return;}/*----------------------------------------------------------------* am930DI_event** Responsible for dispatching and/or scheduling the handling of* PCMCIA events. * Events and the responses:* CS_EVENT_REGISTRATION_COMPLETE* in debug, log the event, otherwise nothing.* CS_EVENT_BATTERY_LOW* currently unsupported.* CS_EVENT_BATTERY_DEAD* currently unsupported.* CS_EVENT_CARD_INSERTION* call the DI_config method to configure the interface* to the device and get the ball rolling on the * OS interface.* CS_EVENT_CARD_REMOVAL* schedule a delayed run of the destructor, delayed* because the event handler can't wait for the destructor* to complete, we must return immediately.* CS_EVENT_RESET_REQUEST * CS_EVENT_RESET_PHYSICAL* CS_EVENT_CARD_RESET* CS_EVENT_RESET_COMPLETE* CS_EVENT_PM_SUSPEND * CS_EVENT_PM_RESUME* all unsupported, but logged in debug** returns: zero----------------------------------------------------------------*/int am930DI_event( event_t event, int priority, event_callback_args_t *args){ dev_link_t *instance = args->client_data; DBFENTER; switch (event) { case CS_EVENT_REGISTRATION_COMPLETE: WLAN_LOG_DEBUG1(2, "CS_EVENT_REGISTRATION_COMPLETE event, instance %x\n", (UINT)instance); break; case CS_EVENT_CARD_INSERTION: WLAN_LOG_DEBUG1(2, "CS_EVENT_CARD_INSERTION event, instance %x\n", (UINT)instance); instance->state |= DEV_PRESENT | DEV_CONFIG_PENDING; { UINT32 membase = 0; /* temp to hold membase from config */ if ( am930DI_config(instance, &membase) == AM930DI_SUCCESS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -