iPXE
Data Structures | Defines | Typedefs | Functions | Variables
prism2.c File Reference
#include <etherboot.h>
#include <nic.h>
#include <ipxe/pci.h>
#include <ipxe/ethernet.h>
#include "wlan_compat.h"
#include "p80211hdr.h"
#include "hfa384x.h"
#include <errno.h>

Go to the source code of this file.

Data Structures

struct  hfa384x
struct  wlan_llc
struct  wlan_snap
struct  wlan_80211hdr

Defines

#define MAX_JOIN_INFO_COUNT   2
#define WLAN_HOSTIF   WLAN_PLX
#define __LINUX_WLAN__
#define __I386__
#define BAP_TIMEOUT   ( 5000 )
#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_t)(n)))
#define hfa384x2host_32(n)   (__le32_to_cpu((uint32_t)(n)))
#define host2hfa384x_16(n)   (__cpu_to_le16((uint16_t)(n)))
#define host2hfa384x_32(n)   (__cpu_to_le32((uint32_t)(n)))
#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 )
#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 )
#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) */
#define WLAN_IEEE_OUI_LEN   3

Typedefs

typedef struct hfa384x hfa384x_t
typedef struct wlan_llc wlan_llc_t
typedef struct wlan_snap wlan_snap_t
typedef struct wlan_80211hdr wlan_80211hdr_t

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static uint16_t hfa384x_getreg (hfa384x_t *hw, unsigned int reg)
static void hfa384x_setreg (hfa384x_t *hw, uint16_t val, unsigned int reg)
static uint16_t hfa384x_getreg_noswap (hfa384x_t *hw, unsigned int reg)
static void hfa384x_setreg_noswap (hfa384x_t *hw, uint16_t val, unsigned int reg)
static int hfa384x_docmd_wait (hfa384x_t *hw, uint16_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2)
static int hfa384x_prepare_bap (hfa384x_t *hw, uint16_t id, uint16_t offset)
static int hfa384x_copy_from_bap (hfa384x_t *hw, uint16_t id, uint16_t offset, void *buf, unsigned int len)
static int hfa384x_copy_to_bap (hfa384x_t *hw, uint16_t id, uint16_t offset, void *buf, unsigned int len)
static int hfa384x_cmd_access (hfa384x_t *hw, uint16_t write, uint16_t rid)
static int hfa384x_drvr_getconfig (hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
static int hfa384x_drvr_setconfig (hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
static int hfa384x_drvr_setconfig16 (hfa384x_t *hw, uint16_t rid, uint16_t *val)
static int hfa384x_wait_for_event (hfa384x_t *hw, uint16_t event_mask, uint16_t event_ack, int wait, int timeout, const char *descr)
static int prism2_poll (struct nic *nic, int retrieve)
static void prism2_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static void prism2_disable (struct nic *nic __unused)
static void prism2_irq (struct nic *nic __unused, irq_action_t action __unused)
static int prism2_probe (struct nic *nic, hfa384x_t *hw)

Variables

static const char hardcoded_ssid [] = ""
static hfa384x_t hw_global
static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }
static struct nic_operations prism2_operations

Define Documentation

#define MAX_JOIN_INFO_COUNT   2

Definition at line 49 of file prism2.c.

Referenced by prism2_probe().

#define WLAN_HOSTIF   WLAN_PLX

Definition at line 56 of file prism2.c.

#define __LINUX_WLAN__

Definition at line 64 of file prism2.c.

#define __I386__

Definition at line 66 of file prism2.c.

#define BAP_TIMEOUT   ( 5000 )

Definition at line 70 of file prism2.c.

Referenced by hfa384x_prepare_bap().

#define __le16_to_cpu (   x)    (x)

Definition at line 77 of file prism2.c.

#define __le32_to_cpu (   x)    (x)

Definition at line 78 of file prism2.c.

#define __cpu_to_le16 (   x)    (x)

Definition at line 79 of file prism2.c.

#define __cpu_to_le32 (   x)    (x)

Definition at line 80 of file prism2.c.

#define hfa384x2host_16 (   n)    (__le16_to_cpu((uint16_t)(n)))

Definition at line 82 of file prism2.c.

Referenced by hfa384x_drvr_getconfig(), prism2_poll(), and prism2_probe().

#define hfa384x2host_32 (   n)    (__le32_to_cpu((uint32_t)(n)))

Definition at line 83 of file prism2.c.

Referenced by prism2_poll().

#define host2hfa384x_16 (   n)    (__cpu_to_le16((uint16_t)(n)))

Definition at line 84 of file prism2.c.

Referenced by hfa384x_drvr_setconfig(), hfa384x_drvr_setconfig16(), and prism2_transmit().

#define host2hfa384x_32 (   n)    (__cpu_to_le32((uint32_t)(n)))

Definition at line 85 of file prism2.c.

Definition at line 92 of file prism2.c.

Referenced by prism2_find_plx().

Definition at line 93 of file prism2.c.

Definition at line 94 of file prism2.c.

Definition at line 95 of file prism2.c.

Definition at line 96 of file prism2.c.

Definition at line 98 of file prism2.c.

Referenced by prism2_find_plx().

Definition at line 99 of file prism2.c.

Referenced by prism2_find_plx().

Definition at line 101 of file prism2.c.

#define CISTPL_VERS_1   ( 0x15 )

Definition at line 108 of file prism2.c.

Referenced by prism2_find_plx().

#define CISTPL_END   ( 0xff )

Definition at line 109 of file prism2.c.

Referenced by prism2_find_plx().

#define CIS_STEP   ( 2 )

Definition at line 111 of file prism2.c.

Referenced by prism2_find_plx().

#define CISTPL_HEADER_LEN   ( 2 * CIS_STEP )

Definition at line 112 of file prism2.c.

Referenced by prism2_find_plx().

#define CISTPL_LEN_OFF   ( 1 * CIS_STEP )

Definition at line 113 of file prism2.c.

Referenced by prism2_find_plx().

#define CISTPL_VERS_1_STR_OFF   ( 4 * CIS_STEP )

Definition at line 114 of file prism2.c.

Referenced by prism2_find_plx().

#define COR_OFFSET   ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */

Definition at line 121 of file prism2.c.

Referenced by prism2_find_plx().

#define COR_VALUE   ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) */

Definition at line 122 of file prism2.c.

Referenced by prism2_find_plx().

#define WLAN_IEEE_OUI_LEN   3

Definition at line 159 of file prism2.c.


Typedef Documentation

typedef struct hfa384x hfa384x_t
typedef struct wlan_llc wlan_llc_t
typedef struct wlan_snap wlan_snap_t

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static uint16_t hfa384x_getreg ( hfa384x_t hw,
unsigned int  reg 
) [inline, static]

Definition at line 183 of file prism2.c.

References inw(), hfa384x::iobase, hfa384x::membase, and readw().

Referenced by hfa384x_docmd_wait(), hfa384x_getreg_noswap(), hfa384x_prepare_bap(), hfa384x_wait_for_event(), prism2_poll(), prism2_probe(), and prism2_transmit().

{
#if (WLAN_HOSTIF == WLAN_PLX)
  return inw ( hw->iobase + reg );
#elif (WLAN_HOSTIF == WLAN_PCI)
  return readw ( hw->membase + reg );
#endif
}
static void hfa384x_setreg ( hfa384x_t hw,
uint16_t  val,
unsigned int  reg 
) [inline, static]

Definition at line 193 of file prism2.c.

References hfa384x::iobase, hfa384x::membase, outw(), and writew().

Referenced by hfa384x_docmd_wait(), hfa384x_prepare_bap(), hfa384x_setreg_noswap(), hfa384x_wait_for_event(), prism2_poll(), and prism2_probe().

{
#if (WLAN_HOSTIF == WLAN_PLX)
  outw ( val, hw->iobase + reg );
#elif (WLAN_HOSTIF == WLAN_PCI)
  writew ( val, hw->membase + reg );
#endif
  return;
}
static uint16_t hfa384x_getreg_noswap ( hfa384x_t hw,
unsigned int  reg 
) [inline, static]

Definition at line 207 of file prism2.c.

References hfa384x_getreg().

Referenced by hfa384x_copy_from_bap(), and hfa384x_copy_to_bap().

{
  return hfa384x_getreg ( hw, reg );
}
static void hfa384x_setreg_noswap ( hfa384x_t hw,
uint16_t  val,
unsigned int  reg 
) [inline, static]

Definition at line 211 of file prism2.c.

References hfa384x_setreg().

Referenced by hfa384x_copy_to_bap().

{
  hfa384x_setreg ( hw, val, reg );
}
static int hfa384x_docmd_wait ( hfa384x_t hw,
uint16_t  cmd,
uint16_t  parm0,
uint16_t  parm1,
uint16_t  parm2 
) [static]

Definition at line 238 of file prism2.c.

References cmd, ETIMEDOUT, HFA384x_CMD, HFA384x_CMD_ISBUSY, HFA384x_EVACK, HFA384x_EVACK_CMD, HFA384x_EVSTAT, HFA384x_EVSTAT_ISCMD, hfa384x_getreg(), HFA384x_PARAM0, HFA384x_PARAM1, HFA384x_PARAM2, HFA384x_RESP0, HFA384x_RESP1, HFA384x_RESP2, hfa384x_setreg(), HFA384x_STATUS, HFA384x_STATUS_RESULT_GET, hfa384x::lastcmd, printf(), reg, hfa384x::resp0, hfa384x::resp1, hfa384x::resp2, hfa384x::status, and udelay().

Referenced by hfa384x_cmd_access(), prism2_probe(), and prism2_transmit().

{
  uint16_t reg = 0;
  uint16_t 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);
}
static int hfa384x_prepare_bap ( hfa384x_t hw,
uint16_t  id,
uint16_t  offset 
) [static]

