📄 cb20_cb.c
字号:
*/ for(i=0;i!=READLINE_DEL;i++) dummy = *(u32 *)sendbuf; /* Do the right thing (TM) for mic */ if(v_info->flags & MIC_CAPABLE){ adhoc = (v_info->flags & ADHOC) ? 1:0; if(Encapsulate(v_info,(ETH_HEADER_STRUC *)sendbuf,&miclen , adhoc)) { *payloadlen = (s16 ) (miclen - sizeof(HDR_802_3)); txd.length = miclen + sizeof(HDR_802_11); /*1/15/2003 */ } else {#ifdef DEBUG_MIC printk(KERN_DEBUG "Dumped tx packet\n");#endif goto dumptx; } } v_info->txdfc=0; memcpy((char *)v_info->txfids[0].CardRamOff, (char *)&txd, sizeof(CARD_TX_DESC)); v_info->stats.tx_bytes += len + sizeof(HDR_802_11); cb20out(v_info,V_EVACK,EV_XMIT); /* Send packet */ dumptx: if(in_irq()) dev_kfree_skb_irq(skb); else dev_kfree_skb(skb); return 1;}#endif/* * Wait given value to appear on given port. * return 0 if it did in waitms ms else -1 * if not. */static int waitport(struct cb20_info *v_info,int port,int value,int waitms){ u16 inword; int i; for(i=0;i!=waitms;i++){ inword = cb20in(v_info,port); if(inword == value) return 0; mdelay(1); } return -1;}/* * Softreset for cb20 */ int softreset(struct cb20_info *v){ int shakehands=0; cb20out(v ,V_EVINTEN,0); if(!waitport(v,V_SWS0,BB_HANDSHAKE_0,4000)){ if(!waitport(v,V_SWS1,BB_HANDSHAKE_1,4000)) shakehands = 1; else printk(KERN_CRIT "Boot block wait timeout SWS1!!\n"); } else printk(KERN_CRIT "Boot block wait timeout SWS0!!\n"); if(!shakehands){ cb20out (v, V_CNFCTRL, 0x0504); cb20out (v, V_CNFCTRL, 0x8000); udelay (300); cb20out (v, V_CNFCTRL, 0x0504); mdelay (30); /* Jeff adams says this should be here */ } return shakehands;}static void cb20_linkstat(struct net_device *dev,int linkstatus){ struct cb20_info *v_info = (struct cb20_info*)dev->priv;#if ASSOCDEBUG printk(KERN_INFO "Link stat int ls=%x\n",linkstatus);#endif if(linkstatus & 0x8000 ){#ifdef ASSOCDEBUG printk(KERN_INFO "No carrier\n");#endif v_info->flags &= ~(ASSOC); netif_carrier_off( dev); netif_stop_queue( dev ); } else if(linkstatus & 0x400){ v_info->flags |= ASSOC;#ifdef ASSOCDEBUG printk(KERN_INFO "Carrier On\n");#endif /* Update sequence numbers * upon assoc */ v_info->updateMultiSeq = TRUE; v_info->updateUniSeq = TRUE; netif_carrier_on( dev); netif_wake_queue(dev); }}/* * @interrupt */void cb20_interrupt ( int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; u16 stat1,stat=0,len; struct cb20_info *v_info = (struct cb20_info *)dev->priv; CARD_RX_DESC rxd; u32 len32; struct sk_buff *skb; STMIC mic;#ifdef INCLUDE_RFMONITOR unsigned char *buffer; int i;#endif if (!netif_device_present(dev)) return; spin_lock(&v_info->mpi_lock ); /* CB20 Globl lock */ memset((char *)&rxd,0,sizeof(rxd)); stat1 = cb20in(v_info,V_EVSTAT); if(stat1 == 0 || stat1==0xffff){ spin_unlock(&v_info->mpi_lock ); /* Bogus interrupt */ return; } disable_interrupts(v_info); if(stat1 & EV_MIC){#ifdef DEBUG_MIC printk(KERN_INFO "MIC interrupt\n");#endif cb20out(v_info,V_EVACK,EV_MIC); vreadrid((struct cb20_info *)dev->priv,RID_MIC,(char *)&mic, sizeof(mic)); micinit(v_info,&mic); stat1 &= ~(EV_MIC); } if(stat1 & EV_LINK){ stat = cb20in(v_info,V_LINKSTAT); cb20_linkstat(dev,stat); cb20out(v_info,V_EVACK,EV_LINK); stat1 &= ~(EV_LINK); } if(stat1 & EV_AWAKE ){ stat1 &= ~(EV_AWAKE); cb20out(v_info, V_EVACK, EV_AWAKE); cb20out(v_info, V_EVACK, EV_AWAKE); } if(stat1 & EV_CMD ){ cb20out(v_info, V_EVACK, EV_CMD); #ifdef DEBUG_CMD printk(KERN_ERR "Command int!\n");#endif stat1 &= ~(EV_CMD); } if(stat1 & EV_RX){ memcpy((char *)&rxd, v_info->rxfids[0].CardRamOff,sizeof(rxd)); /* Make sure we got something */ if(rxd.RxDone && rxd.valid ==0 ){#ifdef INCLUDE_RFMONITOR if (v_info->rfMonitor) { if (v_info->rxfids[0].VirtualHostAddress[4] & 0x2) { /* CRC error */ len = 0; } else { len = *(u16*)((u16*)(v_info->rxfids[0].VirtualHostAddress)+3)+30; } if (len && len < 2312) { v_info->stats.rx_packets++; v_info->stats.rx_bytes += len; skb = dev_alloc_skb( len ); buffer = skb_put(skb, len); memcpy(buffer, v_info->rxfids[0].VirtualHostAddress+20, 30); /* gap length */ i = *(u16*)((u16*)(v_info->rxfids[0].VirtualHostAddress)+25); if (i+len+52 > rxd.length) { i = 0; } /* skip the gap */ memcpy(buffer+30, v_info->rxfids[0].VirtualHostAddress+52+i,len-30); skb->mac.raw = skb->data; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_802_2); skb->dev = dev; skb->ip_summed = CHECKSUM_NONE; dev->last_rx = jiffies; netif_rx( skb ); } } else#endif { len = rxd.length + 12; if( len > 12 && len < 2048 ){ skb = dev_alloc_skb( len ); if(v_info->flags & MIC_CAPABLE){ /* Check for MIC */ len32 = (u32)len; if(Decapsulate(v_info , (ETH_HEADER_STRUC *)v_info->rxfids[0].VirtualHostAddress, &len32 )) {#ifdef DEBUG_MIC printk(KERN_ERR "Dumping packet from decap\n");#endif dev_kfree_skb_irq(skb); goto dumpit; } len = len32 ; } v_info->stats.rx_bytes += len; v_info->stats.rx_packets++; memcpy(skb_put(skb,len),v_info->rxfids[0].VirtualHostAddress,len); skb->dev = dev; skb->ip_summed = CHECKSUM_NONE; skb->protocol = eth_type_trans( skb, dev ); dev->last_rx = jiffies; netif_rx( skb ); } } } dumpit: if(rxd.valid == 0){ rxd.valid = 1; rxd.RxDone= 0; rxd.length= HOSTBUFSIZ; memcpy(v_info->rxfids[0].CardRamOff,(char *)&rxd,sizeof(rxd)); } cb20out(v_info, V_EVACK, EV_RX); stat1 &= ~(EV_RX); } if(stat1 & EV_TXCPY){ stat1 &= ~(EV_TXCPY); ++v_info->stats.tx_packets; v_info->txdfc =1;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,55 )) if(skb_queue_len(&v_info->txq) !=0){ v_info->flags |= TXBUSY; send_packet(dev); } else{ v_info->flags &= ~(TXBUSY); netif_wake_queue(dev); }#else dev->tbusy=0; /* Reenable queueing */#endif cb20out(v_info, V_EVACK, EV_TXCPY); } if(stat1){ printk(KERN_ERR "Unhandled event %x \n",stat1); cb20out(v_info,V_EVACK,stat1); } if((INT_DISABLE & v_info->flags) == 0){ cb20out(v_info,CB_CLEARINT,CB_FLAGBIT); cb20out(v_info,CB_INTENABLE,CB_FLAGBIT); } spin_unlock(&v_info->mpi_lock ); /* CB20 Globl lock */ enable_interrupts(v_info); return;}/* * @open */static int cb20_open(struct net_device *vdev){ struct cb20_info *v_info; MOD_INC_USE_COUNT; v_info = (struct cb20_info *)vdev->priv; if(v_info->flags & REAP) return -ENODEV; if(!v_info->open){ request_irq(vdev->irq,cb20_interrupt,SA_SHIRQ,vdev->name,vdev); v_info->flags &= ~(INT_DISABLE); netif_start_queue(vdev); enable_interrupts(v_info); } v_info->open++; return 0;}/* * @close */static int cb20_close(struct net_device *dev) { struct cb20_info *vi = (struct cb20_info*)dev->priv; vi->open--; vi->flags |= INT_DISABLE; if ( !vi->open ) { disable_interrupts(vi); netif_stop_queue(dev); free_irq( dev->irq, dev ); } MOD_DEC_USE_COUNT; return 0;}static struct net_device_stats *cb20_get_stats(struct net_device *dev){ return &(((struct cb20_info *)dev->priv)->stats);}static int cb20_change_mtu(struct net_device *dev, int new_mtu){ if ((new_mtu < 68) || (new_mtu > 2400)) return -EINVAL; dev->mtu = new_mtu; return 0;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,55 ))/* * @cb20_transmit */static int cb20_transmit(struct sk_buff *skb, struct net_device *dev) { int flags,npacks; struct cb20_info *v_info = (struct cb20_info*)dev->priv; if ( skb == NULL ) { printk( KERN_ERR "CB20 : skb == NULL!!!\n" ); return 0; } disable_interrupts(v_info); spin_lock_irqsave(&v_info->mpi_lock,flags); npacks = skb_queue_len(&v_info->txq); if(npacks >= MAXTXQ ){ netif_stop_queue(dev); skb_queue_tail(&v_info->txq,skb); dev_kfree_skb(skb); /* Throw on floor */ v_info->stats.tx_dropped++; enable_interrupts(v_info); spin_unlock_irqrestore(&v_info->mpi_lock,flags); return 0; } if(npacks >= MAXTXQ - 10 ){ netif_stop_queue(dev); skb_queue_tail(&v_info->txq,skb); enable_interrupts(v_info); spin_unlock_irqrestore(&v_info->mpi_lock,flags); return 0; } skb_queue_tail(&v_info->txq, skb); netif_wake_queue(dev); if((v_info->flags & TXBUSY) == 0){ send_packet(dev); } enable_interrupts(v_info); spin_unlock_irqrestore(&v_info->mpi_lock,flags); return 0;}#endif/* * Multiple card list handling reaping and locating etc * @devlist */static void cb20_reap(void){ struct cb20_info *v_info; struct net_device *devp; CB20_CARDS **p = &cb20_units; while( *p ){ devp = (*p)->dev; v_info = (struct cb20_info *)devp->priv; /* If found then reap it and * remove it from the list */ if(v_info->flags & REAP && !v_info->open ){ unregister_netdev(devp); kfree(devp); *p = (*p)->next; continue; } p = &(*p)->next; }}static void add_cb20( struct net_device *dev ) { CB20_CARDS *node = (CB20_CARDS *)kmalloc( sizeof( *node ), GFP_KERNEL ); if ( !node ) { printk( KERN_ERR "CB20: Out of memory\n" ); } else { node->dev = dev; node->next = cb20_units ; cb20_units = node; }}#if !defined(CONFIG_NET_PCMCIA) /* * Return netdevice struct pointer for * specified interface null if not found * @loc_cb20 */static struct net_device *loc_cb20(char *devname){ CB20_CARDS **p = &cb20_units; struct net_device *devp ; while( *p ){ devp = (*p)->dev ; if(!strcmp(devp->name,devname)) return devp; p = &(*p)->next; } return NULL;}#endif#if defined(CONFIG_NET_PCMCIA) /* * Return the struct net_device * used by struct pci_dev *locate * return null if none found and b*tch as something is seriously * hosed. */static struct net_device *pcidev_loc(struct pci_dev *locate){ CB20_CARDS **p = &cb20_units; struct net_device *devp ; struct cb20_info *vp; struct pci_dev *pcid; while( *p ){ devp = (*p)->dev ; vp= (struct cb20_info *)devp->priv; pcid = vp->pcip; if(!memcmp((void*)pcid,(void *)locate,sizeof(*locate))) return devp; p = &(*p)->next; } printk(KERN_ERR "Can not find %p\n",locate); return NULL;} #endifvoid del_cb20( struct net_device *dev ) { CB20_CARDS **p = &cb20_units; struct cb20_info *v_info; struct net_device *devp; v_info = (struct cb20_info *)dev->priv ;#if !defined(CONFIG_NET_PCMCIA) if(v_info->flags & REAP ){#ifdef DEBUG_DEL printk(KERN_DEBUG "REAP BIT SET not deleted!!\n");#endif return; }#endif while( *p && (*p)->dev != dev ){ devp = (*p)->dev; p = &(*p)->next; } if ( *p && (*p)->dev == dev ){ v_info = (struct cb20_info *)(*p)->dev->priv; v_info = (struct cb20_info *)(*p)->dev->priv; *p = (*p)->next; }}/* * Proc filesystem processing *//* @del_proc */static int del_proc_entry( struct net_device *dev,struct cb20_info *apriv ) { struct cb20_info *v_info ; v_info = (struct cb20_info *)dev->priv;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,55))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -