[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

pc386/i386ex ne2000 drivers



   Date:	Fri, 06 Aug 1999 12:09:33 -0700
   From: "erik.ivanenko" <erik.ivanenko at utoronto.ca>

   The ne2k driver I use is quite old.  It did originally appear with the pc386
   BSP.  I altered it slightly so that bootp would work properly.  The latest
   incarnation of the driver does not work at all on my card:

   PCM 3660 PC104 version.  Chipset = RTL8010AS

   It does not even get the ethernet address from the board correctly... bootpc
   reports that it is using a hw address of FF:FF:FF:FF:FF:FF.

   There were quite a few changes to the code.  Does anyone recall what bugs were
   being addressed by the changes?

   I wish I could tell you what version I use, but it was back when there was
   only a "network" subdirectory.  I submitted a patch to make ne2k work with
   bootp.  That is that last change I was aware of,  since my i386ex BSP sucked
   up and froze that particular incarnation of the ne2k.c code.

Here are the patches I am using against the file in the 19990528 RTEMS
snapshot.  This driver does work for me.  However, I do not use bootp.
I don't think any of these differences would affect the reported
hardware address.

I do vaguely remember your bootp patches, and I thought they were
incorporated into the official distribution.

What sorts of changes are you seeing in the code?  Most of the changes
I'm aware of are the ones Joel mentioned, which added support for byte
transfers as opposed to word transfers.

Ian

Index: ne2000.c
===================================================================
RCS file: /zembu/cvsfiles/devo/rtems/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -p -r1.1.1.1 -r1.2
--- ne2000.c	1999/06/01 18:30:58	1.1.1.1
+++ ne2000.c	1999/06/01 21:29:13	1.2
@@ -156,8 +156,6 @@ struct ne_softc {
 
   /* Set if we have a packet overrun while receiving.  */
   int overrun;
-  /* Set if we should resend after an overrun.  */
-  int resend;
 
   /* Statistics.  */
   struct {
@@ -260,7 +258,7 @@ ne_check_status (struct ne_softc *sc)
 
   while (1) {
     inport_byte (port + ISR, status);
-    if (status == 0)
+    if ((status & ~(MSK_RDC | MSK_RST)) == 0)
       break;
 
 #ifdef DEBUG_NE2000
@@ -271,21 +269,10 @@ ne_check_status (struct ne_softc *sc)
 
     /* Check for incoming packet overwrite.  */
     if (status & MSK_OVW) {
-      unsigned char status2;
-
       ++sc->stats.overruns;
-      outport_byte (port + CMDR, MSK_PG0 | MSK_STP | MSK_RD2);
-      Wait_X_ms (2);
-      outport_byte (port + RBCR0, 0);
-      outport_byte (port + RBCR1, 0);
-      inport_byte (port + ISR, status2);
-      status |= status2 & (MSK_PTX | MSK_TXE);
-      outport_byte (port + TCR, MSK_LOOP);
-      outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
+      outport_byte (port + ISR, MSK_OVW);
       sc->overrun = 1;
-      if ((status & (MSK_PTX | MSK_TXE)) == 0)
-	sc->resend = 1;
-      rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
+      rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);      
     }
 
     /* Check for transmitted packet.  The transmit daemon may now be
@@ -384,7 +371,7 @@ ne_init_hardware (struct ne_softc *sc)
 {
   unsigned int port = sc->port;
   int i;
-  rtems_irq_connect_data irq;
+  unsigned char rcr;
 
 #ifdef DEBUG_NE2000
   printk ("ne_init_hardware\n");
@@ -411,9 +398,10 @@ ne_init_hardware (struct ne_softc *sc)
   outport_byte (port + PSTART, NE_FIRST_RX_PAGE);
   outport_byte (port + BNRY, NE_STOP_PAGE - 1);
 
-  /* Set the Ethernet hardware address.  */
-
+  /* Switch to page 1 registers.   */
   outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
+
+  /* Set the Ethernet hardware address.  */
   for (i = 0; i < ETHER_ADDR_LEN; ++i)
     outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);
 
@@ -428,29 +416,25 @@ ne_init_hardware (struct ne_softc *sc)
   for (i = 0; i < MARsize; ++i)
     outport_byte (port + MAR + i, 0);
 
+  /* Start receiving into the first receive buffer.  */
   outport_byte (port + CURR, NE_FIRST_RX_PAGE);
 
+  /* Switch back to page 0 registers.  */
   outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
 
-  /* Put the device on line.  */
-  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
-
-  /* Set up interrupts.  */
-
-  irq.name = sc->irno;
-  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",
-		 sc->irno);
-
   /* Prepare to receive packets.  */
-
   outport_byte (port + TCR, 0);
-  outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));
+
+  rcr = 0;
+  if (sc->accept_broadcasts)
+    rcr |= MSK_AB;
+  /* FIXME: For multicast packets, we need to set MSK_AM.  */
+  if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) != 0)
+    rcr |= MSK_PRO | MSK_AM | MSK_AR | MSK_SEP;
+  outport_byte (port + RCR, rcr);
+
+  /* Put the device on line.  */
+  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
 }
 
 /* The NE2000 packet receive daemon.  This task is started when the
@@ -570,11 +554,12 @@ ne_rx_daemon (void *arg)
     }
 
     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;
+      /* We got a packet overrun.  Reset the device so that we can be
+         certain of the current status.  This will lose any packet
+         currently being transmitted, but we're probably in trouble
+         anyhow.  */
+      ne_stop (sc);
+      ne_init (sc);
       sc->overrun = 0;
     }
 
@@ -818,17 +803,36 @@ ne_init (void *arg)
 {
   struct ne_softc *sc = (struct ne_softc *) arg;
   struct ifnet *ifp = &sc->arpcom.ac_if;
+  int first;
 
+  first = 0;
   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);
+
+    first = 1;
+  }
+
+  sc->inuse = 0;
+  sc->nextavail = 0;
+  sc->nextsend = 0;
+  sc->transmitting = 0;
+
+  ne_init_hardware (sc);
+
+  if (first) {
+    rtems_irq_connect_data irq;
+
+    /* Set up the interrupt handler after we have initialized the
+       hardware.  */
+    irq.name = sc->irno;
+    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",
+		   sc->irno);
   }
 
   ifp->if_flags |= IFF_RUNNING;
@@ -920,7 +924,7 @@ ne_ioctl (struct ifnet *ifp, int command
     /* FIXME: Multicast commands must be added here.  */
 
   default:
-    error = EINVAL;
+    error = EOPNOTSUPP;
     break;
   }