Definition at line 300 of file prism2.c.

References BAP_TIMEOUT, EINVAL, HFA384x_BAP_OFFSET_MAX, hfa384x_getreg(), HFA384x_OFFSET0, HFA384x_OFFSET_ISBUSY, HFA384x_OFFSET_ISERR, HFA384x_SELECT0, hfa384x_setreg(), reg, and udelay().

Referenced by hfa384x_copy_from_bap(), and hfa384x_copy_to_bap().

{
  int result = 0;
  uint16_t reg;
  uint16_t 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;
}
static int hfa384x_copy_from_bap ( hfa384x_t hw,
uint16_t  id,
uint16_t  offset,
void *  buf,
unsigned int  len 
) [static]

Definition at line 344 of file prism2.c.

References HFA384x_DATA0, hfa384x_getreg_noswap(), hfa384x_prepare_bap(), printf(), and reg.

Referenced by hfa384x_drvr_getconfig(), prism2_poll(), prism2_probe(), and prism2_transmit().

{
  int result = 0;
  uint8_t       *d = (uint8_t*)buf;
  uint16_t i;
  uint16_t 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_t*)(&(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_t*)(&reg))[0];
    }
  }
  if (result) {
    printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
  }
  return result;
}
static int hfa384x_copy_to_bap ( hfa384x_t hw,
uint16_t  id,
uint16_t  offset,
void *  buf,
unsigned int  len 
) [static]

