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

📄 ne2000.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
  sc = ne_device_for_irno (irq->name);  if (sc != NULL)    outport_byte (sc->port + IMR, 0);}/* Return whether NE2000 interrupts are on.  */static intne_interrupt_is_on (const rtems_irq_connect_data *irq){  return BSP_irq_enabled_at_i8259s (irq->name);}/* Initialize the NE2000 hardware.  */static voidne_init_hardware (struct ne_softc *sc){  unsigned int port = sc->port;  int i;#ifdef DEBUG_NE2000  printk ("ne_init_hardware()\n");#endif  /* Initialize registers.  */  /* Set interface for page 0, Remote DMA complete, Stopped */  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);  /* Set FIFO threshold to 8, No auto-init Remote DMA, byte order=80x86 */  /* byte-wide DMA xfers */  if (sc->byte_transfers)    outport_byte (port + DCR, MSK_FT10 | MSK_BMS);  /* word-wide DMA xfers */  else    outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);  /* Clear Remote Byte Count Registers */  outport_byte (port + RBCR0, 0);  outport_byte (port + RBCR1, 0);  /* For the moment, don't store incoming packets in memory. */  outport_byte (port + RCR, MSK_MON);  /* Place NIC in internal loopback mode */  outport_byte (port + TCR, MSK_LOOP);  /* Initialize transmit/receive (ring-buffer) Page Start */  outport_byte (port + TPSR, NE_FIRST_TX_PAGE);  outport_byte (port + PSTART, NE_FIRST_RX_PAGE);  /* Initialize Receiver (ring-buffer) Page Stop and Boundry */  outport_byte (port + PSTOP, NE_STOP_PAGE);  outport_byte (port + BNRY, NE_STOP_PAGE - 1);  /* Clear all interrupts */  outport_byte (port + ISR, 0xff);  /* Disable all interrupts */  outport_byte (port + IMR, 0);  /* Program Command Register for page 1 */  outport_byte (port + CMDR, MSK_PG1 | MSK_RD2 | MSK_STP);  /* Set the Ethernet hardware address.  */  for (i = 0; i < ETHER_ADDR_LEN; ++i)    outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);  /* Set Current Page pointer to next_packet */  outport_byte (port + CURR, NE_FIRST_RX_PAGE);  /* Clear the multicast address.  */  for (i = 0; i < MARsize; ++i)    outport_byte (port + MAR + i, 0);  /* Set page 0 registers */  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);  /* accept broadcast */  outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));  /* Start interface */  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);  /* Take interface out of loopback */  outport_byte (port + TCR, 0);}/* Set up interrupts.*/static voidne_init_irq_handler(int irno){  rtems_irq_connect_data irq;#ifdef DEBUG_NE  printk("ne_init_irq_handler(%d)\n", irno);#endif  irq.name = irno;  irq.hdl = (rtems_irq_hdl)ne_interrupt_handler;  irq.on = ne_interrupt_on;  irq.off = ne_interrupt_off;  irq.isOn = ne_interrupt_is_on;  if (!BSP_install_rtems_irq_handler (&irq))    rtems_panic ("Can't attach NE interrupt handler for irq %d\n", irno);}/* The NE2000 packet receive daemon.  This task is started when the   NE2000 driver is initialized.  */#ifdef DEBUG_NEstatic int ccc = 0; /* experinent! */#endifstatic voidne_rx_daemon (void *arg){  struct ne_softc *sc = (struct ne_softc *) arg;  struct ifnet *ifp = &sc->arpcom.ac_if;  unsigned int port = sc->port;  while (1)  {    rtems_event_set events;    /* Wait for the interrupt handler to tell us that there is a       packet ready to receive.  */    rtems_bsdnet_event_receive (INTERRUPT_EVENT,                                RTEMS_WAIT | RTEMS_EVENT_ANY,                                RTEMS_NO_TIMEOUT,                                &events);    /* Don't let the device interrupt us now.  */    outport_byte (port + IMR, 0);    while (1)    {      unsigned char startpage, currpage;      unsigned short len;      unsigned char next, stat, cnt1, cnt2;      struct mbuf *m;      unsigned char *p;      int startaddr;      int toend;      struct ether_header *eh;      struct ne_ring hdr; /* ring buffer header */      int reset;      inport_byte (port + BNRY, startpage);      outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);      inport_byte (port + CURR, currpage);      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);      ++startpage;      if (startpage >= NE_STOP_PAGE)        startpage = NE_FIRST_RX_PAGE;      if (startpage == currpage)        break;#ifdef DEBUG_NE2000      printk ("ne_rx_daemon: start page %x; current page %x\n",              startpage, currpage);#endif      reset = 0;      /* Read the buffer header */      startaddr = startpage * NE_PAGE_SIZE;      ne_read_data(sc, startaddr, sizeof(hdr), (unsigned char *)&hdr);      next = hdr.next;      if (next >= NE_STOP_PAGE)        next = NE_FIRST_RX_PAGE;      /* check packet length */      len = hdr.count;      if (currpage < startpage)        cnt1 = currpage + (NE_STOP_PAGE - NE_FIRST_RX_PAGE) - startpage;      else        cnt1 = currpage - startpage;      cnt2 = len / NE_PAGE_SIZE;      if (len % NE_PAGE_SIZE)        cnt2++;      if (cnt1 < cnt2)      {#ifdef DEBUG_NE        printk("(%x<%x:%x)", cnt1, cnt2, len);/*        printk("start page 0x%x; current page 0x%x\n",                startpage, currpage);        printk("cnt1 < cnt2 (0x%x, 0x%x); len 0x%x\n",                cnt1, cnt2, len);*/#endif        reset = 1;      }      if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) ||          len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) ||          len > MCLBYTES)      {#ifdef DEBUG_NE        printk("(%x)", len);/*        printk("start page 0x%x; current page 0x%x\n",                startpage, currpage);        printk("len out of range: 0x%x\n", len);        printk("stat: 0x%x, next: 0x%x\n", hdr.rsr, hdr.next);*/#endif        reset = 1;      }#ifdef DEBUG_NE      if (++ccc == 100)      { ccc = 0; reset = 1;        printk("T");      }#endif      /* reset interface */      if (reset)      {        ne_reset(sc);        goto Next;      }      stat = hdr.rsr;      /* The first four bytes of the length are the buffer header.  */      len -= sizeof(struct ne_ring);      startaddr += sizeof(struct ne_ring);      MGETHDR (m, M_WAIT, MT_DATA);      MCLGET (m, M_WAIT);      m->m_pkthdr.rcvif = ifp;      p = mtod (m, unsigned char *);      m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);      toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr;      if (toend < len)      {        ne_read_data (sc, startaddr, toend, p);        p += toend;        len -= toend;        startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE;      }      if (len > 0)        ne_read_data (sc, startaddr, len, p);      eh = mtod (m, struct ether_header *);      m->m_data += sizeof (struct ether_header);#ifdef DEBUG_NE  /* printk("[r%d]", hdr.count - sizeof(hdr)); */  printk("<");#endif      ether_input (ifp, eh, m);      ++sc->stats.rx_packets;      outport_byte (port + BNRY, next - 1);    }    if (sc->overrun) {      outport_byte (port + ISR, MSK_OVW);      outport_byte (port + TCR, 0);      if (sc->resend)        outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);      sc->resend = 0;      sc->overrun = 0;    }  Next:    /* Reenable device interrupts.  */    outport_byte (port + IMR, NE_INTERRUPTS);  }}/* Load an NE2000 packet onto the device.  */static voidne_loadpacket (struct ne_softc *sc, struct mbuf *m){  unsigned int port = sc->port;  unsigned int dport = port + DATAPORT;  struct mbuf *mhold = m;  int leftover;  unsigned char leftover_data;  int timeout;  int send_cnt = 0;#ifdef DEBUG_NE2000  printk ("Uploading NE2000 packet\n");#endif  /* Reset remote DMA complete flag.  */  outport_byte (port + ISR, MSK_RDC);  /* Write out the count.  */  outport_byte (port + RBCR0, m->m_pkthdr.len);  outport_byte (port + RBCR1, m->m_pkthdr.len >> 8);  sc->sendlen[sc->nextavail] = m->m_pkthdr.len;  /* Tell the device which address we want to write to.  */  outport_byte (port + RSAR0, 0);  outport_byte (port + RSAR1,                NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES));  /* Set up the write.  */  outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA);  /* Transfer the mbuf chain to device memory.  NE2000 devices require     that the data be transferred as words, so we need to handle odd     length mbufs.  Never occurs if we force byte transfers. */  leftover = 0;  leftover_data = '\0';  for (; m != NULL; m = m->m_next) {    int len;    unsigned char *data;    len = m->m_len;    if (len == 0)      continue;    data = mtod (m, unsigned char *);    if (leftover) {      unsigned char next;      /* Data left over from previous mbuf in chain.  */      next = *data++;      --len;      outport_word (dport, leftover_data | (next << 8));      send_cnt += 2;      leftover = 0;    }    /* If using byte transfers, len always ends up as zero so       there are no leftovers. */    if (sc->byte_transfers)      while (len > 0) {        outport_byte (dport, *data++);        len--;      }    else      while (len > 1) {        outport_word (dport, data[0] | (data[1] << 8));        data += 2;        len -= 2;        send_cnt += 2;      }    if (len > 0)      {        leftover = 1;        leftover_data = *data++;      }  }  if (leftover)  {    outport_word (dport, leftover_data);    send_cnt += 2;  }#ifdef DEBUG_NE  /* printk("{l%d|%d}", send_cnt, sc->nextavail); */  printk("v");#endif  m_freem (mhold);  /* Wait for the device to complete accepting the data, with a     limiting counter so that we don't wait too long.  */  for (timeout = 0; timeout < 100; ++timeout)    {      unsigned char status;      inport_byte (port + ISR, status);#ifdef DEBUG_NE2000      if ((status &~ MSK_RDC) != 0)        printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n",                status);#endif      if ((status & MSK_RDC) != 0) {        outport_byte (port + ISR, MSK_RDC);        break;      }    }  if (timeout >= 100)    printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n");  ++sc->nextavail;  if (sc->nextavail == NE_TX_BUFS)    sc->nextavail = 0;}/* Tell the NE2000 to transmit a buffer whose contents we have already   loaded onto the device.  */static voidne_transmit (struct ne_softc *sc){  struct ifnet *ifp = &sc->arpcom.ac_if;  unsigned int port = sc->port;  int len;#ifdef DEBUG_NE2000  printk ("Transmitting NE2000 packet\n");#endif  len = sc->sendlen[sc->nextsend];  if (len < ET_MINLEN)    len = ET_MINLEN;  outport_byte (port + TBCR0, len);

⌨️ 快捷键说明

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