📄 ar5212.c
字号:
/* * Restore interrupt mask */ ar5k_ar5212_set_intr(hal, imr); return (status);}int /*O.K.*/ar5k_ar5212_setup_tx_queue(struct ath_hal *hal, HAL_TX_QUEUE queue_type, const HAL_TXQ_INFO *queue_info){ u_int queue; AR5K_TRACE; /* * Get queue by type */ if (queue_type == HAL_TX_QUEUE_DATA) { for (queue = HAL_TX_QUEUE_ID_DATA_MIN; hal->ah_txq[queue].tqi_type != HAL_TX_QUEUE_INACTIVE; queue++) if (queue > HAL_TX_QUEUE_ID_DATA_MAX) return (-1); } else if (queue_type == HAL_TX_QUEUE_PSPOLL) { queue = HAL_TX_QUEUE_ID_PSPOLL; } else if (queue_type == HAL_TX_QUEUE_BEACON) { queue = HAL_TX_QUEUE_ID_BEACON; } else if (queue_type == HAL_TX_QUEUE_CAB) { queue = HAL_TX_QUEUE_ID_CAB; } else return (-1); /* * Setup internal queue structure */ bzero(&hal->ah_txq[queue], sizeof(HAL_TXQ_INFO)); hal->ah_txq[queue].tqi_type = queue_type; if (queue_info != NULL) { if (ar5k_ar5212_setup_tx_queueprops(hal, queue, queue_info) != AH_TRUE) return (-1); } AR5K_Q_ENABLE_BITS(hal->ah_txq_interrupts, queue); return (queue);}HAL_BOOL /*O.K.*/ar5k_ar5212_setup_tx_queueprops(struct ath_hal *hal, int queue, const HAL_TXQ_INFO *queue_info){ AR5K_TRACE; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); if (hal->ah_txq[queue].tqi_type == HAL_TX_QUEUE_INACTIVE) return (AH_FALSE); bcopy(queue_info, &hal->ah_txq[queue], sizeof(HAL_TXQ_INFO)); if (queue_info->tqi_type == HAL_TX_QUEUE_DATA && (queue_info->tqi_subtype >= HAL_WME_AC_VI) && (queue_info->tqi_subtype <= HAL_WME_UPSD)) hal->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; return (AH_TRUE);}HAL_BOOL /*New*/ar5k_ar5212_get_tx_queueprops(struct ath_hal *hal, int queue, HAL_TXQ_INFO *queue_info){ AR5K_TRACE; memcpy(queue_info, &hal->ah_txq[queue], sizeof(HAL_TXQ_INFO)); return (AH_TRUE);}HAL_BOOL /*O.K.*/ar5k_ar5212_release_tx_queue(struct ath_hal *hal, u_int queue){ AR5K_TRACE; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* This queue will be skipped in further operations */ hal->ah_txq[queue].tqi_type = HAL_TX_QUEUE_INACTIVE; AR5K_Q_DISABLE_BITS(hal->ah_txq_interrupts, queue); return (AH_FALSE); /*???*/}HAL_BOOL /*O.K.*/ar5k_ar5212_reset_tx_queue(struct ath_hal *hal, u_int queue){ u_int32_t cw_min, cw_max, retry_lg, retry_sh; struct ieee80211_channel *channel = (struct ieee80211_channel*) &hal->ah_current_channel; HAL_TXQ_INFO *tq; AR5K_TRACE; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); tq = &hal->ah_txq[queue]; if (tq->tqi_type == HAL_TX_QUEUE_INACTIVE) return (AH_TRUE); /* * Set registers by channel mode */ cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN; cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX; hal->ah_aifs = AR5K_TUNE_AIFS; if (IEEE80211_IS_CHAN_XR(channel)) { cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN_XR; cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX_XR; hal->ah_aifs = AR5K_TUNE_AIFS_XR; } else if (IEEE80211_IS_CHAN_B(channel)) { cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN_11B; cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX_11B; hal->ah_aifs = AR5K_TUNE_AIFS_11B; } /* * Set retry limits */ if (hal->ah_software_retry == AH_TRUE) { /* XXX Need to test this */ retry_lg = hal->ah_limit_tx_retries; retry_sh = retry_lg = retry_lg > AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY ? AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY : retry_lg; } else { retry_lg = AR5K_INIT_LG_RETRY; retry_sh = AR5K_INIT_SH_RETRY; } AR5K_REG_WRITE(AR5K_AR5212_DCU_RETRY_LMT(queue), AR5K_REG_SM(AR5K_INIT_SLG_RETRY, AR5K_AR5212_DCU_RETRY_LMT_SLG_RETRY) | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, AR5K_AR5212_DCU_RETRY_LMT_SSH_RETRY) | AR5K_REG_SM(retry_lg, AR5K_AR5212_DCU_RETRY_LMT_LG_RETRY) | AR5K_REG_SM(retry_sh, AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY)); /* * Set initial content window (cw_min/cw_max) */ cw_min = 1; while (cw_min < hal->ah_cw_min) cw_min = (cw_min << 1) | 1; cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); AR5K_REG_WRITE(AR5K_AR5212_DCU_LCL_IFS(queue), AR5K_REG_SM(cw_min, AR5K_AR5212_DCU_LCL_IFS_CW_MIN) | AR5K_REG_SM(cw_max, AR5K_AR5212_DCU_LCL_IFS_CW_MAX) | AR5K_REG_SM(hal->ah_aifs + tq->tqi_aifs, AR5K_AR5212_DCU_LCL_IFS_AIFS)); /* * Set misc registers */ AR5K_REG_WRITE(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_DCU_EARLY); if (tq->tqi_cbr_period) { AR5K_REG_WRITE(AR5K_AR5212_QCU_CBRCFG(queue), AR5K_REG_SM(tq->tqi_cbr_period, AR5K_AR5212_QCU_CBRCFG_INTVAL) | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, AR5K_AR5212_QCU_CBRCFG_ORN_THRES)); AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_FRSHED_CBR); if (tq->tqi_cbr_overflow_limit) AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_CBR_THRES_ENABLE); } if (tq->tqi_ready_time) { AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue), AR5K_REG_SM(tq->tqi_ready_time, AR5K_AR5212_QCU_RDYTIMECFG_INTVAL) | AR5K_AR5212_QCU_RDYTIMECFG_ENABLE); } if (tq->tqi_burst_time) { AR5K_REG_WRITE(AR5K_AR5212_DCU_CHAN_TIME(queue), AR5K_REG_SM(tq->tqi_burst_time, AR5K_AR5212_DCU_CHAN_TIME_DUR) | AR5K_AR5212_DCU_CHAN_TIME_ENABLE); if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) { AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_TXE); } } if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) { AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue), AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS); } if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue), AR5K_AR5212_DCU_MISC_BACKOFF_FRAG); } /* * Set registers by queue type */ switch (tq->tqi_type) { case HAL_TX_QUEUE_BEACON: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT | AR5K_AR5212_QCU_MISC_CBREXP_BCN | AR5K_AR5212_QCU_MISC_BCN_ENABLE); AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue), (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL) | AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_AR5212_DCU_MISC_BCN_ENABLE); AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue), ((AR5K_TUNE_BEACON_INTERVAL - (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | AR5K_AR5212_QCU_RDYTIMECFG_ENABLE); break; case HAL_TX_QUEUE_CAB: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT | AR5K_AR5212_QCU_MISC_CBREXP | AR5K_AR5212_QCU_MISC_CBREXP_BCN); AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue), (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL)); break; case HAL_TX_QUEUE_PSPOLL: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), AR5K_AR5212_QCU_MISC_CBREXP); break; case HAL_TX_QUEUE_DATA: default: break; } /* * Enable tx queue in the secondary interrupt mask registers */ AR5K_REG_WRITE(AR5K_AR5212_SIMR0, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXOK) | AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXDESC)); AR5K_REG_WRITE(AR5K_AR5212_SIMR1, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR1_QCU_TXERR)); AR5K_REG_WRITE(AR5K_AR5212_SIMR2, AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR2_QCU_TXURN)); return (AH_TRUE);}u_int32_t /*O.K.*/ar5k_ar5212_get_tx_buf(struct ath_hal *hal, u_int queue){ AR5K_TRACE; 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_AR5212_QCU_TXDP(queue)));}HAL_BOOL /*O.K.*/ar5k_ar5212_put_tx_buf(struct ath_hal *hal, u_int queue, u_int32_t phys_addr){ AR5K_TRACE; 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_AR5212_QCU_TXE, queue)) return (AH_FALSE); AR5K_REG_WRITE(AR5K_AR5212_QCU_TXDP(queue), phys_addr); return (AH_TRUE);}u_int32_t /*Code from roofnet*/ar5k_ar5212_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_AR5212_QCU_STS(queue) & AR5K_AR5212_QCU_STS_FRMPENDCNT);}HAL_BOOL /*O.K.*/ar5k_ar5212_tx_start(struct ath_hal *hal, u_int queue){ AR5K_TRACE; AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); /* Return if queue is disabled */ if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXD, queue)) return (AH_FALSE); /* Start queue */ AR5K_REG_WRITE_Q(AR5K_AR5212_QCU_TXE, queue); return (AH_TRUE);}HAL_BOOL /*Fixed delay*/ar5k_ar5212_stop_tx_dma(struct ath_hal *hal, u_int queue){ int i = 100, pending; AR5K_TRACE; 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_AR5212_QCU_TXD, queue); do { pending = AR5K_REG_READ(AR5K_AR5212_QCU_STS(queue)) & AR5K_AR5212_QCU_STS_FRMPENDCNT; AR5K_DELAY(100); } while (--i && pending); /* Clear register */ AR5K_REG_WRITE(AR5K_AR5212_QCU_TXD, 0); return (AH_TRUE);}HAL_BOOL /*O.K. - Initialize tx_desc and clear ds_hw */ar5k_ar5212_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_ar5212_tx_desc *tx_desc; AR5K_TRACE; /*Got that from roofnet*/// if (flags & HAL_TXDESC_NOACK) {// tx_tries0 = 1;// } tx_desc = (struct ar5k_ar5212_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; tx_desc->tx_control_2 = 0; tx_desc->tx_control_3 = 0; /* Setup status descriptor */ if ((tx_desc->tx_control_0 = (packet_length & AR5K_AR5212_DESC_TX_CTL0_FRAME_LEN)) != packet_length) return (AH_FALSE); tx_desc->tx_control_0 |= AR5K_REG_SM(tx_power, AR5K_AR5212_DESC_TX_CTL0_XMIT_POWER) | AR5K_REG_SM(antenna_mode, AR5K_AR5212_DESC_TX_CTL0_ANT_MODE_XMIT); tx_desc->tx_control_1 = AR5K_REG_SM(type, AR5K_AR5212_DESC_TX_CTL1_FRAME_TYPE); tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES0); tx_desc->tx_control_3 = tx_rate0 & AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE0;#define _TX_FLAGS(_c, _flag) \ if (flags & HAL_TXDESC_##_flag) \ tx_desc->tx_control_##_c |= \ AR5K_AR5212_DESC_TX_CTL##_c##_##_flag _TX_FLAGS(0, CLRDMASK); _TX_FLAGS(0, VEOL); _TX_FLAGS(0, INTREQ); _TX_FLAGS(0, RTSENA); _TX_FLAGS(0, CTSENA); _TX_FLAGS(1, NOACK);#undef _TX_FLAGS /* * WEP crap */ if (key_index != HAL_TXKEYIX_INVALID) { tx_desc->tx_control_0 |= AR5K_AR5212_DESC_TX_CTL0_ENCRYPT_KEY_VALID; tx_desc->tx_control_1 |= AR5K_REG_SM(key_index, AR5K_AR5212_DESC_TX_CTL1_ENCRYPT_KEY_INDEX); } /* * RTS/CTS */ if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) { if ((flags & HAL_TXDESC_RTSENA) && (flags & HAL_TXDESC_CTSENA)) return (AH_FALSE); tx_desc->tx_control_2 |= rtscts_duration & AR5K_AR5212_DESC_TX_CTL2_RTS_DURATION; tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate, AR5K_AR5212_DESC_TX_CTL3_RTS_CTS_RATE); } return (AH_TRUE);}HAL_BOOL /*Added an argument *last_desc -need revision -don't clear descriptor here*/ar5k_ar5212_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_ar5212_tx_desc *tx_desc; AR5K_TRACE; tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0; /* Clear status descriptor (we 've clean it during setup)*/// bzero(desc->ds_hw, sizeof(desc->ds_hw)); /* Validate segment length and initialize the descriptor */ if ((tx_desc->tx_control_1 = (segment_length & AR5K_AR5212_DESC_TX_CTL1_BUF_LEN)) != segment_length) return (AH_FALSE);/*Code from roofnet*/// if (segment_length> AR5K_AR5212_DESC_TX_CTL1_BUF_LEN){// return (AH_FALSE);//}// tx_desc->tx_control_1 &= ~AR5K_AR5212_DESC_TX_CTL1_BUF_LEN;// tx_desc->tx_control_1 |= (segment_length & AR5K_AR5212_DESC_TX_CTL1_BUF_LEN);/* */ if (first_segment != AH_TRUE) tx_desc->tx_control_0 &= ~AR5K_AR5212_DESC_TX_CTL0_FRAME_LEN; if (last_segment != AH_TRUE) tx_desc->tx_control_1 |= AR5K_AR5212_DESC_TX_CTL1_MORE; return (AH_TRUE);}HAL_BOOL /*O.K.*/ar5k_ar5212_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){ struct ar5k_ar5212_tx_desc *tx_desc; tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0;#define _XTX_TRIES(_n) \ if (tx_tries##_n) { \ tx_desc->tx_control_2 |= \ AR5K_REG_SM(tx_tries##_n, \ AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES##_n); \ tx_desc->tx_control_3 |= \ AR5K_REG_SM(tx_rate##_n, \ AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE##_n); \ } _XTX_TRIES(1); _XTX_TRIES(2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -