diff -Naur qemu-0.10.6/hw/eepro100.c qemu-0.10.6-e100/hw/eepro100.c
--- qemu-0.10.6/hw/eepro100.c	2009-07-16 20:56:22.000000000 -0400
+++ qemu-0.10.6-e100/hw/eepro100.c	2009-11-10 12:30:42.000000000 -0500
@@ -74,10 +74,12 @@
 #define KiB 1024
 
 /* debug EEPRO100 card */
-//~ #define DEBUG_EEPRO100
+#define DEBUG_EEPRO100
+
+int e100_debug = 0;
 
 #ifdef DEBUG_EEPRO100
-#define logout(fmt, args...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ##args)
+#define logout(fmt, args...) {if (e100_debug) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ##args);}
 #else
 #define logout(fmt, args...) ((void)0)
 #endif
@@ -173,6 +175,15 @@
 } eepro100_rx_t;
 
 typedef struct {
+    uint16_t count;
+    uint16_t pad0;
+    uint32_t link;
+    uint32_t buf_addr;
+    uint16_t size;
+    uint16_t pad1;
+} eepro100_rbd_t;
+
+typedef struct {
     uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
         tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
         tx_multiple_collisions, tx_total_collisions;
@@ -243,6 +254,7 @@
     /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
     uint32_t ru_base;           /* RU base address */
     uint32_t ru_offset;         /* RU address offset */
+    uint32_t rbd_offset;         /* RBD address offset */
     uint32_t statsaddr;         /* pointer to eepro100_stats_t */
     eepro100_stats_t statistics;        /* statistical counters */
 #if 0
@@ -723,20 +735,13 @@
             uint16_t size = 0;
             uint32_t tbd_address = cb_address + 0x10;
             assert(tcb_bytes <= sizeof(buf));
-            while (size < tcb_bytes) {
-                uint32_t tx_buffer_address = ldl_phys(tbd_address);
-                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
-                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
-                tbd_address += 8;
+            if (tbd_array == 0xffffffff) {
+                /* Simplified mode. */
                 logout
                     ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
-                     tx_buffer_address, tx_buffer_size);
-                cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                         tx_buffer_size);
-                size += tx_buffer_size;
-            }
-            if (tbd_array == 0xffffffff) {
-                /* Simplified mode. Was already handled by code above. */
+                     tbd_address, tcb_bytes);
+                cpu_physical_memory_read(tbd_address, buf, tcb_bytes);
+		size = tcb_bytes;
             } else {
                 /* Flexible mode. */
                 uint8_t tbd_count = 0;
@@ -745,7 +750,7 @@
                     assert(tcb_bytes == 0);
                     for (; tbd_count < 2; tbd_count++) {
                         uint32_t tx_buffer_address = ldl_phys(tbd_address);
-                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4) & 0x3fff;
                         uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
                         tbd_address += 8;
                         logout
@@ -868,6 +873,16 @@
         }
         set_ru_state(s, ru_ready);
         s->ru_offset = s->pointer;
+
+        eepro100_rx_t rx;
+        cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
+                                 offsetof(eepro100_rx_t, packet));
+        uint16_t rfd_command = le16_to_cpu(rx.command);
+
+        /* If the SF bit is set, then use flexible mode. */
+        if (rfd_command & 0x0008)
+            s->rbd_offset = le32_to_cpu(rx.rx_buf_addr);
+
         logout("val=0x%02x (rx start)\n", val);
         break;
     case RX_RESUME:
@@ -884,6 +899,10 @@
         logout("val=0x%02x (RU base address)\n", val);
         s->ru_base = s->pointer;
         break;
+    case RX_ABORT:      
+        /* TODO XXX _AP_ need to generate interrupts and halt all activity. */
+        set_ru_state(s, ru_idle);
+        break;
     default:
         logout("val=0x%02x (undefined RU command)\n", val);
         missing("Undefined SU command");
@@ -1538,7 +1557,7 @@
                              offsetof(eepro100_rx_t, packet));
     uint16_t rfd_command = le16_to_cpu(rx.command);
     uint16_t rfd_size = le16_to_cpu(rx.size);
-    assert(size <= rfd_size);
+
     if (size < 64) {
         rfd_status |= 0x0080;
     }
@@ -1546,15 +1565,33 @@
            rx.link, rx.rx_buf_addr, rfd_size);
     stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
              rfd_status);
-    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
     /* Early receive interrupt not supported. */
     //~ eepro100_er_interrupt(s);
     /* Receive CRC Transfer not supported. */
     assert(!(s->configuration[18] & 4));
     /* TODO: check stripping enable bit. */
     //~ assert(!(s->configuration[17] & 1));
-    cpu_physical_memory_write(s->ru_base + s->ru_offset +
-                              offsetof(eepro100_rx_t, packet), buf, size);
+
+    if (rfd_command & 0x0008) {
+	/* XXX TODO _AP_ support more links */
+	eepro100_rbd_t rbd;
+	int wrote = 0;
+	do {
+            cpu_physical_memory_read(s->ru_base + s->rbd_offset, (uint8_t *) &rbd, sizeof(rbd));
+            int w = (size - wrote) > rbd.size ? rbd.size : (size - wrote);
+            cpu_physical_memory_write(s->ru_base + rbd.buf_addr, buf + wrote, w);
+            stw_phys(s->ru_base + s->rbd_offset, w | 0x8000 | 0x4000);
+            wrote += w;
+            s->rbd_offset = le32_to_cpu(rbd.link);
+	} while(wrote < size);
+    } else {
+        /* Simplified mode. */
+        assert(size <= rfd_size);
+        cpu_physical_memory_write(s->ru_base + s->ru_offset +
+                                  offsetof(eepro100_rx_t, packet), buf, size);
+    }
+    /* Update the EOF and F bits in addition to setting the size. */
+    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size | 0x8000 | 0x4000);
     s->statistics.rx_good_frames++;
     eepro100_fr_interrupt(s);
     s->ru_offset = le32_to_cpu(rx.link);
@@ -1624,6 +1661,7 @@
     qemu_get_be32s(f, &s->cu_offset);
     qemu_get_be32s(f, &s->ru_base);
     qemu_get_be32s(f, &s->ru_offset);
+    qemu_get_be32s(f, &s->rbd_offset);
     qemu_get_be32s(f, &s->statsaddr);
     /* Restore epro100_stats_t statistics */
     qemu_get_be32s(f, &s->statistics.tx_good_frames);
@@ -1703,6 +1741,7 @@
     qemu_put_be32s(f, &s->cu_offset);
     qemu_put_be32s(f, &s->ru_base);
     qemu_put_be32s(f, &s->ru_offset);
+    qemu_put_be32s(f, &s->rbd_offset);
     qemu_put_be32s(f, &s->statsaddr);
     /* Save epro100_stats_t statistics */
     qemu_put_be32s(f, &s->statistics.tx_good_frames);
