1#define IO_PIC 0x20 2#define IRQ_OFFSET 32 3#define IO_PIT 0x40 4#define TIMER_FREQ 1193182 5#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 6 7#define TEST_COUNT 0x0200 8 9 .code16gcc 10 .text 11 .globl _start 12 .type _start, @function 13_start: 14/* 15 * fill up noop handlers 16 */ 17 xorw %ax, %ax 18 xorw %di, %di 19 movw %ax, %es 20 movw $256, %cx 21fill_noop_idt: 22 movw $noop_handler, %es:(%di) 23 movw %cs, %es:2(%di) 24 add $4, %di 25 loop fill_noop_idt 26 27set_idt: 28 movw $timer_isr, %es:(IRQ_OFFSET*4) 29 movw %cs, %es:(IRQ_OFFSET*4+2) 30 31set_pic: 32 # ICW1 33 mov $0x11, %al 34 mov $(IO_PIC), %dx 35 out %al,%dx 36 # ICW2 37 mov $(IRQ_OFFSET), %al 38 mov $(IO_PIC+1), %dx 39 out %al, %dx 40 # ICW3 41 mov $0x00, %al 42 mov $(IO_PIC+1), %dx 43 out %al, %dx 44 # ICW4 45 mov $0x3, %al 46 mov $(IO_PIC+1), %dx 47 out %al, %dx 48 49set_pit: 50 # set 8254 mode 51 mov $(IO_PIT+3), %dx 52 mov $0x34, %al 53 outb %al, %dx 54 # set 8254 freq 1KHz 55 mov $(IO_PIT), %dx 56 movb $(TIMER_DIV(1000) % 256), %al 57 outb %al, %dx 58 movb $(TIMER_DIV(1000) / 256), %al 59 outb %al, %dx 60 61enable_irq0: 62 mov $0xfe, %al 63 mov $(IO_PIC+1), %dx 64 out %al, %dx 65 sti 66loop: 67 1: 68 jmp 1b 69 70test_ok: 71 mov $0x3f8,%dx 72 cs lea msg2, %si 73 mov $(msg2_end-msg2), %cx 74 cs rep/outsb 75 76 /* Reboot by using the i8042 reboot line */ 77 mov $0xfe, %al 78 outb %al, $0x64 79 80timer_isr: 81 cli 82 pushaw 83 pushfw 84 mov $0x3f8,%dx 85 mov $0x2e, %al # . 86 out %al,%dx 87 decw count 88 jz test_ok 89 popfw 90 popaw 91 iretw 92 93noop_handler: 94 iretw 95 96count: 97 .word TEST_COUNT 98 99msg2: 100 .asciz "\nTest OK\n" 101msg2_end: 102