📄 prism2.c
字号:
/**************************************************************************Etherboot - BOOTP/TFTP Bootstrap ProgramPrism2 NIC driver for EtherbootWritten by Michael Brown of Fen Systems Ltd$Id: prism2.c,v 1.5 2003/03/18 02:45:11 ebiederm Exp $***************************************************************************//* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. *//* to get some global routines like printf */#include "etherboot.h"/* to get the interface to the body of the program */#include "nic.h"/* to get the PCI support functions, if this is a PCI NIC */#include "pci.h"/* * Hard-coded SSID * Leave blank in order to connect to any available SSID */static const char hardcoded_ssid[] = "";/* * Maximum number of info packets to wait for on a join attempt. * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet * before sending the "you are connected" packet, if the card has previously been * attached to the AP. * * 2 is probably a sensible value, but YMMV. */#define MAX_JOIN_INFO_COUNT 2/* * Type of Prism2 interface to support * If not already defined, select PLX */#ifndef WLAN_HOSTIF#define WLAN_HOSTIF WLAN_PLX#endif/* * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver * We need to hack some defines in order to avoid compiling kernel-specific routines */#define __LINUX_WLAN__#undef __KERNEL__#define __I386__#include "wlan_compat.h"#include "p80211hdr.h"#include "hfa384x.h"#define BAP_TIMEOUT ( 5000 )/* * A few hacks to make the coding environment more Linux-like. This makes it somewhat * quicker to convert code from the Linux Prism2 driver. */#include <errno.h>#include "timer.h"#define __le16_to_cpu(x) (x)#define __le32_to_cpu(x) (x)#define __cpu_to_le16(x) (x)#define __cpu_to_le32(x) (x)/* * PLX9052 PCI register offsets * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf */#define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )#define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )#define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )#define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )#define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )#define PRISM2_PLX_ATTR_MEM_BASE ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )#define PRISM2_PLX_IO_BASE ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )#define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )/* * PCMCIA CIS types * Taken from cistpl.h in pcmcia-cs */#define CISTPL_VERS_1 ( 0x15 )#define CISTPL_END ( 0xff )#define CIS_STEP ( 2 )#define CISTPL_HEADER_LEN ( 2 * CIS_STEP )#define CISTPL_LEN_OFF ( 1 * CIS_STEP )#define CISTPL_VERS_1_STR_OFF ( 4 * CIS_STEP )/* * Prism2 constants * Taken from prism2sta.c in linux-wlan-ng */#define COR_OFFSET ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */#define COR_VALUE ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) *//* NIC specific static variables *//* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined. * This is a dummy version that contains only the fields we are interested in. */typedef struct hfa384x{ UINT32 iobase; UINT32 membase; UINT16 lastcmd; UINT16 status; /* in host order */ UINT16 resp0; /* in host order */ UINT16 resp1; /* in host order */ UINT16 resp2; /* in host order */ UINT8 bssid[WLAN_BSSID_LEN];} hfa384x_t;/* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */static hfa384x_t hw_global = { 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}};/* * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP) * Taken from p80211conv.h */typedef struct wlan_llc{ UINT8 dsap __WLAN_ATTRIB_PACK__; UINT8 ssap __WLAN_ATTRIB_PACK__; UINT8 ctl __WLAN_ATTRIB_PACK__;} __WLAN_ATTRIB_PACK__ wlan_llc_t;static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */#define WLAN_IEEE_OUI_LEN 3typedef struct wlan_snap{ UINT8 oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__; UINT16 type __WLAN_ATTRIB_PACK__;} __WLAN_ATTRIB_PACK__ wlan_snap_t;typedef struct wlan_80211hdr{ wlan_llc_t llc; wlan_snap_t snap;} wlan_80211hdr_t;/* * Function prototypes */#if (WLAN_HOSTIF == WLAN_PLX)static int prism2_find_plx ( hfa384x_t *hw, struct pci_device *p );#elif (WLAN_HOSTIF == WLAN_PCI)static int prism2_find_pci ( hfa384x_t *hw, struct pci_device *p );#endif/* * Hardware-level hfa384x functions * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined). * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions. *//* Retrieve the value of one of the MAC registers. */static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg ){#if (WLAN_HOSTIF == WLAN_PLX) return inw ( hw->iobase + reg );#elif (WLAN_HOSTIF == WLAN_PCI) return readw ( hw->membase + reg );#endif}/* Set the value of one of the MAC registers. */static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg ){#if (WLAN_HOSTIF == WLAN_PLX) outw ( val, hw->iobase + reg );#elif (WLAN_HOSTIF == WLAN_PCI) writew ( val, hw->membase + reg );#endif return;}/* * Noswap versions * Etherboot is i386 only, so swap and noswap are the same... */static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg ){ return hfa384x_getreg ( hw, reg );}static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg ){ hfa384x_setreg ( hw, val, reg );}/* * Low-level hfa384x functions * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment. *//* * hfa384x_docmd_wait * * Waits for availability of the Command register, then * issues the given command. Then polls the Evstat register * waiting for command completion. * Arguments: * hw device structure * cmd Command in host order * parm0 Parameter0 in host order * parm1 Parameter1 in host order * parm2 Parameter2 in host order * Returns: * 0 success * >0 command indicated error, Status and Resp0-2 are * in hw structure. */static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2){ UINT16 reg = 0; UINT16 counter = 0; /* 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)) { printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg); return -ETIMEDOUT; } /* busy bit clear, write command */ hfa384x_setreg(hw, parm0, HFA384x_PARAM0); hfa384x_setreg(hw, parm1, HFA384x_PARAM1); hfa384x_setreg(hw, parm2, HFA384x_PARAM2); hw->lastcmd = cmd; hfa384x_setreg(hw, cmd, HFA384x_CMD); /* 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) ) { printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg); return -ETIMEDOUT; } /* Read status and response */ hw->status = hfa384x_getreg(hw, HFA384x_STATUS); hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0); hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1); hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2); hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK); return HFA384x_STATUS_RESULT_GET(hw->status);}/* * Prepare BAP for access. Assigns FID and RID, sets offset register * and waits for BAP to become available. * * Arguments: * hw device structure * id FID or RID, destined for the select register (host order) * offset An _even_ offset into the buffer for the given FID/RID. * Returns: * 0 success */static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset){ int result = 0; UINT16 reg; UINT16 i; /* Validate offset, buf, and len */ if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) { result = -EINVAL; } else { /* Write fid/rid and offset */ hfa384x_setreg(hw, id, HFA384x_SELECT0); udelay(10); hfa384x_setreg(hw, offset, HFA384x_OFFSET0); /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -