📄 ni65.c
字号:
if(!(csr0 & (CSR0_ERR | CSR0_RINT | CSR0_TINT))) break; if(csr0 & CSR0_RINT) /* RECV-int? */ ni65_recv_intr(dev,csr0); if(csr0 & CSR0_TINT) /* XMIT-int? */ ni65_xmit_intr(dev,csr0); if(csr0 & CSR0_ERR) { struct priv *p = (struct priv *) dev->priv; if(debuglevel > 1) printk("%s: general error: %04x.\n",dev->name,csr0); if(csr0 & CSR0_BABL) p->stats.tx_errors++; if(csr0 & CSR0_MISS) { int i; for(i=0;i<RMDNUM;i++) printk("%02x ",p->rmdhead[i].u.s.status); printk("\n"); p->stats.rx_errors++; } if(csr0 & CSR0_MERR) { if(debuglevel > 1) printk("%s: Ooops .. memory error: %04x.\n",dev->name,csr0); ni65_stop_start(dev,p); } } }#ifdef RCV_PARANOIA_CHECK{ int j; for(j=0;j<RMDNUM;j++) { struct priv *p = (struct priv *) dev->priv; int i,k,num1,num2; for(i=RMDNUM-1;i>0;i--) { num2 = (p->rmdnum + i) & (RMDNUM-1); if(!(p->rmdhead[num2].u.s.status & RCV_OWN)) break; } if(i) { for(k=0;k<RMDNUM;k++) { num1 = (p->rmdnum + k) & (RMDNUM-1); if(!(p->rmdhead[num1].u.s.status & RCV_OWN)) break; } if(!k) break; if(debuglevel > 0) { char buf[256],*buf1; int k; buf1 = buf; for(k=0;k<RMDNUM;k++) { sprintf(buf1,"%02x ",(p->rmdhead[k].u.s.status)); /* & RCV_OWN) ); */ buf1 += 3; } *buf1 = 0; printk(KERN_ERR "%s: Ooops, receive ring corrupted %2d %2d | %s\n",dev->name,p->rmdnum,i,buf); } p->rmdnum = num1; ni65_recv_intr(dev,csr0); if((p->rmdhead[num2].u.s.status & RCV_OWN)) break; /* ok, we are 'in sync' again */ } else break; }}#endif if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) { printk("%s: RX or TX was offline -> restart\n",dev->name); ni65_stop_start(dev,p); } else writedatareg(CSR0_INEA); dev->interrupt = 0; return;}/* * We have received an Xmit-Interrupt .. * send a new packet if necessary */static void ni65_xmit_intr(struct device *dev,int csr0){ struct priv *p = (struct priv *) dev->priv; while(p->xmit_queued) { struct tmd *tmdp = p->tmdhead + p->tmdlast; int tmdstat = tmdp->u.s.status; if(tmdstat & XMIT_OWN) break; if(tmdstat & XMIT_ERR) {#if 0 if(tmdp->status2 & XMIT_TDRMASK && debuglevel > 3) printk(KERN_ERR "%s: tdr-problems (e.g. no resistor)\n",dev->name);#endif /* checking some errors */ if(tmdp->status2 & XMIT_RTRY) p->stats.tx_aborted_errors++; if(tmdp->status2 & XMIT_LCAR) p->stats.tx_carrier_errors++; if(tmdp->status2 & (XMIT_BUFF | XMIT_UFLO )) { /* this stops the xmitter */ p->stats.tx_fifo_errors++; if(debuglevel > 0) printk(KERN_ERR "%s: Xmit FIFO/BUFF error\n",dev->name); if(p->features & INIT_RING_BEFORE_START) { tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END; /* test: resend this frame */ ni65_stop_start(dev,p); break; /* no more Xmit processing .. */ } else ni65_stop_start(dev,p); } if(debuglevel > 2) printk(KERN_ERR "%s: xmit-error: %04x %02x-%04x\n",dev->name,csr0,(int) tmdstat,(int) tmdp->status2); if(!(csr0 & CSR0_BABL)) /* don't count errors twice */ p->stats.tx_errors++; tmdp->status2 = 0; } else p->stats.tx_packets++;#ifdef XMT_VIA_SKB if(p->tmd_skb[p->tmdlast]) { dev_kfree_skb(p->tmd_skb[p->tmdlast],FREE_WRITE); p->tmd_skb[p->tmdlast] = NULL; }#endif p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1); if(p->tmdlast == p->tmdnum) p->xmit_queued = 0; } dev->tbusy = 0; mark_bh(NET_BH);}/* * We have received a packet */static void ni65_recv_intr(struct device *dev,int csr0){ struct rmd *rmdp; int rmdstat,len; int cnt=0; struct priv *p = (struct priv *) dev->priv; rmdp = p->rmdhead + p->rmdnum; while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN)) { cnt++; if( (rmdstat & (RCV_START | RCV_END | RCV_ERR)) != (RCV_START | RCV_END) ) /* error or oversized? */ { if(!(rmdstat & RCV_ERR)) { if(rmdstat & RCV_START) { p->stats.rx_length_errors++; printk(KERN_ERR "%s: recv, packet too long: %d\n",dev->name,rmdp->mlen & 0x0fff); } } else { if(debuglevel > 2) printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n", dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) ); if(rmdstat & RCV_FRAM) p->stats.rx_frame_errors++; if(rmdstat & RCV_OFLO) p->stats.rx_over_errors++; if(rmdstat & RCV_CRC) p->stats.rx_crc_errors++; if(rmdstat & RCV_BUF_ERR) p->stats.rx_fifo_errors++; } if(!(csr0 & CSR0_MISS)) /* don't count errors twice */ p->stats.rx_errors++; } else if( (len = (rmdp->mlen & 0x0fff) - 4) >= 60) {#ifdef RCV_VIA_SKB struct sk_buff *skb = alloc_skb(R_BUF_SIZE+2+16,GFP_ATOMIC); if (skb) skb_reserve(skb,16);#else struct sk_buff *skb = dev_alloc_skb(len+2);#endif if(skb) { skb_reserve(skb,2); skb->dev = dev;#ifdef RCV_VIA_SKB if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) { skb_put(skb,len); eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0); } else { struct sk_buff *skb1 = p->recv_skb[p->rmdnum]; skb_put(skb,R_BUF_SIZE); p->recv_skb[p->rmdnum] = skb; rmdp->u.buffer = (u32) virt_to_bus(skb->data); skb = skb1; skb_trim(skb,len); }#else skb_put(skb,len); eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);#endif p->stats.rx_packets++; skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); } else { printk(KERN_ERR "%s: can't alloc new sk_buff\n",dev->name); p->stats.rx_dropped++; } } else { printk(KERN_INFO "%s: received runt packet\n",dev->name); p->stats.rx_errors++; } rmdp->blen = -(R_BUF_SIZE-8); rmdp->mlen = 0; rmdp->u.s.status = RCV_OWN; /* change owner */ p->rmdnum = (p->rmdnum + 1) & (RMDNUM-1); rmdp = p->rmdhead + p->rmdnum; }}/* * kick xmitter .. */static int ni65_send_packet(struct sk_buff *skb, struct device *dev){ struct priv *p = (struct priv *) dev->priv; if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 50) return 1; printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);{ int i; for(i=0;i<TMDNUM;i++) printk("%02x ",p->tmdhead[i].u.s.status); printk("\n");} ni65_lance_reinit(dev); dev->tbusy=0; dev->trans_start = jiffies; } if(skb == NULL) { dev_tint(dev); return 0; } if (skb->len <= 0) return 0; if (set_bit(0, (void*)&dev->tbusy) != 0) { printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name); return 1; } if (set_bit(0, (void*)&p->lock)) { printk(KERN_ERR "%s: Queue was locked.\n", dev->name); return 1; } { short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; struct tmd *tmdp; long flags;#ifdef XMT_VIA_SKB if( (unsigned long) (skb->data + skb->len) > 0x1000000) {#endif memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data, (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len); dev_kfree_skb (skb, FREE_WRITE); save_flags(flags); cli(); tmdp = p->tmdhead + p->tmdnum; tmdp->u.buffer = (u32) virt_to_bus(p->tmdbounce[p->tmdbouncenum]); p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);#ifdef XMT_VIA_SKB } else { save_flags(flags); cli(); tmdp = p->tmdhead + p->tmdnum; tmdp->u.buffer = (u32) virt_to_bus(skb->data); p->tmd_skb[p->tmdnum] = skb; }#endif tmdp->blen = -len; tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END; writedatareg(CSR0_TDMD | CSR0_INEA); /* enable xmit & interrupt */ p->xmit_queued = 1; p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1); dev->tbusy = (p->tmdnum == p->tmdlast) ? 1 : 0; p->lock = 0; dev->trans_start = jiffies; restore_flags(flags); } return 0;}static struct enet_statistics *ni65_get_stats(struct device *dev){#if 0 int i; struct priv *p = (struct priv *) dev->priv; for(i=0;i<RMDNUM;i++) { struct rmd *rmdp = p->rmdhead + ((p->rmdnum + i) & (RMDNUM-1)); printk("%02x ",rmdp->u.s.status); } printk("\n");#endif return &((struct priv *) dev->priv)->stats;}static void set_multicast_list(struct device *dev){ if(!ni65_lance_reinit(dev)) printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name); dev->tbusy = 0;}#ifdef MODULEstatic struct device dev_ni65 = { " ", /* "ni6510": device name inserted by net_init.c */ 0, 0, 0, 0, 0x360, 9, /* I/O address, IRQ */ 0, 0, 0, NULL, ni65_probe };/* set: io,irq,dma or set it when calling insmod */static int irq=0;static int io=0;static int dma=0;int init_module(void){#if 0 if(io <= 0x0 || irq < 2) { printk("ni65: Autoprobing not allowed for modules.\n"); printk("ni65: Set symbols 'io' 'irq' and 'dma'\n"); return -ENODEV; }#endif dev_ni65.irq = irq; dev_ni65.dma = dma; dev_ni65.base_addr = io; if (register_netdev(&dev_ni65) != 0) return -EIO; return 0;}void cleanup_module(void){ struct priv *p; p = (struct priv *) dev_ni65.priv; if(!p) { printk("Ooops .. no privat struct\n"); return; } disable_dma(dev_ni65.dma); free_dma(dev_ni65.dma); release_region(dev_ni65.base_addr,cards[p->cardno].total_size); ni65_free_buffer(p); dev_ni65.priv = NULL; unregister_netdev(&dev_ni65);}#endif /* MODULE *//* * END of ni65.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -