169 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| .code16
 | |
| .section .stage2
 | |
| 
 | |
| # checks whether A20 line is enabled or disabled
 | |
| # return
 | |
| #	ax: 1 if enabled, 0 otherwise
 | |
| check_a20:
 | |
| 	pushf
 | |
| 	pushw %si
 | |
| 	pushw %di
 | |
| 	pushw %ds
 | |
| 	pushw %es
 | |
| 
 | |
| 	cli
 | |
| 
 | |
| 	xorw %ax, %ax
 | |
| 	movw %ax, %es
 | |
| 	notw %ax
 | |
| 	movw %ax, %ds
 | |
| 
 | |
| 	movw $0x0500, %di
 | |
| 	movw $0x0510, %si
 | |
| 
 | |
| 	movb %es:(%di), %al
 | |
| 	pushw %ax
 | |
| 
 | |
| 	movb %ds:(%si), %al
 | |
| 	pushw %ax
 | |
| 
 | |
| 	movb $0x00, %es:(%di)
 | |
| 	movb $0xFF, %ds:(%si)
 | |
| 
 | |
| 	cmpb $0xFF, %es:(%di)
 | |
| 
 | |
| 	pop %ax
 | |
| 	movb %al, %ds:(%si)
 | |
| 
 | |
| 	pop %ax
 | |
| 	movb %al, %es:(%di)
 | |
| 
 | |
| 	movw $0, %ax
 | |
| 	je .check_a20_done
 | |
| 
 | |
| 	movw $1, %ax
 | |
| 
 | |
|  .check_a20_done:
 | |
| 	popw %es
 | |
| 	popw %ds
 | |
| 	popw %di
 | |
| 	popw %si
 | |
| 	popf
 | |
| 	ret
 | |
| 
 | |
| 
 | |
| # Try to enable A20 using PS2 controller
 | |
| enable_a20_ps2:
 | |
| 	pushf
 | |
| 	pushw %ax
 | |
| 
 | |
| 	cli
 | |
| 
 | |
| 	# disable first port
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 	movb $0xAD, %al
 | |
| 	outb %al, $0x64
 | |
| 
 | |
| 	# read controller output
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 	movb $0xD0, %al
 | |
| 	outb %al, $0x64
 | |
| 
 | |
| 	call .enable_a20_ps2_wait2
 | |
| 	inb $0x60, %al
 | |
| 	pushw %ax
 | |
| 
 | |
| 	# write controller output
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 	movb $0xD1, %al
 | |
| 	outb %al, $0x64
 | |
| 
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 	popw %ax
 | |
| 	orw $2, %ax
 | |
| 	outb %al, $0x60
 | |
| 
 | |
| 	# enable first port
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 	movb $0xAE, %al
 | |
| 	outb %al, $0x64
 | |
| 
 | |
| 	call .enable_a20_ps2_wait1
 | |
| 
 | |
| 	popw %ax
 | |
| 	popf
 | |
| 	ret
 | |
| 
 | |
|  .enable_a20_ps2_wait1:
 | |
| 	inb $0x64, %al
 | |
| 	test $2, %al
 | |
| 	jnz .enable_a20_ps2_wait1
 | |
| 	ret
 | |
| 
 | |
|  .enable_a20_ps2_wait2:
 | |
| 	inb $0x64, %al
 | |
| 	test $1, %al
 | |
| 	jnz .enable_a20_ps2_wait1
 | |
| 	ret
 | |
| 
 | |
| 
 | |
| # Check if A20 line is disabled. If it is, try to enable it
 | |
| .global enable_a20
 | |
| enable_a20:
 | |
| 	pushw %ax
 | |
| 	pushw %si
 | |
| 
 | |
| 	call check_a20
 | |
| 	testw %ax, %ax
 | |
| 	jnz .enable_a20_done
 | |
| 
 | |
| 	movw $a20_line_disabled_msg, %si
 | |
| 	call puts; call print_newline
 | |
| 
 | |
| 	# Try to enable A20 line using bios interrupt
 | |
| 	movw $0x2401, %ax
 | |
| 	int $0x15
 | |
| 	call check_a20
 | |
| 	testw %ax, %ax
 | |
| 	jnz .enable_a20_done
 | |
| 
 | |
| 	# Try to enable A20 line using ps2 controller
 | |
| 	call enable_a20_ps2
 | |
| 	call check_a20
 | |
| 	testw %ax, %ax
 | |
| 	jnz .enable_a20_done
 | |
| 
 | |
| 	# Try to enable A20 line using fast A20 gate
 | |
| 	inb $0x92, %al
 | |
| 	testb $2, %al
 | |
| 	jnz .enable_a20_fast_done
 | |
| 	orb $2, %al
 | |
| 	outb %al, $0x92
 | |
|  .enable_a20_fast_done:
 | |
| 
 | |
| 	call check_a20
 | |
| 	testw %ax, %ax
 | |
| 	jnz .enable_a20_done
 | |
| 
 | |
| 	movw $a20_could_not_enable_msg, %si
 | |
| 	call print_and_halt
 | |
| 
 | |
|  .enable_a20_done:
 | |
| 	movw $a20_line_enabled_msg, %si
 | |
| 	call puts; call print_newline
 | |
| 
 | |
| 	popw %si
 | |
| 	popw %ax
 | |
| 	ret
 | |
| 
 | |
| .section .data
 | |
| 
 | |
| a20_line_disabled_msg:
 | |
| 	.asciz "A20 line disabled. Trying to enable it"
 | |
| 
 | |
| a20_line_enabled_msg:
 | |
| 	.asciz "A20 line enabled"
 | |
| 
 | |
| a20_could_not_enable_msg:
 | |
| 	.asciz "Could not enable A20 line"
 |