1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
//! This file contains the structs that are used to access device registers and contains configuration values to write to registers.
//! 
//! The registers are divided into multiple structs because we need to separate out the
//! receive and transmit queue registers and store them separately in a per-queue struct.
//! Though the e1000 device only has 1 pair of receive and transmit queues, we still structure
//! the design this way to be able to use code shared by all network drivers.
//! 
//! The 4 structs which cover the registers of the entire memory-mapped region are:
//! * `E1000Registers`
//! * `E1000RxRegisters`
//! * `E1000TxRegisters`
//! * `E1000MacRegisters`


use volatile::{Volatile, ReadOnly};
use zerocopy::FromBytes;

/// The layout in memory of the first set of e1000 registers. 
#[derive(FromBytes)]
#[repr(C)]
pub struct E1000Registers {
    pub ctrl:                       Volatile<u32>,          // 0x0
    _padding0:                      [u8; 4],                // 0x4 - 0x7
    pub status:                     ReadOnly<u32>,          // 0x8
    _padding1:                      [u8; 180],              // 0xC - 0xBF,  180 bytes
    
    /// Interrupt control registers
    pub icr:                        ReadOnly<u32>,          // 0xC0   
    _padding2:                      [u8; 12],               // 0xC4 - 0xCF
    pub ims:                        Volatile<u32>,          // 0xD0
    _padding3:                      [u8; 44],               // 0xD4 - 0xFF 

    /// Receive control register
    pub rctl:                       Volatile<u32>,          // 0x100
    _padding4:                      [u8; 764],              // 0x104 - 0x3FF,  764 bytes
    
    /// Transmit control register
    pub tctl:                       Volatile<u32>,          // 0x400
    _padding5:                      [u8; 7164],             // 0x404 - 0x1FFF
    
} // 2 4KiB pages

const _: () = assert!(core::mem::size_of::<E1000Registers>() == 2 * 4096);

/// The layout in memory of e1000 receive registers. 
#[derive(FromBytes)]
#[repr(C)]
pub struct E1000RxRegisters {
    _padding6:                      [u8; 2048],             // 0x2000 - 0x27FF

    pub rx_regs:                    RegistersRx,            // 0x2800    
    _padding7:                      [u8; 2020],             // 0x281C - 0x2FFF
} // 1 4KiB page

const _: () = assert!(core::mem::size_of::<E1000RxRegisters>() == 4096);


/// The layout in memory of e1000 transmit registers. 
#[derive(FromBytes)]
#[repr(C)]
pub struct E1000TxRegisters {
    _padding8:                      [u8; 2048],             // 0x3000 - 0x37FF

    pub tx_regs:                    RegistersTx,            // 0x3800
    _padding9:                      [u8; 2020],             // 0x381C - 0x3FFF
} // 1 4KiB page

const _: () = assert!(core::mem::size_of::<E1000TxRegisters>() == 4096);


/// The layout in memory of e1000 MAC address registers. 
#[derive(FromBytes)]
#[repr(C)]
pub struct E1000MacRegisters {
    _padding10:                     [u8; 5120],             // 0x4000 - 0x53FF
    
    /// The lower (least significant) 32 bits of the NIC's MAC hardware address.
    pub ral:                        Volatile<u32>,          // 0x5400
    /// The higher (most significant) 32 bits of the NIC's MAC hardware address.
    pub rah:                        Volatile<u32>,          // 0x5404
    _padding11:                     [u8; 109560],           // 0x5408 - 0x1FFFF,  109560 bytes
    // End of all register structs should be at offset 0x20000 (128 KiB in total size).

} // 28 4KiB pages

const _: () = assert!(core::mem::size_of::<E1000MacRegisters>() == 28 * 4096);

// check that the sum of all the register structs is equal to the memory of the e1000 device (128 KiB).
const _: () = assert!(
    core::mem::size_of::<E1000Registers>()
    + core::mem::size_of::<E1000RxRegisters>()
    + core::mem::size_of::<E1000TxRegisters>()
    + core::mem::size_of::<E1000MacRegisters>()
    == 0x20000
);