Definition at line 383 of file prism2.c.

References HFA384x_DATA0, hfa384x_getreg_noswap(), hfa384x_prepare_bap(), hfa384x_setreg_noswap(), and printf().

Referenced by hfa384x_drvr_setconfig(), and prism2_transmit().

{
  int result = 0;
  uint8_t       *d = (uint8_t*)buf;
  uint16_t i;
  uint16_t 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_t*)(&(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_t*)(&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;
}
static int hfa384x_cmd_access ( hfa384x_t hw,
uint16_t  write,
uint16_t  rid 
) [inline, static]
static int hfa384x_drvr_getconfig ( hfa384x_t hw,
uint16_t  rid,
void *  buf,
uint16_t  len 
) [static]

Definition at line 445 of file prism2.c.

References hfa384x2host_16, hfa384x_cmd_access(), hfa384x_copy_from_bap(), printf(), and hfa384x_record::reclen.

Referenced by prism2_probe().

{
  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;
}
static int hfa384x_drvr_setconfig ( hfa384x_t hw,
uint16_t  rid,
void *  buf,
uint16_t  len 
) [static]

Definition at line 518 of file prism2.c.

References hfa384x_cmd_access(), hfa384x_copy_to_bap(), host2hfa384x_16, printf(), hfa384x_record::reclen, and hfa384x_record::rid.

Referenced by hfa384x_drvr_setconfig16(), and prism2_probe().

{
  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;
}
static int hfa384x_drvr_setconfig16 ( hfa384x_t hw,
uint16_t  rid,
uint16_t val 
) [static]

Definition at line 555 of file prism2.c.

References hfa384x_drvr_setconfig(), host2hfa384x_16, and value.

Referenced by prism2_probe().

{
  uint16_t value;
  value = host2hfa384x_16(*val);
  return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint16_t));
}
static int hfa384x_wait_for_event ( hfa384x_t hw,
uint16_t  event_mask,
uint16_t  event_ack,
int  wait,
int  timeout,
const char *  descr 
) [static]

