Code: Select all
%ifndef A20_LINE_INCLUDE
%define A20_LINE_INCLUDE
;[*************************************************************]
; enableA20Line
;
; Permet d'activer la A20 line pour pouvoir
; accèder à l'ensemble de la mémoire si elle
; n'est pas déjà activé.
;
; Entrées :
; rien
;
; Sortie :
; CF : Activé si c'est impossible d'activé la A20 line.
; Désactivé si la A20 line est activé.
; [**************************************************************]
enableA20Line:
;MOV AX, 2403
;INT 0x15
CALL checkA20line
JNC .done
CALL enableA20LinePort92
JNC .done
; Méthode classique du clavier qui est très bien suporté
CALL enableA20LineKeybord1
JNC .done
; Méthode alternative du clavier (commande 0xDF du port 0x64)
CALL enableA20LineKeybord2
JNC .done
.done:
RET
;[************************************************]
; checkA20line
;
; Permet de tester si la A20 line est déjas
; activé par le BIOS
;
; Entrées :
; rien
; Sortie :
; CF activée si impossible d'activé A20 line
; CF désactivé si A20 line est activé
;
;[************************************************]
checkA20line:
PUSH es
PUSH ds
PUSH di
PUSH si
CLI
XOR ax, ax ; ax = 0
MOV fs, ax
NOT ax ; ax = 0xFFFF
MOV gs, ax
MOV di, 0x0500
MOV si, 0x0510
MOV al, BYTE [fs:di]
PUSH ax
MOV al, BYTE [gs:si]
PUSH ax
MOV BYTE [fs:di], 0x00
MOV BYTE [gs:si], 0xFF
CMP BYTE [fs:di], 0xFF
POP ax
MOV BYTE [gs:si], al
POP ax
MOV BYTE [fs:di], al
STC ; A20 line désactivé
JE .end
CLC ; A20 line activée
.end:
STI
POP si
POP di
POP ds
POP es
RET
;[***************************************************************************]
; enableA20LinePort92
;
;
;
;
;[***************************************************************************]
enableA20LinePort92:
in al, 0x92
or al, 2
out 0x92, al
in al, 0x92
BT aX, 1
RET
;[***************************************************************************]
; enableA20LineKeybord1
;
; Permet d'activer la A20 line à l'aide du clavier ( 5 Tentatives )
;
; Entrées :
; rien
;
; Sortie :
; CF activée si impossible d'activé A20 line
; CF désactivé si A20 line est activé
;
; Voici les étapes pour l'activation:
;
; 1. Désactivé les interrupteurs
; 2. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 3. Désactiver le clavier
;
; procédure read8042OutputPort
; 4. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 5. Envoyer la commande pour lire le port de sortie
; 6. Attendre que la chip 8042 soit prête à envoyer des données au système
; 7. Lecture du registre de sortie de la chip 8042
;
; 8. Active la A20 line (Activer le BIT 2 du contenue du port de sortie)
;
; procédure write8042OutputPort
; 9. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 10. Envoyer la commande pour ecrire le port de sortie
; 11. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 12. Ecrire le registre de sortie avec A20 line activé
;
; 13. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 14. Activer le clavier
; 15. Activé les interrupteurs
;
; Spécification :
; - Le port 0x60 en lecture : sert à la lecture de données
; ( peut être lu à n'importe quel moment)
; - Le port 0x60 en écriture : sert à la transmission de données
; - Le port 0x64 en lecture : sert à connaître le statut du la chip 8042
; - Le port 0x64 en écriture : sert à émettre des commandes
;
; - Port de sortie de la chip 8042 :
;
; |7|6|5|4|3|2|1|0|
; | | | | | | | `---- system reset line
; | | | | | | `----- A20 line
; | | | | `-------- Non définit
; | | | `--------- Buffer de sortie plien
; | | `---------- Buffer d'entrée vide
; | `----------- keyboard clock (output)
; `------------ keyboard data (output)
;
;[***************************************************************************]
enableA20LineKeybord1:
PUSH AX
PUSH CX
; 1. Désactiver les interruptions
CLI
; Démarre un conteur qui permet d'aseiller d'activé la A20 line
; plusieurs fois si nécessaire.
MOV CX, 5
.retry:
; 2. Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; 3. Désactiver le clavier
MOV AL, 0xAD
OUT 0x64, AL
; Étape 4 à 7
CALL read8042OutputPort
; Active la A20 line (Activer le BIT 2 du contenue du port de sortie)
OR AL, 00000010b
; Étape 9 à 12
CALL write8042OutputPort
; 13. Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; 14. Activer le clavier
MOV AL, 0xAE
OUT 0x64, AL
; ---------------------------------------
; Test si la A20 line est bien activé
; ---------------------------------------
CALL read8042OutputPort
BT AX, 1
JC .a20lineActived
LOOP .retry
STC ; erreur
JMP .end
.a20lineActived:
CLC ; Pas d'erreur
.end:
; 15. Activé les interrupteurs
STI
POP CX
POP AX
RET
;[***************************************************************************]
; enableA20LineKeybord2
;
; Permet d'activer la A20 line à l'aide du clavier ( 5 Tentatives )
; (Méthode alternative qui n'est pas supporté par tous les chipsets 8042)
;
; Entrées :
; rien
;
; Sortie :
; CF activée si impossible d'activé A20 line
; CF désactivé si A20 line est activé
;
; Voici les étapes pour l'activation:
;
; 1. Désactivé les interrupteurs
; 2. Attendre que la chip 8042 soit prêt pour recevoir une commande
; 3. Indiquer à la chip 8042 qu'on veut activé la A20 line (Index 0xDF du port 0x64)
; 4.
; 5.
;
;[***************************************************************************]
enableA20LineKeybord2:
PUSH AX
PUSH CX
; 1. Désactiver les interruptions
CLI
MOV CX, 5
.retry:
; Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; Indiquer à la chip 8042 qu'on veut activé la A20 line
MOV AL, 0xDF
OUT 0x64, AL
CALL read8042OutputPort
BT AX, 1
JC .a20lineActived
LOOP .retry
STC ; erreur
JMP .end
.a20lineActived:
CLC ; Pas d'erreur
.end:
STI ; 15. Activé les interrupteurs
POP CX
POP AX
RET
;[*********************************************************]
; Routine wait8042ReadyInputCMD
;
; Entrée :
; Aucune
;
; Sortie :
; Aucune
;
; BUT : Permet d'attendre que la chip 8042 soit
; prête avant d'envoyé une commande
; via le port 0x64 (le port soit vide).
;
; Spécification :
; - Le port 0x64 en lecture :
; sert à connaître le statut du la chip 8042
;
; - Status du registre 8042 (lecture du port 0x64)
;
; |7|6|5|4|3|2|1|0| Status du registre 8042
; | | | | | | | `---- Registre de sortie (60h) de la chip 8042
; | | | | | | | 1 = Les données sont prête à être envoyé au système
; | | | | | | | 0 = Les données ne sont pas prête à être envoyé au système
; | | | | | | `----- Registre d'entrée (0x60/0x64) de la chip 8042
; | | | | | | 1 = Possède des données pour la chip 8042
; | | | | | | 0 = Aucune données pour la chip 8042
; | | | | | `------ Flag système (set to 0 after power on reset)
; | | | | `------- Les données dans le registre d'entré est une
; | | | | command (1) ou une donnée (0)
; | | | `-------- 1= Clavier activé, 0= Clavier désactivéd (par la switch)
; | | `--------- 1=transmit timeout (data transmit not complete)
; | `---------- 1=receive timeout (data transmit not complete)
; `----------- 1=even parity rec'd, 0=odd parity rec'd (should be odd)
;[************************************************]
wait8042ReadyInputCMD:
PUSH AX
.wait:
IN AL, 0x64 ; Lecture du statut da la chip 8042
BT AX, 1 ; Met le BIT numéro 1 dans le flag CF
JC .wait
POP AX
RET
;[*********************************************************]
; Routine wait8042ReadyOutputData
;
; Entrée :
; Aucune
;
; Sortie :
; Aucune
;
; BUT : Permet d'attendre que la chip 8042 soit
; prête à envoyer des données au système
; via le port 0x60.
;
; Spécification :
; - Le port 0x64 en lecture :
; sert à connaître le statut du la chip 8042
;
; - Status du registre 8042 (lecture du port 0x64)
;
; |7|6|5|4|3|2|1|0| Status du registre 8042
; | | | | | | | `---- Registre de sortie (60h) de la chip 8042
; | | | | | | | 1 = Les données sont prête à être envoyé au système
; | | | | | | | 0 = Les données ne sont pas prête à être envoyé au système
; | | | | | | `----- Registre d'entrée (0x60/0x64) de la chip 8042
; | | | | | | 1 = possède des données pour la chip 8042,
; | | | | | | 0 = aucune données pour la chip 8042
; | | | | | `------ Flag système (set to 0 after power on reset)
; | | | | `------- Les données dans le registre d'entré est une
; | | | | command (1) ou une donnée (0)
; | | | `-------- 1= Clavier activé, 0= Clavier désactivéd (par la switch)
; | | `--------- 1=transmit timeout (data transmit not complete)
; | `---------- 1=receive timeout (data transmit not complete)
; `----------- 1=even parity rec'd, 0=odd parity rec'd (should be odd)
;[************************************************]
wait8042ReadyOutputData:
PUSH AX
.wait:
IN AL, 0x64 ; Lecture du statut da la chip 8042
BT AX, 0 ; Met le BIT numéro 0 dans le flag CF
JNC .wait
POP AX
RET
;[***********************************************************************]
; Routine read8042OutputPort (Étape 4 à 7)
;
; Entrée :
; Aucune
;
; Sortie :
; AL : Le contenue du port de sortie de la chip 8042
;
; BUT : Permet de lire le contenue du port de sortie de la chip 8042
;
; Spécification :
;
;[***********************************************************************]
read8042OutputPort:
; 4. Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; 5. Envoyer la commande pour lire le port de sortie
MOV AL, 0xD0 ; 0xD0 -> Lecture de port de sortie : Les
; données sont lu à partie du port
; de sortie (inacessible par le bus de données)
; et placé dans le registre de sortie.
; (Le registre de sortie doit être vide)
OUT 0x64, AL
; 6. Attendre que la chip 8042 soit prête à envoyer des données au système
CALL wait8042ReadyOutputData
; 7. Lecture du registre de sortie de la chip 8042 et la sauvagarder
IN AL, 0x60
RET
;[***********************************************************************]
; Routine write8042OutputPort (Étape 9 à 12)
;
; Entrée :
; AL : Le contenue du port de sortie de la chip 8042
;
; Sortie :
; Aucune
;
; BUT : Permet d'écrire le contenue du port de sortie de la chip 8042
;
; Spécification :
;
;[***********************************************************************]
write8042OutputPort:
PUSH AX ; Sauvegarde le contenue du port de sortie
; 8. Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; 9. Envoyer la commande pour ecrire le port de sortie
MOV AL, 0xD1 ; 0xD1 -> Écrire le port de sortie : Le prochain octet
; envoyé via la port 0x60 est placé dans le
; port de sortie de la chip 8042.
OUT 0x64, AL
; 10. Attendre que la chip 8042 soit prêt pour recevoir une commande
CALL wait8042ReadyInputCMD
; 11. Ecrire le registre de sortie sauvegardé avec le bit numéro 1 activé (A20 line activé)
POP AX ; Restore le contenue du port de sortie
OUT 0x64, AL
RET
%endif