📄 ar5211.c
字号:
AR5K_AR5211_DCU_MISC_BCN_ENABLE); AR5K_REG_WRITE(AR5K_AR5211_QCU_RDYTIMECFG(queue), ((AR5K_TUNE_BEACON_INTERVAL - (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | AR5K_AR5211_QCU_RDYTIMECFG_ENABLE); break; case HAL_TX_QUEUE_CAB: AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), AR5K_AR5211_QCU_MISC_FRSHED_DBA_GT | AR5K_AR5211_QCU_MISC_CBREXP | AR5K_AR5211_QCU_MISC_CBREXP_BCN); AR5K_REG_ENABLE_BITS(AR5K_AR5211_DCU_MISC(queue), (AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL)); break; case HAL_TX_QUEUE_PSPOLL: AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), AR5K_AR5211_QCU_MISC_CBREXP); break; case HAL_TX_QUEUE_DATA: default: break; } /* * Enable tx queue in the secondary interrupt mask registers */ AR5K_REG_WRITE(AR5K_AR5211_SIMR0, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR0_QCU_TXOK) | AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR0_QCU_TXDESC)); AR5K_REG_WRITE(AR5K_AR5211_SIMR1, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR1_QCU_TXERR)); AR5K_REG_WRITE(AR5K_AR5211_SIMR2, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR2_QCU_TXURN)); return (AH_TRUE);}u_int32_tar5k_ar5211_get_tx_buf(struct ath_hal *hal, u_int queue){ AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* * Get the transmit queue descriptor pointer from the selected queue */ return (AR5K_REG_READ(AR5K_AR5211_QCU_TXDP(queue)));}HAL_BOOLar5k_ar5211_put_tx_buf(struct ath_hal *hal, u_int queue, u_int32_t phys_addr){ AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* * Set the transmit queue descriptor pointer for the selected queue * (this won't work if the queue is still active) */ if (AR5K_REG_READ_Q(AR5K_AR5211_QCU_TXE, queue)) return (AH_FALSE); AR5K_REG_WRITE(AR5K_AR5211_QCU_TXDP(queue), phys_addr); return (AH_TRUE);}u_int32_t /*Code from roofnet*/ar5k_ar5211_num_tx_pending(struct ath_hal *hal, u_int queue) { AR5K_TRACE; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); return (AR5K_AR5211_QCU_STS(queue) & AR5K_AR5211_QCU_STS_FRMPENDCNT);}HAL_BOOLar5k_ar5211_tx_start(struct ath_hal *hal, u_int queue){ AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* Return if queue is disabled */ if (AR5K_REG_READ_Q(AR5K_AR5211_QCU_TXD, queue)) return (AH_FALSE); /* Start queue */ AR5K_REG_WRITE_Q(AR5K_AR5211_QCU_TXE, queue); return (AH_TRUE);}HAL_BOOL /*Fixed delay*/ar5k_ar5211_stop_tx_dma(struct ath_hal *hal, u_int queue){ int i = 100, pending; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* * Schedule TX disable and wait until queue is empty */ AR5K_REG_WRITE_Q(AR5K_AR5211_QCU_TXD, queue); do { pending = AR5K_REG_READ(AR5K_AR5211_QCU_STS(queue)) & AR5K_AR5211_QCU_STS_FRMPENDCNT; AR5K_DELAY(100); } while (--i && pending); /* Clear register */ AR5K_REG_WRITE(AR5K_AR5211_QCU_TXD, 0); return (AH_TRUE);}HAL_BOOL /*O.K. - Initialize tx_desc and clear ds_hw */ar5k_ar5211_setup_tx_desc(struct ath_hal *hal, struct ath_desc *desc, u_int packet_length, u_int header_length, HAL_PKT_TYPE type, u_int tx_power, u_int tx_rate0, u_int tx_tries0, u_int key_index, u_int antenna_mode, u_int flags, u_int rtscts_rate, u_int rtscts_duration){ struct ar5k_ar5211_tx_desc *tx_desc; tx_desc = (struct ar5k_ar5211_tx_desc*)&desc->ds_ctl0; /*Clear ds_hw*/ bzero(desc->ds_hw, sizeof(desc->ds_hw)); /* * Validate input */ if (tx_tries0 == 0) return (AH_FALSE); /* Initialize status descriptor */ tx_desc->tx_control_0 = 0; tx_desc->tx_control_1 = 0; /* Setup status descriptor */ if ((tx_desc->tx_control_0 = (packet_length & AR5K_AR5211_DESC_TX_CTL0_FRAME_LEN)) != packet_length) return (AH_FALSE); tx_desc->tx_control_0 |= AR5K_REG_SM(tx_rate0, AR5K_AR5211_DESC_TX_CTL0_XMIT_RATE) | AR5K_REG_SM(antenna_mode, AR5K_AR5211_DESC_TX_CTL0_ANT_MODE_XMIT); tx_desc->tx_control_1 = AR5K_REG_SM(type, AR5K_AR5211_DESC_TX_CTL1_FRAME_TYPE);#define _TX_FLAGS(_c, _flag) \ if (flags & HAL_TXDESC_##_flag) \ tx_desc->tx_control_##_c |= \ AR5K_AR5211_DESC_TX_CTL##_c##_##_flag _TX_FLAGS(0, CLRDMASK); _TX_FLAGS(0, VEOL); _TX_FLAGS(0, INTREQ); _TX_FLAGS(0, RTSENA); _TX_FLAGS(1, NOACK);#undef _TX_FLAGS /* * WEP crap */ if (key_index != HAL_TXKEYIX_INVALID) { tx_desc->tx_control_0 |= AR5K_AR5211_DESC_TX_CTL0_ENCRYPT_KEY_VALID; tx_desc->tx_control_1 |= AR5K_REG_SM(key_index, AR5K_AR5211_DESC_TX_CTL1_ENCRYPT_KEY_INDEX); } return (AH_TRUE);}HAL_BOOL/*Added an argument *last_desc -need revision -don't clear descriptor here*/ar5k_ar5211_fill_tx_desc(struct ath_hal *hal, struct ath_desc *desc, u_int segment_length, HAL_BOOL first_segment, HAL_BOOL last_segment, const struct ath_desc *last_desc){ struct ar5k_ar5211_tx_desc *tx_desc; tx_desc = (struct ar5k_ar5211_tx_desc*)&desc->ds_ctl0; /* Clear status descriptor */// bzero(desc->ds_hw, sizeof(desc->ds_hw)); /* Validate segment length and initialize the descriptor */ if ((tx_desc->tx_control_1 = (segment_length & AR5K_AR5211_DESC_TX_CTL1_BUF_LEN)) != segment_length) return (AH_FALSE); if (first_segment != AH_TRUE) tx_desc->tx_control_0 &= ~AR5K_AR5211_DESC_TX_CTL0_FRAME_LEN; if (last_segment != AH_TRUE) tx_desc->tx_control_1 |= AR5K_AR5211_DESC_TX_CTL1_MORE; return (AH_TRUE);}HAL_BOOLar5k_ar5211_setup_xtx_desc(struct ath_hal *hal, struct ath_desc *desc, u_int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, u_int tx_rate3, u_int tx_tries3){ return (AH_FALSE);}HAL_STATUSar5k_ar5211_proc_tx_desc(struct ath_hal *hal, struct ath_desc *desc){ struct ar5k_ar5211_tx_status *tx_status; struct ar5k_ar5211_tx_desc *tx_desc; tx_desc = (struct ar5k_ar5211_tx_desc*)&desc->ds_ctl0; tx_status = (struct ar5k_ar5211_tx_status*)&desc->ds_hw[0]; /* No frame has been send or error */ if ((tx_status->tx_status_1 & AR5K_AR5211_DESC_TX_STATUS1_DONE) == 0) return (HAL_EINPROGRESS); /* * Get descriptor status */ desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, AR5K_AR5211_DESC_TX_STATUS0_SEND_TIMESTAMP); desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_AR5211_DESC_TX_STATUS0_RTS_FAIL_COUNT); desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_AR5211_DESC_TX_STATUS0_DATA_FAIL_COUNT); desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, AR5K_AR5211_DESC_TX_STATUS1_SEQ_NUM); desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, AR5K_AR5211_DESC_TX_STATUS1_ACK_SIG_STRENGTH); desc->ds_us.tx.ts_antenna = 1; desc->ds_us.tx.ts_status = 0; desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0, AR5K_AR5211_DESC_TX_CTL0_XMIT_RATE); if ((tx_status->tx_status_0 & AR5K_AR5211_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0) { if (tx_status->tx_status_0 & AR5K_AR5211_DESC_TX_STATUS0_EXCESSIVE_RETRIES) desc->ds_us.tx.ts_status |= HAL_TXERR_XRETRY; if (tx_status->tx_status_0 & AR5K_AR5211_DESC_TX_STATUS0_FIFO_UNDERRUN) desc->ds_us.tx.ts_status |= HAL_TXERR_FIFO; if (tx_status->tx_status_0 & AR5K_AR5211_DESC_TX_STATUS0_FILTERED) desc->ds_us.tx.ts_status |= HAL_TXERR_FILT; } return (HAL_OK);}HAL_BOOLar5k_ar5211_has_veol(struct ath_hal *hal){ return (AH_TRUE);}void /*Unimplemented*/ar5k_ar5211_get_tx_inter_queue(struct ath_hal *hal, u_int32_t *i){ AR5K_TRACE; /* XXX */ return;}/* * Receive functions */u_int32_tar5k_ar5211_get_rx_buf(struct ath_hal *hal){ return (AR5K_REG_READ(AR5K_AR5211_RXDP));}voidar5k_ar5211_put_rx_buf(struct ath_hal *hal, u_int32_t phys_addr){ AR5K_REG_WRITE(AR5K_AR5211_RXDP, phys_addr);}voidar5k_ar5211_start_rx(struct ath_hal *hal){ AR5K_REG_WRITE(AR5K_AR5211_CR, AR5K_AR5211_CR_RXE);}HAL_BOOLar5k_ar5211_stop_rx_dma(struct ath_hal *hal){ int i; AR5K_REG_WRITE(AR5K_AR5211_CR, AR5K_AR5211_CR_RXD); /* * It may take some time to disable the DMA receive unit */ for (i = 2000; i > 0 && (AR5K_REG_READ(AR5K_AR5211_CR) & AR5K_AR5211_CR_RXE) != 0; i--) AR5K_DELAY(10); return (i > 0 ? AH_TRUE : AH_FALSE);}voidar5k_ar5211_start_rx_pcu(struct ath_hal *hal){ AR5K_REG_DISABLE_BITS(AR5K_AR5211_DIAG_SW, AR5K_AR5211_DIAG_SW_DIS_RX);}voidar5k_ar5211_stop_pcu_recv(struct ath_hal *hal){ AR5K_REG_ENABLE_BITS(AR5K_AR5211_DIAG_SW, AR5K_AR5211_DIAG_SW_DIS_RX);}voidar5k_ar5211_set_mcast_filter(struct ath_hal *hal, u_int32_t filter0, u_int32_t filter1){ /* Set the multicat filter */ AR5K_REG_WRITE(AR5K_AR5211_MCAST_FIL0, filter0); AR5K_REG_WRITE(AR5K_AR5211_MCAST_FIL1, filter1);}HAL_BOOLar5k_ar5211_set_mcast_filterindex(struct ath_hal *hal, u_int32_t index){ if (index >= 64) { return (AH_FALSE); } else if (index >= 32) { AR5K_REG_ENABLE_BITS(AR5K_AR5211_MCAST_FIL1, (1 << (index - 32))); } else { AR5K_REG_ENABLE_BITS(AR5K_AR5211_MCAST_FIL0, (1 << index)); } return (AH_TRUE);}HAL_BOOLar5k_ar5211_clear_mcast_filter_idx(struct ath_hal *hal, u_int32_t index){ if (index >= 64) { return (AH_FALSE); } else if (index >= 32) { AR5K_REG_DISABLE_BITS(AR5K_AR5211_MCAST_FIL1, (1 << (index - 32))); } else { AR5K_REG_DISABLE_BITS(AR5K_AR5211_MCAST_FIL0, (1 << index)); } return (AH_TRUE);}u_int32_tar5k_ar5211_get_rx_filter(struct ath_hal *hal){ return (AR5K_REG_READ(AR5K_AR5211_RX_FILTER));}voidar5k_ar5211_set_rx_filter(struct ath_hal *hal, u_int32_t filter){ AR5K_REG_WRITE(AR5K_AR5211_RX_FILTER, filter);}HAL_BOOL /*O.K. - Initialize rx_desc and clear ds_hw */ar5k_ar5211_setup_rx_desc(struct ath_hal *hal, struct ath_desc *desc, u_int32_t size, u_int flags){ struct ar5k_ar5211_rx_desc *rx_desc; rx_desc = (struct ar5k_ar5211_rx_desc*)&desc->ds_ctl0; /* * Clear ds_hw * If we don't clean the descriptor, while * scanning we get too many results, * most of them virtual, after some secs * of scanning system halts. M.F. */ bzero(desc->ds_hw, sizeof(desc->ds_hw)); /*Initialize rx descriptor*/ rx_desc->rx_control_0 = 0; rx_desc->rx_control_1 = 0; /*Setup descriptor*/ if ((rx_desc->rx_control_1 = (size & AR5K_AR5211_DESC_RX_CTL1_BUF_LEN)) != size) return (AH_FALSE); if (flags & HAL_RXDESC_INTREQ) rx_desc->rx_control_1 |= AR5K_AR5211_DESC_RX_CTL1_INTREQ; return (AH_TRUE);}HAL_STATUSar5k_ar5211_proc_rx_desc(struct ath_hal *hal, struct ath_desc *desc, u_int32_t phys_addr, struct ath_desc *next){ struct ar5k_ar5211_rx_status *rx_status; rx_status = (struct ar5k_ar5211_rx_status*)&desc->ds_hw[0]; /* No frame received / not ready */ if ((rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_DONE) == 0) return (HAL_EINPROGRESS); /* * Frame receive status */ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & AR5K_AR5211_DESC_RX_STATUS0_DATA_LEN; desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, AR5K_AR5211_DESC_RX_STATUS0_RECEIVE_SIGNAL); desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_AR5211_DESC_RX_STATUS0_RECEIVE_RATE); desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & AR5K_AR5211_DESC_RX_STATUS0_RECEIVE_ANTENNA; desc->ds_us.rx.rs_more = rx_status->rx_status_0 & AR5K_AR5211_DESC_RX_STATUS0_MORE; desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_AR5211_DESC_RX_STATUS1_RECEIVE_TIMESTAMP); desc->ds_us.rx.rs_status = 0; /* * Key table status */ if (rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_KEY_INDEX_VALID) { desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, AR5K_AR5211_DESC_RX_STATUS1_KEY_INDEX); } else { desc->ds_us.rx.rs_keyix = HAL_RXKEYIX_INVALID; } /* * Receive/descriptor errors */ if ((rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_FRAME_RECEIVE_OK) == 0) { if (rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_CRC_ERROR) desc->ds_us.rx.rs_status |= HAL_RXERR_CRC; if (rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_PHY_ERROR) { desc->ds_us.rx.rs_status |= HAL_RXERR_PHY; desc->ds_us.rx.rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, AR5K_AR5211_DESC_RX_STATUS1_PHY_ERROR); } if (rx_status->rx_status_1 & AR5K_AR5211_DESC_RX_STATUS1_DECRYPT_CRC_ERROR) desc->ds_us.rx.rs_status |= HAL_RXERR_DECRYPT; } return (HAL_OK);}void /*Added HAL_NODE_STATS argument*/ar5k_ar5211_set_rx_signal(struct ath_hal *hal, const HAL_NODE_STATS *stats){ /* Signal state monitoring is not yet supported */}/* * Misc functions */voidar5k_ar5211_dump_state(struct ath_hal *hal){#ifdef AR5K_DEBUG#define AR5K_PRINT_REGISTER(_x) \ printf("(%s: %08x) ", #_x, AR5K_REG_READ(AR5K_AR5211_##_x)); printf("MAC registers:\n"); AR5K_PRINT_REGISTER(CR); AR5K_PRINT_REGISTER(CFG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -