📄 r8180_core.c
字号:
} 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 + -