diff -urN pearpc/src/io/rtl8139/rtl8139.cc pearpc-verbose15/src/io/rtl8139/rtl8139.cc
--- pearpc/src/io/rtl8139/rtl8139.cc	2004-05-25 04:15:59.000000000 -0500
+++ pearpc-verbose15/src/io/rtl8139/rtl8139.cc	2004-05-25 17:39:46.000000000 -0500
@@ -30,7 +30,6 @@
 #include <cstring>
 #include <unistd.h>
 
-#include "system/sys.h"
 #include "system/systhread.h"
 #include "cpu_generic/ppc_cpu.h"
 #include "cpu_generic/ppc_mmu.h"
@@ -50,7 +49,7 @@
 
 
 enum RxHeaderBits {
-	Rx_ROK =  1<<0, // receive okay
+	Rx_ROK =  1<<0, // recieve okay
 	Rx_FAE =  1<<1, // frame alignment error
 	Rx_CRC =  1<<2, // crc error
 	Rx_LONG = 1<<3, // packet > 4k
@@ -133,6 +132,7 @@
 };
 
 struct Packet {
+	uint32  pid;
 	uint16	size;
 	byte	packet[MAX_PACKET_SIZE];
 };
@@ -205,12 +205,6 @@
 	bool		mEEPROMWritable;
 	Registers	mRegisters;
 	uint16		mIntStatus;
-	bool		mRxEnabled;
-	bool		mTxEnabled;
-	bool		mUpStalled;
-	bool		mDnStalled;
-	byte		mRxPacket[MAX_PACKET_SIZE];
-	uint		mRxPacketSize;
 	int		mRingBufferSize;
 	bool	 	mGoodBSA;
 	enet_iface_t	mENetIf;
@@ -218,6 +212,11 @@
 	int		mVerbose;
 	byte		mHead;
 	byte		mTail;
+	byte		mActive;
+	byte		mWatermark;
+	byte            mLast;
+	byte            mLastPackets[2];
+	uint32		mPid;
 	Packet		mPackets[MAX_PACKETS];
 
 
@@ -263,12 +262,11 @@
 	mRingBufferSize = 8192;
 	mHead = 0;
 	mTail = 0;
+	mActive = 0;
+	mWatermark = 0;
+	mLastPackets[0] = 0;
+	mLastPackets[1] = 0;
 	mGoodBSA = false;
-	mRxEnabled = false;
-	mTxEnabled = false;
-	mUpStalled = false;
-	mDnStalled = false;
-	mRxPacketSize = 0;
 	// EEPROM config (FIXME: endianess)
 
 	// set up mac address
@@ -323,7 +321,7 @@
 	}
 	if (cr & 0x08) {
 		mRegisters.CommandRegister |= 0x08;
-		// enable receiver
+		// enable reciever
 	}
 	if (cr & 0x04) {
 		mRegisters.CommandRegister |= 0x04;
@@ -399,6 +397,7 @@
 	int e;
 	if ((e = sys_create_mutex(&mLock))) throw IOException(e);
 	mENetIf = aENetIf;
+	mPid = 0;
 	PCIReset();
 	totalReset();
 }
