Merge zizzer.eecs.umich.edu:/bk/newmem
authorGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 19:16:36 +0000 (19:16 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 15 Mar 2007 19:16:36 +0000 (19:16 +0000)
into  ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86

--HG--
extra : convert_revision : cf2cc07f18b877f980e2d1fc83916f7849d9c7d9

13 files changed:
src/cpu/o3/thread_context_impl.hh
src/cpu/ozone/cpu_impl.hh
src/cpu/simple_thread.cc
src/dev/SConscript
src/dev/i8254xGBe.cc
src/dev/i8254xGBe.hh
src/dev/i8254xGBe_defs.hh
util/statetrace/Makefile
util/statetrace/arch/tracechild_sparc.cc
util/statetrace/arch/tracechild_sparc.hh
util/statetrace/statetrace.cc
util/statetrace/tracechild.cc
util/statetrace/tracechild.hh

index d2acc6232969d93b3b35cff8fb0da488b546b1e1..a145e046e1036adc96885b661c8aea281bc3a48a 100755 (executable)
@@ -103,7 +103,7 @@ void
 O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp)
 {
     if (vp != thread->getVirtPort()) {
-        delete vp->getPeer();
+        vp->removeConn();
         delete vp;
     }
 }
index 4a76ae11074206209bf01eee99ebf7f1da1eccdc..d78162243c31d6cdf0b906f56e4d2c1743b710ef 100644 (file)
@@ -748,7 +748,7 @@ template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::delVirtPort(VirtualPort *vp)
 {
-    delete vp->getPeer();
+    vp->removeConn();
     delete vp;
 }
 #endif
index 13d0e2e291ace750531303b190244444257eb617..39f31782b09520aec5639e044d258a5e97480d55 100644 (file)
@@ -305,7 +305,7 @@ void
 SimpleThread::delVirtPort(VirtualPort *vp)
 {
     if (vp != virtPort) {
-        delete vp->getPeer();
+        vp->removeConn();
         delete vp;
     }
 }
index 1ec83de4b6cfac30fa81b6dd763b2d5a535caecc..ea529b53629e219e3fb3afcd3a0439e047dfbe91 100644 (file)
@@ -40,7 +40,7 @@ if env['FULL_SYSTEM']:
     Source('etherlink.cc')
     Source('etherpkt.cc')
     Source('ethertap.cc')      
-    #Source('i8254xGBe.cc')
+    Source('i8254xGBe.cc')
     Source('ide_ctrl.cc')
     Source('ide_disk.cc')
     Source('io_device.cc')
index 7fc68f4e7abcb2674a306cc0fb5fc380376f09e7..5476ef9eba41ab808eb91ca939e1812c79c620f9 100644 (file)
 using namespace iGbReg;
 
 IGbE::IGbE(Params *p)
-    : PciDev(p), etherInt(NULL)
+    : PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control)
 {
     // Initialized internal registers per Intel documentation
-    regs.tctl.reg       = 0;
-    regs.rctl.reg       = 0;
-    regs.ctrl.reg       = 0;
-    regs.ctrl.fd        = 1;
-    regs.ctrl.lrst      = 1;
-    regs.ctrl.speed     = 2;
-    regs.ctrl.frcspd    = 1;
-    regs.sts.reg        = 0;
-    regs.eecd.reg       = 0;
-    regs.eecd.fwe       = 1;
-    regs.eecd.ee_type   = 1;
-    regs.eerd.reg       = 0;
-    regs.icd.reg        = 0;
-    regs.imc.reg        = 0;
-    regs.rctl.reg       = 0;
-    regs.tctl.reg       = 0;
-    regs.manc.reg       = 0;
-
-    regs.pba.rxa        = 0x30;
-    regs.pba.txa        = 0x10;
+    regs.tctl(0);
+    regs.rctl(0);
+    regs.ctrl(0);
+    regs.ctrl.fd(1);
+    regs.ctrl.lrst(1);
+    regs.ctrl.speed(2);
+    regs.ctrl.frcspd(1);
+    regs.sts(0);
+    regs.sts.speed(3); // Say we're 1000Mbps
+    regs.sts.fd(1); // full duplex
+    regs.eecd(0);
+    regs.eecd.fwe(1);
+    regs.eecd.ee_type(1);
+    regs.eerd(0);
+    regs.icr(0);
+    regs.rctl(0);
+    regs.tctl(0);
+    regs.fcrtl(0);
+    regs.fcrth(1);
+    regs.manc(0);
+
+    regs.pba.rxa(0x30);
+    regs.pba.txa(0x10);
 
     eeOpBits            = 0;
     eeAddrBits          = 0;
@@ -78,8 +81,17 @@ IGbE::IGbE(Params *p)
     // clear all 64 16 bit words of the eeprom
     memset(&flash, 0, EEPROM_SIZE*2);
 
+    //We'll need to instert the MAC address into the flash
+    flash[0] = 0xA4A4;
+    flash[1] = 0xB6B6;
+    flash[2] = 0xC8C8;
+
+    uint16_t csum = 0;
+    for (int x = 0; x < EEPROM_SIZE; x++)
+        csum += flash[x];
+
     // Magic happy checksum value
-    flash[0] = 0xBABA;
+    flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum));
 }
 
 
@@ -124,47 +136,112 @@ IGbE::read(PacketPtr pkt)
 
 
     switch (daddr) {
-      case CTRL:
-       pkt->set<uint32_t>(regs.ctrl.reg);
-       break;
-      case STATUS:
-       pkt->set<uint32_t>(regs.sts.reg);
-       break;
-      case EECD:
-       pkt->set<uint32_t>(regs.eecd.reg);
-       break;
-      case EERD:
-       pkt->set<uint32_t>(regs.eerd.reg);
-       break;
-      case ICR:
-       pkt->set<uint32_t>(regs.icd.reg);
-       break;
-      case IMC:
-       pkt->set<uint32_t>(regs.imc.reg);
-       break;
-      case RCTL:
-       pkt->set<uint32_t>(regs.rctl.reg);
-       break;
-      case TCTL:
-       pkt->set<uint32_t>(regs.tctl.reg);
-       break;
-      case PBA:
-       pkt->set<uint32_t>(regs.pba.reg);
-       break;
-      case WUC:
-      case LEDCTL:
-       pkt->set<uint32_t>(0); // We don't care, so just return 0
-       break;
-      case MANC:
-       pkt->set<uint32_t>(regs.manc.reg);
-       break;
+      case REG_CTRL:
+        pkt->set<uint32_t>(regs.ctrl());
+        break;
+      case REG_STATUS:
+        pkt->set<uint32_t>(regs.sts());
+        break;
+      case REG_EECD:
+        pkt->set<uint32_t>(regs.eecd());
+        break;
+      case REG_EERD:
+        pkt->set<uint32_t>(regs.eerd());
+        break;
+      case REG_CTRL_EXT:
+        pkt->set<uint32_t>(regs.ctrl_ext());
+        break;
+      case REG_MDIC:
+        pkt->set<uint32_t>(regs.mdic());
+        break;
+      case REG_ICR:
+        pkt->set<uint32_t>(regs.icr());
+        // handle auto setting mask from IAM
+        break;
+      case REG_ITR:
+        pkt->set<uint32_t>(regs.itr());
+        break;
+      case REG_RCTL:
+        pkt->set<uint32_t>(regs.rctl());
+        break;
+      case REG_FCTTV:
+        pkt->set<uint32_t>(regs.fcttv());
+        break;
+      case REG_TCTL:
+        pkt->set<uint32_t>(regs.tctl());
+        break;
+      case REG_PBA:
+        pkt->set<uint32_t>(regs.pba());
+        break;
+      case REG_WUC:
+      case REG_LEDCTL:
+        pkt->set<uint32_t>(0); // We don't care, so just return 0
+        break;
+      case REG_FCRTL:
+        pkt->set<uint32_t>(regs.fcrtl());
+        break;
+      case REG_FCRTH:
+        pkt->set<uint32_t>(regs.fcrth());
+        break;
+      case REG_RDBAL:
+        pkt->set<uint32_t>(regs.rdba.rdbal());
+        break;
+      case REG_RDBAH:
+        pkt->set<uint32_t>(regs.rdba.rdbah());
+        break;
+      case REG_RDLEN:
+        pkt->set<uint32_t>(regs.rdlen());
+        break;
+      case REG_RDH:
+        pkt->set<uint32_t>(regs.rdh());
+        break;
+      case REG_RDT:
+        pkt->set<uint32_t>(regs.rdt());
+        break;
+      case REG_RDTR:
+        pkt->set<uint32_t>(regs.rdtr());
+        break;
+      case REG_RADV:
+        pkt->set<uint32_t>(regs.radv());
+        break;
+      case REG_TDBAL:
+        pkt->set<uint32_t>(regs.tdba.tdbal());
+        break;
+      case REG_TDBAH:
+        pkt->set<uint32_t>(regs.tdba.tdbah());
+        break;
+      case REG_TDLEN:
+        pkt->set<uint32_t>(regs.tdlen());
+        break;
+      case REG_TDH:
+        pkt->set<uint32_t>(regs.tdh());
+        break;
+      case REG_TDT:
+        pkt->set<uint32_t>(regs.tdt());
+        break;
+      case REG_TIDV:
+        pkt->set<uint32_t>(regs.tidv());
+        break;
+      case REG_TXDCTL:
+        pkt->set<uint32_t>(regs.txdctl());
+        break;
+      case REG_TADV:
+        pkt->set<uint32_t>(regs.tadv());
+        break;
+      case REG_RXCSUM:
+        pkt->set<uint32_t>(regs.rxcsum());
+        break;
+      case REG_MANC:
+        pkt->set<uint32_t>(regs.manc());
+        break;
       default:
-       if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
-           !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
-           !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
-           pkt->set<uint32_t>(0);
-       else
-           panic("Read request to unknown register number: %#x\n", daddr);
+        if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
+            !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
+            !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)) &&
+            !(daddr >= REG_CRCERRS && daddr < (REG_CRCERRS + STATS_REGS_SIZE)))
+            panic("Read request to unknown register number: %#x\n", daddr);
+        else
+            pkt->set<uint32_t>(0);
     };
 
     pkt->result = Packet::Success;
