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

📄 r8180_core.c

📁 rtl8180网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			//unsigned long flags;			//spin_lock_irqsave(&priv->irq_lock,flags);						priv->rxringtail+=4;			if(priv->rxringtail >= 			   (priv->rxring)+(priv->rxringcount )*4)				priv->rxringtail=priv->rxring;						//spin_unlock_irqrestore(&priv->irq_lock,flags);				#ifndef DUMMY_RX			priv->rxbuffer=(priv->rxbuffer->next);#endif		}	}	}void rtl8180_dma_kick(struct net_device *dev, int priority){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;		rtl8180_set_mode(dev,EPROM_CMD_CONFIG);		switch(priority){			case LOW_PRIORITY:				write_nic_byte(dev,TX_DMA_POLLING,		       (1<< TX_DMA_POLLING_LOWPRIORITY_SHIFT) |			        priv->dma_poll_mask);		break;				case NORM_PRIORITY:				write_nic_byte(dev,TX_DMA_POLLING,		       (1<< TX_DMA_POLLING_NORMPRIORITY_SHIFT) |			        priv->dma_poll_mask);		break;				case HI_PRIORITY:				write_nic_byte(dev,TX_DMA_POLLING,		       (1<< TX_DMA_POLLING_HIPRIORITY_SHIFT) |			        priv->dma_poll_mask);		break;		}		rtl8180_set_mode(dev,EPROM_CMD_NORMAL);		read_nic_byte(dev,CONFIG1); /* force PCI posting */}void rtl8180_data_hard_stop(struct net_device *dev){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	priv->dma_poll_mask |= (1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);	rtl8180_set_mode(dev,EPROM_CMD_CONFIG);	write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);	rtl8180_set_mode(dev,EPROM_CMD_NORMAL);}void rtl8180_data_hard_resume(struct net_device *dev){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	priv->dma_poll_mask &= ~(1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);	rtl8180_set_mode(dev,EPROM_CMD_CONFIG);	write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);	rtl8180_set_mode(dev,EPROM_CMD_NORMAL);}/* this function TX data frames when the ieee80211 stack requires this. * It checks also if we need to stop the ieee tx queue, eventually do it */void rtl8180_hard_data_xmit(struct net_device *dev,struct sk_buff *skb,short morefrag){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	int mode;	//unsigned long flags;		mode = priv->ieee80211->iw_mode;			/*	* This function doesn't require lock because we make	* sure it's called with the tx_lock already acquired.	* this come from the kernel's hard_xmit callback (trought	* the ieee stack, or from the try_wake_queue (again trought	* the ieee stack.	*/	//spin_lock_irqsave(&priv->tx_lock,flags);						if (!check_nic_enought_desc(dev, LOW_PRIORITY)){		DMESG("Error: no descriptor left by previous TX (avail %d) ",			get_curr_tx_free_desc(dev, LOW_PRIORITY));		ieee80211_r8180_stop_queue(priv->ieee80211);	}	rtl8180_tx(dev, (u32*)skb->data, skb->len, LOW_PRIORITY, morefrag,0);	if (!check_nic_enought_desc(dev, LOW_PRIORITY))		ieee80211_r8180_stop_queue(priv->ieee80211);			//spin_unlock_irqrestore(&priv->tx_lock,flags);				}/* This is a rough attempt to TX a frame * This is called by the ieee 80211 stack to TX management frames. * If the ring is full packet are dropped (for data frame the queue * is stopped before this can happen). For this reason it is better * if the descriptors are larger than the largest management frame * we intend to TX: i'm unsure what the HW does if it will not found * the last fragment of a frame because it has been dropped... * Since queues for Management and Data frames are different we * might use a different lock than tx_lock (for example mgmt_tx_lock) *//* these function may loops if invoked with 0 descriptors or 0 len buffer*/int rtl8180_hard_start_xmit(struct sk_buff *skb,struct net_device *dev){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	int ret;	unsigned long flags;		spin_lock_irqsave(&priv->tx_lock,flags);		ret = rtl8180_tx(dev, (u32*)skb->data, skb->len, NORM_PRIORITY, 0, 0);		priv->ieee80211->stats.tx_bytes+=skb->len;	priv->ieee80211->stats.tx_packets++;		spin_unlock_irqrestore(&priv->tx_lock,flags);			dev_kfree_skb_any(skb);	return ret;}u16 rtl8180_len2duration(u32 len, short rate,short* ext){	u16 duration;	u16 drift;	*ext=0;		switch(rate){	case 0://1mbps		*ext=0;		duration = ((len+4)<<4) /0x2;		drift = ((len+4)<<4) % 0x2;		if(drift ==0 ) break;		duration++;		break;			case 1://2mbps		*ext=0;		duration = ((len+4)<<4) /0x4;		drift = ((len+4)<<4) % 0x4;		if(drift ==0 ) break;		duration++;		break;			case 2: //5.5mbps		*ext=0;		duration = ((len+4)<<4) /0xb;		drift = ((len+4)<<4) % 0xb;		if(drift ==0 ) 			break;		duration++;		break;			default:	case 3://11mbps						*ext=0;		duration = ((len+4)<<4) /0x16;		drift = ((len+4)<<4) % 0x16;		if(drift ==0 ) 			break;		duration++;		if(drift > 6) 			break;		*ext=1;		break;	}		return duration;}void rtl8180_prepare_beacon(struct net_device *dev){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	u32 *tail = priv->txbeacontail;	u32 *begin = priv->txbeaconring;	u16 duration;	short ext;	u8 rate = priv->basic_rate;	u32 len = priv->master_beaconsize;		u16 word  = read_nic_word(dev, BcnItv);	word &= ~BcnItv_BcnItv; // clear Bcn_Itv	word |= cpu_to_le16(priv->ieee80211->beacon_interval);//0x64;		write_nic_word(dev, BcnItv, word);			//DMESG("size %x",len);	if(*tail & (1<<31)){ 		//DMESG("No more beacon TX desc");		return ;				}	//while(! *tail & (1<<31)){		*tail= 0; // zeroes header				*tail = *tail| (1<<29) ; //fist segment of the packet		*tail = (*tail) | (1<<28); // last segment	//	*tail = *tail | (1<<18); // this is  a beacon frame		*(tail+3)=*(tail+3) &~ 0xfff; 		*(tail+3)=*(tail+3) | len; // buffer lenght		*tail = *tail |len; 		// zeroes the second 32-bits dword of the descriptor		*(tail+1)= 0; 		*tail = *tail | (rate << 24);					duration = rtl8180_len2duration(len,rate,&ext);				*(tail+1) = *(tail+1) | ((duration & 0x7fff)<<16);				*tail = *tail | (1<<31); 		//^ descriptor ready to be txed		if((tail - begin)/8 == priv->txbeaconcount-1)			tail=begin; 		else			tail=tail+8;	//}}/* This function do the real dirty work: it enqueues a TX command  * descriptor in the ring buffer, copyes the frame in a TX buffer   * and kicks the NIC to ensure it does the DMA transfer. */short rtl8180_tx(struct net_device *dev, u32* txbuf, int len, int priority,		 short morefrag, short descfrag){	struct r8180_priv *priv = dev->priv;	u32 *tail;	u32 *begin;	u32 *buf;	int i;	int remain;	int buflen;	u16 duration;	short ext;	struct buffer* buflist;	//unsigned long flags;			switch(priority) {	case LOW_PRIORITY:		tail=priv->txlpringtail;		begin=priv->txlpring;		buflist = priv->txlpbufstail;	    		break;			case HI_PRIORITY:		tail=priv->txhpringtail;		begin=priv->txhpring;		buflist = priv->txhpbufstail;		break;	  	case NORM_PRIORITY:		tail=priv->txnpringtail;		begin=priv->txnpring;		buflist = priv->txnpbufstail;	    		break;	  	default:		return -1;		break; 	}	buflen=priv->txbuffsize; 	remain=len;	while(remain!=0){#ifdef DEBUG_TX_FRAG		DMESG("TX iteration");#endif#ifdef DEBUG_TX			DMESG("TX: filling descriptor %x",(u32)tail);#endif		mb();		if(!buflist){			DMESG("EE: TX buffer error, cannot TX frames");			//spin_unlock_irqrestore(&priv->tx_lock,flags);			return -1;		}		buf=buflist->buf;				if(*tail & (1<<31)){ 			DMESG("WW: No more TX desc, returning %x of %x",			      remain,len);			priv->stats.txrdu++;#ifdef DEBUG_TX_DESC			check_tx_ring(dev,priority);			netif_stop_queue(dev);			netif_carrier_off(dev);#endif		//	spin_unlock_irqrestore(&priv->tx_lock,flags);			return remain;										}			*tail= 0; // zeroes header 				if(remain==len && !descfrag) *tail = *tail| (1<<29) ; //fist segment of the packet		#ifdef DEBUG_TX_FRAG		if(remain==len && !descfrag) DMESG("First descriptor");#endif		//rtl8180_set_mode(dev,EPROM_CMD_CONFIG);				for(i=0;i<buflen&& remain >0;i++,remain--){			((u8*)buf)[i]=((u8*)txbuf)[i]; //copy data into descriptor pointed DMAble buffer			if(remain == 4 && i+4 >= buflen) break; 			/* ensure the last desc has at least 4 bytes payload */ 					}		txbuf = (u32*)((u8*)txbuf + i);		*(tail+3)=*(tail+3) &~ 0xfff; 		*(tail+3)=*(tail+3) | i; // buffer lenght		*tail = *tail |(len); 		*(tail+1)= 0; // zeroes the second 32-bits dword of the descriptor		*tail = *tail | (priv->ieee80211->rate << 24);				if(priv->card_8185){			//FIXME!!!!!!!!!			/* there are some stuff to pleace in the descriptor */			*(tail+5)=0;		}				/* hw_plcp_len is never set for rtl8180 chip */		if(!priv->hw_plcp_len){					duration = rtl8180_len2duration(len,				priv->ieee80211->rate,&ext);				#ifdef DEBUG_TX			DMESG("PLCP duration %d",duration );			DMESG("drift %d",drift);			DMESG("extension %s", (ext==1) ? "on":"off");#endif			*(tail+1) = *(tail+1) | ((duration & 0x7fff)<<16);			if(ext) *(tail+1) = *(tail+1) |(1<<31); //plcp length extension		}				if(morefrag) *tail = (*tail) | (1<<17); // more fragment		if(!remain) *tail = (*tail) | (1<<28); // last segment of frame				//FIXME: this should be triggered by HW encryption parameters.		if(priv->card_8185) *tail = (*tail) | (1<<15); // don't perform HW Eencrypt#ifdef DEBUG_TX_FRAG		if(!remain)DMESG("Last descriptor");		if(morefrag)DMESG("More frag");#endif		wmb();		*tail = *tail | (1<<31); // descriptor ready to be txed				if((tail - begin)/8 == priv->txringcount-1)			tail=begin; 				else			tail=tail+8;				buflist=buflist->next;				mb();				switch(priority) {			case LOW_PRIORITY:				priv->txlpringtail=tail;				priv->txlpbufstail=buflist;							break;						case HI_PRIORITY:				priv->txhpringtail=tail;				priv->txhpbufstail = buflist;								break;							case NORM_PRIORITY:				priv->txnpringtail=tail;				priv->txnpbufstail=buflist;												break;		}						rtl8180_dma_kick(dev,priority);			}		//spin_unlock_irqrestore(&priv->tx_lock,flags);		return 0;	}void rtl8180_irq_rx_tasklet(struct r8180_priv * priv);void rtl8180_IBSS_create_wq(struct net_device *dev);short rtl8180_init(struct net_device *dev){			struct r8180_priv *priv = dev->priv;	int i, j;	u16 word;	int ch;	u16 version;	u8 hw_version;	//FIXME: these constants are placed in a bad pleace.	priv->card_8185 = 0;		priv->txbuffsize = 1024;	priv->txringcount = 32;	priv->rxbuffersize = 1024;	priv->rxringcount = 32; 	priv->txbeaconcount = 3;	priv->rx_skb_complete = 1;	//priv->txnp_pending.ispending=0; 	/* ^^ the SKB does not containt a partial RXed	 * packet (is empty)	 */	priv->basic_rate = DEFAULT_BASICRATE;	if(!channels){		DMESG("No channels, aborting");		return -1;	}	ch=channels;	 // set channels 1..14 allowed in given locale	for (i=1; i<=14; i++) {		(priv->challow)[i] = (u8)(ch & 0x01);		ch >>= 1;	}	//memcpy(priv->stats,0,sizeof(struct Stats));		priv->stats.rxdmafail=0;	priv->stats.txrdu=0;	priv->stats.rxrdu=0;	priv->stats.rxnolast=0;	priv->stats.rxnodata=0;	priv->stats.rxreset=0;	priv->stats.rxwrkaround=0;	priv->stats.rxnopointer=0;	priv->stats.txnperr=0;	priv->stats.txresumed=0;	priv->stats.rxerr=0;	priv->stats.rxoverflow=0;	priv->stats.rxint=0;	priv->stats.txnpokint=0;	priv->stats.txhpokint=0;	priv->stats.txhperr=0;	priv->stats.ints=0;	priv->stats.shints=0;	priv->stats.txoverflow=0;	priv->stats.txbeacon=0;	priv->stats.txbeaconerr=0;		priv->ieee80211=ieee80211_r8180_alloc(dev,priv);			priv->ieee80211->beacon_interval = DEFAULT_BEACONINTERVAL;	ieee80211_r8180_set_master_essid(priv->ieee80211,DEFAULT_BEACON_ESSID,		strlen(DEFAULT_BEACON_ESSID));	memcpy(priv->ieee80211->ssid, DEFAULT_SSID, strlen(DEFAULT_SSID));	priv->wq_hurryup = 0;	priv->ieee80211->iw_mode = IW_MODE_INFRA;	priv->ieee80211->dev = dev;	priv->ieee80211->tx_payload_only = 0;	priv->ieee80211->hw_seq = hwseqnum;	priv->ieee80211->sifs_time = RTL8180_SIFS;	DMESG("Hardware frame sequence numbers %s", 	      priv->ieee80211->hw_seq ? "enabled":"disabled");	priv->ieee80211->hw_wep=0;	priv->hw_wep = hwwep;	priv->prism_hdr=0;	priv->dev=dev;	/*priv->master_beaconinterval = cpu_to_le16(DEFAULT_MASTER_BI); */ 	priv->chan = 11;	priv->retry_rts = DEFAULT_RETRY_RTS;	priv->retry_data = DEFAULT_RETRY_DATA;	priv->ieee80211->master_chan = 11;	priv->ieee80211->rate = 3; //11 mbps	init_timer(&priv->scan_timer);	priv->scan_timer.data = (unsigned long)dev;	priv->scan_timer.function = rtl8180_scan;	priv->active_probe = 1;	priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;	spin_lock_init(&priv->scan_lock);	spin_lock_init(&priv->irq_lock);	spin_lock_init(&priv->irq_th_lock);	spin_lock_init(&priv->tx_lock);	sema_init(&priv->wx_sem,1);	priv->workqueue = create_workqueue(DRV_NAME);	INIT_WORK(&priv->IBSS_work,(void(*)(void*)) rtl8180_IBSS_create_wq,dev);		tasklet_init(&priv->irq_rx_tasklet,		     (void(*)(unsigned long)) rtl8180_irq_rx_tasklet,		     (unsigned long)priv);		priv->ieee80211->func = 		kmalloc(sizeof(struct ieee80211_helper_functions),GFP_KERNEL);	memset(priv->ieee80211->func, 0,	       sizeof(struct ieee80211_helper_functions));		priv->ieee80211->func->tx_80211 = rtl8180_hard_start_xmit;	priv->ieee80211->func->start_scan = rtl8180_start_scanning;	priv->ieee80211->func->stop_scan = rtl8180_stop_scanning;	priv->ieee80211->func->set_chan = rtl8180_set_chan;	priv->ieee80211->func->associate = r

⌨️ 快捷键说明

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