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

📄 zd1205.c

📁 Atheros USB WiFi Card 驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
{
	struct rx_list_elem *rx_struct = NULL;
    unsigned long flags;

    flags = dot11Obj.EnterCS();
	if (!list_empty(&(macp->rx_struct_pool))) {

 		rx_struct = list_entry(macp->rx_struct_pool.next,
				       struct rx_list_elem, list_elem);
		list_del(&(rx_struct->list_elem));
	}
    dot11Obj.ExitCS(flags);

	return rx_struct;
}


/**
 * zd1205_alloc_skb - allocate an skb for the adapter
 * @macp: atapter's private data struct
 *
 * Allocates skb with enough room for rfd, and data, and reserve non-data space.
 * Returns the new cell with sk_buff or %NULL.
 */

static struct rx_list_elem *
zd1205_alloc_skb(struct zd1205_private *macp)
{
	struct sk_buff *new_skb;

	u32 skb_size = sizeof (zd1205_RFD_t);
	struct rx_list_elem *rx_struct;

    ZENTER(4);

	new_skb = (struct sk_buff *) dev_alloc_skb(skb_size);
    if (new_skb) {
		/* The IP data should be 
		   DWORD aligned. since the ethernet header is 14 bytes long, 
		   we need to reserve 2 extra bytes so that the TCP/IP headers

		   will be DWORD aligned. */
		//skb_reserve(new_skb, 2); //for zd1202, rx dma must be 4-bytes aligmnebt
		if ((rx_struct = zd1205_get_rx_struct(macp)) == NULL)
			goto err;

	    ZD1211DEBUG(4, "zd1211: rx_struct = %x\n", (u32)rx_struct);


		rx_struct->skb = new_skb;
        
        //Rx DMA address  must be 4 bytes alignment
#ifndef HOST_IF_USB	        
		rx_struct->dma_addr = pci_map_single(macp->pdev, new_skb->data, sizeof (zd1205_RFD_t), PCI_DMA_FROMDEVICE);

#endif

        ZD1211DEBUG(4, "zd1211: rx_struct->dma_addr = %x\n", (u32)rx_struct->dma_addr);

#ifndef HOST_IF_USB            
		if (!rx_struct->dma_addr)
			goto err;
#endif            


       	skb_reserve(new_skb, macp->rfd_size); //now skb->data point to RxBuffer

#ifdef HOST_IF_USB      
     	rx_struct->dma_addr = (unsigned long)new_skb->data;
        rx_struct->UnFinishFrmLen = 0;
#endif
       
        ZEXIT(4);
		return rx_struct;
	} else {
        macp->AllocSkbFailCnt++;
        printk(KERN_DEBUG "zd1205: dev_alloc_skb fail\n");
		return NULL;
	}

err:
    printk(KERN_DEBUG "zd1205: ****** err\n");                
    dev_kfree_skb_any(new_skb);

	return NULL;
}


/**
 * zd1205_add_skb_to_end - add an skb to the end of our rfd list

 * @macp: atapter's private data struct
 * @rx_struct: rx_list_elem with the new skb
 *
 * Adds a newly allocated skb to the end of our rfd list.
 */



void
zd1205_add_skb_to_end(struct zd1205_private *macp, struct rx_list_elem *rx_struct)
{
	zd1205_RFD_t *rfdn;	/* The new rfd */

	zd1205_RFD_t *rfd;		/* The old rfd */
	struct rx_list_elem *rx_struct_last;
    unsigned long flags;

    ZENTER(4);


	(rx_struct->skb)->dev = macp->device;
	rfdn = RFD_POINTER(rx_struct->skb, macp);

	rfdn->CbCommand = RFD_EL_BIT;
	wmb();
	rfdn->CbStatus = 0xffffffff;

	rfdn->ActualCount = 0;
	rfdn->MaxSize = MAX_WLAN_SIZE;

	rfdn->NextCbPhyAddrHighPart = 0;

	rfdn->NextCbPhyAddrLowPart = 0;


#ifndef HOST_IF_USB
	wmb();

	pci_dma_sync_single(macp->pdev, rx_struct->dma_addr, macp->rfd_size,
			    PCI_DMA_TODEVICE);
#endif

    flags = dot11Obj.EnterCS();
	if (!list_empty(&(macp->active_rx_list))) {
    	rx_struct_last = list_entry(macp->active_rx_list.prev,

					    struct rx_list_elem, list_elem);


		rfd = RFD_POINTER(rx_struct_last->skb, macp);
		ZD1211DEBUG(4, "zd1211: rfd = %x\n", (u32)rfd);
		    
#ifndef HOST_IF_USB		    
		pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,

 				    4, PCI_DMA_FROMDEVICE);
#endif				 
   
		put_unaligned(rx_struct->dma_addr,
			      ((unsigned long *) (&(rfd->NextCbPhyAddrLowPart))));
#ifndef HOST_IF_USB				      
		wmb();
		pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,
				    8, PCI_DMA_TODEVICE);

