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

📄 nmclan_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (link->open) {	  nmclan_reset(dev);	  netif_device_attach(dev);	}      }      break;    case CS_EVENT_RESET_REQUEST:      return 1;      break;  }  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 = netdev_priv(dev);#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;  pcmcia_access_configuration_register(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;  pcmcia_access_configuration_register(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);  pcmcia_access_configuration_register(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(lp, dev->base_addr, dev->dev_addr);  mace_write(lp, 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){  kio_addr_t ioaddr = dev->base_addr;  mace_private *lp = netdev_priv(dev);  dev_link_t *link = &lp->link;  if (!DEV_OK(link))    return -ENODEV;  link->open++;  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){  kio_addr_t ioaddr = dev->base_addr;  mace_private *lp = netdev_priv(dev);  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);  return 0;} /* mace_close */static void netdev_get_drvinfo(struct net_device *dev,			       struct ethtool_drvinfo *info){	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);}#ifdef PCMCIA_DEBUGstatic u32 netdev_get_msglevel(struct net_device *dev){	return pc_debug;}static void netdev_set_msglevel(struct net_device *dev, u32 level){	pc_debug = level;}#endif /* PCMCIA_DEBUG */static struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,#ifdef PCMCIA_DEBUG	.get_msglevel		= netdev_get_msglevel,	.set_msglevel		= netdev_set_msglevel,#endif /* PCMCIA_DEBUG */};/* ----------------------------------------------------------------------------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 = netdev_priv(dev);  dev_link_t *link = &lp->link;  printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);#if RESET_ON_TIMEOUT  printk("resetting card\n");  pcmcia_reset_card(link->handle, NULL);#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 = netdev_priv(dev);  kio_addr_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 irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs){  struct net_device *dev = (struct net_device *) dev_id;  mace_private *lp = netdev_priv(dev);  kio_addr_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 IRQ_NONE;  }  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 IRQ_NONE;  }  if (!netif_device_present(dev)) {    DEBUG(2, "%s: interrupt from dead card\n", dev->name);    return IRQ_NONE;  }  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));  return IRQ_HANDLED;} /* mace_interrupt *//* ----------------------------------------------------------------------------mace_rx	Receives packets.---------------------------------------------------------------------------- */static int mace_rx(struct net_device *dev, unsigned char RxCnt){  mace_private *lp = netdev_priv(dev);  kio_addr_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;        /* Auto Strip is off, always subtract 4 */      struct sk_buff *skb;      lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV);        /* runt packet count */      lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV);        /* rcv collision count */      DEBUG(3, "    receiving packet size 0x%X rx_status"

⌨️ 快捷键说明

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