menios
menios copied to clipboard
Implement network device driver (e1000/virtio-net)
Goal
Write an interrupt-driven network device driver for QEMU-emulated NICs to enable network packet transmission and reception.
Context
This is the foundation layer for TCP/IP networking support. We need reliable hardware-level packet I/O before building protocol stacks.
Definition of Done
- PCI discovery: Detect and initialize network controllers via PCI enumeration
- MMIO register setup: Configure device registers for operation
- Descriptor rings: Implement TX/RX descriptor ring management
- DMA buffers: Allocate and manage DMA-safe packet buffers
- Transmit queue: Implement packet transmission with queueing
- Receive path: Handle incoming packets and feed them to network stack
- Interrupt handling: Process device interrupts for TX completion and RX packets
Device Choice: Intel e1000/e1000e
Chosen for:
- Well-documented hardware interface
- Good QEMU emulation support
- Widely used and tested
- Reasonable complexity for educational implementation
Implementation Details
- PCI device detection and BAR mapping
- Device reset and initialization sequence
- TX/RX descriptor ring setup and management
- Packet buffer allocation and DMA mapping
- Interrupt handler for device events
- Basic error handling and device recovery
- Statistics collection and monitoring
Hardware Interface
- PCI configuration space access
- MMIO register programming
- Descriptor ring structure management
- DMA coherency and cache management
- Interrupt line configuration and handling
Files to Create
- drivers/net/e1000.h - Hardware definitions and structures
- drivers/net/e1000.c - Main driver implementation
- drivers/net/netdev.h - Generic network device interface
- drivers/net/netdev.c - Network device management layer
- include/net/netdevice.h - Network device abstractions
API Design
- netdev_register() - Register network device with kernel
- netdev_transmit() - Send packet through device
- netdev_receive() - Handle received packet from device
- netdev_set_mac() - Configure device MAC address
- netdev_get_stats() - Retrieve device statistics
Testing Strategy
- Test device detection and initialization
- Verify packet transmission and reception
- Test interrupt handling and performance
- Validate DMA buffer management
- Test error conditions and recovery
Performance Goals
- Handle standard Ethernet frame sizes (64-1518 bytes)
- Support reasonable throughput for educational OS
- Minimize interrupt overhead through efficient batching
- Proper resource management without memory leaks
Dependencies
Blocked By
-
#279 - Dynamic IRQ handler registration - Required for processing device interrupts for TX completion and RX packets
- Priority: High (critical for interrupt-driven operation)
- Estimated: 8-10 weeks part-time
Nice to Have (Not Blocking)
-
#278 - Kernel work queue system - Could be useful for deferred packet processing and bottom-half handling
- Priority: Medium (can start with direct interrupt handling)
Already Available ✅
- ~~PCI device enumeration infrastructure~~ ✅ Implemented in src/kernel/driver/pciroot/
- ~~PCI configuration space access~~ ✅ Available via pci_config_read/write
- ~~MMCONFIG support~~ ✅ ACPI MCFG integration complete
- ~~PCI constants and register definitions~~ ✅ Centralized in include/kernel/pci.h
- Memory management for DMA buffers ✅ (kernel heap + physical_to_virtual)
Related Issues
- Blocks: Future TCP/IP stack implementation
- Related: #279 (IRQ handlers needed for interrupt-driven I/O)
Current Building Blocks ✅
Progress update: Several key PCI infrastructure pieces have been implemented since this issue was filed:
✅ PCI Constants and Register Offsets
-
include/kernel/pci.h:7 now centralizes PCI register offsets and command bits (
PCI_CONFIG_BARx,PCI_COMMAND_BUS_MASTER, etc.), addressing the "shared constants" gap noted in the original review.
✅ Segment-Aware Config Space Access
-
src/kernel/driver/pciroot/pci.c:18 implements MMCONFIG window tracking plus
pci_config_read/pci_config_write, giving us segment-aware configuration space access (was missing when the issue was filed).
✅ ACPI MCFG Integration
-
src/kernel/driver/pciroot/pciroot.c:20 scans the ACPI MCFG table, registers every MMCONFIG window, and calls
pci_enumerate_devices, providing a reusable enumeration hook instead of AHCI-only probing.
✅ PCI Device Enumeration
- src/kernel/driver/pciroot/pci.c:74 implements device enumeration infrastructure that can be used by network drivers.
Remaining Work
With the PCI infrastructure now in place, the remaining work for e1000 driver implementation:
Device Driver Layer
- e1000 descriptor structures: Create driver skeleton with vendor/device IDs, register offsets (CTRL, STATUS, IMC, IMS, RCTL, TCTL, etc.), and documented reset bit sequences.
-
BAR sizing/mapping helpers: Reusable helpers to query BAR size/type (including 64-bit BAR0 for some parts) before converting to virtual with
physical_to_virtual(). -
Reset sequencing utilities: MMIO-based device reset with
mmio_read32/mmio_write32wrappers and delay/poll loop to clear CTRL.RST per Intel spec.
Integration
- Add
e1000_init()hook in PCI enumeration to probe for network devices. - Implement descriptor ring management (TX/RX).
- Implement DMA buffer allocation and management.
- Implement interrupt handling for device events (blocked by #279).
Next Steps
- Create e1000 driver skeleton in
src/kernel/driver/net/e1000.c - Add register map definitions and hardware structures
- Implement device probe and initialization
- Wire into PCI enumeration system
- Implement TX/RX descriptor rings
- Wait for #279 - Dynamic IRQ handler registration
- Add interrupt handling once #279 is complete
- Test with QEMU e1000 emulation