1 //
2 // Copyright (c) 2021 Travis Geiselbrecht
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7 
8 #pragma once
9 
10 #include <stdint.h>
11 #include <stdio.h>
12 
13 // from 8254x Family SDM Table 13-2
14 enum class e1000_reg {
15     // general
16     CTRL = 0x0,
17     STATUS = 0x8,
18     EECD = 0x10,
19     EERD = 0x14,
20     CTL_EXT = 0x18,
21     MDIC = 0x20,
22     FACL = 0x28,
23     FACH = 0x2c,
24     FCT = 0x30,
25     VET = 0x38,
26     FCTTV = 0x170,
27     TXCW = 0x178,
28     RXCW = 0x180,
29     LEDCTL = 0xe00,
30 
31     // DMA
32     DMA = 0x1000,
33 
34     // interrupt
35     ICR = 0xc0,
36     ITR = 0xc4,
37     IMS = 0xd0,
38     IMC = 0xd8,
39     IAM = 0xe0,
40     EITR0 = 0x1680, // e1000e only (i210)+
41     EITR1 = 0x1684,
42     EITR2 = 0x1688,
43     EITR3 = 0x168c,
44     EITR4 = 0x1690,
45 
46     // receive
47     RCTL = 0x100,
48     FCRTL = 0x2160,
49     FCRTH = 0x2168,
50     RDBAL = 0x2800,
51     RDBAH = 0x2804,
52     RDLEN = 0x2808,
53     RDH = 0x2810,
54     RDT = 0x2818,
55     RDTR = 0x2820,
56     RADV = 0x282c,
57     RSRPD = 0x2c00,
58 
59     // transmit
60     TCTL = 0x400,
61     TIPG = 0x410,
62     AIFS = 0x458,
63     TDBAL = 0x3800,
64     TDBAH = 0x3804,
65     TDLEN = 0x3808,
66     TDH = 0x3810,
67     TDT = 0x3818,
68     TIDV = 0x3820,
69 
70     // tx dma
71     TXDMAC = 0x3000,
72     TXDCTL = 0x3828,
73     TADV = 0x382c,
74     TSPMT = 0x3830,
75 
76     // rx dma
77     RXDCTL = 0x2828,
78     RXCSUM = 0x5000,
79 };
80 
81 // receive descriptor
82 struct rdesc {
83     uint64_t addr;
84     uint16_t length;
85     uint16_t checksum;
86     uint8_t status;
87     uint8_t errors;
88     uint16_t special;
89 
dumprdesc90     void dump() {
91         printf("rdsec %p: addr %#llx len %hu cksum %#hx stat %#hhx err %#hhx spec %#hx\n",
92                this, addr, length, checksum, status, errors, special);
93     }
94 
95 };
96 static_assert(sizeof(rdesc) == 16, "");
97 
98 // transmit descriptor (legacy)
99 struct tdesc {
100     uint64_t addr;
101     uint16_t length;
102     uint8_t cso;
103     uint8_t cmd;
104     uint8_t sta_rsv;
105     uint8_t css;
106     uint16_t special;
107 
dumptdesc108     void dump() {
109         printf("tdsec %p: addr %#llx len %hu cso %#hhx cmd %#hhx sta_rsv %#hhx css %#hhx spec %#hx\n",
110                this, addr, length, cso, cmd, sta_rsv, css, special);
111     }
112 };
113 static_assert(sizeof(tdesc) == 16, "");
114 
115 // efficient copy for rx/tx descriptors out/into uncached memory
116 template <typename T>
copy(T * _dst,const T * _src)117 inline void copy(T *_dst, const T *_src) {
118     // only allow this for structs that are precisely 16 bytes long
119     static_assert(sizeof(T) == 16, "");
120 
121     // treat as two 8 byte copies
122     uint64_t *dst = (uint64_t *)_dst;
123     const uint64_t *src = (uint64_t *)_src;
124 
125     dst[0] = src[0];
126     dst[1] = src[1];
127 }
128 
129