Enable the A20 line
Posted: Fri Apr 24, 2009 6:53 am
Hey every body. T'm trying to enable the A20 line from 3 way ( keybord controller, port 0x92, port 0x64 with register 0xDF) but, when i'm booting in vmWare, only the port 0x64 method enable the A20 line and when I'm booting in a real PC, all the method fail because my enableA20Line function set the CF when this line is not enable. This is my file with all the code for enable this.
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