hfa384x_usb.c
来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 2,513 行 · 第 1/5 页
C
2,513 行
/* src/prism2/driver/hfa384x_usb.c** Functions that talk to the USB variantof the Intersil hfa384x MAC** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.* --------------------------------------------------------------------** linux-wlan** The contents of this file are subject to the Mozilla Public* License Version 1.1 (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.** Alternatively, the contents of this file may be used under the* terms of the GNU Public License version 2 (the "GPL"), in which* case the provisions of the GPL are applicable instead of the* above. If you wish to allow the use of your version of this file* only under the terms of the GPL and not to allow others to use* your version of this file under the MPL, indicate your decision* by deleting the provisions above and replace them with the notice* and other provisions required by the GPL. If you do not delete* the provisions above, a recipient may use your version of this* file under either the MPL or the GPL.** --------------------------------------------------------------------** Inquiries regarding the linux-wlan Open Source project can be* made directly to:** AbsoluteValue Systems Inc.* info@linux-wlan.com* http://www.linux-wlan.com** --------------------------------------------------------------------** Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development.** --------------------------------------------------------------------** This file implements functions that correspond to the prism2/hfa384x* 802.11 MAC hardware and firmware host interface.** The functions can be considered to represent several levels of * abstraction. The lowest level functions are simply C-callable wrappers* around the register accesses. The next higher level represents C-callable* prism2 API functions that match the Intersil documentation as closely* as is reasonable. The next higher layer implements common sequences * of invokations of the API layer (e.g. write to bap, followed by cmd).** Common sequences:* hfa384x_drvr_xxx Highest level abstractions provided by the * hfa384x code. They are driver defined wrappers * for common sequences. These functions generally* use the services of the lower levels.** hfa384x_drvr_xxxconfig An example of the drvr level abstraction. These* functions are wrappers for the RID get/set * sequence. They call copy_[to|from]_bap() and * cmd_access(). These functions operate on the * RIDs and buffers without validation. The caller* is responsible for that.** API wrapper functions:* hfa384x_cmd_xxx functions that provide access to the f/w commands. * The function arguments correspond to each command* argument, even command arguments that get packed* into single registers. These functions _just_* issue the command by setting the cmd/parm regs* & reading the status/resp regs. Additional* activities required to fully use a command* (read/write from/to bap, get/set int status etc.)* are implemented separately. Think of these as* C-callable prism2 commands.** Lowest Layer Functions:* hfa384x_docmd_xxx These functions implement the sequence required* to issue any prism2 command. Primarily used by the* hfa384x_cmd_xxx functions.** hfa384x_bap_xxx BAP read/write access functions.* Note: we usually use BAP0 for non-interrupt context* and BAP1 for interrupt context.** hfa384x_dl_xxx download related functions.* * Driver State Issues:* Note that there are two pairs of functions that manage the* 'initialized' and 'running' states of the hw/MAC combo. The four* functions are create(), destroy(), start(), and stop(). create()* sets up the data structures required to support the hfa384x_** functions and destroy() cleans them up. The start() function gets* the actual hardware running and enables the interrupts. The stop()* function shuts the hardware down. The sequence should be:* create()* start()* .* . Do interesting things w/ the hardware* .* stop()* destroy()** Note that destroy() can be called without calling stop() first.* --------------------------------------------------------------------*//*================================================================*//* System Includes */#define __NO_VERSION__#include <linux/config.h>#define WLAN_DBVAR prism2_debug#include <linux/version.h>#include <wlan/wlan_compat.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/netdevice.h>#include <linux/timer.h>#include <asm/semaphore.h>#include <asm/io.h>#include <linux/delay.h>#include <asm/byteorder.h>#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))#error "This file is specific to USB"#endif#if (WLAN_HOSTIF == WLAN_USB)#include <linux/usb.h>#endif/*================================================================*//* Project Includes */#include <wlan/version.h>#include <wlan/p80211types.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include <wlan/p80211conv.h>#include <wlan/p80211msg.h>#include <wlan/p80211netdev.h>#include <prism2/hfa384x.h>#include <prism2/prism2mgmt.h>/*================================================================*//* Local Constants */#define DOWAIT 1#define DOASYNC 0/*================================================================*//* Local Macros */#define ROUNDUP64(a) (((a)%64)?((((a)/64)*64)+64):(a))/*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */extern int prism2_debug;/*================================================================*//* Local Function Declarations */#if 0static void dbprint_urb(struct urb* urb);#endifstatic int hfa384x_rx_typedrop( wlandevice_t *wlandev, UINT16 fc);#if 0static voidhfa384x_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, hfa384x_rx_frame_t *rxdesc);#endif/*---------------------------------------------------*//* BULKOUT Callbacks */static void hfa384x_usbout_callback(struct urb *urb);/*---------------------------------------------------*//* BULKIN Callbacks */static void hfa384x_usbin_callback(struct urb *urb);static voidhfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbin_rx(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);static voidhfa384x_usbin_ctlx(wlandevice_t *wlandev, struct urb *urb);/*---------------------------------------------------*//* Functions to support the prism2 usb command queue */static hfa384x_usbctlx_t*hfa384x_usbctlxq_dequeue(hfa384x_usbctlxq_t *ctlxq);static void hfa384x_usbctlxq_enqueue_run( hfa384x_usbctlxq_t *ctlxq, hfa384x_usbctlx_t *ctlx);static void hfa384x_usbctlxq_run(hfa384x_usbctlxq_t *ctlxq);static void hfa384x_usbctlx_reqtimerfn(unsigned long data);static void hfa384x_usbctlx_resptimerfn(unsigned long data);static void hfa384x_usbctlx_submit_wait( hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);void hfa384x_usbctlx_submit_async( hfa384x_t *hw, hfa384x_usbctlx_t *ctlx, ctlx_usercb_t usercb, void *usercb_data);static void hfa384x_usbctlx_complete(hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbcmd(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbrrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbwrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbrmem(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbwmem(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);/*---------------------------------------------------*//* Low level req/resp CTLX formatters and submitters */static inthfa384x_docmd( hfa384x_t *hw, UINT wait, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2, ctlx_usercb_t usercb, void *usercb_data);static inthfa384x_dorrid( hfa384x_t *hw, UINT wait, UINT16 rid, void *riddata, UINT riddatalen, ctlx_usercb_t usercb, void *usercb_data);static inthfa384x_dowrid( hfa384x_t *hw, UINT wait, UINT16 rid, void *riddata, UINT riddatalen, ctlx_usercb_t usercb, void *usercb_data);static inthfa384x_dormem( hfa384x_t *hw, UINT wait, UINT16 page, UINT16 offset, void *data, UINT len, ctlx_usercb_t usercb, void *usercb_data);static inthfa384x_dowmem( hfa384x_t *hw, UINT wait, UINT16 page, UINT16 offset, void *data, UINT len, ctlx_usercb_t usercb, void *usercb_data);static inthfa384x_isgood_pdrcode(UINT16 pdrcode);/*================================================================*//* Function Definitions */#if 0voiddbprint_urb(struct urb* urb){ WLAN_LOG_DEBUG1(3,"urb->pipe=0x%08x\n", urb->pipe); WLAN_LOG_DEBUG1(3,"urb->status=0x%08x\n", urb->status); WLAN_LOG_DEBUG1(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags); WLAN_LOG_DEBUG1(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer); WLAN_LOG_DEBUG1(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length); WLAN_LOG_DEBUG1(3,"urb->actual_length=0x%08x\n", urb->actual_length); WLAN_LOG_DEBUG1(3,"urb->bandwidth=0x%08x\n", urb->bandwidth); WLAN_LOG_DEBUG1(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet); WLAN_LOG_DEBUG1(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame); WLAN_LOG_DEBUG1(3,"urb->interval(irq)=0x%08x\n", urb->interval); WLAN_LOG_DEBUG1(3,"urb->error_count(iso)=0x%08x\n", urb->error_count); WLAN_LOG_DEBUG1(3,"urb->timeout=0x%08x\n", urb->timeout); WLAN_LOG_DEBUG1(3,"urb->context=0x%08x\n", (UINT)urb->context); WLAN_LOG_DEBUG1(3,"urb->complete=0x%08x\n", (UINT)urb->complete);}#endif/*----------------------------------------------------------------* hfa384x_create** Sets up the hfa384x_t data structure for use. Note this* does _not_ intialize the actual hardware, just the data structures* we use to keep track of its state.** Arguments:* hw device structure* irq device irq number* iobase i/o base address for register access* membase memory base address for register access** Returns: * nothing** Side effects:** Call context:* process ----------------------------------------------------------------*/voidhfa384x_create( hfa384x_t *hw, struct usb_device *usb, void *usbcontext){ DBFENTER; memset(hw, 0, sizeof(hfa384x_t)); hw->usb = usb; hw->usbcontext = usbcontext; /* this is actually a wlandev */ /* Initialize the command queue */ spin_lock_init(&hw->ctlxq.lock);/* We need to make sure everything is set up to do USB transfers after this * function is complete. * Normally, Initialize will be called after this is set up. */ DBFEXIT; return;}/*----------------------------------------------------------------* hfa384x_destroy** Partner to hfa384x_create(). This function cleans up the hw* structure so that it can be freed by the caller using a simple* kfree. Currently, this function is just a placeholder. If, at some* point in the future, an hw in the 'shutdown' state requires a 'deep'* kfree, this is where it should be done. Note that if this function* is called on a _running_ hw structure, the drvr_stop() function is* called.** Arguments:* hw device structure** Returns: * nothing, this function is not allowed to fail.** Side effects:** Call context:* process ----------------------------------------------------------------*/voidhfa384x_destroy( hfa384x_t *hw){ DBFENTER; if ( hw->state == HFA384x_STATE_RUNNING ) { hfa384x_drvr_stop(hw); } hw->state = HFA384x_STATE_PREINIT; DBFEXIT; return;}/*----------------------------------------------------------------* hfa384x_cbcmd** Ctlx_complete handler for async CMD type control exchanges.* mark the hw struct as such.** Note: If the handling is changed here, it should probably be * changed in docmd as well.** Arguments:* hw hw struct* ctlx complete CTLX** Returns: * nothing** Side effects:** Call context:* interrupt----------------------------------------------------------------*/voidhfa384x_cbcmd(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx){ UINT result; hfa384x_async_cmdresult_t cmdresult; DBFENTER; if ( ctlx->usercb != NULL ) { memset(&cmdresult, 0, sizeof(cmdresult)); result = ctlx->state; if (ctlx->state == HFA384x_USBCTLX_COMPLETE) { cmdresult.status = hfa384x2host_16(ctlx->inbuf.cmdresp.status); cmdresult.resp0 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp0); cmdresult.resp1 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp1); cmdresult.resp2 = hfa384x2host_16(ctlx->inbuf.cmdresp.resp2); } (*ctlx->usercb)(hw, result, &cmdresult, ctlx->usercb_data); } kfree(ctlx); DBFEXIT; return;}/*----------------------------------------------------------------* hfa384x_cbrrid** CTLX completion handler for async RRID type control exchanges.* * Note: If the handling is changed here, it should probably be * changed in dowrid as well.** Arguments:* hw hw struct* ctlx complete CTLX** Returns: * nothing** Side effects:** Call context:* interrupt----------------------------------------------------------------*/voidhfa384x_cbrrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx){ UINT result; hfa384x_async_rridresult_t rridresult;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?