d728f6786b
There are drivers writing to WUFC uncondtionally of anything. In order to not panic gem5 in these cases, ignore writes to WUFC and WUS as we do for WUC. Similarly return 0 (default reset value) on reads. Testing Done: Booted in FS with such a driver revision which would previously panic and now boots fine. Reviewed at http://reviews.gem5.org/r/3791/ Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
857 lines
34 KiB
C++
857 lines
34 KiB
C++
/*
|
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Authors: Ali Saidi
|
|
*/
|
|
|
|
/* @file
|
|
* Register and structure descriptions for Intel's 8254x line of gigabit ethernet controllers.
|
|
*/
|
|
#include "base/bitfield.hh"
|
|
|
|
namespace iGbReg {
|
|
|
|
|
|
// Registers used by the Intel GbE NIC
|
|
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_EICR = 0x01580;
|
|
const uint32_t REG_IVAR0 = 0x01700;
|
|
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_SRRCTL = 0x0280C;
|
|
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_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_TXDCA_CTL = 0x03814;
|
|
const uint32_t REG_TDT = 0x03818;
|
|
const uint32_t REG_TIDV = 0x03820;
|
|
const uint32_t REG_TXDCTL = 0x03828;
|
|
const uint32_t REG_TADV = 0x0382C;
|
|
const uint32_t REG_TDWBAL = 0x03838;
|
|
const uint32_t REG_TDWBAH = 0x0383C;
|
|
const uint32_t REG_CRCERRS = 0x04000;
|
|
const uint32_t REG_RXCSUM = 0x05000;
|
|
const uint32_t REG_RLPML = 0x05004;
|
|
const uint32_t REG_RFCTL = 0x05008;
|
|
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_WUFC = 0x05808;
|
|
const uint32_t REG_WUS = 0x05810;
|
|
const uint32_t REG_MANC = 0x05820;
|
|
const uint32_t REG_SWSM = 0x05B50;
|
|
const uint32_t REG_FWSM = 0x05B54;
|
|
const uint32_t REG_SWFWSYNC = 0x05B5C;
|
|
|
|
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 = 24;
|
|
const uint8_t MULTICAST_TABLE_SIZE = 128;
|
|
const uint32_t STATS_REGS_SIZE = 0x228;
|
|
|
|
|
|
// Registers in that are accessed in the PHY
|
|
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;
|
|
|
|
// Receive Descriptor Status Flags
|
|
const uint16_t RXDS_DYNINT = 0x800;
|
|
const uint16_t RXDS_UDPV = 0x400;
|
|
const uint16_t RXDS_CRCV = 0x100;
|
|
const uint16_t RXDS_PIF = 0x080;
|
|
const uint16_t RXDS_IPCS = 0x040;
|
|
const uint16_t RXDS_TCPCS = 0x020;
|
|
const uint16_t RXDS_UDPCS = 0x010;
|
|
const uint16_t RXDS_VP = 0x008;
|
|
const uint16_t RXDS_IXSM = 0x004;
|
|
const uint16_t RXDS_EOP = 0x002;
|
|
const uint16_t RXDS_DD = 0x001;
|
|
|
|
// Receive Descriptor Error Flags
|
|
const uint8_t RXDE_RXE = 0x80;
|
|
const uint8_t RXDE_IPE = 0x40;
|
|
const uint8_t RXDE_TCPE = 0x20;
|
|
const uint8_t RXDE_SEQ = 0x04;
|
|
const uint8_t RXDE_SE = 0x02;
|
|
const uint8_t RXDE_CE = 0x01;
|
|
|
|
// Receive Descriptor Extended Error Flags
|
|
const uint16_t RXDEE_HBO = 0x008;
|
|
const uint16_t RXDEE_CE = 0x010;
|
|
const uint16_t RXDEE_LE = 0x020;
|
|
const uint16_t RXDEE_PE = 0x080;
|
|
const uint16_t RXDEE_OSE = 0x100;
|
|
const uint16_t RXDEE_USE = 0x200;
|
|
const uint16_t RXDEE_TCPE = 0x400;
|
|
const uint16_t RXDEE_IPE = 0x800;
|
|
|
|
|
|
// Receive Descriptor Types
|
|
const uint8_t RXDT_LEGACY = 0x00;
|
|
const uint8_t RXDT_ADV_ONEBUF = 0x01;
|
|
const uint8_t RXDT_ADV_SPLIT_A = 0x05;
|
|
|
|
// Receive Descriptor Packet Types
|
|
const uint16_t RXDP_IPV4 = 0x001;
|
|
const uint16_t RXDP_IPV4E = 0x002;
|
|
const uint16_t RXDP_IPV6 = 0x004;
|
|
const uint16_t RXDP_IPV6E = 0x008;
|
|
const uint16_t RXDP_TCP = 0x010;
|
|
const uint16_t RXDP_UDP = 0x020;
|
|
const uint16_t RXDP_SCTP = 0x040;
|
|
const uint16_t RXDP_NFS = 0x080;
|
|
|
|
// Interrupt types
|
|
enum IntTypes
|
|
{
|
|
IT_NONE = 0x00000, //dummy value
|
|
IT_TXDW = 0x00001,
|
|
IT_TXQE = 0x00002,
|
|
IT_LSC = 0x00004,
|
|
IT_RXSEQ = 0x00008,
|
|
IT_RXDMT = 0x00010,
|
|
IT_RXO = 0x00040,
|
|
IT_RXT = 0x00080,
|
|
IT_MADC = 0x00200,
|
|
IT_RXCFG = 0x00400,
|
|
IT_GPI0 = 0x02000,
|
|
IT_GPI1 = 0x04000,
|
|
IT_TXDLOW = 0x08000,
|
|
IT_SRPD = 0x10000,
|
|
IT_ACK = 0x20000
|
|
};
|
|
|
|
// Receive Descriptor struct
|
|
struct RxDesc {
|
|
union {
|
|
struct {
|
|
Addr buf;
|
|
uint16_t len;
|
|
uint16_t csum;
|
|
uint8_t status;
|
|
uint8_t errors;
|
|
uint16_t vlan;
|
|
} legacy;
|
|
struct {
|
|
Addr pkt;
|
|
Addr hdr;
|
|
} adv_read;
|
|
struct {
|
|
uint16_t rss_type:4;
|
|
uint16_t pkt_type:12;
|
|
uint16_t __reserved1:5;
|
|
uint16_t header_len:10;
|
|
uint16_t sph:1;
|
|
union {
|
|
struct {
|
|
uint16_t id;
|
|
uint16_t csum;
|
|
};
|
|
uint32_t rss_hash;
|
|
};
|
|
uint32_t status:20;
|
|
uint32_t errors:12;
|
|
uint16_t pkt_len;
|
|
uint16_t vlan_tag;
|
|
} adv_wb ;
|
|
};
|
|
};
|
|
|
|
struct TxDesc {
|
|
uint64_t d1;
|
|
uint64_t d2;
|
|
};
|
|
|
|
namespace TxdOp {
|
|
const uint8_t TXD_CNXT = 0x0;
|
|
const uint8_t TXD_DATA = 0x1;
|
|
const uint8_t TXD_ADVCNXT = 0x2;
|
|
const uint8_t TXD_ADVDATA = 0x3;
|
|
|
|
inline bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
|
|
inline uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
|
|
inline bool isType(TxDesc *d, uint8_t type) { return getType(d) == type; }
|
|
inline bool isTypes(TxDesc *d, uint8_t t1, uint8_t t2) { return isType(d, t1) || isType(d, t2); }
|
|
inline bool isAdvDesc(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_ADVDATA,TXD_ADVCNXT); }
|
|
inline bool isContext(TxDesc *d) { return !isLegacy(d) && isTypes(d,TXD_CNXT, TXD_ADVCNXT); }
|
|
inline bool isData(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_DATA, TXD_ADVDATA); }
|
|
|
|
inline Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; }
|
|
inline Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); }
|
|
inline void setDd(TxDesc *d) { replaceBits(d->d2, 35, 32, ULL(1)); }
|
|
|
|
inline bool ide(TxDesc *d) { return bits(d->d2, 31,31) && (getType(d) == TXD_DATA || isLegacy(d)); }
|
|
inline bool vle(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); }
|
|
inline bool rs(TxDesc *d) { return bits(d->d2, 27,27); }
|
|
inline bool ic(TxDesc *d) { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 26,26); }
|
|
inline bool tse(TxDesc *d) {
|
|
if (isTypes(d, TXD_CNXT, TXD_DATA))
|
|
return bits(d->d2, 26,26);
|
|
if (isType(d, TXD_ADVDATA))
|
|
return bits(d->d2, 31, 31);
|
|
return false;
|
|
}
|
|
|
|
inline bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); }
|
|
inline bool eop(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 24,24); }
|
|
inline bool ip(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 25,25); }
|
|
inline bool tcp(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 24,24); }
|
|
|
|
inline uint8_t getCso(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 23,16); }
|
|
inline uint8_t getCss(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 47,40); }
|
|
|
|
inline bool ixsm(TxDesc *d) { return isData(d) && bits(d->d2, 40,40); }
|
|
inline bool txsm(TxDesc *d) { return isData(d) && bits(d->d2, 41,41); }
|
|
|
|
inline int tucse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,63,48); }
|
|
inline int tucso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,47,40); }
|
|
inline int tucss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,39,32); }
|
|
inline int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); }
|
|
inline int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); }
|
|
inline int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
|
|
inline int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
|
|
inline int hdrlen(TxDesc *d) {
|
|
assert(isContext(d));
|
|
if (!isAdvDesc(d))
|
|
return bits(d->d2,47,40);
|
|
return bits(d->d2, 47,40) + bits(d->d1, 8,0) + bits(d->d1, 15, 9);
|
|
}
|
|
|
|
inline int getTsoLen(TxDesc *d) { assert(isType(d, TXD_ADVDATA)); return bits(d->d2, 63,46); }
|
|
inline int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); }
|
|
} // namespace TxdOp
|
|
|
|
|
|
#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 : public Serializable {
|
|
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; }
|
|
Reg() { _data = 0; }
|
|
void serialize(CheckpointOut &cp) const
|
|
{
|
|
SERIALIZE_SCALAR(_data);
|
|
}
|
|
void unserialize(CheckpointIn &cp)
|
|
{
|
|
UNSERIALIZE_SCALAR(_data);
|
|
}
|
|
};
|
|
|
|
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,1,1); // done read
|
|
ADD_FIELD32(addr,2,14); // 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,1); // 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(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(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
|
|
unsigned descSize()
|
|
{
|
|
switch(bsize()) {
|
|
case 0: return bsex() == 0 ? 2048 : 0;
|
|
case 1: return bsex() == 0 ? 1024 : 16384;
|
|
case 2: return bsex() == 0 ? 512 : 8192;
|
|
case 3: return bsex() == 0 ? 256 : 4096;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
};
|
|
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,0,32); // 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 SRRCTL : public Reg<uint32_t> { // 0x280C SRRCTL Register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(pktlen, 0, 8);
|
|
ADD_FIELD32(hdrlen, 8, 8); // guess based on header, not documented
|
|
ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv,
|
|
//101 hdr split
|
|
unsigned bufLen() { return pktlen() << 10; }
|
|
unsigned hdrLen() { return hdrlen() << 6; }
|
|
};
|
|
SRRCTL srrctl;
|
|
|
|
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,1); // flush partial descriptor block ??
|
|
};
|
|
RDTR rdtr;
|
|
|
|
struct RXDCTL : public Reg<uint32_t> { // 0x2828 RXDCTL Register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(pthresh,0,6); // prefetch threshold, less that this
|
|
// consider prefetch
|
|
ADD_FIELD32(hthresh,8,6); // number of descriptors in host mem to
|
|
// consider prefetch
|
|
ADD_FIELD32(wthresh,16,6); // writeback threshold
|
|
ADD_FIELD32(gran,24,1); // granularity 0 = desc, 1 = cacheline
|
|
};
|
|
RXDCTL rxdctl;
|
|
|
|
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,0,32); // 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 TXDCA_CTL : public Reg<uint32_t> { // 0x3814 TXDCA_CTL Register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(cpu_mask, 0, 5);
|
|
ADD_FIELD32(enabled, 5,1);
|
|
ADD_FIELD32(relax_ordering, 6, 1);
|
|
};
|
|
TXDCA_CTL txdca_ctl;
|
|
|
|
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 TDWBA : public Reg<uint64_t> { // 0x3838 TDWBA Register
|
|
using Reg<uint64_t>::operator=;
|
|
ADD_FIELD64(en,0,1); // enable transmit description ring address writeback
|
|
ADD_FIELD64(tdwbal,2,32); // base address of transmit descriptor ring address writeback
|
|
ADD_FIELD64(tdwbah,32,32); // base address of transmit descriptor ring
|
|
};
|
|
TDWBA tdwba;*/
|
|
uint64_t tdwba;
|
|
|
|
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);
|
|
ADD_FIELD32(pcsd, 13,1);
|
|
};
|
|
RXCSUM rxcsum;
|
|
|
|
uint32_t rlpml; // 0x5004 RLPML probably maximum accepted packet size
|
|
|
|
struct RFCTL : public Reg<uint32_t> { // 0x5008 RFCTL Register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(iscsi_dis,0,1);
|
|
ADD_FIELD32(iscsi_dwc,1,5);
|
|
ADD_FIELD32(nfsw_dis,6,1);
|
|
ADD_FIELD32(nfsr_dis,7,1);
|
|
ADD_FIELD32(nfs_ver,8,2);
|
|
ADD_FIELD32(ipv6_dis,10,1);
|
|
ADD_FIELD32(ipv6xsum_dis,11,1);
|
|
ADD_FIELD32(ackdis,13,1);
|
|
ADD_FIELD32(ipfrsp_dis,14,1);
|
|
ADD_FIELD32(exsten,15,1);
|
|
};
|
|
RFCTL rfctl;
|
|
|
|
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;
|
|
|
|
struct SWSM : public Reg<uint32_t> { // 0x5B50 SWSM register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(smbi,0,1); // Semaphone bit
|
|
ADD_FIELD32(swesmbi, 1,1); // Software eeporm semaphore
|
|
ADD_FIELD32(wmng, 2,1); // Wake MNG clock
|
|
ADD_FIELD32(reserved, 3, 29);
|
|
};
|
|
SWSM swsm;
|
|
|
|
struct FWSM : public Reg<uint32_t> { // 0x5B54 FWSM register
|
|
using Reg<uint32_t>::operator=;
|
|
ADD_FIELD32(eep_fw_semaphore,0,1);
|
|
ADD_FIELD32(fw_mode, 1,3);
|
|
ADD_FIELD32(ide, 4,1);
|
|
ADD_FIELD32(sol, 5,1);
|
|
ADD_FIELD32(eep_roload, 6,1);
|
|
ADD_FIELD32(reserved, 7,8);
|
|
ADD_FIELD32(fw_val_bit, 15, 1);
|
|
ADD_FIELD32(reset_cnt, 16, 3);
|
|
ADD_FIELD32(ext_err_ind, 19, 6);
|
|
ADD_FIELD32(reserved2, 25, 7);
|
|
};
|
|
FWSM fwsm;
|
|
|
|
uint32_t sw_fw_sync;
|
|
|
|
void serialize(CheckpointOut &cp) const override
|
|
{
|
|
paramOut(cp, "ctrl", ctrl._data);
|
|
paramOut(cp, "sts", sts._data);
|
|
paramOut(cp, "eecd", eecd._data);
|
|
paramOut(cp, "eerd", eerd._data);
|
|
paramOut(cp, "ctrl_ext", ctrl_ext._data);
|
|
paramOut(cp, "mdic", mdic._data);
|
|
paramOut(cp, "icr", icr._data);
|
|
SERIALIZE_SCALAR(imr);
|
|
paramOut(cp, "itr", itr._data);
|
|
SERIALIZE_SCALAR(iam);
|
|
paramOut(cp, "rctl", rctl._data);
|
|
paramOut(cp, "fcttv", fcttv._data);
|
|
paramOut(cp, "tctl", tctl._data);
|
|
paramOut(cp, "pba", pba._data);
|
|
paramOut(cp, "fcrtl", fcrtl._data);
|
|
paramOut(cp, "fcrth", fcrth._data);
|
|
paramOut(cp, "rdba", rdba._data);
|
|
paramOut(cp, "rdlen", rdlen._data);
|
|
paramOut(cp, "srrctl", srrctl._data);
|
|
paramOut(cp, "rdh", rdh._data);
|
|
paramOut(cp, "rdt", rdt._data);
|
|
paramOut(cp, "rdtr", rdtr._data);
|
|
paramOut(cp, "rxdctl", rxdctl._data);
|
|
paramOut(cp, "radv", radv._data);
|
|
paramOut(cp, "rsrpd", rsrpd._data);
|
|
paramOut(cp, "tdba", tdba._data);
|
|
paramOut(cp, "tdlen", tdlen._data);
|
|
paramOut(cp, "tdh", tdh._data);
|
|
paramOut(cp, "txdca_ctl", txdca_ctl._data);
|
|
paramOut(cp, "tdt", tdt._data);
|
|
paramOut(cp, "tidv", tidv._data);
|
|
paramOut(cp, "txdctl", txdctl._data);
|
|
paramOut(cp, "tadv", tadv._data);
|
|
//paramOut(cp, "tdwba", tdwba._data);
|
|
SERIALIZE_SCALAR(tdwba);
|
|
paramOut(cp, "rxcsum", rxcsum._data);
|
|
SERIALIZE_SCALAR(rlpml);
|
|
paramOut(cp, "rfctl", rfctl._data);
|
|
paramOut(cp, "manc", manc._data);
|
|
paramOut(cp, "swsm", swsm._data);
|
|
paramOut(cp, "fwsm", fwsm._data);
|
|
SERIALIZE_SCALAR(sw_fw_sync);
|
|
}
|
|
|
|
void unserialize(CheckpointIn &cp) override
|
|
{
|
|
paramIn(cp, "ctrl", ctrl._data);
|
|
paramIn(cp, "sts", sts._data);
|
|
paramIn(cp, "eecd", eecd._data);
|
|
paramIn(cp, "eerd", eerd._data);
|
|
paramIn(cp, "ctrl_ext", ctrl_ext._data);
|
|
paramIn(cp, "mdic", mdic._data);
|
|
paramIn(cp, "icr", icr._data);
|
|
UNSERIALIZE_SCALAR(imr);
|
|
paramIn(cp, "itr", itr._data);
|
|
UNSERIALIZE_SCALAR(iam);
|
|
paramIn(cp, "rctl", rctl._data);
|
|
paramIn(cp, "fcttv", fcttv._data);
|
|
paramIn(cp, "tctl", tctl._data);
|
|
paramIn(cp, "pba", pba._data);
|
|
paramIn(cp, "fcrtl", fcrtl._data);
|
|
paramIn(cp, "fcrth", fcrth._data);
|
|
paramIn(cp, "rdba", rdba._data);
|
|
paramIn(cp, "rdlen", rdlen._data);
|
|
paramIn(cp, "srrctl", srrctl._data);
|
|
paramIn(cp, "rdh", rdh._data);
|
|
paramIn(cp, "rdt", rdt._data);
|
|
paramIn(cp, "rdtr", rdtr._data);
|
|
paramIn(cp, "rxdctl", rxdctl._data);
|
|
paramIn(cp, "radv", radv._data);
|
|
paramIn(cp, "rsrpd", rsrpd._data);
|
|
paramIn(cp, "tdba", tdba._data);
|
|
paramIn(cp, "tdlen", tdlen._data);
|
|
paramIn(cp, "tdh", tdh._data);
|
|
paramIn(cp, "txdca_ctl", txdca_ctl._data);
|
|
paramIn(cp, "tdt", tdt._data);
|
|
paramIn(cp, "tidv", tidv._data);
|
|
paramIn(cp, "txdctl", txdctl._data);
|
|
paramIn(cp, "tadv", tadv._data);
|
|
UNSERIALIZE_SCALAR(tdwba);
|
|
//paramIn(cp, "tdwba", tdwba._data);
|
|
paramIn(cp, "rxcsum", rxcsum._data);
|
|
UNSERIALIZE_SCALAR(rlpml);
|
|
paramIn(cp, "rfctl", rfctl._data);
|
|
paramIn(cp, "manc", manc._data);
|
|
paramIn(cp, "swsm", swsm._data);
|
|
paramIn(cp, "fwsm", fwsm._data);
|
|
UNSERIALIZE_SCALAR(sw_fw_sync);
|
|
}
|
|
};
|
|
} // namespace iGbReg
|