1#include <compiler/core.h>
2#include <console/printf.h>
3#include <drivers/e1000.h>
4#include <drivers/mmio.h>
5#include <drivers/pci.h>
6#include <math/bit.h>
7#include <mem/alloc.h>
8#include <mem/nofail.h>
9#include <mem/page.h>
10#include <mem/pmm.h>
11#include <mem/vmm.h>
12#include <stdbool.h>
13#include <stdint.h>
14#include <string.h>
15#include <time/spin_sleep.h>
16
17LOG_HANDLE_DEFINE_PRINT(e1000);
18LOG_SITE_DEFINE_PRINT(e1000);
19
20#define E1000_MAX_TX_PACKET_SIZE 1518
21#define REG32(dev, offset) (&(dev->regs[(offset) / 4U]))
22
23static void e1000_reset(struct e1000_device *dev) {
24 mmio_write_32(REG32(dev, E1000_REG_CTRL), E1000_CTRL_RST);
25 sleep_spin_ms(msec: 1);
26}
27
28static void e1000_setup_tx_ring(struct e1000_device *dev) {
29 uint64_t space = sizeof(struct e1000_tx_desc) * E1000_NUM_TX_DESC;
30 dev->tx_descs_phys = pmm_alloc_page();
31 dev->tx_descs = mmio_map_dma(phys: dev->tx_descs_phys, size: space);
32 memset(dev->tx_descs, 0, space);
33
34 for (int i = 0; i < E1000_NUM_TX_DESC; i++) {
35 dev->tx_buffers[i] = nofail_valloc(2048);
36
37 dev->tx_descs[i].addr = vmm_get_phys((uintptr_t) dev->tx_buffers[i]);
38 dev->tx_descs[i].status = E1000_TXD_STAT_DD;
39 }
40
41 mmio_write_32(REG32(dev, E1000_REG_TDBAL),
42 value: (uint32_t) (dev->tx_descs_phys & 0xFFFFFFFF));
43 mmio_write_32(REG32(dev, E1000_REG_TDBAH),
44 value: (uint32_t) (dev->tx_descs_phys >> 32));
45 mmio_write_32(REG32(dev, E1000_REG_TDLEN),
46 E1000_NUM_TX_DESC * sizeof(struct e1000_tx_desc));
47 mmio_write_32(REG32(dev, E1000_REG_TDH), value: 0);
48 mmio_write_32(REG32(dev, E1000_REG_TDT), value: 0);
49 dev->tx_tail = 0;
50
51 mmio_write_32(REG32(dev, E1000_REG_TCTL),
52 E1000_TCTL_EN | E1000_TCTL_PSP |
53 (0x10 << E1000_TCTL_CT_SHIFT) |
54 (0x40 << E1000_TCTL_COLD_SHIFT));
55}
56
57static void e1000_setup_rx_ring(struct e1000_device *dev) {
58 uint64_t space = sizeof(struct e1000_rx_desc) * E1000_NUM_RX_DESC;
59 dev->rx_descs_phys = pmm_alloc_page();
60 dev->rx_descs = mmio_map_dma(phys: dev->rx_descs_phys, size: space);
61 memset(dev->rx_descs, 0, space);
62
63 for (int i = 0; i < E1000_NUM_RX_DESC; i++) {
64 dev->rx_buffers[i] = nofail_valloc(E1000_RX_BUF_SIZE);
65
66 dev->rx_descs[i].addr = vmm_get_phys((uintptr_t) dev->rx_buffers[i]);
67 dev->rx_descs[i].status = 0;
68 }
69
70 mmio_write_32(REG32(dev, E1000_REG_RDBAL),
71 value: (uint32_t) (dev->rx_descs_phys & 0xFFFFFFFF));
72 mmio_write_32(REG32(dev, E1000_REG_RDBAH),
73 value: (uint32_t) (dev->rx_descs_phys >> 32));
74 mmio_write_32(REG32(dev, E1000_REG_RDLEN),
75 E1000_NUM_RX_DESC * sizeof(struct e1000_rx_desc));
76 mmio_write_32(REG32(dev, E1000_REG_RDH), value: 0);
77 mmio_write_32(REG32(dev, E1000_REG_RDT), E1000_NUM_RX_DESC - 1);
78 dev->rx_tail = E1000_NUM_RX_DESC - 1;
79
80 mmio_write_32(REG32(dev, E1000_REG_RCTL),
81 E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SECRC);
82}
83
84static int e1000_send_packet(struct e1000_device *dev, const void *data,
85 uint64_t len) {
86 if (len > E1000_MAX_TX_PACKET_SIZE) {
87 return -1;
88 }
89
90 uint32_t next = dev->tx_tail;
91 struct e1000_tx_desc *desc = &dev->tx_descs[next];
92
93 if (!(desc->status & E1000_TXD_STAT_DD)) {
94 return -1;
95 }
96
97 memcpy(dev->tx_buffers[next], data, len);
98
99 desc->length = (uint16_t) len;
100 desc->cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS;
101 desc->status = 0;
102
103 dev->tx_tail = (next + 1) % E1000_NUM_TX_DESC;
104 mmio_write_32(REG32(dev, E1000_REG_TDT), value: dev->tx_tail);
105
106 return 0;
107}
108
109static inline uint16_t htons(uint16_t hostshort) {
110 return (hostshort << 8) | (hostshort >> 8);
111}
112
113static inline uint32_t htonl(uint32_t hostlong) {
114 return ((hostlong << 24) & 0xFF000000) | ((hostlong << 8) & 0x00FF0000) |
115 ((hostlong >> 8) & 0x0000FF00) | ((hostlong >> 24) & 0x000000FF);
116}
117
118static uint16_t checksum(void *data, int len) {
119 uint32_t sum = 0;
120 uint16_t *ptr = (uint16_t *) data;
121 while (len > 1) {
122 sum += *ptr++;
123 len -= 2;
124 }
125 if (len > 0)
126 sum += *((uint8_t *) ptr);
127 while (sum >> 16)
128 sum = (sum & 0xFFFF) + (sum >> 16);
129 return (uint16_t) (~sum);
130}
131
132static void send_hardcoded_ping(struct e1000_device *dev) {
133 uint8_t packet[14 + 20 + 8 + 32];
134 memset(packet, 0, sizeof(packet));
135
136 struct eth_hdr *eth = (void *) packet;
137 struct ipv4_hdr *ip = (void *) (packet + 14);
138 struct icmp_hdr *icmp = (void *) (packet + 14 + 20);
139 uint8_t *payload = packet + 14 + 20 + 8;
140
141 uint8_t src_mac[6] = {0x52, 0x54, 0x00, 0x12, 0x34, 0x56};
142 uint8_t dest_mac[6] = {0x52, 0x54, 0x00, 0x8e, 0x61, 0xf4};
143 ip->dest_ip = htonl(hostlong: 0xC0A87A01); // 192.168.122.1
144 ip->src_ip = htonl(hostlong: 0xC0A87A64); // 192.168.122.100
145
146 memcpy(eth->dest, dest_mac, 6);
147 memcpy(eth->src, src_mac, 6);
148 eth->ethertype = htons(hostshort: 0x0800);
149
150 ip->version_ihl = (4 << 4) | 5;
151 ip->tos = 0;
152 ip->total_length = htons(hostshort: 20 + 8 + 32);
153 ip->id = htons(hostshort: 0x1234);
154 ip->flags_fragment = 0;
155 ip->ttl = 64;
156 ip->protocol = 1;
157 ip->checksum = 0;
158 ip->checksum = checksum(data: ip, len: 20);
159
160 icmp->type = 8; // Echo request
161 icmp->code = 0;
162 icmp->identifier = htons(hostshort: 0x1);
163 icmp->sequence = htons(hostshort: 0x1);
164 memset(payload, 0xAA, 32); // dummy payload
165
166 icmp->checksum = 0;
167 icmp->checksum = checksum(data: icmp, len: 8 + 32);
168
169 e1000_send_packet(dev, data: packet, len: sizeof(packet));
170}
171
172bool e1000_init(struct pci_device *pci, struct e1000_device *dev) {
173 memset(dev, 0, sizeof(*dev));
174
175 dev->bus = pci->bus;
176 dev->device = pci->dev;
177 dev->function = pci->function;
178
179 e1000_log(LOG_INFO, "Found device at %02x:%02x.%02x", pci->bus, pci->dev,
180 pci->function);
181
182 uint32_t bar = pci_read(bus: dev->bus, slot: dev->device, func: dev->function, PCI_BAR0);
183 if (bar & 0x1)
184 return false; // Not MMIO
185
186 uint32_t phys_addr = bar & ~0xF;
187
188 pci_write(bus: dev->bus, slot: dev->device, func: dev->function, PCI_BAR0, value: 0xFFFFFFFF);
189 uint32_t bar_mask =
190 pci_read(bus: dev->bus, slot: dev->device, func: dev->function, PCI_BAR0);
191 pci_write(bus: dev->bus, slot: dev->device, func: dev->function, PCI_BAR0, value: bar);
192
193 uint64_t mmio_size = ~(bar_mask & ~0xF) + 1;
194 if (mmio_size == 0 || mmio_size > BIT(24))
195 return false;
196
197 dev->regs = mmio_map(phys: phys_addr, size: mmio_size);
198 if (!dev->regs)
199 return false;
200
201 e1000_reset(dev);
202
203 e1000_setup_tx_ring(dev);
204 e1000_setup_rx_ring(dev);
205 send_hardcoded_ping(dev);
206 e1000_log(LOG_INFO, "Device initialized successfully");
207 return true;
208}
209
210static enum err e1000_pci_init(struct device *dev) {
211 struct pci_device *db = dev->driver_data;
212 uint16_t did = db->device_id;
213 if (did == 0x1000 || did == 0x100E || did == 0x1010 || did == 0x1026 ||
214 did == 0x10D3 || did == 0x10F5) {
215 struct e1000_device *device = nofail_vnew(device);
216
217 e1000_init(pci: db, dev: device);
218 }
219
220 return ERR_OK;
221}
222
223PCI_DEV_REGISTER(e1000, 2, 0, 0xff, 0x8086, e1000_pci_init);
224