Like homework? Of course not.
It's just that I need to know why my test programs tell me that A20 is NOT hardwired under Bochs (it's determined by actually altering it and then putting it back as it was), and is enabled.
And then, when I try to disable it and pass control to the system, the DOS emulation under Bochs just freezes.
If not, run the following programs under Bochs DOS emulation.
The first one tells whether A20 is currently enabled or disabled.
The second one tells whether A20 is hardwired to 1 or not.
The third one turns off A20. THIS program is the one that freezes my Bochs emulation when I disable it. I'm using the default Bochs 2.3.7 for Win32 (June 3, 2008) from SourceForge, using 4MB of emulated RAM in a Pentium III at 450Mhz.
I don't know why that happens, if A20 is not hardwired in Bochs (according to the second program which actually manipulates and alters it)... and it wouldn't be good if it ever happened in a real system.
This is my BXRC configuration file:
Code:
###############################################################
# bochsrc.txt file for DLX Linux disk image.
###############################################################
# how much memory the emulated machine will have
megs: 4
# filename of ROM images
romimage: file="$BXSHARE/BIOS-bochs-latest"
vgaromimage: file="$BXSHARE/VGABIOS-lgpl-latest-cirrus"
vga: extension=cirrus
i440fxsupport: enabled=1, slot1=cirrus
# what disk images will be used
###floppya: 1_44=a:, status=inserted
floppya: 1_44="c:/win.img", status=inserted
#floppyb: 1_44=floppyb.img, status=inserted
floppyb: 1_44=a:, status=inserted
# hard disk
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
#ata0-master: type=disk, path=""$BXSHARE/dlxlinux/hd10meg.img", cylinders=306, heads=4, spt=17
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
#ata0-slave: type=cdrom, path=e:, status=inserted
# choose the boot disk.
boot: floppy
# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx
#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga
# where do we send log messages?
log: bochsout.txt
# disable the mouse, since DLX is text only
mouse: enabled=0
# enable key mapping, using US layout as default.
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so
# in the DLX Linux example I'm enabling keyboard_mapping so that paste
# will work. Cut&Paste is currently implemented on win32 and X windows only.
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map
Program 1:
Code:
bits 16
org 100h
cli
call waitUntilCommandable
mov AL, 0D0h
out 64h, AL
call waitForDataForUs
;; Read the current port status from port 60h
xor AX, AX
in AL, 60h
;; Is A20 enabled?
and al,00000010b
;; Check the result.
cmp al,0
jne _a20yes_
mov dx,a20no
jmp zzz
_a20yes_:
mov dx,a20yes
zzz:
sti
mov ah,9
int 0x21
mov ah,0x4C
int 0x21
a20yes db "Status: A20 Found Enabled.",13,10,'$'
a20no db "Status: A20 Found Disabled.",13,10,'$'
;This function waits until the
;Keybard Controller is ready to
;accept commands.
;;
;;;
waitUntilCommandable:
push ax
.waitUntilReady:
in al,0x64 ;Port 0x64 is the Status
;Register of the keyboard
;controller port located
;on the motherboard.
test al,00000010b ;We see if bit 1 of the returned
;byte at 0x64 is set to 1, which
;means that the controller is NOT
;ready to accept commands. It means
;"Input Buffer Full (port 0x60 or 0x64);
;don't write yet".
jnz .waitUntilReady ;Repeat until bit 1 of byte from
;port 0x64 is cleared to 0 or, in
;other words, until the keyboard
;controller is ready to accept
;commands. It would mean "Input
;Buffer Empty (port 0x60 or 0x64); can
;be written".
;Note that writing the Input Buffer through
;port 0x64 causes the byte to be interpreted
;as a command.
;
;And if we write the Input Buffer through
;port 0x60 causes the byte to be interpreted
;as data, usually as a parameter to an immediate
;previously sent command at port 0x64.
pop ax
ret
;This function waits until the
;Keybard Controller has a data
;byte ready for us to gather.
;;
;;;
waitForDataForUs:
push ax
.waitUntilReady:
in al,0x64 ;Port 0x64 is the Status
;Register of the keyboard
;controller port located
;on the motherboard.
test al,00000001b
jz .waitUntilReady
pop ax
ret
Program 2:
Code:
bits 16
org 100h
cli
call waitUntilCommandable
mov AL, 0D0h
out 64h, AL
call waitForDataForUs
;; Read the current port status from port 60h
xor AX, AX
in AL, 60h
mov [try1],al
;; Is A20 enabled?
and al,00000010b
;; Check the result.
cmp al,0
jne _a20yes_
call enableA20
jmp zzz
_a20yes_:
call disableA20
zzz:
call waitUntilCommandable
mov AL, 0D0h
out 64h, AL
call waitForDataForUs
;; Read the current port status from port 60h
xor AX, AX
in AL, 60h
cmp al,[try1] ;see if A20 is the same after trying to alter it
je isHardwired
mov dx,nohardwired
jmp zzz2
isHardwired:
mov dx,hardwired
zzz2:
mov al,[try1]
and al,00000010b
jnz ea20
call disableA20
jnz zzz3
ea20:
call enableA20
zzz3:
sti
mov ah,9
int 0x21
mov ah,0x4C
int 0x21
hardwired db "Status: A20 is Hardwired.",13,10,'$'
nohardwired db "Status: A20 is NOT Hardwired.",13,10,'$'
;This function waits until the
;Keybard Controller is ready to
;accept commands.
;;
;;;
waitUntilCommandable:
push ax
.waitUntilReady:
in al,0x64 ;Port 0x64 is the Status
;Register of the keyboard
;controller port located
;on the motherboard.
test al,00000010b ;We see if bit 1 of the returned
;byte at 0x64 is set to 1, which
;means that the controller is NOT
;ready to accept commands. It means
;"Input Buffer Full (port 0x60 or 0x64);
;don't write yet".
jnz .waitUntilReady ;Repeat until bit 1 of byte from
;port 0x64 is cleared to 0 or, in
;other words, until the keyboard
;controller is ready to accept
;commands. It would mean "Input
;Buffer Empty (port 0x60 or 0x64); can
;be written".
;Note that writing the Input Buffer through
;port 0x64 causes the byte to be interpreted
;as a command.
;
;And if we write the Input Buffer through
;port 0x60 causes the byte to be interpreted
;as data, usually as a parameter to an immediate
;previously sent command at port 0x64.
pop ax
ret
;This function waits until the
;Keybard Controller has a data
;byte ready for us to gather.
;;
;;;
waitForDataForUs:
push ax
.waitUntilReady:
in al,0x64 ;Port 0x64 is the Status
;Register of the keyboard
;controller port located
;on the motherboard.
test al,00000001b
jz .waitUntilReady
pop ax
ret
enableA20:
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
mov al,0xD1 ;This command is to write the
;status byte. This command is
;called WRITE OUTPUT PORT.
out 0x64,al ;Here we send the command, and
;it gets processed.
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
mov al,11111111b ;This is a data byte to serve
;as a parameter to the previous
;controller command (0xD1). We
;are setting the necessary bits
;here to the normal operation
;of the controller, and, of course,
;it is here that we enable the A20
;Address Line by setting its bit
;to 1.
;bit 0-Normal (1) or Reset CPU (0)
;bit 1-Enable A20 (1) or Disable A20 (0)
;bit 2-Data to Mouse (1) or Disabled (0)
;bit 3-Mouse Clock (1) or Disabled (0)
;bit 4-IRQ1 Active (1) or IRQ1 Inactive (0)
;bit 5-IRQ12 Active (1) or IRQ12 Inactive (0)
;bit 6-Keyboard Clock (1) or Disabled (0)
;bit 7-Data to Keyboard (1) or Disabled (0)
out 0x60,al ;We send this bit-set to the
;data port of the keyboard. At
;this point is where really the
;A20 line gets enabled.
ret
disableA20:
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
mov al,0xD1 ;This command is to write the
;status byte. This command is
;called WRITE OUTPUT PORT.
out 0x64,al ;Here we send the command, and
;it gets processed.
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
mov al,11111101b ;This is a data byte to serve
;as a parameter to the previous
;controller command (0xD1). We
;are setting the necessary bits
;here to the normal operation
;of the controller, and, of course,
;it is here that we enable the A20
;Address Line by setting its bit
;to 1.
;bit 0-Normal (1) or Reset CPU (0)
;bit 1-Enable A20 (1) or Disable A20 (0)
;bit 2-Data to Mouse (1) or Disabled (0)
;bit 3-Mouse Clock (1) or Disabled (0)
;bit 4-IRQ1 Active (1) or IRQ1 Inactive (0)
;bit 5-IRQ12 Active (1) or IRQ12 Inactive (0)
;bit 6-Keyboard Clock (1) or Disabled (0)
;bit 7-Data to Keyboard (1) or Disabled (0)
out 0x60,al ;We send this bit-set to the
;data port of the keyboard. At
;this point is where really the
;A20 line gets enabled.
ret
try1 db 0
Program 3 (trouble):
Code:
bits 16
org 100h
cli
call disableA20
sti
mov ah,0x4C
int 0x21
;This function waits until the
;Keybard Controller is ready to
;accept commands.
;;
;;;
waitUntilCommandable:
push ax
.waitUntilReady:
in al,0x64 ;Port 0x64 is the Status
;Register of the keyboard
;controller port located
;on the motherboard.
test al,00000010b ;We see if bit 1 of the returned
;byte at 0x64 is set to 1, which
;means that the controller is NOT
;ready to accept commands. It means
;"Input Buffer Full (port 0x60 or 0x64);
;don't write yet".
jnz .waitUntilReady ;Repeat until bit 1 of byte from
;port 0x64 is cleared to 0 or, in
;other words, until the keyboard
;controller is ready to accept
;commands. It would mean "Input
;Buffer Empty (port 0x60 or 0x64); can
;be written".
;Note that writing the Input Buffer through
;port 0x64 causes the byte to be interpreted
;as a command.
;
;And if we write the Input Buffer through
;port 0x60 causes the byte to be interpreted
;as data, usually as a parameter to an immediate
;previously sent command at port 0x64.
pop ax
ret
disableA20:
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
;;;Write Output Port (Command -- Step 1/2):
mov al,0xD1 ;This command is to write the
;status byte. This command is
;called WRITE OUTPUT PORT.
out 0x64,al ;Here we send the command, and
;it gets processed.
;;;Wait for controller to accept
;;;commands
;;
;
call waitUntilCommandable
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
;;;Write The Output Port (Command Parameter -- Step 2/2):
mov al,11111101b ;This is a data byte to serve
;as a parameter to the previous
;controller command (0xD1). We
;are setting the necessary bits
;here to the normal operation
;of the controller, and, of course,
;it is here that we enable the A20
;Address Line by setting its bit
;to 1.
;bit 0-Normal (1) or Reset CPU (0)
;bit 1-Enable A20 (1) or Disable A20 (0)
;bit 2-Data to Mouse (1) or Disabled (0)
;bit 3-Mouse Clock (1) or Disabled (0)
;bit 4-IRQ1 Active (1) or IRQ1 Inactive (0)
;bit 5-IRQ12 Active (1) or IRQ12 Inactive (0)
;bit 6-Keyboard Clock (1) or Disabled (0)
;bit 7-Data to Keyboard (1) or Disabled (0)
out 0x60,al ;We send this bit-set to the
;data port of the keyboard. At
;this point is where really the
;A20 line gets enabled.
ret