| #define IO_PIC 0x20 |
| #define IRQ_OFFSET 32 |
| #define IO_PIT 0x40 |
| #define TIMER_FREQ 1193182 |
| #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) |
| |
| #define TEST_COUNT 0x0200 |
| |
| .code16gcc |
| .text |
| .globl _start |
| .type _start, @function |
| _start: |
| /* |
| * fill up noop handlers |
| */ |
| xorw %ax, %ax |
| xorw %di, %di |
| movw %ax, %es |
| movw $256, %cx |
| fill_noop_idt: |
| movw $noop_handler, %es:(%di) |
| movw %cs, %es:2(%di) |
| add $4, %di |
| loop fill_noop_idt |
| |
| set_idt: |
| movw $timer_isr, %es:(IRQ_OFFSET*4) |
| movw %cs, %es:(IRQ_OFFSET*4+2) |
| |
| set_pic: |
| # ICW1 |
| mov $0x11, %al |
| mov $(IO_PIC), %dx |
| out %al,%dx |
| # ICW2 |
| mov $(IRQ_OFFSET), %al |
| mov $(IO_PIC+1), %dx |
| out %al, %dx |
| # ICW3 |
| mov $0x00, %al |
| mov $(IO_PIC+1), %dx |
| out %al, %dx |
| # ICW4 |
| mov $0x3, %al |
| mov $(IO_PIC+1), %dx |
| out %al, %dx |
| |
| set_pit: |
| # set 8254 mode |
| mov $(IO_PIT+3), %dx |
| mov $0x34, %al |
| outb %al, %dx |
| # set 8254 freq 1KHz |
| mov $(IO_PIT), %dx |
| movb $(TIMER_DIV(1000) % 256), %al |
| outb %al, %dx |
| movb $(TIMER_DIV(1000) / 256), %al |
| outb %al, %dx |
| |
| enable_irq0: |
| mov $0xfe, %al |
| mov $(IO_PIC+1), %dx |
| out %al, %dx |
| sti |
| loop: |
| 1: |
| jmp 1b |
| |
| test_ok: |
| mov $0x3f8,%dx |
| cs lea msg2, %si |
| mov $(msg2_end-msg2), %cx |
| cs rep/outsb |
| |
| /* Reboot by using the i8042 reboot line */ |
| mov $0xfe, %al |
| outb %al, $0x64 |
| |
| timer_isr: |
| cli |
| pushaw |
| pushfw |
| mov $0x3f8,%dx |
| mov $0x2e, %al # . |
| out %al,%dx |
| decw count |
| jz test_ok |
| popfw |
| popaw |
| iretw |
| |
| noop_handler: |
| iretw |
| |
| count: |
| .word TEST_COUNT |
| |
| msg2: |
| .asciz "\nTest OK\n" |
| msg2_end: |