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

📄 nmclan_cs.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
  }  return 0;} /* nmclan_event *//* ----------------------------------------------------------------------------nmclan_reset	Reset and restore all of the Xilinx and MACE registers.---------------------------------------------------------------------------- */static void nmclan_reset(struct net_device *dev){  mace_private *lp = dev->priv;#if RESET_XILINX  dev_link_t *link = &lp->link;  conf_reg_t reg;  u_long OrigCorValue;   /* Save original COR value */  reg.Function = 0;  reg.Action = CS_READ;  reg.Offset = CISREG_COR;  reg.Value = 0;  CardServices(AccessConfigurationRegister, link->handle, &reg);  OrigCorValue = reg.Value;  /* Reset Xilinx */  reg.Action = CS_WRITE;  reg.Offset = CISREG_COR;  DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",	OrigCorValue);  reg.Value = COR_SOFT_RESET;  CardServices(AccessConfigurationRegister, link->handle, &reg);  /* Need to wait for 20 ms for PCMCIA to finish reset. */  /* Restore original COR configuration index */  reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);  CardServices(AccessConfigurationRegister, link->handle, &reg);  /* Xilinx is now completely reset along with the MACE chip. */  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;#endif /* #if RESET_XILINX */  /* Xilinx is now completely reset along with the MACE chip. */  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;  /* Reinitialize the MACE chip for operation. */  mace_init(dev->base_addr, dev->dev_addr);  mace_write(dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);  /* Restore the multicast list and enable TX and RX. */  restore_multicast_list(dev);} /* nmclan_reset *//* ----------------------------------------------------------------------------mace_config	[Someone tell me what this is supposed to do?  Is if_port a defined	standard?  If so, there should be defines to indicate 1=10Base-T,	2=10Base-2, etc. including limited automatic detection.]---------------------------------------------------------------------------- */static int mace_config(struct net_device *dev, struct ifmap *map){  if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {    if (map->port <= 2) {      dev->if_port = map->port;      printk(KERN_INFO "%s: switched to %s port\n", dev->name,	     if_names[dev->if_port]);    } else      return -EINVAL;  }  return 0;} /* mace_config *//* ----------------------------------------------------------------------------mace_open	Open device driver.---------------------------------------------------------------------------- */static int mace_open(struct net_device *dev){  ioaddr_t ioaddr = dev->base_addr;  mace_private *lp = dev->priv;  dev_link_t *link = &lp->link;  if (!DEV_OK(link))    return -ENODEV;  link->open++;  MOD_INC_USE_COUNT;  MACEBANK(0);  netif_start_queue(dev);  nmclan_reset(dev);  return 0; /* Always succeed */} /* mace_open *//* ----------------------------------------------------------------------------mace_close	Closes device driver.---------------------------------------------------------------------------- */static int mace_close(struct net_device *dev){  ioaddr_t ioaddr = dev->base_addr;  mace_private *lp = dev->priv;  dev_link_t *link = &lp->link;  DEBUG(2, "%s: shutting down ethercard.\n", dev->name);  /* Mask off all interrupts from the MACE chip. */  outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);  link->open--;  netif_stop_queue(dev);  if (link->state & DEV_STALE_CONFIG)    mod_timer(&link->release, jiffies + HZ/20);  MOD_DEC_USE_COUNT;  return 0;} /* mace_close */static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	u32 ethcmd;	/* dev_ioctl() in ../../net/core/dev.c has already checked	   capable(CAP_NET_ADMIN), so don't bother with that here.  */	if (get_user(ethcmd, (u32 *)useraddr))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		strcpy (info.driver, DRV_NAME);		strcpy (info.version, DRV_VERSION);		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);		if (copy_to_user (useraddr, &info, sizeof (info)))			return -EFAULT;		return 0;	}#ifdef PCMCIA_DEBUG	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = pc_debug;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		pc_debug = edata.data;		return 0;	}#endif	default:		break;	}	return -EOPNOTSUPP;}static int smc91c92_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	switch (cmd) {	case SIOCETHTOOL:		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);	default:		return -EOPNOTSUPP;	}	return 0;}/* ----------------------------------------------------------------------------mace_start_xmit	This routine begins the packet transmit function.  When completed,	it will generate a transmit interrupt.	According to /usr/src/linux/net/inet/dev.c, if _start_xmit	returns 0, the "packet is now solely the responsibility of the	driver."  If _start_xmit returns non-zero, the "transmission	failed, put skb back into a list."---------------------------------------------------------------------------- */static void mace_tx_timeout(struct net_device *dev){  mace_private *lp = (mace_private *)dev->priv;  dev_link_t *link = &lp->link;  printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);#if RESET_ON_TIMEOUT  printk("resetting card\n");  CardServices(ResetCard, link->handle);#else /* #if RESET_ON_TIMEOUT */  printk("NOT resetting card\n");#endif /* #if RESET_ON_TIMEOUT */  dev->trans_start = jiffies;  netif_wake_queue(dev);}static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev){  mace_private *lp = (mace_private *)dev->priv;  ioaddr_t ioaddr = dev->base_addr;  netif_stop_queue(dev);  DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n",	dev->name, (long)skb->len);#if (!TX_INTERRUPTABLE)  /* Disable MACE TX interrupts. */  outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT,    ioaddr + AM2150_MACE_BASE + MACE_IMR);  lp->tx_irq_disabled=1;#endif /* #if (!TX_INTERRUPTABLE) */  {    /* This block must not be interrupted by another transmit request!       mace_tx_timeout will take care of timer-based retransmissions from       the upper layers.  The interrupt handler is guaranteed never to       service a transmit interrupt while we are in here.    */    lp->linux_stats.tx_bytes += skb->len;    lp->tx_free_frames--;    /* WARNING: Write the _exact_ number of bytes written in the header! */    /* Put out the word header [must be an outw()] . . . */    outw(skb->len, ioaddr + AM2150_XMT);    /* . . . and the packet [may be any combination of outw() and outb()] */    outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1);    if (skb->len & 1) {      /* Odd byte transfer */      outb(skb->data[skb->len-1], ioaddr + AM2150_XMT);    }    dev->trans_start = jiffies;#if MULTI_TX    if (lp->tx_free_frames > 0)      netif_start_queue(dev);#endif /* #if MULTI_TX */  }#if (!TX_INTERRUPTABLE)  /* Re-enable MACE TX interrupts. */  lp->tx_irq_disabled=0;  outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR);#endif /* #if (!TX_INTERRUPTABLE) */  dev_kfree_skb(skb);  return 0;} /* mace_start_xmit *//* ----------------------------------------------------------------------------mace_interrupt	The interrupt handler.---------------------------------------------------------------------------- */static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs){  mace_private *lp = (mace_private *)dev_id;  struct net_device *dev = &lp->dev;  ioaddr_t ioaddr = dev->base_addr;  int status;  int IntrCnt = MACE_MAX_IR_ITERATIONS;  if (dev == NULL) {    DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n",	  irq);    return;  }  if (lp->tx_irq_disabled) {    printk(      (lp->tx_irq_disabled?       KERN_NOTICE "%s: Interrupt with tx_irq_disabled "       "[isr=%02X, imr=%02X]\n":        KERN_NOTICE "%s: Re-entering the interrupt handler "       "[isr=%02X, imr=%02X]\n"),      dev->name,      inb(ioaddr + AM2150_MACE_BASE + MACE_IR),      inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)    );    /* WARNING: MACE_IR has been read! */    return;  }  if (!netif_device_present(dev)) {    DEBUG(2, "%s: interrupt from dead card\n", dev->name);    goto exception;  }  do {    /* WARNING: MACE_IR is a READ/CLEAR port! */    status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR);    DEBUG(3, "mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);    if (status & MACE_IR_RCVINT) {      mace_rx(dev, MACE_MAX_RX_ITERATIONS);    }    if (status & MACE_IR_XMTINT) {      unsigned char fifofc;      unsigned char xmtrc;      unsigned char xmtfs;      fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC);      if ((fifofc & MACE_FIFOFC_XMTFC)==0) {	lp->linux_stats.tx_errors++;	outb(0xFF, ioaddr + AM2150_XMT_SKIP);      }      /* Transmit Retry Count (XMTRC, reg 4) */      xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC);      if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++;      lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC);      if (        (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) &        MACE_XMTFS_XMTSV /* Transmit Status Valid */      ) {	lp->mace_stats.xmtsv++;	if (xmtfs & ~MACE_XMTFS_XMTSV) {	  if (xmtfs & MACE_XMTFS_UFLO) {	    /* Underflow.  Indicates that the Transmit FIFO emptied before	       the end of frame was reached. */	    lp->mace_stats.uflo++;	  }	  if (xmtfs & MACE_XMTFS_LCOL) {	    /* Late Collision */	    lp->mace_stats.lcol++;	  }	  if (xmtfs & MACE_XMTFS_MORE) {	    /* MORE than one retry was needed */	    lp->mace_stats.more++;	  }	  if (xmtfs & MACE_XMTFS_ONE) {	    /* Exactly ONE retry occurred */	    lp->mace_stats.one++;	  }	  if (xmtfs & MACE_XMTFS_DEFER) {	    /* Transmission was defered */	    lp->mace_stats.defer++;	  }	  if (xmtfs & MACE_XMTFS_LCAR) {	    /* Loss of carrier */	    lp->mace_stats.lcar++;	  }	  if (xmtfs & MACE_XMTFS_RTRY) {	    /* Retry error: transmit aborted after 16 attempts */	    lp->mace_stats.rtry++;	  }        } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */      } /* if (xmtfs & MACE_XMTFS_XMTSV) */      lp->linux_stats.tx_packets++;      lp->tx_free_frames++;      netif_wake_queue(dev);    } /* if (status & MACE_IR_XMTINT) */    if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {      if (status & MACE_IR_JAB) {        /* Jabber Error.  Excessive transmit duration (20-150ms). */        lp->mace_stats.jab++;      }      if (status & MACE_IR_BABL) {        /* Babble Error.  >1518 bytes transmitted. */        lp->mace_stats.babl++;      }      if (status & MACE_IR_CERR) {	/* Collision Error.  CERR indicates the absence of the	   Signal Quality Error Test message after a packet	   transmission. */        lp->mace_stats.cerr++;      }      if (status & MACE_IR_RCVCCO) {        /* Receive Collision Count Overflow; */        lp->mace_stats.rcvcco++;      }      if (status & MACE_IR_RNTPCO) {        /* Runt Packet Count Overflow */        lp->mace_stats.rntpco++;      }      if (status & MACE_IR_MPCO) {        /* Missed Packet Count Overflow */        lp->mace_stats.mpco++;      }    } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */  } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));exception:  return;} /* mace_interrupt *//* ----------------------------------------------------------------------------mace_rx	Receives packets.---------------------------------------------------------------------------- */static int mace_rx(struct net_device *dev, unsigned char RxCnt){  mace_private *lp = (mace_private *)dev->priv;  ioaddr_t ioaddr = dev->base_addr;  unsigned char rx_framecnt;  unsigned short rx_status;  while (    ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) &&    (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */    (RxCnt--)  ) {    rx_status = inw(ioaddr + AM2150_RCV);    DEBUG(3, "%s: in mace_rx(), framecnt 0x%X, rx_status"	  " 0x%X.\n", dev->name, rx_framecnt, rx_status);    if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */      lp->linux_stats.rx_errors++;      if (rx_status & MACE_RCVFS_OFLO) {        lp->mace_stats.oflo++;      }      if (rx_status & MACE_RCVFS_CLSN) {        lp->mace_stats.clsn++;      }      if (rx_status & MACE_RCVFS_FRAM) {	lp->mace_stats.fram++;      }      if (rx_status & MACE_RCVFS_FCS) {        lp->mace_stats.fcs++;      }    } else {      short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4;

⌨️ 快捷键说明

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