Skip to content

Completing the IDT (with IRQ)

randcode-generator edited this page Sep 14, 2014 · 4 revisions

To complete the IDT, we need to have handler for all interrupts. Interrupts from 0-31 are exceptions. Interrupts 32-47 are interrupt requests (IRQ) from hardware. For example, IRQ1 (interrupt 33) is triggered when a key is pressed.

  1. Remap the PIC so that the hardware interrupt requests (IRQ) starts at 32.
    Reference (http://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller#Remapping)
    mov al, 0x11
    out 0x20, al
    out 0xA0, al
    mov al, 0x20
    out 0x21, al
    mov al, 0x28
    out 0xA1, al
    mov al, 0x04
    out 0x21, al
    mov al, 0x02
    out 0xA1, al
    mov al, 0x01
    out 0x21, al
    out 0xA1, al
    mov al, 0x0
    out 0x21, al
    out 0xA1, al
  1. Create default exception interrupts. This is for interrupts 0-31
interrupt_default:
iret
  1. Create default interrupt requests for 32-39. Note that we have to send "End of Interrupt" (EOI) to the master PIC.
IRQ_32_39_interrupt_default:
    mov al, 0x20        ; EOI command
    out 0x20, al        ; send to master
iret
  1. Create default interrupt requests for 40-47. Note that we have to send EOI to both master and slave PIC.
IRQ_40_47_interrupt_default:
    mov al, 0x20        ; EOI command
    out 0x20, al        ; send to master
    out 0xA0, al        ; send to slave
iret
  1. Handle the keyboard interrupt (IRQ 1 or interrupt 33)
    Create a table of keyscan. This is incomplete I only mapped a-z and space. Note that 0x90 represents keyup 'q'.
keyscan:
    times 0x90 db 0
    db 'q','w','e','r','t','y','u','i','o','p'
    times 4 db 0
    db 'a','s','d','f','g','h','j','k','l'
    times 5 db 0
    db 'z','x','c','v','b','n','m'
    times 6 db 0
    db ' '

Here is the interrupt handler (function) for interrupt 33. First, poll the status of the keyboard buffer. If the buffer is full, read the buffer, otherwise, keep polling. Anything less then 0x80 is keydown. Anything above 0x80 is keyup. So we only care about keyup, so we check if the value from the keyboard is greater than 0x80. If it is greater, output the character to screen. And finally send EOI.

interrupt33:

poll_status:
    ; bit 0 is the output buffer status
    ; 1 means buffer is full, can be read
    ; 0 means buffer is empty, don't read
    mov eax, 0              ; set eax to 0
    in al, 0x64             ; read status from keyboard
    and al, 1               ; zero out all bits except first
    cmp al, 1               ; compare bits 
    jne poll_status         ; jump if not equal

    in al, 0x60             ; read from buffer

    mov cx, ax
    cmp cx, 0x80            ; compare cx to 0x80
    jl cont                 ; if cx is less then 0x80 go to cont

    mov ebx, [VIDEO_MEMEORY]    ; copy video memory to ebx
    and eax, 0x00FF             ; zero all bytes except the first
    mov cl, [keyscan+eax]       ; map the keyscan to ascii
    mov byte[ebx], cl           ; copy to video memory
    mov cl, 15                  ; set the character color to white
    mov byte[ebx+1], cl         ; copy to second byte of video memory
    add word[VIDEO_MEMEORY], 2  ; add 2 to video memory variable

cont:
    mov al, 0x20                ; EOI command
    out 0x20, al                ; send EOI command to master
iret
  1. Completed IDT
idt_info:
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt interrupt33-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_32_39_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
    interrupt IRQ_40_47_interrupt_default-starting+org
idt_info_end:

Reference
https://github.com/randcode-generator/RandCodeOS/commit/f81eafb430572e43680fe1b3eb83fd713aa5ed84