%define IRQ0 32
%define IRQ1 33
%define IRQ2 34
%define IRQ3 35
%define IRQ4 36
%define IRQ5 37
%define IRQ6 38
%define IRQ7 39
%define IRQ8 40
%define IRQ9 41
%define IRQ10 42
%define IRQ11 43
%define IRQ12 44
%define IRQ13 45
%define IRQ14 46
%define IRQ15 47


%macro ISR_NOERRCODE 1  ; define a macro, taking one parameter
  ;[GLOBAL isr%1]        ; %1 accesses the first parameter.
  isr%1:
    cli
    push byte 0
    push byte %1
    jmp isr_common_stub
%endmacro


%macro ISR_ERRCODE 1
  ;[GLOBAL isr%1]
  isr%1:
    cli
    push byte %1
    jmp isr_common_stub
%endmacro


;idt_set_gate
%macro SETUP_ISR_X 2
        mov eax,%1    ;base isr
        mov [idt_temp], word ax         ;lower 16 bits
        mov [idt_temp+2],word 0x08      ;kernel segment selector
        mov [idt_temp+4],byte 0x0       ;always 0   
        ; We must change 0x8E with 0xEE below when we get to using user-mode.
        ; It sets the interrupt gate's privilege level to 3.
        mov [idt_temp+5],byte 0x8E      ;0x8E | 0x60 = 0xEE... we have to enable this later on
        shld edx,eax,16
        mov [idt_temp+6],word dx
        ;store idt_temp in idt and repeat the process
        mov esi,idt_temp
        mov edi,idt+(%2*8)
        mov ecx,2
        rep movsd       ;verify this is working!!!!!!!!!! DO NOT LET IT AS IS WITHOUT CHECKING
%endmacro

; This macro creates a stub for an IRQ - the first parameter is
; the IRQ number, the second is the ISR number it is remapped to.
%macro IRQ 2
  global irq%1
  irq%1:
    cli
    push byte 0
    push byte %2
    jmp irq_common_stub
%endmacro

SECTION .data
isr_notification: db 'Recieved Interrupt.',`\n`,0x0


;;this is our IDT entry
idt_ptr_struct:
        dw idt_end - idt - 1 ; size of the GDT
        dd idt ; linear address of GDT

;256 idt entries. each entry has 8 bytes. 256*8 =2048

SECTION .text

extern prints
global init_idt
        ;first we have to create the interrupt handlers

        ISR_NOERRCODE 0
        ISR_NOERRCODE 1
        ISR_NOERRCODE 2
        ISR_NOERRCODE 3
        ISR_NOERRCODE 4
        ISR_NOERRCODE 5
        ISR_NOERRCODE 6
        ISR_NOERRCODE 7
        ISR_ERRCODE   8
        ISR_NOERRCODE 9
        ISR_ERRCODE   10
        ISR_ERRCODE   11
        ISR_ERRCODE   12
        ISR_ERRCODE   13
        ISR_ERRCODE   14
        ISR_NOERRCODE 15
        ISR_NOERRCODE 16
        ISR_NOERRCODE 17
        ISR_NOERRCODE 18
        ISR_NOERRCODE 19
        ISR_NOERRCODE 20
        ISR_NOERRCODE 21
        ISR_NOERRCODE 22
        ISR_NOERRCODE 23
        ISR_NOERRCODE 24
        ISR_NOERRCODE 25
        ISR_NOERRCODE 26
        ISR_NOERRCODE 27
        ISR_NOERRCODE 28
        ISR_NOERRCODE 29
        ISR_NOERRCODE 30
        ISR_NOERRCODE 31
	IRQ   0,    32
	IRQ   1,    33
	IRQ   2,    34
	IRQ   3,    35
	IRQ   4,    36
	IRQ   5,    37
	IRQ   6,    38
	IRQ   7,    39
	IRQ   8,    40
	IRQ   9,    41
	IRQ  10,    42
	IRQ  11,    43
	IRQ  12,    44
	IRQ  13,    45
	IRQ  14,    46
	IRQ  15,    47