@@ -407,24 +406,41 @@
 {
 	byte*		addr;
 	byte*           base;
+	bool		good;
 
+	if (mTail == mHead) {
+		return;
+	}
 	if (ppc_direct_physical_memory_handle(mRegisters.RxBufferStartAddr, base) == PPC_MMU_OK) {
 		addr = base + mRegisters.CBA;
+		if (mRegisters.CBA > mRingBufferSize) {// sending outside, could cause problems?
+			good = false;
+		} else {
+			good = true;
+		}
+#if 0
 		if ((mRegisters.CBA) > mRingBufferSize) {
-			if (mVerbose) IO_RTL8139_TRACE("client ring buffer wrap around [%d]\n", raiseIntr);
+			IO_RTL8139_TRACE("client ring buffer wrap around [%d]\n", raiseIntr);
 			addr = base;
 			mRegisters.CBA = 0;
 			mRegisters.CAPR = 0xfff0;
 //			mRegisters.CommandRegister |= 1;
 			return;
 		}
+#endif
 		memcpy(addr, mPackets[mTail].packet, mPackets[mTail].size);
 		if (mVerbose) IO_RTL8139_TRACE("wrote %04x bytes to the ring buffer\n", mPackets[mTail].size);
 		mRegisters.EarlyRxByteCount = mPackets[mTail].size;
 		mRegisters.EarlyRxStatus = 8;
 		mRegisters.CBA += mPackets[mTail].size;
 		mRegisters.CommandRegister &= 0xfe; // RxBuffer has data
-		mTail = (mTail+1) % MAX_PACKETS;
+		mLastPackets[1] = mLastPackets[0];
+		mLastPackets[0] = mTail;
+		mActive--;
+		IO_RTL8139_TRACE("Outgoing - Addr: %08x, Pid: %08x, Size: %04x\n", addr, mPackets[mTail].pid, mPackets[mTail].size-4);
+		if (good) {
+			mTail = (mTail+1) % MAX_PACKETS;
+		}
 		if (raiseIntr) {
 			mIntStatus |= 1;
 			maybeRaiseIntr();
@@ -470,7 +486,10 @@
 {
 	if (r != 0) return false;
 	bool retval = false;
+//	IO_RTL8139_TRACE("readDevice waiting for mLock\n");
 	sys_lock_mutex(mLock);
+//	IO_RTL8139_TRACE("readDevice has mLock\n");
+
 	if (port == 0x3e) {
 		// IntStatus (no matter which window)
 		if (size != 2) {
@@ -493,6 +512,13 @@
 			if (mVerbose) IO_RTL8139_TRACE("read Command Register = %02x\n", data);
 			break;
 		}
+		case 0x64: {
+			if (mVerbose) IO_RTL8139_TRACE("read Basic Mode Status = %04x\n", data);
+			if ((mTail != mHead) && (mRegisters.CommandRegister & 0x01)) {
+				transferPacket(true);
+			}
+			break;
+		}
 		default:
 			if (mVerbose) IO_RTL8139_TRACE("read reg %04x (size %d) = %08x\n", port, size, data);
 			break;
@@ -501,6 +527,7 @@
 		retval = true;
 	}
 	sys_unlock_mutex(mLock);
+//	IO_RTL8139_TRACE("readDevice freed mLock\n");
 	return retval;
 }
 
@@ -510,7 +537,9 @@
 
 	if (r != 0) return false;
 	bool retval = false;
+//	IO_RTL8139_TRACE("writeDevice waiting for mLock\n");
 	sys_lock_mutex(mLock);
+//	IO_RTL8139_TRACE("writeDevice has mLock\n");
 	original = data;
 	data = swapData(data, size);
 	if (port == 0x37) {
@@ -582,21 +611,26 @@
 			mRegisters.CAPR = 0xfff0;
 			mRegisters.CommandRegister |= 1;
 			mGoodBSA = true;
-			if (mTail != mHead) {
-				transferPacket(true);
-			}
+			transferPacket(true);
 			break;
 		}
 		case 0x38: {
 			if (mVerbose) IO_RTL8139_TRACE("update to CAPR: CAPR %04x, CBA %04x\n", data, mRegisters.CBA);
 			mRegisters.CAPR = data;
+			if (mRegisters.CAPR >= mRegisters.CBA) {
+				IO_RTL8139_WARN("Bad packet read by client? Active %02x, CAPR %04x, CBA %04x, Tail %02x, Head %02x\n", mActive, mRegisters.CAPR, mRegisters.CBA, mTail, mHead);
+				mRegisters.CBA = mRegisters.CAPR + 0x10;
+			}
 			if (mRegisters.CAPR > mRingBufferSize) { //client knows about wrap, so wrap
+				mRegisters.CBA = 0;
 				mIntStatus |= 1; // fake send
 				maybeRaiseIntr();
+				IO_RTL8139_TRACE("client wrap on CAPR set Active %02x, CAPR %04x, CBA %04x, Tail %02x, Head %02x\n", mActive, mRegisters.CAPR, mRegisters.CBA, mTail, mHead);
 				/*
+				mIntStatus |= 1; // fake send
+				maybeRaiseIntr();
 				mRegisters.CAPR = 0xfff0;
 				mRegisters.CommandRegister |= 1;
-				mRegisters.CBA = 0;
 				*/
 			} else {
 				if (mTail != mHead) {
@@ -633,84 +667,85 @@
 		retval = true;
 	}
 	sys_unlock_mutex(mLock);
+//	IO_RTL8139_TRACE("writeDevice freed mLock\n");
 	return retval;
 }
 
-void handlePacket()
+void handleRxQueue()
 {
 	uint16		header;
 	uint16		psize;
+	byte            rxPacket[MAX_PACKET_SIZE];
+	uint16          rxPacketSize;
 	byte		tmp;
 	byte		broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-	mRxPacketSize = read(mENetIf.fd, mRxPacket, sizeof mRxPacket);
-	if (!mGoodBSA) {
-		mRxPacketSize = 0;
-	} else {
+	while(1) {
+		rxPacketSize = read(mENetIf.fd, rxPacket, sizeof rxPacket);
 		if (mVerbose) IO_RTL8139_TRACE("got packet from the world at large\n");
+		if (!mGoodBSA) continue;
 		if (mVerbose > 1) {
-			dumpMem(mRxPacket, mRxPacketSize);
+			dumpMem(rxPacket, rxPacketSize);
 		}
 		header = 0;
-		if (mRxPacketSize < 64) {
-			for ( ; mRxPacketSize < 60; mRxPacketSize++) {
-				mRxPacket[mRxPacketSize] = 0;
+		if (rxPacketSize < 64) {
+			for ( ; rxPacketSize < 60; rxPacketSize++) {
+				rxPacket[rxPacketSize] = 0;
 			}
 			//header |= Rx_RUNT; // set runt status
 		}
 		/* pad to a 4 byte boundary */
-		for (int i = 4-(mRxPacketSize % 4); i != 0; i--) {
-			mRxPacket[mRxPacketSize++] = 0;
-		}
-		if (memcmp((byte*)&(mRxPacket[0]), (byte*)&(mRegisters.id0), 6) == 0) {
-			//	if (mVerbose) IO_RTL8139_TRACE("Physical Address Match\n");
-			header |= Rx_PAM;
+		for (int i = 4-(rxPacketSize % 4); i != 0; i--) {
+			rxPacket[rxPacketSize++] = 0;
 		}
-		if (memcmp((byte*)&(mRxPacket[0]), broadcast, 6) == 0) {
+		if (memcmp(rxPacket, broadcast, 6) == 0) {
 			header |= Rx_BAR;
 		}
+//		IO_RTL8139_TRACE("handleRxQueue waiting for mLock\n");
+		sys_lock_mutex(mLock);
+//		IO_RTL8139_TRACE("handleRxQueue has mLock\n");
+		if (memcmp(rxPacket, (byte*)&(mRegisters.id0), 6) == 0) {
+			if (mVerbose > 1) IO_RTL8139_TRACE("Physical Address Match\n");
+			header |= Rx_PAM;
+		}
 		// check crc?
 		header |= Rx_ROK;
-		psize = mRxPacketSize;
+		psize = rxPacketSize;
+		IO_RTL8139_TRACE("Incoming - Pid: %08x, Header: %04x, Size: %04x\n", mPid, header, psize);
 		mPackets[mHead].packet[0] = header;
 		mPackets[mHead].packet[1] = header>>8;
 		mPackets[mHead].packet[2] = psize;
 		mPackets[mHead].packet[3] = psize>>8;
-		memcpy(&(mPackets[mHead].packet[4]), mRxPacket, mRxPacketSize);
-		mPackets[mHead].size = mRxPacketSize+4;
+		memcpy(&(mPackets[mHead].packet[4]), rxPacket, rxPacketSize);
+		mPackets[mHead].size = rxPacketSize+4;
+		mPackets[mHead].pid = mPid;
+		tmp = mHead;
 		if (mHead == mTail) { /* first recent packet buffer */
 			mHead = (mHead+1) % MAX_PACKETS;
 		} else {
-			tmp = mHead;
 			mHead = (mHead+1) % MAX_PACKETS;
 			if (mHead == mTail) {
 				mHead = tmp; // reset it back 
 				IO_RTL8139_WARN("Internal Buffer wrapped around\n");
+			} 
+		}
+		if (tmp != mHead) {
+			mPid++;
+			mActive++;
+			if (mActive > mWatermark) {
+				IO_RTL8139_TRACE("Watermark: %02x\n", mWatermark);
+				mWatermark = mActive;
 			}
 		}
 		if (mRegisters.CommandRegister & 1) { /* no packets in process, kick one out */
-			sys_lock_mutex(mLock);
 			transferPacket(true);
-			sys_unlock_mutex(mLock);
-		}
-	}
-}
-
-/* new */
-void handleRxQueue()
-{
-	mRxPacketSize = 0; // no packets at the moment
-	while (1) {
-		if (g_sys_ethtun_pd.wait_receive(&mENetIf) == 0) {
-			handlePacket();
-		} else {
-			// don't waste our timeslice
-			sys_suspend();
 		}
+		sys_unlock_mutex(mLock);
+//		IO_RTL8139_TRACE("handleRxQueue freed mLock\n");
 	}
 }
 
-};
+}; // end of rtl8139 class
 
 static void *rtl8139HandleRxQueue(void *nic)
 {
@@ -724,15 +759,12 @@
 #include "configparser.h"
 #include "tools/strtools.h"
 
-#define RTL8139_KEY_INSTALLED   "pci_rtl8139_installed"
-#define RTL8139_KEY_MAC         "pci_rtl8139_mac"
-#define RTL8139_KEY_VERBOSE     "pci_rtl8139_verbose"
+#define RTL8139_KEY_INSTALLED	"pci_rtl8139_installed"
+#define RTL8139_KEY_MAC		"pci_rtl8139_mac"
+#define RTL8139_KEY_VERBOSE	"pci_rtl8139_verbose"
 
 void rtl8139_init()
 {
-	String tunstr_;
-	char   tun_name[1024];
-
 	int verbose = 0;
 
 	verbose = gConfig->getConfigInt(RTL8139_KEY_VERBOSE); 
