Patchwork eepro100: Restructure code

login
register
mail settings
Submitter Stefan Weil
Date Oct. 2, 2009, 6:57 p.m.
Message ID <1254509872-13051-1-git-send-email-weil@mail.berlios.de>
Download mbox | patch
Permalink /patch/34874/
State Superseded
Headers show

Comments

Stefan Weil - Oct. 2, 2009, 6:57 p.m.
* Move common code for CU_START, CU_RESUME
  to new function action_command.

* Move code for CmdTx to new function tx_command.

This patch is a step to synchronize my maintainer version
of eepro100.c (git://repo.or.cz/qemu/ar7.git) with the
version integrated in QEMU.

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
---
 hw/eepro100.c |  270 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 142 insertions(+), 128 deletions(-)

Patch

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6d49bb8..e2f6e8a 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -56,7 +56,7 @@ 
 #define KiB 1024
 
 /* Debug EEPRO100 card. */
-//~ #define DEBUG_EEPRO100
+/* #define DEBUG_EEPRO100 */
 
 #ifdef DEBUG_EEPRO100
 #define logout(fmt, ...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ## __VA_ARGS__)
@@ -214,6 +214,11 @@  typedef struct {
     uint32_t ru_base;           /* RU base address */
     uint32_t ru_offset;         /* RU address offset */
     uint32_t statsaddr;         /* pointer to eepro100_stats_t */
+
+    /* Temporary data. */
+    eepro100_tx_t tx;
+    uint32_t cb_address;
+
     /* Statistical counters. Also used for wake-up packet (i82559). */
     eepro100_stats_t statistics;
 #if 0
@@ -412,13 +417,9 @@  static void pci_reset(EEPRO100State * s)
     /* check cache line size!!! */
     //~ PCI_CONFIG_8(0x0c, 0x00);
     /* PCI Latency Timer */
-    PCI_CONFIG_8(0x0d, 0x20);   // latency timer = 32 clocks
+    PCI_CONFIG_8(0x0d, 0x20);   /* latency timer = 32 clocks */
     /* PCI Header Type */
     /* BIST (built-in self test) */
-#if defined(TARGET_I386)
-// !!! workaround for buggy bios
-//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0
-#endif
 #if 0
     /* PCI Base Address Registers */
     /* CSR Memory Mapped Base Address */
@@ -437,7 +438,7 @@  static void pci_reset(EEPRO100State * s)
     PCI_CONFIG_8(0x34, 0xdc);
     /* Interrupt Line */
     /* Interrupt Pin */
-    PCI_CONFIG_8(0x3d, 1);      // interrupt pin 0
+    PCI_CONFIG_8(0x3d, 1);      /* interrupt pin 0 */
     /* Minimum Grant */
     PCI_CONFIG_8(0x3e, 0x08);
     /* Maximum Latency */
@@ -631,49 +632,122 @@  static void dump_statistics(EEPRO100State * s)
     //~ missing("CU dump statistical counters");
 }
 
-static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
-{
-    eepro100_tx_t tx;
-    uint32_t cb_address;
-    switch (val) {
-    case CU_NOP:
-        /* No operation. */
-        break;
-    case CU_START:
-        if (get_cu_state(s) != cu_idle) {
-            /* Intel documentation says that CU must be idle for the CU
-             * start command. Intel driver for Linux also starts the CU
-             * from suspended state. */
-            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);
-            //~ assert(!"wrong CU state");
+static void tx_command(EEPRO100State *s)
+{
+    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
+    uint8_t buf[2600];
+    uint16_t size = 0;
+    uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr);
+    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
+    uint32_t tbd_address;
+    TRACE(RXTX, logout
+        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
+         tbd_array, tcb_bytes, s->tx.tbd_count));
+    //~ assert(!bit_sf);
+    assert(tcb_bytes <= 2600);
+    /* Next assertion fails for local configuration. */
+    //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
+    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
+        logout
+            ("illegal values of TBD array address and TCB byte count!\n");
+    }
+    tbd_address = s->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;
+        TRACE(RXTX, logout
+            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
+             tx_buffer_address, tx_buffer_size));
+        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - 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. */
+    } else {
+        /* Flexible mode. */
+        uint8_t tbd_count = 0;
+        if (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) {
+            /* Extended Flexible TCB. */
+            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_el = lduw_phys(tbd_address + 6);
+                tbd_address += 8;
+                TRACE(RXTX, logout
+                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
+                     tx_buffer_address, tx_buffer_size));
+                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
+                cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                         tx_buffer_size);
+                size += tx_buffer_size;
+                if (tx_buffer_el & 1) {
+                    break;
+                }
+            }
         }
