📄 am930hw.c
字号:
/* Clear the int bit of the hw->state */ hw->state &= ~AM930HW_INTOCURRED; } else { /* save the int_mask for future restoration */ int_mask1 = read8( hw, hw->cs + CS_OFF_INT_MASK); int_mask2 = read8( hw, hw->cs + CS_OFF_INT_MASK2); write8(hw, hw->cs + CS_OFF_INT_MASK, 0xff); write8(hw, hw->cs + CS_OFF_INT_MASK2, 0xff); int_status1 = read8(hw, hw->cs + CS_OFF_INT_STATUS); int_status2 = read8(hw, hw->cs + CS_OFF_INT_STATUS2); write8(hw, hw->cs + CS_OFF_INT_STATUS, 0); write8(hw, hw->cs + CS_OFF_INT_STATUS2, 0); am930hw_unlockint(hw); WLAN_LOG_DEBUG2(4,"Int mask=0x%02x, status=0x%02x\n", int_mask1, int_status1); /* Handle various int sources */ if ( int_status1 == 0 ) { WLAN_LOG_DEBUG0(1,"in ISR, int_status1 == 0\n"); } do { handled++; if ( SUCS_INT_IS_RX(int_status1) ) { #if (WLAN_OS == WLAN_LWOS) LED_Blink( WIRELESS_DATA_LED, 1); #endif am930hw_onint_rx(hw); } if ( SUCS_INT_IS_TX(int_status1) ) { #if (WLAN_OS == WLAN_LWOS) LED_Blink( WIRELESS_DATA_LED, 1); #endif am930hw_onint_tx(hw); } if ( SUCS_INT_IS_SCANCMPLT(int_status1) ) { am930hw_onint_scancomplete(hw); } if ( SUCS_INT_IS_CMD(int_status1) ) { am930hw_onint_cmdcomplete(hw); } /* Check the int status again, to see if more int events */ /* have occurred */ if ( am930hw_lockint(hw) != 0 ) { WLAN_LOG_DEBUG0(2,"Unable to lockout f/w, 2nd time\n"); int_status1 = 0; } else { int_status1 = read8(hw, hw->cs + CS_OFF_INT_STATUS); int_status2 = read8(hw, hw->cs + CS_OFF_INT_STATUS2); if ( int_status1 != 0 ) /* are we handling again? */ { write8(hw, hw->cs + CS_OFF_INT_STATUS, 0); write8(hw, hw->cs + CS_OFF_INT_STATUS2, 0); } else { /* reset the int_mask to the setting it had on ISR entry */ write8(hw, hw->cs + CS_OFF_INT_MASK, int_mask1); write8(hw, hw->cs + CS_OFF_INT_MASK2, int_mask2); } am930hw_unlockint(hw); } } while ( int_status1 != 0 ); if ( handled > 1 ) { WLAN_LOG_DEBUG1(3, "hw_ISR: handled=%d\n", handled); } /* Clear the ECWAIT bit of GCR (by setting...wierd) */ gcr = inb_p( GCR(hw)); gcr |= BIT3; outb_p( gcr, GCR(hw)); /* Clear the int bit of the hw->state */ hw->state &= ~AM930HW_INTOCURRED; } /* endif lockint */ } /* endif !overlapped */ } /* hw OK, card in slot */ else { WLAN_LOG_WARNING0("ISR called when hw is NULL, not CONFIG or " "no card in slot, future ints may be lost!\n"); } DBFEXIT; return;}/*----------------------------------------------------------------* am930hw_joinbss** I/F function used by mac and mgr to join a specific bss. The* only nod here to the sutro implementation is the sutro_ref_time* argument used by the sutro to update it's internal timers.** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_joinbss( am930hw_t *hw, UINT32 ch, UINT32 newBSS, UINT8 *bssid, wlan_ie_ssid_t *ssid, UINT32 bcn_int, wlan_bss_ts_t ts, UINT32 sutro_ref_time ){ UINT32 result = AM930HW_SUCCESS; su_mib_mac_mgmt_t mm_mib; DBFENTER; /* retrieve the mib */ if ( am930hw_mibget(hw, SUMIB_MGMT, 0, sizeof(mm_mib), &mm_mib) != AM930HW_SUCCESS ) { result = AM930HW_FAILURE; } else { /* set the bssid */ memcpy( mm_mib.current_bssid, bssid, WLAN_ADDR_LEN ); /* set the ssid */ memcpy( mm_mib.current_essid, ssid, ssid->len + 2); /* set the beaconrate */ mm_mib.beacon_period = host2amd16(bcn_int); /* save the mib */ if ( am930hw_mibset(hw, SUMIB_MGMT, 0, sizeof(mm_mib), &mm_mib) != AM930HW_SUCCESS ) { result = AM930HW_FAILURE; } else { /* send the sync command */ if ( am930hw_sync( hw, ch, newBSS, (newBSS == 0) ? ts : NULL, sutro_ref_time ) != AM930HW_CMD_SUCCESS ) { result = AM930HW_FAILURE; } else { /* Set the driver state */ if (hw->mac->mode == AM930_MACMODE_ESS_AP) { write8( hw, hw->cs + CS_OFF_DRIVER_STATE, SUCS_DS_AP_NO_ASSOC); } } } } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_onint_cmdcomplete** ISR helper for f/w generated command complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_cmdcomplete( am930hw_t *hw ){ DBFENTER; WLAN_LOG_DEBUG1(3,"cmd complete int, last_cmd= 0x%x\n", hw->last_cmd); hw->last_cmd = 0; DBFEXIT;}/*----------------------------------------------------------------* am930hw_onint_rx** ISR helper for f/w generated rx complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_rx( am930hw_t *hw ){ UINT8 old_state; UINT32 old_head; UINT32 next; UINT32 len; UINT32 data_off; UINT8 state; am930rxstats_t *stats; wlan_pb_t *pb; UINT nhandled = 0; UINT frm_rxd = 0; UINT payloadlen; DBFENTER; /* read the state and next fields from the old head */ state = read8(hw, hw->rx_head + RXD_OFF_STATE); next = am930hw_read_rxnext(hw); while ( !SURXD_ST_IS_FWOWN(state) && SURXD_ST_IS_CONSUMED(state) && !SURXD_ISLAST(next) && ((next&0x0000ffffL) >= hw->rx_base && (next&0x0000ffffL) < (hw->rx_base+hw->rx_len)) ) { /* we've got a valid next ptr, it's time to move on */ old_head = hw->rx_head; old_state = state; nhandled++; hw->rx_head = next & 0x0000ffffL; state = read8( hw, hw->rx_head + RXD_OFF_STATE); /* make sure we own the new descriptor */ if ( SURXD_ST_IS_FWOWN(state) ) { /* we've been handed a desc that's still owned by the f/w */ /* set the head back to the old one, and stop the loop */ hw->rx_head = old_head; break; } else { /* we have a new, valid descriptor...process it */ /* first, get rid of the old one */ old_state |= SURXD_ST_FWOWN; write8( hw, old_head + RXD_OFF_STATE, old_state); if ( SURXD_ST_IS_CONSUMED(state) ) { /* it's a dummy, do nothing */ WLAN_LOG_DEBUG0(1, "We got a dummy!\n"); } if ( SURXD_ST_IS_RXERR(state) ) { if ( SURXD_ST_IS_CRC_ERR(state) ) { WLAN_LOG_WARNING0( "RX int, desc err=CRC\n"); hw->stats.rx_crcerr++; } if ( SURXD_ST_IS_BUF_OFLOW(state) ) { WLAN_LOG_WARNING0( "RX int, desc err=BUF_OFLOW\n"); hw->stats.rx_buf_oflow++; } state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); am930mac_rxframe_err(hw->mac); } else if ( !SURXD_ST_IS_CONSUMED(state) ) { /* hey! we've actually got something! */ /* copy the frame to host memory and pass it up */ len = read16(hw, hw->rx_head + RXD_OFF_LEN); /* Make a packet buffer */ pb = am930shim_pballoc(); if ( pb == NULL ) { WLAN_LOG_DEBUG0(2,"pballoc failed.\n"); state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); } else { am930shim_pballoc_p80211(pb, len); if ( pb->p80211hostbuf == NULL ) { WLAN_LOG_DEBUG0(2,"pballoc_p80211 failed!\n"); state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); } else { data_off = read32(hw, hw->rx_head + RXD_OFF_START_FRAME); data_off &= 0x0000ffff; payloadlen = len; readcard(hw, data_off, pb->p80211buf, WLAN_HDR_A3_LEN); data_off += WLAN_HDR_A3_LEN; payloadlen -= (WLAN_HDR_A3_LEN + WLAN_CRC_LEN); if ( WLAN_GET_FC_ISWEP(ieee2host16(pb->p80211_hdr->a3.fc))) { /* read the encrypted frame into the pb fields */ payloadlen -= (WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN); /* wep iv */ readcard(hw, data_off, &(pb->wep_iv), WLAN_WEP_IV_LEN); data_off += WLAN_WEP_IV_LEN; /* wep icv */ readcard(hw, data_off + payloadlen, &(pb->wep_icv), WLAN_WEP_ICV_LEN); /* payload */ readcard(hw, data_off, pb->p80211buf + WLAN_HDR_A3_LEN, payloadlen); /* wlan crc */ readcard(hw, data_off + payloadlen + WLAN_WEP_ICV_LEN, pb->p80211buf + WLAN_HDR_A3_LEN + payloadlen, WLAN_CRC_LEN ); /* adjust the pb len fields and mark as encrypted */ pb->p80211frmlen = WLAN_HDR_A3_LEN + payloadlen + WLAN_CRC_LEN; pb->p80211_payloadlen = payloadlen; pb->wep_iscrypt = 1; } else { readcard( hw, data_off, pb->p80211buf + WLAN_HDR_A3_LEN, len - WLAN_HDR_A3_LEN); } stats = (am930rxstats_t*)kmalloc(sizeof(am930rxstats_t), GFP_ATOMIC); if ( stats == NULL ) { WLAN_LOG_DEBUG0(2,"rxstats alloc_p80211 failed!\n"); state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); } else { stats->rssi = read8(hw, hw->rx_head + RXD_OFF_RSSI); stats->ch = read8(hw, hw->rx_head + RXD_OFF_INDEX_OR_CH); stats->local_time = read32(hw, hw->rx_head + RXD_OFF_LOCAL_TIME); stats->rate = read8(hw, hw->rx_head + RXD_OFF_RATE); state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); WLAN_HEX_DUMP(3,"hwrxf",pb->p80211buf,pb->p80211frmlen); am930mac_rxenqueue( hw->mac, pb, stats); frm_rxd = 1; #ifdef WLAN_INCLUDE_SNIF if ( hw->mac->snifflags & SNIFFLAG_SNIFRX ) { am930mac_snifframe(hw->mac, pb, stats); } #endif } } } } } /* read the state and next fields from the head */ state = read8(hw, hw->rx_head + RXD_OFF_STATE); next = am930hw_read_rxnext(hw); } if ( nhandled > 1 ) { WLAN_LOG_DEBUG1(2, "onint_rx handled %d\n", nhandled); } #if (WLAN_OS == WLAN_LINUX_KERNEL) if ( frm_rxd ) { am930mac_rxframe(hw->mac);/* am930hw_txkick(hw); */ } #endif DBFEXIT;}/*----------------------------------------------------------------* am930hw_read_rxnext** Repeated read of the rxnext field to make _sure_ we have real* data. Very paranoid.** returns: nothing----------------------------------------------------------------*/static UINT32 am930hw_read_rxnext(am930hw_t *hw){ UINT32 result = 0; UINT32 old = 0; result = read32( hw, hw->rx_head + RXD_OFF_NEXT); while ( result != old ) { old = result; result = read32( hw, hw->rx_head + RXD_OFF_NEXT); if ( old != result ) { WLAN_LOG_DEBUG1(1, "reread of rxnext:0x%04lx didn't match!\n", hw->rx_head + RXD_OFF_NEXT); } } return result;}/*----------------------------------------------------------------* am930hw_onint_tx** ISR helper for f/w generated tx complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_tx( am930hw_t *hw ){ UINT32 last; UINT32 back; UINT8 state; UINT32 host; UINT32 txresult = 0; UINT32 nhandled = 0; DBFENTER; last = reread32(hw, hw->txcmplt + TXCMPLT_OFF_DATA); state = read8(hw, last + TXD_OFF_STATE); host = read32(hw, last + TXD_OFF_HOST); /* backwalk the queue to find last unserviced desc */ back = last; while ( !(state & SUTXD_ST_FWOWN) && host != 0 ) { last = back; write32(hw, back + TXD_OFF_HOST, 0); back = reread32(hw, back + TXD_OFF_PREV); state = read8(hw, back + TXD_OFF_STATE); host = read32(hw, back + TXD_OFF_HOST); } state = read8(hw, last + TXD_OFF_STATE); host = read32(hw, last + TXD_OFF_HOST); while ( !(state & SUTXD_ST_FWOWN) && (state & SUTXD_ST_DONE) ) { write8(hw, last + TXD_OFF_STATE, 0); write32(hw, last + TXD_OFF_HOST, 0); if ( state & SUTXD_ST_TXERR ) { WLAN_LOG_DEBUG0(2, "TX err:\n"); if ( state & SUTXD_ST_REJECTED ) { WLAN_LOG_DEBUG0(2, "TX err=frame rejected by f/w.\n"); hw->stats.tx_rejected++; } if ( state & SUTXD_ST_MSDU_TMOUT ) { WLAN_LOG_DEBUG0(2, "TX err=msdu timeout.\n"); hw->stats.tx_tmout++; } if ( state & SUTXD_ST_ABRT ) { WLAN_LOG_DEBUG0(2, "TX err=frame aborted, after >1 tx attempt.\n"); } if ( state & SUTXD_ST_ABRT_NOTX ) { WLAN_LOG_DEBUG0(2, "TX err=frame aborted, no tx attempts.\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -