diff options
Diffstat (limited to 'gpxe/src/drivers/net/prism2.c')
-rw-r--r-- | gpxe/src/drivers/net/prism2.c | 857 |
1 files changed, 0 insertions, 857 deletions
diff --git a/gpxe/src/drivers/net/prism2.c b/gpxe/src/drivers/net/prism2.c deleted file mode 100644 index 4c665929..00000000 --- a/gpxe/src/drivers/net/prism2.c +++ /dev/null @@ -1,857 +0,0 @@ -/************************************************************************** -Etherboot - BOOTP/TFTP Bootstrap Program -Prism2 NIC driver for Etherboot - -Written by Michael Brown of Fen Systems Ltd -$Id$ -***************************************************************************/ - -/* - * 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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <etherboot.h> -#include <nic.h> -#include <gpxe/pci.h> -#include <gpxe/ethernet.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> -#define __le16_to_cpu(x) (x) -#define __le32_to_cpu(x) (x) -#define __cpu_to_le16(x) (x) -#define __cpu_to_le32(x) (x) - -#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n))) -#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n))) -#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n))) -#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n))) - -/* - * 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; - void *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; - UINT8 ssap; - UINT8 ctl; -} wlan_llc_t; - -static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */ - -#define WLAN_IEEE_OUI_LEN 3 -typedef struct wlan_snap -{ - UINT8 oui[WLAN_IEEE_OUI_LEN]; - UINT16 type; -} wlan_snap_t; - -typedef struct wlan_80211hdr -{ - wlan_llc_t llc; - wlan_snap_t snap; -} wlan_80211hdr_t; - -/* - * Function prototypes - */ - -/* - * 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; - do { - reg = hfa384x_getreg(hw, HFA384x_OFFSET0); - if ( i > 0 ) udelay(2); - i++; - } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg)); - if ( i >= BAP_TIMEOUT ) { - /* failure */ - result = reg; - } else if ( HFA384x_OFFSET_ISERR(reg) ){ - /* failure */ - result = reg; - } - } - return result; -} - -/* - * Copy data from BAP to memory. - * - * 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. - * buf ptr to array of bytes - * len length of data to transfer in bytes - * Returns: - * 0 success - */ -static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, - void *buf, UINT len) -{ - int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 i; - UINT16 reg = 0; - - /* Prepare BAP */ - result = hfa384x_prepare_bap ( hw, id, offset ); - if ( result == 0 ) { - /* Read even(len) buf contents from data reg */ - for ( i = 0; i < (len & 0xfffe); i+=2 ) { - *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0); - } - /* If len odd, handle last byte */ - if ( len % 2 ){ - reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0); - d[len-1] = ((UINT8*)(®))[0]; - } - } - if (result) { - printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result); - } - return result; -} - -/* - * Copy data from memory to BAP. - * - * 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. - * buf ptr to array of bytes - * len length of data to transfer in bytes - * Returns: - * 0 success - */ -static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, - void *buf, UINT len) -{ - int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 i; - UINT16 savereg; - - /* Prepare BAP */ - result = hfa384x_prepare_bap ( hw, id, offset ); - if ( result == 0 ) { - /* Write even(len) buf contents to data reg */ - for ( i = 0; i < (len & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0); - } - /* If len odd, handle last byte */ - if ( len % 2 ){ - savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0); - result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) ); - if ( result == 0 ) { - ((UINT8*)(&savereg))[0] = d[len-1]; - hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0); - } - } - } - if (result) { - printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result); - } - return result; -} - -/* - * Request a given record to be copied to/from the record buffer. - * - * 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) - * - * Returns: - * 0 success - */ -static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid) -{ - return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0); -} - -/* - * 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 - */ -static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) -{ - int result = 0; - hfa384x_rec_t rec; - - /* Request read of RID */ - result = hfa384x_cmd_access( hw, 0, rid); - if ( result ) { - printf("Call to hfa384x_cmd_access failed\n"); - return -1; - } - /* Copy out record length */ - result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec)); - if ( result ) { - return -1; - } - /* Validate the record length */ - if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */ - printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2); - return -1; - } - /* Copy out record data */ - result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len); - return result; -} - -/* - * Performs the sequence necessary to read a 16/32 bit config/info item - * and convert it to host order. - * - * Arguments: - * hw device structure - * rid config/info record id (in host order) - * val ptr to 16/32 bit buffer to receive value (in host order) - * - * Returns: - * 0 success - */ -#if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val) -{ - int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); - if ( result == 0 ) { - *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); - } - return result; -} -#endif -#if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) -{ - int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); - if ( result == 0 ) { - *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); - } - return result; -} -#endif - -/* - * 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 - */ -static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) -{ - int result = 0; - hfa384x_rec_t rec; - - rec.rid = host2hfa384x_16(rid); - rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */ - /* write the record header */ - result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec)); - if ( result ) { - printf("Failure writing record header\n"); - return -1; - } - /* write the record data (if there is any) */ - if ( len > 0 ) { - result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len); - if ( result ) { - printf("Failure writing record data\n"); - return -1; - } - } - /* Trigger setting of record */ - result = hfa384x_cmd_access( hw, 1, rid); - return result; -} - -/* - * Performs the sequence necessary to write a 16/32 bit config/info item. - * - * Arguments: - * hw device structure - * rid config/info record id (in host order) - * val 16/32 bit value to store (in host order) - * - * Returns: - * 0 success - */ -static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val) -{ - UINT16 value; - value = host2hfa384x_16(*val); - return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16)); -} -#if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val) -{ - UINT32 value; - value = host2hfa384x_32(*val); - return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32)); -} -#endif - -/* - * Wait for an event, with specified checking interval and timeout. - * Automatically acknolwedges events. - * - * Arguments: - * hw device structure - * event_mask EVSTAT register mask of events to wait for - * event_ack EVACK register set of events to be acknowledged if they happen (can be - * used to acknowledge "ignorable" events in addition to the "main" event) - * wait Time (in us) to wait between each poll of the register - * timeout Maximum number of polls before timing out - * descr Descriptive text string of what is being waited for - * (will be printed out if a timeout happens) - * - * Returns: - * value of EVSTAT register, or 0 on failure - */ -static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr) -{ - UINT16 reg; - int count = 0; - - do { - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - if ( count > 0 ) udelay(wait); - count++; - } while ( !(reg & event_mask) && count < timeout); - if ( count >= timeout ) { - printf("hfa384x: Timed out waiting for %s\n", descr); - return 0; /* Return failure */ - } - /* Acknowledge all events that we were waiting on */ - hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK); - return reg; -} - -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int prism2_poll(struct nic *nic, int retrieve) -{ - UINT16 reg; - UINT16 rxfid; - UINT16 result; - hfa384x_rx_frame_t rxdesc; - hfa384x_t *hw = &hw_global; - - /* Check for received packet */ - reg = hfa384x_getreg(hw, HFA384x_EVSTAT); - if ( ! HFA384x_EVSTAT_ISRX(reg) ) { - /* No packet received - return 0 */ - return 0; - } - - if ( ! retrieve ) return 1; - - /* Acknowledge RX event */ - hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK); - /* Get RX FID */ - rxfid = hfa384x_getreg(hw, HFA384x_RXFID); - /* Get the descriptor (including headers) */ - result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc)); - if ( result ) { - return 0; /* fail */ - } - /* Byte order convert once up front. */ - rxdesc.status = hfa384x2host_16(rxdesc.status); - rxdesc.time = hfa384x2host_32(rxdesc.time); - rxdesc.data_len = hfa384x2host_16(rxdesc.data_len); - - /* Fill in nic->packetlen */ - nic->packetlen = rxdesc.data_len; - if ( nic->packetlen > 0 ) { - /* Fill in nic->packet */ - /* - * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type. - * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the - * header), so we use a quick hack to achieve this. - */ - result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF, - nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen); - if ( result ) { - return 0; /* fail */ - } - } - return 1; /* Packet successfully received */ -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static void prism2_transmit( - struct nic *nic, - const char *d, /* Destination */ - unsigned int t, /* Type */ - unsigned int s, /* size */ - const char *p) /* Packet */ -{ - hfa384x_t *hw = &hw_global; - hfa384x_tx_frame_t txdesc; - wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} }; - UINT16 fid; - UINT16 status; - int result; - - // Request FID allocation - result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0); - if (result != 0) { - printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n"); - return; - } - if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return; - fid = hfa384x_getreg(hw, HFA384x_ALLOCFID); - - /* Build Tx frame structure */ - memset(&txdesc, 0, sizeof(txdesc)); - txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) ); - txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | - WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) | - WLAN_SET_FC_TODS(1) ); - memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN); - memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN); - memcpy(txdesc.address3, d, WLAN_ADDR_LEN); - txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s ); - /* Set up SNAP header */ - /* Let OUI default to RFC1042 (0x000000) */ - p80211hdr.snap.type = htons(t); - - /* Copy txdesc, p80211hdr and payload parts to FID */ - result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc)); - if ( result ) return; /* fail */ - result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) ); - if ( result ) return; /* fail */ - result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s ); - if ( result ) return; /* fail */ - - /* Issue Tx command */ - result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0); - if ( result != 0 ) { - printf("hfa384x: Transmit failed with result %#hx.\n", result); - return; - } - - /* Wait for transmit completion (or exception) */ - result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO, - 200, 500, "Tx to complete\n" ); - if ( !result ) return; /* timeout failure */ - if ( HFA384x_EVSTAT_ISTXEXC(result) ) { - fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID); - printf ( "Tx exception occurred with fid %#hx\n", fid ); - result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status)); - if ( result ) return; /* fail */ - printf("hfa384x: Tx error occurred (status %#hx):\n", status); - if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); } - if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); } - if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); } - if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); } - if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); } - return; /* fail */ - } -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void prism2_disable ( struct nic *nic __unused ) { - /* put the card in its initial state */ -} - -/************************************************************************** -IRQ - Enable, Disable, or Force interrupts -***************************************************************************/ -static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused) -{ - switch ( action ) { - case DISABLE : - break; - case ENABLE : - break; - case FORCE : - break; - } -} - -/************************************************************************** -Operations table -***************************************************************************/ -static struct nic_operations prism2_operations = { - .connect = dummy_connect, - .poll = prism2_poll, - .transmit = prism2_transmit, - .irq = prism2_irq, -}; - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -You should omit the last argument struct pci_device * for a non-PCI NIC -***************************************************************************/ -static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) { - int result; - UINT16 tmp16 = 0; - UINT16 infofid; - hfa384x_InfFrame_t inf; - char ssid[HFA384x_RID_CNFDESIREDSSID_LEN]; - int info_count = 0; - - nic->irqno = 0; - - /* Initialize card */ - result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */ - if ( result ) printf ( "Initialize command returned %#hx\n", result ); - hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */ - hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */ - - DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) ); - - /* Retrieve MAC address (and fill out nic->node_addr) */ - hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN ); - - /* Prepare card for autojoin */ - /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */ - tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */ - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16); - if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result ); - tmp16 = 0x000f; /* Set transmit rate(?) */ - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16); - if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result ); - tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */ - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16); - if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result ); - /* Set SSID */ - memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN); - for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; } - ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */ - result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */ - if ( result ) printf ( "Set SSID command returned %#hx\n", result ); - tmp16 = 1; /* Set port type to ESS port */ - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16); - if ( result ) printf ( "Set port type command returned %#hx\n", result ); - /* Enable card */ - result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0); - if ( result ) printf ( "Enable command returned %#hx\n", result ); - - do { - /* Increment info_count, abort if too many attempts. - * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation. - */ - info_count++; - if ( info_count > MAX_JOIN_INFO_COUNT ) { - printf ( "Too many failed attempts - aborting\n" ); - return 0; - } - - /* Wait for info frame to indicate link status */ - if ( sizeof(hardcoded_ssid) == 1 ) { - /* Empty SSID => join to any SSID */ - printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count ); - } else { - printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count ); - } - - if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0; - printf("done\n"); - infofid = hfa384x_getreg(hw, HFA384x_INFOFID); - /* Retrieve the length */ - result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16)); - if ( result ) return 0; /* fail */ - inf.framelen = hfa384x2host_16(inf.framelen); - /* Retrieve the rest */ - result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16), - &(inf.infotype), inf.framelen * sizeof(UINT16)); - if ( result ) return 0; /* fail */ - if ( inf.infotype != HFA384x_IT_LINKSTATUS ) { - /* Not a Link Status info frame: die */ - printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype ); - return 0; - } - inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus); - if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) { - /* Link not connected - retry */ - printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus ); - } - } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ); - - /* Retrieve BSSID and print Connected message */ - result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN); - - DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) ); - DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) ); - - /* point to NIC specific routines */ - nic->nic_op = &prism2_operations; - return 1; -} - |