@@ -195,92 +272,211 @@ IGbE::write(PacketPtr pkt)
     uint32_t val = pkt->get<uint32_t>();
 
     switch (daddr) {
-      case CTRL:
-       regs.ctrl.reg = val;
-       break;
-      case STATUS:
-       regs.sts.reg = val;
-       break;
-      case EECD:
-       int oldClk;
-       oldClk = regs.eecd.sk;
-       regs.eecd.reg = val;
-       // See if this is a eeprom access and emulate accordingly
-       if (!oldClk && regs.eecd.sk) {
-           if (eeOpBits < 8) {
-               eeOpcode = eeOpcode << 1 | regs.eecd.din;
-               eeOpBits++;
-           } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
-               eeAddr = eeAddr << 1 | regs.eecd.din;
-               eeAddrBits++;
-           } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
-               assert(eeAddr>>1 < EEPROM_SIZE);
-               DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
-                       flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]);
-               regs.eecd.dout = (flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1;
-               eeDataBits++;
-           } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
-               regs.eecd.dout = 0;
-               eeDataBits++;
-           } else
-               panic("What's going on with eeprom interface? opcode:"
-                      " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode,
-                      (uint32_t)eeOpBits, (uint32_t)eeAddr,
-                      (uint32_t)eeAddrBits, (uint32_t)eeDataBits);
-
-           // Reset everything for the next command
-           if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) ||
+      case REG_CTRL:
+        regs.ctrl = val;
+        if (regs.ctrl.tfce())
+            warn("TX Flow control enabled, should implement\n");
+        if (regs.ctrl.rfce())
+            warn("RX Flow control enabled, should implement\n");
+        break;
+      case REG_CTRL_EXT:
+        regs.ctrl_ext = val;
+        break;
+      case REG_STATUS:
+        regs.sts = val;
+        break;
+      case REG_EECD:
+        int oldClk;
+        oldClk = regs.eecd.sk();
+        regs.eecd = val;
+        // See if this is a eeprom access and emulate accordingly
+        if (!oldClk && regs.eecd.sk()) {
+            if (eeOpBits < 8) {
+                eeOpcode = eeOpcode << 1 | regs.eecd.din();
+                eeOpBits++;
+            } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
+                eeAddr = eeAddr << 1 | regs.eecd.din();
+                eeAddrBits++;
+            } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
+                assert(eeAddr>>1 < EEPROM_SIZE);
+                DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
+                        flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]);
+                regs.eecd.dout((flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1);
+                eeDataBits++;
+            } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
+                regs.eecd.dout(0);
+                eeDataBits++;
+            } else
+                panic("What's going on with eeprom interface? opcode:"
+                       " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode,
+                       (uint32_t)eeOpBits, (uint32_t)eeAddr,
+                       (uint32_t)eeAddrBits, (uint32_t)eeDataBits);
+
+            // Reset everything for the next command
+            if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) ||
                (eeDataBits == 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI)) {
-               eeOpBits = 0;
-               eeAddrBits = 0;
-               eeDataBits = 0;
+                eeOpBits = 0;
+                eeAddrBits = 0;
+                eeDataBits = 0;
                eeOpcode = 0;
-               eeAddr = 0;
-           }
+                eeAddr = 0;
+            }
 
            DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
