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

📄 depca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		       &lp->rx_ring[i].base);		writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length);		lp->rx_buff[i] = lp->sh_mem + offset;	}	for (i = 0; i <= lp->txRingMask; i++) {		offset = lp->buffs_offset + (i + lp->rxRingMask+1)*TX_BUFF_SZ;		writel((lp->device_ram_start + offset) & 0x00ffffff,	               &lp->tx_ring[i].base);		lp->tx_buff[i] = lp->sh_mem + offset;	}	/* Set up the initialization block */	lp->init_block.rx_ring = (lp->device_ram_start + lp->rx_ring_offset) | lp->rx_rlen;	lp->init_block.tx_ring = (lp->device_ram_start + lp->tx_ring_offset) | lp->tx_rlen;	SetMulticastFilter(dev);	for (i = 0; i < ETH_ALEN; i++) {		lp->init_block.phys_addr[i] = dev->dev_addr[i];	}	lp->init_block.mode = 0x0000;            /* Enable the Tx and Rx */}static void depca_tx_timeout (struct net_device *dev){	u_long ioaddr = dev->base_addr;	printk ("%s: transmit timed out, status %04x, resetting.\n",		dev->name, inw (DEPCA_DATA));	STOP_DEPCA;	depca_init_ring (dev);	LoadCSRs (dev);	dev->trans_start = jiffies;	netif_wake_queue (dev);	InitRestartDepca (dev);}/* ** Writes a socket buffer to TX descriptor ring and starts transmission */static int depca_start_xmit (struct sk_buff *skb, struct net_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 (skb->len < 1)		goto out;	netif_stop_queue (dev);	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)			netif_start_queue (dev);	} else		status = -1;out:	return status;}/*** The DEPCA interrupt handler. */static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs){	struct net_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);		return;	}	lp = (struct depca_private *) dev->priv;	ioaddr = dev->base_addr;	spin_lock (&lp->lock);	/* 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);	/* Any resources available? */	if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {		netif_wake_queue (dev);	}	/* Unmask the DEPCA board interrupts and turn off the LED */	nicsr = (nicsr & ~IM & ~LED);	outb (nicsr, DEPCA_NICSR);	spin_unlock (&lp->lock);}static intdepca_rx(struct net_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) - 4;	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_buff[lp->rx_old], len);	    memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len-len);	  } else {                          /* Linear buffer */	    memcpy_fromio(buf, lp->rx_buff[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 net_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 net_device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  s16 nicsr;  u_long ioaddr = dev->base_addr;  netif_stop_queue(dev);  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 net_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->device_ram_start, DEPCA_DATA);  outw(CSR2, DEPCA_ADDR);                /* initialisation block address MSW */  outw((u16)(lp->device_ram_start >> 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 net_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(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, virt_to_phys(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, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));    status = -1;  }  return status;}static struct net_device_stats *depca_get_stats(struct net_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 net_device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;    if (dev) {    netif_stop_queue(dev);    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. */    netif_start_queue(dev);           /* 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 net_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++) {

⌨️ 快捷键说明

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