#endif
				    
		rfd->CbCommand = 0; 

		
#ifndef HOST_IF_USB			
		wmb();
		pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,
				    4, PCI_DMA_TODEVICE);

#endif				    
	}
	
	list_add_tail(&(rx_struct->list_elem), &(macp->active_rx_list)); //add elem to active_rx_list
    dot11Obj.ExitCS(flags);
    ZEXIT(4);
}


void zd1205_alloc_skbs(struct zd1205_private *macp)
{
	for (; macp->skb_req > 0; macp->skb_req--) {
		struct rx_list_elem *rx_struct;

		if ((rx_struct = zd1205_alloc_skb(macp)) == NULL){
            printk(KERN_DEBUG "zd1205: zd1205_alloc_skb fail\n");
			return;

        }    
		zd1205_add_skb_to_end(macp, rx_struct);
	}

}


void zd1205_transmit_cleanup(struct zd1205_private *macp, zd1205_SwTcb_t *sw_tcb)
{
	zd1205_HwTCB_t *hw_tcb;
	u32 tbd_cnt;
	zd1205_TBD_t *tbd_arr = sw_tcb->pFirstTbd;

	ZENTER(2);

	hw_tcb = sw_tcb->pTcb;
	tbd_cnt = hw_tcb->TxCbTbdNumber;
 	tbd_arr += 2; //CtrlSetting and MacHeader

	ZD1211DEBUG(2, "zd1211: umap tbd cnt = %x\n", tbd_cnt-2);

#ifndef HOST_IF_USB
	for (i=0; i<tbd_cnt-2; i++, tbd_arr++) {
		ZD1211DEBUG(2, "zd1211: umap body_dma = %x\n", le32_to_cpu(tbd_arr->TbdBufferAddrLowPart));
			pci_unmap_single(macp->pdev,
			le32_to_cpu(tbd_arr->TbdBufferAddrLowPart),
			le32_to_cpu(tbd_arr->TbdCount),
			PCI_DMA_TODEVICE);
	}
#endif

	ZD1211DEBUG(2, "zd1211: Free TcbPhys = %x\n", (u32)sw_tcb->TcbPhys);
	zd1205_qlast_txq(macp, macp->freeTxQ, sw_tcb);
	ZD1211DEBUG(2, "zd1211: Cnt of freeTxQ = %x\n", macp->freeTxQ->count);

	//sw_tcb->HangDur = 0;
	hw_tcb->CbStatus = 0xffffffff;
	hw_tcb->TxCbTbdNumber = 0xaaaaaaaa;	/* for debug */
	hw_tcb->CbCommand = CB_S_BIT;

	if ((netif_running(macp->device)) && (macp->bAssoc)){
	netif_carrier_on(macp->device);
		netif_wake_queue(macp->device);   //resume tx
	}
    
	ZEXIT(2);
	return;		
}

