Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

INIT_A20.ASM

Initialize A20 Address Line


; =============================================================================
;
;                Litos - Initialize A20 address line, real mode
;
; =============================================================================

%ifdef DEBUG
;%define	DEBUG_A20		; uncomment this to display A20 info
%endif

		CODE_SECTION	16

%define		INITA20_LOOPS	250	; number of tries to enable A20 gate

; -----------------------------------------------------------------------------
;                         Test A20 address line
; -----------------------------------------------------------------------------
; OUTPUT:	ZY (ZF=1): A20 not enabled, NZ (ZF=0): A20 enabled
; DESTROYS:	All registers except DS
; -----------------------------------------------------------------------------

; ------------- Push registers

TestA20:	push	ds		; push DS

; ------------- Prepare registers

		xor	ax,ax		; AX <- 0
		mov	ds,ax		; DS <- 0
		dec	ax		; AX <- 0ffffh
		mov	es,ax		; ES <- 0ffffh
		mov	ch,15		; CH <- number of A20 test loops HIGH
		mov	si,4*80h	; SI <- A20 test address (= Int 80h)

; ------------- Push old value from the test address

		mov	ax,[si]		; AX <- olf value from the test address
		push	ax		; push old value

; ------------- Check A20

TestA202:	inc	ax		; AX <- changed value
		mov	[si],ax		; change value on the test address
		call	ShortDelay	; short delay
		cmp	ax,[es:si+10h]	; check alternative address
		loope	TestA202	; address content is the same

; ------------- Pop old value to the test address

		pop	word [si]	; return old value

; ------------- Pop registers

		pop	ds		; pop DS
		ret

; -----------------------------------------------------------------------------
;                     Empty 8042 keyboard controller
; -----------------------------------------------------------------------------
; DESTROYS:	All registers except DS
; -----------------------------------------------------------------------------

; ------------- Prepare time-out counters (for first loop CX may be random)

Empty8042:	mov	ah,10		; AH <- time out value HIGH

; ------------- Check if input buffer is empty

Empty80422:	in	al,64h		; AL <- 8042 status port
		test	al,B1		; input buffer is full?
		jnz	Empty80426	; input buffer is full

; ------------- Check if output buffer is empty

		test	al,B0		; output buffer is full?
		jz	Empty80428	; output buffer is empty, all OK
		
; ------------- Flush output buffer

		call	ShortDelay	; short delay
		in	al,60h		; flush output buffer

; ------------- Next wait loop

Empty80426:	call	ShortDelay	; short delay
		loop	Empty80422	; wait for empty input buffer
		dec	ah		; counter HIGH
		jnz	Empty80422	; continue
Empty80428:	ret

; -----------------------------------------------------------------------------
;                      Enable A20 address line gate
; -----------------------------------------------------------------------------
; INPUT:	DS = data segment
; DESTROYS:	All registers except DS
; -----------------------------------------------------------------------------
; NOTES: If it cannot enable A20 address line, it halts the system.
; -----------------------------------------------------------------------------

; ------------- Check if A20 address line is already enabled

InitA20:
%ifdef DEBUG_A20
		mov	si,A20Msg	; SI <- debug message
		call	BIOSDispText	; display text
%endif
		call	TestA20		; test A20 address line
%ifdef DEBUG_A20
		mov	si,A20Msg1	; SI <- debug message
%endif
		jnz	InitA209	; A20 is enabled

; ------------- Enable A20 with BIOS

InitA202:	mov	ax,2401h	; AX <- function code
		int	15h		; enable A20 address line
		cli			; disable interrupts again

; ------------- Check if A20 address line is already enabled

		call	TestA20		; test A20 address line
%ifdef DEBUG_A20
		mov	si,A20Msg2	; SI <- debug message
%endif
		jnz	InitA209	; A20 is enabled

; ------------- Enable A20 with keyboard controller

		call	Empty8042	; empty 8042 keyboard controller
		mov	al,0d1h		; AL <- index of write output port
		out	64h,al		; set index of write output port
		call	Empty8042	; empty 8042 keyboard controller
		mov	al,0dfh		; AL <- enable A20
		out	60h,al		; enable A20 with write output port
		call	Empty8042	; empty 8042 keyboard controller

; ------------- Check if A20 address line is already enabled

		call	TestA20		; test A20 address line
%ifdef DEBUG_A20
		mov	si,A20Msg3	; SI <- debug message
%endif
		jnz	InitA209	; A20 is enabled

; ------------- Fast A20 gating (if "Fast A20" is enabled with a BIOS setting)

		cmp	byte [InitA20Loops],INITA20_LOOPS-6 ; skip some loops
		jae	InitA205	; carefully with "Fast A20"
		in	al,92h		; AL <- system control port A
		test	al,B1		; is this port valid?
		jnz	InitA204	; no fast A20 supported
		or	al,B1		; enable A20 gate
		and	al,~B0		; don't do fast reset
		out	92h,al		; enable A20 gate

; ------------- Check if A20 address line is already enabled

InitA204:	call	TestA20		; test A20 address line
%ifdef DEBUG_A20
		mov	si,A20Msg4	; SI <- debug message
%endif
		jnz	InitA209	; A20 is enabled

; ------------- Next loop

InitA205:	dec	byte [InitA20Loops] ; A20 loop counter
		jnz	InitA202	; next A20 test

; ------------- Error enabling A20 gate

		mov	si,A20ErrMessage ; error message
		call	BIOSDispText	; display error message
InitA206:	hlt			; halt system
		jmp	short InitA206	; halt system

InitA209:
; ------------- Debug display method
%ifdef DEBUG_A20
		call	BIOSDispText	; display text
%endif
		ret

; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

InitA20Loops:	db	INITA20_LOOPS	; number of tries to enable A20 gate

A20ErrMessage:	db	'Error: Cannot enable A20!',0

; ------------- Debug messages
%ifdef DEBUG_A20
A20Msg:		db	13,10,'A20 method: ',0
A20Msg1:	db	'Enabled',13,10,0
A20Msg2:	db	'BIOS 2401h',13,10,0
A20Msg3:	db	'Keyboard controller',13,10,0
A20Msg4:	db	'Fast A20',13,10,0
%endif

Back to source browser