Precedent | Sommaire | Suivant

7. Gerer les interruptions (1)

Precedement, nous avons vu comment commuter le PC en mode protege et quelles sont les implications de ce mode en terme d'adressage. Dans ce chapitre, nous allons voir un autre element tres important pour un systeme, la gestion des interruptions. Ce chapitre est uniquement theorique. La mise en pratique des notions vues ici est l'objet du chapitre suivant.

7.1 Le processeur et les interruptions

7.1.1 Des interruption pour prevenir le processeur d'un evenement

Les interruptions sont des signaux envoyes par les peripheriques (clavier, disque, souris, etc.) au processeur pour l'avertir d'evenements. Par exemple, le disque va prevenir le processeur que des donnees sont pretes en lecture en lui envoyant une interruption.
Lorsque le processeur recoit une interruption, il interrompt la tache en cours, apres avoir sauvegarde le contexte de celle-ci, et une routine (ISR, Interrupt Service Routine) liee a l'interruption est executee. Une fois la routine executee, le processeur reprend la tache interrompue.
Il y a trois types d'interruptions :
  • les interruptions materielles, declenchees par les peripheriques ;
  • les exceptions, declenchees par le processeur en cas de faute (division par zero, faute de page, etc.) ;
  • les interruptions logicielles qui permettent de gerer les appels systemes.
    Voici un exemple d'interruption materielle. Quand on presse ou qu'on relache une touche du clavier d'un PC, Une interruption est envoyee au processeur. Le processeur va en reponse executer une routine pour traiter l'evenement dont il a ete averti par le processeur (une touche a ete pressee ou relachee). Cette routine va plus specifiquement interroger le clavier pour savoir quelle touche a ete pressee, puis il va eventuellement afficher le caractere correspondant et le stocker dans un buffer. Une fois la routine de traitement des caracteres terminee, la tache interrompue reprend.

    7.1.2 Executer la bonne routine : la table des vecteurs d'interruptions

    Une table permet d'associer a chaque interruption une routine a executer, c'est la table IDT (Interrupt Descriptor Table). A chaque interruption est associe un "vecteur" qui est un index dans cette table afin de declencher la bonne procedure.

    La table IDT contient des descripteurs systemes appeles 'gates'. Il y a plusieurs types de gates, mais pour traiter les interruptions materielles et les exceptions, ont utilise classiquement les 'interrupt gate'. Un gate est une structure qui pointe sur une routine.

    7.2 Le controleur d'interruptions

    7.2.1 Des interruptions materielles gerees par un chipset : le 8259A (1)

    Les interruptions materielles sont les sonnettes que tirent les peripheriques pour dire au processeur que quelque chose se passe. Mais si chaque peripherique pouvait envoier directement un signal au processeur, il faudrait sur celui-ci autant de broche (jouant le role de cordons de sonnette) que de peripheriques. Pour eviter cela, les peripheriques envoient leur requete d'interruption a un chipset auquel ils sont connectes, le 8259A, appele aussi "Programmable interrupt controler" (PIC). C'est ce chipset qui va envoyer a leur place une interruption au processeur.
    Chaque 8259A peut gerer les interruptions de 8 peripheriques mais la plupart des PC ont deux controleurs cascades entre eux, ce qui leur permet de gerer jusqu'a 14 peripheriques. Le second controleur (l'esclave) est chaine au premier (le maitre).
    Les requetes faites par le controleur sont appelees IRQ (Interrupt Request).

    7.2.2 Des interruptions materielles gerees par un chipset : le 8259A (2)

    Quand un peripherique transmet au 8259A une requete pour une interruption, celle-ci subit un traitement complexe :
    - la requete passe au travers d'un masque (Interrupt Mask Register). Si l'interruption est masquee, son traitement finit ici.
    - le registre IRR est charge de gerer les priorites entre interruptions. La requete avec la plus haute priorite est evaluee.
    - le 8259A signale au processeur la demande d'interruption.
    - Le processeur acquitte ce signal puis demande au controleur, par un autre signal, le numero de l'interruption demandee afin de declencher la bonne routine.
    - le controleur depose sur le bus de donnees un octet, le vecteur d'interruptions.
    - Une fois la routine terminee, le processeur doit envoyer au controleur un signal pour l'avertir que tout est fini et que tout peut recommencer.

    Un controleur peut ainsi realiser des fonctions plus complexes que la simple transmission d'interruptions. Il est possible de masquer des interruptions, de definir des priorites, etc. Ce fonctionnement est librement parametrable. La partie suivante explique comment il est possible de parametrer un controleur.

    7.2.3 Parametrer le controleur d'interruptions

    7.2.3.1 Envoyer des parametres en utilisant les ports d'entree/sortie
    Il est possible de parametrer les deux PIC d'un PC en utilisant les ports d'entree/sortie. On accede au controleur maitre via les ports 0x20 et 0x21 et au controleur esclave via les ports 0xA0 et 0xA1. En ecrivant sur l'un de ses ports, on envoie au controleur des donnees qui seront inscrite dans l'un de ses registres. Les valeurs placees dans les registres internes du controleur determinent son fonctionnement.
    7.2.3.2 Des registres pour stocker les parametres du controleur
    On parametre un controleur en mettant des valeurs dans ses registres internes. Il y a deux types de registres, les ICW et les OCW.
    Les registres ICW (Initialization Command Word) reinitialisent le controleur quand ils sont fournis.
    Les registres OCW (Operation Control Word) permettent de parametrer certaines fonctions du controleur une fois que celui-ci a ete initialise.

    Les encadres ci-dessous presentent les differents registres avec leur signification.

    ICW1 (port 0x20 and 0xA0)
            |0|0|0|1|x|0|x|x|
                     |   | +--- avec ICW4 (1) ou sans (0)
                     |   +----- un seul 8259 (1), ou cascades (0)
                     +--------- declenchement par niveau (1) ou par front (0)
    

    ICW2 (port 0x21 et 0xA1)
            |x|x|x|x|x|0|0|0|  
             | | | | |
             +----------------- bits A7-A3 du vecteur d'interruption
    
    Comme il n'y a que 8 interruptions possible par PIC, seuls les 3 bits
    de poids faible comptent dans le vecteur pour determiner l'interruption.
    Les 5 autres bits, de poids fort, servent a calculer l'adresse du
    vecteur.
    

    ICW3 (port 0x21 et 0xA1)
            |x|x|x|x|x|x|x|x|  pour le maitre
             | | | | | | | |
             +------------------ controleur esclave rattache (1), ou non (0)
    
            |x|x|x|x|x|x|x|x|  pour l'esclave
             | | | | | | | |
             +------------------ controleur maitre rattache (1), ou non (0)
    

    ICW4 (port 0x21 et 0xA1)
            |0|0|0|0|0|0|0|1|
    

    OCW1 (ports 0x21 et 0xA1)
            |x|x|x|x|x|x|x|x|  
             | | | | | | | |
             +------------------ masque d'interruption etabli (1) ou non (0)
                                 chaque bit correspond a une IRQ
    

    OCW2 (ports 0x20 et 0xA0)
            |x|x|x|0|0|x|x|x|
             | | |     +-------- niveau d'interruption
             | | | 
             | | |
             +--------------- End Of Interrupt (EOI)
    
    EOI : 
            001  EOI non specifique
            010  NOP
            011  EOI specifique
            100  Rotation sur EOI automatique
            101  Rotation sur EOI non specifique
            110  Etablissement de code prioritaire
            111  Rotation sur EOI specifique
    

    OCW3 (ports 0x20 et 0xA0)
            |0|x|x|0|1|x|x|x|  
               | |     | +---- lecture IRR (10) ou lecture ISR (11) a la
               | |     |       prochaine lecture.
               | |     +------ acquisition d'interruptions par polling (1)
               +-------------- NOP (0x), reset (10), set (11)
    

    7.2.3.3 Initialiser le controleur en remplissant les registres ICW
    Pour initialiser un controleur, il faut remplir ses registres d'initialisation ICW1, ICW2, ICW3 et ICW4 en respectant cet ordre.
    On remplit chaque registre en envoyant sur le port aproprie les bonnes donnees. Il faut savoir qu'apres avoir transmis les donnees pour le registre ICW1, le controleur attend obligatoirement que lui soit fournis l'octet du registre ICW2. Si il n'y a qu'un seul controleur, il n'est pas la peine de renseigner les registres ICW3 et ICW4.
    Ces informations sont transmises en ecrivant sur le port approprie (0x20 et 0x21 pour le maitre, 0xA0 et 0xA1 pour l'esclave)
    Les registres OCW peuvent etre rempli a n'importe quel moment apres l'initialisation des PIC. Nous utiliserons uniquement le registre OCW1 pour masquer et demasquer les interruptions.
    7.2.3.4 Une routine en assembleur pour initialiser le controleur
    Cette sequence initialise le maitre puis l'esclave :
     ; Maitre
     mov al,0x11 ; Initialisation de ICW1
     out 0x20,al
     jmp $+2    ; temps d'attente
    
     mov al,0x08 ; Initialisation de ICW2
     out 0x21,al
     jmp $+2    
    
     mov al,0x04 ; Initialisation de ICW3
     out 0x21,al
     jmp $+2  
    
     mov al,0x01 ; Initialisation de ICW4
     out 0x21,al
     jmp $+2   
    
     mov al,0xFF ; masquage des interruptions
     out 0x21,al
     
     ; Esclave
     mov al,0x11 ; Initialisation de ICW1
     out 0xA0,al
     jmp $+2    ; temps d'attente
    
     mov al,0x70 ; Initialisation de ICW2
     out 0xA1,al
     jmp $+2    
    
     mov al,0x02 ; Initialisation de ICW3
     out 0xA1,al
     jmp $+2    
    
     mov al,0x01 ; Initialisation de ICW4
     out 0xA1,al
     jmp $+2   
    
     mov al,0xFF ; masquage des interruptions
     out 0xA1,al