⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5212.c

📁 无线网卡驱动 固件程序 There are currently 3 "programming generations" of Atheros 802.11 wireless devices (
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * 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 + -