void zd1205_tx_isr(struct zd1205_private *macp)
{
    int i;
	zd1205_SwTcb_t *sw_tcb = NULL;

#ifndef HOST_IF_USB
	zd1250_SwTcb_t *next_sw_tcb;
#endif
	u16 aid;

#ifdef HOST_IF_USB
	int bRunOnce = false;
#endif

	ZD1211DEBUG(2, "***** zd1205_tx_isr enter *****\n");

	if (!macp->activeTxQ->count){
		printk(KERN_DEBUG "No element in activeQ\n");
        clear_bit(ZD1211_TX_BUSY, &macp->flags);
		return;
	}	

	/* Look at the TCB at the head of the queue.  If it has been completed
	   then pop it off and place it at the tail of the completed list.
	   Repeat this process until all the completed TCBs have been moved to the
	   completed list */
	while (macp->activeTxQ->count){
		sw_tcb = macp->activeTxQ->first;

#ifdef HOST_IF_USB
		// in USB modem, only run once
		if (bRunOnce)	
			break;
		bRunOnce = true;
#endif
		// check to see if the TCB has been DMA'd

		// Workaround for hardware problem that seems leap over a TCB
		// and then fill completion token in the next TCB.
		ZD1211DEBUG(2, "zd1211: hw_tcb = %x\n", (u32)sw_tcb->pTcb);
		ZD1211DEBUG(2, "zd1211: CbStatus = %x\n", (u16)(sw_tcb->pTcb->CbStatus));

#ifndef HOST_IF_USB        
        rmb();

       	if ((u16)le32_to_cpu(sw_tcb->pTcb->CbStatus) != CB_STATUS_COMPLETE){
			next_sw_tcb = sw_tcb;

			while(1){
        		next_sw_tcb = next_sw_tcb->next;
        		if (!next_sw_tcb)
        			break;

				if ((u16)le32_to_cpu(next_sw_tcb->pTcb->CbStatus) == CB_STATUS_COMPLETE)
					break;
			}

			if (!next_sw_tcb)
				break;
		}
#endif        
	
		/* Remove the TCB from the active queue. */
		sw_tcb = zd1205_first_txq(macp, macp->activeTxQ);
        //Clear bit should run once only. This depends on the "bRunOnce"
        //mechanism. Clear twice may interfer normal tx
        clear_bit(ZD1211_TX_BUSY, &macp->flags);
		ZD1211DEBUG(2, "zd1211: Cnt of activeQ = %x\n", macp->activeTxQ->count);

		aid = sw_tcb->aid;
		zd1205_transmit_cleanup(macp, sw_tcb);
		macp->txCmpCnt++;
        
		if (!sw_tcb->LastFrag)
			continue;
        
#if ZDCONF_LP_SUPPORT == 1
        if(dot11Obj.LP_MODE && sw_tcb->LP_bucket) {
            //printk("TX_ISR Free LP_bucket\n");
            struct lp_desc *lp = (struct lp_desc *)sw_tcb->LP_bucket ;
            for(i=0;i<lp->pktCnt;i++) {
                //printk("msgID:%d\n", lp->pkt[i].msgID);
                zd_EventNotify(EVENT_TX_COMPLETE, ZD_TX_CONFIRM, (U32)lp->pkt[i].msgID, (U32)aid);
            }
            sw_tcb->LP_bucket = NULL;
            lp->pktCnt = 0;
            lp->sending = 0;
            lp->createTime = 0;
            lp->pktSize = 0;
            lp_recycle_tx_bucket(lp);
        }
        else
#endif
        {
            zd_EventNotify(EVENT_TX_COMPLETE, ZD_TX_CONFIRM, (U32)sw_tcb->MsgID, (U32)aid);
        }

		macp->SequenceNum++;
		macp->bDataTrafficLight = 1;
	}

#ifdef HOST_IF_USB
	if(sw_tcb->CalMIC[MIC_LNG] == TRUE)
		zd1211_submit_tx_urb(macp,TRUE);
	else
		zd1211_submit_tx_urb(macp,FALSE);
#endif

	ZD1211DEBUG(2, "***** zd1205_tx_isr exit *****\n");
	return;
} 