-        set_cu_state(s, cu_active);
-        s->cu_offset = s->pointer;
-      next_command:
-        cb_address = s->cu_base + s->cu_offset;
-        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));
-        uint16_t status = le16_to_cpu(tx.status);
-        uint16_t command = le16_to_cpu(tx.command);
+        tbd_address = tbd_array;
+        for (; tbd_count < s->tx.tbd_count; 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_el = lduw_phys(tbd_address + 6);
+            tbd_address += 8;
+            TRACE(RXTX, logout
+                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
+                 tx_buffer_address, tx_buffer_size));
+            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
+            cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                     tx_buffer_size);
+            size += tx_buffer_size;
+            if (tx_buffer_el & 1) {
+                break;
+            }
+        }
+    }
+    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
+    qemu_send_packet(s->vc, buf, size);
+    s->statistics.tx_good_frames++;
+    /* Transmit with bad status would raise an CX/TNO interrupt.
+     * (82557 only). Emulation never has bad status. */
+    //~ eepro100_cx_interrupt(s);
+}
+
+static void action_command(EEPRO100State *s)
+{
+    for (;;) {
+        uint16_t status;
+        uint16_t command;
+        bool bit_el;
+        bool bit_s;
+        bool bit_i;
+        uint16_t cmd;
+        s->cb_address = s->cu_base + s->cu_offset;
+        cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx, sizeof(s->tx));
+        status = le16_to_cpu(s->tx.status);
+        command = le16_to_cpu(s->tx.command);
         logout
             ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
-             val, status, command, tx.link);
-        bool bit_el = ((command & 0x8000) != 0);
-        bool bit_s = ((command & 0x4000) != 0);
-        bool bit_i = ((command & 0x2000) != 0);
-        bool bit_nc = ((command & 0x0010) != 0);
-        //~ bool bit_sf = ((command & 0x0008) != 0);
-        uint16_t cmd = command & 0x0007;
-        s->cu_offset = le32_to_cpu(tx.link);
+             val, status, command, s->tx.link);
+        bit_el = ((command & 0x8000) != 0);
+        bit_s = ((command & 0x4000) != 0);
+        bit_i = ((command & 0x2000) != 0);
+        cmd = command & 0x0007;
+        s->cu_offset = le32_to_cpu(s->tx.link);
         switch (cmd) {
         case CmdNOp:
             /* Do nothing. */
             break;
         case CmdIASetup:
-            cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6);
+            cpu_physical_memory_read(s->cb_address + 8, &s->macaddr[0], 6);
             TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));
             break;
         case CmdConfigure:
-            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],
+            cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
                                      sizeof(s->configuration));
             TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
             break;
@@ -681,88 +755,7 @@  static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
             //~ missing("multicast list");
             break;
         case CmdTx:
