📄 am930hw.c
字号:
if ( state & SUTXD_ST_MAX_RETRY ) { WLAN_LOG_DEBUG0(2, "TX err=too many RTS or MPDU retries.\n"); hw->stats.tx_retry++; } } txresult = state & (SUTXD_ST_TXERR | SUTXD_ST_ABRT) ? 1 : 0; hw->used_txbuf--; hw->used_txbuf = wlan_max( 0, hw->used_txbuf); nhandled++; last = reread32(hw, last + TXD_OFF_NEXT); state = read8(hw, last + TXD_OFF_STATE); host = read32(hw, last + TXD_OFF_HOST); } if ( nhandled > 1 ) { WLAN_LOG_DEBUG0(2, "onint_tx handled >1 txdesc\n"); } #if (WLAN_OS == WLAN_LINUX_KERNEL) am930mac_ontxcomplete(hw->mac, txresult); #elif (WLAN_OS == WLAN_LWOS) am930lw_readerkick(); #else #error "No WLAN_OS match!" #endif DBFEXIT;}/*----------------------------------------------------------------* am930hw_onint_scancomplete** ISR helper for f/w generated scan complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_scancomplete( am930hw_t *hw){ DBFENTER; hw->state &= ~AM930HW_SCANNING; if ( hw->scan_callback != NULL ) { /* alert the callback function */ (*hw->scan_callback)(hw->scan_callbackarg); /* check to see if the callback put us back in scan mode */ if ( (hw->state & AM930HW_SCANNING) == 0 ) { /* if not, clear the callback and arg fields */ hw->scan_callback = NULL; hw->scan_callbackarg = NULL; } } DBFEXIT;}/*----------------------------------------------------------------* am930hw_reset** This function performs a reset of the am930 processor, waits* for the firmware to "reboot" and then sends the firmware a * test command.** returns: 0 on success, non-zero on failure----------------------------------------------------------------*/UINT32 am930hw_reset( am930hw_t *hw ){ UINT32 result = 0; UINT32 init_retry = 0; UINT8 reg; UINT32 count; UINT32 i; UINT8 selftest; am930hw_cmd_result_t cmd_result; DBFENTER; do { /* Lets go through a reset cycle */ /* Set the CORESET bit of GCR and wait 10 us */ outb( BIT6, GCR(hw) ); udelay(10); /* Set the SWRESET bit of GCR and wait 10 us */ outb( BIT7, GCR(hw) ); udelay(10); /* Clear the GCR and wait 10 us */ outb( 0, GCR(hw) ); udelay(10); /* Set the CORESET bit of GCR and wait 10 us */ outb( BIT6, GCR(hw) ); udelay(10); /* Clear the ctl memory regions (f/w should do this, but doesn't) */ for ( i = SU_OFF_LAST_TXDESC; i < SU_OFF_BUFFER; i++) { write8(hw, i, 0); } /* Clear the GCR and wait 10 us */ outb( 0, GCR(hw) ); udelay(10); /* Before doing the ALE test, do an initial read of BSS */ reg = inb( BSS(hw) ); count = 0; do { udelay(50); /* Write zero to BSS and wait 10us */ outb( 0, BSS(hw) ); udelay(50); /* Read BSS and check the ALE Test Read bit */ reg = inb( BSS(hw) ); } while ( reg != 0x80 && ++count < 20 ); /* Now wait for 2 seconds */#if (WLAN_OS == WLAN_LINUX_KERNEL) schedule_timeout( 2*HZ ); /* Now, check the selftest status */ count = jiffies + (1 * HZ); while ( ((selftest = read8(hw, hw->cs + CS_OFF_SELF_TEST)) < 0xf0) && (jiffies < count) ) { }#elif (WLAN_OS == WLAN_LWOS) count = 200; while( count-- ) { udelay(1000); } /* Now, check the selftest status */ count = 500; while ( ((selftest = read8(hw, hw->cs + CS_OFF_SELF_TEST)) < 0xf0) && (count--) ) { udelay(10) }#else #error "No WLAN_OS match!"#endif if ( selftest != 0xFF ) { WLAN_LOG_WARNING1("Card self-test failed, code=0x%02x\n", selftest); result = 1; } /* Issue the test interface command */ cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_TEST_NOP, NULL, 0); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_WARNING1( "Firmware Test Interface failed, status=0x%x\n", cmd_result.fw_status); result = 1; } init_retry++; } while ( init_retry < 10 && ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) ); /* if the reset failed, log it */ if ( init_retry >= 10 && ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) ) { WLAN_LOG_ERROR1( "All retries of reset and Test Interface failed status=0x%x\n", cmd_result.fw_status); result = 1; } return result;} /*----------------------------------------------------------------* am930hw_rx_enable** Helper function to send the sutro ENABLE_RX command. ** returns: AM930HW_CMD_SUCCESS or* AM930HW_CMD_INITTXFAILED----------------------------------------------------------------*/UINT32 am930hw_rx_enable(am930hw_t *hw){ UINT32 result = AM930HW_CMD_SUCCESS; sucmd_en_rcvr_t cmd; am930hw_cmd_result_t cmd_result; DBFENTER; cmd.data_desc = host2amd32(0);/* TODO: handle the setting up of the pspoll descriptor */ cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_EN_RCVR, &cmd, -sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_ERROR0("init_rx failed!\n"); result = AM930HW_CMD_INITRXFAILED; } else { hw->rx_head = amd2host32(cmd.data_desc); } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_resumefromscan** Public method used to tell the MAC to stop scanning. ** returns: AM930HW_CMD_SUCCESS----------------------------------------------------------------*/UINT32 am930hw_resumefromscan( am930hw_t *hw){ UINT32 result = AM930HW_SUCCESS; am930hw_cmd_result_t cmd_result; DBFENTER; cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_RESUME, NULL, 0); DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_scan** Public method used to tell the MAC to scan. In this case it * is the hardware element of the MAC that's being told what to* do.** The cntl argument has two purposes, it specifies* what kind of BSS to scan for (BSSType)and what kind of scan to* perform (active or passive).* The values of the bit fields are:* AM930HWSCAN_ACTIVE* AM930HWSCAN_PASSIVE* AM930HWSCAN_IBSS* AM930HWSCAN_ESS* note 1: that IBSS and ESS can be used together.* note 2: the units for the duration field are Kus.** returns: AM930HW_CMD_SUCCESS or* AM930HW_CMD_INITTXFAILED----------------------------------------------------------------*/UINT32 am930hw_scan( am930hw_t *hw, UINT32 cntl, UINT8 *bssid, UINT32 ch, UINT32 duration, wlan_ie_ssid_t *ssid, am930hw_scan_callback_t cb, void *callback_arg){ UINT32 result = AM930HW_SUCCESS; sucmd_scan_t cmd; am930hw_cmd_result_t cmd_result; su_mib_mac_mgmt_t mib; DBFENTER; /* Get the mac_mgmt mib */ if ( am930hw_mibget( hw, SUMIB_MGMT, 0, sizeof(mib), &mib) != AM930HW_CMD_SUCCESS ) { WLAN_LOG_WARNING0("MIB_MGMT read failed!\n"); result = AM930HW_FAILURE; } else { /* set the scan mode and duration (if passive) */ if ( cntl & AM930HWSCAN_PASSIVE ) { mib.scan_mode = SUMIB_SCANMODE_PASSIVE; mib.passive_scan_duration = host2amd16(duration); } else /* ACTIVE */ { mib.scan_mode = SUMIB_SCANMODE_ACTIVE; } if ( am930hw_mibset( hw, SUMIB_MGMT, 0, sizeof(mib), &mib) != AM930HW_CMD_SUCCESS ) { WLAN_LOG_WARNING0("MIB write failed!\n"); result = AM930HW_FAILURE; } else { /* Set the desired ssid */ am930hw_mibsetitem( hw, MAC_DESIRED_ESSID, ssid, MI_SZ(MAC_DESIRED_ESSID)); /* set the callback */ hw->scan_callback = cb; hw->scan_callbackarg = callback_arg; /* send the scan command */ memset( &cmd, 0, sizeof(cmd)); cmd.duration = host2amd16(duration); cmd.set_or_ch = ch; hw->state |= AM930HW_SCANNING; hw->scan_ch = ch; cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_SCAN, &cmd, sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { hw->state &= ~AM930HW_SCANNING; hw->scan_ch = 0; WLAN_LOG_WARNING1("scan command failed! ch=%ld\n", ch); result = AM930HW_FAILURE; } } } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_stateset** Sets the driver state field of the f/w control/status block.** returns: Prior value of the state field----------------------------------------------------------------*/UINT8 am930hw_stateset( am930hw_t *hw, UINT8 state){ UINT8 result; DBFENTER; result = read8( hw, hw->cs + CS_OFF_DRIVER_STATE); write8( hw, hw->cs + CS_OFF_DRIVER_STATE, state); DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_stateget** Gets the driver state field of the f/w control/status block.** returns: Prior value of the state field----------------------------------------------------------------*/UINT8 am930hw_stateget( am930hw_t *hw){ UINT8 result; DBFENTER; result = read8( hw, hw->cs + CS_OFF_DRIVER_STATE); DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_mibget** I/F function used by mac and mgr to retrieve elements of or an* entire mib section. Also used by the mibgetitem function.** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibget( am930hw_t *hw, UINT32 mibsec, UINT32 offset, UINT32 len, void *buf){ UINT32 result = AM930HW_SUCCESS; sucmd_get_mib_var_t cmd; am930hw_cmd_result_t cmd_result; DBFENTER; memset( &cmd, 0, sizeof(cmd)); cmd.type = mibsec; cmd.size = len; cmd.index = offset; cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_GET_MIB_VAR, &cmd, -sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_DEBUG3(1, "GetMIB failed! mibsec=0x%02lx, offset=%lu, len=%lu\n", mibsec, offset, len); result = AM930HW_FAILURE; } else { /* TODO: keep an eye on the where the f/w copies the result to */ memcpy( buf, cmd.data, len); } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_mibgetitem** I/F function used by mac and mgr to retrieve the values of * particular MIB elements.** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibgetitem( am930hw_t *hw, UINT32 itemid, void *buf, UINT32 len){ UINT32 result = AM930HW_SUCCESS; DBFENTER; result = am930hw_mibget( hw, MI_SEC(itemid), MI_OFF(itemid), MI_SZ(itemid), buf); DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_mibset** I/F function used by mac and mgr to set the values of MIB* elements.** TODO: for now this function operates on entire sutro MIB structures.* TODO: need to make the function work on individual elements** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibset( am930hw_t *hw, UINT32 mibsec, UINT32 offset, UINT32 len, void *buf){ UINT32 result = AM930HW_SUCCESS; sucmd_set_mib_var_t cmd; am930hw_cmd_result_t cmd_result; DBFENTER; memset( &cmd, 0, sizeof(cmd)); cmd.type = mibsec; cmd.size = len; cmd.index = offset; memcpy( cmd.data, buf, len); cmd_result = am930hw_fw_cmd( hw, SUCMD_CMD_SET_MIB_VAR, &cmd, sizeof(cmd)); if ( cmd_result.fw_status != SUCMD_STAT_CMPLT || cmd_result.drvr_status != 0 ) { WLAN_LOG_WARNING0("SetMIB failed!\n"); result = AM930HW_FAILURE; } DBFEXIT; return result;}/*----------------------------------------------------------------* am930hw_mibsetitem** I/F function used by mac and mgr to set the values of MIB* items.** returns: AM930HW_SUCCESS or* AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_mibsetitem( am930hw_t *hw, UINT32 itemid, void *buf, UINT32 len){ UINT32 result = AM930HW_SUCCESS; DBFENTER; result = am930hw_mibset( hw, MI_SEC(itemid), MI_OFF(itemid), MI_SZ(itemid), buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -