#include "interruption.h"
#include "affichage.h"
#include "memoire.h"
#include "clavier.h"
#include "commun.h"
INTERRUPTGATE idt[256]; //256 entrée -> 0-255
unsigned char* pBuffer = 0;
unsigned int taille = 0;
void initialiseDescripteurDeVecteurInt(void* routine, unsigned short segSelecteur, unsigned short type, PINTERRUPTGATE pDescVecteur)
{
pDescVecteur->offset0_15 = ((unsigned int)routine&0xffff); //On récupère les 2 premiers octets (coté LSB)
pDescVecteur->offset16_31 = ((unsigned int)routine>>16); //On récupère les 2 derniers octets (du coté MSB)
pDescVecteur->segmentSelector = segSelecteur;
pDescVecteur->type = type;
return;
}
void chargementIDT(void)
{
unsigned short i;
IDTR idtr;
//On forge notre IDT en mémoire
for(i = 0 ; i < 256 ; i++)
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteInterruptionParDefaut), SEGCODER0, INTGATETYPER0, &idt[i]);
//Les ints hw doivent envoyer le EOI au pic
//Ici un EOI au controleur maitre
for(i = 32; i < 39+1; i++)
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteInterruptionHardwareParDefautCtrlM), SEGCODER0, INTGATETYPER0, &idt[i]);
//Ici un EOI au controleur esclave
for(i = 40; i < 46+1; i++)
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteInterruptionHardwareParDefautCtrlE), SEGCODER0, INTGATETYPER0, &idt[i]);
//On pose des ISRs pour les interruptions qui nous interessent, celle du clavier en particulier
//Le clavier est relie à la broche n°2 (en commençant a 1) du controleur d'interruption maitre ;
//or la première IRQ est associé à l'interruption n° 32 (d'apres notre configuration), c'est donc l'interruption n°33 (en commençant à 0) (0-31 => Reservé pour les exceptions)
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteInterruptionClavier), SEGCODER0, INTGATETYPER0, &idt[33]);
//On installe un handler pour les pagefaults (#PF)
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traitePageFault), SEGCODER0, INTGATETYPER0, &idt[14]);
//On installe un handler pour gerer les appels systemes
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteAppelSysteme), SEGCODER0, TRAPGATETYPER3, &idt[137]); //stay l33t wiz 137
//On installe un #GP handler
initialiseDescripteurDeVecteurInt(AligneAddrSurSegCode(traiteGP), SEGCODER0, INTGATETYPER0, &idt[13]);
//On prepare le registre IDTR contenant l'adresse de base/limite de notre IDT
idtr.base = (unsigned int)idt;
idtr.limite = 256 * TAILLEINTGATE;
//A present on écrit dans le réel registre IDTR par le bias de l'instruction lidt
lidt(idtr);
//Il faut stocker le nbr d'interrupt d'horloge a avoir
*((char*)0x713238) = 59;
//Le chargement de l'idt est ok
afficheChargementIDTOk();
return;
}
void configurationControleursInteruptions(void)
{
//Configuration du registre ICW1 (Initialization Command Word)
//Configurons le registre ICW1 du port1 maitre -> 00010001
EcritureSurPort(Port1Maitre, 0x11); //Registre sur 8b => |0|0|0|1|x|0|x|x|
// | | +--- avec ICW4 (1) ou sans (0)
// | +----- un seul contrôleur (1), ou cascadés (0)
// +--------- declenchement par niveau (level) (1) ou par front (edge) (0)
//Configurons le registre ICW1 du port1 esclave
EcritureSurPort(Port1Esclave, 0x11);
//Configuration du registre ICW2
//Configurons le registre ICW2 du port2 maitre
//IRQ0-7 seront utilisé pour les interruptions n° 32 à 39
EcritureSurPort(Port2Maitre, 32); //Registre sur 8b => |x|x|x|x|x|0|0|0|
// | | | | |
// +----------------- adresse de base des vecteurs d'interruption
//Configurons le registre ICW2 du port2 esclave
//IRQ8-15 seront utilisé pour les interruptions n° 112 à 120
EcritureSurPort(Port2Esclave, 112);
//Configuration du registre ICW3
//Configurons le registre ICW3 du port2 maitre -> 00000100
//Chaque bit correspond à une broche, le lsb à la broche n° 0 bien evidement, nous avons qu'un controleur d'int branché à la broche n°2
EcritureSurPort(Port2Maitre, 4); //Registre sur 8b => |x|x|x|x|x|x|x|x| pour le maître
// | | | | | | | |
// +------------------ contrôleur esclave rattaché à la broche d'interruption (1), ou non (0)
//Configurons le registre ICW3 du port2 esclave
//Le controleur esclave est branché sur la broche n° 2 du controleur maitre
EcritureSurPort(Port2Esclave, 2); //Registre sur 8b => |0|0|0|0|0|x|x|x| pour l'esclave
// | | |
// +-------- Identifiant de l'esclave, qui correspond au numéro de broche IR sur le maître
//Configuration du registre ICW4
//Configurons le registre ICW4 du port2 maitre
EcritureSurPort(Port2Maitre, 1); //Registre sur 8b => |0|0|0|x|x|x|x|1|
// | | | +------ mode "automatic end of interrupt" AEOI (1)
// | | +-------- mode bufferisé esclave (0) ou maître (1)
// | +---------- mode bufferisé (1)
// +------------ mode "fully nested" (1)
//Configurons le registre ICW4 du port2 esclave
EcritureSurPort(Port2Esclave, 1);
//On masque l'interruption du clavier
MasqueInterruptionClavier;
//Les controlleurs sont configurés
afficheConfigurationControleursIntsOk();
return;
}
void isrIntClavier(void)
{
//Pour nous ballader dans le tableau de caractere, on n'est oblige de prendre en compte les touches accompagné d'une autre (ctr, alt, shift etc)
unsigned char scancode, estMakeCode, estCaractereControle = 0, ajout, caractere;
static unsigned char shiftPresse = 0, altPresse = 0, ctrlPresse = 0;
CARACTERE ch;
ch.attribut = forgeCouleurClair(Vert);
//On récupère le scancode de la touche
LecturePort(PortLectureOuTransmissionDonnees, scancode);
//Si c'est un makecode
estMakeCode = ToucheEnfonce(scancode);
if(estMakeCode == 0)
//breakcode = makecode + 0x80
scancode -= 0x80;
//On récupere les touches spécial appuyé
switch(scancode)
{
case RSHIFTKEY:
case LSHIFTKEY:
if(estMakeCode)
{
//La touche est bel et bien appuyé
shiftPresse = 1;
//C'est un caractère de "controle" nous ne devons pas l'afficher
estCaractereControle = 1;
}
else
//La touche est relaché
shiftPresse = 0;
break;
case CTRLKEY:
if(estMakeCode)
{
ctrlPresse = 1;
estCaractereControle = 1;
}
else
ctrlPresse = 0;
break;
case ALTKEY:
if(estMakeCode)
{
altPresse = 1;
estCaractereControle = 1;
}
else
altPresse = 0;
break;
}
if(estMakeCode && estCaractereControle == 0) //c'est un makecode, et pas une touche de controle
{
//Je considere ici que deux combinaisons possible, shift + letter (=>min/maj), et ctrl+alt+letter (=>char spéciaux)
//Si on fait un shift + letter
if(shiftPresse)
//C'est la colonne n°2 du tableau qui nous intéresse
ajout = 1;
else if(ctrlPresse && altPresse)
ajout = 2;
else
ajout = 0;
caractere = kbdmap[scancode*3 + ajout];
//Si le caractere peut etre imprimé
if(caractere != SANSAFFICHAGE)
{
if(caractere == '\n')
{
ch.caractere = '\n';
((char*)(pBuffer+SEGDONNEER3BASE))[taille] = 0;
pBuffer = (char*)0;
taille = 0;
}
else
{
ch.caractere = caractere;
((char*)(pBuffer+SEGDONNEER3BASE))[taille] = caractere;
taille++;
}
afficheUnCaractere(&ch);
}
}
return;
}
void isrPageFault(void)
{
CHAINE ch;
ENTIER integ;
int cr2 = 0;
//L'adresse du defaut de page se situe dans le cr2
asm volatile
(
"movl %%cr2, %0"
: "=r" (cr2)
:
);
ch.attribut = forgeCouleurClair(Rouge);
ch.chaine = "\n*** Page Fault @ 0x";
integ.attribut = ch.attribut;
integ.entier = cr2;
afficheUneChaine(&ch);
afficheUnEntier(&integ);
ch.chaine = "***\n";
afficheUneChaine(&ch);
while(1);
return;
}
//EAX=>id syscall
void isrIntAppelSysteme(void)
{
unsigned int idSyscall, arg1, arg2;
CHAINE ch;
ch.attribut = forgeCouleurClair(Rouge);
asm volatile
(
"movl %%eax, %0\n"
"movl %%ebx, %1\n"
"movl %%ecx, %2\n"
: "=g" (idSyscall) , "=g" (arg1), "=g" (arg2)
:
);
switch(idSyscall)
{
case 0x1337:
//EBX=>ptr sur le buffer
pBuffer = (char*)arg1;
DemasqueInterruptionClavier;
while(pBuffer != 0);
break;
case 0x137:
//EBX=>ptr sur la chaine null-terminated
ch.chaine = (char*)(SEGDONNEER3BASE + (char*)arg1);
afficheUneChaine(&ch);
break;
case 0x138:
ch.chaine = "\n*** You Win !1!1§&&&! ***\n";
afficheUneChaine(&ch);
while(1);
break;
}
return;
}
void isrGP(void)
{
CHAINE a;
a.attribut = forgeCouleurClair(Rouge);
a.chaine = "\n*** #GP ***\n";
afficheUneChaine(&a);
while(1);
return;
}