Enable the A20 line

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
spiner900
Member
Member
Posts: 26
Joined: Mon Mar 09, 2009 10:47 am

Enable the A20 line

Post by spiner900 »

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 
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: Enable the A20 line

Post by yemista »

Knowing how to enable the A20 line requires a lot of technical details, and I doubt(but please dont jump down my throat if im wrong) there are many people on this board who are able to debug such a thing. Your best bet is to just go to the wiki, search "enable A20", and use the code posted there. It should work on a real PC. If you are interested in the details of the A20 controller and the process of enabling it, thats fine, but in general, this is not a part of your OS you should really bother much with.
spiner900
Member
Member
Posts: 26
Joined: Mon Mar 09, 2009 10:47 am

Re: Enable the A20 line

Post by spiner900 »

I finally found my error. When I write the output register to the controller with the A20 enable, I used the 0x64 port but it the 0x60.

yemista I'm able to debug that :D

Code: Select all

	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 0x60, AL   ; THIS LINE
	RET
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Enable the A20 line

Post by Love4Boobies »

yemista wrote:Knowing how to enable the A20 line requires a lot of technical details, and I doubt(but please dont jump down my throat if im wrong) there are many people on this board who are able to debug such a thing. Your best bet is to just go to the wiki, search "enable A20", and use the code posted there. It should work on a real PC. If you are interested in the details of the A20 controller and the process of enabling it, thats fine, but in general, this is not a part of your OS you should really bother much with.
I would have to disagree with that. By the way, back in the days when they used PPIs for KBCs, how would they cope with the A20 gate issue? Or was that long before they added the 21st bus line? - I'm supposing that's the case.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Enable the A20 line

Post by jal »

Love4Boobies wrote:By the way, back in the days when they used PPIs for KBCs, how would they cope with the A20 gate issue? Or was that long before they added the 21st bus line? - I'm supposing that's the case.
The reason the A20 is controlled at all through the KBC is that when they added the 21st line (when designing the AT), there was some spare logic in the KBC they could use. The AT keyboard had a PPI, I don't think the XT keyboard had.


JAL
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Enable the A20 line

Post by Love4Boobies »

jal wrote:
Love4Boobies wrote:By the way, back in the days when they used PPIs for KBCs, how would they cope with the A20 gate issue? Or was that long before they added the 21st bus line? - I'm supposing that's the case.
The reason the A20 is controlled at all through the KBC is that when they added the 21st line (when designing the AT), there was some spare logic in the KBC they could use. The AT keyboard had a PPI, I don't think the XT keyboard had.


JAL
Yep, I'm aware why they did that. I think I'll open a new thread asking more about the PPI.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
extremecoder
Member
Member
Posts: 59
Joined: Tue May 23, 2006 11:00 pm

Re: Enable the A20 line

Post by extremecoder »

as Intel gives CR0 register to enable protected mode, is enabling A20 still required these days ?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Enable the A20 line

Post by Brendan »

Hi,
extremecoder wrote:as Intel gives CR0 register to enable protected mode, is enabling A20 still required these days ?
Yes, it's (mostly) still required; and it's entirely possible to be in protected mode (or long mode) and still have A20 disabled...

Some BIOSs break backward compatibility by leaving A20 enabled when they start an OS's boot loader, but you can't assume A20 will be enabled (unless you use something like GRUB that does it for you, and/or unless the firmware isn't meant to be compatible with a legacy BIOS - e.g. UEFI/EFI or Coreboot).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Enable the A20 line

Post by jal »

extremecoder wrote:as Intel gives CR0 register to enable protected mode, is enabling A20 still required these days ?
The A20 control lies outside the CPU, the CPU has no knowledge of it.


JAL
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Enable the A20 line

Post by Brendan »

Hi,
jal wrote:
extremecoder wrote:as Intel gives CR0 register to enable protected mode, is enabling A20 still required these days ?
The A20 control lies outside the CPU, the CPU has no knowledge of it.
For 80286 and 80386, A20 is entirely external and the CPU, but...

For all CPUs with internal caches (80486 and later) the CPU's cache needs to be aware of A20 state (which may be a simple as flushing the cache when A20 state changes); and for all CPUs with MTRRs (Pentium and later) the CPU needs to mask A20 internally before looking up the caching type to use for the access (write-back, write-through, uncached, etc) in it's MTRRs. Note: This includes Cyrix chips (which had eight "Address Region Registers" and eight "Region Control Registers" that serve exactly the same purpose as Intel's "Variable Range MTRRs") and anything similar that other CPU manufacturers may have used.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Enable the A20 line

Post by jal »

Brendan wrote:For 80286 and 80386, A20 is entirely external and the CPU, but...
I stand corrected.


JAL
Post Reply