#ifndef HOST_IF_USB
static void zd1205_retry_failed(struct zd1205_private *macp)
{
	zd1205_SwTcb_t *sw_tcb;
	zd1205_SwTcb_t *next_sw_tcb = NULL;

    zd1205_HwTCB_t *hw_tcb;
	zd1205_Ctrl_Set_t *ctrl_set;

	u8 CurrentRate, NewRate;
	u8 ShortPreambleFg;
	u16 Len;
	u16 NextLen;
	u16 LenInUs;
	u16 NextLenInUs;
    u8 Service;
	u16 aid;

    ZD1211DEBUG(2, "+++++ zd1205_retry_failed enter +++++\n");
	
	if (!macp->activeTxQ->count){
		ZD1211DEBUG(1, "**********empty activeTxQ, got retry failed");
		sw_tcb = macp->freeTxQ->first;
		zd1205_start_download(sw_tcb->TcbPhys | BIT_0);
		return;
	}

		
	// Feature: Rate Adaption
	// - During the procedure of processing a transmitting frame, we must keep
	//   the TaRate consistent.
	// - When to fall OppositeContext.CurrentTxRate:
	//   Whenever RetryFail occurs, change OppositeContext.CurrentTxRate by a value
	//   ((Rate of this TCB) minus a degree) and modify this TCB's control-setting 
 	//   with the OppositeContext.CurrentTxRate and then Restart this TCB.
	//	 (Set RetryMAX = 2).
	//   Once the TxRate is 1M and still RetryFail, abandon this frame.
	// - When to rise TxRate:
 	//   If there are 10 frames transmitted successfully 
	//   (OppositeContext.ConsecutiveSuccessFrames >= 10), change 
	//   OppositeContext.CurrentTxRate by a value
	//   ((Rate of this TCB) plus a degree).


	// - Adjust OppositeContext.CurrentTxRate manually. (by application tool)
	sw_tcb = macp->activeTxQ->first;
	aid = sw_tcb->aid;
	ctrl_set = sw_tcb->pHwCtrlPtr;

	if (ctrl_set->CtrlSetting[11] & BIT_3){ //management frame
		goto no_rate_adaption;
	}	
	
	//CurrentRate = (ctrl_set->CtrlSetting[0] & 0x1f);

	CurrentRate = sw_tcb->Rate;

	ShortPreambleFg = (ctrl_set->CtrlSetting[0] & 0x20);
	
	if (((!ShortPreambleFg) && (CurrentRate > RATE_1M)) ||
		 ((ShortPreambleFg) && (CurrentRate > RATE_2M))){ 
		// Fall TxRate a degree

		NewRate = zd1205_RateAdaption(aid, CurrentRate, FALL_RATE);
		sw_tcb->Rate = NewRate;
 
		// Modify Control-setting
		ctrl_set->CtrlSetting[0] = (ShortPreambleFg | NewRate);
		ctrl_set->CtrlSetting[11] |= BIT_0; // Set need backoff
		
		// LenInUs, Service
		Len = (ctrl_set->CtrlSetting[1] + ((u16)ctrl_set->CtrlSetting[2] << 8));
		Cal_Us_Service(NewRate, Len, &LenInUs, &Service);
		ctrl_set->CtrlSetting[20] = (u8)LenInUs;
		ctrl_set->CtrlSetting[21] = (u8)(LenInUs >> 8);
 		ctrl_set->CtrlSetting[22] = Service;


		// NextLenInUs
#if defined(OFDM)
		NextLen = (ctrl_set->CtrlSetting[25+1] + ((u16)ctrl_set->CtrlSetting[25+2] << 8));
#else		
		NextLen = (ctrl_set->CtrlSetting[18] + ((u16)ctrl_set->CtrlSetting[19] << 8));
#endif		





		Cal_Us_Service(NewRate, NextLen, &NextLenInUs, &Service);
		ctrl_set->CtrlSetting[23] = (u8)NextLenInUs;
		ctrl_set->CtrlSetting[24] = (u8)(NextLenInUs >> 8);

#if defined(OFDM)
 		if (NewRate > RATE_11M){
			NewRate = OfdmRateTbl[NewRate];
		}
		
		macp->retryFailCnt++;

 		ctrl_set->CtrlSetting[0] = (ShortPreambleFg | NewRate);
		ctrl_set->CtrlSetting[11] |= BIT_0; // Set need backoff

#endif		
		// Re-Start Tx-Bus master with a lower Rate

		z

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -