E1000 networking overhaul — replace polling with proper interrupt-driven I/O:
1. RX interrupt-driven:
- IRQ handler (e1000_irq_handler) now signals e1000_rx_sem on
RXT0/RXDMT0/RXO events instead of being a no-op.
- Dedicated kernel thread (e1000_rx_thread) blocks on the
semaphore, drains all available packets via e1000_recv(),
and delivers them to lwIP via tcpip_input().
- Latency: immediate wake on packet arrival (was 20ms polling).
2. TX non-blocking:
- e1000_send() checks the DD bit immediately and returns -1 if
the descriptor is not ready (was: busy-wait up to 100K iters).
- lwIP's linkoutput callback returns ERR_IF on ring-full.
3. Idle loop cleanup:
- net_poll() removed from kernel_main's idle loop.
- net_poll() is now a no-op (kept for backward compat).
- PID 0 idle loop is pure hlt — no wasted CPU cycles.
4. root= kernel command line parameter:
- Syntax: root=/dev/hdX (e.g. root=/dev/hda)
- Auto-detects filesystem (tries diskfs, fat, ext2 in order)
- Mounts at /disk on success
- Processed after ATA init, before /etc/fstab parsing
- Example GRUB entry:
multiboot2 /boot/adros-x86.bin root=/dev/hda quiet