menios icon indicating copy to clipboard operation
menios copied to clipboard

Implement network device driver (e1000/virtio-net)

Open pbalduino opened this issue 4 months ago • 2 comments

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_write32 wrappers 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

  1. Create e1000 driver skeleton in src/kernel/driver/net/e1000.c
  2. Add register map definitions and hardware structures
  3. Implement device probe and initialization
  4. Wire into PCI enumeration system
  5. Implement TX/RX descriptor rings
  6. Wait for #279 - Dynamic IRQ handler registration
  7. Add interrupt handling once #279 is complete
  8. Test with QEMU e1000 emulation

pbalduino avatar Sep 26 '25 19:09 pbalduino