Exemplo n.º 1
0
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int prism2_poll(struct nic *nic, int retrieve)
{
  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 */
}
Exemplo n.º 2
0
/*
 * 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_t id, uint16_t offset)
{
  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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
/*
 * 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_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2)
{
  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);
}
Exemplo n.º 5
0
/*
 * 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_t event_mask, uint16_t event_ack, int wait, int timeout, const char *descr)
{
  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;
}
Exemplo n.º 6
0
/**************************************************************************
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_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 */
  }
}
Exemplo n.º 7
0
/*
 * Noswap versions
 * Etherboot is i386 only, so swap and noswap are the same...
 */
static inline uint16_t hfa384x_getreg_noswap( hfa384x_t *hw, unsigned int reg )
{
  return hfa384x_getreg ( hw, reg );
}
Exemplo n.º 8
0
/* 
 * 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 );
}