1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31/* @file
32 * Register and structure descriptions for Intel's 8254x line of gigabit ethernet controllers.
33 */
34#include "base/bitfield.hh"
35
36namespace iGbReg {
37
38
39// Registers used by the Intel GbE NIC
40const uint32_t REG_CTRL     = 0x00000;
41const uint32_t REG_STATUS   = 0x00008;
42const uint32_t REG_EECD     = 0x00010;
43const uint32_t REG_EERD     = 0x00014;
44const uint32_t REG_CTRL_EXT = 0x00018;
45const uint32_t REG_MDIC     = 0x00020;
46const uint32_t REG_FCAL     = 0x00028;
47const uint32_t REG_FCAH     = 0x0002C;
48const uint32_t REG_FCT      = 0x00030;
49const uint32_t REG_VET      = 0x00038;
50const uint32_t REG_PBA      = 0x01000;
51const uint32_t REG_ICR      = 0x000C0;
52const uint32_t REG_ITR      = 0x000C4;
53const uint32_t REG_ICS      = 0x000C8;
54const uint32_t REG_IMS      = 0x000D0;
55const uint32_t REG_IMC      = 0x000D8;
56const uint32_t REG_IAM      = 0x000E0;
57const uint32_t REG_RCTL     = 0x00100;
58const uint32_t REG_FCTTV    = 0x00170;
59const uint32_t REG_TIPG     = 0x00410;
60const uint32_t REG_AIFS     = 0x00458;
61const uint32_t REG_LEDCTL   = 0x00e00;
62const uint32_t REG_EICR     = 0x01580;
63const uint32_t REG_IVAR0    = 0x01700;
64const uint32_t REG_FCRTL    = 0x02160;
65const uint32_t REG_FCRTH    = 0x02168;
66const uint32_t REG_RDBAL    = 0x02800;
67const uint32_t REG_RDBAH    = 0x02804;
68const uint32_t REG_RDLEN    = 0x02808;
69const uint32_t REG_SRRCTL   = 0x0280C;
70const uint32_t REG_RDH      = 0x02810;
71const uint32_t REG_RDT      = 0x02818;
72const uint32_t REG_RDTR     = 0x02820;
73const uint32_t REG_RXDCTL   = 0x02828;
74const uint32_t REG_RADV     = 0x0282C;
75const uint32_t REG_TCTL     = 0x00400;
76const uint32_t REG_TDBAL    = 0x03800;
77const uint32_t REG_TDBAH    = 0x03804;
78const uint32_t REG_TDLEN    = 0x03808;
79const uint32_t REG_TDH      = 0x03810;
80const uint32_t REG_TXDCA_CTL = 0x03814;
81const uint32_t REG_TDT      = 0x03818;
82const uint32_t REG_TIDV     = 0x03820;
83const uint32_t REG_TXDCTL   = 0x03828;
84const uint32_t REG_TADV     = 0x0382C;
85const uint32_t REG_TDWBAL   = 0x03838;
86const uint32_t REG_TDWBAH   = 0x0383C;
87const uint32_t REG_CRCERRS  = 0x04000;
88const uint32_t REG_RXCSUM   = 0x05000;
89const uint32_t REG_RLPML    = 0x05004;
90const uint32_t REG_RFCTL    = 0x05008;
91const uint32_t REG_MTA      = 0x05200;
92const uint32_t REG_RAL      = 0x05400;
93const uint32_t REG_RAH      = 0x05404;
94const uint32_t REG_VFTA     = 0x05600;
95
96const uint32_t REG_WUC      = 0x05800;
97const uint32_t REG_WUFC     = 0x05808;
98const uint32_t REG_WUS      = 0x05810;
99const uint32_t REG_MANC     = 0x05820;
100const uint32_t REG_SWSM     = 0x05B50;
101const uint32_t REG_FWSM     = 0x05B54;
102const uint32_t REG_SWFWSYNC = 0x05B5C;
103
104const uint8_t EEPROM_READ_OPCODE_SPI    = 0x03;
105const uint8_t EEPROM_RDSR_OPCODE_SPI    = 0x05;
106const uint8_t EEPROM_SIZE               = 64;
107const uint16_t EEPROM_CSUM              = 0xBABA;
108
109const uint8_t VLAN_FILTER_TABLE_SIZE    = 128;
110const uint8_t RCV_ADDRESS_TABLE_SIZE    = 24;
111const uint8_t MULTICAST_TABLE_SIZE      = 128;
112const uint32_t STATS_REGS_SIZE           = 0x228;
113
114
115// Registers in that are accessed in the PHY
116const uint8_t PHY_PSTATUS       = 0x1;
117const uint8_t PHY_PID           = 0x2;
118const uint8_t PHY_EPID          = 0x3;
119const uint8_t PHY_GSTATUS       = 10;
120const uint8_t PHY_EPSTATUS      = 15;
121const uint8_t PHY_AGC           = 18;
122
123// Receive Descriptor Status Flags
124const uint16_t RXDS_DYNINT      = 0x800;
125const uint16_t RXDS_UDPV        = 0x400;
126const uint16_t RXDS_CRCV        = 0x100;
127const uint16_t RXDS_PIF         = 0x080;
128const uint16_t RXDS_IPCS        = 0x040;
129const uint16_t RXDS_TCPCS       = 0x020;
130const uint16_t RXDS_UDPCS       = 0x010;
131const uint16_t RXDS_VP          = 0x008;
132const uint16_t RXDS_IXSM        = 0x004;
133const uint16_t RXDS_EOP         = 0x002;
134const uint16_t RXDS_DD          = 0x001;
135
136// Receive Descriptor Error Flags
137const uint8_t RXDE_RXE         = 0x80;
138const uint8_t RXDE_IPE         = 0x40;
139const uint8_t RXDE_TCPE        = 0x20;
140const uint8_t RXDE_SEQ         = 0x04;
141const uint8_t RXDE_SE          = 0x02;
142const uint8_t RXDE_CE          = 0x01;
143
144// Receive Descriptor Extended Error Flags
145const uint16_t RXDEE_HBO       = 0x008;
146const uint16_t RXDEE_CE        = 0x010;
147const uint16_t RXDEE_LE        = 0x020;
148const uint16_t RXDEE_PE        = 0x080;
149const uint16_t RXDEE_OSE       = 0x100;
150const uint16_t RXDEE_USE       = 0x200;
151const uint16_t RXDEE_TCPE      = 0x400;
152const uint16_t RXDEE_IPE       = 0x800;
153
154
155// Receive Descriptor Types
156const uint8_t RXDT_LEGACY      = 0x00;
157const uint8_t RXDT_ADV_ONEBUF  = 0x01;
158const uint8_t RXDT_ADV_SPLIT_A = 0x05;
159
160// Receive Descriptor Packet Types
161const uint16_t RXDP_IPV4       = 0x001;
162const uint16_t RXDP_IPV4E      = 0x002;
163const uint16_t RXDP_IPV6       = 0x004;
164const uint16_t RXDP_IPV6E      = 0x008;
165const uint16_t RXDP_TCP        = 0x010;
166const uint16_t RXDP_UDP        = 0x020;
167const uint16_t RXDP_SCTP       = 0x040;
168const uint16_t RXDP_NFS        = 0x080;
169
170// Interrupt types
171enum IntTypes
172{
173    IT_NONE    = 0x00000, //dummy value
174    IT_TXDW    = 0x00001,
175    IT_TXQE    = 0x00002,
176    IT_LSC     = 0x00004,
177    IT_RXSEQ   = 0x00008,
178    IT_RXDMT   = 0x00010,
179    IT_RXO     = 0x00040,
180    IT_RXT     = 0x00080,
181    IT_MADC    = 0x00200,
182    IT_RXCFG   = 0x00400,
183    IT_GPI0    = 0x02000,
184    IT_GPI1    = 0x04000,
185    IT_TXDLOW  = 0x08000,
186    IT_SRPD    = 0x10000,
187    IT_ACK     = 0x20000
188};
189
190// Receive Descriptor struct
191struct RxDesc {
192    union {
193        struct {
194            Addr buf;
195            uint16_t len;
196            uint16_t csum;
197            uint8_t status;
198            uint8_t errors;
199            uint16_t vlan;
200        } legacy;
201        struct {
202            Addr pkt;
203            Addr hdr;
204        } adv_read;
205        struct {
206            uint16_t rss_type:4;
207            uint16_t pkt_type:12;
208            uint16_t __reserved1:5;
209            uint16_t header_len:10;
210            uint16_t sph:1;
211            union {
212                struct {
213                    uint16_t id;
214                    uint16_t csum;
215                };
216                uint32_t rss_hash;
217            };
218            uint32_t status:20;
219            uint32_t errors:12;
220            uint16_t pkt_len;
221            uint16_t vlan_tag;
222        } adv_wb ;
223    };
224};
225
226struct TxDesc {
227    uint64_t d1;
228    uint64_t d2;
229};
230
231namespace TxdOp {
232const uint8_t TXD_CNXT = 0x0;
233const uint8_t TXD_DATA = 0x1;
234const uint8_t TXD_ADVCNXT = 0x2;
235const uint8_t TXD_ADVDATA = 0x3;
236
237inline bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
238inline uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
239inline bool isType(TxDesc *d, uint8_t type) { return getType(d) == type; }
240inline bool isTypes(TxDesc *d, uint8_t t1, uint8_t t2) { return isType(d, t1) || isType(d, t2); }
241inline bool isAdvDesc(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_ADVDATA,TXD_ADVCNXT);  }
242inline bool isContext(TxDesc *d) { return !isLegacy(d) && isTypes(d,TXD_CNXT, TXD_ADVCNXT); }
243inline bool isData(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_DATA, TXD_ADVDATA); }
244
245inline Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; }
246inline Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); }
247inline void setDd(TxDesc *d) { replaceBits(d->d2, 35, 32, ULL(1)); }
248
249inline bool ide(TxDesc *d)  { return bits(d->d2, 31,31) && (getType(d) == TXD_DATA || isLegacy(d)); }
250inline bool vle(TxDesc *d)  { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); }
251inline bool rs(TxDesc *d)   { return bits(d->d2, 27,27); }
252inline bool ic(TxDesc *d)   { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 26,26); }
253inline bool tse(TxDesc *d)  {
254    if (isTypes(d, TXD_CNXT, TXD_DATA))
255        return bits(d->d2, 26,26);
256    if (isType(d, TXD_ADVDATA))
257        return bits(d->d2, 31, 31);
258    return false;
259}
260
261inline bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); }
262inline bool eop(TxDesc *d)  { assert(isLegacy(d) || isData(d)); return bits(d->d2, 24,24); }
263inline bool ip(TxDesc *d)   { assert(isContext(d)); return bits(d->d2, 25,25); }
264inline bool tcp(TxDesc *d)  { assert(isContext(d)); return bits(d->d2, 24,24); }
265
266inline uint8_t getCso(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 23,16); }
267inline uint8_t getCss(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 47,40); }
268
269inline bool ixsm(TxDesc *d)  { return isData(d) && bits(d->d2, 40,40); }
270inline bool txsm(TxDesc *d)  { return isData(d) && bits(d->d2, 41,41); }
271
272inline int tucse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,63,48); }
273inline int tucso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,47,40); }
274inline int tucss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,39,32); }
275inline int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); }
276inline int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); }
277inline int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
278inline int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
279inline int hdrlen(TxDesc *d) {
280    assert(isContext(d));
281    if (!isAdvDesc(d))
282        return bits(d->d2,47,40);
283    return bits(d->d2, 47,40) + bits(d->d1, 8,0) + bits(d->d1, 15, 9);
284}
285
286inline int getTsoLen(TxDesc *d) { assert(isType(d, TXD_ADVDATA)); return bits(d->d2, 63,46); }
287inline int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); }
288} // namespace TxdOp
289
290
291#define ADD_FIELD32(NAME, OFFSET, BITS) \
292    inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
293    inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
294
295#define ADD_FIELD64(NAME, OFFSET, BITS) \
296    inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \
297    inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); }
298
299struct Regs : public Serializable {
300    template<class T>
301    struct Reg {
302        T _data;
303        T operator()() { return _data; }
304        const Reg<T> &operator=(T d) { _data = d; return *this;}
305        bool operator==(T d) { return d == _data; }
306        void operator()(T d) { _data = d; }
307        Reg() { _data = 0; }
308        void serialize(CheckpointOut &cp) const
309        {
310            SERIALIZE_SCALAR(_data);
311        }
312        void unserialize(CheckpointIn &cp)
313        {
314            UNSERIALIZE_SCALAR(_data);
315        }
316    };
317
318    struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register
319        using Reg<uint32_t>::operator=;
320        ADD_FIELD32(fd,0,1);       // full duplex
321        ADD_FIELD32(bem,1,1);      // big endian mode
322        ADD_FIELD32(pcipr,2,1);    // PCI priority
323        ADD_FIELD32(lrst,3,1);     // link reset
324        ADD_FIELD32(tme,4,1);      // test mode enable
325        ADD_FIELD32(asde,5,1);     // Auto-speed detection
326        ADD_FIELD32(slu,6,1);      // Set link up
327        ADD_FIELD32(ilos,7,1);     // invert los-of-signal
328        ADD_FIELD32(speed,8,2);    // speed selection bits
329        ADD_FIELD32(be32,10,1);    // big endian mode 32
330        ADD_FIELD32(frcspd,11,1);  // force speed
331        ADD_FIELD32(frcdpx,12,1);  // force duplex
332        ADD_FIELD32(duden,13,1);   // dock/undock enable
333        ADD_FIELD32(dudpol,14,1);  // dock/undock polarity
334        ADD_FIELD32(fphyrst,15,1); // force phy reset
335        ADD_FIELD32(extlen,16,1);  // external link status enable
336        ADD_FIELD32(rsvd,17,1);    // reserved
337        ADD_FIELD32(sdp0d,18,1);   // software controlled pin data
338        ADD_FIELD32(sdp1d,19,1);   // software controlled pin data
339        ADD_FIELD32(sdp2d,20,1);   // software controlled pin data
340        ADD_FIELD32(sdp3d,21,1);   // software controlled pin data
341        ADD_FIELD32(sdp0i,22,1);   // software controlled pin dir
342        ADD_FIELD32(sdp1i,23,1);   // software controlled pin dir
343        ADD_FIELD32(sdp2i,24,1);   // software controlled pin dir
344        ADD_FIELD32(sdp3i,25,1);   // software controlled pin dir
345        ADD_FIELD32(rst,26,1);     // reset
346        ADD_FIELD32(rfce,27,1);    // receive flow control enable
347        ADD_FIELD32(tfce,28,1);    // transmit flow control enable
348        ADD_FIELD32(rte,29,1);     // routing tag enable
349        ADD_FIELD32(vme,30,1);     // vlan enable
350        ADD_FIELD32(phyrst,31,1);  // phy reset
351    };
352    CTRL ctrl;
353
354    struct STATUS : public Reg<uint32_t> { // 0x0008 STATUS Register
355        using Reg<uint32_t>::operator=;
356        ADD_FIELD32(fd,0,1);       // full duplex
357        ADD_FIELD32(lu,1,1);       // link up
358        ADD_FIELD32(func,2,2);     // function id
359        ADD_FIELD32(txoff,4,1);    // transmission paused
360        ADD_FIELD32(tbimode,5,1);  // tbi mode
361        ADD_FIELD32(speed,6,2);    // link speed
362        ADD_FIELD32(asdv,8,2);     // auto speed detection value
363        ADD_FIELD32(mtxckok,10,1); // mtx clock running ok
364        ADD_FIELD32(pci66,11,1);   // In 66Mhz pci slot
365        ADD_FIELD32(bus64,12,1);   // in 64 bit slot
366        ADD_FIELD32(pcix,13,1);    // Pci mode
367        ADD_FIELD32(pcixspd,14,2); // pci x speed
368    };
369    STATUS sts;
370
371    struct EECD : public Reg<uint32_t> { // 0x0010 EECD Register
372        using Reg<uint32_t>::operator=;
373        ADD_FIELD32(sk,0,1);       // clack input to the eeprom
374        ADD_FIELD32(cs,1,1);       // chip select to eeprom
375        ADD_FIELD32(din,2,1);      // data input to eeprom
376        ADD_FIELD32(dout,3,1);     // data output bit
377        ADD_FIELD32(fwe,4,2);      // flash write enable
378        ADD_FIELD32(ee_req,6,1);   // request eeprom access
379        ADD_FIELD32(ee_gnt,7,1);   // grant eeprom access
380        ADD_FIELD32(ee_pres,8,1);  // eeprom present
381        ADD_FIELD32(ee_size,9,1);  // eeprom size
382        ADD_FIELD32(ee_sz1,10,1);  // eeprom size
383        ADD_FIELD32(rsvd,11,2);    // reserved
384        ADD_FIELD32(ee_type,13,1); // type of eeprom
385    } ;
386    EECD eecd;
387
388    struct EERD : public Reg<uint32_t> { // 0x0014 EERD Register
389        using Reg<uint32_t>::operator=;
390        ADD_FIELD32(start,0,1);  // start read
391        ADD_FIELD32(done,1,1);   // done read
392        ADD_FIELD32(addr,2,14);   // address
393        ADD_FIELD32(data,16,16); // data
394    };
395    EERD eerd;
396
397    struct CTRL_EXT : public Reg<uint32_t> { // 0x0018 CTRL_EXT Register
398        using Reg<uint32_t>::operator=;
399        ADD_FIELD32(gpi_en,0,4);      // enable interrupts from gpio
400        ADD_FIELD32(phyint,5,1);      // reads the phy internal int status
401        ADD_FIELD32(sdp2_data,6,1);   // data from gpio sdp
402        ADD_FIELD32(spd3_data,7,1);   // data frmo gpio sdp
403        ADD_FIELD32(spd2_iodir,10,1); // direction of sdp2
404        ADD_FIELD32(spd3_iodir,11,1); // direction of sdp2
405        ADD_FIELD32(asdchk,12,1);     // initiate auto-speed-detection
406        ADD_FIELD32(eerst,13,1);      // reset the eeprom
407        ADD_FIELD32(spd_byps,15,1);   // bypass speed select
408        ADD_FIELD32(ro_dis,17,1);     // disable relaxed memory ordering
409        ADD_FIELD32(vreg,21,1);       // power down the voltage regulator
410        ADD_FIELD32(link_mode,22,2);  // interface to talk to the link
411        ADD_FIELD32(iame, 27,1);      // interrupt acknowledge auto-mask ??
412        ADD_FIELD32(drv_loaded, 28,1);// driver is loaded and incharge of device
413        ADD_FIELD32(timer_clr, 29,1); // clear interrupt timers after IMS clear ??
414    };
415    CTRL_EXT ctrl_ext;
416
417    struct MDIC : public Reg<uint32_t> { // 0x0020 MDIC Register
418        using Reg<uint32_t>::operator=;
419        ADD_FIELD32(data,0,16);   // data
420        ADD_FIELD32(regadd,16,5); // register address
421        ADD_FIELD32(phyadd,21,5); // phy addresses
422        ADD_FIELD32(op,26,2);     // opcode
423        ADD_FIELD32(r,28,1);      // ready
424        ADD_FIELD32(i,29,1);      // interrupt
425        ADD_FIELD32(e,30,1);      // error
426    };
427    MDIC mdic;
428
429    struct ICR : public Reg<uint32_t> { // 0x00C0 ICR Register
430        using Reg<uint32_t>::operator=;
431        ADD_FIELD32(txdw,0,1)   // tx descr witten back
432        ADD_FIELD32(txqe,1,1)   // tx queue empty
433        ADD_FIELD32(lsc,2,1)    // link status change
434        ADD_FIELD32(rxseq,3,1)  // rcv sequence error
435        ADD_FIELD32(rxdmt0,4,1) // rcv descriptor min thresh
436        ADD_FIELD32(rsvd1,5,1)  // reserved
437        ADD_FIELD32(rxo,6,1)    // receive overrunn
438        ADD_FIELD32(rxt0,7,1)   // receiver timer interrupt
439        ADD_FIELD32(mdac,9,1)   // mdi/o access complete
440        ADD_FIELD32(rxcfg,10,1)  // recv /c/ ordered sets
441        ADD_FIELD32(phyint,12,1) // phy interrupt
442        ADD_FIELD32(gpi1,13,1)   // gpi int 1
443        ADD_FIELD32(gpi2,14,1)   // gpi int 2
444        ADD_FIELD32(txdlow,15,1) // transmit desc low thresh
445        ADD_FIELD32(srpd,16,1)   // small receive packet detected
446        ADD_FIELD32(ack,17,1);    // receive ack frame
447        ADD_FIELD32(int_assert, 31,1); // interrupt caused a system interrupt
448    };
449    ICR icr;
450
451    uint32_t imr; // register that contains the current interrupt mask
452
453    struct ITR : public Reg<uint32_t> { // 0x00C4 ITR Register
454        using Reg<uint32_t>::operator=;
455        ADD_FIELD32(interval, 0,16); // minimum inter-interrutp inteval
456                                     // specified in 256ns interrupts
457    };
458    ITR itr;
459
460    // When CTRL_EXT.IAME and the ICR.INT_ASSERT is 1 an ICR read or write
461    // causes the IAM register contents to be written into the IMC
462    // automatically clearing all interrupts that have a bit in the IAM set
463    uint32_t iam;
464
465    struct RCTL : public Reg<uint32_t> { // 0x0100 RCTL Register
466        using Reg<uint32_t>::operator=;
467        ADD_FIELD32(rst,0,1);   // Reset
468        ADD_FIELD32(en,1,1);    // Enable
469        ADD_FIELD32(sbp,2,1);   // Store bad packets
470        ADD_FIELD32(upe,3,1);   // Unicast Promiscuous enabled
471        ADD_FIELD32(mpe,4,1);   // Multicast promiscuous enabled
472        ADD_FIELD32(lpe,5,1);   // long packet reception enabled
473        ADD_FIELD32(lbm,6,2);   //
474        ADD_FIELD32(rdmts,8,2); //
475        ADD_FIELD32(mo,12,2);    //
476        ADD_FIELD32(mdr,14,1);   //
477        ADD_FIELD32(bam,15,1);   //
478        ADD_FIELD32(bsize,16,2); //
479        ADD_FIELD32(vfe,18,1);   //
480        ADD_FIELD32(cfien,19,1); //
481        ADD_FIELD32(cfi,20,1);   //
482        ADD_FIELD32(dpf,22,1);   // discard pause frames
483        ADD_FIELD32(pmcf,23,1);  // pass mac control  frames
484        ADD_FIELD32(bsex,25,1);  // buffer size extension
485        ADD_FIELD32(secrc,26,1); // strip ethernet crc from incoming packet
486        unsigned descSize()
487        {
488            switch(bsize()) {
489                case 0: return bsex() == 0 ? 2048 : 0;
490                case 1: return bsex() == 0 ? 1024 : 16384;
491                case 2: return bsex() == 0 ? 512 : 8192;
492                case 3: return bsex() == 0 ? 256 : 4096;
493                default:
494                        return 0;
495            }
496        }
497    };
498    RCTL rctl;
499
500    struct FCTTV : public Reg<uint32_t> { // 0x0170 FCTTV
501        using Reg<uint32_t>::operator=;
502        ADD_FIELD32(ttv,0,16);    // Transmit Timer Value
503    };
504    FCTTV fcttv;
505
506    struct TCTL : public Reg<uint32_t> { // 0x0400 TCTL Register
507        using Reg<uint32_t>::operator=;
508        ADD_FIELD32(rst,0,1);    // Reset
509        ADD_FIELD32(en,1,1);     // Enable
510        ADD_FIELD32(bce,2,1);    // busy check enable
511        ADD_FIELD32(psp,3,1);    // pad short packets
512        ADD_FIELD32(ct,4,8);     // collision threshold
513        ADD_FIELD32(cold,12,10); // collision distance
514        ADD_FIELD32(swxoff,22,1); // software xoff transmission
515        ADD_FIELD32(pbe,23,1);    // packet burst enable
516        ADD_FIELD32(rtlc,24,1);   // retransmit late collisions
517        ADD_FIELD32(nrtu,25,1);   // on underrun no TX
518        ADD_FIELD32(mulr,26,1);   // multiple request
519    };
520    TCTL tctl;
521
522    struct PBA : public Reg<uint32_t> { // 0x1000 PBA Register
523        using Reg<uint32_t>::operator=;
524        ADD_FIELD32(rxa,0,16);
525        ADD_FIELD32(txa,16,16);
526    };
527    PBA pba;
528
529    struct FCRTL : public Reg<uint32_t> { // 0x2160 FCRTL Register
530        using Reg<uint32_t>::operator=;
531        ADD_FIELD32(rtl,3,28); // make this bigger than the spec so we can have
532                               // a larger buffer
533        ADD_FIELD32(xone, 31,1);
534    };
535    FCRTL fcrtl;
536
537    struct FCRTH : public Reg<uint32_t> { // 0x2168 FCRTL Register
538        using Reg<uint32_t>::operator=;
539        ADD_FIELD32(rth,3,13); // make this bigger than the spec so we can have
540                               //a larger buffer
541        ADD_FIELD32(xfce, 31,1);
542    };
543    FCRTH fcrth;
544
545    struct RDBA : public Reg<uint64_t> { // 0x2800 RDBA Register
546        using Reg<uint64_t>::operator=;
547        ADD_FIELD64(rdbal,0,32); // base address of rx descriptor ring
548        ADD_FIELD64(rdbah,32,32); // base address of rx descriptor ring
549    };
550    RDBA rdba;
551
552    struct RDLEN : public Reg<uint32_t> { // 0x2808 RDLEN Register
553        using Reg<uint32_t>::operator=;
554        ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
555    };
556    RDLEN rdlen;
557
558    struct SRRCTL : public Reg<uint32_t> { // 0x280C SRRCTL Register
559        using Reg<uint32_t>::operator=;
560        ADD_FIELD32(pktlen, 0, 8);
561        ADD_FIELD32(hdrlen, 8, 8); // guess based on header, not documented
562        ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv,
563                                     //101 hdr split
564        unsigned bufLen() { return pktlen() << 10; }
565        unsigned hdrLen() { return hdrlen() << 6; }
566    };
567    SRRCTL srrctl;
568
569    struct RDH : public Reg<uint32_t> { // 0x2810 RDH Register
570        using Reg<uint32_t>::operator=;
571        ADD_FIELD32(rdh,0,16); // head of the descriptor ring
572    };
573    RDH rdh;
574
575    struct RDT : public Reg<uint32_t> { // 0x2818 RDT Register
576        using Reg<uint32_t>::operator=;
577        ADD_FIELD32(rdt,0,16); // tail of the descriptor ring
578    };
579    RDT rdt;
580
581    struct RDTR : public Reg<uint32_t> { // 0x2820 RDTR Register
582        using Reg<uint32_t>::operator=;
583        ADD_FIELD32(delay,0,16); // receive delay timer
584        ADD_FIELD32(fpd, 31,1);   // flush partial descriptor block ??
585    };
586    RDTR rdtr;
587
588    struct RXDCTL : public Reg<uint32_t> { // 0x2828 RXDCTL Register
589        using Reg<uint32_t>::operator=;
590        ADD_FIELD32(pthresh,0,6);   // prefetch threshold, less that this
591                                    // consider prefetch
592        ADD_FIELD32(hthresh,8,6);   // number of descriptors in host mem to
593                                    // consider prefetch
594        ADD_FIELD32(wthresh,16,6);  // writeback threshold
595        ADD_FIELD32(gran,24,1);     // granularity 0 = desc, 1 = cacheline
596    };
597    RXDCTL rxdctl;
598
599    struct RADV : public Reg<uint32_t> { // 0x282C RADV Register
600        using Reg<uint32_t>::operator=;
601        ADD_FIELD32(idv,0,16); // absolute interrupt delay
602    };
603    RADV radv;
604
605    struct RSRPD : public Reg<uint32_t> { // 0x2C00 RSRPD Register
606        using Reg<uint32_t>::operator=;
607        ADD_FIELD32(idv,0,12); // size to interrutp on small packets
608    };
609    RSRPD rsrpd;
610
611    struct TDBA : public Reg<uint64_t> { // 0x3800 TDBAL Register
612        using Reg<uint64_t>::operator=;
613        ADD_FIELD64(tdbal,0,32); // base address of transmit descriptor ring
614        ADD_FIELD64(tdbah,32,32); // base address of transmit descriptor ring
615    };
616    TDBA tdba;
617
618    struct TDLEN : public Reg<uint32_t> { // 0x3808 TDLEN Register
619        using Reg<uint32_t>::operator=;
620        ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer
621    };
622    TDLEN tdlen;
623
624    struct TDH : public Reg<uint32_t> { // 0x3810 TDH Register
625        using Reg<uint32_t>::operator=;
626        ADD_FIELD32(tdh,0,16); // head of the descriptor ring
627    };
628    TDH tdh;
629
630    struct TXDCA_CTL : public Reg<uint32_t> { // 0x3814 TXDCA_CTL Register
631        using Reg<uint32_t>::operator=;
632        ADD_FIELD32(cpu_mask, 0, 5);
633        ADD_FIELD32(enabled, 5,1);
634        ADD_FIELD32(relax_ordering, 6, 1);
635    };
636    TXDCA_CTL txdca_ctl;
637
638    struct TDT : public Reg<uint32_t> { // 0x3818 TDT Register
639        using Reg<uint32_t>::operator=;
640        ADD_FIELD32(tdt,0,16); // tail of the descriptor ring
641    };
642    TDT tdt;
643
644    struct TIDV : public Reg<uint32_t> { // 0x3820 TIDV Register
645        using Reg<uint32_t>::operator=;
646        ADD_FIELD32(idv,0,16); // interrupt delay
647    };
648    TIDV tidv;
649
650    struct TXDCTL : public Reg<uint32_t> { // 0x3828 TXDCTL Register
651        using Reg<uint32_t>::operator=;
652        ADD_FIELD32(pthresh, 0,6);  // if number of descriptors control has is
653                                    // below this number, a prefetch is considered
654        ADD_FIELD32(hthresh,8,8);   // number of valid descriptors is host memory
655                                    // before a prefetch is considered
656        ADD_FIELD32(wthresh,16,6);  // number of descriptors to keep until
657                                    // writeback is considered
658        ADD_FIELD32(gran, 24,1);    // granulatiry of above values (0 = cacheline,
659                                    // 1 == desscriptor)
660        ADD_FIELD32(lwthresh,25,7); // xmit descriptor low thresh, interrupt
661                                    // below this level
662    };
663    TXDCTL txdctl;
664
665    struct TADV : public Reg<uint32_t> { // 0x382C TADV Register
666        using Reg<uint32_t>::operator=;
667        ADD_FIELD32(idv,0,16); // absolute interrupt delay
668    };
669    TADV tadv;
670/*
671    struct TDWBA : public Reg<uint64_t> { // 0x3838 TDWBA Register
672        using Reg<uint64_t>::operator=;
673        ADD_FIELD64(en,0,1); // enable  transmit description ring address writeback
674        ADD_FIELD64(tdwbal,2,32); // base address of transmit descriptor ring address writeback
675        ADD_FIELD64(tdwbah,32,32); // base address of transmit descriptor ring
676    };
677    TDWBA tdwba;*/
678    uint64_t tdwba;
679
680    struct RXCSUM : public Reg<uint32_t> { // 0x5000 RXCSUM Register
681        using Reg<uint32_t>::operator=;
682        ADD_FIELD32(pcss,0,8);
683        ADD_FIELD32(ipofld,8,1);
684        ADD_FIELD32(tuofld,9,1);
685        ADD_FIELD32(pcsd, 13,1);
686    };
687    RXCSUM rxcsum;
688
689    uint32_t rlpml; // 0x5004 RLPML probably maximum accepted packet size
690
691    struct RFCTL : public Reg<uint32_t> { // 0x5008 RFCTL Register
692        using Reg<uint32_t>::operator=;
693        ADD_FIELD32(iscsi_dis,0,1);
694        ADD_FIELD32(iscsi_dwc,1,5);
695        ADD_FIELD32(nfsw_dis,6,1);
696        ADD_FIELD32(nfsr_dis,7,1);
697        ADD_FIELD32(nfs_ver,8,2);
698        ADD_FIELD32(ipv6_dis,10,1);
699        ADD_FIELD32(ipv6xsum_dis,11,1);
700        ADD_FIELD32(ackdis,13,1);
701        ADD_FIELD32(ipfrsp_dis,14,1);
702        ADD_FIELD32(exsten,15,1);
703    };
704    RFCTL rfctl;
705
706    struct MANC : public Reg<uint32_t> { // 0x5820 MANC Register
707        using Reg<uint32_t>::operator=;
708        ADD_FIELD32(smbus,0,1);    // SMBus enabled #####
709        ADD_FIELD32(asf,1,1);      // ASF enabled #####
710        ADD_FIELD32(ronforce,2,1); // reset of force
711        ADD_FIELD32(rsvd,3,5);     // reserved
712        ADD_FIELD32(rmcp1,8,1);    // rcmp1 filtering
713        ADD_FIELD32(rmcp2,9,1);    // rcmp2 filtering
714        ADD_FIELD32(ipv4,10,1);     // enable ipv4
715        ADD_FIELD32(ipv6,11,1);     // enable ipv6
716        ADD_FIELD32(snap,12,1);     // accept snap
717        ADD_FIELD32(arp,13,1);      // filter arp #####
718        ADD_FIELD32(neighbor,14,1); // neighbor discovery
719        ADD_FIELD32(arp_resp,15,1); // arp response
720        ADD_FIELD32(tcorst,16,1);   // tco reset happened
721        ADD_FIELD32(rcvtco,17,1);   // receive tco enabled ######
722        ADD_FIELD32(blkphyrst,18,1);// block phy resets ########
723        ADD_FIELD32(rcvall,19,1);   // receive all
724        ADD_FIELD32(macaddrfltr,20,1); // mac address filtering ######
725        ADD_FIELD32(mng2host,21,1); // mng2 host packets #######
726        ADD_FIELD32(ipaddrfltr,22,1); // ip address filtering
727        ADD_FIELD32(xsumfilter,23,1); // checksum filtering
728        ADD_FIELD32(brfilter,24,1); // broadcast filtering
729        ADD_FIELD32(smbreq,25,1);   // smb request
730        ADD_FIELD32(smbgnt,26,1);   // smb grant
731        ADD_FIELD32(smbclkin,27,1); // smbclkin
732        ADD_FIELD32(smbdatain,28,1); // smbdatain
733        ADD_FIELD32(smbdataout,29,1); // smb data out
734        ADD_FIELD32(smbclkout,30,1); // smb clock out
735    };
736    MANC manc;
737
738    struct SWSM : public Reg<uint32_t> { // 0x5B50 SWSM register
739        using Reg<uint32_t>::operator=;
740        ADD_FIELD32(smbi,0,1); // Semaphone bit
741        ADD_FIELD32(swesmbi, 1,1); // Software eeporm semaphore
742        ADD_FIELD32(wmng, 2,1); // Wake MNG clock
743        ADD_FIELD32(reserved, 3, 29);
744    };
745    SWSM swsm;
746
747    struct FWSM : public Reg<uint32_t> { // 0x5B54 FWSM register
748        using Reg<uint32_t>::operator=;
749        ADD_FIELD32(eep_fw_semaphore,0,1);
750        ADD_FIELD32(fw_mode, 1,3);
751        ADD_FIELD32(ide, 4,1);
752        ADD_FIELD32(sol, 5,1);
753        ADD_FIELD32(eep_roload, 6,1);
754        ADD_FIELD32(reserved, 7,8);
755        ADD_FIELD32(fw_val_bit, 15, 1);
756        ADD_FIELD32(reset_cnt, 16, 3);
757        ADD_FIELD32(ext_err_ind, 19, 6);
758        ADD_FIELD32(reserved2, 25, 7);
759    };
760    FWSM fwsm;
761
762    uint32_t sw_fw_sync;
763
764    void serialize(CheckpointOut &cp) const override
765    {
766        paramOut(cp, "ctrl", ctrl._data);
767        paramOut(cp, "sts", sts._data);
768        paramOut(cp, "eecd", eecd._data);
769        paramOut(cp, "eerd", eerd._data);
770        paramOut(cp, "ctrl_ext", ctrl_ext._data);
771        paramOut(cp, "mdic", mdic._data);
772        paramOut(cp, "icr", icr._data);
773        SERIALIZE_SCALAR(imr);
774        paramOut(cp, "itr", itr._data);
775        SERIALIZE_SCALAR(iam);
776        paramOut(cp, "rctl", rctl._data);
777        paramOut(cp, "fcttv", fcttv._data);
778        paramOut(cp, "tctl", tctl._data);
779        paramOut(cp, "pba", pba._data);
780        paramOut(cp, "fcrtl", fcrtl._data);
781        paramOut(cp, "fcrth", fcrth._data);
782        paramOut(cp, "rdba", rdba._data);
783        paramOut(cp, "rdlen", rdlen._data);
784        paramOut(cp, "srrctl", srrctl._data);
785        paramOut(cp, "rdh", rdh._data);
786        paramOut(cp, "rdt", rdt._data);
787        paramOut(cp, "rdtr", rdtr._data);
788        paramOut(cp, "rxdctl", rxdctl._data);
789        paramOut(cp, "radv", radv._data);
790        paramOut(cp, "rsrpd", rsrpd._data);
791        paramOut(cp, "tdba", tdba._data);
792        paramOut(cp, "tdlen", tdlen._data);
793        paramOut(cp, "tdh", tdh._data);
794        paramOut(cp, "txdca_ctl", txdca_ctl._data);
795        paramOut(cp, "tdt", tdt._data);
796        paramOut(cp, "tidv", tidv._data);
797        paramOut(cp, "txdctl", txdctl._data);
798        paramOut(cp, "tadv", tadv._data);
799        //paramOut(cp, "tdwba", tdwba._data);
800        SERIALIZE_SCALAR(tdwba);
801        paramOut(cp, "rxcsum", rxcsum._data);
802        SERIALIZE_SCALAR(rlpml);
803        paramOut(cp, "rfctl", rfctl._data);
804        paramOut(cp, "manc", manc._data);
805        paramOut(cp, "swsm", swsm._data);
806        paramOut(cp, "fwsm", fwsm._data);
807        SERIALIZE_SCALAR(sw_fw_sync);
808    }
809
810    void unserialize(CheckpointIn &cp) override
811    {
812        paramIn(cp, "ctrl", ctrl._data);
813        paramIn(cp, "sts", sts._data);
814        paramIn(cp, "eecd", eecd._data);
815        paramIn(cp, "eerd", eerd._data);
816        paramIn(cp, "ctrl_ext", ctrl_ext._data);
817        paramIn(cp, "mdic", mdic._data);
818        paramIn(cp, "icr", icr._data);
819        UNSERIALIZE_SCALAR(imr);
820        paramIn(cp, "itr", itr._data);
821        UNSERIALIZE_SCALAR(iam);
822        paramIn(cp, "rctl", rctl._data);
823        paramIn(cp, "fcttv", fcttv._data);
824        paramIn(cp, "tctl", tctl._data);
825        paramIn(cp, "pba", pba._data);
826        paramIn(cp, "fcrtl", fcrtl._data);
827        paramIn(cp, "fcrth", fcrth._data);
828        paramIn(cp, "rdba", rdba._data);
829        paramIn(cp, "rdlen", rdlen._data);
830        paramIn(cp, "srrctl", srrctl._data);
831        paramIn(cp, "rdh", rdh._data);
832        paramIn(cp, "rdt", rdt._data);
833        paramIn(cp, "rdtr", rdtr._data);
834        paramIn(cp, "rxdctl", rxdctl._data);
835        paramIn(cp, "radv", radv._data);
836        paramIn(cp, "rsrpd", rsrpd._data);
837        paramIn(cp, "tdba", tdba._data);
838        paramIn(cp, "tdlen", tdlen._data);
839        paramIn(cp, "tdh", tdh._data);
840        paramIn(cp, "txdca_ctl", txdca_ctl._data);
841        paramIn(cp, "tdt", tdt._data);
842        paramIn(cp, "tidv", tidv._data);
843        paramIn(cp, "txdctl", txdctl._data);
844        paramIn(cp, "tadv", tadv._data);
845        UNSERIALIZE_SCALAR(tdwba);
846        //paramIn(cp, "tdwba", tdwba._data);
847        paramIn(cp, "rxcsum", rxcsum._data);
848        UNSERIALIZE_SCALAR(rlpml);
849        paramIn(cp, "rfctl", rfctl._data);
850        paramIn(cp, "manc", manc._data);
851        paramIn(cp, "swsm", swsm._data);
852        paramIn(cp, "fwsm", fwsm._data);
853        UNSERIALIZE_SCALAR(sw_fw_sync);
854    }
855};
856} // namespace iGbReg
857