Definition at line 587 of file prism2.c.

References count, HFA384x_EVACK, HFA384x_EVSTAT, hfa384x_getreg(), hfa384x_setreg(), printf(), reg, and udelay().

Referenced by prism2_probe(), and prism2_transmit().

{
  uint16_t 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;
}
static int prism2_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 609 of file prism2.c.

References hfa384x_rx_frame::data_len, ETH_HLEN, hfa384x2host_16, hfa384x2host_32, hfa384x_copy_from_bap(), HFA384x_EVACK, HFA384x_EVACK_RX_SET, HFA384x_EVSTAT, HFA384x_EVSTAT_ISRX, hfa384x_getreg(), HFA384x_RX_DATA_OFF, HFA384x_RXFID, hfa384x_setreg(), hw_global, reg, hfa384x_rx_frame::status, and hfa384x_rx_frame::time.

{
  uint16_t reg;
  uint16_t rxfid;
  uint16_t 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 */
}
static void prism2_transmit ( struct nic nic,
const char *  d,
unsigned int  t,
unsigned int  s,
const char *  p 
) [static]

Definition at line 661 of file prism2.c.

References hfa384x_tx_frame::address1, hfa384x_tx_frame::address2, hfa384x_tx_frame::address3, hfa384x::bssid, hfa384x_tx_frame::data_len, hfa384x_tx_frame::frame_control, HFA384x_ALLOCFID, HFA384x_CMD_CMDCODE_SET, HFA384x_CMDCODE_ALLOC, HFA384x_CMDCODE_TX, hfa384x_copy_from_bap(), hfa384x_copy_to_bap(), hfa384x_docmd_wait(), HFA384x_DRVR_TXBUF_MAX, HFA384x_EVACK_INFO, HFA384x_EVSTAT_ALLOC, HFA384x_EVSTAT_ISTXEXC, HFA384x_EVSTAT_TX, HFA384x_EVSTAT_TXEXC, hfa384x_getreg(), HFA384x_TX_MACPORT_SET, HFA384x_TX_STRUCTYPE_SET, HFA384x_TX_TXEX_SET, HFA384x_TX_TXOK_SET, HFA384x_TXCOMPLFID, HFA384x_TXSTATUS_ISACKERR, HFA384x_TXSTATUS_ISAGEDERR, HFA384x_TXSTATUS_ISDISCON, HFA384x_TXSTATUS_ISFORMERR, HFA384x_TXSTATUS_ISRETRYERR, hfa384x_wait_for_event(), host2hfa384x_16, htons, hw_global, memcpy(), memset(), printf(), wlan_80211hdr::snap, status, hfa384x_tx_frame::tx_control, wlan_snap::type, WLAN_ADDR_LEN, WLAN_FSTYPE_DATAONLY, WLAN_FTYPE_DATA, wlan_llc_snap, WLAN_SET_FC_FSTYPE, WLAN_SET_FC_FTYPE, and WLAN_SET_FC_TODS.