-                   (uint32_t)eeOpcode, (uint32_t) eeOpBits,
-                   (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
+                    (uint32_t)eeOpcode, (uint32_t) eeOpBits,
+                    (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
            if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI ||
-                                  eeOpcode == EEPROM_RDSR_OPCODE_SPI ))
-               panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
-                       (uint32_t)eeOpBits);
-
-
-       }
-       // If driver requests eeprom access, immediately give it to it
-       regs.eecd.ee_gnt = regs.eecd.ee_req;
-       break;
-      case EERD:
-       regs.eerd.reg = val;
-       break;
-      case ICR:
-       regs.icd.reg = val;
-       break;
-      case IMC:
-       regs.imc.reg = val;
-       break;
-      case RCTL:
-       regs.rctl.reg = val;
-       break;
-      case TCTL:
-       regs.tctl.reg = val;
-       break;
-      case PBA:
-       regs.pba.rxa = val;
-       regs.pba.txa = 64 - regs.pba.rxa;
-       break;
-      case WUC:
-      case LEDCTL:
-       ; // We don't care, so don't store anything
-       break;
-      case MANC:
-       regs.manc.reg = val;
-       break;
+                                   eeOpcode == EEPROM_RDSR_OPCODE_SPI ))
+                panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
+                        (uint32_t)eeOpBits);
+
+
+        }
+        // If driver requests eeprom access, immediately give it to it
+        regs.eecd.ee_gnt(regs.eecd.ee_req());
+        break;
+      case REG_EERD:
+        regs.eerd = val;
+        break;
+      case REG_MDIC:
+        regs.mdic = val;
+        if (regs.mdic.i())
+            panic("No support for interrupt on mdic complete\n");
+        if (regs.mdic.phyadd() != 1)
+            panic("No support for reading anything but phy\n");
+        DPRINTF(Ethernet, "%s phy address %x\n", regs.mdic.op() == 1 ? "Writing"
+                : "Reading", regs.mdic.regadd());
+        switch (regs.mdic.regadd()) {
+            case PHY_PSTATUS:
+                regs.mdic.data(0x796D); // link up
+                break;
+            case PHY_PID:
+                regs.mdic.data(0x02A8);
+                break;
+            case PHY_EPID:
+                regs.mdic.data(0x0380);
+                break;
+            case PHY_GSTATUS:
+                regs.mdic.data(0x7C00);
+                break;
+            case PHY_EPSTATUS:
+                regs.mdic.data(0x3000);
+                break;
+            case PHY_AGC:
+                regs.mdic.data(0x180); // some random length
+                break;
+            default:
+                regs.mdic.data(0);
+                warn("Accessing unknown phy register %d\n", regs.mdic.regadd());
+        }
+        regs.mdic.r(1);
+        break;
+      case REG_ICR:
+        regs.icr = val;
+        // handle auto setting mask from IAM
+        break;
+      case REG_ITR:
+        regs.itr = val;
+        break;
+      case REG_ICS:
+        regs.icr = val | regs.icr();
+        // generate an interrupt if needed here
+        break;
+       case REG_IMS:
+        regs.imr |= val;
+        // handle interrupts if needed here
+        break;
+      case REG_IMC:
+        regs.imr |= ~val;
+        // handle interrupts if needed here
+        break;
+      case REG_IAM:
+        regs.iam = val;
+        break;
+      case REG_RCTL:
+        regs.rctl = val;
+        break;
+      case REG_FCTTV:
+        regs.fcttv = val;
+        break;
+      case REG_TCTL:
+        regs.tctl = val;
+        break;
+      case REG_PBA:
+        regs.pba.rxa(val);
+        regs.pba.txa(64 - regs.pba.rxa());
+        break;
+      case REG_WUC:
+      case REG_LEDCTL:
+      case REG_FCAL:
+      case REG_FCAH:
+      case REG_FCT:
+      case REG_VET:
+      case REG_AIFS:
+      case REG_TIPG:
+        ; // We don't care, so don't store anything
+        break;
+      case REG_FCRTL:
+        regs.fcrtl = val;
+        break;
+      case REG_FCRTH:
+        regs.fcrth = val;
+        break;
+      case REG_RDBAL:
+        regs.rdba.rdbal( val & ~mask(4));
+        break;
+      case REG_RDBAH:
+        regs.rdba.rdbah(val);
+        break;
+      case REG_RDLEN:
+        regs.rdlen = val & ~mask(7);
+        break;
+      case REG_RDH:
+        regs.rdh = val;
+        break;
+      case REG_RDT:
+        regs.rdt = val;
+        break;
+      case REG_RDTR:
+        regs.rdtr = val;
+        break;
+      case REG_RADV:
+        regs.radv = val;
+        break;
+      case REG_TDBAL:
+        regs.tdba.tdbal( val & ~mask(4));
+        break;
+      case REG_TDBAH:
+        regs.tdba.tdbah(val);
+        break;
+      case REG_TDLEN:
+        regs.tdlen = val & ~mask(7);
+        break;
+      case REG_TDH:
+        regs.tdh = val;
+        break;
+      case REG_TDT:
+        regs.tdt = val;
+        break;
+      case REG_TIDV:
+        regs.tidv = val;
+        break;
+      case REG_TXDCTL:
+        regs.txdctl = val;
+        break;
+      case REG_TADV:
+        regs.tadv = val;
+        break;
+      case REG_RXCSUM:
+        regs.rxcsum = val;
+        break;
+      case REG_MANC:
+        regs.manc = val;
+        break;
       default:
-       if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
-           !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
-           !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
+       if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
+           !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
+           !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)))
            panic("Write request to unknown register number: %#x\n", daddr);
     };
 
index ce400726330118a7edfaf473ec45d7c07c142f3c..fa9e65b22c62f233789535b7670db1047cc45c73 100644 (file)
@@ -54,13 +54,15 @@ class IGbE : public PciDev
     int eeOpBits, eeAddrBits, eeDataBits;
     uint8_t eeOpcode, eeAddr;
 
+    bool useFlowControl;
+
     uint16_t flash[iGbReg::EEPROM_SIZE];
 
 
   public:
     struct Params : public PciDev::Params
     {
-        ;
+        bool use_flow_control;
     };
 
     IGbE(Params *params);
index ae09253568bd5839d5546a620bb3489b7502ad9b..b59b34a6753b0929a547d4529fbcf7cf89b2eeef 100644 (file)
 /* @file
  * Register and structure descriptions for Intel's 8254x line of gigabit ethernet controllers.
  */
