Index: c/src/libchip/ChangeLog
===================================================================
--- c/src/libchip/ChangeLog	(revision 774515b753a1a29ab75ed1a6b5684c09f6b7ed15)
+++ c/src/libchip/ChangeLog	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -1,2 +1,14 @@
+2005-10-05  Jiri Gaisler <jiri@gaisler.com>
+            Edvin Catovic <edvin@gaisler.com>
+            Konrad Eisele <konrad@gaisler.com>
+
+	PR 827/bsps
+	* network/Makefile.am, network/open_eth.c, network/open_eth.h: Portion
+	of large update of SPARC BSPs. Includes addition of sis, leon2 and
+	leon3 BSPs, deletion of leon BSP, addition of SMC91111 NIC driver and
+	much more.
+	* network/README.smc91111, network/smc91111.c, network/smc91111.h,
+	network/smc91111config.h, network/smc91111exp.h: New files.
+
 2005-04-28      Jennifer Averett <jennifer.averett@oarcorp.com>
 
Index: c/src/libchip/network/Makefile.am
===================================================================
--- c/src/libchip/network/Makefile.am	(revision 774515b753a1a29ab75ed1a6b5684c09f6b7ed15)
+++ c/src/libchip/network/Makefile.am	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -9,9 +9,10 @@
 LIB = $(ARCH)/$(LIBNAME).a
 
-C_FILES = cs8900.c dec21140.c i82586.c sonic.c if_fxp.c elnk.c open_eth.c
+C_FILES = cs8900.c dec21140.c i82586.c sonic.c if_fxp.c elnk.c open_eth.c \
+          smc91111.c 
 OBJS = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT))
 
 include_libchip_HEADERS = cs8900.h i82586var.h if_fxpvar.h sonic.h if_media.h \
-    mii.h open_eth.h
+    mii.h open_eth.h smc91111.h smc91111exp.h
 
 include $(top_srcdir)/../../../automake/compile.am
@@ -50,5 +51,6 @@
 EXTRA_DIST = README README.cs8900 README.dec21140 README.i82586 \
     README.open_eth README.sonic cs8900.c cs8900.c.bsp dec21140.c \
-    i82586.c if_fxp.c open_eth.c sonic.c
+    i82586.c if_fxp.c open_eth.c sonic.c \
+    smc91111.c 
 
 include $(top_srcdir)/../../../automake/local.am
Index: c/src/libchip/network/README.smc91111
===================================================================
--- c/src/libchip/network/README.smc91111	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
+++ c/src/libchip/network/README.smc91111	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -0,0 +1,15 @@
+#
+#  $Id$
+#
+
+Driver for smc91111 chip  - README
+----------------------------------
+
+The driver for SMC's 91111 ethernet chip.
+
+Each BSP must provide its own attach function.  Examples can be found
+in the SPARC leon2 and leon3 BSPs.  The attach function for the leon3
+BSP is rtems_smc91111_driver_attach_leon3().
+
+Tested on leon2, using the Pender Electronic Design GR-CPCI-AT697 board.
+
Index: c/src/libchip/network/open_eth.c
===================================================================
--- c/src/libchip/network/open_eth.c	(revision 774515b753a1a29ab75ed1a6b5684c09f6b7ed15)
+++ c/src/libchip/network/open_eth.c	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -7,5 +7,5 @@
  *  The license and distribution terms for this file may be
  *  found in found in the file LICENSE in this distribution or at
- *  http://www.rtems.com/license/LICENSE.
+ *  http://www.OARcorp.com/rtems/license.html.
  *
  */
@@ -89,6 +89,4 @@
 #define OETH_SUSPEND_NOTXBUF
  */
-
-#define OETH_RATE_10MHZ
 
 #if (MCLBYTES < RBUF_SIZE)
@@ -117,4 +115,5 @@
     struct MDRX *rxdesc;
     rtems_vector_number vector;
+    unsigned int en100MHz;
 
 
@@ -219,16 +218,12 @@
 
     /* reset PHY and wait for complettion */
-    mii_cr = read_mii(0);
-    mii_cr = 0x3320;
-#ifdef OETH_RATE_10MHZ
-    mii_cr = 0;
-#endif
+    /*
+    */
+    mii_cr = 0x3300;
+    if (!sc->en100MHz) mii_cr = 0;
     write_mii(0, mii_cr | 0x8000); 
     while (read_mii(0) & 0x8000) {}
-    write_mii(20, 0x1422);
-#ifdef OETH_RATE_10MHZ
-    mii_cr = 0;
-#endif
-    write_mii(0, mii_cr); 
+    if (!sc->en100MHz) write_mii(0, 0); 
+    mii_cr = read_mii(0);
     printf("open_eth: driver attached, PHY config : 0x%04x\n", read_mii(0));
 
@@ -484,4 +479,5 @@
 
       /* write buffer descriptor length and status */
+      len_status &= 0x0000ffff;
       len_status |= (len << 16) | (OETH_TX_BD_READY | OETH_TX_BD_CRC);
       dp->regs->xd[dp->tx_ptr].len_status = len_status;
@@ -710,4 +706,5 @@
     sc->txbufs = chip->txd_count;
     sc->rxbufs = chip->rxd_count;
+    sc->en100MHz = chip->en100MHz;
 
 
Index: c/src/libchip/network/open_eth.h
===================================================================
--- c/src/libchip/network/open_eth.h	(revision 774515b753a1a29ab75ed1a6b5684c09f6b7ed15)
+++ c/src/libchip/network/open_eth.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -13,4 +13,5 @@
   unsigned32              txd_count;
   unsigned32              rxd_count;
+  unsigned32              en100MHz;
 } open_eth_configuration_t;
 
Index: c/src/libchip/network/smc91111.c
===================================================================
--- c/src/libchip/network/smc91111.c	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
+++ c/src/libchip/network/smc91111.c	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -0,0 +1,1587 @@
+/*
+ *  $Id$
+ */
+
+#include <rtems.h>
+
+/*
+ *  This driver currently only supports architectures with the old style
+ *  exception processing.  The following checks try to keep this
+ *  from being compiled on systems which can't support this driver.
+ *
+ *  NOTE: As of 28 September 2005, this has only been tested on the SPARC,
+ *        so that is all it is enabled for.
+ */
+
+#if defined(__sparc__)
+  #define SMC91111_SUPPORTED
+#endif
+
+#if defined(SMC91111_SUPPORTED)
+
+#include <bsp.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#define SMC91111_INTERRUPT_EVENT      RTEMS_EVENT_1	/* RTEMS event used by interrupt handler to signal driver tasks. This must not be any of the events used by the network task synchronization. */
+#define SMC91111_START_TRANSMIT_EVENT RTEMS_EVENT_2	/* RTEMS event used to start transmit/receive daemon. This must not be the same as INTERRUPT_EVENT. */
+#define SMC91111_TX_WAIT_EVENT        RTEMS_EVENT_3	/* event to send when tx buffers become available */
+
+/* Set to perms of:
+   0 disables all debug output
+   1 for process debug output
+   2 for added data IO output: get_reg, put_reg
+   4 for packet allocation/free output
+   8 for only startup status, so we can tell we're installed OK
+   16 dump phy read/write 
+   32 precise register dump
+   64 dump packets
+*/
+/*#define DEBUG (-1)*/
+/*#define DEBUG (-1 & ~(16))*/
+#define DEBUG (0) 
+
+#include "smc91111config.h"
+#include <libchip/smc91111.h>
+
+struct lan91cxx_priv_data smc91111;
+
+int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd);
+static cyg_uint16 lan91cxx_read_phy(struct lan91cxx_priv_data *cpd,
+				    cyg_uint8 phyaddr, cyg_uint8 phyreg);
+static void lan91cxx_write_phy(struct lan91cxx_priv_data *cpd,
+			       cyg_uint8 phyaddr, cyg_uint8 phyreg,
+			       cyg_uint16 value);
+static void lan91cxx_start(struct ifnet *ifp);
+static void smc91111_start(struct ifnet *ifp);
+static int smc_probe(struct lan91cxx_priv_data *cpd);
+static void smc91111_stop(struct lan91cxx_priv_data *cpd);
+static void smc91111_init(void *arg);
+static void lan91cxx_finish_sent(struct lan91cxx_priv_data *cpd);
+#if 0
+static int lan91cxx_phy_fixed(struct lan91cxx_priv_data *cpd);
+static void lan91cxx_phy_configure(struct lan91cxx_priv_data *cpd);
+#endif
+
+#define min(l,r) ((l) < (r) ? (l) : (r))
+#define max(l,r) ((l) > (r) ? (l) : (r))
+
+/* \ ------------- Interrupt ------------- \ */
+rtems_isr lan91cxx_interrupt_handler(rtems_vector_number v)
+{
+	struct lan91cxx_priv_data *cpd = &smc91111;
+	unsigned short irq, event;
+	unsigned short oldbase;
+	unsigned short oldpointer;
+	INCR_STAT(cpd, interrupts);
+	DEBUG_FUNCTION();
+
+	HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), oldbase);
+	oldpointer = get_reg(cpd, LAN91CXX_POINTER);
+
+	/* Get the (unmasked) requests */
+	irq = get_reg(cpd, LAN91CXX_INTERRUPT);
+	event = irq & (irq >> 8) & 0xff;
+	if (0 == event)
+		return;
+
+	/*put_reg(cpd, LAN91CXX_INTERRUPT, irq ); *//* ack interrupts */
+
+	if (event & LAN91CXX_INTERRUPT_ERCV_INT) {
+		db_printf("Early receive interrupt");
+	} else if (event & LAN91CXX_INTERRUPT_EPH_INT) {
+		db_printf("ethernet protocol handler failures");
+	} else if (event & LAN91CXX_INTERRUPT_RX_OVRN_INT) {
+		db_printf("receive overrun");
+	} else if (event & LAN91CXX_INTERRUPT_ALLOC_INT) {
+		db_printf("allocation interrupt");
+	} else {
+
+		if (event & LAN91CXX_INTERRUPT_TX_SET) {
+			DEBUG_puts("#tx error\n");
+			db_printf("#*tx irq\n");
+			lan91cxx_finish_sent(cpd);
+			put_reg(cpd, LAN91CXX_INTERRUPT,
+				(irq & 0xff00) | LAN91CXX_INTERRUPT_TX_INT);
+
+			/*rtems_event_send (cpd->txDaemonTid, SMC91111_INTERRUPT_EVENT); */
+			/*put_reg(cpd, LAN91CXX_INTERRUPT, (irq & 0xff00) | LAN91CXX_INTERRUPT_TX_INT); */
+			/*rtems_event_send (cpd->txDaemonTid, SMC91111_TX_WAIT_EVENT); */
+		}
+		if (event & LAN91CXX_INTERRUPT_RCV_INT) {
+			db_printf("#*rx irq\n");
+			rtems_event_send(cpd->rxDaemonTid,
+					 SMC91111_INTERRUPT_EVENT);
+		}
+		if (event &
+		    ~(LAN91CXX_INTERRUPT_TX_SET | LAN91CXX_INTERRUPT_RCV_INT))
+			db_printf("Unknown interrupt\n");
+	}
+	db_printf("out %s\n", __FUNCTION__);
+
+	put_reg(cpd, LAN91CXX_POINTER, oldpointer);
+	HAL_WRITE_UINT16(cpd->base + (LAN91CXX_BS), oldbase);
+}
+
+/* \ ------------- Rx receive ------------- \ */
+
+ /**/
+/* This function is called as a result of the "readpacket()" call.*/
+/* Its job is to actually fetch data for a packet from the hardware once*/
+/* memory buffers have been allocated for the packet.  Note that the buffers*/
+/* may come in pieces, using a mbuf list.  */
+static void lan91cxx_recv(struct lan91cxx_priv_data *cpd, struct mbuf *m)
+{
+	struct ifnet *ifp = &cpd->arpcom.ac_if;
+	struct ether_header *eh;
+	short mlen = 0, plen;
+	char *start;
+	rxd_t *data = NULL, val, lp;
+	struct mbuf *n;
+	lp = 0;
+	dbg_prefix = "<";
+
+	DEBUG_FUNCTION();
+	INCR_STAT(cpd, rx_deliver);
+
+	/* ############ read packet ############ */
+
+	put_reg(cpd, LAN91CXX_POINTER,
+		(LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
+		 LAN91CXX_POINTER_AUTO_INCR));
+	val = get_data(cpd);
+
+	/* packet length (minus header/footer) */
+#ifdef LAN91CXX_32BIT_RX
+	val = CYG_LE32_TO_CPU(val);
+	plen = (val >> 16) - 6;
+#else
+	val = CYG_LE16_TO_CPU(val);
+	plen = get_data(cpd);
+	plen = CYG_LE16_TO_CPU(plen) - 6;
+#endif
+
+	if (LAN91CXX_RX_STATUS_IS_ODD(cpd, val))
+		plen++;
+
+	for (n = m; n; n = n->m_next) {
+#ifdef LAN91CXX_32BIT_RX
+		if (mlen == 2) {
+#if DEBUG & 64
+			db_printf("Appending to last apacket\n");
+#endif
+
+			val = get_data(cpd);
+			*((unsigned short *)data) = (val >> 16) & 0xffff;
+			plen -= 2;
+			data = (rxd_t *) n->m_data;
+			start = (char *)data;
+			mlen = n->m_len;
+			if ((data) && (mlen > 1)) {
+				*((unsigned short *)data)++ = (val & 0xffff);
+				plen -= 2;
+				mlen -= 2;
+			}
+		} else {
+			data = (rxd_t *) n->m_data;
+			start = (char *)data;
+			mlen = n->m_len;
+		}
+#else
+		data = (rxd_t *) n->m_data;
+		start = (char *)data;
+		mlen = n->m_len;
+#endif
+
+		db1_printf("<[packet : mlen 0x%x, plen 0x%x]\n", mlen, plen);
+
+		if (data) {
+			while (mlen >= sizeof(*data)) {
+#ifdef LAN91CXX_32BIT_RX
+				val = get_data(cpd);
+				*((unsigned short *)data)++ =
+				    (val >> 16) & 0xffff;
+				*((unsigned short *)data)++ = (val & 0xffff);
+#else
+				*data++ = get_data(cpd);
+#endif
+				mlen -= sizeof(*data);
+				plen -= sizeof(*data);
+			}
+		} else {	/* must actively discard ie. read it from the chip anyway. */
+			while (mlen >= sizeof(*data)) {
+				(void)get_data(cpd);
+				mlen -= sizeof(*data);
+				plen -= sizeof(*data);
+			}
+		}
+
+#if DEBUG & 64
+		lp = 0;
+		while (((int)start) < ((int)data)) {
+			unsigned char a = *(start++);
+			unsigned char b = *(start++);
+			db64_printf("%02x %02x ", a, b);
+			lp += 2;
+			if (lp >= 16) {
+				db64_printf("\n");
+				lp = 0;
+			}
+		}
+		db64_printf(" \n");
+
+#endif
+	}
+	val = get_data(cpd);	/* Read control word (and potential data) unconditionally */
+#ifdef LAN91CXX_32BIT_RX
+	if (plen & 2) {
+		if (data) {
+			*((unsigned short *)data)++ = (val >> 16) & 0xffff;
+			val <<= 16;
+		}
+	}
+	if (plen & 1)
+		*(unsigned char *)data = val >> 24;
+#else
+	val = CYG_LE16_TO_CPU(val);
+	cp = (unsigned char *)data;
+
+	CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX, "Controlbyte is not for Rx");
+	CYG_ASSERT((1 == mlen) == (0 != LAN91CXX_CONTROLBYTE_IS_ODD(cpd, val)),
+		   "Controlbyte does not match");
+	if (data && (1 == mlen) && LAN91CXX_CONTROLBYTE_IS_ODD(cpd, val)) {
+		cval = val & 0x00ff;	/* last byte contains data */
+		*cp = cval;
+	}
+#endif
+
+	val = get_reg(cpd, LAN91CXX_FIFO_PORTS);
+	if (0x8000 & val) {	/* Then the Rx FIFO is empty */
+		db4_printf
+		    ("<+Rx packet NOT freed, stat is %x (expected %x)\n",
+		     val, cpd->rxpacket);
+	} else {
+		db4_printf("<+Rx packet freed %x (expected %x)\n",
+			   0xff & (val >> 8), cpd->rxpacket);
+	}
+
+	CYG_ASSERT((0xff & (val >> 8)) == cpd->rxpacket,
+		   "Unexpected rx packet");
+
+	/* ############ free packet ############ */
+	/* Free packet */
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);
+
+	dbg_prefix = "";
+
+	/* Remove the mac header. This is different from the NetBSD stack. */
+	eh = mtod(m, struct ether_header *);
+	m->m_data += sizeof(struct ether_header);
+	m->m_len -= sizeof(struct ether_header);
+	m->m_pkthdr.len -= sizeof(struct ether_header);
+
+	ether_input(ifp, eh, m);
+
+}
+
+/* allocate mbuf chain */
+static struct mbuf *smc91111_allocmbufchain(int totlen, struct ifnet *ifp)
+{
+
+	struct mbuf *m, *m0, *newm;
+	int len;
+
+	MGETHDR(m0, M_DONTWAIT, MT_DATA);
+	if (m0 == 0)
+		return (0);
+	m0->m_pkthdr.rcvif = ifp;
+	m0->m_pkthdr.len = totlen;
+	len = MHLEN;
+	m = m0;
+
+	/* This loop goes through and allocates mbufs for all the data we will be copying in.  */
+	while (totlen > 0) {
+		if (totlen >= MINCLSIZE) {
+			MCLGET(m, M_DONTWAIT);
+			if ((m->m_flags & M_EXT) == 0)
+				goto bad;
+			len = MCLBYTES;
+		}
+
+		if (m == m0) {
+			caddr_t newdata = (caddr_t)
+			    ALIGN(m->m_data +
+				  sizeof(struct ether_header)) -
+			    sizeof(struct ether_header);
+			len -= newdata - m->m_data;
+			m->m_data = newdata;
+		}
+
+		m->m_len = len = min(totlen, len);
+
+		totlen -= len;
+		if (totlen > 0) {
+			MGET(newm, M_DONTWAIT, MT_DATA);
+			if (newm == 0)
+				goto bad;
+			len = MLEN;
+			m = m->m_next = newm;
+		}
+	}
+	return (m0);
+
+      bad:
+	m_freem(m0);
+	return (0);
+}
+
+static int readpacket(struct lan91cxx_priv_data *cpd)
+{
+	struct mbuf *m;
+	unsigned short stat, complen;
+	struct ifnet *ifp = &cpd->arpcom.ac_if;
+#ifdef LAN91CXX_32BIT_RX
+	cyg_uint32 val;
+#endif
+
+	DEBUG_FUNCTION();
+
+	/* ############ read packet nr ############ */
+	stat = get_reg(cpd, LAN91CXX_FIFO_PORTS);
+	db1_printf("+LAN91CXX_FIFO_PORTS: 0x%04x\n", stat);
+
+	if (0x8000 & stat) {
+		/* Then the Rx FIFO is empty */
+		db4_printf("!RxEvent with empty fifo\n");
+		return 0;
+	}
+
+	INCR_STAT(cpd, rx_count);
+
+	db4_printf("+Rx packet allocated %x (previous %x)\n",
+		   0xff & (stat >> 8), cpd->rxpacket);
+
+	/* There is an Rx Packet ready */
+	cpd->rxpacket = 0xff & (stat >> 8);
+
+	/* ############ read packet header ############ */
+	/* Read status and (word) length */
+	put_reg(cpd, LAN91CXX_POINTER,
+		(LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
+		 LAN91CXX_POINTER_AUTO_INCR | 0x0000));
+#ifdef LAN91CXX_32BIT_RX
+	val = get_data(cpd);
+	val = CYG_LE32_TO_CPU(val);
+	stat = val & 0xffff;
+	complen = ((val >> 16) & 0xffff) - 6;	/* minus header/footer words */
+#else
+	stat = get_data(cpd);
+	stat = CYG_LE16_TO_CPU(stat);
+	complen = get_data(cpd);
+	complen = CYG_LE16_TO_CPU(len) - 6;	/* minus header/footer words */
+#endif
+
+#ifdef KEEP_STATISTICS
+	if (stat & LAN91CXX_RX_STATUS_ALIGNERR)
+		INCR_STAT(cpd, rx_align_errors);
+	/*if ( stat & LAN91CXX_RX_STATUS_BCAST    ) INCR_STAT(  ); */
+	if (stat & LAN91CXX_RX_STATUS_BADCRC)
+		INCR_STAT(cpd, rx_crc_errors);
+	if (stat & LAN91CXX_RX_STATUS_TOOLONG)
+		INCR_STAT(cpd, rx_too_long_frames);
+	if (stat & LAN91CXX_RX_STATUS_TOOSHORT)
+		INCR_STAT(cpd, rx_short_frames);
+	/*if ( stat & LAN91CXX_RX_STATUS_MCAST    ) INCR_STAT(  ); */
+#endif				/* KEEP_STATISTICS */
+
+	if ((stat & LAN91CXX_RX_STATUS_BAD) == 0) {
+		INCR_STAT(cpd, rx_good);
+		/* Then it's OK */
+
+		if (LAN91CXX_RX_STATUS_IS_ODD(cpd, stat))
+			complen++;
+
+#if DEBUG & 1
+		db_printf("good rx - stat: 0x%04x, len: 0x%04x\n", stat,
+			  complen);
+#endif
+		/* Check for bogusly short packets; can happen in promisc mode: */
+		/* Asserted against and checked by upper layer driver. */
+		if (complen > sizeof(struct ether_header)) {
+			/* then it is acceptable; offer the data to the network stack */
+
+			complen = ((complen + 3) & ~3);
+
+			m = smc91111_allocmbufchain(complen, ifp);
+			{
+				struct mbuf *n = m;
+				db_printf("mbuf-chain:");
+				while (n) {
+					db_printf("[%x:%x]",
+						  (unsigned int)(n->
+								 m_data),
+						  (unsigned int)(n->m_len));
+					n = n->m_next;
+				}
+				db_printf("\n");
+			}
+
+			if (m) {
+				/* fetch packet data into mbuf chain */
+				lan91cxx_recv(cpd, m);
+				return 1;
+			}
+		}
+		/*(sc->funs->eth_drv->recv)(sc, len); */
+	}
+
+	/* Not OK for one reason or another... */
+	db1_printf("!bad rx: stat: 0x%04x, len: 0x%04x\n", stat, complen);
+
+	/* ############ free packet ############ */
+	/* Free packet */
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);
+	return 1;
+
+}
+
+static void smc91111_rxDaemon(void *arg)
+{
+	struct lan91cxx_priv_data *cpd = arg;
+	rtems_event_set events;
+	DEBUG_FUNCTION();
+
+	for (;;) {
+		rtems_bsdnet_event_receive(INTERRUPT_EVENT,
+					   RTEMS_WAIT | RTEMS_EVENT_ANY,
+					   RTEMS_NO_TIMEOUT, &events);
+
+		/* read until read fifo is empty */
+		while (!(get_reg(cpd, LAN91CXX_FIFO_PORTS) & 0x8000)) {
+			readpacket(cpd);
+		}
+	}
+}
+
+/* \ ------------- Tx send ------------- \ */
+
+static void sendpacket(struct ifnet *ifp, struct mbuf *m)
+{
+	struct lan91cxx_priv_data *cpd = ifp->if_softc;
+	int i, len, plen, tcr;
+	struct mbuf *n = m;
+	unsigned short *sdata = NULL;
+	unsigned short ints, control;
+	cyg_uint16 packet, status;
+	dbg_prefix = ">";
+	DEBUG_FUNCTION();
+
+	cpd->txbusy = 1;
+
+	/* Worry about the TX engine stopping. */
+	tcr = get_reg(cpd, LAN91CXX_TCR);
+	if (0 == (LAN91CXX_TCR_TXENA & tcr)) {
+		db1_printf("> ENGINE RESTART: tcr %x\n", tcr);
+		tcr |= LAN91CXX_TCR_TXENA;
+		put_reg(cpd, LAN91CXX_TCR, tcr);
+	}
+
+	/* ############ packet allocation ############ */
+
+	/* Find packet length */
+	plen = 0;
+	while (n) {
+		plen += n->m_len;
+		n = n->m_next;
+	}
+
+	/* Alloc new TX packet */
+	do {
+		put_reg(cpd, LAN91CXX_MMU_COMMAND,
+			LAN91CXX_MMU_alloc_for_tx | ((plen >> 8) & 0x07));
+
+		i = 1024 * 1024;
+		do {
+			status = get_reg(cpd, LAN91CXX_INTERRUPT);
+		} while (0 == (status & LAN91CXX_INTERRUPT_ALLOC_INT)
+			 && (--i > 0));
+		if (i)
+			packet = get_reg(cpd, LAN91CXX_PNR);
+		else
+			packet = 0xffff;
+		db1_printf(">+allocated packet %04x\n", packet);
+
+		packet = packet >> 8;
+		if (packet & 0x80) {
+			/* Hm.. Isn't this a dead end? */
+			db1_printf("Allocation failed! Retrying...\n");
+			continue;
+		}
+	} while (0);
+
+	db4_printf(">+Tx packet allocated %x (previous %x)\n",
+		   packet, cpd->txpacket);
+
+	cpd->txpacket = packet;
+
+	/* ############ assemble packet data ############ */
+
+	/* prepare send */
+	put_reg(cpd, LAN91CXX_PNR, packet);
+	/* Note: Check FIFO state here before continuing? */
+	put_reg(cpd, LAN91CXX_POINTER, LAN91CXX_POINTER_AUTO_INCR | 0x0000);
+	/* Pointer is now set, and the proper bank is selected for */
+	/* data writes. */
+
+	/* Prepare header: */
+	put_data(cpd, CYG_CPU_TO_LE16(0));	/* reserve space for status word */
+	/* packet length (includes status, byte-count and control shorts) */
+	put_data(cpd, CYG_CPU_TO_LE16(0x7FE & (plen + 6)));	/* Always even, always < 15xx(dec) */
+
+	/* Put data into buffer */
+	n = m;
+	while (n) {
+		sdata = (unsigned short *)n->m_data;
+		len = n->m_len;
+
+		CYG_ASSERT((0 == (len & 1)
+			    || !(n->m_next)), "!odd length");
+		CYG_ASSERT(sdata, "!No sg data pointer here");
+
+		while (len >= sizeof(*sdata)) {
+			put_data(cpd, *sdata++);
+			len -= sizeof(*sdata);
+		}
+		n = n->m_next;
+	}
+#if DEBUG & 64
+	n = m;
+	while (n) {
+		int lp = 0;
+		unsigned char *start = (unsigned char *)n->m_data;
+		len = n->m_len;
+		while (len > 0) {
+			unsigned char a = *(start++);
+			unsigned char b = *(start++);
+			db64_printf("%02x %02x ", a, b);
+			lp += 2;
+			if (lp >= 16) {
+				db64_printf("\n");
+				lp = 0;
+			}
+			len -= 2;
+		}
+		n = n->m_next;
+	}
+	db64_printf(" \n");
+#endif
+
+	m_freem(m);
+	CYG_ASSERT(sdata, "!No sg data pointer outside");
+
+	/* Lay down the control short unconditionally at the end. */
+	/* (or it might use random memory contents) */
+	control = 0;
+	if (1 & plen) {
+		/* Need to set ODD flag and insert the data */
+		unsigned char onebyte = *(unsigned char *)sdata;
+		control = onebyte;
+		control |= LAN91CXX_CONTROLBYTE_ODD;
+	}
+	control |= LAN91CXX_CONTROLBYTE_CRC;	/* Just in case... */
+	put_data(cpd, CYG_CPU_TO_LE16(control));
+
+	/* ############ start transmit ############ */
+
+	/* Ack TX empty int and unmask it. */
+	ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00;
+	put_reg(cpd, LAN91CXX_INTERRUPT,
+		ints | LAN91CXX_INTERRUPT_TX_EMPTY_INT);
+	put_reg(cpd, LAN91CXX_INTERRUPT, ints | LAN91CXX_INTERRUPT_TX_INT_M);	/* notify on error only (Autorelease) */
+
+	/* Enqueue the packet */
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_enq_packet);
+
+	ints = get_reg(cpd, LAN91CXX_INTERRUPT);
+	db1_printf(">END: ints at TX: %04x\n", ints);
+	dbg_prefix = "";
+}
+
+void smc91111_txDaemon(void *arg)
+{
+	struct lan91cxx_priv_data *cpd = arg;
+	struct ifnet *ifp = &cpd->arpcom.ac_if;
+	struct mbuf *m;
+	rtems_event_set events;
+	DEBUG_FUNCTION();
+
+	for (;;) {
+		/*
+		 * Wait for packet
+		 */
+
+		rtems_bsdnet_event_receive
+		    (SMC91111_START_TRANSMIT_EVENT,
+		     RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
+
+		/*IF_DEQUEUE (&ifp->if_snd, m);
+		   if (m) {
+		   sendpacket (ifp, m);
+		   } */
+
+		for (;;) {
+			IF_DEQUEUE(&ifp->if_snd, m);
+			if (!m)
+				break;
+			sendpacket(ifp, m);
+		}
+		ifp->if_flags &= ~IFF_OACTIVE;
+
+	}
+
+}
+
+/* start transmit */
+static void smc91111_start(struct ifnet *ifp)
+{
+	struct lan91cxx_priv_data *cpd = ifp->if_softc;
+
+	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+		return;
+
+	rtems_event_send(cpd->txDaemonTid, START_TRANSMIT_EVENT);
+	ifp->if_flags |= IFF_OACTIVE;
+
+}
+
+/* called after a tx error interrupt, freet the packet */
+static void lan91cxx_finish_sent(struct lan91cxx_priv_data *cpd)
+{
+	unsigned short packet, tcr;
+	int success = 1;
+	int saved_packet;
+
+	DEBUG_FUNCTION();
+
+	INCR_STAT(cpd, tx_complete);
+
+	saved_packet = get_reg(cpd, LAN91CXX_PNR);
+
+	/* Ack and mask TX interrupt set */
+	/*ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00;
+	   ints |= LAN91CXX_INTERRUPT_TX_SET_ACK;
+	   ints &= ~LAN91CXX_INTERRUPT_TX_SET_M;
+	   put_reg(cpd, LAN91CXX_INTERRUPT, ints); */
+
+	/* Get number of completed packet and read the status word */
+	packet = get_reg(cpd, LAN91CXX_FIFO_PORTS);
+	db1_printf("%s:START: fifo %04x \n", __FUNCTION__, packet);
+
+	{
+		unsigned short reg;
+
+		reg = get_reg(cpd, LAN91CXX_EPH_STATUS);
+
+		/* Covering each bit in turn... */
+		if (reg & LAN91CXX_STATUS_TX_UNRN)
+			INCR_STAT(cpd, tx_underrun);
+		if (reg & LAN91CXX_STATUS_LOST_CARR)
+			INCR_STAT(cpd, tx_carrier_loss);
+		if (reg & LAN91CXX_STATUS_LATCOL)
+			INCR_STAT(cpd, tx_late_collisions);
+		if (reg & LAN91CXX_STATUS_TX_DEFR)
+			INCR_STAT(cpd, tx_deferred);
+		if (reg & LAN91CXX_STATUS_SQET)
+			INCR_STAT(cpd, tx_sqetesterrors);
+		if (reg & LAN91CXX_STATUS_16COL)
+			INCR_STAT(cpd, tx_max_collisions);
+		if (reg & LAN91CXX_STATUS_MUL_COL)
+			INCR_STAT(cpd, tx_mult_collisions);
+		if (reg & LAN91CXX_STATUS_SNGL_COL)
+			INCR_STAT(cpd, tx_single_collisions);
+		if (reg & LAN91CXX_STATUS_TX_SUC)
+			INCR_STAT(cpd, tx_good);
+
+		cpd->stats.tx_total_collisions =
+		    cpd->stats.tx_late_collisions +
+		    cpd->stats.tx_max_collisions +
+		    cpd->stats.tx_mult_collisions +
+		    cpd->stats.tx_single_collisions;
+
+		/* We do not need to look in the Counter Register (LAN91CXX_COUNTER)
+		   because it just mimics the info we already have above. */
+	}
+
+	/* We do not really care about Tx failure.  Ethernet is not a reliable
+	   medium.  But we do care about the TX engine stopping. */
+	tcr = get_reg(cpd, LAN91CXX_TCR);
+	if (0 == (LAN91CXX_TCR_TXENA & tcr)) {
+		db1_printf("%s: ENGINE RESTART: tcr %x \n", __FUNCTION__, tcr);
+		tcr |= LAN91CXX_TCR_TXENA;
+		put_reg(cpd, LAN91CXX_TCR, tcr);
+		success = 0;	/* And treat this as an error... */
+	}
+
+	packet &= 0xff;
+
+	/* and then free the packet */
+	put_reg(cpd, LAN91CXX_PNR, cpd->txpacket);
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_rel_packet);
+
+	while (get_reg(cpd, LAN91CXX_MMU_COMMAND) & LAN91CXX_MMU_COMMAND_BUSY) ;
+	/* Don't change Packet Number Reg until busy bit is cleared */
+	/* Per LAN91C111 Spec, Page 50 */
+	put_reg(cpd, LAN91CXX_PNR, saved_packet);
+
+}
+
+/* \ ------------- Helpers ------------- \ */
+
+/*
+ * Show interface statistics
+ */
+static void smc91111_stats(struct lan91cxx_priv_data *priv)
+{
+	printf("tx_good             :%-8d", priv->stats.tx_good);
+	printf("tx_max_collisions   :%-8d", priv->stats.tx_max_collisions);
+	printf("tx_late_collisions  :%-8d", priv->stats.tx_late_collisions);
+	printf("tx_underrun         :%-8d", priv->stats.tx_underrun);
+	printf("tx_carrier_loss     :%-8d", priv->stats.tx_carrier_loss);
+	printf("tx_deferred         :%-8d", priv->stats.tx_deferred);
+	printf("tx_sqetesterrors    :%-8d", priv->stats.tx_sqetesterrors);
+	printf("tx_single_collisions:%-8d", priv->stats.tx_single_collisions);
+	printf("tx_mult_collisions  :%-8d", priv->stats.tx_mult_collisions);
+	printf("tx_total_collisions :%-8d", priv->stats.tx_total_collisions);
+	printf("rx_good             :%-8d", priv->stats.rx_good);
+	printf("rx_crc_errors       :%-8d", priv->stats.rx_crc_errors);
+	printf("rx_align_errors     :%-8d", priv->stats.rx_align_errors);
+	printf("rx_resource_errors  :%-8d", priv->stats.rx_resource_errors);
+	printf("rx_overrun_errors   :%-8d", priv->stats.rx_overrun_errors);
+	printf("rx_collisions       :%-8d", priv->stats.rx_collisions);
+	printf("rx_short_frames     :%-8d", priv->stats.rx_short_frames);
+	printf("rx_too_long_frames  :%-8d", priv->stats.rx_too_long_frames);
+	printf("rx_symbol_errors    :%-8d", priv->stats.rx_symbol_errors);
+	printf("interrupts          :%-8d", priv->stats.interrupts);
+	printf("rx_count            :%-8d", priv->stats.rx_count);
+	printf("rx_deliver          :%-8d", priv->stats.rx_deliver);
+	printf("rx_resource         :%-8d", priv->stats.rx_resource);
+	printf("rx_restart          :%-8d", priv->stats.rx_restart);
+	printf("tx_count            :%-8d", priv->stats.tx_count);
+	printf("tx_complete         :%-8d", priv->stats.tx_complete);
+	printf("tx_dropped          :%-8d", priv->stats.tx_dropped);
+}
+
+/*
+ * Driver ioctl handler
+ */
+static int smc91111_ioctl(struct ifnet *ifp, int command, caddr_t data)
+{
+	struct lan91cxx_priv_data *cpd = ifp->if_softc;
+	int error = 0;
+	DEBUG_FUNCTION();
+
+	switch (command) {
+	case SIOCGIFADDR:
+	case SIOCSIFADDR:
+		db_printf("SIOCSIFADDR\n");
+		ether_ioctl(ifp, command, data);
+		break;
+
+	case SIOCSIFFLAGS:
+		db_printf("SIOCSIFFLAGS\n");
+		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+		case IFF_RUNNING:
+			smc91111_stop(cpd);
+			break;
+
+		case IFF_UP:
+			smc91111_init(cpd);
+			break;
+
+		case IFF_UP | IFF_RUNNING:
+			smc91111_stop(cpd);
+			smc91111_init(cpd);
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	case SIO_RTEMS_SHOW_STATS:
+		db_printf("SIO_RTEMS_SHOW_STATS\n");
+		smc91111_stats(cpd);
+		break;
+
+		/*
+		 * FIXME: All sorts of multicast commands need to be added here!
+		 */
+	default:
+		error = EINVAL;
+		break;
+	}
+
+	return error;
+}
+
+/*
+ * Attach an SMC91111 driver to the system
+ */
+int _rtems_smc91111_driver_attach (struct rtems_bsdnet_ifconfig *config,
+                                  struct scmv91111_configuration * chip)
+{
+	struct ifnet *ifp;
+	struct lan91cxx_priv_data *cpd;
+	int unitNumber;
+	char *unitName;
+	int mtu;
+	DEBUG_FUNCTION();
+
+/* 	/\* activate io area *\/ */
+/* 	switch (sparc_leon23_get_psr_version()) { */
+/* 	case 0: */
+/* 	case 2: */
+/* 		db_printf("Activating Leon2 io port\n"); */
+/* 		/\*configure pio *\/ */
+/* 		*((volatile unsigned int *)0x80000000) |= 0x10f80000; */
+/* 		*((volatile unsigned int *)0x800000A8) |= */
+/* 		    (0xe0 | chip->vector) << (8 * (chip->pio - 4)); */
+/* 		break; */
+/* 	default: */
+/* 		{ */
+/* 			unsigned long irq_pio, irq_mctrl, addr_pio, addr_mctrl; */
+/* 			if ((addr_pio = */
+/* 			     amba_find_apbslv_addr(VENDOR_GAISLER, */
+/* 						   GAISLER_PIOPORT, &irq_pio)) */
+/* 			    && (addr_mctrl = */
+/* 				amba_find_apbslv_addr(VENDOR_ESA, */
+/* 						      ESA_MCTRL, &irq_mctrl))) { */
+/* 				LEON3_IOPORT_Regs_Map *io = */
+/* 				    (LEON3_IOPORT_Regs_Map *) addr_pio; */
+/* 				db_printf */
+/* 				    ("Activating Leon3 io port for smsc_lan91cxx (pio:%x mctrl:%x)\n", */
+/* 				     (unsigned int)addr_pio, */
+/* 				     (unsigned int)addr_mctrl); */
+/* 				*((volatile unsigned int *)addr_mctrl) |= 0x10f80000;	/\*mctrl ctrl 1 *\/ */
+/* 				io->irqmask |= (1 << chip->pio); */
+/* 				io->irqpol |= (1 << chip->pio); */
+/* 				io->irqedge |= (1 << chip->pio); */
+/* 				io->iodir &= ~(1 << chip->pio); */
+/* 			} else { */
+/* 				return 0; */
+/* 			} */
+/* 		} */
+/* 	} */
+
+	/* parse driver name */
+	if ((unitNumber =
+	     rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) {
+		db_printf("Unitnumber < 0: %d\n", unitNumber);
+		return 0;
+	}
+
+	db_printf("Unitnumber: %d, baseaddr: 0x%p\n", unitNumber, chip->baseaddr);
+
+	cpd = &smc91111;
+	ifp = &cpd->arpcom.ac_if;
+	memset(cpd, 0, sizeof(*cpd));
+
+	cpd->config = *chip;
+	cpd->base = chip->baseaddr;
+
+	if (smc_probe(cpd)) {
+		return 0;
+	}
+
+	if (config->hardware_address) {
+		memcpy(cpd->arpcom.ac_enaddr, config->hardware_address,
+		       ETHER_ADDR_LEN);
+	} else {
+		/* dummy default address */
+		cpd->arpcom.ac_enaddr[0] = 0x12;
+		cpd->arpcom.ac_enaddr[1] = 0x13;
+		cpd->arpcom.ac_enaddr[2] = 0x14;
+		cpd->arpcom.ac_enaddr[3] = 0x15;
+		cpd->arpcom.ac_enaddr[4] = 0x16;
+		cpd->arpcom.ac_enaddr[5] = 0x17;
+	}
+
+	cpd->enaddr[0] = cpd->arpcom.ac_enaddr[0];
+	cpd->enaddr[1] = cpd->arpcom.ac_enaddr[1];
+	cpd->enaddr[2] = cpd->arpcom.ac_enaddr[2];
+	cpd->enaddr[3] = cpd->arpcom.ac_enaddr[3];
+	cpd->enaddr[4] = cpd->arpcom.ac_enaddr[4];
+	cpd->enaddr[5] = cpd->arpcom.ac_enaddr[5];
+	cpd->rpc_cur_mode =
+	    LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK |
+	    LAN91CXX_RPCR_ANEG;
+
+	if (config->mtu)
+		mtu = config->mtu;
+	else
+		mtu = ETHERMTU;
+
+	/*
+	 * Set up network interface values
+	 */
+	ifp->if_softc = cpd;
+	ifp->if_unit = unitNumber;
+	ifp->if_name = unitName;
+	ifp->if_mtu = mtu;
+	ifp->if_init = smc91111_init;
+	ifp->if_ioctl = smc91111_ioctl;
+	ifp->if_start = smc91111_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);
+
+#ifdef DEBUG
+	printf("SMC91111 : driver has been attached\n");
+#endif
+
+	return 1;
+};
+
+/* \ ------------- Initialization ------------- \ */
+
+/*
+ * Initialize and start the device
+ */
+static void smc91111_init(void *arg)
+{
+	struct lan91cxx_priv_data *cpd = arg;
+	struct ifnet *ifp = &cpd->arpcom.ac_if;
+	DEBUG_FUNCTION();
+
+	if (cpd->txDaemonTid == 0) {
+
+		lan91cxx_hardware_init(cpd);
+		lan91cxx_start(ifp);
+
+		cpd->rxDaemonTid = rtems_bsdnet_newproc("DCrx", 4096,
+							smc91111_rxDaemon, cpd);
+		cpd->txDaemonTid =
+		    rtems_bsdnet_newproc("DCtx", 4096, smc91111_txDaemon, cpd);
+	}
+
+	/*
+	 * Tell the world that we're running.
+	 */
+	ifp->if_flags |= IFF_RUNNING;
+}
+
+/*
+ * Stop the device
+ */
+static void smc91111_stop(struct lan91cxx_priv_data *cpd)
+{
+	struct ifnet *ifp = &cpd->arpcom.ac_if;
+	DEBUG_FUNCTION();
+
+	ifp->if_flags &= ~IFF_RUNNING;
+
+	/* Reset chip */
+	put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST);
+	put_reg(cpd, LAN91CXX_RCR, 0);
+	cpd->txbusy = cpd->within_send = 0;
+
+}
+
+int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd)
+{
+	unsigned short val;
+	int i;
+
+	DEBUG_FUNCTION();
+
+	cpd->txbusy = cpd->within_send = 0;
+
+	/* install interrupt vector */
+	db_printf("Install lan91cxx irqvector at %d\n", cpd->config.vector);
+	set_vector(lan91cxx_interrupt_handler, cpd->config.vector, 1);
+
+	/* Reset chip */
+	put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST);
+	put_reg(cpd, LAN91CXX_RCR, 0);
+	HAL_DELAY_US(100000);
+	put_reg(cpd, LAN91CXX_CONFIG, 0x9000);
+	put_reg(cpd, LAN91CXX_RCR, 0);
+	put_reg(cpd, LAN91CXX_TCR, 0);
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu);
+
+	val = get_reg(cpd, LAN91CXX_EPH_STATUS);
+	/* probe chip by reading the signature in BS register */
+	val = get_banksel(cpd);
+	db9_printf("LAN91CXX - supposed BankReg @ %x = %04x\n",
+		   (unsigned int)(cpd->base + LAN91CXX_BS), val);
+
+	if ((0xff00 & val) != 0x3300) {
+		printf("No 91Cxx signature");
+		printf("smsc_lan91cxx_init: No 91Cxx signature found\n");
+		return 0;
+	}
+
+	val = get_reg(cpd, LAN91CXX_REVISION);
+
+	db9_printf("LAN91CXX - type: %01x, rev: %01x\n",
+		   (val >> 4) & 0xf, val & 0xf);
+
+	/* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */
+	cpd->c111_reva = (val == 0x3390);
+
+	/* The controller may provide a function used to set up the ESA */
+	if (cpd->config_enaddr)
+		(*cpd->config_enaddr) (cpd);
+
+	db9_printf("LAN91CXX - status: %04x\n", val);
+	/* Use statically configured ESA from the private data */
+	db9_printf
+	    ("LAN91CXX - static ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	     cpd->enaddr[0], cpd->enaddr[1], cpd->enaddr[2],
+	     cpd->enaddr[3], cpd->enaddr[4], cpd->enaddr[5]);
+	/* Set up hardware address */
+	for (i = 0; i < sizeof(cpd->enaddr); i += 2)
+		put_reg(cpd, LAN91CXX_IA01 + i / 2,
+			cpd->enaddr[i] | (cpd->enaddr[i + 1] << 8));
+
+	return 1;
+}
+
+/*
+  This function is called to "start up" the interface.  It may be called
+  multiple times, even when the hardware is already running.  It will be
+  called whenever something "hardware oriented" changes and should leave
+  the hardware ready to send/receive packets.
+*/
+static void lan91cxx_start(struct ifnet *ifp)
+{
+	struct lan91cxx_priv_data *cpd = ifp->if_softc;
+
+	cyg_uint16 intr;
+	cyg_uint16 phy_ctl;
+	int delay;
+	DEBUG_FUNCTION();
+
+	HAL_DELAY_US(100000);
+
+	/* 91C111 Errata. Internal PHY comes up disabled. Must enable here. */
+	phy_ctl = lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_CTRL);
+	phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS;
+	lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CTRL, phy_ctl);
+
+	/* Start auto-negotiation */
+	put_reg(cpd, LAN91CXX_RPCR,
+		LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK |
+		LAN91CXX_RPCR_ANEG);
+	cpd->rpc_cur_mode =
+	    LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK |
+	    LAN91CXX_RPCR_ANEG;
+
+	/* wait for auto-negotiation to finish. */
+	/* give it ~5 seconds before giving up (no cable?) */
+	delay = 50;
+	while (!(lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_STAT) & 0x20)) {
+		if (--delay <= 0) {
+			printf("Timeout autonegotiation\n");
+			break;
+		}
+		HAL_DELAY_US(100000);
+	}
+
+	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu);
+
+	put_reg(cpd, LAN91CXX_INTERRUPT, 0);	/* disable interrupts */
+	intr = get_reg(cpd, LAN91CXX_INTERRUPT);
+	put_reg(cpd, LAN91CXX_INTERRUPT, intr &	/* ack old interrupts */
+		(LAN91CXX_INTERRUPT_TX_INT |
+		 LAN91CXX_INTERRUPT_TX_EMPTY_INT |
+		 LAN91CXX_INTERRUPT_RX_OVRN_INT | LAN91CXX_INTERRUPT_ERCV_INT));
+	put_reg(cpd, LAN91CXX_RCR,
+		LAN91CXX_RCR_STRIP_CRC | LAN91CXX_RCR_RXEN |
+		LAN91CXX_RCR_ALMUL);
+	put_reg(cpd, LAN91CXX_TCR, LAN91CXX_TCR_TXENA | LAN91CXX_TCR_PAD_EN);
+	put_reg(cpd, LAN91CXX_CONTROL, LAN91CXX_CONTROL_AUTO_RELEASE);	/*  */
+	put_reg(cpd, LAN91CXX_INTERRUPT,	/* enable interrupts */
+		LAN91CXX_INTERRUPT_RCV_INT_M);
+
+	if ((0
+#ifdef ETH_DRV_FLAGS_PROMISC_MODE
+	     != (flags & ETH_DRV_FLAGS_PROMISC_MODE)
+#endif
+	    ) || (ifp->if_flags & IFF_PROMISC)
+	    ) {
+		/* Then we select promiscuous mode. */
+		unsigned short rcr;
+		rcr = get_reg(cpd, LAN91CXX_RCR);
+		rcr |= LAN91CXX_RCR_PRMS;
+		put_reg(cpd, LAN91CXX_RCR, rcr);
+	}
+}
+
+/* \ ------------- Probe ------------- \ */
+
+static const char *chip_ids[15] = {
+	NULL, NULL, NULL,
+	/* 3 */ "SMC91C90/91C92",
+	/* 4 */ "SMC91C94",
+	/* 5 */ "SMC91C95",
+	/* 6 */ "SMC91C96",
+	/* 7 */ "SMC91C100",
+	/* 8 */ "SMC91C100FD",
+	/* 9 */ "SMC91C11xFD",
+	NULL, NULL,
+	NULL, NULL, NULL
+};
+
+static int smc_probe(struct lan91cxx_priv_data *cpd)
+{
+	unsigned short bank;
+	unsigned short revision_register;
+
+	DEBUG_FUNCTION();
+
+	/* First, see if the high byte is 0x33 */
+	HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank);
+	bank = CYG_LE16_TO_CPU(bank);
+	if ((bank & 0xFF00) != 0x3300) {
+		db_printf("<1>Smc probe bank check 1 failed.\n");
+		return -ENODEV;
+	}
+	/* The above MIGHT indicate a device, but I need to write to further
+	   test this.  */
+	HAL_WRITE_UINT16(cpd->base + (LAN91CXX_BS), CYG_CPU_TO_LE16(0 >> 3));
+	HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank);
+	bank = CYG_LE16_TO_CPU(bank);
+	if ((bank & 0xFF00) != 0x3300) {
+		db_printf("<1>Smc probe bank check 2 failed.\n");
+		return -ENODEV;
+	}
+#if SMC_DEBUG > 3
+	{
+		unsigned short bank16, bank16_0, bank16_1;
+		HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank16);
+		bank = CYG_LE16_TO_CPU(bank);
+		HAL_READ_UINT8(cpd->base + (LAN91CXX_BS), bank16_0);
+		HAL_READ_UINT8(cpd->base + (LAN91CXX_BS + 1), bank16_1);
+
+		db_printf
+		    ("smc_probe:Bank read as a 16 bit value:0x%04x\n", bank16);
+		db_printf
+		    ("smc_probe:Bank read as an 8 bit value:0x%02x\n",
+		     bank16_0);
+		db_printf
+		    ("smc_probe:Bank + 1 read as an 8 bit value:0x%02x\n",
+		     bank16_1);
+	}
+#endif
+
+	/*  check if the revision register is something that I recognize.
+	   These might need to be added to later, as future revisions
+	   could be added.  */
+	revision_register = get_reg(cpd, LAN91CXX_REVISION);
+	if (!chip_ids[(revision_register >> 4) & 0xF]) {
+		/* I don't recognize this chip, so... */
+		db_printf
+		    ("smc_probe: IO %x: Unrecognized revision register:"
+		     " %x, Contact author. \n", (unsigned int)cpd->base,
+		     revision_register);
+
+		return -ENODEV;
+	}
+	db_printf("LAN91CXX(0x%x) - type: %s, rev: %01x\n",
+		  revision_register,
+		  chip_ids[(revision_register >> 4) & 0xF],
+		  revision_register & 0xf);
+
+	/* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */
+	if (revision_register == 0x3390) {
+		db_printf("!Revision A\n");
+	}
+
+	return 0;
+}
+
+#if 0
+/* \ ------------- PHY read/write ------------- \ */
+/*Sets the PHY to a configuration as determined by the user*/
+static int lan91cxx_phy_fixed(struct lan91cxx_priv_data *cpd)
+{
+	int my_fixed_caps;
+	int cfg1;
+
+	DEBUG_FUNCTION();
+	db4_printf("lan91cxx_phy_fixed: full duplex: %d, speed: %d\n",
+		   cpd->config.ctl_rfduplx, cpd->config.ctl_rspeed);
+
+	/* Enter Link Disable state */
+	cfg1 = lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_CONFIG1);
+	cfg1 |= PHY_CFG1_LNKDIS;
+	lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CONFIG1, cfg1);
+
+	/* Set our fixed capabilities, Disable auto-negotiation */
+	my_fixed_caps = 0;
+
+	if (cpd->config.ctl_rfduplx)
+		my_fixed_caps |= LAN91CXX_PHY_CTRL_DPLX;
+
+	if (cpd->config.ctl_rspeed == 100)
+		my_fixed_caps |= LAN91CXX_PHY_CTRL_SPEED;
+
+	/* Write capabilities to the phy control register */
+	lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CTRL, my_fixed_caps);
+
+	/* Re-Configure the Receive/Phy Control register */
+	put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode);
+
+	return (1);
+}
+#endif
+
+#if 0
+/*Configures the specified PHY using Autonegotiation. */
+static void lan91cxx_phy_configure(struct lan91cxx_priv_data *cpd)
+{
+
+	unsigned int phyaddr;
+	unsigned int my_phy_caps;	/* My PHY capabilities */
+	unsigned int my_ad_caps;	/* My Advertised capabilities */
+	unsigned int status = 0;
+	int failed = 0, delay;
+
+	DEBUG_FUNCTION();
+
+	/* Set the blocking flag */
+	cpd->autoneg_active = 1;
+
+	/* Get the detected phy address */
+	phyaddr = cpd->phyaddr;
+
+	/* Reset the PHY, setting all other bits to zero */
+	lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG, PHY_CNTL_RST);
+
+	/* Wait for the reset to complete, or time out */
+	delay = 50;
+	while (delay--) {
+		if (!(lan91cxx_read_phy(cpd, 0, PHY_CNTL_REG)
+		      & PHY_CNTL_RST)) {
+			break;
+		}
+		HAL_DELAY_US(100000);
+	}
+
+	if (delay < 1) {
+		db_printf("smc91111:!PHY reset timed out\n");
+		goto smc_phy_configure_exit;
+	}
+
+	/* Read PHY Register 18, Status Output */
+	cpd->lastPhy18 = lan91cxx_read_phy(cpd, 0, PHY_INT_REG);
+
+	/* Enable PHY Interrupts (for register 18) */
+	/* Interrupts listed here are disabled */
+	lan91cxx_write_phy(cpd, 0, PHY_MASK_REG,
+			   PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD
+			   | PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
+			   PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+	/* Configure the Receive/Phy Control register */
+	put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode);
+
+	/* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */
+	my_phy_caps = lan91cxx_read_phy(cpd, phyaddr, PHY_STAT_REG);
+	my_ad_caps = PHY_AD_CSMA;	/* I am CSMA capable */
+
+	if (my_phy_caps & PHY_STAT_CAP_T4)
+		my_ad_caps |= PHY_AD_T4;
+
+	if (my_phy_caps & PHY_STAT_CAP_TXF)
+		my_ad_caps |= PHY_AD_TX_FDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TXH)
+		my_ad_caps |= PHY_AD_TX_HDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TF)
+		my_ad_caps |= PHY_AD_10_FDX;
+
+	if (my_phy_caps & PHY_STAT_CAP_TH)
+		my_ad_caps |= PHY_AD_10_HDX;
+
+	/* Disable capabilities not selected by our user */
+	if (cpd->config.ctl_rspeed != 100) {
+		my_ad_caps &= ~(PHY_AD_T4 | PHY_AD_TX_FDX | PHY_AD_TX_HDX);
+	}
+
+	if (!cpd->config.ctl_rfduplx) {
+		my_ad_caps &= ~(PHY_AD_TX_FDX | PHY_AD_10_FDX);
+	}
+
+	/* Update our Auto-Neg Advertisement Register */
+	lan91cxx_write_phy(cpd, 0, PHY_AD_REG, my_ad_caps);
+
+	db4_printf("smc91111:phy caps=%x\n", my_phy_caps);
+	db4_printf("smc91111:phy advertised caps=%x\n", my_ad_caps);
+
+	/* If the user requested no auto neg, then go set his request */
+	if (!(cpd->config.ctl_autoneg)) {
+		lan91cxx_phy_fixed(cpd);
+
+		goto smc_phy_configure_exit;
+	}
+
+	/* Restart auto-negotiation process in order to advertise my caps */
+	lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG,
+			   PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST);
+
+	/* wait for auto-negotiation to finish. */
+	/* give it ~5 seconds before giving up (no cable?) */
+	delay = 50;
+	while (!
+	       ((status =
+		 lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_STAT)) & 0x20)) {
+		if (--delay <= 0) {
+			printf("Timeout autonegotiation\n");
+			failed = 1;
+			break;
+		}
+
+		/* Restart auto-negotiation if remote fault */
+		if (status & PHY_STAT_REM_FLT) {
+			db_printf("smc91111:PHY remote fault detected\n");
+
+			/* Restart auto-negotiation */
+			db_printf("smc91111:PHY restarting auto-negotiation\n");
+			lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG,
+					   PHY_CNTL_ANEG_EN |
+					   PHY_CNTL_ANEG_RST |
+					   PHY_CNTL_SPEED | PHY_CNTL_DPLX);
+		}
+		HAL_DELAY_US(100000);
+	}
+
+	/* Fail if we detected an auto-negotiate remote fault */
+	if (status & PHY_STAT_REM_FLT) {
+		db_printf("smc91111:PHY remote fault detected\n");
+		failed = 1;
+	}
+
+	/* The smc_phy_interrupt() routine will be called to update lastPhy18 */
+
+	/* Set our sysctl parameters to match auto-negotiation results */
+	if (cpd->lastPhy18 & PHY_INT_SPDDET) {
+		db_printf("smc91111:PHY 100BaseT\n");
+		cpd->rpc_cur_mode |= LAN91CXX_RPCR_SPEED;
+	} else {
+		db_printf("smc91111:PHY 10BaseT\n");
+		cpd->rpc_cur_mode &= ~LAN91CXX_RPCR_SPEED;
+	}
+
+	if (cpd->lastPhy18 & PHY_INT_DPLXDET) {
+		db_printf("smc91111:PHY Full Duplex\n");
+		cpd->rpc_cur_mode |= LAN91CXX_RPCR_DPLX;
+	} else {
+		db_printf("smc91111:PHY Half Duplex\n");
+		cpd->rpc_cur_mode &= ~LAN91CXX_RPCR_DPLX;
+	}
+
+	/* Re-Configure the Receive/Phy Control register */
+	put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode);
+
+      smc_phy_configure_exit:
+
+	/* Exit auto-negotiation */
+	cpd->autoneg_active = 0;
+}
+#endif
+
+static cyg_uint16
+lan91cxx_read_phy(struct lan91cxx_priv_data *cpd, cyg_uint8 phyaddr,
+		  cyg_uint8 phyreg)
+{
+	int i, mask, input_idx, clk_idx = 0;
+	cyg_uint16 mii_reg, value;
+	cyg_uint8 bits[64];
+
+	/* 32 consecutive ones on MDO to establish sync */
+	for (i = 0; i < 32; ++i)
+		bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+	/* Start code <01> */
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+	/* Read command <10> */
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+
+	/* Output the PHY address, msb first */
+	for (mask = 0x10; mask; mask >>= 1) {
+		if (phyaddr & mask)
+			bits[clk_idx++] =
+			    LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+		else
+			bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	}
+
+	/* Output the phy register number, msb first */
+	for (mask = 0x10; mask; mask >>= 1) {
+		if (phyreg & mask)
+			bits[clk_idx++] =
+			    LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+		else
+			bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	}
+
+	/* Tristate and turnaround (1 bit times) */
+	bits[clk_idx++] = 0;
+
+	/* Input starts at this bit time */
+	input_idx = clk_idx;
+
+	/* Will input 16 bits */
+	for (i = 0; i < 16; ++i)
+		bits[clk_idx++] = 0;
+
+	/* Final clock bit */
+	bits[clk_idx++] = 0;
+
+	/* Get the current MII register value */
+	mii_reg = get_reg(cpd, LAN91CXX_MGMT);
+
+	/* Turn off all MII Interface bits */
+	mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK |
+		     LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);
+	HAL_DELAY_US(50);
+
+	/* Clock all 64 cycles */
+	for (i = 0; i < sizeof(bits); ++i) {
+		/* Clock Low - output data */
+		put_reg(cpd, LAN91CXX_MGMT, mii_reg | bits[i]);
+		HAL_DELAY_US(50);
+
+		/* Clock Hi - input data */
+		put_reg(cpd, LAN91CXX_MGMT,
+			mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
+		HAL_DELAY_US(50);
+
+		bits[i] |= get_reg(cpd, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;
+	}
+
+	/* Return to idle state */
+	put_reg(cpd, LAN91CXX_MGMT, mii_reg);
+	HAL_DELAY_US(50);
+
+	/* Recover input data */
+	for (value = 0, i = 0; i < 16; ++i) {
+		value <<= 1;
+		if (bits[input_idx++] & LAN91CXX_MGMT_MDI)
+			value |= 1;
+	}
+
+	db16_printf("phy_read : %d : %04x\n", phyreg, value);
+	return value;
+}
+
+static void
+lan91cxx_write_phy(struct lan91cxx_priv_data *cpd, cyg_uint8 phyaddr,
+		   cyg_uint8 phyreg, cyg_uint16 value)
+{
+	int i, mask, clk_idx = 0;
+	cyg_uint16 mii_reg;
+	cyg_uint8 bits[65];
+
+	/* 32 consecutive ones on MDO to establish sync */
+	for (i = 0; i < 32; ++i)
+		bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+	/* Start code <01> */
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+	/* Write command <01> */
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+	/* Output the PHY address, msb first */
+	for (mask = 0x10; mask; mask >>= 1) {
+		if (phyaddr & mask)
+			bits[clk_idx++] =
+			    LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+		else
+			bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	}
+
+	/* Output the phy register number, msb first */
+	for (mask = 0x10; mask; mask >>= 1) {
+		if (phyreg & mask)
+			bits[clk_idx++] =
+			    LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+		else
+			bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	}
+
+	/* Tristate and turnaround (2 bit times) */
+	bits[clk_idx++] = 0;
+	bits[clk_idx++] = 0;
+
+	/* Write out 16 bits of data, msb first */
+	for (mask = 0x8000; mask; mask >>= 1) {
+		if (value & mask)
+			bits[clk_idx++] =
+			    LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+		else
+			bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+	}
+
+	/* Final clock bit (tristate) */
+	bits[clk_idx++] = 0;
+
+	/* Get the current MII register value */
+	mii_reg = get_reg(cpd, LAN91CXX_MGMT);
+
+	/* Turn off all MII Interface bits */
+	mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK |
+		     LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);
+	HAL_DELAY_US(50);
+
+	/* Clock all cycles */
+	for (i = 0; i < sizeof(bits); ++i) {
+		/* Clock Low - output data */
+		put_reg(cpd, LAN91CXX_MGMT, mii_reg | bits[i]);
+		HAL_DELAY_US(50);
+
+		/* Clock Hi - input data */
+		put_reg(cpd, LAN91CXX_MGMT,
+			mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
+		HAL_DELAY_US(50);
+
+/*	bits[i] |= get_reg(cpd, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;*/
+	}
+
+	/* Return to idle state */
+	put_reg(cpd, LAN91CXX_MGMT, mii_reg);
+	HAL_DELAY_US(50);
+
+	db16_printf("phy_write: %d : %04x\n", phyreg, value);
+}
+
+#endif
Index: c/src/libchip/network/smc91111.h
===================================================================
--- c/src/libchip/network/smc91111.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
+++ c/src/libchip/network/smc91111.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -0,0 +1,552 @@
+/*
+ *  $Id$
+ */
+
+#ifndef _SMC91111_H_
+#define _SMC91111_H_
+
+#include <libchip/smc91111exp.h>
+
+
+#define LAN91CXX_TCR         0x00
+#define LAN91CXX_EPH_STATUS  0x01
+#define LAN91CXX_RCR         0x02
+#define LAN91CXX_COUNTER     0x03
+#define LAN91CXX_MIR         0x04
+#define LAN91CXX_MCR         0x05 /* Other than 91C111*/
+#define LAN91CXX_RPCR        0x05 /* 91C111 only*/
+#define LAN91CXX_RESERVED_0  0x06
+#define LAN91CXX_BS          0x07
+#define LAN91CXX_CONFIG      0x08
+#define LAN91CXX_BASE_REG    0x09
+#define LAN91CXX_IA01        0x0a
+#define LAN91CXX_IA23        0x0b
+#define LAN91CXX_IA45        0x0c
+#define LAN91CXX_GENERAL     0x0d /* 91C96 - was "RESERVED_1" for others*/
+#define LAN91CXX_CONTROL     0x0e
+#define LAN91CXX_BS2         0x0f
+#define LAN91CXX_MMU_COMMAND 0x10
+#define LAN91CXX_PNR         0x11
+#define LAN91CXX_FIFO_PORTS  0x12
+#define LAN91CXX_POINTER     0x13
+#define LAN91CXX_DATA_HIGH   0x14
+#define LAN91CXX_DATA        0x15
+#define LAN91CXX_INTERRUPT   0x16
+#define LAN91CXX_BS3         0x17
+#define LAN91CXX_MT01        0x18
+#define LAN91CXX_MT23        0x19
+#define LAN91CXX_MT45        0x1a
+#define LAN91CXX_MT67        0x1b
+#define LAN91CXX_MGMT        0x1c
+#define LAN91CXX_REVISION    0x1d
+#define LAN91CXX_ERCV        0x1e
+#define LAN91CXX_BS4         0x1f
+
+#define LAN91CXX_RCR_SOFT_RST   0x8000    /* soft reset*/
+#define LAN91CXX_RCR_FILT_CAR   0x4000    /* filter carrier*/
+#define LAN91CXX_RCR_ABORT_ENB  0x2000    /* abort on collision*/
+#define LAN91CXX_RCR_STRIP_CRC  0x0200    /* strip CRC*/
+#define LAN91CXX_RCR_RXEN       0x0100    /* enable RX*/
+#define LAN91CXX_RCR_ALMUL      0x0004    /* receive all muticasts*/
+#define LAN91CXX_RCR_PRMS       0x0002    /* promiscuous*/
+#define LAN91CXX_RCR_RX_ABORT   0x0001    /* set when abort due to long frame*/
+
+#define LAN91CXX_TCR_SWFDUP     0x8000    /* Switched Full Duplex mode*/
+#define LAN91CXX_TCR_ETEN_TYPE  0x4000    /* ETEN type (91C96) 0 <=> like a 91C94*/
+#define LAN91CXX_TCR_EPH_LOOP   0x2000    /* loopback mode*/
+#define LAN91CXX_TCR_STP_SQET   0x1000    /* Stop transmission on SQET error*/
+#define LAN91CXX_TCR_FDUPLX     0x0800    /* full duplex*/
+#define LAN91CXX_TCR_MON_CSN    0x0400    /* monitor carrier during tx (91C96)*/
+#define LAN91CXX_TCR_NOCRC      0x0100    /* does not append CRC to frames*/
+#define LAN91CXX_TCR_PAD_EN     0x0080    /* pads frames with 00 to min length*/
+#define LAN91CXX_TCR_FORCOL     0x0004    /* force collision*/
+#define LAN91CXX_TCR_LLOOP      0x0002    /* local loopback (91C96)*/
+#define LAN91CXX_TCR_TXENA      0x0001    /* enable*/
+
+#define LAN91CXX_POINTER_RCV        0x8000
+#define LAN91CXX_POINTER_AUTO_INCR  0x4000
+#define LAN91CXX_POINTER_READ       0x2000
+#define LAN91CXX_POINTER_ETEN       0x1000
+#define LAN91CXX_POINTER_NOT_EMPTY  0x0800
+
+
+#define LAN91CXX_INTERRUPT_TX_IDLE_M      0x8000 /* (91C96)*/
+#define LAN91CXX_INTERRUPT_ERCV_INT_M     0x4000
+#define LAN91CXX_INTERRUPT_EPH_INT_M      0x2000
+#define LAN91CXX_INTERRUPT_RX_OVRN_INT_M  0x1000
+#define LAN91CXX_INTERRUPT_ALLOC_INT_M    0x0800
+#define LAN91CXX_INTERRUPT_TX_EMPTY_INT_M 0x0400
+#define LAN91CXX_INTERRUPT_TX_INT_M       0x0200
+#define LAN91CXX_INTERRUPT_RCV_INT_M      0x0100
+#define LAN91CXX_INTERRUPT_TX_IDLE        0x0080 /* (91C96)*/
+#define LAN91CXX_INTERRUPT_ERCV_INT       0x0040 /* also ack*/
+#define LAN91CXX_INTERRUPT_EPH_INT        0x0020
+#define LAN91CXX_INTERRUPT_RX_OVRN_INT    0x0010 /* also ack*/
+#define LAN91CXX_INTERRUPT_ALLOC_INT      0x0008
+#define LAN91CXX_INTERRUPT_TX_EMPTY_INT   0x0004 /* also ack*/
+#define LAN91CXX_INTERRUPT_TX_INT         0x0002 /* also ack*/
+#define LAN91CXX_INTERRUPT_RCV_INT        0x0001
+
+#define LAN91CXX_INTERRUPT_TX_SET         0x0006 /* TX_EMPTY + TX*/
+#define LAN91CXX_INTERRUPT_TX_SET_ACK     0x0004 /* TX_EMPTY and not plain TX*/
+#define LAN91CXX_INTERRUPT_TX_FIFO_ACK    0x0002 /* TX alone*/
+#define LAN91CXX_INTERRUPT_TX_SET_M       0x0600 /* TX_EMPTY + TX*/
+
+#define LAN91CXX_CONTROL_RCV_BAD       0x4000
+#define LAN91CXX_CONTROL_AUTO_RELEASE  0x0800
+#define LAN91CXX_CONTROL_LE_ENABLE     0x0080
+#define LAN91CXX_CONTROL_CR_ENABLE     0x0040
+#define LAN91CXX_CONTROL_TE_ENABLE     0x0020
+
+/* These are for setting the MAC address in the 91C96 serial EEPROM*/
+#define LAN91CXX_CONTROL_EEPROM_SELECT 0x0004
+#define LAN91CXX_CONTROL_RELOAD        0x0002
+#define LAN91CXX_CONTROL_STORE         0x0001
+#define LAN91CXX_CONTROL_EEPROM_BUSY   0x0003
+#define LAN91CXX_ESA_EEPROM_OFFSET     0x0020
+
+#define LAN91CXX_STATUS_TX_UNRN        0x8000
+#define LAN91CXX_STATUS_LINK_OK        0x4000
+#define LAN91CXX_STATUS_CTR_ROL        0x1000
+#define LAN91CXX_STATUS_EXC_DEF        0x0800
+#define LAN91CXX_STATUS_LOST_CARR      0x0400
+#define LAN91CXX_STATUS_LATCOL         0x0200
+#define LAN91CXX_STATUS_WAKEUP         0x0100
+#define LAN91CXX_STATUS_TX_DEFR        0x0080
+#define LAN91CXX_STATUS_LTX_BRD        0x0040
+#define LAN91CXX_STATUS_SQET           0x0020
+#define LAN91CXX_STATUS_16COL          0x0010
+#define LAN91CXX_STATUS_LTX_MULT       0x0008
+#define LAN91CXX_STATUS_MUL_COL        0x0004
+#define LAN91CXX_STATUS_SNGL_COL       0x0002
+#define LAN91CXX_STATUS_TX_SUC         0x0001
+
+#define LAN91CXX_MMU_COMMAND_BUSY      0x0001
+
+#define LAN91CXX_MMU_noop              0x0000
+#define LAN91CXX_MMU_alloc_for_tx      0x0020
+#define LAN91CXX_MMU_reset_mmu         0x0040
+#define LAN91CXX_MMU_rem_rx_frame      0x0060
+#define LAN91CXX_MMU_rem_tx_frame      0x0070 /* (91C96) only when TX stopped*/
+#define LAN91CXX_MMU_remrel_rx_frame   0x0080
+#define LAN91CXX_MMU_rel_packet        0x00a0
+#define LAN91CXX_MMU_enq_packet        0x00c0
+#define LAN91CXX_MMU_reset_tx_fifo     0x00e0
+
+#define LAN91CXX_CONTROLBYTE_CRC       0x1000
+#define LAN91CXX_CONTROLBYTE_ODD       0x2000
+#define LAN91CXX_CONTROLBYTE_RX        0x4000
+
+#define LAN91CXX_RX_STATUS_ALIGNERR    0x8000
+#define LAN91CXX_RX_STATUS_BCAST       0x4000
+#define LAN91CXX_RX_STATUS_BADCRC      0x2000
+#define LAN91CXX_RX_STATUS_ODDFRM      0x1000
+#define LAN91CXX_RX_STATUS_TOOLONG     0x0800
+#define LAN91CXX_RX_STATUS_TOOSHORT    0x0400
+#define LAN91CXX_RX_STATUS_HASHVALMASK 0x007e /* MASK*/
+#define LAN91CXX_RX_STATUS_MCAST       0x0001
+#define LAN91CXX_RX_STATUS_BAD     \
+    (LAN91CXX_RX_STATUS_ALIGNERR | \
+     LAN91CXX_RX_STATUS_BADCRC   | \
+     LAN91CXX_RX_STATUS_TOOLONG  | \
+     LAN91CXX_RX_STATUS_TOOSHORT)
+
+#define LAN91CXX_RX_STATUS_IS_ODD(__cpd,__stat) ((__stat) & LAN91CXX_RX_STATUS_ODDFRM)
+#define LAN91CXX_CONTROLBYTE_IS_ODD(__cpd,__val) ((__val) & LAN91CXX_CONTROLBYTE_ODD)
+
+/* Attribute memory registers in PCMCIA mode*/
+#define LAN91CXX_ECOR                  0x8000
+#define LAN91CXX_ECOR_RESET            (1<<7)
+#define LAN91CXX_ECOR_LEVIRQ           (1<<6)
+#define LAN91CXX_ECOR_ATTWR            (1<<2)
+#define LAN91CXX_ECOR_ENABLE           (1<<0)
+
+#define LAN91CXX_ECSR                  0x8002
+#define LAN91CXX_ECSR_IOIS8            (1<<5)
+#define LAN91CXX_ECSR_PWRDWN           (1<<2)
+#define LAN91CXX_ECSR_INTR             (1<<1)
+
+/* These are for manipulating the MII interface*/
+#define LAN91CXX_MGMT_MDO              0x0001
+#define LAN91CXX_MGMT_MDI              0x0002
+#define LAN91CXX_MGMT_MCLK             0x0004
+#define LAN91CXX_MGMT_MDOE             0x0008
+
+/* Internal PHY registers (91c111)*/
+#define LAN91CXX_PHY_CTRL              0
+#define LAN91CXX_PHY_STAT              1
+#define LAN91CXX_PHY_ID1               2
+#define LAN91CXX_PHY_ID2               3
+#define LAN91CXX_PHY_AUTO_AD           4
+#define LAN91CXX_PHY_AUTO_CAP          5
+#define LAN91CXX_PHY_CONFIG1          16
+#define LAN91CXX_PHY_CONFIG2          17
+#define LAN91CXX_PHY_STATUS_OUT       18
+#define LAN91CXX_PHY_MASK             19
+
+/* PHY control bits*/
+#define LAN91CXX_PHY_CTRL_COLTST      (1 << 7)
+#define LAN91CXX_PHY_CTRL_DPLX        (1 << 8)
+#define LAN91CXX_PHY_CTRL_ANEG_RST    (1 << 9)
+#define LAN91CXX_PHY_CTRL_MII_DIS     (1 << 10)
+#define LAN91CXX_PHY_CTRL_PDN         (1 << 11)
+#define LAN91CXX_PHY_CTRL_ANEG_EN     (1 << 12)
+#define LAN91CXX_PHY_CTRL_SPEED       (1 << 13)
+#define LAN91CXX_PHY_CTRL_LPBK        (1 << 14)
+#define LAN91CXX_PHY_CTRL_RST         (1 << 15)
+
+// PHY Configuration Register 1
+#define PHY_CFG1_LNKDIS		0x8000	// 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS		0x4000	// 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN		0x2000	// 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR		0x0400	// 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS		0x0200	// 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR		0x0100	// 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE		0x0080	// 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0		0x0040	// 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT	2	// Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK	0x003C
+#define PHY_CFG1_TRF_MASK	0x0003	// Transmitter Rise/Fall time
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG		0x11
+#define PHY_CFG2_APOLDIS	0x0020	// 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS		0x0010	// 1=Jabber disabled
+#define PHY_CFG2_MREG		0x0008	// 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO	0x0004	// 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG		0x12	// Status Output (Interrupt Status)
+#define PHY_INT_INT		0x8000	// 1=bits have changed since last read
+#define	PHY_INT_LNKFAIL		0x4000	// 1=Link Not detected
+#define PHY_INT_LOSSSYNC	0x2000	// 1=Descrambler has lost sync
+#define PHY_INT_CWRD		0x1000	// 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD		0x0800	// 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD		0x0400	// 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL		0x0200	// 1=Reverse Polarity detected
+#define PHY_INT_JAB		0x0100	// 1=Jabber detected
+#define PHY_INT_SPDDET		0x0080	// 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET		0x0040	// 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG		0x13	// Interrupt Mask
+
+#define LAN91CXX_RPCR_LEDA_LINK       (0 << 2)
+#define LAN91CXX_RPCR_LEDA_TXRX       (4 << 2)
+#define LAN91CXX_RPCR_LEDA_RX         (6 << 2)
+#define LAN91CXX_RPCR_LEDA_TX         (7 << 2)
+#define LAN91CXX_RPCR_LEDB_LINK       (0 << 5)
+#define LAN91CXX_RPCR_LEDB_TXRX       (4 << 5)
+#define LAN91CXX_RPCR_LEDB_RX         (6 << 5)
+#define LAN91CXX_RPCR_LEDB_TX         (7 << 5)
+#define LAN91CXX_RPCR_ANEG            (1 << 11)
+#define LAN91CXX_RPCR_DPLX            (1 << 12)
+#define LAN91CXX_RPCR_SPEED           (1 << 13)
+
+// PHY Control Register
+#define PHY_CNTL_REG		0x00
+#define PHY_CNTL_RST		0x8000	// 1=PHY Reset
+#define PHY_CNTL_LPBK		0x4000	// 1=PHY Loopback
+#define PHY_CNTL_SPEED		0x2000	// 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN	0x1000 // 1=Enable Auto negotiation
+#define PHY_CNTL_PDN		0x0800	// 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS	0x0400	// 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST	0x0200 // 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX		0x0100	// 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST		0x0080	// 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG		0x01
+#define PHY_STAT_CAP_T4		0x8000	// 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF	0x4000	// 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH	0x2000	// 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF		0x1000	// 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH		0x0800	// 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR	0x0040	// 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK	0x0020	// 1=ANEG has completed
+#define PHY_STAT_REM_FLT	0x0010	// 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG	0x0008	// 1=Auto negotiate capable
+#define PHY_STAT_LINK		0x0004	// 1=valid link
+#define PHY_STAT_JAB		0x0002	// 1=10Mbps jabber condition
+#define PHY_STAT_EXREG		0x0001	// 1=extended registers implemented
+#define PHY_STAT_RESERVED   0x0780  // Reserved bits mask.
+
+// PHY Identifier Registers
+#define PHY_ID1_REG		0x02	// PHY Identifier 1
+#define PHY_ID2_REG		0x03	// PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG		0x04
+#define PHY_AD_NP		0x8000	// 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK		0x4000	// 1=got link code word from remote
+#define PHY_AD_RF		0x2000	// 1=advertise remote fault
+#define PHY_AD_T4		0x0200	// 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX		0x0100	// 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX		0x0080	// 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX		0x0040	// 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX		0x0020	// 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA		0x0001	// 1=PHY is capable of 802.3 CMSA
+
+
+static int debugflag_out = 0;
+
+#define dbc_printf(lvl,format, args...) do { \
+  if (!debugflag_out) { \
+  if (lvl & DEBUG) { \
+    char buf[1024]; \
+    sprintf(buf,format,##args); \
+    DEBUG_puts(buf); \
+  }} \
+} while(0)
+
+#define db64_printf(format, args...) dbc_printf(64,format,##args);
+#define db16_printf(format, args...) dbc_printf(16,format,##args);
+#define db9_printf(format, args...) dbc_printf(9,format,##args);
+#define db4_printf(format, args...) dbc_printf(4,format,##args);
+#define db2_printf(format, args...) dbc_printf(2,format,##args);
+#define db1_printf(format, args...) dbc_printf(1,format,##args);
+#define db_printf(format, args...) dbc_printf(0xffff,format,##args);
+
+#if DEBUG & 1
+#define DEBUG_FUNCTION() do { db_printf("# %s\n", __FUNCTION__); } while (0)
+#else
+#define DEBUG_FUNCTION() do {} while(0)
+#endif
+
+
+/* ------------------------------------------------------------------------*/
+
+struct smsc_lan91cxx_stats {
+    unsigned int tx_good             ;
+    unsigned int tx_max_collisions   ;
+    unsigned int tx_late_collisions  ;
+    unsigned int tx_underrun         ;
+    unsigned int tx_carrier_loss     ;
+    unsigned int tx_deferred         ;
+    unsigned int tx_sqetesterrors    ;
+    unsigned int tx_single_collisions;
+    unsigned int tx_mult_collisions  ;
+    unsigned int tx_total_collisions ;
+    unsigned int rx_good             ;
+    unsigned int rx_crc_errors       ;
+    unsigned int rx_align_errors     ;
+    unsigned int rx_resource_errors  ;
+    unsigned int rx_overrun_errors   ;
+    unsigned int rx_collisions       ;
+    unsigned int rx_short_frames     ;
+    unsigned int rx_too_long_frames  ;
+    unsigned int rx_symbol_errors    ;
+    unsigned int interrupts          ;
+    unsigned int rx_count            ;
+    unsigned int rx_deliver          ;
+    unsigned int rx_resource         ;
+    unsigned int rx_restart          ;
+    unsigned int tx_count            ;
+    unsigned int tx_complete         ;
+    unsigned int tx_dropped          ;
+};
+#define INCR_STAT(c,n) (((c)->stats.n)++)
+
+struct lan91cxx_priv_data;
+
+typedef struct lan91cxx_priv_data {
+
+    /* frontend */
+    struct arpcom arpcom;
+    rtems_id rxDaemonTid;
+    rtems_id txDaemonTid;
+
+    scmv91111_configuration_t config;
+  
+    /* backend */
+    int rpc_cur_mode;
+    int autoneg_active;
+    int phyaddr;
+    unsigned int lastPhy18;
+  
+    int txbusy;                         /* A packet has been sent*/
+    unsigned long txkey;                /* Used to ack when packet sent*/
+    unsigned short* base;               /* Base I/O address of controller*/
+                                        /* (as it comes out of reset)*/
+    int interrupt;                      /* Interrupt vector used by controller*/
+    unsigned char enaddr[6];            /* Controller ESA*/
+    /* Function to configure the ESA - may fetch ESA from EPROM or */
+    /* RedBoot config option.  Use of the 'config_enaddr()' function*/
+    /* is depreciated in favor of the 'provide_esa()' function and*/
+    /* 'hardwired_esa' boolean*/
+    void (*config_enaddr)(struct lan91cxx_priv_data* cpd);
+    int hardwired_esa;
+    int txpacket;
+    int rxpacket;
+    int within_send;
+    int c111_reva;                      /* true if this is a revA LAN91C111*/
+    struct smsc_lan91cxx_stats stats;
+} lan91cxx_priv_data;
+
+/* ------------------------------------------------------------------------*/
+
+#ifdef LAN91CXX_32BIT_RX
+typedef unsigned int rxd_t;
+#else
+typedef unsigned short rxd_t;
+#endif
+
+typedef struct _debug_regs_pair {
+  int reg; char *name; struct _debug_regs_pair *bits;
+} debug_regs_pair;
+
+static debug_regs_pair debug_regs[] = {
+  {LAN91CXX_TCR        , "LAN91CXX_TCR"       ,0},  
+  {LAN91CXX_EPH_STATUS , "LAN91CXX_EPH_STATUS",0},  
+  {LAN91CXX_RCR        , "LAN91CXX_RCR"       ,0},         
+  {LAN91CXX_COUNTER    , "LAN91CXX_COUNTER"   ,0},     
+  {LAN91CXX_MIR        , "LAN91CXX_MIR"       ,0},         
+  {LAN91CXX_MCR        , "LAN91CXX_MCR"       ,0},         
+  {LAN91CXX_RPCR       , "LAN91CXX_RPCR"      ,0},        
+  {LAN91CXX_RESERVED_0 , "LAN91CXX_RESERVED_0",0},  
+  {LAN91CXX_BS         , "LAN91CXX_BS"        ,0},          
+  {LAN91CXX_CONFIG     , "LAN91CXX_CONFIG"    ,0},      
+  {LAN91CXX_BASE_REG   , "LAN91CXX_BASE_REG"  ,0},    
+  {LAN91CXX_IA01       , "LAN91CXX_IA01"      ,0},        
+  {LAN91CXX_IA23       , "LAN91CXX_IA23"      ,0},        
+  {LAN91CXX_IA45       , "LAN91CXX_IA45"      ,0},        
+  {LAN91CXX_GENERAL    , "LAN91CXX_GENERAL"   ,0},     
+  {LAN91CXX_CONTROL    , "LAN91CXX_CONTROL"   ,0},     
+  {LAN91CXX_BS2        , "LAN91CXX_BS2"       ,0},         
+  {LAN91CXX_MMU_COMMAND, "LAN91CXX_MMU_COMMAND",0}, 
+  {LAN91CXX_PNR        , "LAN91CXX_PNR"        ,0},         
+  {LAN91CXX_FIFO_PORTS , "LAN91CXX_FIFO_PORTS" ,0},  
+  {LAN91CXX_POINTER    , "LAN91CXX_POINTER"    ,0},     
+  {LAN91CXX_DATA_HIGH  , "LAN91CXX_DATA_HIGH"  ,0},   
+  {LAN91CXX_DATA       , "LAN91CXX_DATA"       ,0},        
+  {LAN91CXX_INTERRUPT  , "LAN91CXX_INTERRUPT"  ,0},
+  {LAN91CXX_BS3        , "LAN91CXX_BS3"        ,0},
+  {LAN91CXX_MT01       , "LAN91CXX_MT01"       ,0},
+  {LAN91CXX_MT23       , "LAN91CXX_MT23"       ,0},   
+  {LAN91CXX_MT45       , "LAN91CXX_MT45"       ,0},      
+  {LAN91CXX_MT67       , "LAN91CXX_MT67"       ,0},
+/*{LAN91CXX_MGMT       , "LAN91CXX_MGMT"       ,0},      */
+  {LAN91CXX_REVISION   , "LAN91CXX_REVISION"   ,0},  
+  {LAN91CXX_ERCV       , "LAN91CXX_ERCV"       ,0},      
+  {LAN91CXX_BS4        , "LAN91CXX_BS4"        ,0},             
+
+
+  
+  {-1,0}
+};
+
+static char *dbg_prefix = "";
+
+#ifndef SMSC_PLATFORM_DEFINED_GET_REG
+static __inline__ unsigned short
+get_reg(struct lan91cxx_priv_data *cpd, int regno)
+{
+    unsigned short val; debug_regs_pair *dbg = debug_regs; int c;
+    unsigned32              Irql;
+
+    /*rtems_interrupt_disable(Irql);*/
+
+    HAL_WRITE_UINT16(cpd->base+(LAN91CXX_BS), CYG_CPU_TO_LE16(regno>>3));
+    HAL_READ_UINT16(cpd->base+((regno&0x7)), val);
+    val = CYG_LE16_TO_CPU(val);
+    
+    /*rtems_interrupt_enable(Irql);*/
+
+#ifdef DEBUG & 32
+    while ((c = dbg->reg) != -1) {
+      if (c == regno) {
+        db_printf("%sread  reg [%d:%x] -> 0x%04x (%-20s)\n", dbg_prefix, regno>>3,(regno&0x7)*2, val, dbg->name);
+        break;
+      }
+      dbg++;
+    }
+#else    
+    db2_printf("%sread  reg %d:%x -> 0x%04x\n", dbg_prefix, regno>>3,(regno&0x7)*2, val);
+#endif
+    
+    return val;
+}
+#endif /* SMSC_PLATFORM_DEFINED_GET_REG*/
+
+#ifndef SMSC_PLATFORM_DEFINED_PUT_REG
+static __inline__ void
+put_reg(struct lan91cxx_priv_data *cpd, int regno, unsigned short val)
+{
+    debug_regs_pair *dbg = debug_regs; int c;
+    unsigned32              Irql;
+
+#ifdef DEBUG & 32
+    while ((c = dbg->reg) != -1) {
+      if (c == regno) {
+        db_printf("%swrite reg [%d:%x] <- 0x%04x (%-20s)\n", dbg_prefix, regno>>3, (regno&0x07)*2, val, dbg->name);
+        break;
+      }
+      dbg++;
+    }
+#else    
+    db2_printf("%swrite reg %d:%x <- 0x%04x\n", dbg_prefix, regno>>3,(regno&0x7)*2, val);
+#endif
+    
+    /*rtems_interrupt_disable(Irql);*/
+    
+    HAL_WRITE_UINT16(cpd->base+(LAN91CXX_BS), CYG_CPU_TO_LE16(regno>>3));
+    HAL_WRITE_UINT16(cpd->base+((regno&0x7)), CYG_CPU_TO_LE16(val));
+    
+    /*rtems_interrupt_enable(Irql);*/
+
+}
+#endif /* SMSC_PLATFORM_DEFINED_PUT_REG*/
+
+#ifndef SMSC_PLATFORM_DEFINED_PUT_DATA
+/* ------------------------------------------------------------------------*/
+/* Assumes bank2 has been selected*/
+static __inline__ void
+put_data(struct lan91cxx_priv_data *cpd, unsigned short val)
+{
+    db2_printf("%s[wdata] <- 0x%04x\n", dbg_prefix, val);
+    
+    HAL_WRITE_UINT16(cpd->base+((LAN91CXX_DATA & 0x7)), val);
+
+}
+#endif /* SMSC_PLATFORM_DEFINED_PUT_DATA*/
+
+#ifndef SMSC_PLATFORM_DEFINED_GET_DATA
+/* Assumes bank2 has been selected*/
+static __inline__ rxd_t
+get_data(struct lan91cxx_priv_data *cpd)
+{
+    rxd_t val;
+	
+#ifdef LAN91CXX_32BIT_RX
+    HAL_READ_UINT32(cpd->base+((LAN91CXX_DATA_HIGH & 0x7)), val);
+#else
+    HAL_READ_UINT16(cpd->base+((LAN91CXX_DATA & 0x7)), val);
+#endif
+
+    db2_printf("%s[rdata] -> 0x%08x\n", dbg_prefix, val);
+    return val;
+}
+#endif /* SMSC_PLATFORM_DEFINED_GET_DATA*/
+
+/* ------------------------------------------------------------------------*/
+/* Read the bank register (this one is bank-independent)*/
+#ifndef SMSC_PLATFORM_DEFINED_GET_BANKSEL
+static __inline__ unsigned short
+get_banksel(struct lan91cxx_priv_data *cpd)
+{
+    unsigned short val;
+    
+    HAL_READ_UINT16(cpd->base+(LAN91CXX_BS), val);
+    val = CYG_LE16_TO_CPU(val);
+    db2_printf("read bank sel val 0x%04x\n", val);
+    return val;
+}
+#endif
+
+
+
+
+
+#endif  /* _SMC_91111_H_ */
+
+
Index: c/src/libchip/network/smc91111config.h
===================================================================
--- c/src/libchip/network/smc91111config.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
+++ c/src/libchip/network/smc91111config.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -0,0 +1,132 @@
+/*
+ *  $Id$
+ */
+
+#ifndef _SMC91111_CONFIG_H_
+#define _SMC91111_CONFIG_H_
+
+/*
+ * RTEMS event used by interrupt handler to signal driver tasks.
+ * This must not be any of the events used by the network task synchronization.
+ */
+#define INTERRUPT_EVENT	RTEMS_EVENT_1
+
+/*
+ * RTEMS event used to start transmit daemon.
+ * This must not be the same as INTERRUPT_EVENT.
+ */
+#define START_TRANSMIT_EVENT	RTEMS_EVENT_2
+
+ /* event to send when tx buffers become available */
+#define SMC91111_TX_WAIT_EVENT  RTEMS_EVENT_3
+
+
+/* Number of OCs supported by this driver*/
+#define NOCDRIVER	1
+
+/* Receive buffer size -- Allow for a full ethernet packet including CRC */
+#define RBUF_SIZE	1536
+
+#define	ET_MINLEN 64		/* minimum message length */
+
+#if (MCLBYTES < RBUF_SIZE)
+# error "Driver must have MCLBYTES > RBUF_SIZE"
+#endif
+
+/* ----------------- cygdriver params ----------------- */
+
+#define LAN91CXX_32BIT_RX
+#define LAN91CXX_IS_LAN91C111
+
+/* ----------------- compat layer ----------------- */
+
+/* -------------------------------------------------------------------------
+   Define basic types for using integers in memory and structures;
+   depends on compiler defaults and CPU type. */
+
+typedef unsigned char    cyg_uint8  ;
+typedef   signed char    cyg_int8   ;
+typedef unsigned short   cyg_uint16 ;
+typedef   signed short   cyg_int16  ;
+typedef unsigned int     cyg_uint32 ;
+typedef   signed int     cyg_int32  ;
+typedef unsigned int     cyg_bool   ;
+
+typedef cyg_uint32  CYG_WORD;
+typedef cyg_uint8   CYG_BYTE;
+typedef cyg_uint16  CYG_WORD16;
+typedef cyg_uint32  CYG_WORD32;
+
+#ifndef CYG_SWAP16
+# define CYG_SWAP16(_x_)                                        \
+    ({ cyg_uint16 _x = (_x_); ((_x << 8) | (_x >> 8)); })
+#endif
+
+#ifndef CYG_SWAP32
+# define CYG_SWAP32(_x_)                        \
+    ({ cyg_uint32 _x = (_x_);                   \
+       ((_x << 24) |                            \
+       ((0x0000FF00UL & _x) <<  8) |            \
+       ((0x00FF0000UL & _x) >>  8) |            \
+       (_x  >> 24)); })
+#endif
+
+# define CYG_CPU_TO_BE16(_x_) (_x_)
+# define CYG_CPU_TO_BE32(_x_) (_x_)
+# define CYG_BE16_TO_CPU(_x_) (_x_)
+# define CYG_BE32_TO_CPU(_x_) (_x_)
+
+# define CYG_CPU_TO_LE16(_x_) CYG_SWAP16((_x_))
+# define CYG_CPU_TO_LE32(_x_) CYG_SWAP32((_x_))
+# define CYG_LE16_TO_CPU(_x_) CYG_SWAP16((_x_))
+# define CYG_LE32_TO_CPU(_x_) CYG_SWAP32((_x_))
+
+#define CYG_MACRO_START do {
+#define CYG_MACRO_END   } while (0)
+#define HAL_IO_BARRIER()                        \
+    asm volatile ( "" : : : "memory" )
+
+#define HAL_READ_UINT8( _register_, _value_ )           \
+    CYG_MACRO_START                                     \
+    ((_value_) = *((volatile CYG_BYTE *)(_register_))); \
+    HAL_IO_BARRIER ();                                  \
+    CYG_MACRO_END
+
+#define HAL_WRITE_UINT8( _register_, _value_ )          \
+    CYG_MACRO_START                                     \
+    (*((volatile CYG_BYTE *)(_register_)) = (_value_)); \
+    HAL_IO_BARRIER ();                                  \
+    CYG_MACRO_END
+
+#define HAL_READ_UINT16( _register_, _value_ )                  \
+    CYG_MACRO_START                                             \
+    ((_value_) = *((volatile CYG_WORD16 *)(_register_)));       \
+    HAL_IO_BARRIER ();                                          \
+    CYG_MACRO_END
+
+#define HAL_WRITE_UINT16( _register_, _value_ )                 \
+    CYG_MACRO_START                                             \
+    (*((volatile CYG_WORD16 *)(_register_)) = (_value_));       \
+    HAL_IO_BARRIER ();                                          \
+    CYG_MACRO_END
+
+#define HAL_READ_UINT32( _register_, _value_ )                  \
+    CYG_MACRO_START                                             \
+    ((_value_) = *((volatile CYG_WORD32 *)(_register_)));       \
+    HAL_IO_BARRIER ();                                          \
+    CYG_MACRO_END
+
+#define HAL_READ_UINT16( _register_, _value_ )                  \
+    CYG_MACRO_START                                             \
+    ((_value_) = *((volatile CYG_WORD16 *)(_register_)));       \
+    HAL_IO_BARRIER ();                                          \
+    CYG_MACRO_END
+
+#define CYG_ASSERT(c,p) do { if (!(c)) { while(1) { printf(p);} }; } while(0)
+
+#define HAL_DELAY_US(p) rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (p))
+
+
+#endif  /* _SMC_91111_CONFIG_H_ */
+
+
Index: c/src/libchip/network/smc91111exp.h
===================================================================
--- c/src/libchip/network/smc91111exp.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
+++ c/src/libchip/network/smc91111exp.h	(revision 3ffa81419930d7984ca31534e47b8321a2dd8cfc)
@@ -0,0 +1,19 @@
+/*
+ *  $Id$
+ */
+
+#ifndef _SMC91111_EXP_H_
+#define _SMC91111_EXP_H_
+
+typedef struct scmv91111_configuration {
+  void                     *baseaddr;
+  unsigned int              vector;
+  unsigned int              pio;
+  unsigned int              ctl_rspeed;
+  unsigned int              ctl_rfduplx;
+  unsigned int              ctl_autoneg;
+} scmv91111_configuration_t;
+
+#endif  /* _SMC_91111_EXP_H_ */
+
+
