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

📄 ni65.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -