os

Toy OS
git clone git://git.christosmarg.xyz
Log | Files | Refs | README | LICENSE

a20.asm (3323B)


      1 call	a20_test
      2 call	a20_enable
      3 
      4 ; Test to see if the A20 line is enabled.
      5 ; As a reference we will use the magic number 0xaa55 since we know it's always
      6 ; going to have the same value and be located at address 0x7dfe (0x7c00 + 510).
      7 ; If the return code in `ax` is 1, the A20 is enabled, and if it's 0 it's disabled.
      8 a20_test:
      9 	pusha
     10 	
     11 	mov	ax, [0x7dfe]	; 0x7c00 + 510. The magic number is there.
     12 	mov	dx, ax
     13 
     14 ; We'll try to advance 1MB in memory. If the end result hasn't wrapped up
     15 ; around zero, it means that our processor is able to access more than 1MB
     16 ; of addresses, so the A20 is enabled. Using 0x7dfe again, the expected
     17 ; address after the 1MB advance should be:
     18 ;
     19 ;	0x100000 + 0x7dfe = 0x107dfe
     20 ;
     21 ; The formula for memory segmentation is:
     22 ; 
     23 ;	address = segment * 16 + offset
     24 ;
     25 ; To find the offset, the segment will be 0xffff, so `0xffff * 16 = 0xffff0`.
     26 ; Applying the formula to calculate our offset, we have:
     27 ; 
     28 ;	0xffff0 + offset = 0x107dfe =>
     29 ;	offset = 0x107dfe - 0xffff0 =>
     30 ;	offset = 0x7e0e
     31 
     32 	push	bx
     33 	mov	bx, 0xffff
     34 	mov	es, bx		; Assign value to the segment register.
     35 	pop	bx
     36 	
     37 	mov	bx, 0x7e0e
     38 	mov	dx, [es:bx]	; If the A20 line is disabled we get 0xaa55.
     39 
     40 	cmp	ax, dx
     41 	je	cont		; If they're equal, the A20 line might be disabled.
     42 	popa
     43 	mov	ax, 0x01	; Success code 1.
     44 	ret
     45 cont:
     46 	mov	ax, [0x7dff]
     47 	mov	dx, ax
     48 
     49 	push	bx
     50 	mov	bx, 0xffff	; Make another segment.
     51 	mov	es, bx
     52 	pop	bx
     53 
     54 	mov	bx, 0x7e0f
     55 	mov	dx, [es:bx]
     56 
     57 	cmp	ax, dx		; Now it really is disabled if ax == [es:bx].
     58 	je	exit
     59 	popa
     60 	mov	ax, 0x01	; Success code 1.
     61 	ret
     62 exit:
     63 	popa
     64 	xor	ax, ax		; Error code 0.	
     65 	ret
     66 
     67 ; Enable the A20 line. We'll try enabling it using the following ways:
     68 ;	- BIOS interrupt.
     69 ;	- Keyboard controller.
     70 ;	- FastA20.
     71 a20_enable:
     72 	pusha
     73 
     74 ; BIOS interrupt.
     75 	mov	ax, 0x2401	; A20-Gate Active.
     76 	int	0x15
     77 
     78 	call	a20_test
     79 	cmp	ax, 0x01
     80 	je	a20_done
     81 	jmp	a20_fail
     82 
     83 ; Keyboard controller.
     84 	sti			; Enable interrupts.
     85 
     86 	call	a20_waitc
     87 	mov	al, 0xad	; Disable controller.
     88 	out	0x64, al	; Send data to port 0x64.
     89 	call	a20_waitc
     90 	mov	al, 0xd0	; We want to read from the controller.
     91 	out	0x64, al
     92 	
     93 	call	a20_waitd
     94 	in	al, 0x60	; Read data from port 0x60.
     95 	push	ax		; Save data.
     96 
     97 	call	a20_waitc
     98 	mov	al, 0xd1	; We want to send data.
     99 	out	0x64, al
    100 	
    101 	call	a20_waitc
    102 	pop	ax
    103 	or	al, 0x02	; Write the second bit back.
    104 	out	0x60, al	; Send data to the data port.
    105 
    106 	call	a20_waitc
    107 	mov	al, 0xae	; Enable controller.
    108 	out	0x64, al
    109 	
    110 	call	a20_waitc
    111 	sti			; Enable interrupts again.
    112 
    113 	call	a20_test
    114 	cmp	ax, 0x01
    115 	je	a20_done
    116 	jmp	a20_fail
    117 
    118 ; Wait for the keyboard controller to be available for receiving commands.
    119 a20_waitc:
    120 	in	al, 0x64	; Read from port 0x64.
    121 	test	al, 0x02	; Test the second bit.
    122 	jnz	a20_waitc		; If it's 1, it's busy.
    123 	ret
    124 ; Wait for the keyboard controller to send data back.
    125 a20_waitd:
    126 	in	al, 0x64	; Read from port 0x64 again.
    127 	test	al, 0x01	; Test the first bit.
    128 	jz	a20_waitd		; If it's 1, the data is not ready to be sent.
    129 	ret
    130 
    131 ; FastA20
    132 	in	al, 0x92	; FastA20 uses port 0x92. 
    133 	or	al, 0x02	; Mask second bit.
    134 	out	0x92, al	; Send data back to port 0x92.
    135 
    136 	call	a20_test
    137 	cmp	ax, 0x01
    138 	je	a20_done
    139 	jmp	a20_fail
    140 
    141 ; The A20 is enabled. Go on.
    142 a20_done:
    143 	popa
    144 	ret
    145 
    146 ; The A20 is disabled.
    147 a20_fail:
    148 	mov	si, str_a20_fail
    149 	call	puts
    150 	jmp	$	
    151 
    152 
    153 str_a20_fail:	db "The A20 Line is disabled", 0x0a, 0x0d, 0x00