still working on getting past initialization
authorAli Saidi <saidi@eecs.umich.edu>
Fri, 20 Oct 2006 17:00:05 +0000 (13:00 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Fri, 20 Oct 2006 17:00:05 +0000 (13:00 -0400)
--HG--
extra : convert_revision : 7a5fccb9a19d363e479ef24012a7b8598272eaa9

src/dev/i8254xGBe.cc
src/dev/i8254xGBe.hh
src/dev/i8254xGBe_defs.hh
src/python/m5/objects/Ethernet.py

index 77c7318991f72dff40ae3eadc8b7cf8425a0f8ed..e95cc15c6c68763522dc2859766a78ac0ca268a0 100644 (file)
@@ -30,6 +30,9 @@
 
 /* @file
  * Device model for Intel's 8254x line of gigabit ethernet controllers.
+ * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the
+ * fewest workarounds in the driver. It will probably work with most of the
+ * other MACs with slight modifications.
  */
 
 #include "base/inet.hh"
 #include "sim/stats.hh"
 #include "sim/system.hh"
 
+using namespace iGbReg;
+
 IGbE::IGbE(Params *p)
     : PciDev(p), etherInt(NULL)
 {
-
+    // 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;
+
+    eeOpBits            = 0;
+    eeAddrBits          = 0;
+    eeDataBits          = 0;
+    eeOpcode            = 0;
+
+    memset(&flash, 0, EEPROM_SIZE);
+    // Magic happy checksum value
+    flash[0] = 0xBABA;
 }
 
 
@@ -74,15 +105,49 @@ IGbE::read(Packet *pkt)
     // Only Memory register BAR is allowed
     assert(bar == 0);
 
-    DPRINTF(Ethernet, "Accessed devie register %#X\n", daddr);
+    // Only 32bit accesses allowed
+    assert(pkt->getSize() == 4);
 
-    pkt->allocate();
+    DPRINTF(Ethernet, "Read device register %#X\n", daddr);
 
+    pkt->allocate();
 
     ///
     /// Handle read of register here
     ///
 
+    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 MANC:
+       pkt->set<uint32_t>(regs.manc.reg);
+       break;
+      default:
+       panic("Read request to unknown register number: %#x\n", daddr);
+    };
+
     pkt->result = Packet::Success;
     return pioDelay;
 }
@@ -93,17 +158,100 @@ IGbE::write(Packet *pkt)
     int bar;
     Addr daddr;
 
+
     if (!getBAR(pkt->getAddr(), bar, daddr))
         panic("Invalid PCI memory access to unmapped memory.\n");
 
     // Only Memory register BAR is allowed
     assert(bar == 0);
 
-    DPRINTF(Ethernet, "Accessed devie register %#X\n", daddr);
+    // Only 32bit accesses allowed
+    assert(pkt->getSize() == sizeof(uint32_t));
+
+    DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
 
     ///
     /// Handle write of register here
     ///
+    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 < EEPROM_SIZE);
+               DPRINTF(Ethernet, "EEPROM bit read: %d word: %#X\n",
+                       flash[eeAddr] >> eeDataBits & 0x1, flash[eeAddr]);
+               regs.eecd.dout = (flash[eeAddr] >> 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;
+               eeOpcode = 0;
+               eeAddr = 0;
+           }
+
+           DPRINTF(Ethernet, "EEPROM: opcode: %#X:%d\n",
+                   (uint32_t)eeOpcode, (uint32_t) eeOpBits);
+           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 MANC:
+       regs.manc.reg = val;
+       break;
+      default:
+       panic("Write request to unknown register number: %#x\n", daddr);
+    };
 
     pkt->result = Packet::Success;
     return pioDelay;
index 88931eb6dc58a54f053894538744c694180c8ab0..8e2dd2e9c5814a53dc459bf31c1fc3ee02b6e1f7 100644 (file)
@@ -39,6 +39,7 @@
 #include "base/statistics.hh"
 #include "dev/etherint.hh"
 #include "dev/etherpkt.hh"
+#include "dev/i8254xGBe_defs.hh"
 #include "dev/pcidev.hh"
 #include "dev/pktfifo.hh"
 #include "sim/eventq.hh"
@@ -49,6 +50,12 @@ class IGbE : public PciDev
 {
   private:
     IGbEInt *etherInt;
+    iGbReg::Regs regs;
+    int eeOpBits, eeAddrBits, eeDataBits;
+    uint8_t eeOpcode, eeAddr;
+
+    uint16_t flash[iGbReg::EEPROM_SIZE];
+
 
   public:
     struct Params : public PciDev::Params
index 81d7d0d80ca779d5ecbd02ae22e80c2b69952b61..ae09253568bd5839d5546a620bb3489b7502ad9b 100644 (file)
 
 namespace iGbReg {
 
-const uint32_t CTRL     = 0x00000;
-const uint32_t STATUS   = 0x00008;
-const uint32_t EECD     = 0x00010;
+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 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 IMC      = 0x000D8; //*
+const uint32_t RCTL     = 0x00100; //*
 const uint32_t RDBAL    = 0x02800;
 const uint32_t RDBAH    = 0x02804;
 const uint32_t RDLEN    = 0x02808;
@@ -53,7 +54,7 @@ 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 TCTL     = 0x00400; //*
 const uint32_t TDBAL    = 0x03800;
 const uint32_t TDBAH    = 0x03804;
 const uint32_t TDLEN    = 0x03808;
@@ -66,6 +67,11 @@ 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 uint8_t EEPROM_READ_OPCODE_SPI    = 0x03;
+const uint8_t EEPROM_RDSR_OPCODE_SPI    = 0x05;
+const uint8_t EEPROM_SIZE               = 64;
 
 struct RxDesc {
     Addr buf;
@@ -239,4 +245,219 @@ union TxDesc {
     } type;
 };
 
+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;
+
+    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;
+};
+
 }; // iGbReg namespace
index f17a6c8885c1c37a4fee9e676f0763d26afe8b8f..a52e35511ea475968daffe1791fff16279db7204 100644 (file)
@@ -71,7 +71,7 @@ class IGbE(PciDevice):
 
 class IGbEPciData(PciConfigData):
     VendorID = 0x8086
-    DeviceID = 0x1026
+    DeviceID = 0x1075
     SubsystemID = 0x1008
     SubsystemVendorID = 0x8086
     Status = 0x0000