feat: add ethernet & TCP/IP stack
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* E1000.hpp
|
||||
* Intel 82540EM (E1000) Ethernet driver
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Drivers::Net::E1000 {
|
||||
|
||||
// E1000 register offsets (memory-mapped via BAR0)
|
||||
constexpr uint32_t REG_CTRL = 0x0000; // Device Control
|
||||
constexpr uint32_t REG_STATUS = 0x0008; // Device Status
|
||||
constexpr uint32_t REG_EERD = 0x0014; // EEPROM Read
|
||||
constexpr uint32_t REG_ICR = 0x00C0; // Interrupt Cause Read
|
||||
constexpr uint32_t REG_IMS = 0x00D0; // Interrupt Mask Set
|
||||
constexpr uint32_t REG_IMC = 0x00D8; // Interrupt Mask Clear
|
||||
constexpr uint32_t REG_RCTL = 0x0100; // Receive Control
|
||||
constexpr uint32_t REG_TCTL = 0x0400; // Transmit Control
|
||||
constexpr uint32_t REG_TIPG = 0x0410; // Transmit IPG
|
||||
constexpr uint32_t REG_RDBAL = 0x2800; // RX Descriptor Base Low
|
||||
constexpr uint32_t REG_RDBAH = 0x2804; // RX Descriptor Base High
|
||||
constexpr uint32_t REG_RDLEN = 0x2808; // RX Descriptor Length
|
||||
constexpr uint32_t REG_RDH = 0x2810; // RX Descriptor Head
|
||||
constexpr uint32_t REG_RDT = 0x2818; // RX Descriptor Tail
|
||||
constexpr uint32_t REG_TDBAL = 0x3800; // TX Descriptor Base Low
|
||||
constexpr uint32_t REG_TDBAH = 0x3804; // TX Descriptor Base High
|
||||
constexpr uint32_t REG_TDLEN = 0x3808; // TX Descriptor Length
|
||||
constexpr uint32_t REG_TDH = 0x3810; // TX Descriptor Head
|
||||
constexpr uint32_t REG_TDT = 0x3818; // TX Descriptor Tail
|
||||
constexpr uint32_t REG_MTA = 0x5200; // Multicast Table Array (128 entries)
|
||||
constexpr uint32_t REG_RAL = 0x5400; // Receive Address Low
|
||||
constexpr uint32_t REG_RAH = 0x5404; // Receive Address High
|
||||
|
||||
// CTRL register bits
|
||||
constexpr uint32_t CTRL_SLU = (1 << 6); // Set Link Up
|
||||
constexpr uint32_t CTRL_RST = (1 << 26); // Device Reset
|
||||
|
||||
// RCTL register bits
|
||||
constexpr uint32_t RCTL_EN = (1 << 1); // Receiver Enable
|
||||
constexpr uint32_t RCTL_SBP = (1 << 2); // Store Bad Packets
|
||||
constexpr uint32_t RCTL_UPE = (1 << 3); // Unicast Promiscuous
|
||||
constexpr uint32_t RCTL_MPE = (1 << 4); // Multicast Promiscuous
|
||||
constexpr uint32_t RCTL_BAM = (1 << 15); // Broadcast Accept Mode
|
||||
constexpr uint32_t RCTL_BSIZE_4096 = (3 << 16); // Buffer Size 4096 (with BSEX)
|
||||
constexpr uint32_t RCTL_BSEX = (1 << 25); // Buffer Size Extension
|
||||
constexpr uint32_t RCTL_SECRC = (1 << 26); // Strip Ethernet CRC
|
||||
|
||||
// TCTL register bits
|
||||
constexpr uint32_t TCTL_EN = (1 << 1); // Transmit Enable
|
||||
constexpr uint32_t TCTL_PSP = (1 << 3); // Pad Short Packets
|
||||
constexpr uint32_t TCTL_CT_SHIFT = 4; // Collision Threshold shift
|
||||
constexpr uint32_t TCTL_COLD_SHIFT = 12; // Collision Distance shift
|
||||
|
||||
// ICR (interrupt cause) bits
|
||||
constexpr uint32_t ICR_TXDW = (1 << 0); // TX Descriptor Written Back
|
||||
constexpr uint32_t ICR_TXQE = (1 << 1); // TX Queue Empty
|
||||
constexpr uint32_t ICR_LSC = (1 << 2); // Link Status Change
|
||||
constexpr uint32_t ICR_RXDMT0 = (1 << 4); // RX Descriptor Minimum Threshold
|
||||
constexpr uint32_t ICR_RXO = (1 << 6); // Receiver Overrun
|
||||
constexpr uint32_t ICR_RXT0 = (1 << 7); // Receiver Timer Interrupt
|
||||
|
||||
// TX descriptor command bits
|
||||
constexpr uint8_t TXCMD_EOP = (1 << 0); // End Of Packet
|
||||
constexpr uint8_t TXCMD_IFCS = (1 << 1); // Insert FCS/CRC
|
||||
constexpr uint8_t TXCMD_RS = (1 << 3); // Report Status
|
||||
|
||||
// TX descriptor status bits
|
||||
constexpr uint8_t TXSTA_DD = (1 << 0); // Descriptor Done
|
||||
|
||||
// RX descriptor status bits
|
||||
constexpr uint8_t RXSTA_DD = (1 << 0); // Descriptor Done
|
||||
constexpr uint8_t RXSTA_EOP = (1 << 1); // End Of Packet
|
||||
|
||||
// Descriptor ring sizes
|
||||
constexpr uint32_t RX_DESC_COUNT = 32;
|
||||
constexpr uint32_t TX_DESC_COUNT = 32;
|
||||
constexpr uint32_t PACKET_BUFFER_SIZE = 8192;
|
||||
|
||||
// RX descriptor (legacy format, 16 bytes)
|
||||
struct RxDescriptor {
|
||||
uint64_t BufferAddress;
|
||||
uint16_t Length;
|
||||
uint16_t Checksum;
|
||||
uint8_t Status;
|
||||
uint8_t Errors;
|
||||
uint16_t Special;
|
||||
} __attribute__((packed));
|
||||
|
||||
// TX descriptor (legacy format, 16 bytes)
|
||||
struct TxDescriptor {
|
||||
uint64_t BufferAddress;
|
||||
uint16_t Length;
|
||||
uint8_t ChecksumOffset;
|
||||
uint8_t Command;
|
||||
uint8_t Status;
|
||||
uint8_t ChecksumStart;
|
||||
uint16_t Special;
|
||||
} __attribute__((packed));
|
||||
|
||||
// Initialize the E1000 driver (scans PCI for the device)
|
||||
void Initialize();
|
||||
|
||||
// Send a raw Ethernet frame
|
||||
bool SendPacket(const uint8_t* data, uint16_t length);
|
||||
|
||||
// Get the MAC address (6 bytes)
|
||||
const uint8_t* GetMacAddress();
|
||||
|
||||
// Check if the device was found and initialized
|
||||
bool IsInitialized();
|
||||
|
||||
// RX callback type: called with (packet data, length)
|
||||
using RxCallback = void(*)(const uint8_t* data, uint16_t length);
|
||||
|
||||
// Register a callback for received packets
|
||||
void SetRxCallback(RxCallback callback);
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user