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

📄 r8180_core.c

📁 rtl8180网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	desc = (u32*)pci_alloc_consistent(pdev,					  sizeof(u32)*8*count+256, &dma_desc);	if(desc==NULL) return -1; 	if(dma_desc & 0xff){ 				/* 		 * descriptor's buffer must be 256 byte aligned		 * we shouldn't be here, since we set DMA mask ! 		 */		DMESG("WW: Fixing TX alignment"); 		desc = (u32*)((u8*)desc + 256);#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR))		desc = (u32*)((u64)desc &~ 0xff);		dma_desc = (dma_addr_t)((u8*)dma_desc + 256);		dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff);#else 		desc = (u32*)((u32)desc &~ 0xff);		dma_desc = (dma_addr_t)((u8*)dma_desc + 256);		dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff);#endif	}	tmp=desc;	for (i=0;i<count;i++)	{		buf = (void*)pci_alloc_consistent(pdev,bufsize,&dma_tmp);		if (buf == NULL) return -1;		switch(addr) {		case TX_NORMPRIORITY_RING_ADDR:			buffer_add(&(priv->txnpbufs),buf,dma_tmp,NULL);			break;					case TX_LOWPRIORITY_RING_ADDR:			buffer_add(&(priv->txlpbufs),buf,dma_tmp,NULL);			break;					case TX_HIGHPRIORITY_RING_ADDR:			buffer_add(&(priv->txhpbufs),buf,dma_tmp,NULL);			break;					/*		case TX_BEACON_RING_ADDR:		        buffer_add(&(priv->txbeaconbufs),buf,dma_tmp,NULL);			break;*/		}				*tmp = *tmp &~ (1<<31); // descriptor empty, owned by the drv 		*(tmp+2) = (u32)dma_tmp;		*(tmp+3) = bufsize;		if(i+1<count)			*(tmp+4) = (u32)dma_desc+((i+1)*8*4);		else			*(tmp+4) = (u32)dma_desc;				tmp=tmp+8;	}		switch(addr) {	case TX_NORMPRIORITY_RING_ADDR:		priv->txnpringdma=dma_desc;		priv->txnpring=desc;		break;			case TX_LOWPRIORITY_RING_ADDR:		priv->txlpringdma=dma_desc;		priv->txlpring=desc;		break;			case TX_HIGHPRIORITY_RING_ADDR:		priv->txhpringdma=dma_desc;		priv->txhpring=desc;		break;				/*		  case TX_BEACON_RING_ADDR:		  priv->txbeaconringdma=dma_desc;		  priv->txbeaconring=desc;		  break;		*/	}	#ifdef DEBUG_TX	DMESG("Tx dma physical address: %x",dma_desc);#endif		return 0;}void free_tx_desc_ring(struct net_device *dev,int count){		struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	struct pci_dev *pdev=priv->pdev;		pci_free_consistent(pdev, sizeof(u32)*8*count+256, 			    priv->txlpring, priv->txlpringdma);			    	buffer_free(dev,&(priv->txlpbufs),priv->txbuffsize,1);	pci_free_consistent(pdev, sizeof(u32)*8*count+256, 			    priv->txhpring, priv->txhpringdma);			    	buffer_free(dev,&(priv->txhpbufs),priv->txbuffsize,1);	pci_free_consistent(pdev, sizeof(u32)*8*count+256, 			    priv->txnpring, priv->txnpringdma);			    	buffer_free(dev,&(priv->txnpbufs),priv->txbuffsize,1);}void free_beacon_desc_ring(struct net_device *dev,int count){		struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	struct pci_dev *pdev=priv->pdev;		pci_free_consistent(pdev, sizeof(u32)*8*count+256, 			    priv->txbeaconring, priv->txbeaconringdma);		if (priv->beacon_buf) 		pci_free_consistent(priv->pdev,			priv->master_beaconsize,priv->beacon_buf,priv->beacondmabuf);  }void free_rx_desc_ring(struct net_device *dev,int count){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	struct pci_dev *pdev = priv->pdev;		pci_free_consistent(pdev, sizeof(u32)*4*count+256, 			    priv->rxring, priv->rxringdma);			    	buffer_free(dev,&(priv->rxbuffer),priv->txbuffsize,0);}short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count){	int i;	u32 *desc;	u32 *tmp;	dma_addr_t dma_desc,dma_tmp;	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	struct pci_dev *pdev=priv->pdev;	void *buf;		if((bufsize & 0xfff) != bufsize){ 		DMESG ("EE: RX buffer allocation too large");		return -1;	}		desc = (u32*)pci_alloc_consistent(pdev,sizeof(u32)*4*count+256,					  &dma_desc);		if(dma_desc & 0xff){ 				/* 		 * descriptor's buffer must be 256 byte aligned		 * should never happen since we specify the DMA mask		 */				DMESG("WW: Fixing RX alignment"); 		desc = (u32*)((u8*)desc + 256);#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR))		desc = (u32*)((u64)desc &~ 0xff);		dma_desc = (dma_addr_t)((u8*)dma_desc + 256);		dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff);#else 		desc = (u32*)((u32)desc &~ 0xff);		dma_desc = (dma_addr_t)((u8*)dma_desc + 256);		dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff);#endif	}		priv->rxring=desc;	priv->rxringdma=dma_desc;	tmp=desc;		for (i=0;i<count;i++){				if ((buf= kmalloc(bufsize * sizeof(u8),GFP_ATOMIC)) == NULL){			DMESG ("EE: Failed to kmalloc RX buffer");			return -1;		}				dma_tmp = pci_map_single(pdev,buf,bufsize * sizeof(u8), 					 PCI_DMA_FROMDEVICE);		//buf = (void*)pci_alloc_consistent(pdev,bufsize,&dma_tmp);		buffer_add(&(priv->rxbuffer), buf,dma_tmp,			   &(priv->rxbufferhead));		*tmp = 0; //zero pads the header of the descriptor		*tmp = *tmp |( bufsize&0xfff);		*(tmp+2) = (u32)dma_tmp;		*tmp = *tmp |(1<<31); // descriptor void, owned by the NIC		#ifdef DEBUG_RXALLOC		DMESG("Alloc %x size buffer, DMA mem @ %x, virtual mem @ %x",		      (u32)(bufsize&0xfff), (u32)dma_tmp, (u32)buf);#endif				tmp=tmp+4;	}		*(tmp-4) = *(tmp-4) | (1<<30); // this is the last descriptor		#ifdef DEBUG_RXALLOC	DMESG("RX DMA physical address: %x",dma_desc);#endif		return 0;}void set_nic_rxring(struct net_device *dev){	u8 pgreg;	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;		rtl8180_set_mode(dev, EPROM_CMD_CONFIG);		pgreg=read_nic_byte(dev, PGSELECT);	write_nic_byte(dev, PGSELECT, pgreg &~ (1<<PGSELECT_PG_SHIFT));		rtl8180_set_mode(dev, EPROM_CMD_NORMAL);		write_nic_dword(dev, RXRING_ADDR,priv->rxringdma);}void rtl8180_reset(struct net_device *dev){	u32 txconf = 0x80e00707; //FIXME: Make me understandable	u8 cr;		write_nic_dword(dev,TX_CONF,txconf);		rtl8180_irq_disable(dev);		cr=read_nic_byte(dev,CMD);	cr = cr & 2;	cr = cr | (1<<CMD_RST_SHIFT);	write_nic_byte(dev,CMD,cr);		read_nic_byte(dev,CMD); //force PCI posting		mdelay(200);		if(read_nic_byte(dev,CMD) & (1<<CMD_RST_SHIFT)) 		DMESG("WW: Card reset timeout!");	else 		DMESG("Card successfully reset");		rtl8180_set_mode(dev,EPROM_CMD_LOAD);	read_nic_byte(dev,CMD);	mdelay(200);}/* This is rough RX isr handling routine*/void rtl8180_rx(struct net_device *dev){	struct r8180_priv *priv = (struct r8180_priv *)dev->priv;	struct sk_buff *tmp_skb;		//struct sk_buff *skb;	short first,last;	u32 len;	unsigned char quality, signal;	u8 rate;	u32 *prism_hdr;	struct ieee80211_rx_stats stats = {		.signal = 0,		.noise = -98,		.rate = 0,		.mac_time = jiffies,	};			if (!priv->rxbuffer) DMESG ("EE: NIC RX ack, but RX queue corrupted!");	else {		if (*(priv->rxringtail) & (1<<31)) {			//DMESG("WW: RX invoked, but no data");			priv->stats.rxnodata++;			priv->ieee80211->stats.rx_errors++;			if (! *(priv->rxring) & (1<<31)) {				//DMESG("WW: Fifo RX HW reset, using workaround...");				priv->stats.rxreset++;				priv->rxringtail=priv->rxring;				priv->rxbuffer=priv->rxbufferhead;							}else{				u32 *tmp = priv->rxringtail;				//DMESG("WW: RX pointer lost, trying workaround..");				priv->stats.rxwrkaround++;				while (*(priv->rxringtail) & (1<<31)){					priv->rxringtail+=4;					if(priv->rxringtail >= 					   (priv->rxring)+(priv->rxringcount )*4)						priv->rxringtail=priv->rxring;										priv->rxbuffer=(priv->rxbuffer->next);					if(priv->rxringtail == tmp ){						//DMESG("EE: Could not find RX pointer");						priv->stats.rxnopointer++;						break;					}				}			}		}				while( ! (*(priv->rxringtail) & (1<<31))){			//priv->ieee80211->stats.rx_packets++;			#ifndef DUMMY_RX				if(*(priv->rxringtail) & (1<<26)) 				DMESG("WW: RX buffer overflow");			if(*(priv->rxringtail) & (1<<27)){				priv->stats.rxdmafail++; 				//DMESG("EE: RX DMA FAILED at buffer pointed by descriptor %x",(u32)priv->rxringtail);							}else{	#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 8)						pci_dma_sync_single_for_cpu(priv->pdev,						    priv->rxbuffer->dma,						    priv->rxbuffersize * \						    sizeof(u8),						    PCI_DMA_FROMDEVICE);#else				pci_dma_sync_single(priv->pdev,						    priv->rxbuffer->dma,						    priv->rxbuffersize * \						    sizeof(u8),						    PCI_DMA_FROMDEVICE);#endif				first = *(priv->rxringtail) & (1<<29) ? 1:0;				if(first) priv->rx_prevlen=0;				last = *(priv->rxringtail) & (1<<28) ? 1:0;								len = (last ? 					       ((*priv->rxringtail) &0xfff) \				       -priv->rx_prevlen: 				       priv->rxbuffersize);				priv->rx_prevlen+=len;				#ifdef DEBUG_RX_FRAG				DMESG("Iteration.. len %x",len);				if(first) DMESG ("First descriptor");				if(last) DMESG("Last descriptor");				#endif#ifdef DEBUG_RX_VERBOSE				print_buffer( priv->rxbuffer->buf, len);#endif								signal=((*(priv->rxringtail+1))&\					      (0xff00))>>8;								quality=((*(priv->rxringtail+1)) &(0xff));								rate=((*(priv->rxringtail)) &					((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;								switch(rate){				case 0: 					stats.rate=10;					break;				case 1: 					stats.rate=20;					break;				case 2: 					stats.rate=55;					break;				case 3: 					stats.rate=110;					break;				}								rtl8180_RSSI_calc(dev,&signal,&quality);								priv->wstats.qual.level = signal + 125;				priv->wstats.qual.qual = quality;				priv->wstats.qual.noise = 100 - quality;				priv->wstats.qual.updated = 7;												stats.signal =  signal+125;//- (signal+50) ;				/*we use noise to carry quality info */				stats.noise = quality;								if(first && !priv->rx_skb_complete){					/* seems that HW sometimes fails to reiceve and 					   doesn't not provide the last descriptor */										dev_kfree_skb_any(priv->rx_skb);					/*  priv->rx_skb = dev_alloc_skb(len+2);					    priv->rx_skb->dev=dev;*/					priv->stats.rxnolast++;				}								if(!first && priv->rx_skb_complete) 					DMESG ("EE: RX: fd flag not set, \but rx sbk not allocated \n\**PLEASE** REPORT THIS TO <andreamrl@tiscali.it> !!!");								if(first || priv->rx_skb_complete){					priv->rx_skb_complete=0; 										/* support for prism header has been originally added by Christian */										if(priv->prism_hdr && priv->ieee80211->iw_mode == IW_MODE_MONITOR){						priv->rx_skb = dev_alloc_skb(len+2+PRISM_HDR_SIZE);						prism_hdr = (u32*) skb_put(priv->rx_skb,PRISM_HDR_SIZE);						prism_hdr[0]=htonl(0x80211001);        //version						prism_hdr[1]=htonl(0x40);              //length						prism_hdr[2]=0x00;                     //mactime (HIGH)						prism_hdr[3]=htonl(stats.mac_time);    //mactime (LOW)						rdtsc(prism_hdr[5], prism_hdr[4]);         //hostime (LOW+HIGH)						prism_hdr[4]=htonl(prism_hdr[4]);          //Byte-Order aendern						prism_hdr[5]=htonl(prism_hdr[5]);          //Byte-Order aendern						prism_hdr[6]=0x00;                     //phytype						prism_hdr[7]=htonl(priv->chan);        //channel						prism_hdr[8]=htonl(stats.rate);        //datarate						prism_hdr[9]=0x00;                     //antenna						prism_hdr[10]=0x00;                    //priority						prism_hdr[11]=0x00;                    //ssi_type						prism_hdr[12]=htonl(stats.signal);     //ssi_signal						prism_hdr[13]=htonl(stats.noise);      //ssi_noise						prism_hdr[14]=0x00;                    //preamble						prism_hdr[15]=0x00;                    //encoding					}else{						priv->rx_skb = dev_alloc_skb(len+2);#ifdef DEBUG_RX_SKB						DMESG("Alloc initial skb %x",len+2);#endif										}															priv->rx_skb->dev=dev;				}else{										tmp_skb= dev_alloc_skb(priv->rx_skb->len +len+2);					tmp_skb->dev=dev;#ifdef DEBUG_RX_SKB					DMESG("Realloc skb %x",len+2);#endif#ifdef DEBUG_RX_SKB					DMESG("going copy prev frag %x",priv->rx_skb->len);#endif					memcpy(skb_put(tmp_skb,priv->rx_skb->len),					       priv->rx_skb->data,					       priv->rx_skb->len);#ifdef DEBUG_RX_SKB					DMESG("skb copy prev frag complete");#endif					dev_kfree_skb_any(priv->rx_skb);				 					priv->rx_skb=tmp_skb;				}#ifdef DEBUG_RX_SKB				DMESG("going to copy current payload %x",len);#endif				memcpy(skb_put(priv->rx_skb,len),				       priv->rxbuffer->buf,len);#ifdef DEBUG_RX_SKB				DMESG("current fragment skb copy complete");#endif				if(last){#ifdef DEBUG_RX_SKB					DMESG("Got last fragment");#endif														skb_trim(priv->rx_skb,priv->rx_skb->len-4);#ifdef DEBUG_RX_SKB					DMESG("yanked out crc, passing to the upper layer");#endif					if(!ieee80211_r8180_rx(priv->ieee80211, 							 priv->rx_skb, &stats)){#ifdef DEBUG_RX						DMESG("WW: Packet not consumed");#endif										dev_kfree_skb_any(priv->rx_skb);					}#ifdef DEBUG_RX					else{						DMESG("Rcv frag");					}#endif					priv->rx_skb_complete=1;				}			}#endif //DUMMY_RX#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 8)					pci_dma_sync_single_for_device(priv->pdev,						    priv->rxbuffer->dma,						    priv->rxbuffersize * \						    sizeof(u8),						    PCI_DMA_FROMDEVICE);#endif			/* restore the descriptor */						*(priv->rxringtail+2)=priv->rxbuffer->dma;			*(priv->rxringtail)=*(priv->rxringtail) &~ 0xfff;			*(priv->rxringtail)=				*(priv->rxringtail) | priv->rxbuffersize;							*(priv->rxringtail)=				*(priv->rxringtail) | (1<<31); 			//^empty descriptor			//wmb();				#ifdef DEBUG_RX			DMESG("Current descriptor: %x",(u32)priv->rxringtail);#endif

⌨️ 快捷键说明

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