text: #include "interrupts.h"
  #include "pic.h"
  #include "../drivers/io.h"
  
  
  #include "../drivers/framebuffer.h"
  #include "../drivers/serial_port.h"
  #include "keyboard.h"
  #include "../all_paging/paging.h"
  
  #define INTERRUPTS_DESCRIPTOR_COUNT 256 
  #define INTERRUPTS_KEYBOARD 33 
  #define INTERRUPTS_PAGING 14 
  
  struct IDTDescriptor idt_descriptors[INTERRUPTS_DESCRIPTOR_COUNT];
  struct IDT idt;
  
  
  void interrupts_init_descriptor(int index, unsigned int address)
  {
  	idt_descriptors[index].offset_high = (address >> 16) & 0xFFFF; // offset bits 0..15
  	idt_descriptors[index].offset_low = (address & 0xFFFF); // offset bits 16..31
  
  	idt_descriptors[index].segment_selector = 0x08; // The second (code) segment selector in GDT: one segment is 64b.
  	idt_descriptors[index].reserved = 0x00; // Reserved.
  
  	/*
  	   Bit:     | 31              16 | 15 | 14 13 | 12 | 11     10 9 8   | 7 6 5 | 4 3 2 1 0 |
  	   Content: | offset high        | P  | DPL   | S  | D and  GateType | 0 0 0 | reserved
  		P	If the handler is present in memory or not (1 = present, 0 = not present). Set to 0 for unused interrupts or for Paging.
  		DPL	Descriptor Privilige Level, the privilege level the handler can be called from (0, 1, 2, 3).
  		S	Storage Segment. Set to 0 for interrupt gates.
  		D	Size of gate, (1 = 32 bits, 0 = 16 bits).
  	*/
  
  	idt_descriptors[index].type_and_attr =	(0x01 << 7) |			// P
  						(0x00 << 6) | (0x00 << 5) |	// DPL
  						0xe;				// 0b1110=0xE 32-bit interrupt gate
  }
  
  
  void interrupts_install_idt()
  {
  	interrupts_init_descriptor(INTERRUPTS_KEYBOARD, (unsigned int) interrupt_handler_33);
  	interrupts_init_descriptor(INTERRUPTS_PAGING, (unsigned int) interrupt_handler_14);
  
  	idt.address = (int) &idt_descriptors;
  	idt.size = sizeof(struct IDTDescriptor) * INTERRUPTS_DESCRIPTOR_COUNT;
  	load_idt((int) &idt);
  
  	/*pic_remap(PIC_PIC1_OFFSET, PIC_PIC2_OFFSET);*/
  	pic_remap(PIC_1_OFFSET, PIC_2_OFFSET);
  }
  
  
  /* Interrupt handlers ********************************************************/
  
  void interrupt_handler(__attribute__((unused)) struct cpu_state cpu, unsigned int interrupt, __attribute__((unused)) struct stack_state stack)
  {
  	unsigned char scan_code;
  	unsigned char ascii;
  
  	switch (interrupt){
  		case INTERRUPTS_KEYBOARD:
  
  			scan_code = keyboard_read_scan_code();
  
  			if (scan_code <= KEYBOARD_MAX_ASCII) {
  				ascii = keyboard_scan_code_to_ascii(scan_code);
  
  				char str[1];
  				str[0] = ascii;
  
  				fb_write(str, 1);
  				serial_write(0x3F8,str,1);
  			}
  
  			pic_acknowledge(interrupt);
  
  			break;
  		
  		case INTERRUPTS_PAGING:
  			page_fault();	
  			break;
  		default:
  			break;
      }
  }
  