%define INTGATE  	0x8E00	
%define IDTBASE  	0x800	;addr. physique où doit resider la IDT
%define IDTSIZE  	0xFF	;nombre max. de descripteurs dans la table
%define INTERRUPTION_PIC_MAITRE 0x20
%define INTERRUPTION_PIC_ESCLAVE 0x70

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialisation du PIC				;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
init_pic:
	mov al, 0x11	; Initialisation de ICW1
	out 0x20, al	; maître
	out 0xA0, al	; esclave

	mov al, INTERRUPTION_PIC_MAITRE  ; Initialisation de ICW2
	out 0x21, al	; maître, vecteur de départ = 32
	mov al, INTERRUPTION_PIC_ESCLAVE  
	out 0xA1, al	; esclave, vecteur de départ = 96

	mov al, 0x04	; initialisation de ICW3
	out 0x21, al
	mov al, 0x02	; esclave
	out 0xA1, al

	mov al, 0x05	; initialisation de ICW4
	out 0x21, al
	mov al, 0x01
	out 0xA1, al

	xor al, al		; masquage des interruptions
	out 0x21, al
	out 0xA1, al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin de l'initialisation du PIC		;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Création d'une table des vecteurs d'interruption pointant sur un simple EOI (End Of Interrupt)	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IDT : Interrupt Descriptor Table
;;
;; Structure : http://fr.wikipedia.org/wiki/Interrupt_Descriptor_Table
;; mot : les 16 bits les plus faibles de l'offset de la fonction (gestionnaire d'interruption ou d'exception) associée à l'interruption
;; mot : le sélecteur du segment de code, donc l'adresse du descripteur de code dans la GDT
;; 1 bit : drapeau IF (sur "1" pour activer le masquage des interruptions masquables)
;; 2 bits : DPL, de 0 à 3 inclus, qui indique le niveau de privilèges requis pour appeler l'interruption (0 est le plus élevé)
;; 1 bit : doit être mis à 0
;; 4 bits : le type d'interruption (porte d'interruption, de trappe ou de tâche)
;; 8 bits : réservé pour un futur usage (doit être à 0)
;; mot : les 16 bits les plus hauts de l'offset de la fonction associée à l'interruption
;;
;;   7                           0
;;+---+---+---+---+---+---+---+---+
;;| P |  DPL  | S |    GateType   |
;;+---+---+---+---+---+---+---+---+
;;P 	7	 Present 	 can be set to 0 for unused interrupts or for Paging.
;;DPL 	6,5 	Descriptor Privilege Level 	Gate call protection. Specifies which privilege Level the calling Descriptor minimum should have. So hardware and CPU interrupts can be protected from beeing called out of userspace.
;;S 	4 	Storage Segment 	= 0 for interrupt gates.
;;Typ 	0..3 	Gate Type 0..3 	Possible IDT gate types :
;;0b0101 	0x5 	5 	80386 32 bit Task gate
;;0b0110 	0x6 	6 	80286 16-bit interrupt gate
;;0b0111 	0x7 	7 	80286 16-bit trap gate
;;0b1110 	0xE 	14 	80386 32-bit interrupt gate
;;0b1111 	0xF 	15 	80386 32-bit trap gate
;; Pour nous : les bits indiqués seront 00000000(forcément)10001110, à passer en bigendian
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov eax, IDTBASE 				; Adresse de l'IDT
	mov ebx, interruptionParDefaut 	; On va remplir toute la table avec l'interruption par défaut : bx contient les bits de poids faible
	mov ecx, IDTSIZE				; Nombre de vecteurs d'interruption
	call metInterruptionNFois

; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction.
	mov eax, IDTBASE + (INTERRUPTION_PIC_MAITRE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur.
	mov ebx, interruptionPICMaitreParDefaut
	mov ecx, 8
	call metInterruptionNFois
	mov eax, IDTBASE + (INTERRUPTION_PIC_ESCLAVE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur.
	mov ebx, interruptionPICEsclaveParDefaut
	mov ecx, 8
	call metInterruptionNFois

; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction.
	mov eax, IDTBASE + 0x21*8;(INTERRUPTION_PIC_MAITRE + 1) * 8 ; Le clavier a l'IRQ1.
	mov ebx, interruptionClavier
	mov ecx, 1
	call metInterruptionNFois

	mov eax, IDTBASE + INTERRUPTION_PIC_MAITRE * 8 ; L'IRQ0, un timer.
	mov ebx, interruptionTimer
	mov ecx, 1
	call metInterruptionNFois
	
	lidt [idtptr]	; charge l'idt
	sti

	ret

;;Met l'interruption n fois dans l'idt
metInterruptionNFois:
	mov edx, ebx
	shr edx, 16
	mov [descripteurInterruption], bx	;bx contient les bits de poids faible
	mov [descripteurInterruption + 6], dx; et dx ceux de poids fort
	mov edi, eax
.remplitIDTPIC:
	mov esi, descripteurInterruption
	movsd
	movsd
	loop .remplitIDTPIC
	ret
	
interruptionPICMaitreParDefaut:
	mov al,0x20	; EOI (End Of Interrupt)
	out 0x20,al	; qu'on envoie au PIC
interruptionParDefaut:
	iret

interruptionPICEsclaveParDefaut:
	mov al,0x20	; EOI (End Of Interrupt)
	out 0xA0,al	; qu'on envoie au PIC
	iret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Gestion des interruptions clavier	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
interruptionClavier:
;	cli
	push ecx
	xor eax, eax
	xor ebx, ebx
.attendBuffer:
;	in		al,		0x64	; lire statut
;	and		al,		1		; bus de sortie prêt ?
;	jz		.attendBuffer	; non => boucler

	in		al, 	0x60	;Lit la touche pressée
;	cmp		al, 	224		;224 est un code spécial, ça veut dire qu'il y a autre chose derrière, mais pour l'instant on s'en fiche
;	je		.attendBuffer	;On va donc lire la suite
	cmp		al, 	122		;J'ai repéré les 122 premiers codes. Au-dessus, c'est de la blague.
	ja		.attendBuffer

	mov bl, al
	shr bl, 3; On divise le code par 8 pour savoir dans quel octet il se situe
	push eax	; On sauve le caractère dans la pile
	mov cl, 8
	div cl		; On le divise par 8
	mov cl, ah	; Pour une division par 8 bits, le reste est dans AH
	pop eax
	mov edx, 1
	shl dl, cl
	add ebx, touchesActives ;C'est l'adresse de l'octet contenant ce qui nous intéresse
	cmp		al,		128		;Les touches appuyées ont un code inférieur à 128, les touches relâchées, c'est le même code qu'appuyées plus 128
	jb		.stockeActif
	sub		al,		128
	sub		ebx,	128/8
	not dl
	and byte[ebx], dl
	jmp .suite
.stockeActif:
	or byte[ebx], dl	; Un OU met le bit à 1, un NOT AND le mettra à 0
	mov [derniereTouche], al

.suite:
;	in 		al, 	0x61
;	or		al, 	130
;	out 	0x61, 	al		;Dit à l'ordi qu'une touche a été pressée

;	and 	al,		127
;	out 	0x61,	al		;Reinitialisation terminée
 
;    sti
	pop ecx
	jmp 	interruptionPICMaitreParDefaut

touchesActives: ;Il me faut 128 bits (à la louche) pour stocker les touches actives, soit, 128/8 = 16 octets, soit 4 doubles mots
	dd 0, 0, 0, 0
derniereTouche:
	db 0
traductionASCII:
;	db Inconnu,Echap,'1','2','3','4','5','6','7','8','9','0','°','+',Espace arrière,Tab
;	db 'a','z','e','r','t','y','u','i','o','p','^','$',Entrée,Ctrl,'q','s'
;	db 'd','f','g','h','j','k','l','m','%','²',demiShiftGauche,'*','w','x','c','v'
;	db 'b','n',',',';',':','!',demiShiftDroit,ImprEcran,Alt&AltGr,' ',Verr.Maj.,F1,F2,F3,F4,F5
;	db F6,F7,F8,F9,F10,Verr.Num.&Pause,Arretdéfil,home,Haut,PgUp,-,Gauche,5,Droite,+,Fin
;	db Bas,PgDw,Inser,Suppr,Inconnu,Inconnu,'<',F11,F12; 89 caractères gérés
	db  00, 48, 02, 03, 04, 05, 06, 07, 08, 09, 10, 01, 37, 38,110,111
	db  11, 36, 15, 28, 30, 35, 31, 19, 25, 26, 39, 40,112,113, 27, 29
	db  14, 16, 17, 18, 20, 21, 22, 23, 41, 47,114, 42, 33, 34, 13, 32
	db  12, 24, 43, 44, 45, 46,115, 70, 50, 51,116, 52, 49, 53, 54, 55
	db  56, 57, 58, 59, 60, 61, 62, 63,117, 65, 64,118, 66,119, 67, 68
	db 120, 69,121,122, 00, 00, 71, 72, 73;89
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin gestion interruptions clavier	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

interruptionTimer:
	push eax
	push ecx
	push ebx
	push es

	mov 	bl, 	[.courant]
	dec 	bl
	or 		bl, 	bl
	jnz .depile
	mov 	ax, 	8*3		;En route pour le 3ème segment
	mov 	es, 	ax
	;clignotement curseur
	xor 	eax, 	eax
	mov 	al, 	[.prochainCaractere]
	mov 	ecx, 	[curseur]
	call afficheCaractere
	mov 	[curseur], ecx
	mov 	bl, 	[.vitesse]
	or 		al, 	al
	jnz .plein
	mov 	byte [.prochainCaractere], 51
	jmp .depile
.plein:
	mov 	byte [.prochainCaractere], 0
.depile:
	mov 	[.courant], bl
	pop es
	pop ebx
	pop ecx
	pop eax
	jmp		interruptionPICMaitreParDefaut
.prochainCaractere: db 0
.vitesse: db 5
.courant: db 5
	
;--------------------------------------------------------------------
idtptr:
	dw	IDTSIZE << 3			; limite
	dd	IDTBASE					; base

descripteurInterruption:
	dw 0, 1 * 8, INTGATE, 0
