[Kos-dev] DSR du commit de Thomas

Hlide kos-dev@enix.org
Thu, 5 Jul 2001 00:38:01 +0200


Salut !

Bon, je voudrais revenir un petit peu sur le contrôleur PIC. J'ai lu la doc
Intel de ce PIC et j'ai trouvé quelques éléments intéressants même  si je
n'ai pas encore toutes les réponses que je souhaitais.

Trois choses :

1) Automatic EOI
2) Automatic Priority Rotation
3) Special Mask Mode

De quoi s'agit-il ?

1) Ce mode évite la fameuse commande EOI à envoyer par le CPU. Mais il a un
inconvénient : on ne pourra plus lire le registre ISR (In Service Register)
qui contient normalement le masque des interruptions en service qui n'ont
pas encore commis un EOI. Or, précisémment, l'exception #DF en a besoin pour
déterminer quel IRQ en est l'auteur.

2) Ce mode permet de donner la même chance à toutes les interruptions. En
effet, à la fin de chaque IRQ on peut faire un EOI avec rotation de priorité
automatique dont l'effet est de donner la priorité la plus basse à cet IRQ.
Ce mode a d'intéressant qu'il évite qu'une interruption monopolise le CPU.
Par contre, je m'interroge dans le cas de l'IRQ 2 qui sert à la cascade :
sitôt qu'un IRQ du contrôleur PIC esclave va se déclarer l'IRQ 2 aura la
plus basse priorité, il y a-t-il un risque pour que tous les IRQ 8 à 15
deviennent moins prioritaire aux IRQ 0 à 7 ?

3) Ce mode est celui qui m'intéresse le plus. Voici ce que je peux lire de
la doc :
" Some applications may require an interrupt service routine to dynamically
alter the system priority structure during its execution under software
control. For example, the routine may wish to inhibit lower priority request
for a portion of its execution but enable some of them for another portion.

The difficulty here is that if an Interrupt Request is acknowledged and an
End od Interrupt command did not reset its IS bit (i.e, while executing a
service routine), the 8259A would have inhibited all lower priority requests
with no easy way for the routine to enable them.

That is where the Special Mask Mode comes in. In the Special Mask Mode, when
a mask bit is set in OCW1, it inhibits further interrupts at that level *and
enables* interrupts from *all other* levels (lower as well as higher) that
are not masked.

Thus, any interrupts may be selectively enabled by loading the mask
register.

The Special Mask Mode is set by OCW3 where : SSMM = 1, SMM = 1, and cleared
where SSMM = 1, SMM = 0.
"

Cependant, des zones d'ombres persistent : faut-il un EOI à la fin ? il
semblerait que oui à cause de l'inhibition lors du chargement de ce masque
de l'IRQ dont on exécute la routine de service. Que se passerait-il si deux
IRQ #0 et IRQ #1 se trouvait dans une imbrication de ce genre :

IRQ #0 : #0 n'est plus permis, #1 est permis
  IRQ #1 : #1 n'est plus permis, #0 est permis à cause du masque qui
l'autorise ?
    IRQ #0 : cet IRQ peut-il avoir lieu ?

Si le masquage dans ce mode spécial s'obtenait avec un OU logique entre ISR
(In Service register) et IMR (Interrupt Mask Register), alors on serait
rassuré car IRQ #0 serait à 1 dans l'ISR et donc il sera bien masqué au
final et on aurait à faire ceci :

1.sauvegarder les registres et sélecteurs
2.sauvegarder la copie globale du masque OCW1 courant
3.trouver le masque correspondant à l'IPL de l'IRQ en cours (lookup table)
4.écrire dans OCW1 le masque et mettre à jour la copie globale de OCW1
courant
5.exécuter "sti"
6.exécuter l'ISR (Interrupt Service Routine)
7.exécuter "cli"
8.restaurer la copie globale du masque OCW1 d'avant l'IRQ
9.envoyer la commande EOI avec rotation de priorité automatique
A.écrire dans OCW1 le masque
B.restaurer les registres et sélecteurs
C.retourner au code interrompu

Sinon, je ne vois pas d'autre nécessité que d'inclure dans le masque les IRQ
encore en service (Il n'est pas nécessaire de lire ISR puisque que l'on sait
quel IRQ entre en action, on peut obtenir facilement le masque
correspondant) :

On reprend la même chose qu'au-dessus mais en gardant une copie global de
l'ISR (In Service Register) pour effectuer le OU entre cette copie et celle
du masque OCW1 avant de l'écrire dans OCW1.

Je pense que l'on peut avoir une gestion relativement assez efficace des IPL
pour les ISR.

Pour les IRQ de 0 à 7, il n'est pas nécessaire de s'intéresser au PIC
esclave. Donc il s'agira que des opérations touchant au PIC maître.

Pour les IRQ de 8 à 15, il faut peut-être ceci :

1.sauvegarder les registres et sélecteurs
2.sauvegarder la copie globale du masque OCW1 courant
3.trouver le masque correspondant à l'IPL de l'IRQ en cours (lookup table)
4.envoyer la commande Specific EOI pour l'IRQ 2 au PIC master
(outb(0x62,0x20))
5.écrire dans OCW1 le masque et mettre à jour la copie globale de OCW1
courant
6.exécuter "sti"
7.exécuter l'ISR (Interrupt Service Routine)
8.exécuter "cli"
9.restaurer la copie globale du masque OCW1 d'avant l'IRQ
A.envoyer la commande EOI avec rotation de priorité automatique
B.écrire dans OCW1 le masque
C.restaurer les registres et sélecteurs
D.retourner au code interrompu

le point 4. est important sinon on masquera indirectement les IRQ 8 à 15 en
laissant le bit IS de l'IRQ 2.

Pour les DSR (Defered Service Routine), il n'est plus nécessaire d'avoir une
queue à priorité mais juste une FIFO. Pourquoi ? le fait que les ISR soient
sensibles aux IPL se répercute également dans l'ordre d'exécution des DSR.

En effet :

1.exécuter "cli"
2.restaurer la copie globale du masque OCW1 d'avant l'IRQ
3.envoyer la commande EOI avec rotation de priorité automatique
4.écrire dans OCW1 le masque
5.restaurer les registres et sélecteurs
6.retourner au code interrompu

Entre le point 1. et 3. on pourrait ajouter l'insertion simple d'un DSR
(s'il existe) dans une FIFO simple. Pas besoin d'une gestion compliqué d'une
queue à priorité puisque c'est l'imbrication par le jeu simulé des IPL qui
va également ordonné nos DSR. En effet si un ISR s'exécute à l'intérieur
d'un autre ISR en raison d'un IPL supérieur, son DSR sera également inséré
avant le DSR de l'autre. Notez qu'avec cette méthode, on a un algorithme
d'ordre O(1) !!!!!

Une autre possibilité, c'est que ce soit l'ISR qui installe le DSR dans un
FIFO non-bloquant. En particulier si l'on souhaite permettre à l'ISR d'avoir
plusieurs DSRs (point à éclaircir dans vos emails d'ailleurs...) : l'ISR de
l'IRQ 1 récupère le scancode et attache un DSR, on peut se retrouver avec
une FIFO ayant dans le bon ordre plusieurs DSR pour l'IRQ 1 (je ne sais pas
si vous souhaitez cette possibilité quand bien même je la trouve un peu trop
complexe à mettre en place).

A vos cogitations, Messieurs !