Not logged inTalkContributionsCreate accountLog in

Interrupts & Timers

From nexOS Wiki
IDT, 8259 PIC remap, PIT 100 Hz, PS/2 keyboard & mouse

Contents

[hide]

Interrupt sources

nexOS now has three live sources (the old “timer masked” note is obsolete): PIT timer on IRQ0, PS/2 keyboard on IRQ1, PS/2 mouse on IRQ12. Each handler is an assembly stub that saves registers, calls C, then iretd.

VectorSourceHandlerSelectorFlags
32 (0x20)PIT timer, IRQ0isr32 → timer_handler()0x080x8E
33 (0x21)PS/2 keyboard, IRQ1isr33 → keyboard_handler()0x080x8E
44 (0x2C)PS/2 mouse, IRQ12isr44 → mouse_handler()0x080x8E
0–255others(zeroed)00

IDT structures

typedef struct { u16 lo; u16 sel; u8 zero; u8 fl; u16 hi; } __attribute__((packed)) idt_e;
typedef struct { u16 lim; u32 base; } __attribute__((packed)) idt_p;
static idt_e idt[256];  static idt_p idt_r;  // 2048 bytes, loaded with lidt

ISR stubs (kernel_entry.asm)

_isr44:  pusha; call _mouse_handler;    popa; iretd   ; mouse INT 44
_isr33:  pusha; call _keyboard_handler; popa; iretd   ; keyboard INT 33
_isr32:  pusha; call _timer_handler;    popa; iretd   ; timer INT 32

8259 PIC remap

remap_pic():
  outb(0x20,0x11); outb(0xA0,0x11);  // ICW1
  outb(0x21,0x20); outb(0xA1,0x28);  // ICW2: master 0x20, slave 0x28
  outb(0x21,0x04); outb(0xA1,0x02);  // ICW3: slave on IRQ2
  outb(0x21,0x01); outb(0xA1,0x01);  // ICW4: 8086 mode
  outb(0x21,0xF8); outb(0xA1,0xEF);  // masks
PICPortsBaseMaskEnabled
Master0x20/0x210x200xF8IRQ0 (PIT) + IRQ1 (kbd) + IRQ2 (cascade)
Slave0xA0/0xA10x280xEFIRQ12 (mouse)

Master 0xF8 = 11111000b: bits 0–2 clear = unmasked. The old mask 0xF9 kept the timer masked; the current tree unmasks IRQ0 for the scheduler tick.

PIT 100 Hz tick

pit_init():
  u16 div = 11932;              // 1193182 / 11932 ~= 100 Hz
  outb(0x43, 0x36);             // ch0, lo/hi, mode 3 square wave
  outb(0x40, div & 0xFF);
  outb(0x40, (div >> 8) & 0xFF);

timer_handler(): pit_ticks++; outb(0x20, 0x20);  // EOI

// main loop polling (every 10 ticks = 10 Hz):
if (pit_ticks - last_poll >= 10) { last_poll = pit_ticks; if (net_poll()) redraw = 1; }

The tick does not preempt; it increments a counter the main loop polls for NIC work and redraw timing.

Mouse press queue

A single mouse_updated flag collapsed press+release inside one render window (“nothing happened”). The current handler records press edges into a 4-deep ring; the main loop drains one per iteration as a synthetic press, so fast 0.05 s clicks survive long renders. Movement uses 2× gain and clamps to true screen edges.

ACPI shutdown

shutdown_system(): cli; outw(0x604, 0x2000); for(;;) hlt;  // QEMU/Bochs power port