Skip to content

Implement network device driver (e1000/virtio-net) #67

@pbalduino

Description

@pbalduino

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

Nice to Have (Not Blocking)

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

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

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 Implement dynamic IRQ handler registration/unregistration API #279 - Dynamic IRQ handler registration
  7. Add interrupt handling once Implement dynamic IRQ handler registration/unregistration API #279 is complete
  8. Test with QEMU e1000 emulation

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions