Index: hw/rtl8139.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/rtl8139.c,v
retrieving revision 1.16
diff -u -r1.16 rtl8139.c
--- hw/rtl8139.c	18 Nov 2007 01:44:38 -0000	1.16
+++ hw/rtl8139.c	20 Nov 2007 21:58:23 -0000
@@ -47,6 +47,7 @@
 #include "pci.h"
 #include "qemu-timer.h"
 #include "net.h"
+#include "eeprom93xx.h"
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
@@ -367,31 +368,6 @@
     Chip9346_op_write_disable = 0x00, /* 00 00zzzz */
 };
 
-enum Chip9346Mode
-{
-    Chip9346_none = 0,
-    Chip9346_enter_command_mode,
-    Chip9346_read_command,
-    Chip9346_data_read,      /* from output register */
-    Chip9346_data_write,     /* to input register, then to contents at specified address */
-    Chip9346_data_write_all, /* to input register, then filling contents */
-};
-
-typedef struct EEprom9346
-{
-    uint16_t contents[EEPROM_9346_SIZE];
-    int      mode;
-    uint32_t tick;
-    uint8_t  address;
-    uint16_t input;
-    uint16_t output;
-
-    uint8_t eecs;
-    uint8_t eesk;
-    uint8_t eedi;
-    uint8_t eedo;
-} EEprom9346;
-
 typedef struct RTL8139TallyCounters
 {
     /* Tally counters */
@@ -478,7 +454,7 @@
     uint32_t   RxRingAddrLO;
     uint32_t   RxRingAddrHI;
 
-    EEprom9346 eeprom;
+    eeprom_t  *eeprom;
 
     uint32_t   TCTR;
     uint32_t   TimerInt;
@@ -497,191 +473,7 @@
 
 } RTL8139State;
 
-static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
-{
-    DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
-
-    switch (command & Chip9346_op_mask)
-    {
-        case Chip9346_op_read:
-        {
-            eeprom->address = command & EEPROM_9346_ADDR_MASK;
-            eeprom->output = eeprom->contents[eeprom->address];
-            eeprom->eedo = 0;
-            eeprom->tick = 0;
-            eeprom->mode = Chip9346_data_read;
-            DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
-                   eeprom->address, eeprom->output));
-        }
-        break;
-
-        case Chip9346_op_write:
-        {
-            eeprom->address = command & EEPROM_9346_ADDR_MASK;
-            eeprom->input = 0;
-            eeprom->tick = 0;
-            eeprom->mode = Chip9346_none; /* Chip9346_data_write */
-            DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",
-                   eeprom->address));
-        }
-        break;
-        default:
-            eeprom->mode = Chip9346_none;
-            switch (command & Chip9346_op_ext_mask)
-            {
-                case Chip9346_op_write_enable:
-                    DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));
-                    break;
-                case Chip9346_op_write_all:
-                    DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));
-                    break;
-                case Chip9346_op_write_disable:
-                    DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));
-                    break;
-            }
-            break;
-    }
-}
-
-static void prom9346_shift_clock(EEprom9346 *eeprom)
-{
-    int bit = eeprom->eedi?1:0;
-
-    ++ eeprom->tick;
-
-    DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo));
-
-    switch (eeprom->mode)
-    {
-        case Chip9346_enter_command_mode:
-            if (bit)
-            {
-                eeprom->mode = Chip9346_read_command;
-                eeprom->tick = 0;
-                eeprom->input = 0;
-                DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n"));
-            }
-            break;
-
-        case Chip9346_read_command:
-            eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 8)
-            {
-                prom9346_decode_command(eeprom, eeprom->input & 0xff);
-            }
-            break;
-
-        case Chip9346_data_read:
-            eeprom->eedo = (eeprom->output & 0x8000)?1:0;
-            eeprom->output <<= 1;
-            if (eeprom->tick == 16)
-            {
-#if 1
-        // the FreeBSD drivers (rl and re) don't explicitly toggle
-        // CS between reads (or does setting Cfg9346 to 0 count too?),
-        // so we need to enter wait-for-command state here
-                eeprom->mode = Chip9346_enter_command_mode;
-                eeprom->input = 0;
-                eeprom->tick = 0;
-
-                DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n"));
-#else
-        // original behaviour
-                ++eeprom->address;
-                eeprom->address &= EEPROM_9346_ADDR_MASK;
-                eeprom->output = eeprom->contents[eeprom->address];
-                eeprom->tick = 0;
-
-                DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
-                       eeprom->address, eeprom->output));
-#endif
-            }
-            break;
-
-        case Chip9346_data_write:
-            eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 16)
-            {
-                DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
-                       eeprom->address, eeprom->input));
-
-                eeprom->contents[eeprom->address] = eeprom->input;
-                eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
-                eeprom->tick = 0;
-                eeprom->input = 0;
-            }
-            break;
-
-        case Chip9346_data_write_all:
-            eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 16)
-            {
-                int i;
-                for (i = 0; i < EEPROM_9346_SIZE; i++)
-                {
-                    eeprom->contents[i] = eeprom->input;
-                }
-                DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",
-                       eeprom->input));
-
-                eeprom->mode = Chip9346_enter_command_mode;
-                eeprom->tick = 0;
-                eeprom->input = 0;
-            }
-            break;
-
-        default:
-            break;
-    }
-}
-
-static int prom9346_get_wire(RTL8139State *s)
-{
-    EEprom9346 *eeprom = &s->eeprom;
-    if (!eeprom->eecs)
-        return 0;
-
-    return eeprom->eedo;
-}
-
 /* FIXME: This should be merged into/replaced by eeprom93xx.c.  */