+#include "base/bitfield.hh"
 
 namespace iGbReg {
 
-const uint32_t CTRL     = 0x00000; //*
-const uint32_t STATUS   = 0x00008; //*
-const uint32_t EECD     = 0x00010; //*
-const uint32_t EERD     = 0x00014; //*
-const uint32_t CTRL_EXT = 0x00018;
-const uint32_t PBA      = 0x01000;
-const uint32_t ICR      = 0x000C0; //*
-const uint32_t ITR      = 0x000C4;
-const uint32_t ICS      = 0x000C8;
-const uint32_t IMS      = 0x000D0;
-const uint32_t IMC      = 0x000D8; //*
-const uint32_t RCTL     = 0x00100; //*
-const uint32_t RDBAL    = 0x02800;
-const uint32_t RDBAH    = 0x02804;
-const uint32_t RDLEN    = 0x02808;
-const uint32_t RDH      = 0x02810;
-const uint32_t RDT      = 0x02818;
-const uint32_t RDTR     = 0x02820;
-const uint32_t RADV     = 0x0282C;
-const uint32_t RSRPD    = 0x02C00;
-const uint32_t TCTL     = 0x00400; //*
-const uint32_t TDBAL    = 0x03800;
-const uint32_t TDBAH    = 0x03804;
-const uint32_t TDLEN    = 0x03808;
-const uint32_t TDH      = 0x03810;
-const uint32_t THT      = 0x03818;
-const uint32_t TIDV     = 0x03820;
-const uint32_t TXDMAC   = 0x03000;
-const uint32_t TXDCTL   = 0x03828;
-const uint32_t TADV     = 0x0282C;
-const uint32_t TSPMT    = 0x03830;
-const uint32_t RXDCTL   = 0x02828;
-const uint32_t RXCSUM   = 0x05000;
-const uint32_t MANC     = 0x05820;//*
+const uint32_t REG_CTRL     = 0x00000; //*
+const uint32_t REG_STATUS   = 0x00008; //*
+const uint32_t REG_EECD     = 0x00010; //*
+const uint32_t REG_EERD     = 0x00014; //*
+const uint32_t REG_CTRL_EXT = 0x00018; //*-
+const uint32_t REG_MDIC     = 0x00020; //*
+const uint32_t REG_FCAL     = 0x00028; //*
+const uint32_t REG_FCAH     = 0x0002C; //*
+const uint32_t REG_FCT      = 0x00030; //*
+const uint32_t REG_VET      = 0x00038; //*
+const uint32_t REG_PBA      = 0x01000; //*
+const uint32_t REG_ICR      = 0x000C0; //*
+const uint32_t REG_ITR      = 0x000C4; //*
+const uint32_t REG_ICS      = 0x000C8; //*
+const uint32_t REG_IMS      = 0x000D0; //*
+const uint32_t REG_IMC      = 0x000D8; //*
+const uint32_t REG_IAM      = 0x000E0; //*
+const uint32_t REG_RCTL     = 0x00100; //*
+const uint32_t REG_FCTTV    = 0x00170; //*
+const uint32_t REG_TIPG     = 0x00410; //*
+const uint32_t REG_AIFS     = 0x00458; //*
+const uint32_t REG_LEDCTL   = 0x00e00; //*
+const uint32_t REG_FCRTL    = 0x02160; //*
+const uint32_t REG_FCRTH    = 0x02168; //*
+const uint32_t REG_RDBAL    = 0x02800; //*-
+const uint32_t REG_RDBAH    = 0x02804; //*-
+const uint32_t REG_RDLEN    = 0x02808; //*-
+const uint32_t REG_RDH      = 0x02810; //*-
+const uint32_t REG_RDT      = 0x02818; //*-
+const uint32_t REG_RDTR     = 0x02820; //*-
+const uint32_t REG_RXDCTL   = 0x02828; //*
+const uint32_t REG_RADV     = 0x0282C; //*-
+const uint32_t REG_RSRPD    = 0x02C00;
+const uint32_t REG_TCTL     = 0x00400; //*
+const uint32_t REG_TDBAL    = 0x03800; //*
+const uint32_t REG_TDBAH    = 0x03804; //*
+const uint32_t REG_TDLEN    = 0x03808; //*
+const uint32_t REG_TDH      = 0x03810; //*
+const uint32_t REG_TDT      = 0x03818; //*
+const uint32_t REG_TIDV     = 0x03820; //*
+const uint32_t REG_TXDMAC   = 0x03000;
+const uint32_t REG_TXDCTL   = 0x03828; //*
+const uint32_t REG_TADV     = 0x0382C; //*
+const uint32_t REG_TSPMT    = 0x03830;
+const uint32_t REG_CRCERRS  = 0x04000;
+const uint32_t REG_RXCSUM   = 0x05000; //*-
+const uint32_t REG_MTA      = 0x05200;
+const uint32_t REG_RAL      = 0x05400;
+const uint32_t REG_RAH      = 0x05404;
+const uint32_t REG_VFTA     = 0x05600;
+
+const uint32_t REG_WUC      = 0x05800;//*
+const uint32_t REG_MANC     = 0x05820;//*
 
 const uint8_t EEPROM_READ_OPCODE_SPI    = 0x03;
 const uint8_t EEPROM_RDSR_OPCODE_SPI    = 0x05;
 const uint8_t EEPROM_SIZE               = 64;
+const uint16_t EEPROM_CSUM              = 0xBABA;
+
+const uint8_t VLAN_FILTER_TABLE_SIZE    = 128;
+const uint8_t RCV_ADDRESS_TABLE_SIZE    = 16;
+const uint8_t MULTICAST_TABLE_SIZE      = 128;
+const uint32_t STATS_REGS_SIZE           = 0x124;
+
+const uint8_t PHY_PSTATUS       = 0x1;
+const uint8_t PHY_PID           = 0x2;
+const uint8_t PHY_EPID          = 0x3;
+const uint8_t PHY_GSTATUS       = 10;
+const uint8_t PHY_EPSTATUS      = 15;
+const uint8_t PHY_AGC           = 18;
+
 
 struct RxDesc {
     Addr buf;
@@ -245,219 +279,377 @@ union TxDesc {
     } type;
 };
 
+#define ADD_FIELD32(NAME, OFFSET, BITS) \
+    inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
+    inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
+
+#define ADD_FIELD64(NAME, OFFSET, BITS) \
+    inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
+    inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
+
 struct Regs {
-    union {  // 0x0000 CTRL Register
-       uint32_t reg;
-       struct {
-           uint8_t fd:1;      // full duplex
-           uint8_t bem:1;     // big endian mode
-           uint8_t pcipr:1;   // PCI priority
-           uint8_t lrst:1;    // link reset
-           uint8_t tme:1;     // test mode enable
-           uint8_t asde:1;    // Auto-speed detection
-           uint8_t slu:1;     // Set link up
-           uint8_t ilos:1;    // invert los-of-signal
-           uint8_t speed:2;   // speed selection bits
-           uint8_t be32:1;    // big endian mode 32
-           uint8_t frcspd:1;  // force speed
-           uint8_t frcdpx:1;  // force duplex
-           uint8_t duden:1;   // dock/undock enable
-           uint8_t dudpol:1;  // dock/undock polarity
-           uint8_t fphyrst:1; // force phy reset
-           uint8_t extlen:1;  // external link status enable
-           uint8_t rsvd:1;    // reserved
-           uint8_t sdp0d:1;   // software controlled pin data
-           uint8_t sdp1d:1;   // software controlled pin data
-           uint8_t sdp2d:1;   // software controlled pin data
-           uint8_t sdp3d:1;   // software controlled pin data
-           uint8_t sdp0i:1;   // software controlled pin dir
-           uint8_t sdp1i:1;   // software controlled pin dir
-           uint8_t sdp2i:1;   // software controlled pin dir
-           uint8_t sdp3i:1;   // software controlled pin dir
-           uint8_t rst:1;     // reset
-           uint8_t rfce:1;    // receive flow control enable
-           uint8_t tfce:1;    // transmit flow control enable
-           uint8_t rte:1;     // routing tag enable
-           uint8_t vme:1;     // vlan enable
-           uint8_t phyrst:1;  // phy reset
-       } ;
-    } ctrl;
-
-    union { // 0x0008 STATUS
-        uint32_t reg;
-        struct {
-            uint8_t fd:1;      // full duplex
-            uint8_t lu:1;      // link up
-            uint8_t func:2;    // function id
-            uint8_t txoff:1;   // transmission paused
-            uint8_t tbimode:1; // tbi mode
-            uint8_t speed:2;   // link speed
-            uint8_t asdv:2;    // auto speed detection value
-            uint8_t mtxckok:1; // mtx clock running ok
-            uint8_t pci66:1;   // In 66Mhz pci slot
-            uint8_t bus64:1;   // in 64 bit slot
-            uint8_t pcix:1;    // Pci mode
-            uint8_t pcixspd:1; // pci x speed
-            uint8_t reserved;  // reserved
-        } ;
-    } sts;
-
-    union { // 0x0010 EECD
-        uint32_t reg;
-        struct {
-            uint8_t sk:1;      // clack input to the eeprom
-            uint8_t cs:1;      // chip select to eeprom
-            uint8_t din:1;     // data input to eeprom
-            uint8_t dout:1;    // data output bit
-            uint8_t fwe:2;     // flash write enable
-            uint8_t ee_req:1;  // request eeprom access
-            uint8_t ee_gnt:1;  // grant eeprom access
-            uint8_t ee_pres:1; // eeprom present
-            uint8_t ee_size:1; // eeprom size
-            uint8_t ee_sz1:1;  // eeprom size
-            uint8_t rsvd:2;    // reserved
-            uint8_t ee_type:1; // type of eeprom
-        } ;
-    } eecd;
-
-    union { // 0x0014 EERD
-        uint32_t reg;
-        struct {
-            uint8_t start:1;  // start read
-            uint8_t done:1;   // done read
-            uint16_t addr:14; // address
-            uint16_t data;    // data
-        };
-    } eerd;
+    template<class T>
+    struct Reg {
+        T _data;
+        T operator()() { return _data; }
+        const Reg<T> &operator=(T d) { _data = d; return *this;}
+        bool operator==(T d) { return d == _data; }
+        void operator()(T d) { _data = d; }
+    };
 
-    union { // 0x00C0 ICR
-        uint32_t reg;
-        struct {
-            uint8_t txdw:1;   // tx descr witten back
-            uint8_t txqe:1;   // tx queue empty
-            uint8_t lsc:1;    // link status change
-            uint8_t rxseq:1;  // rcv sequence error
-            uint8_t rxdmt0:1; // rcv descriptor min thresh
-            uint8_t rsvd1:1;  // reserved
-            uint8_t rxo:1;    // receive overrunn
-            uint8_t rxt0:1;   // receiver timer interrupt
-            uint8_t rsvd2:1;  // reserved
-            uint8_t mdac:1;   // mdi/o access complete
-            uint8_t rxcfg:1;  // recv /c/ ordered sets
-            uint8_t rsvd3:1;  // reserved
-            uint8_t phyint:1; // phy interrupt
-            uint8_t gpi1:1;   // gpi int 1
-            uint8_t gpi2:1;   // gpi int 2
-            uint8_t txdlow:1; // transmit desc low thresh
-            uint8_t srpd:1;   // small receive packet detected
-            uint16_t rsvd4:15; // reserved
-        } ;
-    } icd;
-
-    union { // 0x00C0 IMC
-        uint32_t reg;
-        struct {
-            uint8_t txdw:1;   // tx descr witten back
-            uint8_t txqe:1;   // tx queue empty
-            uint8_t lsc:1;    // link status change
-            uint8_t rxseq:1;  // rcv sequence error
-            uint8_t rxdmt0:1; // rcv descriptor min thresh
-            uint8_t rsvd1:1;  // reserved
-            uint8_t rxo:1;    // receive overrunn
-            uint8_t rxt0:1;   // receiver timer interrupt
-            uint8_t rsvd2:1;  // reserved
-            uint8_t mdac:1;   // mdi/o access complete
-            uint8_t rxcfg:1;  // recv /c/ ordered sets
-            uint8_t rsvd3:1;  // reserved
-            uint8_t phyint:1; // phy interrupt
-            uint8_t gpi1:1;   // gpi int 1
-            uint8_t gpi2:1;   // gpi int 2
-            uint8_t txdlow:1; // transmit desc low thresh
-            uint8_t srpd:1;   // small receive packet detected
-            uint16_t rsvd4:15; // reserved
-        } ;
-    } imc;
-
-    union { // 0x0100 RCTL
-        uint32_t reg;
-        struct {
-            uint8_t rst:1;   // Reset
-            uint8_t en:1;    // Enable
-            uint8_t sbp:1;   // Store bad packets
-            uint8_t upe:1;   // Unicast Promiscuous enabled
-            uint8_t mpe:1;   // Multicast promiscuous enabled
-            uint8_t lpe:1;   // long packet reception enabled
-            uint8_t lbm:2;   //
-            uint8_t rdmts:2; //
-            uint8_t rsvd:2;  //
-            uint8_t mo:2;    //
-            uint8_t mdr:1;   //
-            uint8_t bam:1;   //
-            uint8_t bsize:2; //
-            uint8_t vpe:1;   //
-            uint8_t cfien:1; //
-            uint8_t cfi:1;   //
-            uint8_t rsvd2:1; //
-            uint8_t dpf:1;   // discard pause frames
-            uint8_t pmcf:1;  // pass mac control  frames
-            uint8_t rsvd3:1; // reserved
-            uint8_t bsex:1;  // buffer size extension
-            uint8_t secrc:1; // strip ethernet crc from incoming packet
-            uint8_t rsvd1:5;  // reserved
-        } ;
-    } rctl;
-
-    union { // 0x0400 TCTL
-        uint32_t reg;
-        struct {
-            uint8_t rst:1;    // Reset
-            uint8_t en:1;     // Enable
-            uint8_t bce:1;    // busy check enable
-            uint8_t psp:1;    // pad short packets
-            uint8_t ct:8;     // collision threshold
-            uint16_t cold:10; // collision distance
-            uint8_t swxoff:1; // software xoff transmission
-            uint8_t pbe:1;    // packet burst enable
-            uint8_t rtlc:1;   // retransmit late collisions
-            uint8_t nrtu:1;   // on underrun no TX
-            uint8_t mulr:1;   // multiple request
-            uint8_t rsvd:5;   // reserved
-        } ;
-    } tctl;
-
-    union { // 0x5820 MANC
-        uint32_t reg;
-        struct {
-            uint8_t smbus:1;    // SMBus enabled #####
-            uint8_t asf:1;      // ASF enabled #####
-            uint8_t ronforce:1; // reset of force
-            uint8_t rsvd:5;     // reserved
-            uint8_t rmcp1:1;    // rcmp1 filtering
-            uint8_t rmcp2:1;    // rcmp2 filtering
-            uint8_t ipv4:1;     // enable ipv4
-            uint8_t ipv6:1;     // enable ipv6
-            uint8_t snap:1;     // accept snap
-            uint8_t arp:1;      // filter arp #####
-            uint8_t neighbor:1; // neighbor discovery
-            uint8_t arp_resp:1; // arp response
-            uint8_t tcorst:1;   // tco reset happened
-            uint8_t rcvtco:1;   // receive tco enabled ######
-            uint8_t blkphyrst:1;// block phy resets ########
-            uint8_t rcvall:1;   // receive all
-            uint8_t macaddrfltr:1; // mac address filtering ######
-            uint8_t mng2host:1; // mng2 host packets #######
-            uint8_t ipaddrfltr:1; // ip address filtering
-            uint8_t xsumfilter:1; // checksum filtering
-            uint8_t brfilter:1; // broadcast filtering
-            uint8_t smbreq:1;   // smb request
-            uint8_t smbgnt:1;   // smb grant
-            uint8_t smbclkin:1; // smbclkin
-            uint8_t smbdatain:1; // smbdatain
-            uint8_t smbdataout:1; // smb data out
-            uint8_t smbclkout:1; // smb clock out
-            uint8_t rsvd2:2;
-        };
-    } manc;
+    struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(fd,0,1);       // full duplex
+        ADD_FIELD32(bem,1,1);      // big endian mode
+        ADD_FIELD32(pcipr,2,1);    // PCI priority
+        ADD_FIELD32(lrst,3,1);     // link reset
+        ADD_FIELD32(tme,4,1);      // test mode enable
+        ADD_FIELD32(asde,5,1);     // Auto-speed detection
+        ADD_FIELD32(slu,6,1);      // Set link up
+        ADD_FIELD32(ilos,7,1);     // invert los-of-signal
+        ADD_FIELD32(speed,8,2);    // speed selection bits
+        ADD_FIELD32(be32,10,1);    // big endian mode 32
+        ADD_FIELD32(frcspd,11,1);  // force speed
+        ADD_FIELD32(frcdpx,12,1);  // force duplex
+        ADD_FIELD32(duden,13,1);   // dock/undock enable
+        ADD_FIELD32(dudpol,14,1);  // dock/undock polarity
+        ADD_FIELD32(fphyrst,15,1); // force phy reset
+        ADD_FIELD32(extlen,16,1);  // external link status enable
+        ADD_FIELD32(rsvd,17,1);    // reserved
+        ADD_FIELD32(sdp0d,18,1);   // software controlled pin data
+        ADD_FIELD32(sdp1d,19,1);   // software controlled pin data
+        ADD_FIELD32(sdp2d,20,1);   // software controlled pin data
+        ADD_FIELD32(sdp3d,21,1);   // software controlled pin data
+        ADD_FIELD32(sdp0i,22,1);   // software controlled pin dir
+        ADD_FIELD32(sdp1i,23,1);   // software controlled pin dir
+        ADD_FIELD32(sdp2i,24,1);   // software controlled pin dir
+        ADD_FIELD32(sdp3i,25,1);   // software controlled pin dir
+        ADD_FIELD32(rst,26,1);     // reset
+        ADD_FIELD32(rfce,27,1);    // receive flow control enable
+        ADD_FIELD32(tfce,28,1);    // transmit flow control enable
+        ADD_FIELD32(rte,29,1);     // routing tag enable
+        ADD_FIELD32(vme,30,1);     // vlan enable
+        ADD_FIELD32(phyrst,31,1);  // phy reset
+    };
+    CTRL ctrl;
+
+    struct STATUS : public Reg<uint32_t> { // 0x0008 STATUS Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(fd,0,1);       // full duplex
+        ADD_FIELD32(lu,1,1);       // link up
+        ADD_FIELD32(func,2,2);     // function id
+        ADD_FIELD32(txoff,4,1);    // transmission paused
+        ADD_FIELD32(tbimode,5,1);  // tbi mode
+        ADD_FIELD32(speed,6,2);    // link speed
+        ADD_FIELD32(asdv,8,2);     // auto speed detection value
+        ADD_FIELD32(mtxckok,10,1); // mtx clock running ok
+        ADD_FIELD32(pci66,11,1);   // In 66Mhz pci slot
+        ADD_FIELD32(bus64,12,1);   // in 64 bit slot
+        ADD_FIELD32(pcix,13,1);    // Pci mode
+        ADD_FIELD32(pcixspd,14,2); // pci x speed
+    };
+    STATUS sts;
+
+    struct EECD : public Reg<uint32_t> { // 0x0010 EECD Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(sk,0,1);       // clack input to the eeprom
+        ADD_FIELD32(cs,1,1);       // chip select to eeprom
+        ADD_FIELD32(din,2,1);      // data input to eeprom
+        ADD_FIELD32(dout,3,1);     // data output bit
+        ADD_FIELD32(fwe,4,2);      // flash write enable
+        ADD_FIELD32(ee_req,6,1);   // request eeprom access
+        ADD_FIELD32(ee_gnt,7,1);   // grant eeprom access
+        ADD_FIELD32(ee_pres,8,1);  // eeprom present
+        ADD_FIELD32(ee_size,9,1);  // eeprom size
+        ADD_FIELD32(ee_sz1,10,1);  // eeprom size
+        ADD_FIELD32(rsvd,11,2);    // reserved
+        ADD_FIELD32(ee_type,13,1); // type of eeprom
+    } ;
+    EECD eecd;
+
+    struct EERD : public Reg<uint32_t> { // 0x0014 EERD Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(start,0,1);  // start read
+        ADD_FIELD32(done,4,1);   // done read
+        ADD_FIELD32(addr,8,8);   // address
+        ADD_FIELD32(data,16,16); // data
+    };
+    EERD eerd;
+
+    struct CTRL_EXT : public Reg<uint32_t> { // 0x0018 CTRL_EXT Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(gpi_en,0,4);      // enable interrupts from gpio
+        ADD_FIELD32(phyint,5,1);      // reads the phy internal int status
+        ADD_FIELD32(sdp2_data,6,1);   // data from gpio sdp
+        ADD_FIELD32(spd3_data,7,1);   // data frmo gpio sdp
+        ADD_FIELD32(spd2_iodir,10,1); // direction of sdp2
+        ADD_FIELD32(spd3_iodir,11,1); // direction of sdp2
+        ADD_FIELD32(asdchk,12,1);     // initiate auto-speed-detection
+        ADD_FIELD32(eerst,13,1);      // reset the eeprom
+        ADD_FIELD32(spd_byps,15,1);   // bypass speed select
+        ADD_FIELD32(ro_dis,17,1);     // disable relaxed memory ordering
+        ADD_FIELD32(vreg,21,1);       // power down the voltage regulator
+        ADD_FIELD32(link_mode,22,2);  // interface to talk to the link
+        ADD_FIELD32(iame, 27,1);      // interrupt acknowledge auto-mask ??
+        ADD_FIELD32(drv_loaded, 28,1);// driver is loaded and incharge of device
+        ADD_FIELD32(timer_clr, 29,1); // clear interrupt timers after IMS clear ??
+    };
+    CTRL_EXT ctrl_ext;
+
+    struct MDIC : public Reg<uint32_t> { // 0x0020 MDIC Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(data,0,16);   // data
+        ADD_FIELD32(regadd,16,5); // register address
+        ADD_FIELD32(phyadd,21,5); // phy addresses
+        ADD_FIELD32(op,26,2);     // opcode
+        ADD_FIELD32(r,28,1);      // ready
+        ADD_FIELD32(i,29,1);      // interrupt
+        ADD_FIELD32(e,30,1);      // error
+    };
+    MDIC mdic;
+
+    struct ICR : public Reg<uint32_t> { // 0x00C0 ICR Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(txdw,0,1)   // tx descr witten back
+        ADD_FIELD32(txqe,1,1)   // tx queue empty
+        ADD_FIELD32(lsc,2,1)    // link status change
+        ADD_FIELD32(rxseq,3,1)  // rcv sequence error
+        ADD_FIELD32(rxdmt0,4,1) // rcv descriptor min thresh
+        ADD_FIELD32(rsvd1,5,1)  // reserved
+        ADD_FIELD32(rxo,6,1)    // receive overrunn
+        ADD_FIELD32(rxt0,7,1)   // receiver timer interrupt
+        ADD_FIELD32(mdac,9,1)   // mdi/o access complete
+        ADD_FIELD32(rxcfg,10,1)  // recv /c/ ordered sets
+        ADD_FIELD32(phyint,12,1) // phy interrupt
+        ADD_FIELD32(gpi1,13,1)   // gpi int 1
+        ADD_FIELD32(gpi2,14,1)   // gpi int 2
+        ADD_FIELD32(txdlow,15,1) // transmit desc low thresh
+        ADD_FIELD32(srpd,16,1)   // small receive packet detected
+        ADD_FIELD32(ack,17,1);    // receive ack frame
+        ADD_FIELD32(int_assert, 31,0); // interrupt caused a system interrupt
+    };
+    ICR icr;
+
+    uint32_t imr; // register that contains the current interrupt mask
+
+    struct ITR : public Reg<uint32_t> { // 0x00C4 ITR Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(interval, 0,16); // minimum inter-interrutp inteval
+                                     // specified in 256ns interrupts
+    };
+    ITR itr;
+
+    // When CTRL_EXT.IAME and the ICR.INT_ASSERT is 1 an ICR read or write
+    // causes the IAM register contents to be written into the IMC
+    // automatically clearing all interrupts that have a bit in the IAM set
+    uint32_t iam;
+
+    struct RCTL : public Reg<uint32_t> { // 0x0100 RCTL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rst,0,1);   // Reset
+        ADD_FIELD32(en,1,1);    // Enable
+        ADD_FIELD32(sbp,2,1);   // Store bad packets
+        ADD_FIELD32(upe,3,1);   // Unicast Promiscuous enabled
+        ADD_FIELD32(mpe,4,1);   // Multicast promiscuous enabled
+        ADD_FIELD32(lpe,5,1);   // long packet reception enabled
+        ADD_FIELD32(lbm,6,2);   //
+        ADD_FIELD32(rdmts,8,2); //
+        ADD_FIELD32(rsvd,10,2);  //
+        ADD_FIELD32(mo,12,2);    //
+        ADD_FIELD32(mdr,14,1);   //
+        ADD_FIELD32(bam,15,1);   //
+        ADD_FIELD32(bsize,16,2); //
+        ADD_FIELD32(vfe,18,1);   //
+        ADD_FIELD32(cfien,19,1); //
+        ADD_FIELD32(cfi,20,1);   //
+        ADD_FIELD32(rsvd2,21,1); //
+        ADD_FIELD32(dpf,22,1);   // discard pause frames
+        ADD_FIELD32(pmcf,23,1);  // pass mac control  frames
+        ADD_FIELD32(bsex,25,1);  // buffer size extension
+        ADD_FIELD32(secrc,26,1); // strip ethernet crc from incoming packet
+    };
+    RCTL rctl;
+
+    struct FCTTV : public Reg<uint32_t> { // 0x0170 FCTTV
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(ttv,0,16);    // Transmit Timer Value
+    };
+    FCTTV fcttv;
+
+    struct TCTL : public Reg<uint32_t> { // 0x0400 TCTL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rst,0,1);    // Reset
+        ADD_FIELD32(en,1,1);     // Enable
+        ADD_FIELD32(bce,2,1);    // busy check enable
+        ADD_FIELD32(psp,3,1);    // pad short packets
+        ADD_FIELD32(ct,4,8);     // collision threshold
+        ADD_FIELD32(cold,12,10); // collision distance
+        ADD_FIELD32(swxoff,22,1); // software xoff transmission
+        ADD_FIELD32(pbe,23,1);    // packet burst enable
+        ADD_FIELD32(rtlc,24,1);   // retransmit late collisions
+        ADD_FIELD32(nrtu,25,1);   // on underrun no TX
+        ADD_FIELD32(mulr,26,1);   // multiple request
+    };
+    TCTL tctl;
+
+    struct PBA : public Reg<uint32_t> { // 0x1000 PBA Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rxa,0,16);
+        ADD_FIELD32(txa,16,16);
+    };
+    PBA pba;
+
+    struct FCRTL : public Reg<uint32_t> { // 0x2160 FCRTL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rtl,3,28); // make this bigger than the spec so we can have
+                               // a larger buffer
+        ADD_FIELD32(xone, 31,1);
+    };
+    FCRTL fcrtl;
+
+    struct FCRTH : public Reg<uint32_t> { // 0x2168 FCRTL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rth,3,13); // make this bigger than the spec so we can have
+                               //a larger buffer
+        ADD_FIELD32(xfce, 31,1);
+    };
+    FCRTH fcrth;
+
+    struct RDBA : public Reg<uint64_t> { // 0x2800 RDBA Register
+        using Reg<uint64_t>::operator=;
+        ADD_FIELD64(rdbal,4,28); // base address of rx descriptor ring
+        ADD_FIELD64(rdbah,32,32); // base address of rx descriptor ring
+    };
+    RDBA rdba;
+
+    struct RDLEN : public Reg<uint32_t> { // 0x2808 RDLEN Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
+    };
+    RDLEN rdlen;
+
+    struct RDH : public Reg<uint32_t> { // 0x2810 RDH Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rdh,0,16); // head of the descriptor ring
+    };
+    RDH rdh;
+
+    struct RDT : public Reg<uint32_t> { // 0x2818 RDT Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(rdt,0,16); // tail of the descriptor ring
+    };
+    RDT rdt;
+
+    struct RDTR : public Reg<uint32_t> { // 0x2820 RDTR Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(delay,0,16); // receive delay timer
+        ADD_FIELD32(fpd, 31,);   // flush partial descriptor block ??
+    };
+    RDTR rdtr;
+
+    struct RADV : public Reg<uint32_t> { // 0x282C RADV Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(idv,0,16); // absolute interrupt delay
+    };
+    RADV radv;
+
+    struct RSRPD : public Reg<uint32_t> { // 0x2C00 RSRPD Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(idv,0,12); // size to interrutp on small packets
+    };
+    RSRPD rsrpd;
+
+    struct TDBA : public Reg<uint64_t> { // 0x3800 TDBAL Register
+        using Reg<uint64_t>::operator=;
+        ADD_FIELD64(tdbal,4,28); // base address of transmit descriptor ring
+        ADD_FIELD64(tdbah,32,32); // base address of transmit descriptor ring
+    };
+    TDBA tdba;
+
+    struct TDLEN : public Reg<uint32_t> { // 0x3808 TDLEN Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
+    };
+    TDLEN tdlen;
+
+    struct TDH : public Reg<uint32_t> { // 0x3810 TDH Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(tdh,0,16); // head of the descriptor ring
+    };
+    TDH tdh;
+
+    struct TDT : public Reg<uint32_t> { // 0x3818 TDT Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(tdt,0,16); // tail of the descriptor ring
+    };
+    TDT tdt;
+
+    struct TIDV : public Reg<uint32_t> { // 0x3820 TIDV Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(idv,0,16); // interrupt delay
+    };
+    TIDV tidv;
+
+    struct TXDCTL : public Reg<uint32_t> { // 0x3828 TXDCTL Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(pthresh, 0,6);  // if number of descriptors control has is
+                                    // below this number, a prefetch is considered
+        ADD_FIELD32(hthresh,8,8);   // number of valid descriptors is host memory
+                                    // before a prefetch is considered
+        ADD_FIELD32(wthresh,16,6);  // number of descriptors to keep until
+                                    // writeback is considered
+        ADD_FIELD32(gran, 24,1);    // granulatiry of above values (0 = cacheline,
+                                    // 1 == desscriptor)
+        ADD_FIELD32(lwthresh,25,7); // xmit descriptor low thresh, interrupt
+                                    // below this level
+    };
+    TXDCTL txdctl;
+
+    struct TADV : public Reg<uint32_t> { // 0x382C TADV Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(idv,0,16); // absolute interrupt delay
+    };
+    TADV tadv;
+
+    struct RXCSUM : public Reg<uint32_t> { // 0x5000 RXCSUM Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(pcss,0,8);
+        ADD_FIELD32(ipofld,8,1);
+        ADD_FIELD32(tuofld,9,1);
+    };
+    RXCSUM rxcsum;
+
+    struct MANC : public Reg<uint32_t> { // 0x5820 MANC Register
+        using Reg<uint32_t>::operator=;
+        ADD_FIELD32(smbus,0,1);    // SMBus enabled #####
+        ADD_FIELD32(asf,1,1);      // ASF enabled #####
+        ADD_FIELD32(ronforce,2,1); // reset of force
+        ADD_FIELD32(rsvd,3,5);     // reserved
+        ADD_FIELD32(rmcp1,8,1);    // rcmp1 filtering
+        ADD_FIELD32(rmcp2,9,1);    // rcmp2 filtering
+        ADD_FIELD32(ipv4,10,1);     // enable ipv4
+        ADD_FIELD32(ipv6,11,1);     // enable ipv6
+        ADD_FIELD32(snap,12,1);     // accept snap
+        ADD_FIELD32(arp,13,1);      // filter arp #####
+        ADD_FIELD32(neighbor,14,1); // neighbor discovery
+        ADD_FIELD32(arp_resp,15,1); // arp response
+        ADD_FIELD32(tcorst,16,1);   // tco reset happened
+        ADD_FIELD32(rcvtco,17,1);   // receive tco enabled ######
+        ADD_FIELD32(blkphyrst,18,1);// block phy resets ########
+        ADD_FIELD32(rcvall,19,1);   // receive all
+        ADD_FIELD32(macaddrfltr,20,1); // mac address filtering ######
+        ADD_FIELD32(mng2host,21,1); // mng2 host packets #######
+        ADD_FIELD32(ipaddrfltr,22,1); // ip address filtering
+        ADD_FIELD32(xsumfilter,23,1); // checksum filtering
+        ADD_FIELD32(brfilter,24,1); // broadcast filtering
+        ADD_FIELD32(smbreq,25,1);   // smb request
+        ADD_FIELD32(smbgnt,26,1);   // smb grant
+        ADD_FIELD32(smbclkin,27,1); // smbclkin
+        ADD_FIELD32(smbdatain,28,1); // smbdatain
+        ADD_FIELD32(smbdataout,29,1); // smb data out
+        ADD_FIELD32(smbclkout,30,1); // smb clock out
+    };
+    MANC manc;
 };
 
 }; // iGbReg namespace
