Skip to content

Drivers

kazah-png edited this page Jul 26, 2026 · 7 revisions

Drivers

Every device driver is compiled into the kernel — there is no module loading. All of them live in kernel/.

See also: Architecture, Networking Stack, GUI Subsystem, Filesystem, SMP

Interrupt controllers

APIC (apic.c)

Local APIC at 0xFEE00000, I/O APIC at 0xFEC00000 with 24 redirection entries, and ISA IRQ override handling.

The PIT arrives on I/O APIC pin 2, not pin 0 — QEMU's ACPI interrupt-source override remaps ISA IRQ 0. Unmasking pin 0 is a no-op, which is why the timer appeared dead for several releases.

The legacy PIC is fully masked once the APIC is active.

Input

Keyboard (keyboard.c)

PS/2 on IRQ 1, feeding a circular buffer. US and Spanish layouts with AltGr; Set-2 scancodes.

  • Ctrl-A…Ctrl-Z map to control bytes 0x010x1A for editor bindings
  • Ctrl-C raises SIGINT and Ctrl-Z raises SIGTSTP against the terminal foreground process
  • Two stdin disciplines: TTY_CANON (echoed, backspace-edited lines) and TTY_RAW (byte-at-a-time, arrows as ANSI escapes) — see ttymode in Syscalls
  • A separate raw key-event ring delivers press and release with Set-1 scancodes, for fullscreen games (getkeyevent)
  • The input path is spinlock-protected for SMP safety

The E0-prefix check once ran after the press-bit mask, so extended keys — every arrow, Home, End, PgUp, PgDn — never worked anywhere in the system. Worth remembering when a key seems inert.

layout <us|es> switches keymap at runtime.

Mouse (mouse.c)

PS/2 on IRQ 12. Three-byte packets, relative movement, roughly 4 counts/mm, plus wheel events used by the terminal scrollback.

Timers

PIT (timer.c)

Channel 0 at 1000 Hz, delivered via I/O APIC pin 2 to vector 32. It drives tick_count, the scheduler quantum, and the sleep wait queue.

Local APIC timer (smp.c)

Each application processor runs its own periodic LAPIC timer on a dedicated vector — a real context-switching ISR feeding that core's scheduler. The reload value is deliberately uncalibrated: calibration needs a reference clock the APs do not have, since the PIT belongs to the BSP. Under QEMU, divide-by-16 with 62500 counts gives roughly 500 Hz per AP; real hardware will differ.

RTC (rtc.c)

CMOS ports 0x70/0x71, BCD decoded. Backs the date command, SYS_TIME, gettimeofday, and X.509 certificate validity checks.

Storage

ATA (ata.c)

PIO mode on the primary channel (0x1F0), IRQ 14, 28-bit LBA (up to 128 GB), polled I/O. This is what the EXT2 driver sits on — see Filesystem.

Display

VBE (vbe.c)

Bochs VBE extensions with a custom CRTC, up to 1024×768×32, linear framebuffer at 0xE0000000. Runtime mode changes via setres / mode.

Audio

Sound Blaster 16 (sb16.c)

I/O port 0x220, IRQ 5, DMA channel 1. 8-bit PCM in auto-init mode with mixer control. sb16play [freq] [ms] from the shell; the Sound Test app exposes sine, square and sweep.

Under QEMU: -audiodev dsound,id=audio0 -device sb16,audiodev=audio0 (which run.ps1 -Sound adds).

PC speaker (speaker.c)

PIT channel 2 square wave. beep() and play_melody(), exposed as the beep and play commands.

Network

RTL8139 (rtl8139.c)

PCI NIC with I/O and MMIO BARs, 4 TX descriptors, a circular RX ring, 10/100 Mbps, link detection. Full detail in Networking Stack.

Interrupt map

IRQ Vector Device
0 (I/O APIC pin 2) 32 PIT timer
1 33 PS/2 keyboard
5 37 Sound Blaster 16
12 44 PS/2 mouse
14 46 ATA primary (polled in practice)
0x41 TLB shootdown IPI (SMP)
per-CPU AP LAPIC timer, AP spurious

See also

External resources

Clone this wiki locally