From pizza@shaftnet.org Mon Oct 27 12:07:16 2008 From: Solomon Peachy Date: Mon, 27 Oct 2008 11:13:55 -0400 Subject: Staging: wlan-ng: Remove PCI/PLX/PCMCIA files. To: greg@kroah.com Cc: mark@linux-wlan.com, Solomon Peachy Message-ID: <1225120446-2908-2-git-send-email-pizza@shaftnet.org> This portion of the driver is not needed at all, so remove it. Signed-off-by: Solomon Peachy Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/README | 1 drivers/staging/wlan-ng/hfa384x.c | 4018 ----------------------------------- drivers/staging/wlan-ng/prism2_cs.c | 1487 ------------ drivers/staging/wlan-ng/prism2_pci.c | 332 -- drivers/staging/wlan-ng/prism2_plx.c | 472 ---- 5 files changed, 6310 deletions(-) --- a/drivers/staging/wlan-ng/hfa384x.c +++ /dev/null @@ -1,4018 +0,0 @@ -/* src/prism2/driver/hfa384x.c -* -* Implements the functions of 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() -* . -* . Self contained test routines can run here, particularly -* . corereset() and test_hostif(). -* . -* 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 "version.h" - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include -#else -#include -#endif - -#if (WLAN_HOSTIF == WLAN_PCMCIA) -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) -#include -#endif -#include -#include -#include -#include -#include -#endif - -#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI)) -#include -#include -#endif - -#include "wlan_compat.h" - -// XXXX #define CMD_IRQ - -/*================================================================*/ -/* Project Includes */ - -#include "p80211types.h" -#include "p80211hdr.h" -#include "p80211mgmt.h" -#include "p80211conv.h" -#include "p80211msg.h" -#include "p80211netdev.h" -#include "p80211req.h" -#include "p80211metadef.h" -#include "p80211metastruct.h" -#include "hfa384x.h" -#include "prism2mgmt.h" - -/*================================================================*/ -/* Local Constants */ - -static const UINT16 crc16tab[256] = -{ - 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, - 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, - 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, - 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, - 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, - 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, - 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, - 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, - 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, - 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, - 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, - 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, - 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, - 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, - 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, - 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, - 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, - 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, - 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, - 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, - 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, - 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, - 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, - 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, - 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, - 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, - 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, - 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, - 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, - 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, - 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, - 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 -}; - -/*================================================================*/ -/* Local Macros */ - -/*================================================================*/ -/* Local Types */ - -/*================================================================*/ -/* Local Static Definitions */ -extern int prism2_debug; - -/*================================================================*/ -/* Local Function Declarations */ - -static void hfa384x_int_dtim(wlandevice_t *wlandev); -static void hfa384x_int_infdrop(wlandevice_t *wlandev); - -static void hfa384x_bap_tasklet(unsigned long data); - -static void hfa384x_int_info(wlandevice_t *wlandev); -static void hfa384x_int_txexc(wlandevice_t *wlandev); -static void hfa384x_int_tx(wlandevice_t *wlandev); -static void hfa384x_int_rx(wlandevice_t *wlandev); - -#ifdef CMD_IRQ -static void hfa384x_int_cmd(wlandevice_t *wlandev); -#endif -static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, - UINT16 rxfid, hfa384x_rx_frame_t *rxdesc); -static void hfa384x_int_alloc(wlandevice_t *wlandev); - -static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); - -static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd); - -static UINT16 -hfa384x_mkcrc16(UINT8 *p, int len); - -int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, - void *buf, UINT len, void* buf2, UINT len2, - void *buf3, UINT len3, void* buf4, UINT len4); - -/*================================================================*/ -/* Function Definitions */ - -static UINT16 -txfid_queue_empty(hfa384x_t *hw) -{ - return (hw->txfid_head == hw->txfid_tail) ? 1 : 0; -} - -static UINT16 -txfid_queue_remove(hfa384x_t *hw) -{ - UINT16 result= 0; - - if (txfid_queue_empty(hw)) { - WLAN_LOG_DEBUG(3,"queue empty.\n"); - } else { - result = hw->txfid_queue[hw->txfid_head]; - hw->txfid_head = (hw->txfid_head + 1) % hw->txfid_N; - } - - return (UINT16)result; -} - -static INT16 -txfid_queue_add(hfa384x_t *hw, UINT16 val) -{ - INT16 result = 0; - - if (hw->txfid_head == ((hw->txfid_tail + 1) % hw->txfid_N)) { - result = -1; - WLAN_LOG_DEBUG(3,"queue full.\n"); - } else { - hw->txfid_queue[hw->txfid_tail] = val; - result = hw->txfid_tail; - hw->txfid_tail = (hw->txfid_tail + 1) % hw->txfid_N; - } - - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_create -* -* Initializes 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 [pcmcia] i/o base address for register access -* [pci] zero -* [plx] i/o base address for register access -* membase [pcmcia] pcmcia_cs "link" pointer -* [pci] memory base address for register access -* [plx] memory base address for card attribute memory -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -void hfa384x_create(hfa384x_t *hw, UINT irq, UINT32 iobase, - UINT8 __iomem *membase) -{ - DBFENTER; - memset(hw, 0, sizeof(hfa384x_t)); - hw->irq = irq; - hw->iobase = iobase; - hw->membase = membase; - spin_lock_init(&(hw->cmdlock)); - - /* BAP setup */ - spin_lock_init(&(hw->baplock)); - tasklet_init(&hw->bap_tasklet, - hfa384x_bap_tasklet, - (unsigned long) hw); - - init_waitqueue_head(&hw->cmdq); - sema_init(&hw->infofid_sem, 1); - - hw->txfid_head = 0; - hw->txfid_tail = 0; - hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; - memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); - - hw->isram16 = 1; - - /* Init the auth queue head */ - skb_queue_head_init(&hw->authq); - - INIT_WORK2(&hw->link_bh, prism2sta_processing_defer); - - INIT_WORK2(&hw->commsqual_bh, prism2sta_commsqual_defer); - - init_timer(&hw->commsqual_timer); - hw->commsqual_timer.data = (unsigned long) hw; - hw->commsqual_timer.function = prism2sta_commsqual_timer; - - hw->link_status = HFA384x_LINK_NOTCONNECTED; - hw->state = HFA384x_STATE_INIT; - - DBFEXIT; -} - -/*---------------------------------------------------------------- -* 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 -----------------------------------------------------------------*/ -void -hfa384x_destroy( hfa384x_t *hw) -{ - struct sk_buff *skb; - - DBFENTER; - - if ( hw->state == HFA384x_STATE_RUNNING ) { - hfa384x_drvr_stop(hw); - } - hw->state = HFA384x_STATE_PREINIT; - - if (hw->scanresults) { - kfree(hw->scanresults); - hw->scanresults = NULL; - } - - /* Now to clean out the auth queue */ - while ( (skb = skb_dequeue(&hw->authq)) ) { - dev_kfree_skb(skb); - } - - DBFEXIT; - return; -} - -/*---------------------------------------------------------------- -* hfa384x_drvr_getconfig -* -* Performs the sequence necessary to read a config/info item. -* -* Arguments: -* hw device structure -* rid config/info record id (host order) -* buf host side record buffer. Upon return it will -* contain the body portion of the record (minus the -* RID and len). -* len buffer length (in bytes, should match record length) -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -ENODATA length mismatch between argument and retrieved -* record. -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) -{ - int result = 0; - DBFENTER; - - result = hfa384x_cmd_access( hw, 0, rid, buf, len); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_setconfig -* -* Performs the sequence necessary to write a config/info item. -* -* Arguments: -* hw device structure -* rid config/info record id (in host order) -* buf host side record buffer -* len buffer length (in bytes) -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) -{ - int result = 0; - DBFENTER; - - result = hfa384x_cmd_access( hw, 1, rid, buf, len); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_readpda -* -* Performs the sequence to read the PDA space. Note there is no -* drvr_writepda() function. Writing a PDA is -* generally implemented by a calling component via calls to -* cmd_download and writing to the flash download buffer via the -* aux regs. -* -* Arguments: -* hw device structure -* buf buffer to store PDA in -* len buffer length -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -ETIMEOUT timout waiting for the cmd regs to become -* available, or waiting for the control reg -* to indicate the Aux port is enabled. -* -ENODATA the buffer does NOT contain a valid PDA. -* Either the card PDA is bad, or the auxdata -* reads are giving us garbage. - -* -* Side effects: -* -* Call context: -* process thread or non-card interrupt. -----------------------------------------------------------------*/ -int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len) -{ - int result = 0; - UINT16 *pda = buf; - int pdaok = 0; - int morepdrs = 1; - int currpdr = 0; /* word offset of the current pdr */ - int i; - UINT16 pdrlen; /* pdr length in bytes, host order */ - UINT16 pdrcode; /* pdr code, host order */ - UINT16 crc; - UINT16 pdacrc; - struct pdaloc { - UINT32 cardaddr; - UINT16 auxctl; - } pdaloc[] = - { - { HFA3842_PDA_BASE, HFA384x_AUX_CTL_NV}, - { HFA3842_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, - { HFA3841_PDA_BASE, HFA384x_AUX_CTL_NV}, - { HFA3841_PDA_BASE, HFA384x_AUX_CTL_EXTDS}, - { HFA3841_PDA_BOGUS_BASE, HFA384x_AUX_CTL_NV} - }; - - DBFENTER; - /* Check for aux available */ - result = hfa384x_cmd_aux_enable(hw, 0); - if ( result ) { - WLAN_LOG_DEBUG(1,"aux_enable() failed. result=%d\n", result); - goto failed; - } - - /* Read the pda from each known address. */ - for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) { - WLAN_LOG_DEBUG( 3, "Checking PDA@(0x%08x,%s)\n", - pdaloc[i].cardaddr, - pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ? - "CTL_NV" : "CTL_EXTDS"); - - /* Copy bufsize bytes from our current pdaloc */ - hfa384x_copy_from_aux(hw, - pdaloc[i].cardaddr, - pdaloc[i].auxctl, - buf, - len); - - /* Test for garbage */ - /* Traverse the PDR list Looking for PDA-END */ - pdaok = 1; /* intially assume good */ - morepdrs = 1; - currpdr = 0; - while ( pdaok && morepdrs ) { - pdrlen = hfa384x2host_16(pda[currpdr]) * 2; - pdrcode = hfa384x2host_16(pda[currpdr+1]); - - /* Test for completion at END record */ - if ( pdrcode == HFA384x_PDR_END_OF_PDA ) { - if ( pdrlen == 4 ) { - morepdrs = 0; - /* Calculate CRC-16 and compare to PDA - * value. Note the addition of 2 words - * for ENDREC.len and ENDREC.code - * fields. - */ - crc = hfa384x_mkcrc16( (UINT8*)pda, - (currpdr + 2) * sizeof(UINT16)); - pdacrc =hfa384x2host_16(pda[currpdr+2]); - if ( crc != pdacrc ) { - WLAN_LOG_DEBUG(3, - "PDA crc failed:" - "calc_crc=0x%04x," - "pdr_crc=0x%04x.\n", - crc, pdacrc); - pdaok = 0; - } - } else { - WLAN_LOG_DEBUG(3, - "END record detected w/ " - "len(%d) != 2, assuming bad PDA\n", - pdrlen); - pdaok = 0; - - } - break; - } - - /* Test the record length */ - if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { - WLAN_LOG_DEBUG(3, - "pdrlen for address #%d " - "at %#x:%#x:%d\n", - i, pdaloc[i].cardaddr, - pdaloc[i].auxctl, pdrlen); - WLAN_LOG_DEBUG(3,"pdrlen invalid=%d\n", - pdrlen); - pdaok = 0; - break; - } - - /* Move to the next pdr */ - if ( morepdrs ) { - /* note the access to pda[], we need words */ - currpdr += hfa384x2host_16(pda[currpdr]) + 1; - if (currpdr*sizeof(UINT16) > len) { - WLAN_LOG_DEBUG(3, - "Didn't find PDA_END in buffer, " - "trying next location.\n"); - pdaok = 0; - break; - } - } - } - if ( pdaok ) { - WLAN_LOG_INFO( - "PDA Read from 0x%08x in %s space.\n", - pdaloc[i].cardaddr, - pdaloc[i].auxctl == 0 ? "EXTDS" : - pdaloc[i].auxctl == 1 ? "NV" : - pdaloc[i].auxctl == 2 ? "PHY" : - pdaloc[i].auxctl == 3 ? "ICSRAM" : - ""); - break; - } - } - result = pdaok ? 0 : -ENODATA; - - if ( result ) { - WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); - } - - hfa384x_cmd_aux_disable(hw); -failed: - DBFEXIT; - return result; -} - - - -/*---------------------------------------------------------------- -* mkpda_crc -* -* Calculates the CRC16 for the given PDA and inserts the value -* into the end record. -* -* Arguments: -* pda ptr to the PDA data structure. -* -* Returns: -* 0 - success -* ~0 - failure (probably an errno) -----------------------------------------------------------------*/ -static UINT16 -hfa384x_mkcrc16(UINT8 *p, int len) -{ - UINT16 crc = 0; - UINT8 *lim = p + len; - - while (p < lim) { - crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++]; - } - - return crc; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_enable -* -* Begins the ram download state. Checks to see that we're not -* already in a download state and that a port isn't enabled. -* Sets the download state and calls cmd_download with the -* ENABLE_VOLATILE subcommand and the exeaddr argument. -* -* Arguments: -* hw device structure -* exeaddr the card execution address that will be -* jumped to when ramdl_disable() is called -* (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr) -{ - int result = 0; - UINT16 lowaddr; - UINT16 hiaddr; - int i; - DBFENTER; - /* Check that a port isn't active */ - for ( i = 0; i < HFA384x_PORTID_MAX; i++) { - if ( hw->port_enabled[i] ) { - WLAN_LOG_DEBUG(1,"Can't download with a port enabled.\n"); - result = -EINVAL; - goto done; - } - } - - /* Check that we're not already in a download state */ - if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { - WLAN_LOG_DEBUG(1,"Download state not disabled.\n"); - result = -EINVAL; - goto done; - } - - /* Are we supposed to go into genesis mode? */ - if (exeaddr == 0x3f0000) { - UINT16 initseq[2] = { 0xe100, 0xffa1 }; - UINT16 readbuf[2]; - UINT8 hcr = 0x0f; /* Default to x16 SRAM */ - hw->isram16 = 1; - - WLAN_LOG_DEBUG(1, "Dropping into Genesis mode\n"); - - /* Issue card reset and enable aux port */ - hfa384x_corereset(hw, prism2_reset_holdtime, - prism2_reset_settletime, 0); - hfa384x_cmd_aux_enable(hw, 1); - - /* Genesis set */ - hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - initseq, sizeof(initseq)); - - hfa384x_corereset(hw, prism2_reset_holdtime, - prism2_reset_settletime, hcr); - - /* Validate memory config */ - hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - initseq, sizeof(initseq)); - hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - readbuf, sizeof(initseq)); - WLAN_HEX_DUMP(3, "readback", readbuf, sizeof(readbuf)); - - if (memcmp(initseq, readbuf, sizeof(readbuf))) { - hcr = 0x1f; /* x8 SRAM */ - hw->isram16 = 0; - - hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - initseq, sizeof(initseq)); - hfa384x_corereset(hw, prism2_reset_holdtime, - prism2_reset_settletime, hcr); - - hfa384x_copy_to_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - initseq, sizeof(initseq)); - hfa384x_copy_from_aux(hw, 0x7E0038, HFA384x_AUX_CTL_EXTDS, - readbuf, sizeof(initseq)); - WLAN_HEX_DUMP(2, "readback", readbuf, sizeof(readbuf)); - - if (memcmp(initseq, readbuf, sizeof(readbuf))) { - WLAN_LOG_ERROR("Genesis mode failed\n"); - result = -1; - goto done; - } - } - - /* Now we're in genesis mode */ - hw->dlstate = HFA384x_DLSTATE_GENESIS; - goto done; - } - - /* Retrieve the buffer loc&size and timeout */ - if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, - &(hw->bufinfo), sizeof(hw->bufinfo))) ) { - goto done; - } - hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); - hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); - hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); - if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, - &(hw->dltimeout))) ) { - goto done; - } - hw->dltimeout = hfa384x2host_16(hw->dltimeout); - - /* Enable the aux port */ - if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { - WLAN_LOG_DEBUG(1,"Aux enable failed, result=%d.\n", result); - goto done; - } - - /* Call the download(1,addr) function */ - lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); - hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); - - result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, - lowaddr, hiaddr, 0); - if ( result == 0) { - /* Set the download state */ - hw->dlstate = HFA384x_DLSTATE_RAMENABLED; - } else { - WLAN_LOG_DEBUG(1,"cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", - lowaddr,hiaddr, result); - /* Disable the aux port */ - hfa384x_cmd_aux_disable(hw); - } - - done: - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_disable -* -* Ends the ram download state. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) -{ - DBFENTER; - /* Check that we're already in the download state */ - if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && - ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { - return -EINVAL; - } - - if (hw->dlstate == HFA384x_DLSTATE_GENESIS) { - hfa384x_corereset(hw, prism2_reset_holdtime, - prism2_reset_settletime, - hw->isram16 ? 0x07: 0x17); - goto done; - } - - /* Disable the aux port */ - hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); - - done: - hw->dlstate = HFA384x_DLSTATE_DISABLED; - hfa384x_cmd_aux_disable(hw); - - DBFEXIT; - return 0; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_ramdl_write -* -* Performs a RAM download of a chunk of data. First checks to see -* that we're in the RAM download state, then uses the aux functions -* to 1) copy the data, 2) readback and compare. The download -* state is unaffected. When all data has been written using -* this function, call drvr_ramdl_disable() to end the download state -* and restart the MAC. -* -* Arguments: -* hw device structure -* daddr Card address to write to. (host order) -* buf Ptr to data to write. -* len Length of data (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) -{ - int result = 0; - UINT8 *verbuf; - DBFENTER; - /* Check that we're in the ram download state */ - if ( ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) && - ( hw->dlstate != HFA384x_DLSTATE_GENESIS ) ) { - return -EINVAL; - } - - WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); -#if 0 -WLAN_HEX_DUMP(1, "dldata", buf, len); -#endif - /* Copy the data via the aux port */ - hfa384x_copy_to_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, buf, len); - - /* Create a buffer for the verify */ - verbuf = kmalloc(len, GFP_KERNEL); - if (verbuf == NULL ) return 1; - - /* Read back and compare */ - hfa384x_copy_from_aux(hw, daddr, HFA384x_AUX_CTL_EXTDS, verbuf, len); - - if ( memcmp(buf, verbuf, len) ) { - WLAN_LOG_DEBUG(1,"ramdl verify failed!\n"); - result = -EINVAL; - } - - kfree_s(verbuf, len); - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_enable -* -* Begins the flash download state. Checks to see that we're not -* already in a download state and that a port isn't enabled. -* Sets the download state and retrieves the flash download -* buffer location, buffer size, and timeout length. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) -{ - int result = 0; - int i; - - DBFENTER; - /* Check that a port isn't active */ - for ( i = 0; i < HFA384x_PORTID_MAX; i++) { - if ( hw->port_enabled[i] ) { - WLAN_LOG_DEBUG(1,"called when port enabled.\n"); - return -EINVAL; - } - } - - /* Check that we're not already in a download state */ - if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { - return -EINVAL; - } - - /* Retrieve the buffer loc&size and timeout */ - if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, - &(hw->bufinfo), sizeof(hw->bufinfo))) ) { - return result; - } - hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); - hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); - hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); - if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, - &(hw->dltimeout))) ) { - return result; - } - hw->dltimeout = hfa384x2host_16(hw->dltimeout); - - /* Enable the aux port */ - if ( (result = hfa384x_cmd_aux_enable(hw, 0)) ) { - return result; - } - - hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_disable -* -* Ends the flash download state. Note that this will cause the MAC -* firmware to restart. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) -{ - DBFENTER; - /* Check that we're already in the download state */ - if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { - return -EINVAL; - } - - /* There isn't much we can do at this point, so I don't */ - /* bother w/ the return value */ - hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); - hw->dlstate = HFA384x_DLSTATE_DISABLED; - - /* Disable the aux port */ - hfa384x_cmd_aux_disable(hw); - - DBFEXIT; - return 0; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_flashdl_write -* -* Performs a FLASH download of a chunk of data. First checks to see -* that we're in the FLASH download state, then sets the download -* mode, uses the aux functions to 1) copy the data to the flash -* buffer, 2) sets the download 'write flash' mode, 3) readback and -* compare. Lather rinse, repeat as many times an necessary to get -* all the given data into flash. -* When all data has been written using this function (possibly -* repeatedly), call drvr_flashdl_disable() to end the download state -* and restart the MAC. -* -* Arguments: -* hw device structure -* daddr Card address to write to. (host order) -* buf Ptr to data to write. -* len Length of data (host order). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len) -{ - int result = 0; - UINT8 *verbuf; - UINT32 dlbufaddr; - UINT32 currlen; - UINT32 currdaddr; - UINT16 destlo; - UINT16 desthi; - int nwrites; - int i; - - DBFENTER; - /* Check that we're in the flash download state */ - if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { - return -EINVAL; - } - - WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); - - /* Need a flat address for arithmetic */ - dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( - hw->bufinfo.page, - hw->bufinfo.offset); - verbuf = kmalloc(hw->bufinfo.len, GFP_KERNEL); - -#if 0 -WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); -#endif - /* Figure out how many times to to the flash prog */ - nwrites = len / hw->bufinfo.len; - nwrites += (len % hw->bufinfo.len) ? 1 : 0; - - if ( verbuf == NULL ) { - WLAN_LOG_ERROR("Failed to allocate flash verify buffer\n"); - return 1; - } - /* For each */ - for ( i = 0; i < nwrites; i++) { - /* Get the dest address and len */ - currlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? - hw->bufinfo.len : - (len - (hw->bufinfo.len * i)); - currdaddr = daddr + (hw->bufinfo.len * i); - destlo = HFA384x_ADDR_CMD_MKOFF(currdaddr); - desthi = HFA384x_ADDR_CMD_MKPAGE(currdaddr); - WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", currlen, currdaddr); -#if 0 -WLAN_HEX_DUMP(1, "dldata", buf+(hw->bufinfo.len*i), currlen); -#endif - /* Set the download mode */ - result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, - destlo, desthi, currlen); - if ( result ) { - WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " - "cmd failed, result=%d. Aborting d/l\n", - destlo, desthi, currlen, result); - goto exit_proc; - } - /* copy the data to the flash buffer */ - hfa384x_copy_to_aux(hw, dlbufaddr, HFA384x_AUX_CTL_EXTDS, - buf+(hw->bufinfo.len*i), currlen); - /* set the download 'write flash' mode */ - result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NVWRITE, 0,0,0); - if ( result ) { - WLAN_LOG_ERROR( - "download(NVWRITE,lo=%x,hi=%x,len=%x) " - "cmd failed, result=%d. Aborting d/l\n", - destlo, desthi, currlen, result); - goto exit_proc; - } - /* readback and compare, if fail...bail */ - hfa384x_copy_from_aux(hw, - currdaddr, HFA384x_AUX_CTL_NV, - verbuf, currlen); - - if ( memcmp(buf+(hw->bufinfo.len*i), verbuf, currlen) ) { - return -EINVAL; - } - } - -exit_proc: - /* DOH! This kfree's for you Mark :-) My forehead hurts... */ - kfree(verbuf); - - /* Leave the firmware in the 'post-prog' mode. flashdl_disable will */ - /* actually disable programming mode. Remember, that will cause the */ - /* the firmware to effectively reset itself. */ - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_initialize -* -* Issues the initialize command and sets the hw->state based -* on the result. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_initialize(hfa384x_t *hw) -{ - int result = 0; - int i; - hfa384x_metacmd_t cmd; - - DBFENTER; - - /* we don't want to be interrupted during the reset */ - hfa384x_setreg(hw, 0, HFA384x_INTEN); - hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); - - cmd.cmd = HFA384x_CMDCODE_INIT; - cmd.parm0 = 0; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - if ( result == 0 ) { - for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { - hw->port_enabled[i] = 0; - } - } - - hw->link_status = HFA384x_LINK_NOTCONNECTED; - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_commtallies -* -* Send a commtallies inquiry to the MAC. Note that this is an async -* call that will result in an info frame arriving sometime later. -* -* Arguments: -* hw device structure -* -* Returns: -* zero success. -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ -int hfa384x_drvr_commtallies( hfa384x_t *hw ) -{ - hfa384x_metacmd_t cmd; - int result; - - DBFENTER; - - cmd.cmd = HFA384x_CMDCODE_INQ; - cmd.parm0 = HFA384x_IT_COMMTALLIES; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_enable -* -* Issues the enable command to enable communications on one of -* the MACs 'ports'. Only macport 0 is valid for stations. -* APs may also enable macports 1-6. Only ports that are currently -* disabled may be enabled. -* -* Arguments: -* hw device structure -* macport MAC port number -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport) -{ - int result = 0; - - DBFENTER; - if ((!hw->isap && macport != 0) || - (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || - (hw->port_enabled[macport]) ){ - result = -EINVAL; - } else { - result = hfa384x_cmd_enable(hw, macport); - if ( result == 0 ) { - hw->port_enabled[macport] = 1; - } - } - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_enable -* -* Issues the the enable command to enable communications on one of the -* MACs 'ports'. -* -* Arguments: -* hw device structure -* macport MAC port number -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | - HFA384x_CMD_MACPORT_SET(macport); - cmd.parm0 = 0; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_disable -* -* Issues the disable command to stop communications on one of -* the MACs 'ports'. Only macport 0 is valid for stations. -* APs may also disable macports 1-6. Only ports that have been -* previously enabled may be disabled. -* -* Arguments: -* hw device structure -* macport MAC port number (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport) -{ - int result = 0; - - DBFENTER; - if ((!hw->isap && macport != 0) || - (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || - !(hw->port_enabled[macport]) ){ - result = -EINVAL; - } else { - result = hfa384x_cmd_disable(hw, macport); - if ( result == 0 ) { - hw->port_enabled[macport] = 0; - } - } - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_disable -* -* Issues the command to disable a port. -* -* Arguments: -* hw device structure -* macport MAC port number (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | - HFA384x_CMD_MACPORT_SET(macport); - cmd.parm0 = 0; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_diagnose -* -* Issues the diagnose command to test the: register interface, -* MAC controller (including loopback), External RAM, Non-volatile -* memory integrity, and synthesizers. Following execution of this -* command, MAC/firmware are in the 'initial state'. Therefore, -* the Initialize command should be issued after successful -* completion of this command. This function may only be called -* when the MAC is in the 'communication disabled' state. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -#define DIAG_PATTERNA ((UINT16)0xaaaa) -#define DIAG_PATTERNB ((UINT16)0x5555) - -int hfa384x_cmd_diagnose(hfa384x_t *hw) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DIAG); - cmd.parm0 = DIAG_PATTERNA; - cmd.parm1 = DIAG_PATTERNB; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_allocate -* -* Issues the allocate command instructing the firmware to allocate -* a 'frame structure buffer' in MAC controller RAM. This command -* does not provide the result, it only initiates one of the f/w's -* asynchronous processes to construct the buffer. When the -* allocation is complete, it will be indicated via the Alloc -* bit in the EvStat register and the FID identifying the allocated -* space will be available from the AllocFID register. Some care -* should be taken when waiting for the Alloc event. If a Tx or -* Notify command w/ Reclaim has been previously executed, it's -* possible the first Alloc event after execution of this command -* will be for the reclaimed buffer and not the one you asked for. -* This case must be handled in the Alloc event handler. -* -* Arguments: -* hw device structure -* len allocation length, must be an even value -* in the range [4-2400]. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - if ( (len % 2) || - len < HFA384x_CMD_ALLOC_LEN_MIN || - len > HFA384x_CMD_ALLOC_LEN_MAX ) { - result = -EINVAL; - } else { - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC); - cmd.parm0 = len; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - } - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_transmit -* -* Instructs the firmware to transmit a frame previously copied -* to a given buffer. This function returns immediately, the Tx -* results are available via the Tx or TxExc events (if the frame -* control bits are set). The reclaim argument specifies if the -* FID passed will be used by the f/w tx process or returned for -* use w/ another transmit command. If reclaim is set, expect an -* Alloc event signalling the availibility of the FID for reuse. -* -* NOTE: hw->cmdlock MUST BE HELD before calling this function! -* -* Arguments: -* hw device structure -* reclaim [0|1] indicates whether the given FID will -* be handed back (via Alloc event) for reuse. -* (host order) -* qos [0-3] Value to put in the QoS field of the -* tx command, identifies a queue to place the -* outgoing frame in. -* (host order) -* fid FID of buffer containing the frame that was -* previously copied to MAC memory via the bap. -* (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* hw->resp0 will contain the FID being used by async tx -* process. If reclaim==0, resp0 will be the same as the fid -* argument. If reclaim==1, resp0 will be the different and -* is the value to watch for in the Tx|TxExc to indicate completion -* of the frame passed in fid. -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX) | - HFA384x_CMD_RECL_SET(reclaim) | - HFA384x_CMD_QOS_SET(qos); - cmd.parm0 = fid; - cmd.parm1 = 0; - cmd.parm2 = 0; - - result = hfa384x_docmd_wait(hw, &cmd); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_clearpersist -* -* Instructs the firmware to clear the persistence bit in a given -* FID. This has the effect of telling the firmware to drop the -* persistent frame. The FID must be one that was previously used -* to transmit a PRST frame. -* -* Arguments: -* hw device structure -* fid FID of the persistent frame (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_CLRPRST); - cmd.parm0 = fid; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_cmd_notify -* -* Sends an info frame to the firmware to alter the behavior -* of the f/w asynch processes. Can only be called when the MAC -* is in the enabled state. -* -* Arguments: -* hw device structure -* reclaim [0|1] indicates whether the given FID will -* be handed back (via Alloc event) for reuse. -* (host order) -* fid FID of buffer containing the frame that was -* previously copied to MAC memory via the bap. -* (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* hw->resp0 will contain the FID being used by async notify -* process. If reclaim==0, resp0 will be the same as the fid -* argument. If reclaim==1, resp0 will be the different. -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, - void *buf, UINT16 len) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_NOTIFY) | - HFA384x_CMD_RECL_SET(reclaim); - cmd.parm0 = fid; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - - /* Copy the record to FID */ - result = hfa384x_copy_to_bap(hw, HFA384x_BAP_PROC, hw->infofid, 0, buf, len); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_to_bap(%04x, 0, %d) failed, result=0x%x\n", - hw->infofid, len, result); - result = -EIO; - goto failed; - } - - result = hfa384x_docmd_wait(hw, &cmd); - - failed: - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -#if 0 -/*---------------------------------------------------------------- -* hfa384x_cmd_inquiry -* -* Requests an info frame from the firmware. The info frame will -* be delivered asynchronously via the Info event. -* -* Arguments: -* hw device structure -* fid FID of the info frame requested. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -static int hfa384x_cmd_inquiry(hfa384x_t *hw, UINT16 fid) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_INQ); - cmd.parm0 = fid; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} -#endif - - -/*---------------------------------------------------------------- -* hfa384x_cmd_access -* -* Requests that a given record be copied to/from the record -* buffer. If we're writing from the record buffer, the contents -* must previously have been written to the record buffer via the -* bap. If we're reading into the record buffer, the record can -* be read out of the record buffer after this call. -* -* Arguments: -* hw device structure -* write [0|1] copy the record buffer to the given -* configuration record. (host order) -* rid RID of the record to read/write. (host order) -* buf host side record buffer. Upon return it will -* contain the body portion of the record (minus the -* RID and len). -* len buffer length (in bytes, should match record length) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, - void* buf, UINT16 len) -{ - int result = 0; - hfa384x_metacmd_t cmd; - hfa384x_rec_t rec; - - DBFENTER; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) - /* This should NOT be called in interrupt context! */ - if (in_irq()) { - WLAN_LOG_ERROR("Krap, in Interrupt context!"); -#ifdef WLAN_INCLUDE_DEBUG - BUG(); -#endif - } -#endif - spin_lock_bh(&hw->cmdlock); - - if (write) { - rec.rid = host2hfa384x_16(rid); - rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */ - /* write the record */ - result = hfa384x_copy_to_bap4( hw, HFA384x_BAP_PROC, rid, 0, - &rec, sizeof(rec), - buf, len, - NULL, 0, NULL, 0); - if ( result ) { - WLAN_LOG_DEBUG(3,"Failure writing record header+data\n"); - goto fail; - } - - } - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | - HFA384x_CMD_WRITE_SET(write); - cmd.parm0 = rid; - cmd.parm1 = 0; - cmd.parm2 = 0; - - result = hfa384x_docmd_wait(hw, &cmd); - if ( result ) { - WLAN_LOG_ERROR("Call to hfa384x_docmd_wait failed (%d %d)\n", - result, cmd.result.resp0); - goto fail; - } - - if (!write) { - result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, 0, &rec, sizeof(rec)); - if ( result ) { - WLAN_LOG_DEBUG(3,"Call to hfa384x_copy_from_bap failed\n"); - goto fail; - } - - /* Validate the record length */ - if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */ - WLAN_LOG_DEBUG(1, "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", - rid, len, (hfa384x2host_16(rec.reclen)-1)*2); - result = -ENODATA; - goto fail; - } - - result = hfa384x_copy_from_bap( hw, HFA384x_BAP_PROC, rid, sizeof(rec), buf, len); - - } - - fail: - spin_unlock_bh(&hw->cmdlock); - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_monitor -* -* Enables the 'monitor mode' of the MAC. Here's the description of -* monitor mode that I've received thus far: -* -* "The "monitor mode" of operation is that the MAC passes all -* frames for which the PLCP checks are correct. All received -* MPDUs are passed to the host with MAC Port = 7, with a -* receive status of good, FCS error, or undecryptable. Passing -* certain MPDUs is a violation of the 802.11 standard, but useful -* for a debugging tool." Normal communication is not possible -* while monitor mode is enabled. -* -* Arguments: -* hw device structure -* enable a code (0x0b|0x0f) that enables/disables -* monitor mode. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | - HFA384x_CMD_AINFO_SET(enable); - cmd.parm0 = 0; - cmd.parm1 = 0; - cmd.parm2 = 0; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_download -* -* Sets the controls for the MAC controller code/data download -* process. The arguments set the mode and address associated -* with a download. Note that the aux registers should be enabled -* prior to setting one of the download enable modes. -* -* Arguments: -* hw device structure -* mode 0 - Disable programming and begin code exec -* 1 - Enable volatile mem programming -* 2 - Enable non-volatile mem programming -* 3 - Program non-volatile section from NV download -* buffer. -* (host order) -* lowaddr -* highaddr For mode 1, sets the high & low order bits of -* the "destination address". This address will be -* the execution start address when download is -* subsequently disabled. -* For mode 2, sets the high & low order bits of -* the destination in NV ram. -* For modes 0 & 3, should be zero. (host order) -* NOTE: these address args are in CMD format -* codelen Length of the data to write in mode 2, -* zero otherwise. (host order) -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_download(hfa384x_t *hw, UINT16 mode, UINT16 lowaddr, - UINT16 highaddr, UINT16 codelen) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | - HFA384x_CMD_PROGMODE_SET(mode); - cmd.parm0 = lowaddr; - cmd.parm1 = highaddr; - cmd.parm2 = codelen; - - spin_lock_bh(&hw->cmdlock); - result = hfa384x_dl_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_aux_enable -* -* Goes through the process of enabling the auxilary port. This -* is necessary prior to raw reads/writes to card data space. -* Direct access to the card data space is only used for downloading -* code and debugging. -* Note that a call to this function is required before attempting -* a download. -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force) -{ - int result = -ETIMEDOUT; - unsigned long flags; - UINT32 retries_remaining; - UINT16 reg; - UINT auxen_mirror = hw->auxen; - - DBFENTER; - - /* Check for existing enable */ - if ( hw->auxen ) { - hw->auxen++; - return 0; - } - - /* acquire the lock */ - spin_lock_irqsave( &(hw->cmdlock), flags); - /* wait for cmd register busy bit to clear */ - retries_remaining = 100000; - do { - reg = hfa384x_getreg(hw, HFA384x_CMD); - udelay(10); - } - while (HFA384x_CMD_ISBUSY(reg) && --retries_remaining); - if (retries_remaining != 0) { - /* busy bit clear, it's OK to write to ParamX regs */ - hfa384x_setreg(hw, HFA384x_AUXPW0, - HFA384x_PARAM0); - hfa384x_setreg(hw, HFA384x_AUXPW1, - HFA384x_PARAM1); - hfa384x_setreg(hw, HFA384x_AUXPW2, - HFA384x_PARAM2); - - /* Set the aux enable in the Control register */ - hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DOENABLE, - HFA384x_CONTROL); - - /* Now wait for completion */ - retries_remaining = 100000; - do { - reg = hfa384x_getreg(hw, HFA384x_CONTROL); - udelay(10); - } - while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISENABLED) && - --retries_remaining ); - if (retries_remaining != 0) { - result = 0; - hw->auxen++; - } - } - - /* Force it enabled even if the command failed, if told.. */ - if ((hw->auxen == auxen_mirror) && force) - hw->auxen++; - - spin_unlock_irqrestore( &(hw->cmdlock), flags); - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_aux_disable -* -* Goes through the process of disabling the auxilary port -* enabled with aux_enable(). -* -* Arguments: -* hw device structure -* -* Returns: -* 0 success -* >0 f/w reported failure - f/w status code -* <0 driver reported error (timeout) -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_cmd_aux_disable(hfa384x_t *hw) -{ - int result = -ETIMEDOUT; - unsigned long timeout; - UINT16 reg = 0; - - DBFENTER; - - /* See if there's more than one enable */ - if (hw->auxen) hw->auxen--; - if (hw->auxen) return 0; - - /* Clear the aux enable in the Control register */ - hfa384x_setreg(hw, 0, HFA384x_PARAM0); - hfa384x_setreg(hw, 0, HFA384x_PARAM1); - hfa384x_setreg(hw, 0, HFA384x_PARAM2); - hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DODISABLE, - HFA384x_CONTROL); - - /* Now wait for completion */ - timeout = jiffies + 1*HZ; - reg = hfa384x_getreg(hw, HFA384x_CONTROL); - while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISDISABLED) && - time_before(jiffies,timeout) ){ - udelay(10); - reg = hfa384x_getreg(hw, HFA384x_CONTROL); - } - if ((reg & (BIT14|BIT15)) == HFA384x_CONTROL_AUX_ISDISABLED ) { - result = 0; - } - DBFEXIT; - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_drvr_low_level -* -* Write test commands to the card. Some test commands don't make -* sense without prior set-up. For example, continous TX isn't very -* useful until you set the channel. That functionality should be -* -* Side effects: -* -* Call context: -* process thread -* -----------------------------------------------------------------*/ -int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) -{ - int result = 0; - DBFENTER; - - /* Do i need a host2hfa... conversion ? */ -#if 0 - printk(KERN_INFO "%#x %#x %#x %#x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); -#endif - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/* TODO: determine if these will ever be needed */ -#if 0 -int hfa384x_cmd_readmif(hfa384x_t *hw) -{ - DBFENTER; - DBFEXIT; - return 0; -} - - -int hfa384x_cmd_writemif(hfa384x_t *hw) -{ - DBFENTER; - DBFEXIT; - return 0; -} -#endif - -/*---------------------------------------------------------------- -* hfa384x_drvr_mmi_read -* -* Read mmi registers. mmi is intersil-speak for the baseband -* processor registers. -* -* Arguments: -* hw device structure -* register The test register to be accessed (must be even #). -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - cmd.cmd = (UINT16) 0x30; - cmd.parm0 = (UINT16) addr; - cmd.parm1 = 0; - cmd.parm2 = 0; - - /* Do i need a host2hfa... conversion ? */ - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - *resp = (UINT32) cmd.result.resp0; - - DBFEXIT; - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_drvr_mmi_write -* -* Read mmi registers. mmi is intersil-speak for the baseband -* processor registers. -* -* Arguments: -* hw device structure -* addr The test register to be accessed (must be even #). -* data The data value to write to the register. -* -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ - -int -hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data) -{ - int result = 0; - hfa384x_metacmd_t cmd; - - DBFENTER; - cmd.cmd = (UINT16) 0x31; - cmd.parm0 = (UINT16) addr; - cmd.parm1 = (UINT16) data; - cmd.parm2 = 0; - - WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08x\n", addr); - WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08x\n", data); - - /* Do i need a host2hfa... conversion ? */ - spin_lock_bh(&hw->cmdlock); - result = hfa384x_docmd_wait(hw, &cmd); - spin_unlock_bh(&hw->cmdlock); - - DBFEXIT; - return result; -} - - -/* TODO: determine if these will ever be needed */ -#if 0 -int hfa384x_cmd_readmif(hfa384x_t *hw) -{ - DBFENTER; - DBFEXIT; - return 0; -} - - -int hfa384x_cmd_writemif(hfa384x_t *hw) -{ - DBFENTER; - DBFEXIT; - return 0; -} -#endif - - - -/*---------------------------------------------------------------- -* hfa384x_copy_from_bap -* -* Copies a collection of bytes from the MAC controller memory via -* one set of BAP registers. -* -* Arguments: -* hw device structure -* bap [0|1] which BAP to use -* id FID or RID, destined for the select register (host order) -* offset An _even_ offset into the buffer for the given -* FID/RID. We haven't the means to validate this, -* so be careful. (host order) -* buf ptr to array of bytes -* len length of data to transfer in bytes -* -* Returns: -* 0 success -* >0 f/w reported failure - value of offset reg. -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, - void *buf, UINT len) -{ - int result = 0; - unsigned long flags = 0; - UINT8 *d = (UINT8*)buf; - UINT selectreg; - UINT offsetreg; - UINT datareg; - UINT i; - UINT16 reg = 0; - - DBFENTER; - - /* Validate bap, offset, buf, and len */ - if ( (bap > 1) || - (offset > HFA384x_BAP_OFFSET_MAX) || - (offset % 2) || - (buf == NULL) || - (len > HFA384x_BAP_DATALEN_MAX) ){ - result = -EINVAL; - } else { - selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0 ; - offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0 ; - datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0 ; - - /* Obtain lock */ - spin_lock_irqsave( &(hw->baplock), flags); - - /* Write id to select reg */ - hfa384x_setreg(hw, id, selectreg); - /* Write offset to offset reg */ - hfa384x_setreg(hw, offset, offsetreg); - /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ - i = 0; - do { - reg = hfa384x_getreg(hw, offsetreg); - if ( i > 0 ) udelay(10); - i++; - } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); -#if (WLAN_HOSTIF != WLAN_PCI) - /* Release lock */ - spin_unlock_irqrestore( &(hw->baplock), flags); -#endif - - if ( HFA384x_OFFSET_ISBUSY(reg) ){ - /* If timeout, return -ETIMEDOUT */ - result = reg; - } else if ( HFA384x_OFFSET_ISERR(reg) ){ - /* If offset[err] == 1, return -EINVAL */ - result = reg; - } else { - /* Read even(len) buf contents from data reg */ - for ( i = 0; i < (len & 0xfffe); i+=2 ) { - *(UINT16*)(&(d[i])) = - hfa384x_getreg_noswap(hw, datareg); - } - /* If len odd, handle last byte */ - if ( len % 2 ){ - reg = hfa384x_getreg_noswap(hw, datareg); - d[len-1] = ((UINT8*)(®))[0]; - } - } - - /* According to Intersil errata dated 9/16/02: - - "In PRISM PCI MAC host interface, if both BAPs are concurrently - requesing memory access, both will accept the Ack. There is no - firmware workaround possible. To prevent BAP access failures or - hang conditions the host MUST NOT access both BAPs in sucession - unless at least 5us elapses between accesses. The safest choice - is to USE ONLY ONE BAP for all data movement operations." - - What this means: - - We have to serialize ALL BAP accesses, and furthermore, add a 5us - delay after access if we're using a PCI platform. - - Unfortunately, this means we have to lock out interrupts througout - the entire BAP copy. - - It remains to be seen if "BAP access" means "BAP setup" or the more - literal definition of "copying data back and forth" I'm erring for - the latter, safer definition. -- SLP. - - */ - -#if (WLAN_HOSTIF == WLAN_PCI) - udelay(5); - /* Release lock */ - spin_unlock_irqrestore( &(hw->baplock), flags); -#endif - - } - - if (result) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", - reg, len, result); - } - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_copy_to_bap -* -* Copies a collection of bytes to the MAC controller memory via -* one set of BAP registers. -* -* Arguments: -* hw device structure -* bap [0|1] which BAP to use -* id FID or RID, destined for the select register (host order) -* offset An _even_ offset into the buffer for the given -* FID/RID. We haven't the means to validate this, -* so be careful. (host order) -* buf ptr to array of bytes -* len length of data to transfer (in bytes) -* -* Returns: -* 0 success -* >0 f/w reported failure - value of offset reg. -* <0 driver reported error (timeout|bad arg) -* -* Side effects: -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, - void *buf, UINT len) -{ - return hfa384x_copy_to_bap4(hw, bap, id, offset, buf, len, NULL, 0, NULL, 0, NULL, 0); -} - -int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset, - void *buf, UINT len1, void* buf2, UINT len2, - void *buf3, UINT len3, void *buf4, UINT len4) -{ - int result = 0; - unsigned long flags = 0; - UINT8 *d; - UINT selectreg; - UINT offsetreg; - UINT datareg; - UINT i; - UINT16 reg; - - DBFENTER; - -// printk(KERN_DEBUG "ctb1 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); - - /* Validate bap, offset, buf, and len */ - if ( (bap > 1) || - (offset > HFA384x_BAP_OFFSET_MAX) || - (offset % 2) || - (buf == NULL) || - (len1+len2+len3+len4 > HFA384x_BAP_DATALEN_MAX) ){ - result = -EINVAL; - } else { - selectreg = (bap == 1) ? HFA384x_SELECT1 : HFA384x_SELECT0; - offsetreg = (bap == 1) ? HFA384x_OFFSET1 : HFA384x_OFFSET0; - datareg = (bap == 1) ? HFA384x_DATA1 : HFA384x_DATA0; - /* Obtain lock */ - spin_lock_irqsave( &(hw->baplock), flags); - - /* Write id to select reg */ - hfa384x_setreg(hw, id, selectreg); - udelay(10); - /* Write offset to offset reg */ - hfa384x_setreg(hw, offset, offsetreg); - /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ - i = 0; - do { - reg = hfa384x_getreg(hw, offsetreg); - if ( i > 0 ) udelay(10); - i++; - } while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg)); - -#if (WLAN_HOSTIF != WLAN_PCI) - /* Release lock */ - spin_unlock_irqrestore( &(hw->baplock), flags); -#endif - - if ( HFA384x_OFFSET_ISBUSY(reg) ){ - /* If timeout, return reg */ - result = reg; - } else if ( HFA384x_OFFSET_ISERR(reg) ){ - /* If offset[err] == 1, return reg */ - result = reg; - } else { - d = (UINT8*)buf; - /* Write even(len1) buf contents to data reg */ - for ( i = 0; i < (len1 & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, - *(UINT16*)(&(d[i])), datareg); - } - if (len1 & 1) { - UINT16 data; - UINT8 *b = (UINT8 *) &data; - b[0] = d[len1-1]; - if (buf2 != NULL) { - d = (UINT8*)buf2; - b[1] = d[0]; - len2--; - buf2++; - } - hfa384x_setreg_noswap(hw, data, datareg); - } - if ((buf2 != NULL) && (len2 > 0)) { - /* Write even(len2) buf contents to data reg */ - d = (UINT8*)buf2; - for ( i = 0; i < (len2 & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); - } - if (len2 & 1) { - UINT16 data; - UINT8 *b = (UINT8 *) &data; - b[0] = d[len2-1]; - if (buf3 != NULL) { - d = (UINT8*)buf3; - b[1] = d[0]; - len3--; - buf3++; - } - hfa384x_setreg_noswap(hw, data, datareg); - } - } - - if ((buf3 != NULL) && (len3 > 0)) { - /* Write even(len3) buf contents to data reg */ - d = (UINT8*)buf3; - for ( i = 0; i < (len3 & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); - } - if (len3 & 1) { - UINT16 data; - UINT8 *b = (UINT8 *) &data; - b[0] = d[len3-1]; - if (buf4 != NULL) { - d = (UINT8*)buf4; - b[1] = d[0]; - len4--; - buf4++; - } - hfa384x_setreg_noswap(hw, data, datareg); - } - } - if ((buf4 != NULL) && (len4 > 0)) { - /* Write even(len4) buf contents to data reg */ - d = (UINT8*)buf4; - for ( i = 0; i < (len4 & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), datareg); - } - if (len4 & 1) { - UINT16 data; - UINT8 *b = (UINT8 *) &data; - b[0] = d[len4-1]; - b[1] = 0; - - hfa384x_setreg_noswap(hw, data, datareg); - } - } -// printk(KERN_DEBUG "ctb2 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4); - - } - -#if (WLAN_HOSTIF == WLAN_PCI) - udelay(5); - /* Release lock */ - spin_unlock_irqrestore( &(hw->baplock), flags); -#endif - - } - - if (result) - WLAN_LOG_ERROR("copy_to_bap() failed.\n"); - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_copy_from_aux -* -* Copies a collection of bytes from the controller memory. The -* Auxiliary port MUST be enabled prior to calling this function. -* We _might_ be in a download state. -* -* Arguments: -* hw device structure -* cardaddr address in hfa384x data space to read -* auxctl address space select -* buf ptr to destination host buffer -* len length of data to transfer (in bytes) -* -* Returns: -* nothing -* -* Side effects: -* buf contains the data copied -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -void -hfa384x_copy_from_aux( - hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) -{ - UINT16 currpage; - UINT16 curroffset; - UINT i = 0; - - DBFENTER; - - if ( !(hw->auxen) ) { - WLAN_LOG_DEBUG(1, - "Attempt to read 0x%04x when aux not enabled\n", - cardaddr); - return; - - } - /* Build appropriate aux page and offset */ - currpage = HFA384x_AUX_MKPAGE(cardaddr); - curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); - hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); - hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); - udelay(5); /* beat */ - - /* read the data */ - while ( i < len) { - *((UINT16*)(buf+i)) = hfa384x_getreg_noswap(hw, HFA384x_AUXDATA); - i+=2; - curroffset+=2; - if ( (curroffset&HFA384x_ADDR_AUX_OFF_MASK) > - HFA384x_ADDR_AUX_OFF_MAX ) { - currpage++; - curroffset = 0; - curroffset = HFA384x_AUX_MKOFF(curroffset, auxctl); - hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); - hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); - udelay(5); /* beat */ - } - } - /* Make sure the auxctl bits are clear */ - hfa384x_setreg(hw, 0, HFA384x_AUXOFFSET); - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* hfa384x_copy_to_aux -* -* Copies a collection of bytes to the controller memory. The -* Auxiliary port MUST be enabled prior to calling this function. -* We _might_ be in a download state. -* -* Arguments: -* hw device structure -* cardaddr address in hfa384x data space to read -* auxctl address space select -* buf ptr to destination host buffer -* len length of data to transfer (in bytes) -* -* Returns: -* nothing -* -* Side effects: -* Controller memory now contains a copy of buf -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -void -hfa384x_copy_to_aux( - hfa384x_t *hw, UINT32 cardaddr, UINT32 auxctl, void *buf, UINT len) -{ - UINT16 currpage; - UINT16 curroffset; - UINT i = 0; - - DBFENTER; - - if ( !(hw->auxen) ) { - WLAN_LOG_DEBUG(1, - "Attempt to read 0x%04x when aux not enabled\n", - cardaddr); - return; - - } - /* Build appropriate aux page and offset */ - currpage = HFA384x_AUX_MKPAGE(cardaddr); - curroffset = HFA384x_AUX_MKOFF(cardaddr, auxctl); - hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); - hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); - udelay(5); /* beat */ - - /* write the data */ - while ( i < len) { - hfa384x_setreg_noswap(hw, - *((UINT16*)(buf+i)), HFA384x_AUXDATA); - i+=2; - curroffset+=2; - if ( curroffset > HFA384x_ADDR_AUX_OFF_MAX ) { - currpage++; - curroffset = 0; - hfa384x_setreg(hw, currpage, HFA384x_AUXPAGE); - hfa384x_setreg(hw, curroffset, HFA384x_AUXOFFSET); - udelay(5); /* beat */ - } - } - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* hfa384x_cmd_wait -* -* Waits for availability of the Command register, then -* issues the given command. Then polls the Evstat register -* waiting for command completion. Timeouts shouldn't be -* possible since we're preventing overlapping commands and all -* commands should be cleared and acknowledged. -* -* Arguments: -* wlandev device structure -* cmd cmd structure. Includes all arguments and result -* data points. All in host order. -* -* Returns: -* 0 success -* -ETIMEDOUT timed out waiting for register ready or -* command completion -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* -* Call context: -* process thread -----------------------------------------------------------------*/ -static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) -{ - int result = -ETIMEDOUT; - UINT16 reg = 0; - UINT16 counter; - - DBFENTER; - - hw->cmdflag = 0; - hw->cmddata = cmd; - - /* wait for the busy bit to clear */ - counter = 0; - reg = hfa384x_getreg(hw, HFA384x_CMD); - while ( HFA384x_CMD_ISBUSY(reg) && - (counter < 10)) { - reg = hfa384x_getreg(hw, HFA384x_CMD); - counter++; - udelay(10); - } - - if (HFA384x_CMD_ISBUSY(reg)) { - WLAN_LOG_ERROR("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg); - goto failed; - } - if (!HFA384x_CMD_ISBUSY(reg)) { - /* busy bit clear, write command */ - hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); - hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); - hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); - hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); - -#ifdef CMD_IRQ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) - while (! hw->cmdflag) - interruptible_sleep_on(&hw->cmdq); -#else - wait_event_interruptible(hw->cmdq, hw->cmdflag); -#endif - result = HFA384x_STATUS_RESULT_GET(cmd->status); -#else // CMD_IRQ - /* Now wait for completion */ - counter = 0; - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - /* Initialization is the problem. It takes about - 100ms. "normal" commands are typically is about - 200-400 us (I've never seen less than 200). Longer - is better so that we're not hammering the bus. */ - while ( !HFA384x_EVSTAT_ISCMD(reg) && - (counter < 5000)) { - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - counter++; - udelay(200); - } - - if ( HFA384x_EVSTAT_ISCMD(reg) ) { - result = 0; - cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); - cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); - cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); - cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); - hfa384x_setreg(hw, HFA384x_EVACK_CMD, - HFA384x_EVACK); - result = HFA384x_STATUS_RESULT_GET(cmd->result.status); - } else { - WLAN_LOG_ERROR("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg); - } -#endif /* CMD_IRQ */ - } - - failed: - hw->cmdflag = 0; - hw->cmddata = NULL; - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_dl_docmd_wait -* -* Waits for availability of the Command register, then -* issues the given command. Then polls the Evstat register -* waiting for command completion. Timeouts shouldn't be -* possible since we're preventing overlapping commands and all -* commands should be cleared and acknowledged. -* -* This routine is only used for downloads. Since it doesn't lock out -* interrupts the system response is much better. -* -* Arguments: -* wlandev device structure -* cmd cmd structure. Includes all arguments and result -* data points. All in host order. -* -* Returns: -* 0 success -* -ETIMEDOUT timed out waiting for register ready or -* command completion -* >0 command indicated error, Status and Resp0-2 are -* in hw structure. -* -* Side effects: -* -* -* Call context: -* process thread -----------------------------------------------------------------*/ -static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd) -{ - int result = -ETIMEDOUT; - unsigned long timeout; - UINT16 reg = 0; - - DBFENTER; - /* wait for the busy bit to clear */ - timeout = jiffies + 1*HZ; - reg = hfa384x_getreg(hw, HFA384x_CMD); - while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { - reg = hfa384x_getreg(hw, HFA384x_CMD); - udelay(10); - } - if (HFA384x_CMD_ISBUSY(reg)) { - WLAN_LOG_WARNING("Timed out waiting for cmd register.\n"); - goto failed; - } - - if (!HFA384x_CMD_ISBUSY(reg)) { - /* busy bit clear, write command */ - hfa384x_setreg(hw, cmd->parm0, HFA384x_PARAM0); - hfa384x_setreg(hw, cmd->parm1, HFA384x_PARAM1); - hfa384x_setreg(hw, cmd->parm2, HFA384x_PARAM2); - hfa384x_setreg(hw, cmd->cmd, HFA384x_CMD); - - /* Now wait for completion */ - if ( (HFA384x_CMD_CMDCODE_GET(cmd->cmd) == HFA384x_CMDCODE_DOWNLD) ) { - /* dltimeout is in ms */ - timeout = (((UINT32)hw->dltimeout) / 1000UL) * HZ; - if ( timeout > 0 ) { - timeout += jiffies; - } else { - timeout = jiffies + 1*HZ; - } - } else { - timeout = jiffies + 1*HZ; - } - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - while ( !HFA384x_EVSTAT_ISCMD(reg) && time_before(jiffies,timeout) ) { - udelay(100); - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - } - if ( HFA384x_EVSTAT_ISCMD(reg) ) { - result = 0; - cmd->result.status = hfa384x_getreg(hw, HFA384x_STATUS); - cmd->result.resp0 = hfa384x_getreg(hw, HFA384x_RESP0); - cmd->result.resp1 = hfa384x_getreg(hw, HFA384x_RESP1); - cmd->result.resp2 = hfa384x_getreg(hw, HFA384x_RESP2); - hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK); - result = HFA384x_STATUS_RESULT_GET(cmd->result.status); - } - } - -failed: - DBFEXIT; - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_drvr_start -* -* Issues the MAC initialize command, sets up some data structures, -* and enables the interrupts. After this function completes, the -* low-level stuff should be ready for any/all commands. -* -* Arguments: -* hw device structure -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_start(hfa384x_t *hw) -{ - int result = 0; - UINT16 reg; - int i; - int j; - DBFENTER; - - /* call initialize */ - result = hfa384x_cmd_initialize(hw); - if (result != 0) { - WLAN_LOG_ERROR("Initialize command failed.\n"); - goto failed; - } - - /* make sure interrupts are disabled and any layabout events cleared */ - hfa384x_setreg(hw, 0, HFA384x_INTEN); - hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); - - hw->txfid_head = 0; - hw->txfid_tail = 0; - hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX; - memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue)); - - /* Allocate tx and notify FIDs */ - /* First, tx */ - for ( i = 0; i < HFA384x_DRVR_FIDSTACKLEN_MAX-1; i++) { - result = hfa384x_cmd_allocate(hw, HFA384x_DRVR_TXBUF_MAX); - if (result != 0) { - WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); - goto failed; - } - j = 0; - do { - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - udelay(10); - j++; - } while ( !HFA384x_EVSTAT_ISALLOC(reg) && j < 50); /* 50 is timeout */ - if ( j >= 50 ) { - WLAN_LOG_ERROR("Timed out waiting for evalloc(tx).\n"); - result = -ETIMEDOUT; - goto failed; - } - reg = hfa384x_getreg(hw, HFA384x_ALLOCFID); - - txfid_queue_add(hw, reg); - - WLAN_LOG_DEBUG(4,"hw->txfid_queue[%d]=0x%04x\n",i,reg); - - reg = HFA384x_EVACK_ALLOC_SET(1); - hfa384x_setreg(hw, reg, HFA384x_EVACK); - - } - - /* Now, the info frame fid */ - result = hfa384x_cmd_allocate(hw, HFA384x_INFOFRM_MAXLEN); - if (result != 0) { - WLAN_LOG_ERROR("Allocate(tx) command failed.\n"); - goto failed; - } - i = 0; - do { - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - udelay(10); - i++; - } while ( !HFA384x_EVSTAT_ISALLOC(reg) && i < 50); /* 50 is timeout */ - if ( i >= 50 ) { - WLAN_LOG_ERROR("Timed out waiting for evalloc(info).\n"); - result = -ETIMEDOUT; - goto failed; - } - hw->infofid = hfa384x_getreg(hw, HFA384x_ALLOCFID); - reg = HFA384x_EVACK_ALLOC_SET(1); - hfa384x_setreg(hw, reg, HFA384x_EVACK); - WLAN_LOG_DEBUG(4,"hw->infofid=0x%04x\n", hw->infofid); - - /* Set swsupport regs to magic # for card presence detection */ - hfa384x_setreg(hw, HFA384x_DRVR_MAGIC, HFA384x_SWSUPPORT0); - - /* Now enable the interrupts and set the running state */ - hfa384x_setreg(hw, 0xffff, HFA384x_EVSTAT); - hfa384x_events_all(hw); - - hw->state = HFA384x_STATE_RUNNING; - - goto done; -failed: - WLAN_LOG_ERROR("Failed, result=%d\n", result); -done: - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_stop -* -* Issues the initialize command to leave us in the 'reset' state. -* -* Arguments: -* hw device structure -* Returns: -* 0 success -* >0 f/w reported error - f/w status code -* <0 driver reported error -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_stop(hfa384x_t *hw) -{ - int result = 0; - int i; - DBFENTER; - - del_timer_sync(&hw->commsqual_timer); - - if ( hw->wlandev->hwremoved ) { - /* only flush when we're shutting down for good */ - flush_scheduled_work(); - } - - if (hw->state == HFA384x_STATE_RUNNING) { - /* - * Send the MAC initialize cmd. - */ - hfa384x_cmd_initialize(hw); - - /* - * Make absolutely sure interrupts are disabled and any - * layabout events cleared - */ - hfa384x_setreg(hw, 0, HFA384x_INTEN); - hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); - } - - tasklet_kill(&hw->bap_tasklet); - - hw->link_status = HFA384x_LINK_NOTCONNECTED; - hw->state = HFA384x_STATE_INIT; - - /* Clear all the port status */ - for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { - hw->port_enabled[i] = 0; - } - - DBFEXIT; - return result; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_txframe -* -* Takes a frame from prism2sta and queues it for transmission. -* -* Arguments: -* hw device structure -* skb packet buffer struct. Contains an 802.11 -* data frame. -* p80211_hdr points to the 802.11 header for the packet. -* Returns: -* 0 Success and more buffs available -* 1 Success but no more buffs -* 2 Allocation failure -* 3 MAC Tx command failed -* 4 Buffer full or queue busy -* -* Side effects: -* -* Call context: -* process thread -----------------------------------------------------------------*/ -int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) -{ - hfa384x_tx_frame_t txdesc; - UINT16 macq = 0; - UINT16 fid; - int result; - - DBFENTER; - - /* Build Tx frame structure */ - /* Set up the control field */ - memset(&txdesc, 0, sizeof(txdesc)); - -/* Tx complete and Tx exception disable per dleach. Might be causing - * buf depletion - */ -#define DOBOTH 1 -#if DOBOTH - txdesc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); -#elif DOEXC - txdesc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); -#else - txdesc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); -#endif - - /* if we're using host WEP, increase size by IV+ICV */ - if (p80211_wep->data) { - txdesc.data_len = host2hfa384x_16(skb->len+8); - // txdesc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); - } else { - txdesc.data_len = host2hfa384x_16(skb->len); - } - - txdesc.tx_control = host2hfa384x_16(txdesc.tx_control); - /* copy the header over to the txdesc */ - memcpy(&(txdesc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); - - /* Since tbusy is set whenever the stack is empty, there should - * always be something on the stack if we get to this point. - * [MSM]: NOT TRUE!!!!! so I added the test of fid below. - */ - - /* Allocate FID */ - - fid = txfid_queue_remove(hw); - - if ( fid == 0 ) { /* stack or queue was empty */ - return 4; - } - - /* now let's get the cmdlock */ - spin_lock(&hw->cmdlock); - - /* Copy descriptor+payload to FID */ - if (p80211_wep->data) { - result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, - &txdesc, sizeof(txdesc), - p80211_wep->iv, sizeof(p80211_wep->iv), - p80211_wep->data, skb->len, - p80211_wep->icv, sizeof(p80211_wep->icv)); - } else { - result = hfa384x_copy_to_bap4(hw, HFA384x_BAP_PROC, fid, 0, - &txdesc, sizeof(txdesc), - skb->data, skb->len, - NULL, 0, NULL, 0); - } - - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_to_bap(%04x, %d, %d) failed, result=0x%x\n", - fid, - sizeof(txdesc), - skb->len, - result); - - /* put the fid back in the queue */ - txfid_queue_add(hw, fid); - - result = 3; - goto failed; - } - - /* Issue Tx command */ - result = hfa384x_cmd_transmit(hw, HFA384x_TXCMD_RECL, macq, fid); - - if ( result != 0 ) { - txfid_queue_add(hw, fid); - - WLAN_LOG_DEBUG(1,"cmd_tx(%04x) failed, result=%d\n", - fid, result); - result = 3; - goto failed; - } - - /* indicate we haven't any buffers, int_alloc will clear */ - result = txfid_queue_empty(hw); -failed: - - spin_unlock(&hw->cmdlock); - - DBFEXIT; - return result; -} - -/*---------------------------------------------------------------- -* hfa384x_interrupt -* -* Driver interrupt handler. -* -* Arguments: -* irq irq number -* dev_id pointer to the device -* regs registers -* -* Returns: -* nothing -* -* Side effects: -* May result in a frame being passed up the stack or an info -* frame being handled. -* -* Call context: -* Ummm, could it be interrupt? -----------------------------------------------------------------*/ -irqreturn_t hfa384x_interrupt(int irq, void *dev_id PT_REGS) -{ - int reg; - wlandevice_t *wlandev = (wlandevice_t*)dev_id; - hfa384x_t *hw = wlandev->priv; - int ev_read = 0; - DBFENTER; - - if (!wlandev || wlandev->hwremoved) - return IRQ_NONE; /* Not much we can do w/o hardware */ -#if (WLAN_HOSTIF == WLAN_PCMCIA) - if (hw->iobase == 0) /* XXX FIXME Properly */ - return IRQ_NONE; -#endif - - for (;;ev_read++) { - if (ev_read >= prism2_irq_evread_max) - break; - - /* Check swsupport reg magic # for card presence */ - reg = hfa384x_getreg(hw, HFA384x_SWSUPPORT0); - if ( reg != HFA384x_DRVR_MAGIC) { - WLAN_LOG_DEBUG(2, "irq=%d, no magic. Card removed?.\n", irq); - break; - } - - /* read the EvStat register for interrupt enabled events */ - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - - /* AND with the enabled interrupts */ - reg &= hfa384x_getreg(hw, HFA384x_INTEN); - - /* Handle the events */ - if ( HFA384x_EVSTAT_ISWTERR(reg) ){ - WLAN_LOG_ERROR( - "Error: WTERR interrupt received (unhandled).\n"); - hfa384x_setreg(hw, HFA384x_EVACK_WTERR_SET(1), - HFA384x_EVACK); - } - - if ( HFA384x_EVSTAT_ISINFDROP(reg) ){ - hfa384x_int_infdrop(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_INFDROP_SET(1), - HFA384x_EVACK); - } - - if (HFA384x_EVSTAT_ISBAP_OP(reg)) { - /* Disable the BAP interrupts */ - hfa384x_events_nobap(hw); - tasklet_schedule(&hw->bap_tasklet); - } - - if ( HFA384x_EVSTAT_ISALLOC(reg) ){ - hfa384x_int_alloc(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_ALLOC_SET(1), - HFA384x_EVACK); - } - - if ( HFA384x_EVSTAT_ISDTIM(reg) ){ - hfa384x_int_dtim(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_DTIM_SET(1), - HFA384x_EVACK); - } -#ifdef CMD_IRQ - if ( HFA384x_EVSTAT_ISCMD(reg) ){ - hfa384x_int_cmd(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_CMD_SET(1), - HFA384x_EVACK); - } -#endif - - /* allow the evstat to be updated after the evack */ - udelay(20); - } - - DBFEXIT; - return IRQ_HANDLED; -} - -#ifdef CMD_IRQ -/*---------------------------------------------------------------- -* hfa384x_int_cmd -* -* Handles command completion event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -void hfa384x_int_cmd(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - DBFENTER; - - // check to make sure it's the right command? - if (hw->cmddata) { - hw->cmddata->status = hfa384x_getreg(hw, HFA384x_STATUS); - hw->cmddata->resp0 = hfa384x_getreg(hw, HFA384x_RESP0); - hw->cmddata->resp1 = hfa384x_getreg(hw, HFA384x_RESP1); - hw->cmddata->resp2 = hfa384x_getreg(hw, HFA384x_RESP2); - } - hw->cmdflag = 1; - - printk(KERN_INFO "um. int_cmd\n"); - - wake_up_interruptible(&hw->cmdq); - - // XXXX perform a bap copy too? - - DBFEXIT; - return; -} -#endif - -/*---------------------------------------------------------------- -* hfa384x_int_dtim -* -* Handles the DTIM early warning event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -static void hfa384x_int_dtim(wlandevice_t *wlandev) -{ -#if 0 - hfa384x_t *hw = wlandev->priv; -#endif - DBFENTER; - prism2sta_ev_dtim(wlandev); - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_int_infdrop -* -* Handles the InfDrop event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -static void hfa384x_int_infdrop(wlandevice_t *wlandev) -{ -#if 0 - hfa384x_t *hw = wlandev->priv; -#endif - DBFENTER; - prism2sta_ev_infdrop(wlandev); - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_int_info -* -* Handles the Info event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* tasklet -----------------------------------------------------------------*/ -static void hfa384x_int_info(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - UINT16 reg; - hfa384x_InfFrame_t inf; - int result; - DBFENTER; - /* Retrieve the FID */ - reg = hfa384x_getreg(hw, HFA384x_INFOFID); - - /* Retrieve the length */ - result = hfa384x_copy_from_bap( hw, - HFA384x_BAP_INT, reg, 0, &inf.framelen, sizeof(UINT16)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", - reg, sizeof(inf), result); - goto failed; - } - inf.framelen = hfa384x2host_16(inf.framelen); - - /* Retrieve the rest */ - result = hfa384x_copy_from_bap( hw, - HFA384x_BAP_INT, reg, sizeof(UINT16), - &(inf.infotype), inf.framelen * sizeof(UINT16)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", - reg, sizeof(inf), result); - goto failed; - } - - prism2sta_ev_info(wlandev, &inf); -failed: - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_int_txexc -* -* Handles the TxExc event. A Transmit Exception event indicates -* that the MAC's TX process was unsuccessful - so the packet did -* not get transmitted. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* tasklet -----------------------------------------------------------------*/ -static void hfa384x_int_txexc(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - UINT16 status; - UINT16 fid; - int result = 0; - DBFENTER; - /* Collect the status and display */ - fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); - result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", - fid, sizeof(status), result); - goto failed; - } - status = hfa384x2host_16(status); - prism2sta_ev_txexc(wlandev, status); -failed: - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_int_tx -* -* Handles the Tx event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* tasklet -----------------------------------------------------------------*/ -static void hfa384x_int_tx(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - UINT16 fid; - UINT16 status; - int result = 0; - DBFENTER; - fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); - result = hfa384x_copy_from_bap(hw, HFA384x_BAP_INT, fid, 0, &status, sizeof(status)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", - fid, sizeof(status), result); - goto failed; - } - status = hfa384x2host_16(status); - prism2sta_ev_tx(wlandev, status); -failed: - DBFEXIT; - return; -} - -/*---------------------------------------------------------------- -* hfa384x_int_rx -* -* Handles the Rx event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* tasklet -----------------------------------------------------------------*/ -static void hfa384x_int_rx(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - UINT16 rxfid; - hfa384x_rx_frame_t rxdesc; - int result; - int hdrlen; - UINT16 fc; - p80211_rxmeta_t *rxmeta; - struct sk_buff *skb = NULL; - UINT8 *datap; - - DBFENTER; - - /* Get the FID */ - rxfid = hfa384x_getreg(hw, HFA384x_RXFID); - /* Get the descriptor (including headers) */ - result = hfa384x_copy_from_bap(hw, - HFA384x_BAP_INT, - rxfid, - 0, - &rxdesc, - sizeof(rxdesc)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", - rxfid, - 0, - sizeof(rxdesc), - result); - goto done; - } - - /* Byte order convert once up front. */ - rxdesc.status = hfa384x2host_16(rxdesc.status); - rxdesc.time = hfa384x2host_32(rxdesc.time); - - /* drop errors and whatnot in promisc mode */ - if (( wlandev->netdev->flags & IFF_PROMISC ) && - (HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) || - HFA384x_RXSTATUS_ISUNDECR(rxdesc.status))) - goto done; - - /* Now handle frame based on port# */ - switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ) - { - case 0: - - fc = ieee2host16(rxdesc.frame_control); - - /* If exclude and we receive an unencrypted, drop it */ - if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && - !WLAN_GET_FC_ISWEP(fc)) { - goto done; - } - - hdrlen = p80211_headerlen(fc); - - /* Allocate the buffer, note CRC (aka FCS). pballoc */ - /* assumes there needs to be space for one */ - skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a little extra */ - - if ( ! skb ) { - WLAN_LOG_ERROR("alloc_skb failed.\n"); - goto done; - } - - skb->dev = wlandev->netdev; - - /* theoretically align the IP header on a 32-bit word. */ - if ( hdrlen == WLAN_HDR_A4_LEN ) - skb_reserve(skb, 2); - - /* Copy the 802.11 hdr to the buffer */ - datap = skb_put(skb, WLAN_HDR_A3_LEN); - memcpy(datap, &rxdesc.frame_control, WLAN_HDR_A3_LEN); - - /* Snag the A4 address if present */ - if (hdrlen == WLAN_HDR_A4_LEN) { - datap = skb_put(skb, WLAN_ADDR_LEN); - memcpy(datap, &rxdesc.address4, WLAN_HDR_A3_LEN); - } - - /* we can convert the data_len as we passed the original on */ - rxdesc.data_len = hfa384x2host_16(rxdesc.data_len); - - /* Copy the payload data to the buffer */ - if ( rxdesc.data_len > 0 ) { - datap = skb_put(skb, rxdesc.data_len); - result = hfa384x_copy_from_bap(hw, - HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, - datap, rxdesc.data_len); - if ( result ) { - WLAN_LOG_DEBUG(1, - "copy_from_bap(0x%04x, %d, %d) failed, result=0x%x\n", - rxfid, - HFA384x_RX_DATA_OFF, - rxdesc.data_len, - result); - goto failed; - } - } - /* the prism2 cards don't return the FCS */ - datap = skb_put(skb, WLAN_CRC_LEN); - memset (datap, 0xff, WLAN_CRC_LEN); - skb_reset_mac_header(skb); - - /* Attach the rxmeta, set some stuff */ - p80211skb_rxmeta_attach(wlandev, skb); - rxmeta = P80211SKB_RXMETA(skb); - rxmeta->mactime = rxdesc.time; - rxmeta->rxrate = rxdesc.rate; - rxmeta->signal = rxdesc.signal - hw->dbmadjust; - rxmeta->noise = rxdesc.silence - hw->dbmadjust; - - prism2sta_ev_rx(wlandev, skb); - goto done; - case 7: - - if ( ! HFA384x_RXSTATUS_ISFCSERR(rxdesc.status) ) { - hfa384x_int_rxmonitor( wlandev, rxfid, &rxdesc); - } else { - WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); - } - goto done; - - default: - - WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", - HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) ); - goto done; - } - - failed: - dev_kfree_skb(skb); - - done: - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_int_rxmonitor -* -* Helper function for int_rx. Handles monitor frames. -* Note that this function allocates space for the FCS and sets it -* to 0xffffffff. The hfa384x doesn't give us the FCS value but the -* higher layers expect it. 0xffffffff is used as a flag to indicate -* the FCS is bogus. -* -* Arguments: -* wlandev wlan device structure -* rxfid received FID -* rxdesc rx descriptor read from card in int_rx -* -* Returns: -* nothing -* -* Side effects: -* Allocates an skb and passes it up via the PF_PACKET interface. -* Call context: -* interrupt -----------------------------------------------------------------*/ -static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, - hfa384x_rx_frame_t *rxdesc) -{ - hfa384x_t *hw = wlandev->priv; - UINT hdrlen = 0; - UINT datalen = 0; - UINT skblen = 0; - UINT truncated = 0; - UINT8 *datap; - UINT16 fc; - struct sk_buff *skb; - - DBFENTER; - /* Don't forget the status, time, and data_len fields are in host order */ - /* Figure out how big the frame is */ - fc = ieee2host16(rxdesc->frame_control); - hdrlen = p80211_headerlen(fc); - datalen = hfa384x2host_16(rxdesc->data_len); - - /* Allocate an ind message+framesize skb */ - skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) + - hdrlen + datalen + WLAN_CRC_LEN; - - /* sanity check the length */ - if ( skblen > - (sizeof(p80211msg_lnxind_wlansniffrm_t) + - WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { - WLAN_LOG_DEBUG(1, "overlen frm: len=%d\n", - skblen - sizeof(p80211msg_lnxind_wlansniffrm_t)); - } - - if ( (skb = dev_alloc_skb(skblen)) == NULL ) { - WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); - return; - } - - /* only prepend the prism header if in the right mode */ - if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && - (hw->sniffhdr == 0)) { - p80211msg_lnxind_wlansniffrm_t *msg; - datap = skb_put(skb, sizeof(p80211msg_lnxind_wlansniffrm_t)); - msg = (p80211msg_lnxind_wlansniffrm_t*) datap; - - /* Initialize the message members */ - msg->msgcode = DIDmsg_lnxind_wlansniffrm; - msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t); - strcpy(msg->devname, wlandev->name); - - msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; - msg->hosttime.status = 0; - msg->hosttime.len = 4; - msg->hosttime.data = jiffies; - - msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; - msg->mactime.status = 0; - msg->mactime.len = 4; - msg->mactime.data = rxdesc->time * 1000; - - msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel; - msg->channel.status = 0; - msg->channel.len = 4; - msg->channel.data = hw->sniff_channel; - - msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; - msg->rssi.status = P80211ENUM_msgitem_status_no_value; - msg->rssi.len = 4; - msg->rssi.data = 0; - - msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq; - msg->sq.status = P80211ENUM_msgitem_status_no_value; - msg->sq.len = 4; - msg->sq.data = 0; - - msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal; - msg->signal.status = 0; - msg->signal.len = 4; - msg->signal.data = rxdesc->signal; - - msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise; - msg->noise.status = 0; - msg->noise.len = 4; - msg->noise.data = rxdesc->silence; - - msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate; - msg->rate.status = 0; - msg->rate.len = 4; - msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */ - - msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx; - msg->istx.status = 0; - msg->istx.len = 4; - msg->istx.data = P80211ENUM_truth_false; - - msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; - msg->frmlen.status = 0; - msg->frmlen.len = 4; - msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN; - } else if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && - (hw->sniffhdr != 0)) { - p80211_caphdr_t *caphdr; - /* The NEW header format! */ - datap = skb_put(skb, sizeof(p80211_caphdr_t)); - caphdr = (p80211_caphdr_t*) datap; - - caphdr->version = htonl(P80211CAPTURE_VERSION); - caphdr->length = htonl(sizeof(p80211_caphdr_t)); - caphdr->mactime = __cpu_to_be64(rxdesc->time); - caphdr->hosttime = __cpu_to_be64(jiffies); - caphdr->phytype = htonl(4); /* dss_dot11_b */ - caphdr->channel = htonl(hw->sniff_channel); - caphdr->datarate = htonl(rxdesc->rate); - caphdr->antenna = htonl(0); /* unknown */ - caphdr->priority = htonl(0); /* unknown */ - caphdr->ssi_type = htonl(3); /* rssi_raw */ - caphdr->ssi_signal = htonl(rxdesc->signal); - caphdr->ssi_noise = htonl(rxdesc->silence); - caphdr->preamble = htonl(0); /* unknown */ - caphdr->encoding = htonl(1); /* cck */ - } - /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ - datap = skb_put(skb, hdrlen); - memcpy( datap, &(rxdesc->frame_control), hdrlen); - - /* If any, copy the data from the card to the skb */ - if ( datalen > 0 ) - { - /* Truncate the packet if the user wants us to */ - UINT dataread = datalen; - if(hw->sniff_truncate > 0 && dataread > hw->sniff_truncate) { - dataread = hw->sniff_truncate; - truncated = 1; - } - - datap = skb_put(skb, dataread); - hfa384x_copy_from_bap(hw, - HFA384x_BAP_INT, rxfid, HFA384x_RX_DATA_OFF, - datap, dataread); - - /* check for unencrypted stuff if WEP bit set. */ - if (*(datap - hdrlen + 1) & 0x40) // wep set - if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) - *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! - } - - if (!truncated && hw->sniff_fcs) { - /* Set the FCS */ - datap = skb_put(skb, WLAN_CRC_LEN); - memset( datap, 0xff, WLAN_CRC_LEN); - } - - /* pass it back up */ - prism2sta_ev_rx(wlandev, skb); - - DBFEXIT; - return; -} - -/*---------------------------------------------------------------- -* hfa384x_int_alloc -* -* Handles the Alloc event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -static void hfa384x_int_alloc(wlandevice_t *wlandev) -{ - hfa384x_t *hw = wlandev->priv; - UINT16 fid; - INT16 result; - - DBFENTER; - - /* Handle the reclaimed FID */ - /* collect the FID and push it onto the stack */ - fid = hfa384x_getreg(hw, HFA384x_ALLOCFID); - - if ( fid != hw->infofid ) { /* It's a transmit fid */ - WLAN_LOG_DEBUG(5, "int_alloc(%#x)\n", fid); - result = txfid_queue_add(hw, fid); - if (result != -1) { - prism2sta_ev_alloc(wlandev); - WLAN_LOG_DEBUG(5, "q_add.\n"); - } else { - WLAN_LOG_DEBUG(5, "q_full.\n"); - } - } else { - /* unlock the info fid */ - up(&hw->infofid_sem); - } - - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* hfa384x_drvr_handover -* -* Sends a handover notification to the MAC. -* -* Arguments: -* hw device structure -* addr address of station that's left -* -* Returns: -* zero success. -* -ERESTARTSYS received signal while waiting for semaphore. -* -EIO failed to write to bap, or failed in cmd. -* -* Side effects: -* -* Call context: -* process thread, NOTE: this call may block on a semaphore! -----------------------------------------------------------------*/ -int hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr) -{ - int result = 0; - hfa384x_HandoverAddr_t rec; - UINT len; - DBFENTER; - - /* Acquire the infofid */ - if ( down_interruptible(&hw->infofid_sem) ) { - result = -ERESTARTSYS; - goto failed; - } - - /* Set up the record */ - len = sizeof(hfa384x_HandoverAddr_t); - rec.framelen = host2hfa384x_16(len/2 - 1); - rec.infotype = host2hfa384x_16(HFA384x_IT_HANDOVERADDR); - memcpy(rec.handover_addr, addr, sizeof(rec.handover_addr)); - - /* Issue the command */ - result = hfa384x_cmd_notify(hw, 1, hw->infofid, &rec, len); - - if ( result != 0 ) { - WLAN_LOG_DEBUG(1,"cmd_notify(%04x) failed, result=%d", - hw->infofid, result); - result = -EIO; - goto failed; - } - -failed: - DBFEXIT; - return result; -} - -void hfa384x_tx_timeout(wlandevice_t *wlandev) -{ - DBFENTER; - - WLAN_LOG_WARNING("Implement me.\n"); - - DBFEXIT; -} - -/* Handles all "rx" BAP operations */ -static void hfa384x_bap_tasklet(unsigned long data) -{ - hfa384x_t *hw = (hfa384x_t *) data; - wlandevice_t *wlandev = hw->wlandev; - int counter = prism2_irq_evread_max; - int reg; - - DBFENTER; - - while (counter-- > 0) { - /* Get interrupt register */ - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - - if ((reg == 0xffff) || - !(reg & HFA384x_INT_BAP_OP)) { - break; - } - - if ( HFA384x_EVSTAT_ISINFO(reg) ){ - hfa384x_int_info(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_INFO_SET(1), - HFA384x_EVACK); - } - if ( HFA384x_EVSTAT_ISTXEXC(reg) ){ - hfa384x_int_txexc(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_TXEXC_SET(1), - HFA384x_EVACK); - } - if ( HFA384x_EVSTAT_ISTX(reg) ){ - hfa384x_int_tx(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_TX_SET(1), - HFA384x_EVACK); - } - if ( HFA384x_EVSTAT_ISRX(reg) ){ - hfa384x_int_rx(wlandev); - hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), - HFA384x_EVACK); - } - } - - /* re-enable interrupts */ - hfa384x_events_all(hw); - - DBFEXIT; -} --- a/drivers/staging/wlan-ng/prism2_cs.c +++ /dev/null @@ -1,1487 +0,0 @@ -#define WLAN_HOSTIF WLAN_PCMCIA -#include "hfa384x.c" -#include "prism2mgmt.c" -#include "prism2mib.c" -#include "prism2sta.c" - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) ) -#if (WLAN_CPU_FAMILY == WLAN_Ix86) -#ifndef CONFIG_ISA -#warning "You may need to enable ISA support in your kernel." -#endif -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) -static u_int irq_mask = 0xdeb8; /* Interrupt mask */ -static int irq_list[4] = { -1 }; /* Interrupt list */ -#endif -static u_int prism2_ignorevcc=1; /* Boolean, if set, we - * ignore what the Vcc - * is set to and what the CIS - * says. - */ -module_param( prism2_ignorevcc, int, 0644); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)) -static int numlist = 4; -module_param_array(irq_list, int, numlist, 0444); -#else -module_param_array(irq_list, int, NULL, 0444); -#endif -module_param( irq_mask, int, 0644); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) -static int prism2_cs_suspend(struct pcmcia_device *pdev); -static int prism2_cs_resume(struct pcmcia_device *pdev); -static void prism2_cs_remove(struct pcmcia_device *pdev); -static int prism2_cs_probe(struct pcmcia_device *pdev); -#else -dev_link_t *prism2sta_attach(void); -static void prism2sta_detach(dev_link_t *link); -static void prism2sta_config(dev_link_t *link); -static void prism2sta_release(u_long arg); -static int prism2sta_event (event_t event, int priority, event_callback_args_t *args); - -static dev_link_t *dev_list = NULL; /* head of instance list */ -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) -/*---------------------------------------------------------------- -* cs_error -* -* Utility function to print card services error messages. -* -* Arguments: -* handle client handle identifying this CS client -* func CS function number that generated the error -* ret CS function return code -* -* Returns: -* nothing -* Side effects: -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -static void cs_error(client_handle_t handle, int func, int ret) -{ -#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911)) - CardServices(ReportError, dev_info, (void *)func, (void *)ret); -#else - error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); -#endif -} -#else // kernel_version - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) -static struct pcmcia_device_id prism2_cs_ids[] = { - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), // Intersil PRISM2 Reference Design 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), // Compaq WL100/200 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), // Compaq iPaq HNW-100 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), // Samsung SWL2000-N 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), // Z-Com XI300 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), // ZoomAir 4100 11Mb/s 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), // Linksys WPC11 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x8649af2, 0x4b74baa0), // Addtron AWP-100 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), // D-Link DWL-650 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("SMC", "SMC2632W", "Version 01.02", 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), // SMC 2632W 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e), // BroMax Freeport 11Mbps 802.11b WLAN Card (Prism 2.5) - PCMCIA_DEVICE_PROD_ID123("U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), // U.S. Robotics IEEE 802.11b PC-CARD - PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), // Level-One WPC-0100 - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 2.5) - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 3) - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), // corega K.K. Wireless LAN PCC-11 - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), // corega K.K. Wireless LAN PCCA-11 - PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), // CONTEC FLEXSCAN/FX-DDS110-PCC - PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), // PLANEX GeoWave/GW-NS110 - PCMCIA_DEVICE_PROD_ID123("OEM", "PRISM2 IEEE 802.11 PC-Card", "Version 01.02", 0xfea54c90, 0x48f2bdd6, 0x4b74baa0), // Ambicom WL1100 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", "Version 01.02", 0x7e3b326a, 0x49893e92, 0x4b74baa0), // LeArtery SYNCBYAIR 11Mbps 802.11b WLAN Card -PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), // Intermec MobileLAN 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID123("NETGEAR MA401 Wireless PC", "Card", "Version 01.00", 0xa37434e9, 0x9762e8f1, 0xa57adb8c), // NETGEAR MA401 11Mbps 802.11 WLAN Card - PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", "Eval-RevA", 0x4b801a17, 0xf222ec2d, 0x630d52b2, 0xc23adc0e), // Intersil PRISM Freedom 11mbps 802.11 WLAN Card - PCMCIA_DEVICE_PROD_ID123("OTC", "Wireless AirEZY 2411-PCC WLAN Card", "Version 01.02", 0x4ac44287, 0x235a6bed, 0x4b74baa0), // OTC Wireless AirEZY 2411-PCC 11Mbps 802.11 WLAN Card - PCMCIA_DEVICE_PROD_ID1234("802.11", "11Mbps Wireless LAN Card", "v08C1", "" , 0xb67a610e, 0x655aa7b7, 0x264b451a, 0x0), // Dynalink L11HDT 11Mbps 802.11 WLAN Card - PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), // Dynalink L11HDT 11Mbps 802.11 WLAN Card - PCMCIA_DEVICE_PROD_ID12("PROXIM", "RangeLAN-DS/LAN PC CARD", 0xc6536a5e, 0x3f35797d), // PROXIM RangeLAN-DS/LAN PC CARD - PCMCIA_DEVICE_PROD_ID1234("ACTIONTEC", "PRISM Wireless LAN PC Card", "0381", "RevA", 0x393089da, 0xa71e69d5, 0x90471fa9, 0x57a66194), // ACTIONTEC PRISM Wireless LAN PC Card - PCMCIA_DEVICE_MANF_CARD(0x1668, 0x0101), // ACTIONTEC PRISM Wireless LAN PC Card - PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), // 3Com AirConnect 3CRWE737A - PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE777A AirConnect Wireless LAN PCI Card" , 0x41240e5b, 0xafc7c33e), // 3Com AirConnect 3CRWE777A - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), // ASUS WL-100 802.11b WLAN PC Card - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), // ASUS WL-110 802.11b WLAN CF Card - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), // BUFFALO WLI-CF-S11G 802.11b WLAN Card - PCMCIA_DEVICE_PROD_ID1234("The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA", 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194), // Linksys WCF11 11Mbps 802.11b WLAN Card (Prism 2.5) - PCMCIA_DEVICE_PROD_ID1234("Linksys", "Wireless CompactFlash Card", "", "", 0x733cc81, 0xc52f395, 0x0, 0x0), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3) - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3) - PCMCIA_DEVICE_PROD_ID1234("NETGEAR MA401RA Wireless PC", "Card", "ISL37300P", "Eval-RevA", 0x306467f, 0x9762e8f1, 0xc9049a39, 0xc23adc0e), // NETGEAR MA401RA 11Mbps 802.11 WLAN Card - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), // D-Link DCF-660W 11Mbps 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), // Microsoft Wireless Notebook Adapter MN-520 - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), // AnyPoint(TM) Wireless II PC Card - PCMCIA_DEVICE_PROD_ID1234("D", "Link DRC-650 11Mbps WLAN Card", "Version 01.02", "" , 0x71b18589, 0xf144e3ac, 0x4b74baa0, 0x0), // D-Link DRC-650 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), // Adaptec AWN-8030 - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7110), // D-Link DWL-650 rev P 802.11b WLAN card - // PCMCIA_DEVICE_PROD_ID1234("D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", "A3", 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52), // D-Link DWL-650 rev P 802.11b WLAN card - PCMCIA_DEVICE_PROD_ID123("INTERSIL", "I-GATE 11M PC Card / PC Card plus", "Version 01.02", 0x74c5e40d, 0x8304ff77, 0x4b74baa0), // I-Gate 11M PC Card - PCMCIA_DEVICE_PROD_ID1234("BENQ", "AWL100 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x35dadc74, 0x1f7fedb, 0xc9049a39, 0xc23adc0e), // benQ AWL100 802.11b WLAN Card - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), // benQ AWL100 802.11b WLAN Card - // PCMCIA_DEVICE_PROD_ID1("INTERSIL", 0x74c5e40d), // Intersil Prism 2 card - // PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), // Intersil Prism 2 card - - PCMCIA_DEVICE_NULL -}; - -MODULE_DEVICE_TABLE(pcmcia, prism2_cs_ids); -#endif - -static struct pcmcia_driver prism2_cs_driver = { - .drv = { - .name = "prism2_cs", - }, - .owner = THIS_MODULE, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) - .suspend = prism2_cs_suspend, - .resume = prism2_cs_resume, - .remove = prism2_cs_remove, - .probe = prism2_cs_probe, - .id_table = prism2_cs_ids, -#else - .attach = prism2sta_attach, - .detach = prism2sta_detach, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) - .id_table = prism2_cs_ids, - .event = prism2sta_event, -#endif // > 2.6.12 -#endif // <= 2.6.15 -}; -#endif /* kernel_version */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -#define CFG_CHECK(fn, retf) \ -do { int ret = (retf); \ -if (ret != 0) { \ - WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ - cs_error(pdev, fn, ret); \ - goto next_entry; \ -} \ -} while (0) - -static void prism2_cs_remove(struct pcmcia_device *pdev) -{ - struct wlandevice *wlandev; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - dev_link_t *link = dev_to_instance(pdev); -#endif - - DBFENTER; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - wlandev = pdev->priv; -#else - wlandev = link->priv; -#endif - - if (wlandev) { - p80211netdev_hwremoved(wlandev); - unregister_wlandev(wlandev); - wlan_unsetup(wlandev); - if (wlandev->priv) { - hfa384x_t *hw = wlandev->priv; - wlandev->priv = NULL; - if (hw) { - hfa384x_destroy(hw); - kfree(hw); - } - } - kfree(wlandev); - } - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->priv = NULL; - pcmcia_disable_device(pdev); -#else - if (link->state & DEV_CONFIG) { - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - } - - link->priv = NULL; - kfree(link); -#endif - - DBFEXIT; - return; -} - -static int prism2_cs_suspend(struct pcmcia_device *pdev) -{ - struct wlandevice *wlandev; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - dev_link_t *link = dev_to_instance(pdev); -#endif - - DBFENTER; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - wlandev = pdev->priv; - prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); -#else - wlandev = link->priv; - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); - pcmcia_release_configuration(link->handle); - } -#endif - - DBFEXIT; - - return 0; -} - -static int prism2_cs_resume(struct pcmcia_device *pdev) -{ - struct wlandevice *wlandev; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - dev_link_t *link = dev_to_instance(pdev); -#endif - - DBFENTER; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - wlandev = pdev->priv; - // XXX do something here? -#else - wlandev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - // XXX do something here? - } -#endif - - - DBFEXIT; - - return 0; -} - -static int prism2_cs_probe(struct pcmcia_device *pdev) -{ - int rval = 0; - struct wlandevice *wlandev = NULL; - hfa384x_t *hw = NULL; - - config_info_t socketconf; - cisparse_t *parse = NULL; - tuple_t tuple; - uint8_t buf[64]; - int last_fn, last_ret; - cistpl_cftable_entry_t dflt = { 0 }; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - dev_link_t *link; -#endif - - DBFENTER; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - /* Set up interrupt type */ - pdev->conf.IntType = INT_MEMORY_AND_IO; -#else - link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); - if (link == NULL) - return -ENOMEM; - memset(link, 0, sizeof(dev_link_t)); - - link->conf.Vcc = 33; - link->conf.IntType = INT_MEMORY_AND_IO; - - link->handle = pdev; - pdev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - -#endif - - // VCC crap? - parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); - - wlandev = create_wlan(); - if (!wlandev || !parse) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); - rval = -EIO; - goto failed; - } - hw = wlandev->priv; - - if ( wlan_setup(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); - rval = -EIO; - goto failed; - } - - /* Initialize the hw struct for now */ - hfa384x_create(hw, 0, 0, NULL); - hw->wlandev = wlandev; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - hw->pdev = pdev; - pdev->priv = wlandev; -#else - hw->link = link; - link->priv = wlandev; -#endif - - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse)); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.ConfigBase = parse->config.base; - pdev->conf.Present = parse->config.rmask[0]; -#else - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; - - link->conf.Vcc = socketconf.Vcc; -#endif - CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(pdev, &socketconf)); - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - for (;;) { - cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); - CFG_CHECK(GetTupleData, - pcmcia_get_tuple_data(pdev, &tuple)); - CFG_CHECK(ParseTuple, - pcmcia_parse_tuple(pdev, &tuple, parse)); - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - dflt = *cfg; - if (cfg->index == 0) - goto next_entry; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.ConfigIndex = cfg->index; -#else - link->conf.ConfigIndex = cfg->index; -#endif - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.Attributes |= CONF_ENABLE_SPKR; - pdev->conf.Status = CCSR_AUDIO_ENA; -#else - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; -#endif - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / - 10000 && !prism2_ignorevcc) { - WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping" - " this entry\n"); - goto next_entry; - } - } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / - 10000 && !prism2_ignorevcc) { - WLAN_LOG_DEBUG(1, " Vcc (default) mismatch " - "- skipping this entry\n"); - goto next_entry; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; -#else - link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; -#endif - } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.Vpp = - dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; -#else - link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; -#endif - } - - /* Do we need to allocate an interrupt? */ - /* HACK: due to a bad CIS....we ALWAYS need an interrupt */ - /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->conf.Attributes |= CONF_ENABLE_IRQ; -#else - link->conf.Attributes |= CONF_ENABLE_IRQ; -#endif - - /* IO window settings */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - pdev->io.BasePort1 = io->win[0].base; - if ( pdev->io.BasePort1 != 0 ) { - WLAN_LOG_WARNING( - "Brain damaged CIS: hard coded iobase=" - "0x%x, try letting pcmcia_cs decide...\n", - pdev->io.BasePort1 ); - pdev->io.BasePort1 = 0; - } - pdev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - pdev->io.Attributes2 = pdev->io.Attributes1; - pdev->io.BasePort2 = io->win[1].base; - pdev->io.NumPorts2 = io->win[1].len; - } - } - /* This reserves IO space but doesn't actually enable it */ - CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io)); -#else - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.BasePort1 = io->win[0].base; - if ( link->io.BasePort1 != 0 ) { - WLAN_LOG_WARNING( - "Brain damaged CIS: hard coded iobase=" - "0x%x, try letting pcmcia_cs decide...\n", - link->io.BasePort1 ); - link->io.BasePort1 = 0; - } - link->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - link->io.Attributes2 = link->io.Attributes1; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = io->win[1].len; - } - } - /* This reserves IO space but doesn't actually enable it */ - CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io)); -#endif - /* If we got this far, we're cool! */ - break; - - next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - dflt = *cfg; - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple)); - - } - - /* Let pcmcia know the device name */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->dev_node = &hw->node; -#else - link->dev = &hw->node; -#endif - - /* Register the network device and get assigned a name */ - SET_MODULE_OWNER(wlandev->netdev); - SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev)); - if (register_wlandev(wlandev) != 0) { - WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); - goto failed; - } - - strcpy(hw->node.dev_name, wlandev->name); - - /* Allocate an interrupt line. Note that this does not assign a */ - /* handler to the interrupt, unless the 'Handler' member of the */ - /* irq structure is initialized. */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - if (pdev->conf.Attributes & CONF_ENABLE_IRQ) { - pdev->irq.IRQInfo1 = IRQ_LEVEL_ID; - pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - pdev->irq.Handler = hfa384x_interrupt; - pdev->irq.Instance = wlandev; - CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); - } -#else - if (link->conf.Attributes & CONF_ENABLE_IRQ) { - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.Handler = hfa384x_interrupt; - link->irq.Instance = wlandev; - CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq)); - } -#endif - - /* This actually configures the PCMCIA socket -- setting up */ - /* the I/O windows and the interrupt mapping, and putting the */ - /* card and host interface into "Memory and IO" mode. */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); -#else - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf)); -#endif - - /* Fill the netdevice with this info */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - wlandev->netdev->irq = pdev->irq.AssignedIRQ; - wlandev->netdev->base_addr = pdev->io.BasePort1; -#else - wlandev->netdev->irq = link->irq.AssignedIRQ; - wlandev->netdev->base_addr = link->io.BasePort1; -#endif - - /* And the rest of the hw structure */ - hw->irq = wlandev->netdev->irq; - hw->iobase = wlandev->netdev->base_addr; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - link->state |= DEV_CONFIG; - link->state &= ~DEV_CONFIG_PENDING; -#endif - - /* And now we're done! */ - wlandev->msdstate = WLAN_MSD_HWPRESENT; - - goto done; - - cs_failed: - cs_error(pdev, last_fn, last_ret); - -failed: - // wlandev, hw, etc etc.. -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - pdev->priv = NULL; -#else - pdev->instance = NULL; - if (link) { - link->priv = NULL; - kfree(link); - } -#endif - if (wlandev) { - wlan_unsetup(wlandev); - if (wlandev->priv) { - hw = wlandev->priv; - wlandev->priv = NULL; - if (hw) { - hfa384x_destroy(hw); - kfree(hw); - } - } - kfree(wlandev); - } - -done: - if (parse) kfree(parse); - - DBFEXIT; - return rval; -} -#else // <= 2.6.15 -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -#define CFG_CHECK(fn, retf) \ -do { int ret = (retf); \ -if (ret != 0) { \ - WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ - cs_error(link->handle, fn, ret); \ - goto next_entry; \ -} \ -} while (0) - -/*---------------------------------------------------------------- -* prism2sta_attach -* -* Half of the attach/detach pair. Creates and registers a device -* instance with Card Services. In this case, it also creates the -* wlandev structure and device private structure. These are -* linked to the device instance via its priv member. -* -* Arguments: -* none -* -* Returns: -* A valid ptr to dev_link_t on success, NULL otherwise -* -* Side effects: -* -* -* Call context: -* process thread (insmod/init_module/register_pccard_driver) -----------------------------------------------------------------*/ -dev_link_t *prism2sta_attach(void) -{ - client_reg_t client_reg; - int result; - dev_link_t *link = NULL; - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; - - DBFENTER; - - /* Alloc our structures */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - - if (!link || ((wlandev = create_wlan()) == NULL)) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); - result = -EIO; - goto failed; - } - hw = wlandev->priv; - - /* Clear all the structs */ - memset(link, 0, sizeof(struct dev_link_t)); - - if ( wlan_setup(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); - result = -EIO; - goto failed; - } - - /* Initialize the hw struct for now */ - hfa384x_create(hw, 0, 0, NULL); - hw->wlandev = wlandev; - - /* Initialize the PC card device object. */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - init_timer(&link->release); - link->release.function = &prism2sta_release; - link->release.data = (u_long)link; -#endif - link->conf.IntType = INT_MEMORY_AND_IO; - link->priv = wlandev; -#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911)) - link->irq.Instance = wlandev; -#endif - - /* Link in to the list of devices managed by this driver */ - link->next = dev_list; - dev_list = link; - - /* Register with Card Services */ - client_reg.dev_info = &dev_info; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_REQUEST | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &prism2sta_event; -#endif - - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - - result = pcmcia_register_client(&link->handle, &client_reg); - if (result != 0) { - cs_error(link->handle, RegisterClient, result); - prism2sta_detach(link); - return NULL; - } - - goto done; - - failed: - if (link) kfree(link); - if (wlandev) kfree(wlandev); - if (hw) kfree(hw); - link = NULL; - - done: - DBFEXIT; - return link; -} - - -/*---------------------------------------------------------------- -* prism2sta_detach -* -* 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. -----------------------------------------------------------------*/ -void prism2sta_detach(dev_link_t *link) -{ - dev_link_t **linkp; - wlandevice_t *wlandev; - hfa384x_t *hw; - - DBFENTER; - - /* Locate prev device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { - if (*linkp == link) break; - } - - if (*linkp != NULL) { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) - unsigned long flags; - /* Get rid of any timer'd release call */ - save_flags(flags); - cli(); -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - if (link->state & DEV_RELEASE_PENDING) { - del_timer_sync(&link->release); - link->state &= ~DEV_RELEASE_PENDING; - } -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) - restore_flags(flags); -#endif - - /* If link says we're still config'd, call release */ - if (link->state & DEV_CONFIG) { - prism2sta_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) { - pcmcia_deregister_client(link->handle); - } - - /* Unlink device structure, free bits */ - *linkp = link->next; - if ( link->priv != NULL ) { - wlandev = (wlandevice_t*)link->priv; - p80211netdev_hwremoved(wlandev); - if (link->dev != NULL) { - unregister_wlandev(wlandev); - } - wlan_unsetup(wlandev); - if (wlandev->priv) { - hw = wlandev->priv; - wlandev->priv = NULL; - if (hw) { - hfa384x_destroy(hw); - kfree(hw); - } - } - link->priv = NULL; - kfree(wlandev); - } - kfree(link); - } - - DBFEXIT; - return; -} - -/*---------------------------------------------------------------- -* prism2sta_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, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -#define CFG_CHECK(fn, retf) \ -do { int ret = (retf); \ -if (ret != 0) { \ - WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \ - cs_error(link->handle, fn, ret); \ - goto next_entry; \ -} \ -} while (0) - -void prism2sta_config(dev_link_t *link) -{ - client_handle_t handle; - wlandevice_t *wlandev; - hfa384x_t *hw; - int last_fn; - int last_ret; - tuple_t tuple; - cisparse_t parse; - config_info_t socketconf; - UINT8 buf[64]; - int minVcc = 0; - int maxVcc = 0; - cistpl_cftable_entry_t dflt = { 0 }; - - DBFENTER; - - handle = link->handle; - wlandev = (wlandevice_t*)link->priv; - hw = wlandev->priv; - - /* Collect the config register info */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Acquire the current socket config (need Vcc setting) */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf)); - - /* Loop through the config table entries until we find one that works */ - /* Assumes a complete and valid CIS */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - while (1) { - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - - if (cfg->index == 0) goto next_entry; - link->conf.ConfigIndex = cfg->index; - - /* Lets print out the Vcc that the controller+pcmcia-cs set - * for us, cause that's what we're going to use. - */ - WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc); - if (prism2_ignorevcc) { - link->conf.Vcc = socketconf.Vcc; - goto skipvcc; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<vcc.param[CISTPL_POWER_VNOM]/10000; - } else if (dflt.vcc.present & (1<vcc.present & (1<vcc.present & (1<vcc.param[CISTPL_POWER_VMIN]/10000; - maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000; - } else if ((dflt.vcc.present & (1<= minVcc && socketconf.Vcc <= maxVcc) { - link->conf.Vcc = socketconf.Vcc; - } else { - /* [MSM]: Note that I've given up trying to change - * the Vcc if a change is indicated. It seems the - * system&socketcontroller&card vendors can't seem - * to get it right, so I'm tired of trying to hack - * my way around it. pcmcia-cs does its best using - * the voltage sense pins but sometimes the controller - * lies. Then, even if we have a good read on the VS - * pins, some system designs will silently ignore our - * requests to set the voltage. Additionally, some - * vendors have 3.3v indicated on their sense pins, - * but 5v specified in the CIS or vice-versa. I've - * had it. My only recommendation is "let the buyer - * beware". Your system might supply 5v to a 3v card - * (possibly causing damage) or a 3v capable system - * might supply 5v to a 3v capable card (wasting - * precious battery life). - * My only recommendation (if you care) is to get - * yourself an extender card (I don't know where, I - * have only one myself) and a meter and test it for - * yourself. - */ - goto next_entry; - } -skipvcc: - WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc); - - /* Do we need to allocate an interrupt? */ - /* HACK: due to a bad CIS....we ALWAYS need an interrupt */ - /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */ - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.BasePort1 = io->win[0].base; - if ( link->io.BasePort1 != 0 ) { - WLAN_LOG_WARNING( - "Brain damaged CIS: hard coded iobase=" - "0x%x, try letting pcmcia_cs decide...\n", - link->io.BasePort1 ); - link->io.BasePort1 = 0; - } - link->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - link->io.Attributes2 = link->io.Attributes1; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); - - /* If we got this far, we're cool! */ - break; - -next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - dflt = *cfg; - CS_CHECK(GetNextTuple, - pcmcia_get_next_tuple(handle, &tuple)); - } - - /* Allocate an interrupt line. Note that this does not assign a */ - /* handler to the interrupt, unless the 'Handler' member of the */ - /* irq structure is initialized. */ - if (link->conf.Attributes & CONF_ENABLE_IRQ) - { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) - int i; - link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i=0; i<4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; -#else - link->irq.IRQInfo1 = IRQ_LEVEL_ID; -#endif - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.Handler = hfa384x_interrupt; - link->irq.Instance = wlandev; - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - } - - /* This actually configures the PCMCIA socket -- setting up */ - /* the I/O windows and the interrupt mapping, and putting the */ - /* card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); - - /* Fill the netdevice with this info */ - wlandev->netdev->irq = link->irq.AssignedIRQ; - wlandev->netdev->base_addr = link->io.BasePort1; - - /* Report what we've done */ - WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d", - dev_info, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq.AssignedIRQ); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1); - printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; - - /* Let pcmcia know the device name */ - link->dev = &hw->node; - - /* Register the network device and get assigned a name */ - SET_MODULE_OWNER(wlandev->netdev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) ) - SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle)); -#endif - if (register_wlandev(wlandev) != 0) { - WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n"); - goto failed; - } - - strcpy(hw->node.dev_name, wlandev->name); - - /* Any device custom config/query stuff should be done here */ - /* For a netdevice, we should at least grab the mac address */ - - return; -cs_failed: - cs_error(link->handle, last_fn, last_ret); - WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n"); - -failed: - prism2sta_release((u_long)link); - return; -} - -/*---------------------------------------------------------------- -* prism2sta_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. It's the value that -* we assigned to link->release.data in sta_attach(). -* -* 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 prism2sta_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *)arg; - - DBFENTER; - - /* First thing we should do is get the MSD back to the - * HWPRESENT state. I.e. everything quiescent. - */ - prism2sta_ifstate(link->priv, P80211ENUM_ifstate_disable); - - if (link->open) { - /* TODO: I don't think we're even using this bit of code - * and I don't think it's hurting us at the moment. - */ - WLAN_LOG_DEBUG(1, - "prism2sta_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); - - DBFEXIT; -} - -/*---------------------------------------------------------------- -* prism2sta_event -* -* Handler for card services events. -* -* Arguments: -* event The event code -* priority hi/low - REMOVAL is the only hi -* args ptr to card services struct containing info about -* pcmcia status -* -* Returns: -* Zero on success, non-zero otherwise -* -* Side effects: -* -* -* Call context: -* Both interrupt and process thread, depends on the event. -----------------------------------------------------------------*/ -static int -prism2sta_event ( - event_t event, - int priority, - event_callback_args_t *args) -{ - int result = 0; - dev_link_t *link = (dev_link_t *) args->client_data; - wlandevice_t *wlandev = (wlandevice_t*)link->priv; - hfa384x_t *hw = NULL; - - DBFENTER; - - if (wlandev) hw = wlandev->priv; - - switch (event) - { - case CS_EVENT_CARD_INSERTION: - WLAN_LOG_DEBUG(5,"event is INSERTION\n"); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - prism2sta_config(link); - if (!(link->state & DEV_CONFIG)) { - wlandev->netdev->irq = 0; - WLAN_LOG_ERROR( - "%s: Initialization failed!\n", dev_info); - wlandev->msdstate = WLAN_MSD_HWFAIL; - break; - } - - /* Fill in the rest of the hw struct */ - hw->irq = wlandev->netdev->irq; - hw->iobase = wlandev->netdev->base_addr; - hw->link = link; - - if (prism2_doreset) { - result = hfa384x_corereset(hw, - prism2_reset_holdtime, - prism2_reset_settletime, 0); - if ( result ) { - WLAN_LOG_ERROR( - "corereset() failed, result=%d.\n", - result); - wlandev->msdstate = WLAN_MSD_HWFAIL; - break; - } - } - -#if 0 - /* - * TODO: test_hostif() not implemented yet. - */ - result = hfa384x_test_hostif(hw); - if (result) { - WLAN_LOG_ERROR( - "test_hostif() failed, result=%d.\n", result); - wlandev->msdstate = WLAN_MSD_HWFAIL; - break; - } -#endif - wlandev->msdstate = WLAN_MSD_HWPRESENT; - break; - - case CS_EVENT_CARD_REMOVAL: - WLAN_LOG_DEBUG(5,"event is REMOVAL\n"); - link->state &= ~DEV_PRESENT; - - if (wlandev) { - p80211netdev_hwremoved(wlandev); - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - if (link->state & DEV_CONFIG) - { - link->release.expires = jiffies + (HZ/20); - add_timer(&link->release); - } -#endif - break; - case CS_EVENT_RESET_REQUEST: - WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n"); - WLAN_LOG_NOTICE( - "prism2 card reset not supported " - "due to post-reset user mode configuration " - "requirements.\n"); - WLAN_LOG_NOTICE( - " From user mode, use " - "'cardctl suspend;cardctl resume' " - "instead.\n"); - break; - case CS_EVENT_RESET_PHYSICAL: - case CS_EVENT_CARD_RESET: - WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not " - "be possible since RESET_REQUEST was denied.\n"); - break; - - case CS_EVENT_PM_SUSPEND: - WLAN_LOG_DEBUG(5,"event is SUSPEND\n"); - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - { - prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); - pcmcia_release_configuration(link->handle); - } - break; - - case CS_EVENT_PM_RESUME: - WLAN_LOG_DEBUG(5,"event is RESUME\n"); - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - } - break; - } - - DBFEXIT; - return 0; /* noone else does anthing with the return value */ -} -#endif // <= 2.6.15 - - - -int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) -{ - int result = 0; - conf_reg_t reg; - UINT8 corsave; - DBFENTER; - - WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n"); - - /* Collect COR */ - reg.Function = 0; - reg.Action = CS_READ; - reg.Offset = CISREG_COR; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - result = pcmcia_access_configuration_register(hw->pdev, ®); -#else - result = pcmcia_access_configuration_register( - hw->link->handle, - ®); -#endif - if (result != CS_SUCCESS ) { - WLAN_LOG_ERROR( - ":0: AccessConfigurationRegister(CS_READ) failed," - "result=%d.\n", result); - result = -EIO; - } - corsave = reg.Value; - - /* Write reset bit (BIT7) */ - reg.Value |= BIT7; - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - result = pcmcia_access_configuration_register(hw->pdev, ®); -#else - result = pcmcia_access_configuration_register( - hw->link->handle, - ®); -#endif - if (result != CS_SUCCESS ) { - WLAN_LOG_ERROR( - ":1: AccessConfigurationRegister(CS_WRITE) failed," - "result=%d.\n", result); - result = -EIO; - } - - /* Hold for holdtime */ - mdelay(holdtime); - - if (genesis) { - reg.Value = genesis; - reg.Action = CS_WRITE; - reg.Offset = CISREG_CCSR; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - result = pcmcia_access_configuration_register(hw->pdev, ®); -#else - result = pcmcia_access_configuration_register( - hw->link->handle, - ®); -#endif - if (result != CS_SUCCESS ) { - WLAN_LOG_ERROR( - ":1: AccessConfigurationRegister(CS_WRITE) failed," - "result=%d.\n", result); - result = -EIO; - } - } - - /* Hold for holdtime */ - mdelay(holdtime); - - /* Clear reset bit */ - reg.Value &= ~BIT7; - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - result = pcmcia_access_configuration_register(hw->pdev, ®); -#else - result = pcmcia_access_configuration_register( - hw->link->handle, - ®); -#endif - if (result != CS_SUCCESS ) { - WLAN_LOG_ERROR( - ":2: AccessConfigurationRegister(CS_WRITE) failed," - "result=%d.\n", result); - result = -EIO; - goto done; - } - - /* Wait for settletime */ - mdelay(settletime); - - /* Set non-reset bits back what they were */ - reg.Value = corsave; - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) - result = pcmcia_access_configuration_register(hw->pdev, ®); -#else - result = pcmcia_access_configuration_register( - hw->link->handle, - ®); -#endif - if (result != CS_SUCCESS ) { - WLAN_LOG_ERROR( - ":2: AccessConfigurationRegister(CS_WRITE) failed," - "result=%d.\n", result); - result = -EIO; - goto done; - } - -done: - DBFEXIT; - return result; -} - -#ifdef MODULE - -static int __init prism2cs_init(void) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) - servinfo_t serv; -#endif - - DBFENTER; - - WLAN_LOG_NOTICE("%s Loaded\n", version); - WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) - pcmcia_get_card_services_info(&serv); - if ( serv.Revision != CS_RELEASE_CODE ) - { - printk(KERN_NOTICE"%s: CardServices release does not match!\n", dev_info); - return -1; - } - - /* This call will result in a call to prism2sta_attach */ - /* and eventually prism2sta_detach */ - register_pccard_driver( &dev_info, &prism2sta_attach, &prism2sta_detach); -#else - pcmcia_register_driver(&prism2_cs_driver); -#endif - - DBFEXIT; - return 0; -} - -static void __exit prism2cs_cleanup(void) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) - dev_link_t *link = dev_list; - dev_link_t *nlink; - DBFENTER; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) - for (link=dev_list; link != NULL; link = nlink) { - nlink = link->next; - if ( link->state & DEV_CONFIG ) { - prism2sta_release((u_long)link); - } - prism2sta_detach(link); /* remember detach() frees link */ - } -#endif - - unregister_pccard_driver( &dev_info); -#else - pcmcia_unregister_driver(&prism2_cs_driver); -#endif - - printk(KERN_NOTICE "%s Unloaded\n", version); - - DBFEXIT; - return; -} - -module_init(prism2cs_init); -module_exit(prism2cs_cleanup); - -#endif // MODULE - --- a/drivers/staging/wlan-ng/prism2_pci.c +++ /dev/null @@ -1,332 +0,0 @@ -#define WLAN_HOSTIF WLAN_PCI -#include "hfa384x.c" -#include "prism2mgmt.c" -#include "prism2mib.c" -#include "prism2sta.c" - -#define PCI_SIZE 0x1000 /* Memory size - 4K bytes */ - -/* ISL3874A 11Mb/s WLAN controller */ -#define PCIVENDOR_INTERSIL 0x1260UL -#define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says - 3873. Trust me, it's a 3874. */ - -/* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */ -#define PCIVENDOR_SAMSUNG 0x167dUL -#define PCIDEVICE_SWL_2210P 0xa000UL - -#define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 */ - -/* PCI Class & Sub-Class code, Network-'Other controller' */ -#define PCI_CLASS_NETWORK_OTHERS 0x280 - - -/*---------------------------------------------------------------- -* prism2sta_probe_pci -* -* Probe routine called when a PCI device w/ matching ID is found. -* The ISL3874 implementation uses the following map: -* BAR0: Prism2.x registers memory mapped, size=4k -* Here's the sequence: -* - Allocate the PCI resources. -* - Read the PCMCIA attribute memory to make sure we have a WLAN card -* - Reset the MAC -* - Initialize the netdev and wlan data -* - Initialize the MAC -* -* Arguments: -* pdev ptr to pci device structure containing info about -* pci configuration. -* id ptr to the device id entry that matched this device. -* -* Returns: -* zero - success -* negative - failed -* -* Side effects: -* -* -* Call context: -* process thread -* -----------------------------------------------------------------*/ -static int __devinit -prism2sta_probe_pci( - struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int result; - phys_t phymem = 0; - void __iomem *mem = NULL; - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; - - DBFENTER; - - /* Enable the pci device */ - if (pci_enable_device(pdev)) { - WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info); - result = -EIO; - goto fail; - } - - /* Figure out our resources */ - phymem = pci_resource_start(pdev, 0); - - if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { - printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); - result = -EIO; - goto fail; - } - - mem = ioremap(phymem, PCI_SIZE); - if ( mem == 0 ) { - WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info); - result = -EIO; - goto fail; - } - - /* Log the device */ - WLAN_LOG_INFO("A Prism2.5 PCI device found, " - "phymem:0x%llx, irq:%d, mem:0x%p\n", - (unsigned long long)phymem, pdev->irq, mem); - - if ((wlandev = create_wlan()) == NULL) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); - result = -EIO; - goto fail; - } - hw = wlandev->priv; - - if ( wlan_setup(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); - result = -EIO; - goto fail; - } - - /* Setup netdevice's ability to report resources - * Note: the netdevice was allocated by wlan_setup() - */ - wlandev->netdev->irq = pdev->irq; - wlandev->netdev->mem_start = (unsigned long) mem; - wlandev->netdev->mem_end = wlandev->netdev->mem_start + - pci_resource_len(pdev, 0); - - /* Initialize the hw data */ - hfa384x_create(hw, wlandev->netdev->irq, 0, mem); - hw->wlandev = wlandev; - - /* Register the wlandev, this gets us a name and registers the - * linux netdevice. - */ - SET_MODULE_OWNER(wlandev->netdev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev)); -#endif - if ( register_wlandev(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); - result = -EIO; - goto fail; - } - -#if 0 - /* TODO: Move this and an irq test into an hfa384x_testif() routine. - */ - outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); - reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); - if ( reg != PRISM2STA_MAGIC ) { - WLAN_LOG_ERROR("MAC register access test failed!\n"); - result = -EIO; - goto fail; - } -#endif - - /* Do a chip-level reset on the MAC */ - if (prism2_doreset) { - result = hfa384x_corereset(hw, - prism2_reset_holdtime, - prism2_reset_settletime, 0); - if (result != 0) { - WLAN_LOG_ERROR( - "%s: hfa384x_corereset() failed.\n", - dev_info); - unregister_wlandev(wlandev); - hfa384x_destroy(hw); - result = -EIO; - goto fail; - } - } - - pci_set_drvdata(pdev, wlandev); - - /* Shouldn't actually hook up the IRQ until we - * _know_ things are alright. A test routine would help. - */ - request_irq(wlandev->netdev->irq, hfa384x_interrupt, - SA_SHIRQ, wlandev->name, wlandev); - - wlandev->msdstate = WLAN_MSD_HWPRESENT; - - result = 0; - goto done; - - fail: - pci_set_drvdata(pdev, NULL); - if (wlandev) kfree(wlandev); - if (hw) kfree(hw); - if (mem) iounmap(mem); - pci_release_regions(pdev); - pci_disable_device(pdev); - - done: - DBFEXIT; - return result; -} - -static void __devexit prism2sta_remove_pci(struct pci_dev *pdev) -{ - wlandevice_t *wlandev; - hfa384x_t *hw; - - wlandev = (wlandevice_t *) pci_get_drvdata(pdev); - hw = wlandev->priv; - - p80211netdev_hwremoved(wlandev); - - /* reset hardware */ - prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); - - if (pdev->irq) - free_irq(pdev->irq, wlandev); - - unregister_wlandev(wlandev); - - /* free local stuff */ - if (hw) { - hfa384x_destroy(hw); - kfree(hw); - } - - iounmap((void __iomem *)wlandev->netdev->mem_start); - wlan_unsetup(wlandev); - - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - - kfree(wlandev); -} - - -static struct pci_device_id pci_id_tbl[] = { - { - PCIVENDOR_INTERSIL, PCIDEVICE_ISL3874, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller" - }, - { - PCIVENDOR_INTERSIL, 0x3872, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller" - }, - { - PCIVENDOR_SAMSUNG, PCIDEVICE_SWL_2210P, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller" - }, - { /* for NetGear MA311 */ - PCIVENDOR_NETGEAR, 0x3872, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Netgear MA311 WLAN Controller" - }, - { - 0, 0, 0, 0, 0, 0, 0 - } -}; - -MODULE_DEVICE_TABLE(pci, pci_id_tbl); - -/* Function declared here because of ptr reference below */ -static int __devinit prism2sta_probe_pci(struct pci_dev *pdev, - const struct pci_device_id *id); -static void __devexit prism2sta_remove_pci(struct pci_dev *pdev); - -static struct pci_driver prism2_pci_drv_id = { - .name = "prism2_pci", - .id_table = pci_id_tbl, - .probe = prism2sta_probe_pci, - .remove = prism2sta_remove_pci, -#ifdef CONFIG_PM - .suspend = prism2sta_suspend_pci, - .resume = prism2sta_resume_pci, -#endif -}; - -#ifdef MODULE - -static int __init prism2pci_init(void) -{ - WLAN_LOG_NOTICE("%s Loaded\n", version); - return pci_module_init(&prism2_pci_drv_id); -}; - -static void __exit prism2pci_cleanup(void) -{ - pci_unregister_driver(&prism2_pci_drv_id); -}; - -module_init(prism2pci_init); -module_exit(prism2pci_cleanup); - -#endif - -int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) -{ - int result = 0; - unsigned long timeout; - UINT16 reg; - DBFENTER; - - /* Assert reset and wait awhile - * (note: these delays are _really_ long, but they appear to be - * necessary.) - */ - hfa384x_setreg(hw, 0xc5, HFA384x_PCICOR); - timeout = jiffies + HZ/4; - while(time_before(jiffies, timeout)) udelay(5); - - if (genesis) { - hfa384x_setreg(hw, genesis, HFA384x_PCIHCR); - timeout = jiffies + HZ/4; - while(time_before(jiffies, timeout)) udelay(5); - } - - /* Clear the reset and wait some more - */ - hfa384x_setreg(hw, 0x45, HFA384x_PCICOR); - timeout = jiffies + HZ/2; - while(time_before(jiffies, timeout)) udelay(5); - - /* Wait for f/w to complete initialization (CMD:BUSY == 0) - */ - timeout = jiffies + 2*HZ; - reg = hfa384x_getreg(hw, HFA384x_CMD); - while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) { - reg = hfa384x_getreg(hw, HFA384x_CMD); - udelay(10); - } - if (HFA384x_CMD_ISBUSY(reg)) { - WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n"); - result=1; - } - DBFEXIT; - return result; -} --- a/drivers/staging/wlan-ng/prism2_plx.c +++ /dev/null @@ -1,472 +0,0 @@ -#define WLAN_HOSTIF WLAN_PLX -#include "hfa384x.c" -#include "prism2mgmt.c" -#include "prism2mib.c" -#include "prism2sta.c" - -#define PLX_ATTR_SIZE 0x1000 /* Attribute memory size - 4K bytes */ -#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */ -#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */ -#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */ -#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ -#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */ - -/* 3Com 3CRW777A (PLX) board ID */ -#define PCIVENDOR_3COM 0x10B7 -#define PCIDEVICE_AIRCONNECT 0x7770 - -/* Eumitcom PCI WL11000 PCI Adapter (PLX) board device+vendor ID */ -#define PCIVENDOR_EUMITCOM 0x1638UL -#define PCIDEVICE_WL11000 0x1100UL - -/* Global Sun Tech GL24110P PCI Adapter (PLX) board device+vendor ID */ -#define PCIVENDOR_GLOBALSUN 0x16abUL -#define PCIDEVICE_GL24110P 0x1101UL -#define PCIDEVICE_GL24110P_ALT 0x1102UL - -/* Netgear MA301 PCI Adapter (PLX) board device+vendor ID */ -#define PCIVENDOR_NETGEAR 0x1385UL -#define PCIDEVICE_MA301 0x4100UL - -/* US Robotics USR2410 PCI Adapter (PLX) board device+vendor ID */ -#define PCIVENDOR_USROBOTICS 0x16ecUL -#define PCIDEVICE_USR2410 0x3685UL - -/* Linksys WPC11 card with the WDT11 adapter (PLX) board device+vendor ID */ -#define PCIVENDOR_Linksys 0x16abUL -#define PCIDEVICE_Wpc11Wdt11 0x1102UL - -/* National Datacomm Corp SOHOware Netblaster II PCI */ -#define PCIVENDOR_NDC 0x15e8UL -#define PCIDEVICE_NCP130_PLX 0x0130UL -#define PCIDEVICE_NCP130_ASIC 0x0131UL - -/* NDC NCP130_PLX is also sold by Corega. Their name is CGWLPCIA11 */ -#define PCIVENDOR_COREGA PCIVENDOR_NDC -#define PCIDEVICE_CGWLPCIA11 PCIDEVICE_NCP130_PLX - -/* PCI Class & Sub-Class code, Network-'Other controller' */ -#define PCI_CLASS_NETWORK_OTHERS 0x280 - -/*---------------------------------------------------------------- -* prism2sta_probe_plx -* -* Probe routine called when a PCI device w/ matching ID is found. -* This PLX implementation uses the following map: -* BAR0: Unused -* BAR1: ???? -* BAR2: PCMCIA attribute memory -* BAR3: PCMCIA i/o space -* Here's the sequence: -* - Allocate the PCI resources. -* - Read the PCMCIA attribute memory to make sure we have a WLAN card -* - Reset the MAC using the PCMCIA COR -* - Initialize the netdev and wlan data -* - Initialize the MAC -* -* Arguments: -* pdev ptr to pci device structure containing info about -* pci configuration. -* id ptr to the device id entry that matched this device. -* -* Returns: -* zero - success -* negative - failed -* -* Side effects: -* -* -* Call context: -* process thread -* -----------------------------------------------------------------*/ -static int __devinit -prism2sta_probe_plx( - struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int result; - phys_t pccard_ioaddr; - phys_t pccard_attr_mem; - unsigned int pccard_attr_len; - void __iomem *attr_mem = NULL; - UINT32 plx_addr; - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; - int reg; - u32 regic; - - if (pci_enable_device(pdev)) - return -EIO; - - /* TMC7160 boards are special */ - if ((pdev->vendor == PCIVENDOR_NDC) && - (pdev->device == PCIDEVICE_NCP130_ASIC)) { - unsigned long delay; - - pccard_attr_mem = 0; - pccard_ioaddr = pci_resource_start(pdev, 1); - - outb(0x45, pccard_ioaddr); - delay = jiffies + 1*HZ; - while (time_before(jiffies, delay)); - - if (inb(pccard_ioaddr) != 0x45) { - WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr)); - return -EIO; - } - - pccard_ioaddr = pci_resource_start(pdev, 2); - prism2_doreset = 0; - - WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq); - goto init; - } - - /* Collect the resource requirements */ - pccard_attr_mem = pci_resource_start(pdev, 2); - pccard_attr_len = pci_resource_len(pdev, 2); - if (pccard_attr_len < PLX_MIN_ATTR_LEN) - return -EIO; - - pccard_ioaddr = pci_resource_start(pdev, 3); - - /* bjoern: We need to tell the card to enable interrupts, in - * case the serial eprom didn't do this already. See the - * PLX9052 data book, p8-1 and 8-24 for reference. - * [MSM]: This bit of code came from the orinoco_cs driver. - */ - plx_addr = pci_resource_start(pdev, 1); - - regic = 0; - regic = inl(plx_addr+PLX_INTCSR); - if(regic & PLX_INTCSR_INTEN) { - WLAN_LOG_DEBUG(1, - "%s: Local Interrupt already enabled\n", dev_info); - } else { - regic |= PLX_INTCSR_INTEN; - outl(regic, plx_addr+PLX_INTCSR); - regic = inl(plx_addr+PLX_INTCSR); - if(!(regic & PLX_INTCSR_INTEN)) { - WLAN_LOG_ERROR( - "%s: Couldn't enable Local Interrupts\n", - dev_info); - return -EIO; - } - } - - /* These assignments are here in case of future mappings for - * io space and irq that might be similar to ioremap - */ - if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) { - WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info); - return -EIO; - } - - attr_mem = ioremap(pccard_attr_mem, pccard_attr_len); - - WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, " - "phymem:0x%llx, phyio=0x%x, irq:%d, " - "mem: 0x%lx\n", - (unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq, - (unsigned long)attr_mem); - - /* Verify whether PC card is present. - * [MSM] This needs improvement, the right thing to do is - * probably to walk the CIS looking for the vendor and product - * IDs. It would be nice if this could be tied in with the - * etc/pcmcia/wlan-ng.conf file. Any volunteers? ;-) - */ - if ( - readb(attr_mem + 0) != 0x01 || readb(attr_mem + 2) != 0x03 || - readb(attr_mem + 4) != 0x00 || readb(attr_mem + 6) != 0x00 || - readb(attr_mem + 8) != 0xFF || readb(attr_mem + 10) != 0x17 || - readb(attr_mem + 12) != 0x04 || readb(attr_mem + 14) != 0x67) { - WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n"); - return -EIO; - } - WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n"); - - /* Write COR to enable PC card */ - writeb(COR_VALUE, attr_mem + COR_OFFSET); - reg = readb(attr_mem + COR_OFFSET); - - init: - - /* - * Now do everything the same as a PCI device - * [MSM] TODO: We could probably factor this out of pcmcia/pci/plx - * and perhaps usb. Perhaps a task for another day....... - */ - - if ((wlandev = create_wlan()) == NULL) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); - result = -EIO; - goto failed; - } - - hw = wlandev->priv; - - if ( wlan_setup(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); - result = -EIO; - goto failed; - } - - /* Setup netdevice's ability to report resources - * Note: the netdevice was allocated by wlan_setup() - */ - wlandev->netdev->irq = pdev->irq; - wlandev->netdev->base_addr = pccard_ioaddr; - wlandev->netdev->mem_start = (unsigned long)attr_mem; - wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0); - - /* Initialize the hw data */ - hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_mem); - hw->wlandev = wlandev; - - /* Register the wlandev, this gets us a name and registers the - * linux netdevice. - */ - SET_MODULE_OWNER(wlandev->netdev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev)); -#endif - if ( register_wlandev(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); - result = -EIO; - goto failed; - } - -#if 0 - /* TODO: Move this and an irq test into an hfa384x_testif() routine. - */ - outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); - reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr)); - if ( reg != PRISM2STA_MAGIC ) { - WLAN_LOG_ERROR("MAC register access test failed!\n"); - result = -EIO; - goto failed; - } -#endif - - /* Do a chip-level reset on the MAC */ - if (prism2_doreset) { - result = hfa384x_corereset(hw, - prism2_reset_holdtime, - prism2_reset_settletime, 0); - if (result != 0) { - unregister_wlandev(wlandev); - hfa384x_destroy(hw); - WLAN_LOG_ERROR( - "%s: hfa384x_corereset() failed.\n", - dev_info); - result = -EIO; - goto failed; - } - } - - pci_set_drvdata(pdev, wlandev); - - /* Shouldn't actually hook up the IRQ until we - * _know_ things are alright. A test routine would help. - */ - request_irq(wlandev->netdev->irq, hfa384x_interrupt, - SA_SHIRQ, wlandev->name, wlandev); - - wlandev->msdstate = WLAN_MSD_HWPRESENT; - - result = 0; - - goto done; - - failed: - - pci_set_drvdata(pdev, NULL); - if (wlandev) kfree(wlandev); - if (hw) kfree(hw); - if (attr_mem) iounmap(attr_mem); - pci_release_regions(pdev); - pci_disable_device(pdev); - - done: - DBFEXIT; - return result; -} - -static void __devexit prism2sta_remove_plx(struct pci_dev *pdev) -{ - wlandevice_t *wlandev; - hfa384x_t *hw; - - wlandev = (wlandevice_t *) pci_get_drvdata(pdev); - hw = wlandev->priv; - - p80211netdev_hwremoved(wlandev); - - /* reset hardware */ - prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); - - if (pdev->irq) - free_irq(pdev->irq, wlandev); - - unregister_wlandev(wlandev); - - /* free local stuff */ - if (hw) { - hfa384x_destroy(hw); - kfree(hw); - } - - iounmap((void __iomem *)wlandev->netdev->mem_start); - wlan_unsetup(wlandev); - - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - - kfree(wlandev); -} - -static struct pci_device_id plx_id_tbl[] = { - { - PCIVENDOR_EUMITCOM, PCIDEVICE_WL11000, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Eumitcom WL11000 PCI(PLX) card" - }, - { - PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" - }, - { - PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P_ALT, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" - }, - { - PCIVENDOR_NETGEAR, PCIDEVICE_MA301, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Global Sun Tech GL24110P PCI(PLX) card" - }, - { - PCIVENDOR_USROBOTICS, PCIDEVICE_USR2410, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"US Robotics USR2410 PCI(PLX) card" - }, - { - PCIVENDOR_Linksys, PCIDEVICE_Wpc11Wdt11, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"Linksys WPC11 with WDT11 PCI(PLX) adapter" - }, - { - PCIVENDOR_NDC, PCIDEVICE_NCP130_PLX, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"NDC Netblaster II PCI(PLX)" - }, - { - PCIVENDOR_NDC, PCIDEVICE_NCP130_ASIC, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"NDC Netblaster II PCI(TMC7160)" - }, - { - PCIVENDOR_3COM, PCIDEVICE_AIRCONNECT, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, - /* Driver data, we just put the name here */ - (unsigned long)"3Com AirConnect PCI 802.11b 11Mb/s WLAN Controller" - }, - { - 0, 0, 0, 0, 0, 0, 0 - } -}; - -MODULE_DEVICE_TABLE(pci, plx_id_tbl); - -/* Function declared here because of ptr reference below */ -static int __devinit prism2sta_probe_plx(struct pci_dev *pdev, - const struct pci_device_id *); -static void __devexit prism2sta_remove_plx(struct pci_dev *pdev); - -static struct pci_driver prism2_plx_drv_id = { - .name = "prism2_plx", - .id_table = plx_id_tbl, - .probe = prism2sta_probe_plx, - .remove = prism2sta_remove_plx, -#ifdef CONFIG_PM - .suspend = prism2sta_suspend_pci, - .resume = prism2sta_resume_pci, -#endif -}; - -#ifdef MODULE - -static int __init prism2plx_init(void) -{ - WLAN_LOG_NOTICE("%s Loaded\n", version); - return pci_module_init(&prism2_plx_drv_id); -}; - -static void __exit prism2plx_cleanup(void) -{ - pci_unregister_driver(&prism2_plx_drv_id); -}; - -module_init(prism2plx_init); -module_exit(prism2plx_cleanup); - -#endif // MODULE - - -int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) -{ - int result = 0; - -#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */ -#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */ - -#define HCR_OFFSET 0x3e2 /* HCR attribute offset of Prism2 PC card */ - - UINT8 corsave; - DBFENTER; - - WLAN_LOG_DEBUG(3, "Doing reset via direct COR access.\n"); - - /* Collect COR */ - corsave = readb(hw->membase + COR_OFFSET); - /* Write reset bit (BIT7) */ - writeb(corsave | BIT7, hw->membase + COR_OFFSET); - /* Hold for holdtime */ - mdelay(holdtime); - - if (genesis) { - writeb(genesis, hw->membase + HCR_OFFSET); - /* Hold for holdtime */ - mdelay(holdtime); - } - - /* Clear reset bit */ - writeb(corsave & ~BIT7, hw->membase + COR_OFFSET); - /* Wait for settletime */ - mdelay(settletime); - /* Set non-reset bits back what they were */ - writeb(corsave, hw->membase + COR_OFFSET); - DBFEXIT; - return result; -} --- a/drivers/staging/wlan-ng/README +++ b/drivers/staging/wlan-ng/README @@ -3,6 +3,5 @@ TODO: - sparse warnings - Lindent cleanups - move to use the in-kernel wireless stack - - possible enable the pcmcia and pci portions of the driver Please send all patches to Greg Kroah-Hartman