index c59748163d1a4f226f771bcbeb9e521f16cfbb69..2abc06d8ebc452f158b8c50cd3b3a6f1b2cb23a4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2006 The Regents of The University of Michigan
+# Copyright (c) 2006-2007 The Regents of The University of Michigan
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -34,4 +34,4 @@ statetrace-native: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc pri
        g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
 
 statetrace-sparc: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc printer.hh refcnt.hh regstate.hh tracechild.hh
-       sparc64-unknown-linux-gnu-g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
+       sparc64-unknown-linux-gnu-g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -g -I ./ -I ./arch/ -O3 --static -o statetrace
index 2f42330e4ba6ae0d0f0980a16b1c49661d37d9aa..f60f9916bdd1ac373e196f6647bfbf2880cc2e6b 100644 (file)
@@ -54,8 +54,45 @@ string SparcTraceChild::regNames[numregs] = {
     //Miscelaneous
     "fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
 
+bool SparcTraceChild::sendState(int socket)
+{
+    uint64_t regVal = 0;
+    for(int x = 0; x <= I7; x++)
+    {
+        regVal = getRegVal(x);
+        if(write(socket, &regVal, sizeof(regVal)) == -1)
+        {
+            cerr << "Write failed! " << strerror(errno) << endl;
+            tracing = false;
+            return false;
+        }
+    }
+    regVal = getRegVal(PC);
+    if(write(socket, &regVal, sizeof(regVal)) == -1)
+    {
+        cerr << "Write failed! " << strerror(errno) << endl;
+        tracing = false;
+        return false;
+    }
+    regVal = getRegVal(NPC);
+    if(write(socket, &regVal, sizeof(regVal)) == -1)
+    {
+        cerr << "Write failed! " << strerror(errno) << endl;
+        tracing = false;
+        return false;
+    }
+    regVal = getRegVal(CCR);
+    if(write(socket, &regVal, sizeof(regVal)) == -1)
+    {
+        cerr << "Write failed! " << strerror(errno) << endl;
+        tracing = false;
+        return false;
+    }
+    return true;
+}
+
 int64_t getRegs(regs & myregs, fpu & myfpu,
-        int64_t * locals, int64_t * inputs, int num)
+        uint64_t * locals, uint64_t * inputs, int num)
 {
     assert(num < SparcTraceChild::numregs && num >= 0);
     switch(num)
@@ -160,14 +197,19 @@ bool SparcTraceChild::update(int pid)
         cerr << "Update failed" << endl;
         return false;
     }