init_idt:
   ;fill it with zero
	mov al,0x0
	mov ecx,2048
	mov edi,idt
	rep stosb
	;;BREAKPOINT: verify it's doing this as it should
	;xch bx,bx

	;Remap the irq table.
	;outb port, byte
	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
	xor  al,al
	out 0x21, al
	out 0xA1, al



	;set idt table:

	SETUP_ISR_X isr0,0
	SETUP_ISR_X isr1,1
	SETUP_ISR_X isr2,2
	SETUP_ISR_X isr3,3
	SETUP_ISR_X isr4,4
	SETUP_ISR_X isr5,5
	SETUP_ISR_X isr6,6
	SETUP_ISR_X isr7,7
	SETUP_ISR_X isr8,8
	SETUP_ISR_X isr9,9
	SETUP_ISR_X isr10,10
	SETUP_ISR_X isr11,11
	SETUP_ISR_X isr12,12
	SETUP_ISR_X isr13,13
	SETUP_ISR_X isr14,14
	SETUP_ISR_X isr15,15
	SETUP_ISR_X isr16,16
	SETUP_ISR_X isr17,17
	SETUP_ISR_X isr18,18
	SETUP_ISR_X isr19,19
	SETUP_ISR_X isr20,20
	SETUP_ISR_X isr21,21
	SETUP_ISR_X isr22,22
	SETUP_ISR_X isr23,23
	SETUP_ISR_X isr24,24
	SETUP_ISR_X isr25,25
	SETUP_ISR_X isr26,26
	SETUP_ISR_X isr27,27
	SETUP_ISR_X isr28,28
	SETUP_ISR_X isr29,29
	SETUP_ISR_X isr30,30
	SETUP_ISR_X isr31,31
        SETUP_ISR_X irq0,32
        SETUP_ISR_X irq1,33
        SETUP_ISR_X irq2,34
        SETUP_ISR_X irq3,35
        SETUP_ISR_X irq4,36
        SETUP_ISR_X irq5,37
        SETUP_ISR_X irq6,38
        SETUP_ISR_X irq7,39
        SETUP_ISR_X irq8,40
        SETUP_ISR_X irq9,41
        SETUP_ISR_X irq10,42
        SETUP_ISR_X irq11,43
        SETUP_ISR_X irq12,44
        SETUP_ISR_X irq13,45
        SETUP_ISR_X irq14,46
        SETUP_ISR_X irq15,47




	;load new idt
	lidt [idt_ptr_struct]
   
ret


;s is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
   pusha                    ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

   mov ax, ds               ; Lower 16-bits of eax = ds.
   push eax                 ; save the data segment descriptor

   mov ax, 0x10  ; load the kernel data segment descriptor
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   call isr_handler

   pop eax        ; reload the original data segment descriptor
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   popa                     ; Pops edi,esi,ebp...
   add esp, 8     ; Cleans up the pushed error code and pushed ISR number
   sti
   iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP

isr_handler:
	mov esi,isr_notification
	call prints
ret


; This is our common IRQ stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
irq_common_stub:
    pusha                    ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

    mov ax, ds               ; Lower 16-bits of eax = ds.
    push eax                 ; save the data segment descriptor

    mov ax, 0x10  ; load the kernel data segment descriptor
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    call irq_handler

    pop ebx        ; reload the original data segment descriptor
    mov ds, bx
    mov es, bx
    mov fs, bx
    mov gs, bx

    popa                     ; Pops edi,esi,ebp...
    add esp, 8     ; Cleans up the pushed error code and pushed ISR number
    sti
    iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP

irq_handler:
        mov esi,isr_notification
        call prints
ret


SECTION .bss

idt: resb 2048
idt_end:
idt_temp: resb 8
