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

📄 ne2000.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
  outport_byte (port + TBCR1, len >> 8);  outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES));  outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);#ifdef DEBUG_NE  /* printk("{s%d|%d}", len, sc->nextsend); */  printk(">");#endif  ++sc->nextsend;  if (sc->nextsend == NE_TX_BUFS)    sc->nextsend = 0;  ++sc->stats.tx_packets;  /* set watchdog timer */  ifp->if_timer = 2;}/* The NE2000 packet transmit daemon.  This task is started when the   NE2000 driver is initialized.  */static voidne_tx_daemon (void *arg){  struct ne_softc *sc = (struct ne_softc *) arg;  unsigned int port = sc->port;  struct ifnet *ifp = &sc->arpcom.ac_if;  while (1) {    rtems_event_set events;    /* Wait for a packet to be ready for sending, or for there to be       room for another packet in the device memory.  */    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,                                RTEMS_EVENT_ANY | RTEMS_WAIT,                                RTEMS_NO_TIMEOUT,                                &events);#ifdef DEBUG_NE2000    printk ("ne_tx_daemon\n");#endif    /* This daemon handles both uploading data onto the device and       telling the device to transmit data which has been uploaded.       These are separate tasks, because while the device is       transmitting one buffer we will upload another.  */    /* Don't let the device interrupt us now.  */    outport_byte (port + IMR, 0);    while (1) {      struct mbuf *m;      /* If the device is not transmitting a packet, and we have         uploaded a packet, tell the device to transmit it.  */      if (! sc->transmitting && sc->inuse > 0) {        sc->transmitting = 1;        ne_transmit (sc);      }      /* If we don't have any more buffers to send, quit now.  */      if (ifp->if_snd.ifq_head == NULL) {        ifp->if_flags &= ~IFF_OACTIVE;        break;      }      /* Allocate a buffer to load data into.  If there are none         available, quit until a buffer has been transmitted.  */      if (sc->inuse >= NE_TX_BUFS)        break;      ++sc->inuse;      IF_DEQUEUE (&ifp->if_snd, m);      if (m == NULL)        panic ("ne_tx_daemon");      ne_loadpacket (sc, m);      /* Check the device status.  It may have finished transmitting         the last packet.  */      ne_check_status(sc, 0);    }    /* Reenable device interrupts.  */    outport_byte (port + IMR, NE_INTERRUPTS);  }}/* Start sending an NE2000 packet.  */static voidne_start (struct ifnet *ifp){  struct ne_softc *sc = ifp->if_softc;#ifdef DEBUG_NE  printk("S");#endif  /* Tell the transmit daemon to wake up and send a packet.  */  rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);  ifp->if_flags |= IFF_OACTIVE;}/* Initialize and start and NE2000.  */static voidne_init (void *arg){  struct ne_softc *sc = (struct ne_softc *) arg;  struct ifnet *ifp = &sc->arpcom.ac_if;#ifdef DEBUG_NE  printk("ne_init()\n");  ne_dump(sc);#endif  /* only once... */  if (sc->tx_daemon_tid == 0)  {    sc->inuse = 0;    sc->nextavail = 0;    sc->nextsend = 0;    sc->transmitting = 0;    ne_init_hardware (sc);    sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc);    sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc);    /* install rtems irq handler */    ne_init_irq_handler(sc->irno);  }  ifp->if_flags |= IFF_RUNNING;}/* Stop an NE2000.  */static voidne_stop (struct ne_softc *sc){  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;  ne_stop_hardware(sc);  sc->inuse = 0;  sc->nextavail = 0;  sc->nextsend = 0;  sc->transmitting = 0;  sc->overrun = 0;  sc->resend = 0;}static voidne_stop_hardware (struct ne_softc *sc){  unsigned int port = sc->port;  int i;  /* Stop everything.  */  outport_byte (port + CMDR, MSK_STP | MSK_RD2);  /* Wait for the interface to stop, using I as a time limit.  */  for (i = 0; i < 5000; ++i)    {      unsigned char status;      inport_byte (port + ISR, status);      if ((status & MSK_RST) != 0)        break;    }}/* reinitializing interface*/static voidne_reset(struct ne_softc *sc){  ne_stop(sc);  ne_init_hardware(sc);  sc->arpcom.ac_if.if_flags |= IFF_RUNNING;  sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;#ifdef DEBUG_NE  printk("*");#endif}#ifdef DEBUG_NE/* show anything about ne*/static voidne_dump(struct ne_softc *sc){  int i;  printk("\nne configuration:\n");  printk("ethernet addr:");  for (i=0; i<ETHER_ADDR_LEN; i++)    printk(" %x", sc->arpcom.ac_enaddr[i]);  printk("\n");  printk("irq = %d\n", sc->irno);  printk("port = 0x%x\n", sc->port);  printk("accept_broadcasts = %d\n", sc->accept_broadcasts);  printk("byte_transfers = %d\n", sc->byte_transfers);}#endif/* Show NE2000 interface statistics.  */static voidne_stats (struct ne_softc *sc){  printf ("    Received packets: %-8lu", sc->stats.rx_packets);  printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets);  printf ("        Receive acks: %-8lu", sc->stats.rx_acks);  printf ("       Transmit acks: %-8lu\n", sc->stats.tx_acks);  printf ("     Packet overruns: %-8lu", sc->stats.overruns);  printf ("        Frame errors: %-8lu\n", sc->stats.rx_frame_errors);  printf ("          CRC errors: %-8lu", sc->stats.rx_crc_errors);  printf ("      Missed packets: %-8lu\n", sc->stats.rx_missed_errors);  printf ("          Interrupts: %-8lu\n", sc->stats.interrupts);}/* NE2000 driver ioctl handler.  */static intne_ioctl (struct ifnet *ifp, int command, caddr_t data){  struct ne_softc *sc = ifp->if_softc;  int error = 0;  switch (command) {  case SIOCGIFADDR:  case SIOCSIFADDR:    error = ether_ioctl (ifp, command, data);    break;  case SIOCSIFFLAGS:    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {    case IFF_RUNNING:      ne_stop (sc);      break;    case IFF_UP:      ne_init (sc);      break;    case IFF_UP | IFF_RUNNING:      ne_stop (sc);      ne_init (sc);      break;    default:      break;    }    break;  case SIO_RTEMS_SHOW_STATS:    ne_stats (sc);    break;    /* FIXME: Multicast commands must be added here.  */  default:    error = EINVAL;    break;  }  return error;}/* * Device timeout/watchdog routine. Entered if the device neglects to *	generate an interrupt after a transmit has been started on it. */static voidne_watchdog(struct ifnet *ifp){  struct ne_softc *sc = ifp->if_softc;  printk("ne2000: device timeout\n");    ifp->if_oerrors++;  ne_reset(sc);}static voidprint_byte(unsigned char b){  printk("%x%x", b >> 4, b & 0x0f);}/* Attach an NE2000 driver to the system.  */intrtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach){  int i;  struct ne_softc *sc;  struct ifnet *ifp;  int mtu;  /* dettach ... */  if (!attach)    return 0;  /* Find a free driver.  */  sc = NULL;  for (i = 0; i < NNEDRIVER; ++i) {    sc = &ne_softc[i];    ifp = &sc->arpcom.ac_if;    if (ifp->if_softc == NULL)      break;  }  if (sc == NULL) {    printf ("Too many NE2000 drivers.\n");    return 0;  }  memset (sc, 0, sizeof *sc);  /* Check whether we do byte-wide or word-wide transfers.  */#ifdef NE2000_BYTE_TRANSFERS  sc->byte_transfers = TRUE;#else  sc->byte_transfers = FALSE;#endif  /* Handle the options passed in by the caller.  */  if (config->mtu != 0)    mtu = config->mtu;  else    mtu = ETHERMTU;  if (config->irno != 0)    sc->irno = config->irno;  else {    /* We use 5 as the default IRQ.  */    sc->irno = 5;  }  if (config->port != 0)    sc->port = config->port;  else {    /* We use 0x300 as the default IO port number.  */    sc->port = 0x300;  }  sc->accept_broadcasts = ! config->ignore_broadcast;  if (config->hardware_address != NULL)    memcpy (sc->arpcom.ac_enaddr, config->hardware_address,            ETHER_ADDR_LEN);  else    {      unsigned char prom[16];      int ia;      /* Read the PROM to get the Ethernet hardware address.  */      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);      if (sc->byte_transfers) {        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS);      }      else {        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);      }      outport_byte (sc->port + RBCR0, 0);      outport_byte (sc->port + RBCR1, 0);      outport_byte (sc->port + RCR, MSK_MON);      outport_byte (sc->port + TCR, MSK_LOOP);      outport_byte (sc->port + IMR, 0);      outport_byte (sc->port + ISR, 0xff);      ne_read_data (sc, 0, sizeof prom, prom);      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);      for (ia = 0; ia < ETHER_ADDR_LEN; ++ia)        sc->arpcom.ac_enaddr[ia] = prom[ia * 2];    }  /* Set up the network interface.  */  ifp->if_softc = sc;  ifp->if_unit = i + 1;  ifp->if_name = "ne";  ifp->if_mtu = mtu;  ifp->if_init = ne_init;  ifp->if_ioctl = ne_ioctl;  ifp->if_watchdog = ne_watchdog;  ifp->if_start = ne_start;  ifp->if_output = ether_output;  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;  if (ifp->if_snd.ifq_maxlen == 0)    ifp->if_snd.ifq_maxlen = ifqmaxlen;  /* Attach the interface.  */  if_attach (ifp);  ether_ifattach (ifp);  printk("network device '%s' <", config->name);  print_byte(sc->arpcom.ac_enaddr[0]);  for (i=1; i<ETHER_ADDR_LEN; i++)  { printk(":");    print_byte(sc->arpcom.ac_enaddr[i]);  }  printk("> initialized on port 0x%x, irq %d\n", sc->port, sc->irno);  return 1;}

⌨️ 快捷键说明

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