-    uint64_t StackPointer = getSP();
-    const int stackBias = (StackPointer % 1) ? 2047 : 0;
+    uint64_t stackPointer = getSP();
+    uint64_t stackBias = 2047;
+    bool v9 = stackPointer % 2;
     for(unsigned int x = 0; x < 8; x++)
     {
-        locals[x] = ptrace(PTRACE_PEEKTEXT, pid,
-            StackPointer + stackBias + x * 8, 0);
-        inputs[x] = ptrace(PTRACE_PEEKTEXT, pid,
-            StackPointer + stackBias + x * 8 + (8 * 8), 0);
+        uint64_t localAddr = stackPointer +
+            (v9 ? (stackBias + x * 8) : (x * 4));
+        locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
+        if(!v9) locals[x] >>= 32;
+        uint64_t inputAddr = stackPointer +
+            (v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
+        inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
+        if(!v9) inputs[x] >>= 32;
     }
     if(ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
         return false;
@@ -366,7 +408,7 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
 {
     bool v8 = false;
     uint64_t sp = getSP();
-    if(sp % 1)
+    if(sp % 2)
     {
         os << "Detected a 64 bit executable.\n";
         v8 = false;
index 8b4ff9aaed5c1a6e9459a59831e300edce3173ca..0284fb82ed42ad91c80d30af28762d1234536978 100644 (file)
@@ -72,10 +72,10 @@ private:
         regs oldregs;
         fpu thefpregs;
         fpu oldfpregs;
-        int64_t locals[8];
-        int64_t oldLocals[8];
-        int64_t inputs[8];
-        int64_t oldInputs[8];
+        uint64_t locals[8];
+        uint64_t oldLocals[8];
+        uint64_t inputs[8];
+        uint64_t oldInputs[8];
         bool regDiffSinceUpdate[numregs];
 
         //This calculates where the pc might go after the current instruction.
@@ -90,6 +90,8 @@ protected:
 public:
         SparcTraceChild();
 
+        bool sendState(int socket);
+
         int getNumRegs()
         {
                 return numregs;
index e5baee3955e62738b0074e3572e871e021c21aa8..4fe47dc02a02f49273b58c69e22bdfc66eff5d68 100644 (file)
 #include <sys/wait.h>
 #include <sys/ptrace.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
 
-#include "tracechild.hh"
 #include "printer.hh"
+#include "tracechild.hh"
 
 using namespace std;
 
 void printUsage(const char * execName)
 {
-        cout << execName << " -f <output format file> | -h | -r -- <command> <arguments>" << endl;
+        cout << execName << " -h | -r -- <command> <arguments>" << endl;
 }
 
 int main(int argc, char * argv[], char * envp[])
 {
         TraceChild * child = genTraceChild();
-        NestingPrinter printer(child);
         string args;
         int startProgramArgs;
 
         //Parse the command line arguments
-        bool formatStringSet = false;
         bool printInitial = false;
         bool printTrace = true;
-        string format;
         for(int x = 1; x < argc; x++)
         {
-                if(!strcmp(argv[x], "-f"))
-                {
-                        if(formatStringSet)
-                        {
-                                cerr << "Attempted to set format twice!"
-                                        << endl;
-                                printUsage(argv[0]);
-                                return 1;
-                        }
-                        formatStringSet = true;
-                        x++;
-                        if(x >= argc)
-                        {
-                                cerr << "Incorrect usage.\n" << endl;
-                                printUsage(argv[0]);
-                                return 1;
-                        }
-                        ifstream formatFile(argv[x]);
-                        if(!formatFile)
-                        {
-                                cerr << "Problem opening file "
-                                        << argv[x] << "." << endl;
-                                return 1;
-                        }
-                        format = "";
-                        while(formatFile)
-                        {
-                                string line;
-                                getline(formatFile, line);
-                                if(formatFile.eof())
-                                {
-                                        format += line;
-                                        break;
-                                }
-                                if(!formatFile)
-                                {
-                                        cerr << "Problem reading from file "
-                                                << argv[x] << "." << endl;
-                                        return 1;
-                                }
-                                format += line + '\n';
-                        }
-                }
-                else if(!strcmp(argv[x], "-h"))
+                if(!strcmp(argv[x], "-h"))
                 {
                         printUsage(argv[0]);
                         return 0;
                 }
                 else if(!strcmp(argv[x], "-r"))
                 {
-                        cout << "Legal register names:" << endl;
-                        int numRegs = child->getNumRegs();
-                        for(unsigned int x = 0; x < numRegs; x++)
-                        {
-                                cout << "\t" << child->getRegName(x) << endl;
-                        }
-                        return 0;
+                    cout << "Legal register names:" << endl;
+                    int numRegs = child->getNumRegs();
+                    for(unsigned int x = 0; x < numRegs; x++)
+                    {
+                            cout << "\t" << child->getRegName(x) << endl;
+                    }
+                    return 0;
                 }
                 else if(!strcmp(argv[x], "-i"))
                 {
@@ -145,11 +105,6 @@ int main(int argc, char * argv[], char * envp[])
                         return 1;
                 }
         }
-        /*for(unsigned int x = startProgramArgs; x < argc; x++)
-        {
-            cout << "Adding argument " << argv[x];
-            args += string(" ") + argv[x];
-        }*/
         if(!child->startTracing(argv[startProgramArgs],
                     argv + startProgramArgs))
         {
@@ -162,26 +117,41 @@ int main(int argc, char * argv[], char * envp[])
         }
         if(printTrace)
         {
-            if(!formatStringSet)
+            // Connect to m5
+            bool portSet = false;
+            int port;
+            int sock = socket(AF_INET, SOCK_STREAM, 0);
+            if(sock < 0)
             {
-                    cerr << "No output format set!" << endl;
-                    child->stopTracing();
-                    printUsage(argv[0]);
-                    return 1;
+                cerr << "Error opening socket! " << strerror(errno) << endl;
+                return 1;
             }
-            if(!printer.configure(format))
+            struct hostent *server;
+            server = gethostbyname("zower.eecs.umich.edu");
+            if(!server)
             {
-                    cerr << "Problem in the output format" << endl;
-                    child->stopTracing();
-                    return 1;
+                cerr << "Couldn't get host ip! " << strerror(errno) << endl;
+                return 1;
+            }
+            struct sockaddr_in serv_addr;
+            bzero((char *)&serv_addr, sizeof(serv_addr));
+            serv_addr.sin_family = AF_INET;
+            bcopy((char *)server->h_addr,
+                    (char *)&serv_addr.sin_addr.s_addr,
+                    server->h_length);
+            serv_addr.sin_port = htons(8000);
+            if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
+            {
+                cerr << "Couldn't connect to server! " << strerror(errno) << endl;
+                return 1;
             }
             child->step();
             while(child->isTracing())
             {
-                    cout << printer;
+                    if(!child->sendState(sock))
+                        break;
                     child->step();
             }
-            cout << printer;
         }
         if(!child->stopTracing())
         {
index 130f9690fc356176fb63e85c33f9962b3468843d..6034298293fa60a3cb5166f2d48828a752faf94a 100644 (file)
@@ -51,12 +51,23 @@ bool TraceChild::startTracing(const char * pathToFile, char * const argv[])
                 //program to trace.
 
                 //Let our parent trace us
-                ptrace(PTRACE_TRACEME, 0, 0, 0);
+                if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1)
+                {
+                        cout << "Failure calling TRACEME\n";
+                        cout << strerror(errno) << endl;
+                        return false;
+                }
+
+                //Set up an empty environment for the child...
+                //We would want to specify this somehow at some point
+                char * env[] = {NULL};
 
                 //Start the program to trace
-                execv(pathToFile, argv);
+                execve(pathToFile, argv, env);
 
                 //We should never get here, so this is an error!
+                cout << "Exec failed\n";
+                cout <<  strerror(errno) << endl;
                 return false;
         }
 
index 84fa595d854292eac845c2a620673ebddd312ec7..24712f8160704f7cb4b82b78a34a7ca8d708744c 100644 (file)
@@ -42,6 +42,7 @@ protected:
 public:
         TraceChild() : tracing(false), instructions(0)
         {;}
+        virtual bool sendState(int socket) = 0;
         virtual bool startTracing(const char * pathToFile,
                 char * const argv[]);
         virtual bool stopTracing();