/// Struct that holds registers related to one receive queue.
#[derive(FromBytes)]
#[repr(C)]
pub struct RegistersRx {
    /// The lower (least significant) 32 bits of the physical address of the array of receive descriptors.
    pub rdbal:                      Volatile<u32>,        // 0x2800
    /// The higher (most significant) 32 bits of the physical address of the array of receive descriptors.
    pub rdbah:                      Volatile<u32>,        // 0x2804
    /// The length in bytes of the array of receive descriptors.
    pub rdlen:                      Volatile<u32>,        // 0x2808
    _padding0:                      [u8; 4],                // 0x280C - 0x280F
    /// The receive descriptor head index, which points to the next available receive descriptor.
    pub rdh:                        Volatile<u32>,          // 0x2810
    _padding1:                      [u8; 4],                // 0x2814 - 0x2817
    /// The receive descriptor tail index, which points to the last available receive descriptor.
    pub rdt:                        Volatile<u32>,          // 0x2818
}


/// Struct that holds registers related to one transmit queue.
#[derive(FromBytes)]
#[repr(C)]
pub struct RegistersTx {
    /// The lower (least significant) 32 bits of the physical address of the array of transmit descriptors.
    pub tdbal:                      Volatile<u32>,        // 0x3800
    /// The higher (most significant) 32 bits of the physical address of the array of transmit descriptors.
    pub tdbah:                      Volatile<u32>,        // 0x3804
    /// The length in bytes of the array of transmit descriptors.
    pub tdlen:                      Volatile<u32>,        // 0x3808
    _padding0:                      [u8; 4],                // 0x380C - 0x380F
    /// The transmit descriptor head index, which points to the next available transmit descriptor.
    pub tdh:                        Volatile<u32>,          // 0x3810
    _padding1:                      [u8; 4],                // 0x3814 - 0x3817
    /// The transmit descriptor tail index, which points to the last available transmit descriptor.
    pub tdt:                        Volatile<u32>,          // 0x3818
}

pub const REG_CTRL:                 u32 = 0x0000;
pub const REG_STATUS:               u32 = 0x0008;
pub const REG_EEPROM:               u32 = 0x0014;
pub const REG_CTRL_EXT:             u32 = 0x0018;
pub const REG_IMASK:                u32 = 0x00D0;
pub const REG_RCTRL:                u32 = 0x0100;
pub const REG_RXDESCLO:             u32 = 0x2800;
pub const REG_RXDESCHI:             u32 = 0x2804;
pub const REG_RXDESCLEN:            u32 = 0x2808;
pub const REG_RXDESCHEAD:           u32 = 0x2810;
pub const REG_RXDESCTAIL:           u32 = 0x2818;

pub const REG_TCTRL:                u32 = 0x0400;
pub const REG_TXDESCLO:             u32 = 0x3800;
pub const REG_TXDESCHI:             u32 = 0x3804;
pub const REG_TXDESCLEN:            u32 = 0x3808;
pub const REG_TXDESCHEAD:           u32 = 0x3810;
pub const REG_TXDESCTAIL:           u32 = 0x3818;

/// RX Delay Timer Register
pub const REG_RDTR:                 u32 = 0x2820;    
/// RX Descriptor Control  
pub const REG_RXDCTL:               u32 = 0x3828;    
/// RX Int. Absolute Delay Timer  
pub const REG_RADV:                 u32 = 0x282C; 
/// RX Small Packet Detect Interrupt     
pub const REG_RSRPD:                u32 = 0x2C00;      
 
pub const REG_MTA:                  u32 = 0x5200; 
pub const REG_CRCERRS:              u32 = 0x4000;

/// Transmit Inter Packet Gap
pub const REG_TIPG:                 u32 = 0x0410;    
/// set link up  
pub const ECTRL_SLU:                u32 = 0x40;        