-            (void)0;
-            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);
-            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);
-            TRACE(RXTX, logout
-                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
-                 tbd_array, tcb_bytes, tx.tbd_count));
-            assert(!bit_nc);
-            //~ assert(!bit_sf);
-            assert(tcb_bytes <= 2600);
-            /* Next assertion fails for local configuration. */
-            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
-            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
-                logout
-                    ("illegal values of TBD array address and TCB byte count!\n");
-            }
-            // sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes
-            uint8_t buf[2600];
-            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;
-                TRACE(RXTX, logout
-                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
-                     tx_buffer_address, tx_buffer_size));
-                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - 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. */
-            } else {
-                /* Flexible mode. */
-                uint8_t tbd_count = 0;
-                if (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) {
-                    /* Extended Flexible TCB. */
-                    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_el = lduw_phys(tbd_address + 6);
-                        tbd_address += 8;
-                        TRACE(RXTX, logout
-                            ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
-                             tx_buffer_address, tx_buffer_size));
-                        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
-                        cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                                 tx_buffer_size);
-                        size += tx_buffer_size;
-                        if (tx_buffer_el & 1) {
-                            break;
-                        }
-                    }
-                }
-                tbd_address = tbd_array;
-                for (; tbd_count < tx.tbd_count; 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_el = lduw_phys(tbd_address + 6);
-                    tbd_address += 8;
-                    TRACE(RXTX, logout
-                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
-                         tx_buffer_address, tx_buffer_size));
-                    tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
-                    cpu_physical_memory_read(tx_buffer_address, &buf[size],
-                                             tx_buffer_size);
-                    size += tx_buffer_size;
-                    if (tx_buffer_el & 1) {
-                        break;
-                    }
-                }
-            }
-            TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
-            qemu_send_packet(s->vc, buf, size);
-            s->statistics.tx_good_frames++;
-            /* Transmit with bad status would raise an CX/TNO interrupt.
-             * (82557 only). Emulation never has bad status. */
-            //~ eepro100_cx_interrupt(s);
+            tx_command(s);
             break;
         case CmdTDR:
             TRACE(OTHER, logout("load microcode\n"));
@@ -773,7 +766,7 @@  static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
             missing("undefined command");
         }
         /* Write new status (success). */
-        stw_phys(cb_address, status | 0x8000 | 0x2000);
+        stw_phys(s->cb_address, status | 0x8000 | 0x2000);
         if (bit_i) {
             /* CU completed action. */
             eepro100_cx_interrupt(s);
@@ -782,17 +775,38 @@  static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
             /* CU becomes idle. Terminate command loop. */
             set_cu_state(s, cu_idle);
             eepro100_cna_interrupt(s);
+            break;
         } else if (bit_s) {
-            /* CU becomes suspended. */
+            /* CU becomes suspended. Terminate command loop. */
             set_cu_state(s, cu_suspended);
             eepro100_cna_interrupt(s);
+            break;
         } else {
             /* More entries in list. */
             TRACE(OTHER, logout("CU list with at least one more entry\n"));
-            goto next_command;
         }
-        TRACE(OTHER, logout("CU list empty\n"));
-        /* List is empty. Now CU is idle or suspended. */
+    }
+    TRACE(OTHER, logout("CU list empty\n"));
+    /* List is empty. Now CU is idle or suspended. */
+}
+
+static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
+{
+    switch (val) {
+    case CU_NOP:
+        /* No operation. */
+        break;
+    case CU_START:
+        if (get_cu_state(s) != cu_idle) {
+            /* Intel documentation says that CU must be idle for the CU
+             * start command. Intel driver for Linux also starts the CU
+             * from suspended state. */
+            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);
+            //~ assert(!"wrong CU state");
+        }
+        set_cu_state(s, cu_active);
+        s->cu_offset = s->pointer;
+        action_command(s);
         break;
     case CU_RESUME:
         if (get_cu_state(s) != cu_suspended) {
@@ -805,7 +819,7 @@  static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
         if (get_cu_state(s) == cu_suspended) {
             TRACE(OTHER, logout("CU resuming\n"));
             set_cu_state(s, cu_active);
-            goto next_command;
+            action_command(s);
         }
         break;
     case CU_STATSADDR:
@@ -1505,7 +1519,7 @@  static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
          * Long frames are discarded. */
         logout("%p received long frame (%zu byte), ignored\n", s, size);
         return -1;
-    } else if (memcmp(buf, s->macaddr, 6) == 0) {       // !!!
+    } else if (memcmp(buf, s->macaddr, 6) == 0) {       /* !!! */
         /* Frame matches individual address. */
         /* TODO: check configuration byte 15/4 (ignore U/L). */
         TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size));
@@ -1513,7 +1527,7 @@  static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
         /* Broadcast frame. */
         TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
         rfd_status |= 0x0002;
-    } else if (buf[0] & 0x01) { // !!!
+    } else if (buf[0] & 0x01) { /* !!! */
         /* Multicast frame. */
         TRACE(RXTX, logout("%p received multicast, len=%zu\n", s, size));
         /* TODO: check multicast all bit. */