Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
e1000.cpp
Go to the documentation of this file.
1#include "e1000/e1000.hpp"
2#include "ioforge/ioforge.h"
4#include <type.h>
5
6#define IO_ADDR_OFFSET 0x0
7#define IO_DATA_OFFSET 0x4
8
9#define REG_CTRL 0x0000
10#define REG_STATUS 0x0008
11#define REG_EEPROM 0x0014
12#define REG_CTRL_EXT 0x0018
13#define REG_IMASK 0x00D0
14#define REG_RCTRL 0x0100
15#define REG_RXDESCLO 0x2800
16#define REG_RXDESCHI 0x2804
17#define REG_RXDESCLEN 0x2808
18#define REG_RXDESCHEAD 0x2810
19#define REG_RXDESCTAIL 0x2818
20
21#define IMS_RXT0 (1 << 7)
22#define IMS_RXO (1 << 6)
23#define IMS_RXDMT0 (1 << 4)
24#define IMS_LSC (1 << 2)
25
26#define IMS_RXQ0 (1 << 20) // Bit 20: Receive Queue 0
27#define IMS_TXQ0 (1 << 22) // Bit 22: Transmit Queue 0
28#define IMS_OTHER (1 << 24) // Bit 24: Other Causes (LSC, dll)
29
30#define REG_TCTRL 0x0400
31#define REG_TXDESCLO 0x3800
32#define REG_TXDESCHI 0x3804
33#define REG_TXDESCLEN 0x3808
34#define REG_TXDESCHEAD 0x3810
35#define REG_TXDESCTAIL 0x3818
36
37#define REG_RDTR 0x2820 // RX Delay Timer Register
38#define REG_RXDCTL 0x2828 // RX Descriptor Control
39#define REG_RADV 0x282C // RX Int. Absolute Delay Timer
40#define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt
41
42#define REG_TIPG 0x0410 // Transmit Inter Packet Gap
43#define ECTRL_SLU 0x40 // set link up
44
45#define RCTL_EN (1 << 1) // Receiver Enable
46#define RCTL_SBP (1 << 2) // Store Bad Packets
47#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled
48#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled
49#define RCTL_LPE (1 << 5) // Long Packet Reception Enable
50#define RCTL_LBM_NONE (0 << 6) // No Loopback
51#define RCTL_LBM_PHY (3 << 6) // PHY or external SerDesc loopback
52#define RTCL_RDMTS_HALF (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN
53#define RTCL_RDMTS_QUARTER (1 << 8) // Free Buffer Threshold is 1/4 of RDLEN
54#define RTCL_RDMTS_EIGHTH (2 << 8) // Free Buffer Threshold is 1/8 of RDLEN
55#define RCTL_MO_36 (0 << 12) // Multicast Offset - bits 47:36
56#define RCTL_MO_35 (1 << 12) // Multicast Offset - bits 46:35
57#define RCTL_MO_34 (2 << 12) // Multicast Offset - bits 45:34
58#define RCTL_MO_32 (3 << 12) // Multicast Offset - bits 43:32
59#define RCTL_BAM (1 << 15) // Broadcast Accept Mode
60#define RCTL_VFE (1 << 18) // VLAN Filter Enable
61#define RCTL_CFIEN (1 << 19) // Canonical Form Indicator Enable
62#define RCTL_CFI (1 << 20) // Canonical Form Indicator Bit Value
63#define RCTL_DPF (1 << 22) // Discard Pause Frames
64#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames
65#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC
66
67// Buffer Sizes
68#define RCTL_BSIZE_256 (3 << 16)
69#define RCTL_BSIZE_512 (2 << 16)
70#define RCTL_BSIZE_1024 (1 << 16)
71#define RCTL_BSIZE_2048 (0 << 16)
72#define RCTL_BSIZE_4096 ((3 << 16) | (1 << 25))
73#define RCTL_BSIZE_8192 ((2 << 16) | (1 << 25))
74#define RCTL_BSIZE_16384 ((1 << 16) | (1 << 25))
75
76// Transmit Command
77
78#define CMD_EOP (1 << 0) // End of Packet
79#define CMD_IFCS (1 << 1) // Insert FCS
80#define CMD_IC (1 << 2) // Insert Checksum
81#define CMD_RS (1 << 3) // Report Status
82#define CMD_RPS (1 << 4) // Report Packet Sent
83#define CMD_VLE (1 << 6) // VLAN Packet Enable
84#define CMD_IDE (1 << 7) // Interrupt Delay Enable
85
86// TCTL Register
87
88#define TCTL_EN (1 << 1) // Transmit Enable
89#define TCTL_PSP (1 << 3) // Pad Short Packets
90#define TCTL_CT_SHIFT 4 // Collision Threshold
91#define TCTL_COLD_SHIFT 12 // Collision Distance
92#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission
93#define TCTL_RTLC (1 << 24) // Re-transmit on Late Collision
94
95#define TSTA_DD (1 << 0) // Descriptor Done
96#define TSTA_EC (1 << 1) // Excess Collisions
97#define TSTA_LC (1 << 2) // Late Collision
98#define LSTA_TU (1 << 3) // Transmit Underrun
99
100//
101#define REG_ICR 0x00C0
102
106
107static volatile int setup_tx_done = 0;
108
109// buffer pool
111
118
119void E1000Module::write(uint16_t p_address, uint32_t p_value) {
120 volatile uint32_t* addr =
121 (volatile uint32_t*) (device->bar[0].address + p_address);
122 *addr = p_value;
123}
124
126 return *((volatile uint32_t*) (device->bar[0].address + p_address));
127}
128
130 uint32_t val = 0;
131 write(REG_EEPROM, 0x1);
132
133 for (int i = 0; i < 1000 && !eerprom_exists; i++) {
134 val = read(REG_EEPROM);
135 // if (val & 0x10)
136 if (val & 0b10)
137 eerprom_exists = true;
138 else
139 eerprom_exists = false;
140 }
141 return eerprom_exists;
142}
143
145 uint16_t data = 0;
146 uint32_t tmp = 0;
147 if (eerprom_exists) {
148 write(REG_EEPROM, (1) | ((uint32_t) (addr) << 8));
149 while (!((tmp = read(REG_EEPROM)) & (1 << 4)))
150 ;
151 } else {
152 write(REG_EEPROM, (1) | ((uint32_t) (addr) << 2));
153 while (!((tmp = read(REG_EEPROM)) & (1 << 1)))
154 ;
155 }
156 data = (uint16_t) ((tmp >> 16) & 0xFFFF);
157 return data;
158}
159
160static const char hexmap[] = "0123456789ABCDEF";
161
163 // TODO: detect eeprom dulu
164
165 uint32_t ral = read(0x5400);
166 uint32_t rah = read(0x5404);
167
168 // Cek bit Address Valid (Bit 31) di RAH
169 // Jika hardware mendukung AV bit, pastikan bit tersebut menyala
170 if ((rah & 0x80000000) == 0 && ral == 0) {
171 log("E1000", "MAC Address tidak valid (AV bit 0) atau kosong!");
172 return false;
173 }
174
175 // aktifkan bit AV (address valid)
176 rah |= (1u << 31);
177 write(0x5404, rah);
178 write(0x5400, ral);
179
180 // Masking rah dengan 0xFFFF untuk membuang bit status seperti AV
181 // agar tidak ikut masuk ke perhitungan MAC
182 mac_addr[0] = ral & 0xFF;
183 mac_addr[1] = (ral >> 8) & 0xFF;
184 mac_addr[2] = (ral >> 16) & 0xFF;
185 mac_addr[3] = (ral >> 24) & 0xFF;
186 mac_addr[4] = (rah & 0xFFFF) & 0xFF;
187 mac_addr[5] = ((rah & 0xFFFF) >> 8) & 0xFF;
188
189 mac_ready = true;
190
191 char outc[18] = {0};
192 uint8_t* out = (uint8_t*) outc;
193 for (int i = 0; i < 6; i++) {
194 uint8_t byte = mac_addr[i];
195 *out++ = hexmap[(byte >> 4) & 0x0F]; // nibble tinggi
196 *out++ = hexmap[byte & 0x0F]; // nibble rendah
197 if (i != 5)
198 *out++ = ':'; // tambahkan pemisah
199 }
200 *out = '\0';
201 log("E1000", "MAC terbaca dari MMIO: %s", outc);
202
203 return true;
204}
205
207 write(REG_IMASK, 0);
208 read(REG_ICR);
209
210 // msix
212
213 // msi
214 // write(REG_IMASK, IMS_RXT0 | IMS_RXDMT0 | IMS_RXO | IMS_LSC);
215 read(REG_ICR); // flush ICR
216}
217
219 write(REG_IMASK, 0x1F6DC);
220 write(REG_IMASK, 0xff);
221 read(0xc0);
222}
223static bool pool_pop(struct rx_buffer* out) {
224 uint32_t h = __atomic_load_n(&rx_buffer_pool.head, __ATOMIC_RELAXED);
225 uint32_t t = __atomic_load_n(&rx_buffer_pool.tail, __ATOMIC_ACQUIRE);
226
227 if (h == t)
228 return false; // kosong
229
230 // Data dijamin sudah ada karena tail baru di-increment SETELAH push
232
233 // head++ adalah sinyal ke producer bahwa slot ini bisa dipakai lagi
234 __atomic_store_n(&rx_buffer_pool.head, h + 1, __ATOMIC_RELEASE);
235 return true;
236}
237
239
240 struct e1000_rx_desc* descs;
241
242 // untuk descriptor
243 uintptr_t paddr = 0;
244 auto ptr = (uint8_t*) (IOUtils::DMAAlloc(
245 sizeof(struct e1000_rx_desc) * E1000_NUM_RX_DESC + 16, &paddr));
246
247 // alloc untuk buffer pool, ini tidak akan di free
248
249 for (int j = 0; j < BUFFER_POOL_SIZE; j += 2) {
250 uintptr_t _paddr = 0;
251 auto _ptr = (uint8_t*) (IOUtils::DMAAlloc(4096, &_paddr));
252
253 rx_buffer_pool.buffers[j].vaddr = _ptr;
254 rx_buffer_pool.buffers[j].paddr = _paddr;
255
256 rx_buffer_pool.buffers[j + 1].vaddr = _ptr + 2048;
257 rx_buffer_pool.buffers[j + 1].paddr = _paddr + 2048;
258
259 g_buf_lookup[g_buf_lookup_count++] = {_ptr, _paddr};
260 g_buf_lookup[g_buf_lookup_count++] = {_ptr + 2048,
261 _paddr + 2048};
262 }
265
266 descs = (struct e1000_rx_desc*) ptr;
267 for (int i = 0; i < E1000_NUM_RX_DESC; i++) {
268 rx_descs[i] =
269 (struct e1000_rx_desc*) ((uintptr_t) descs + i * 16);
270
271 // ambil dari from buffer pool
272 struct rx_buffer buf;
273 if (!pool_pop(&buf)) {
274 // Seharusnya tidak terjadi — pool baru diisi BUFFER_POOL_SIZE slot
275 log(mod, "initReceiverX: pool empty saat init! (BUG)");
276 continue;
277 }
278
279 rx_comp[i].paddr = buf.paddr;
280 rx_comp[i].addr = (uint64_t) buf.vaddr;
281
282 // bagian ini DMA (harus phys addr)
283 rx_descs[i]->addr = (uint64_t) buf.paddr;
284 rx_descs[i]->status = 0;
285 }
286
287 write(REG_RXDESCLO, (uint32_t) ((uint64_t) paddr & 0xFFFFFFFF)); // low
288 write(REG_RXDESCHI, (uint32_t) ((uint64_t) paddr >> 32)); // high
289
291
294
295 rx_cur = 0;
296
298
299 // write(REG_RCTRL, RCTL_EN | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_2048
300 // | RCTL_UPE | RCTL_MPE);
301
302 // Tuning untuk ping -f:
303 // RDTR: delay timer — tunggu N usec setelah paket pertama sebelum interrupt
304 // RADV: absolute timer — paksa interrupt setelah N usec meski paket masih datang
305
306 write(REG_RDTR, 0); // Matikan delay timer — langsung interrupt
307 write(REG_RADV, 0); // Max tunggu 256 usec sebelum paksa flush
308 // write(REG_RADV, 256); // Max tunggu 256 usec sebelum paksa flush
309
310 // RXDCTL: tuning threshold descriptor
311 // bit[0:7] = PTHRESH: pre-fetch threshold
312 // bit[8:15] = HTHRESH: host threshold
313 // bit[16:23]= WTHRESH: writeback threshold
314 // write(REG_RXDCTL, (1 << 25) | (8 << 16) | (4 << 8) | 4);
315 // granularity WTHRESH HTHRESH PTHRESH
316
317 write(REG_RXDCTL, (1 << 25));
318 log(mod, "Receiver initialized");
319}
320
322 struct e1000_tx_desc* descs;
323
324 uintptr_t paddr = 0;
325 uintptr_t ptr = (uintptr_t) (IOUtils::DMAAlloc(
326 sizeof(struct e1000_tx_desc) * E1000_NUM_TX_DESC + 16, &paddr));
327 log("E1000", "tx_desc addr 0x%x (0x%x)", paddr, ptr);
328
329 descs = (struct e1000_tx_desc*) ptr;
330 serial2_printf("descs at 0x%x\n", descs);
331 for (int i = 0; i < E1000_NUM_TX_DESC; i++) {
332 tx_descs[i] = (struct e1000_tx_desc*) &descs[i];
333 tx_descs[i]->addr = 0;
334 tx_descs[i]->cmd = 0;
335 tx_descs[i]->status = TSTA_DD;
336 }
337
338 write(REG_TXDESCHI, (uint32_t) ((uint64_t) paddr >> 32));
339 write(REG_TXDESCLO, (uint32_t) ((uint64_t) paddr & 0xFFFFFFFF));
340
341 // now setup total length of descriptors
343
344 // setup numbers
347 tx_cur = 0;
349 | (64 << TCTL_COLD_SHIFT) | TCTL_RTLC);
350
351 write(REG_TCTRL, 0b0110000000000111111000011111010);
352 write(REG_TIPG, 0x0060200A);
353
354 __atomic_store_n(&setup_tx_done, 1, __ATOMIC_RELEASE);
355 log(mod, "Transmitter initialized");
356}
357
358int E1000Module::sendPacket(const struct data_template data[], size_t count) {
359 int setup_done = __atomic_load_n(&setup_tx_done, __ATOMIC_ACQUIRE);
360 if (setup_done == 0) {
361 serial2_printf("wait tx setup done..\n");
362 while (!__atomic_load_n(&setup_tx_done, __ATOMIC_ACQUIRE)) {
363 asm volatile("pause");
364 }
365 }
366
367 struct data_template latest_item = data[0];
368
369 uint8_t last_cur = tx_cur;
370 for (size_t i = 0; i < count; i++) {
371 latest_item = data[i];
372 tx_descs[tx_cur]->addr = (uint64_t) latest_item.buffer;
373 tx_descs[tx_cur]->length = latest_item.len;
374 tx_descs[tx_cur]->cmd = CMD_IFCS | CMD_RS;
375 if (i == count - 1 && !latest_item.wait_next_data) {
376 tx_descs[tx_cur]->cmd |= CMD_EOP;
377 }
378
379 tx_descs[tx_cur]->status = 0;
380 last_cur = tx_cur;
381
383 // TODO: handle kalau tx_cur hampir mendekati head jadi ada resiko override head
384 }
385
386 bool success = 0;
387 if (!latest_item.wait_next_data) {
388 __asm__ volatile("mfence" ::: "memory");
390
391 success = (tx_descs[last_cur]->status & 0xff) ? 1 : 1;
392 }
393 return success;
394}
395
397 uint32_t val = read(REG_CTRL);
398
399 val |= (1 << 6); // SLU (Set Link Up)
400 val |= (1 << 6); // SLU
401 val |= (1 << 5); // ASDE (auto speed detect enable)
402 val |= (1 << 3); // FD (full duplex)
403
404 write(REG_CTRL, val);
405}
406
407#define ICR_TXDW (1 << 0) // Transmit Descriptor Written Back
408#define ICR_TXQE (1 << 1) // Transmit Queue Empty
409#define ICR_LSC (1 << 2) // Link Status Change
410#define ICR_RXSEQ (1 << 3) // Receive Sequence Error
411#define ICR_RXDMT0 (1 << 4) // RX Descriptor Minimum Threshold
412#define ICR_RXO (1 << 6) // Receiver Overrun
413#define ICR_RXT0 (1 << 7) // RX Timer Interrupt
414#define ICR_MDAC (1 << 9) // MDIO Access Complete
415#define ICR_RXCFG (1 << 10) // RX /C/ ordered sets detected
416#define ICR_GPI_EN0 (1 << 11) // General Purpose Interrupt 0
417#define ICR_GPI_EN1 (1 << 12) // General Purpose Interrupt 1
418#define ICR_GPI_EN2 (1 << 13) // General Purpose Interrupt 2
419#define ICR_GPI_EN3 (1 << 14) // General Purpose Interrupt 3
420
422 // log("E100 IRQ", "fire");
424 if (!module)
425 return;
426
427 // untuk msi-x
428 module->receiveHandle();
429
430 // check icr
431 uint32_t status = module->read(REG_ICR);
432
433 // if (!(status & (IMS_RXT0 | IMS_RXDMT0 | IMS_RXO | IMS_LSC)))
434 // return;
435
436 if (status & 0x04) {
437 log("E100 IRQ", "link up");
438 module->linkup();
439 }
440
441 if (status & (1 << 20)) {
442 module->receiveHandle();
443 }
444 // Catatan penting MSI-X: Karena fitur EIAC (Auto-Clear) aktif,
445 // terkadang hardware membersihkan ICR lebih cepat dari CPU membacanya.
446 // Jika kondisinya begitu, kamu bisa memaksa panggil receiveHandle()
447 // jika modulmu mencatat current_irq_mode == INT_MSIX.
448
449 if (status & 0x80) {
450 // RXT0: paket masuk normal
451 module->receiveHandle();
452 }
453 if (status & 0x40) {
454 // RXO: RX overrun — ring penuh, paksa drain
455 log("E100 IRQ", "RX overrun!");
456 module->receiveHandle();
457 }
458}
459
461 int processed = 0;
462 uint16_t last_tail = (uint16_t) -1;
463
464 while (rx_descs[rx_cur]->status & 0x1) {
465 struct rx_buffer new_buf;
466
467 if (!pool_pop(&new_buf)) {
468 rx_descs[rx_cur]->addr =
469 rx_comp[rx_cur].paddr; // re-post lama
470 rx_descs[rx_cur]->status = 0;
471 last_tail = rx_cur;
473
474 if (++processed % 16 == 0)
475 write(REG_RXDESCTAIL, last_tail);
476 continue; // drop
477 }
478
479 uint8_t* old_vaddr = (uint8_t*) rx_comp[rx_cur].addr;
480 uint16_t pkt_size = rx_descs[rx_cur]->length;
481
482 rx_comp[rx_cur].paddr = new_buf.paddr;
483 rx_comp[rx_cur].addr = (uint64_t) new_buf.vaddr;
484 rx_descs[rx_cur]->addr = new_buf.paddr;
485 rx_descs[rx_cur]->status = 0;
486 last_tail = rx_cur;
488
489 ioforge_nic_rx(nic, old_vaddr, pkt_size, (last_tail));
490
491 if (++processed % 16 == 0)
492 write(REG_RXDESCTAIL, last_tail);
493 }
494
495 if (last_tail != (uint16_t) -1 && processed % 16 != 0)
496 write(REG_RXDESCTAIL, last_tail);
497}
498
500 uint32_t h = __atomic_load_n(&rx_buffer_pool.head, __ATOMIC_ACQUIRE);
501 uint32_t t = __atomic_load_n(&rx_buffer_pool.tail, __ATOMIC_RELAXED);
502
503 if (t - h >= BUFFER_POOL_SIZE) {
504 serial2_printf("[E1000] pool_push: FULL, drop vaddr=%p\n",
505 vaddr);
506 return;
507 }
508
512
513 __atomic_store_n(&rx_buffer_pool.tail, t + 1, __ATOMIC_RELEASE);
514}
515
516void E1000Module::storeBufferToPool(int /*rx_id*/, void* vaddr) {
517 uint64_t paddr = 0;
518 bool found = false;
519 for (uint32_t i = 0; i < g_buf_lookup_count; i++) {
520 if (g_buf_lookup[i].vaddr == (uint8_t*) vaddr) {
521 paddr = g_buf_lookup[i].paddr;
522 found = true;
523 break;
524 }
525 }
526
527 if (!found) {
529 "[E1000] storeBufferToPool: vaddr %p tidak dikenal!\n",
530 vaddr);
531 return;
532 }
533
534 pool_push((uint8_t*) vaddr, paddr);
535}
536
538 // wait until ready
539 while (!mac_ready)
540 asm volatile("pause");
541
542 for (int i = 0; i < 6; i++)
543 mac[i] = mac_addr[i];
544
545 return 1;
546}
struct SDT h
Definition acpi.h:0
int count
Definition cache.h:2
boolean_t detectEeprom()
Definition e1000.cpp:129
ioforge_pci_device * device
Definition e1000.hpp:68
uint32_t rx_cur
Definition e1000.hpp:73
static E1000Module * getInstance()
Definition init.cpp:13
void receiveHandle()
Definition e1000.cpp:460
void write(uint16_t p_address, uint32_t p_value)
Definition e1000.cpp:119
void enableInterrupt()
Definition e1000.cpp:206
boolean_t syncMacAddress()
Definition e1000.cpp:162
int getMacAddress(uint8_t mac[6])
Definition e1000.cpp:537
void disableInterrupt()
Definition e1000.cpp:218
bool mac_ready
Definition e1000.hpp:66
uint32_t readEeprom(uint32_t addr)
Definition e1000.cpp:144
void linkup()
Definition e1000.cpp:396
void storeBufferToPool(int rx_id, void *vaddr)
Definition e1000.cpp:516
void initTransmitterX()
Definition e1000.cpp:321
static void fireHandler()
Definition e1000.cpp:421
uint32_t mac_addr[6]
Definition e1000.hpp:67
uint32_t tx_cur
Definition e1000.hpp:74
boolean_t eerprom_exists
Definition e1000.hpp:69
int sendPacket(const struct data_template data[], size_t count)
Definition e1000.cpp:358
void initReceiverX()
Definition e1000.cpp:238
uint32_t read(uint16_t p_address)
Definition e1000.cpp:125
ioforge_nic_service * nic
Definition e1000.hpp:79
E1000Module()
Definition init.cpp:9
const char * mod
Definition ioforge.hpp:65
#define REG_RDTR
Definition e1000.cpp:37
#define CMD_RS
Definition e1000.cpp:81
#define REG_RADV
Definition e1000.cpp:39
#define REG_RXDESCTAIL
Definition e1000.cpp:19
static rx_buf_lookup_entry g_buf_lookup[1280]
Definition e1000.cpp:116
#define REG_RXDESCLO
Definition e1000.cpp:15
#define REG_TXDESCLO
Definition e1000.cpp:31
#define RCTL_BAM
Definition e1000.cpp:59
#define REG_EEPROM
Definition e1000.cpp:11
#define REG_CTRL
Definition e1000.cpp:9
static uint32_t g_buf_lookup_count
Definition e1000.cpp:117
#define REG_TXDESCHI
Definition e1000.cpp:32
static struct e1000_tx_desc * tx_descs[64]
Definition e1000.cpp:105
#define REG_RXDCTL
Definition e1000.cpp:38
#define IMS_OTHER
Definition e1000.cpp:28
static void pool_push(uint8_t *vaddr, uint64_t paddr)
Definition e1000.cpp:499
#define REG_TXDESCLEN
Definition e1000.cpp:33
#define REG_TXDESCHEAD
Definition e1000.cpp:34
#define CMD_EOP
Definition e1000.cpp:78
#define REG_RCTRL
Definition e1000.cpp:14
#define TCTL_PSP
Definition e1000.cpp:89
#define REG_ICR
Definition e1000.cpp:101
#define RCTL_EN
Definition e1000.cpp:45
#define IMS_TXQ0
Definition e1000.cpp:27
static struct e1000_rx_desc * rx_descs[256]
Definition e1000.cpp:103
#define RCTL_BSIZE_2048
Definition e1000.cpp:71
#define REG_IMASK
Definition e1000.cpp:13
#define TSTA_DD
Definition e1000.cpp:95
#define REG_RXDESCLEN
Definition e1000.cpp:17
#define RCTL_SECRC
Definition e1000.cpp:65
#define TCTL_RTLC
Definition e1000.cpp:93
static bool pool_pop(struct rx_buffer *out)
Definition e1000.cpp:223
#define REG_RXDESCHI
Definition e1000.cpp:16
#define CMD_IFCS
Definition e1000.cpp:79
#define REG_TXDESCTAIL
Definition e1000.cpp:35
#define TCTL_EN
Definition e1000.cpp:88
#define REG_TIPG
Definition e1000.cpp:42
#define REG_RXDESCHEAD
Definition e1000.cpp:18
#define TCTL_COLD_SHIFT
Definition e1000.cpp:91
#define TCTL_CT_SHIFT
Definition e1000.cpp:90
#define IMS_RXQ0
Definition e1000.cpp:26
#define REG_TCTRL
Definition e1000.cpp:30
static const char hexmap[]
Definition e1000.cpp:160
static volatile int setup_tx_done
Definition e1000.cpp:107
static struct e1000_rx_comp rx_comp[256]
Definition e1000.cpp:104
#define E1000_NUM_TX_DESC
Definition e1000.hpp:10
volatile uint64_t addr
Definition e1000.hpp:0
#define E1000_NUM_RX_DESC
Definition e1000.hpp:8
#define E1000_NUM_RX_MASK
Definition e1000.hpp:9
volatile uint8_t status
Definition e1000.hpp:3
struct fs_data data
Definition filesystem.h:1
void serial2_printf(const char *fmt,...)
#define log(mod, fmt,...)
Definition ioforge.hpp:12
void ioforge_nic_rx(struct ioforge_nic_service *nic, uint8_t *buffer, size_t len, int rx_id)
#define BUFFER_POOL_MASK
Definition ioforge_nic.h:12
#define BUFFER_POOL_SIZE
Definition ioforge_nic.h:11
uint8_t wait_next_data
Definition ioforge_nic.h:18
const void * buffer
Definition ioforge_nic.h:16
Definition e1000.cpp:112
uint8_t * vaddr
Definition e1000.cpp:113
uint64_t paddr
Definition e1000.cpp:114
uint32_t tail
Definition ioforge_nic.h:55
struct rx_buffer buffers[1280]
Definition ioforge_nic.h:51
uint32_t head
Definition ioforge_nic.h:53
uintptr_t paddr
Definition ioforge_nic.h:47
void * vaddr
Definition ioforge_nic.h:46
unsigned short uint16_t
Definition type.h:13
unsigned int uint32_t
Definition type.h:19
uint8_t boolean_t
Definition type.h:89
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
struct xhci_slot_ctx slot
Definition xhci.hpp:0
uint64_t ptr
Definition xhci.hpp:0