// CTRL commands
pub const CTRL_LRST:                u32 = 1 << 3;
pub const CTRL_ILOS:                u32 = 1 << 7;
pub const CTRL_VME:                 u32 = 1 << 30; 
pub const CTRL_PHY_RST:             u32 = 1 << 31;

// RCTL commands
/// Receiver Enable
pub const RCTL_EN:                  u32 = 1 << 1;    
/// Store Bad Packets
pub const RCTL_SBP:                 u32 = 1 << 2;   
/// Unicast Promiscuous Enabled 
pub const RCTL_UPE:                 u32 = 1 << 3;  
/// Multicast Promiscuous Enabled  
pub const RCTL_MPE:                 u32 = 1 << 4;    
/// Long Packet Reception Enable
pub const RCTL_LPE:                 u32 = 1 << 5;    
/// No Loopback
pub const RCTL_LBM_NONE:            u32 = 0 << 6;    
/// PHY or external SerDesc loopback
pub const RCTL_LBM_PHY:             u32 = 3 << 6;    
/// Free Buffer Threshold is 1/2 of RDLEN
pub const RTCL_RDMTS_HALF:          u32 = 0 << 8;    
/// Free Buffer Threshold is 1/4 of RDLEN
pub const RTCL_RDMTS_QUARTER:       u32 = 1 << 8;    
/// Free Buffer Threshold is 1/8 of RDLEN
pub const RTCL_RDMTS_EIGHTH:        u32 = 2 << 8;    
/// Multicast Offset - bits 47:36
pub const RCTL_MO_36:               u32 = 0 << 12;   
/// Multicast Offset - bits 46:35
pub const RCTL_MO_35:               u32 = 1 << 12;   
/// Multicast Offset - bits 45:34
pub const RCTL_MO_34:               u32 = 2 << 12;   
/// Multicast Offset - bits 43:32
pub const RCTL_MO_32:               u32 = 3 << 12;   
/// Broadcast Accept Mode
pub const RCTL_BAM:                 u32 = 1 << 15;   
/// VLAN Filter Enable
pub const RCTL_VFE:                 u32 = 1 << 18;   
/// Canonical Form Indicator Enable
pub const RCTL_CFIEN:               u32 = 1 << 19;   
/// Canonical Form Indicator Bit Value
pub const RCTL_CFI:                 u32 = 1 << 20;   
/// Discard Pause Frames
pub const RCTL_DPF:                 u32 = 1 << 22;   
/// Pass MAC Control Frames
pub const RCTL_PMCF:                u32 = 1 << 23;   
/// Strip Ethernet CRC
pub const RCTL_SECRC:               u32 = 1 << 26;   
 
// Buffer Sizes
pub const RCTL_BSIZE_256:           u32 = 3 << 16;
pub const RCTL_BSIZE_512:           u32 = 2 << 16;
pub const RCTL_BSIZE_1024:          u32 = 1 << 16;
pub const RCTL_BSIZE_2048:          u32 = 0 << 16;
pub const RCTL_BSIZE_4096:          u32 = (3 << 16) | (1 << 25);
pub const RCTL_BSIZE_8192:          u32 = (2 << 16) | (1 << 25);
pub const RCTL_BSIZE_16384:         u32 = (1 << 16) | (1 << 25);
 
 
// TCTL commands
/// Transmit Enable
pub const TCTL_EN:                  u32 = 1 << 1;    
/// Pad Short Packets
pub const TCTL_PSP:                 u32 = 1 << 3;   
/// Collision Threshold 
pub const TCTL_CT_SHIFT:            u32 = 4;           
/// Collision Distance
pub const TCTL_COLD_SHIFT:          u32 = 12;         
/// Software XOFF Transmission 
pub const TCTL_SWXOFF:              u32 = 1 << 22;   
/// Re-transmit on Late Collision
pub const TCTL_RTLC:                u32 = 1 << 24;