{
  hfa384x_t *hw = &hw_global;
  hfa384x_tx_frame_t txdesc;
  wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
  uint16_t fid;
  uint16_t 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_t*)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 */
  }
}
static void prism2_disable ( struct nic *nic  __unused) [static]

Definition at line 736 of file prism2.c.

Referenced by prism2_pci_disable(), and prism2_plx_disable().

                                                        {
  /* put the card in its initial state */
}
static void prism2_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 743 of file prism2.c.

{
  switch ( action ) {
  case DISABLE :
    break;
  case ENABLE :
    break;
  case FORCE :
    break;
  }
}
static int prism2_probe ( struct nic nic,
hfa384x_t hw 
) [static]

Definition at line 769 of file prism2.c.

References hfa384x::bssid, DBG, eth_ntoa(), hfa384x_InfFrame::framelen, hardcoded_ssid, hfa384x2host_16, HFA384x_CMD_CMDCODE_SET, HFA384x_CMD_MACPORT_SET, HFA384x_CMDCODE_ENABLE, HFA384x_CMDCODE_INIT, HFA384x_CNFAUTHENTICATION_OPENSYSTEM, hfa384x_copy_from_bap(), hfa384x_docmd_wait(), hfa384x_drvr_getconfig(), hfa384x_drvr_setconfig(), hfa384x_drvr_setconfig16(), HFA384x_EVACK, HFA384x_EVSTAT_INFO, hfa384x_getreg(), HFA384x_INFOFID, HFA384x_INTEN, HFA384x_IT_LINKSTATUS, HFA384x_LINK_CONNECTED, HFA384x_RID_CNFAUTHENTICATION, HFA384x_RID_CNFDESIREDSSID, HFA384x_RID_CNFDESIREDSSID_LEN, HFA384x_RID_CNFMAXDATALEN, HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, HFA384x_RID_CNFPORTTYPE, HFA384x_RID_CURRENTBSSID, HFA384x_RID_TXRATECNTL, hfa384x_setreg(), hfa384x_wait_for_event(), hfa384x_InfFrame::info, hfa384x_InfFrame::infotype, hfa384x_LinkStatus::linkstatus, hfa384x_infodata::linkstatus, MAX_JOIN_INFO_COUNT, memset(), printf(), prism2_operations, ssid, WLAN_BSSID_LEN, and WLAN_DATA_MAXLEN.

Referenced by prism2_pci_probe(), and prism2_plx_probe().

                                                           {
  int result;
  uint16_t tmp16 = 0;
  uint16_t 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_t));
    if ( result ) return 0; /* fail */
    inf.framelen = hfa384x2host_16(inf.framelen);
    /* Retrieve the rest */
    result = hfa384x_copy_from_bap( hw, infofid, sizeof(uint16_t),
                                    &(inf.infotype), inf.framelen * sizeof(uint16_t));
    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;
}

Variable Documentation

const char hardcoded_ssid[] = "" [static]

Definition at line 38 of file prism2.c.

Referenced by prism2_probe().

hfa384x_t hw_global [static]

Definition at line 143 of file prism2.c.

Referenced by prism2_pci_probe(), prism2_plx_probe(), prism2_poll(), and prism2_transmit().

const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 } [static]

Definition at line 157 of file prism2.c.

Referenced by prism2_transmit().

struct nic_operations prism2_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = prism2_poll,
        .transmit       = prism2_transmit,
        .irq            = prism2_irq,
}

Definition at line 758 of file prism2.c.

Referenced by prism2_probe().