?? am930hw.c
字號:
/* 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 */ DBPRT( DBFWINT, "We got a dummy!\n"); } else if ( SURXD_ST_IS_RXERR(state) ) { /* rx error, note it and move on... */ DBPRT( DBFWINT, "RX int, desc err, state=0x%x\n", state); if ( SURXD_ST_IS_CRC_ERR(state) ) hw->stats.rx_crcerr++; if ( SURXD_ST_IS_BUF_OFLOW(state) ) hw->stats.rx_buf_oflow++; state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); am930mac_rxframe_err(hw->mac); } else { /* 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); frm = am930mac_mk_rxfrmbuf( hw->mac, len); if ( frm == NULL ) { printk(KERN_DEBUG"mac_mk_rxfrmbuf 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; readcard(hw, data_off, frm->data, len); /* print new rx_desc */ #ifdef DBMSG_ENABLED if ( (dbmask & FILEBIT) && (dbmask & DBRXDATA)) { int i; printk(KERN_DEBUG"rxframe: "); for ( i = 0; i < len; i++) { printk("%02x ", frm->data[i]); } printk("\n"); } #endif frm->len = len; frm->rssi = read8(hw, hw->rx_head + RXD_OFF_RSSI); /* start mod: tld */ rssi_tld = (int) frm->rssi; /* end mod: tld */ frm->ch = read8(hw, hw->rx_head + RXD_OFF_INDEX_OR_CH); frm->local_time = read32(hw, hw->rx_head + RXD_OFF_LOCAL_TIME); frm->rate = read8(hw, hw->rx_head + RXD_OFF_RATE); state |= SURXD_ST_CONSUMED; write8(hw, hw->rx_head+RXD_OFF_STATE, state); am930mac_rxframe( hw->mac, frm ); } } } /* read the state and next fields from the head */ state = read8(hw, hw->rx_head + RXD_OFF_STATE); next = am930hw_read_rxnext(hw); } DBPRT( DBFWINT, "RXint done\n") }/* start mod: tld *//*---------------------------------------------------------------- * am930hw_rssi_tld * * returns: rssi value as int ----------------------------------------------------------------*/UINT32 am930hw_rssi_tld(int tld_v) { return( rssi_tld );}/* end mod: tld *//*----------------------------------------------------------------* 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 ) { DBPRT( DBFWINT, "two reads of rxnext didn't match!\n"); } } return result;}/*----------------------------------------------------------------* am930hw_onint_tx** ISR helper for f/w generated scan complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_tx( am930hw_t *hw ){ UINT32 last; UINT8 state; UINT32 txresult = 0; DBPRT( DBFWINT, "TX Complete interrupt!\n") last = read32(hw, hw->txcmplt + TXCMPLT_OFF_DATA); state = read8(hw, last + TXD_OFF_STATE); if ( state & SUTXD_ST_TXERR ) { DBPRT( DBFWINT, "Frame TX err detected\n"); if ( state & SUTXD_ST_REJECTED ) { DBPRT( DBFWCMD, "TX frame rejected by f/w\n"); hw->stats.tx_rejected++; } if ( state & SUTXD_ST_MSDU_TMOUT ) { hw->stats.tx_tmout++; } if ( state & SUTXD_ST_ABRT ) {/* hw->stats.tx_fifo_uflow++; */ } if ( state & SUTXD_ST_ABRT_NOTX ) {/* hw->stats.tx_retry++; */ } if ( state & SUTXD_ST_MAX_RETRY ) { hw->stats.tx_retry++; } } txresult = state & (SUTXD_ST_TXERR | SUTXD_ST_ABRT) ? 1 : 0; am930mac_ontxcomplete(hw->mac, txresult);/*#ifdef DBMSG_ENABLED if ( (dbmask & FILEBIT) && (dbmask & DBTXDATA)) { am930tx_desc_t desc; readcard(hw, last, &desc, sizeof(desc)); am930hw_dbprintTXdesc(&desc); }#endif*/ DBPRT( DBFWINT, "TX int done\n")}/*----------------------------------------------------------------* am930hw_onint_scancomplete** ISR helper for f/w generated scan complete interrupts** returns: nothing----------------------------------------------------------------*/void am930hw_onint_scancomplete( am930hw_t *hw){ DBPRT( DBFWINT, "Scan Complete interrupt! ch = %d\n", hw->scan_ch) 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; } }}/*----------------------------------------------------------------* 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 */ /* current->timeout = jiffies + (2 * HZ); current->state = TASK_INTERRUPTIBLE; schedule(); current->timeout = 0; */ schedule_timeout( 2*HZ ); /* Now, check the selftest status */ while ( (selftest = read8(hw, hw->cs + CS_OFF_SELF_TEST)) < 0xf0) { } if ( selftest != 0xFF ) { printk(KERN_DEBUG"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 ) { DBPRT( DBINIT | DBFWCMD, "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 ) ) { DBPRT( DBINIT | DBFWCMD, "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 = 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 ) { printk(KERN_DEBUG "init_rx failed!\n"); result = AM930HW_CMD_INITRXFAILED; } else { hw->rx_head = cmd.data_desc; } 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, UINT48 bssid, UINT32 ch, UINT32 duration, 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 ) { DBPRT( DBFWCMD, "Initial mib 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 = duration; } else /* ACTIVE */ { mib.scan_mode = SUMIB_SCANMODE_ACTIVE; } if ( am930hw_mibset( hw, SUMIB_MGMT, 0, sizeof(mib), &mib) != AM930HW_CMD_SUCCESS ) { DBPRT( DBFWCMD, "MIB write failed!\n"); result = AM930HW_FAILURE; } else { /* set the callback */ hw->scan_callback = cb; hw->scan_callbackarg = callback_arg; /* send the scan command */ memset( &cmd, 0, sizeof(cmd)); cmd.duration = duration; cmd.set_or_ch = ch; /* cmd.pattern = 5; cmd.index = 1; */ 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; printk( KERN_DEBUG "scan command failed! ch=%ld\n", ch); result = AM930HW_FAILURE; } } } 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 ) { DBPRT( DBFWCMD, "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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -