⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfa384x_usb.c

📁 这是基于hfa3841、hfa3842的无线网卡linux驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 WLAN_DBVAR	prism2_debug#include <wlan/version.h>#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/wireless.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>#include <asm/bitops.h>#include <linux/list.h>#include <linux/usb.h>#include <wlan/wlan_compat.h>#if (WLAN_HOSTIF != WLAN_USB)#error "This file is specific to USB"#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)static voidusb_init_urb(struct urb *urb){	memset(urb, 0, sizeof(*urb));#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */	urb->count = (atomic_t)ATOMIC_INIT(1);#endif	spin_lock_init(&urb->lock);}#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */#  define SUBMIT_URB(u,f)  usb_submit_urb(u,f)#else#  define SUBMIT_URB(u,f)  usb_submit_urb(u)#endif/*================================================================*//* Project Includes */#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 <wlan/p80211req.h>#include <wlan/p80211metadef.h>#include <wlan/p80211metastruct.h>#include <prism2/hfa384x.h>#include <prism2/prism2mgmt.h>/*================================================================*//* Local Constants */#define	DOWAIT		1#define DOASYNC		0/*================================================================*//* Local Macros */#define ROUNDUP64(a) (((a)+63)&~63)/*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */extern int prism2_debug;/*================================================================*//* Local Function Declarations */#ifdef DEBUG_USBstatic void dbprint_urb(struct urb* urb);#endifstatic voidhfa384x_int_rxmonitor( 	wlandevice_t *wlandev, 	hfa384x_usb_rxfrm_t *rxfrm);static voidhfa384x_usb_defer(void *hw);static intsubmit_rx_urb(hfa384x_t *hw, int flags);static intsubmit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, int flags);/*---------------------------------------------------*//* Callbacks */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))static void hfa384x_usbout_callback(struct urb *urb);static voidhfa384x_ctlxout_callback(struct urb *urb);static void	hfa384x_usbin_callback(struct urb *urb);#elsestatic void hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs);static voidhfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs);static void	hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs);#endifstatic 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 void hfa384x_usbin_ctlx(wlandevice_t *wlandev, hfa384x_usbin_t *usbin, 			       int urb_status);/*---------------------------------------------------*//* Functions to support the prism2 usb command queue */static inthfa384x_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);static inthfa384x_usbctlx_submit_async(	hfa384x_t		*hw, 	hfa384x_usbctlx_t	*ctlx,	ctlx_usercb_t		usercb,	void			*usercb_data);static voidhfa384x_usbctlx_init(hfa384x_usbctlx_t *ctlx, hfa384x_t *hw);static void hfa384x_usbctlx_complete(hfa384x_usbctlx_t *ctlx);static voidhfa384x_usbctlx_complete_async(deferred_data_t ctlx);static inthfa384x_usbctlx_cancel(hfa384x_usbctlx_t *ctlx);static inthfa384x_usbctlx_cancel_async(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,	hfa384x_metacmd_t *cmd,	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 */#ifdef DEBUG_USBvoiddbprint_urb(struct urb* urb){	WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe);	WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status);	WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags);	WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer);	WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length);	WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length);	WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth);	WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet);	WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame);	WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval);	WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count);	WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout);	WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (UINT)urb->context);	WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (UINT)urb->complete);}#endif/*----------------------------------------------------------------* submit_rx_urb** Listen for input data on the BULK-IN pipe. If the pipe has* stalled then schedule it to be reset.** Arguments:*	hw		device struct*	memflags	memory allocation flags** Returns:*	error code from submission** Call context:*	Any----------------------------------------------------------------*/static intsubmit_rx_urb(hfa384x_t *hw, int memflags){	unsigned long flags;	hfa384x_usbin_t *usbin;	int result;	DBFENTER;		usbin = kmalloc(sizeof(*usbin), memflags);	if (usbin == NULL)		return -ENOMEM;	memset(usbin, 0, sizeof(*usbin));	/* Post the IN urb */	usb_fill_bulk_urb(&hw->rx_urb, hw->usb,	              usb_rcvbulkpipe(hw->usb, hw->endp_in),	              usbin, sizeof(*usbin),	              hfa384x_usbin_callback, hw->wlandev);	result = -ENOLINK;	spin_lock_irqsave(&hw->ctlxq.lock, flags);	if ( !hw->usb_removed && !test_bit(WORK_RX_HALT, &hw->work_flags)) {		result = SUBMIT_URB(&hw->rx_urb, memflags);		/* Check whether we need to reset the RX pipe */		if (result == -EPIPE) {			WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n",			                 hw->wlandev->netdev->name);			set_bit(WORK_RX_HALT, &hw->work_flags);			schedule_work(&hw->usb_work);		}	}	spin_unlock_irqrestore(&hw->ctlxq.lock, flags);	/* Don't leak memory if anything should go wrong */	if (result != 0)		kfree(usbin);	return result;}/*----------------------------------------------------------------* submit_tx_urb** Prepares and submits the URB of transmitted data. If the* submission fails then it will schedule the output pipe to* be reset.** Arguments:*	hw		device struct*	tx_urb		URB of data for tranmission*	memflags	memory allocation flags** Returns:*	error code from submission** Call context:*	Any----------------------------------------------------------------*/static intsubmit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, int memflags){	struct net_device *netdev = hw->wlandev->netdev;	unsigned long flags;	int result;	spin_lock_irqsave(&hw->ctlxq.lock, flags);	result = -ENOLINK;	if ( netif_running(netdev) ) {		if ( !hw->usb_removed && !test_bit(WORK_TX_HALT, &hw->work_flags) ) {			result = SUBMIT_URB(tx_urb, memflags);			/* Test whether we need to reset the TX pipe */			if (result == -EPIPE) {				WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n",				                 netdev->name);				set_bit(WORK_TX_HALT, &hw->work_flags);				schedule_work(&hw->usb_work);			}			else if (result == 0) {				netif_stop_queue(netdev);			}		}	}	spin_unlock_irqrestore(&hw->ctlxq.lock, flags);	return result;}/*----------------------------------------------------------------* hfa394x_usb_defer** There are some things that the USB stack cannot do while* in interrupt context, so we arrange this function to run* in process context.** Arguments:*	hw	device structure** Returns:*	nothing** Call context:*	process (by design)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -