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