-static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
-{
-    EEprom9346 *eeprom = &s->eeprom;
-    uint8_t old_eecs = eeprom->eecs;
-    uint8_t old_eesk = eeprom->eesk;
-
-    eeprom->eecs = eecs;
-    eeprom->eesk = eesk;
-    eeprom->eedi = eedi;
-
-    DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
-                 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));
-
-    if (!old_eecs && eecs)
-    {
-        /* Synchronize start */
-        eeprom->tick = 0;
-        eeprom->input = 0;
-        eeprom->output = 0;
-        eeprom->mode = Chip9346_enter_command_mode;
-
-        DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));
-    }
-
-    if (!eecs)
-    {
-        DEBUG_PRINT(("=== eeprom: end access\n"));
-        return;
-    }
-
-    if (!old_eesk && eesk)
-    {
-        /* SK front rules */
-        prom9346_shift_clock(eeprom);
-    }
-}
-
 static void rtl8139_update_irq(RTL8139State *s)
 {
     int isr;
@@ -1181,17 +973,21 @@
 
     rtl8139_update_irq(s);
 
+    s->eeprom = eeprom93xx_new(EEPROM_9346_SIZE);
+
+    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
+
     /* prepare eeprom */
-    s->eeprom.contents[0] = 0x8129;
+    eeprom_contents[0] = 0x8129;
 #if 1
     // PCI vendor and device ID should be mirrored here
-    s->eeprom.contents[1] = 0x10ec;
-    s->eeprom.contents[2] = 0x8139;
+    eeprom_contents[1] = 0x10ec;
+    eeprom_contents[2] = 0x8139;
 #endif
 
-    s->eeprom.contents[7] = s->macaddr[0] | s->macaddr[1] << 8;
-    s->eeprom.contents[8] = s->macaddr[2] | s->macaddr[3] << 8;
-    s->eeprom.contents[9] = s->macaddr[4] | s->macaddr[5] << 8;
+    eeprom_contents[7] = s->macaddr[0] | s->macaddr[1] << 8;
+    eeprom_contents[8] = s->macaddr[2] | s->macaddr[3] << 8;
+    eeprom_contents[9] = s->macaddr[4] | s->macaddr[5] << 8;
 
     /* mark all status registers as owned by host */
     for (i = 0; i < 4; ++i)
@@ -1530,7 +1326,8 @@
         int eecs = (eeprom_val & 0x08)?1:0;
         int eesk = (eeprom_val & 0x04)?1:0;
         int eedi = (eeprom_val & 0x02)?1:0;
-        prom9346_set_wire(s, eecs, eesk, eedi);
+
+        eeprom93xx_write(s->eeprom, eecs, eesk, eedi);
     } else if (opmode == 0x40) {
         /* Reset.  */
         val = 0;
@@ -1549,7 +1346,7 @@
     if (opmode == 0x80)
     {
         /* eeprom access */
-        int eedo = prom9346_get_wire(s);
+        int eedo = eeprom93xx_read(s->eeprom);
         if (eedo)
         {
             ret |=  0x01;
@@ -3180,21 +2977,6 @@
     qemu_put_be32s(f, &s->RxRingAddrLO);
     qemu_put_be32s(f, &s->RxRingAddrHI);
 
-    for (i=0; i<EEPROM_9346_SIZE; ++i)
-    {
-        qemu_put_be16s(f, &s->eeprom.contents[i]);
-    }
-    qemu_put_be32s(f, &s->eeprom.mode);
-    qemu_put_be32s(f, &s->eeprom.tick);
-    qemu_put_8s(f, &s->eeprom.address);
-    qemu_put_be16s(f, &s->eeprom.input);
-    qemu_put_be16s(f, &s->eeprom.output);
-
-    qemu_put_8s(f, &s->eeprom.eecs);
-    qemu_put_8s(f, &s->eeprom.eesk);
-    qemu_put_8s(f, &s->eeprom.eedi);
-    qemu_put_8s(f, &s->eeprom.eedo);
-
     qemu_put_be32s(f, &s->TCTR);
     qemu_put_be32s(f, &s->TimerInt);
     qemu_put_be64s(f, &s->TCTR_base);
@@ -3274,20 +3056,28 @@
     qemu_get_be32s(f, &s->RxRingAddrLO);
     qemu_get_be32s(f, &s->RxRingAddrHI);
 
-    for (i=0; i<EEPROM_9346_SIZE; ++i)
+    /* since version 4 eeprom contents are handled by eeprom93xx */
+    if (version_id <= 3)
     {
-        qemu_get_be16s(f, &s->eeprom.contents[i]);
+        uint16_t dummy;
+        uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
+
+        for (i=0; i<EEPROM_9346_SIZE; ++i)
+        {
+            qemu_get_be16s(f, &dummy);
+        }
+
+        qemu_get_be32s(f, &i); /* unused */
+        qemu_get_be32s(f, &i); /* unused */
+        qemu_get_8s(f, &i); /* unused */
+        qemu_get_be16s(f, &i); /* unused */
+        qemu_get_be16s(f, &i); /* unused */
+
+        qemu_get_8s(f, &i); /* unused */
+        qemu_get_8s(f, &i); /* unused */
+        qemu_get_8s(f, &i); /* unused */
+        qemu_get_8s(f, &i); /* unused */
     }
-    qemu_get_be32s(f, &s->eeprom.mode);
-    qemu_get_be32s(f, &s->eeprom.tick);
-    qemu_get_8s(f, &s->eeprom.address);
-    qemu_get_be16s(f, &s->eeprom.input);
-    qemu_get_be16s(f, &s->eeprom.output);
-
-    qemu_get_8s(f, &s->eeprom.eecs);
-    qemu_get_8s(f, &s->eeprom.eesk);
-    qemu_get_8s(f, &s->eeprom.eedi);
-    qemu_get_8s(f, &s->eeprom.eedo);
 
     /* saved since version 2 */
     if (version_id >= 2)
@@ -3464,7 +3254,7 @@
     s->cplus_txbuffer_offset = 0;
 
     /* XXX: instance number ? */
-    register_savevm("rtl8139", 0, 3, rtl8139_save, rtl8139_load, s);
+    register_savevm("rtl8139", 0, 4, rtl8139_save, rtl8139_load, s);
 
 #if RTL8139_ONBOARD_TIMER
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
