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

📄 depca.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
  lp->init_block.mode = 0x0000;            /* Enable the Tx and Rx */  return;}/* ** Writes a socket buffer to TX descriptor ring and starts transmission */static intdepca_start_xmit(struct sk_buff *skb, struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;  int status = 0;  /* Transmitter timeout, serious problems. */  if (dev->tbusy) {    int tickssofar = jiffies - dev->trans_start;    if (tickssofar < 1*HZ) {      status = -1;    } else {      printk("%s: transmit timed out, status %04x, resetting.\n",	     dev->name, inw(DEPCA_DATA));	      STOP_DEPCA;      depca_init_ring(dev);      LoadCSRs(dev);      dev->interrupt = UNMASK_INTERRUPTS;      dev->start = 1;      dev->tbusy=0;      dev->trans_start = jiffies;      InitRestartDepca(dev);    }    return status;  } else if (skb->len > 0) {    /* Enforce 1 process per h/w access */    if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {      printk("%s: Transmitter access conflict.\n", dev->name);      status = -1;    } else {      if (TX_BUFFS_AVAIL) {                    /* Fill in a Tx ring entry */	status = load_packet(dev, skb);	if (!status) {	  /* Trigger an immediate send demand. */	  outw(CSR0, DEPCA_ADDR);	  outw(INEA | TDMD, DEPCA_DATA);	  	  dev->trans_start = jiffies;	  dev_kfree_skb(skb);	}	if (TX_BUFFS_AVAIL) {	  dev->tbusy=0;	}        } else {	status = -1;      }    }  }    return status;}/*** The DEPCA interrupt handler. */static voiddepca_interrupt(int irq, void *dev_id, struct pt_regs *regs){  struct device *dev = dev_id;  struct depca_private *lp;  s16 csr0, nicsr;  u_long ioaddr;  if (dev == NULL) {    printk ("depca_interrupt(): irq %d for unknown device.\n", irq);  } else {    lp = (struct depca_private *)dev->priv;    ioaddr = dev->base_addr;        if (dev->interrupt)      printk("%s: Re-entering the interrupt handler.\n", dev->name);    dev->interrupt = MASK_INTERRUPTS;    /* mask the DEPCA board interrupts and turn on the LED */    nicsr = inb(DEPCA_NICSR);    nicsr |= (IM|LED);    outb(nicsr, DEPCA_NICSR);    outw(CSR0, DEPCA_ADDR);    csr0 = inw(DEPCA_DATA);    /* Acknowledge all of the current interrupt sources ASAP. */    outw(csr0 & INTE, DEPCA_DATA);    if (csr0 & RINT)		       /* Rx interrupt (packet arrived) */      depca_rx(dev);    if (csr0 & TINT) 	               /* Tx interrupt (packet sent) */      depca_tx(dev);    if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */      dev->tbusy = 0;                  /* clear TX busy flag */      mark_bh(NET_BH);    }    /* Unmask the DEPCA board interrupts and turn off the LED */    nicsr = (nicsr & ~IM & ~LED);    outb(nicsr, DEPCA_NICSR);    dev->interrupt = UNMASK_INTERRUPTS;  }  return;}static intdepca_rx(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int i, entry;  s32 status;  for (entry=lp->rx_new;        !(readl(&lp->rx_ring[entry].base) & R_OWN);       entry=lp->rx_new){    status = readl(&lp->rx_ring[entry].base) >> 16 ;    if (status & R_STP) {                      /* Remember start of frame */      lp->rx_old = entry;    }    if (status & R_ENP) {                      /* Valid frame status */      if (status & R_ERR) {	               /* There was an error. */	lp->stats.rx_errors++;                 /* Update the error stats. */	if (status & R_FRAM) lp->stats.rx_frame_errors++;	if (status & R_OFLO) lp->stats.rx_over_errors++;	if (status & R_CRC)  lp->stats.rx_crc_errors++;	if (status & R_BUFF) lp->stats.rx_fifo_errors++;      } else {		short len, pkt_len = readw(&lp->rx_ring[entry].msg_length);	struct sk_buff *skb;	skb = dev_alloc_skb(pkt_len+2);	if (skb != NULL) {	  unsigned char *buf;	  skb_reserve(skb,2);               /* 16 byte align the IP header */	  buf = skb_put(skb,pkt_len);	  skb->dev = dev;	  if (entry < lp->rx_old) {         /* Wrapped buffer */	    len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;	    memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len);	    memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len);	  } else {                          /* Linear buffer */	    memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len);	  }	  /* 	  ** Notify the upper protocol layers that there is another 	  ** packet to handle	  */	  skb->protocol=eth_type_trans(skb,dev);	  netif_rx(skb); 	  /*	  ** Update stats	  */	  lp->stats.rx_packets++;	  for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) {	    if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) {	      lp->pktStats.bins[i]++;	      i = DEPCA_PKT_STAT_SZ;	    }	  }	  if (buf[0] & 0x01) {              /* Multicast/Broadcast */	    if ((*(s16 *)&buf[0] == -1) &&		(*(s16 *)&buf[2] == -1) &&		(*(s16 *)&buf[4] == -1)) {	      lp->pktStats.broadcast++;	    } else {	      lp->pktStats.multicast++;	    }	  } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) &&		     (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) &&		     (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {	    lp->pktStats.unicast++;	  }	  	  lp->pktStats.bins[0]++;           /* Duplicates stats.rx_packets */	  if (lp->pktStats.bins[0] == 0) {  /* Reset counters */	    memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats));	  }	} else {	  printk("%s: Memory squeeze, deferring packet.\n", dev->name);	  lp->stats.rx_dropped++;	/* Really, deferred. */	  break;	}      }      /* Change buffer ownership for this last frame, back to the adapter */      for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) {	writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, 	                                        &lp->rx_ring[lp->rx_old].base);      }      writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);    }    /*    ** Update entry information    */    lp->rx_new = (++lp->rx_new) & lp->rxRingMask;    }    return 0;}/*** Buffer sent - check for buffer errors.*/static intdepca_tx(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int entry;  s32 status;  u_long ioaddr = dev->base_addr;  for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {    status = readl(&lp->tx_ring[entry].base) >> 16 ;    if (status < 0) {                          /* Packet not yet sent! */      break;    } else if (status & T_ERR) {               /* An error occurred. */      status = readl(&lp->tx_ring[entry].misc);      lp->stats.tx_errors++;      if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++;      if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++;      if (status & TMD3_LCOL) lp->stats.tx_window_errors++;      if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++;      if (status & (TMD3_BUFF | TMD3_UFLO)) {	/* Trigger an immediate send demand. */	outw(CSR0, DEPCA_ADDR);	outw(INEA | TDMD, DEPCA_DATA);      }    } else if (status & (T_MORE | T_ONE)) {      lp->stats.collisions++;    } else {      lp->stats.tx_packets++;    }    /* Update all the pointers */    lp->tx_old = (++lp->tx_old) & lp->txRingMask;  }  return 0;}static intdepca_close(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  s16 nicsr;  u_long ioaddr = dev->base_addr;  dev->start = 0;  dev->tbusy = 1;  outw(CSR0, DEPCA_ADDR);  if (depca_debug > 1) {    printk("%s: Shutting down ethercard, status was %2.2x.\n",	   dev->name, inw(DEPCA_DATA));  }  /*   ** We stop the DEPCA here -- it occasionally polls  ** memory if we don't.   */  outw(STOP, DEPCA_DATA);  /*  ** Give back the ROM in case the user wants to go to DOS  */  if (lp->adapter != DEPCA) {    nicsr = inb(DEPCA_NICSR);    nicsr &= ~SHE;    outb(nicsr, DEPCA_NICSR);  }  /*  ** Free the associated irq  */  free_irq(dev->irq, dev);  MOD_DEC_USE_COUNT;  return 0;}static void LoadCSRs(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;  outw(CSR1, DEPCA_ADDR);                /* initialisation block address LSW */  outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA);  outw(CSR2, DEPCA_ADDR);                /* initialisation block address MSW */  outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA);  outw(CSR3, DEPCA_ADDR);                /* ALE control */  outw(ACON, DEPCA_DATA);  outw(CSR0, DEPCA_ADDR);                /* Point back to CSR0 */  return;}static int InitRestartDepca(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;  int i, status=0;  /* Copy the shadow init_block to shared memory */  memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init));  outw(CSR0, DEPCA_ADDR);                /* point back to CSR0 */  outw(INIT, DEPCA_DATA);                /* initialize DEPCA */  /* wait for lance to complete initialisation */  for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++);   if (i!=100) {    /* clear IDON by writing a "1", enable interrupts and start lance */    outw(IDON | INEA | STRT, DEPCA_DATA);    if (depca_debug > 2) {      printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n",	     dev->name, i, lp->sh_mem, inw(DEPCA_DATA));    }  } else {    printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n",	     dev->name, i, lp->sh_mem, inw(DEPCA_DATA));    status = -1;  }  return status;}static struct net_device_stats *depca_get_stats(struct device *dev){    struct depca_private *lp = (struct depca_private *)dev->priv;    /* Null body since there is no framing error counter */    return &lp->stats;}/*** Set or clear the multicast filter for this adaptor.*/static voidset_multicast_list(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;    if (dev) {    while(dev->tbusy) barrier();      /* Stop ring access */    set_bit(0, (void*)&dev->tbusy);    while(lp->tx_old != lp->tx_new);  /* Wait for the ring to empty */    STOP_DEPCA;                       /* Temporarily stop the depca.  */    depca_init_ring(dev);             /* Initialize the descriptor rings */    if (dev->flags & IFF_PROMISC) {   /* Set promiscuous mode */      lp->init_block.mode |= PROM;    } else {      SetMulticastFilter(dev);      lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */    }    LoadCSRs(dev);                    /* Reload CSR3 */    InitRestartDepca(dev);            /* Resume normal operation. */    dev->tbusy = 0;                   /* Unlock the TX ring */  }}/*** Calculate the hash code and update the logical address filter** from a list of ethernet multicast addresses.** Big endian crc one liner is mine, all mine, ha ha ha ha!** LANCE calculates its hash codes big endian.*/static void SetMulticastFilter(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  struct dev_mc_list *dmi=dev->mc_list;  char *addrs;  int i, j, bit, byte;  u16 hashcode;  s32 crc, poly = CRC_POLYNOMIAL_BE;  if (dev->flags & IFF_ALLMULTI) {         /* Set all multicast bits */    for (i=0; i<(HASH_TABLE_LEN>>3); i++) {      lp->init_block.mcast_table[i] = (char)0xff;    }  } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -