📄 md.asm
字号:
mov ax,LT_PS2MOUSE ; Set the mouse type in AL
jmp short tfp_leave
tfp_CheckForMS:
test [fSingle8259],0FFh ; Does machine have only 1 8259A?
jnz tfp_no_mouse ; Yes - impossible to have PS/2 mouse.
call CheckForAuxSupport ; Does machine support an aux device?
jc tfp_leave ; Nope - impossible to have PS/2 mouse.
call MouseIntOff ; Disable mouse and mouse interrupts.
call CheckForMSMouse ; Is Microsoft mouse attached?
; If so, will be reset.
jmp short tfp_leave
tfp_no_mouse:
stc ; Show that we failed.
tfp_leave:
ret ; Carry set/clear appropriately.
TestForPS2 ENDP
;*****************************************************************************
;
; CheckForAuxSupport
;
; This procedure will determine if the 8042 supports an auxiliary device.
;
; Note that this procedure will always leave with the keyboard enabled.
;
; ENTRY Keyboard enabled.
;
; EXIT Carry clear The 8042 supports an auxiliary device
; Interrupts enabled.
; Aux device disabled.
;
; Carry set The 8042 does not support an auxiliary device
; Interrupts enabled.
;
; ALTERS AX, BX, CX, DX, DI, ES
;
; CALLS Read8042CommandByte, WriteControlRegister
;
CheckForAuxSupport PROC NEAR
mov al,CMD8042_DISABLE_AUX ; Disable the auxiliary device.
call WriteControlRegister
jc cfas_leave ; Leave if error.
; INTERRUPTS DISABLED!!
mov al,CMD8042_DISABLE_KBD ; Disable the keyboard.
call WriteControlRegister
jc cfas_leave ; Leave if error.
; INTERRUPTS DISABLED!!
; We have to disable the keyboard interrupt here. This is because when the
; 8042 returns the status from the Test Auxiliary Device command,
; it asserts IRQ 1. We can't just disable interrupts entirely, otherwise
; we cannot time ourselves off of the system clock, so we have to do it
; this way.
in al,MASTER_MASK_ADDR ; Read interrrupt mask.
IOdelay
push ax ; Save mask read in.
or al,00000010b ; Mask keyboard interrupt.
out MASTER_MASK_ADDR,al ; Write out changed mask.
IOdelay
call Read8042CommandByte ; Read the 8042 command byte.
; INTERRUPTS ENABLED!!
jc cfas_no_support ; Leave if error.
test al,AUX_DISABLED ; If the auxiliary device isn't
jz cfas_no_support ; disabled, we don't have aux support.
;
; It is still possible that the 8042 supports an auxiliary device. We
; now issue the 8042 command to test the auxiliary interface. This
; command only exists on 8042s that support an auxiliary device. If the
; test succeeds, a 00h will be placed in the 8042's output buffer. If no
; output appears in the 8042's output buffer, it is assumed that the
; 8042 does not support an auxiliary device.
;
; WARNING!!! The testing of the auxiliary interface will more than likely
; screw up an auxiliary device attached to it. Therefore, the auxiliary
; device should be initialized after calling this procedure.
;
mov al,CMD8042_TEST_AUX ; Command to test the auxiliary
call WriteControlRegister ; interface.
jc cfas_no_support ; Leave if error.
; INTERRUPTS DISABLED!!
mov cx,0ah ; We will wait half a second.
call SetupForWait ; BX:CX has ending time, ES:DI points
; at current time.
sti ; Make sure interrupts are enabled so
; timer ticks can get in.
xor dx,dx ; Clear byte read flag.
cfas_read_test_results:
in al,STATUS_8042 ; Get 8042's current status.
test al,I_FULL ; Wait for 8042 to remove the command
jnz cfas_is_wait_over ; from its input buffer.
test al,O_FULL ; Is there an output byte yet?
jz cfas_is_wait_over ; Nope, check if wait is over.
in al,DATA_8042 ; Read byte from 8042.
or dx,dx ; Have we read a byte yet?
jnz cfas_is_wait_over ; Yes, ignore this byte.
mov ah,al ; Save first byte read in.
inc dx ; Show that a byte was read.
cfas_is_wait_over:
call IsWaitOver ; Has interval expired?
jnc cfas_read_test_results ; Nope, keep looking.
or dx,dx ; Did we get a byte?
jz cfas_no_support ; Nope, no auxiliary device.
or ah,ah ; Was the byte we got 0?
jz cfas_clean_up ; Yes, return with carry clear.
cfas_no_support:
stc ; Show no aux device is supported.
cfas_clean_up: ; Carry clear/set appropriately.
pop ax ; Restore saved interrupt mask.
sti ; Interrupts are reenabled.
pushf ; Save result in carry.
cli ; Interrupts off for mask update.
mov ah,al ; Put it in AH.
in al,MASTER_MASK_ADDR ; Read in current mask.
IOdelay
and ax,0000001011111101b ; Unmask keyboard interrupt.
or al,ah ; Move in original state of keyboard.
out MASTER_MASK_ADDR,al ; Write out changed mask.
cfas_reenable_kbd:
mov al,CMD8042_ENABLE_KBD ; Reenable the keyboard.
call WriteControlRegister
jc cfas_reenable_kbd ; Make sure we reenable the keyboard!!
; INTERRUPTS DISABLED!!
popf ; Restore result and interrupts.
; INTERRUPTS ENABLED!!
cfas_leave:
ret
CheckForAuxSupport ENDP
;*****************************************************************************
;
; Read8042CommandByte
;
; This procedure will try to read the 8042's command byte.
;
; Note that this procedure should only be called if both the keyboard
; and auxiliary devices are disabled.
;
; ENTRY none
;
; EXIT Carry clear Command byte was read successfully
; AL Command byte
; Interrupts enabled
;
; Carry set Command byte couldn't be read
; Interrupts enabled
;
; ALTERS AL
;
; CALLS WriteControlRegister
;
Read8042CommandByte PROC NEAR
mov al,CMD8042_READ_CMD ; Tell 8042 that we want to read the
call WriteControlRegister ; command byte.
jc r8cb_leave ; Leave if error.
; INTERRUPTS DISABLED!
push cx ; Save register.
mov cx,400h ; Short delay because ints are off.
r8cb_loop:
in al,STATUS_8042 ; Get current status of 8042.
test al,O_FULL ; Is there data in the output buffer?
jnz r8cb_got_data ; Yes! Go and read it.
loop r8cb_loop ; Keep trying.
stc ; Show failure.
jmp short r8cb_leave2
r8cb_got_data: ; Carry is clear!
in al,DATA_8042 ; Get 8042's command byte.
r8cb_leave2:
pop cx ; Restore register.
IOdelay ; Make sure interrupt is cleared.
sti ; Reenable interrupts.
; INTERRUPTS ENABLED!
r8cb_leave: ; Carry set/clear appropriately.
ret
Read8042CommandByte ENDP
;*****************************************************************************
;
; Write8042CommandByte
;
; This procedure sets the 8042's command byte to the value given.
;
; ENTRY AL Value to set the command byte to
;
; EXIT Carry clear Command byte was set
; Interrupts enabled
;
; Carry set Command byte couldn't be set
; Interrupts enabled
;
; ALTERS none
;
; CALLS WriteControlRegister, WriteInputBuffer
;
Write8042CommandByte PROC NEAR
push ax ; Save value passed in.
mov al,CMD8042_WRITE_CMD ; Tell 8042 that we want to write the
call WriteControlRegister ; command byte.
jc w8cb_leave ; Leave if we have an error.
; INTERRUPTS DISABLED!
pop ax ; Restore value.
call WriteInputBuffer ; Send it to 8042.
; INTERRUPTS ENABLED!
jc Write8042CommandByte ; Retry if unsuccessful.
w8cb_leave: ; Carry set/clear appropriately.
ret
Write8042CommandByte ENDP
;*****************************************************************************
;
; WriteInputBuffer
;
; This procedure sends a byte of data to the 8042's input buffer. It
; should not be called unless the 8042 has already been set up to
; expect this byte of data.
;
; Note that interrupts should be disabled from the time that the command
; is sent to the 8042 until the time that the data byte is
; actually written.
;
; ENTRY AL Byte of data to be sent.
; Interrupts disabled
;
; EXIT Carry clear Byte of data has been sent to the 8042.
; Interrupts enabled
;
; Carry set Byte of data could not be sent to the 8042.
; Interrupts enabled
;
; ALTERS none
;
; CALLS none
;
WriteInputBuffer PROC NEAR
;
; Upon entry, it is assumed that a command has just been sent to the
; 8042. Therefore, we will wait until the 8042 has removed the command
; byte from its input buffer before doing anything else.
;
; Note that because interrupts are disabled at this time, we will only
; wait a short while before timing out.
;
push cx ; Save registers that we use
push ax
mov cx,400h ; Short delay
wib_wait:
in al,STATUS_8042 ; Get 8042's current status.
test al,I_FULL ; Is the input buffer still full?
jz wib_check_output ; Nope - can now test for output.
loop wib_wait ; Keep waiting.
jmp short wib_failure ; Timed out - return with failure.
wib_check_output:
and al,O_FULL + A_FULL ; Keep output and aux buffer bits.
cmp al,O_FULL ; Output buffer contain keybd data?
jne wib_check_aux_data ; Nope - check for aux data.
wib_failure:
pop ax ; Restore saved data byte.
stc ; Show failure.
jmp short wib_leave ; Return to caller
wib_check_aux_data:
cmp al,O_FULL + A_FULL ; Output buffer contain aux data?
jne wib_success ; Nope, can just send data byte.
in al,DATA_8042 ; Yup - read and discard data.
wib_success: ; Input and output buffers are empty.
pop ax ; Get saved data byte.
out DATA_8042,al ; Send data byte.
clc ; Show success.
wib_leave:
pop cx ; Restore register.
sti ; Reenable interrupts.
ret
WriteInputBuffer ENDP
;*****************************************************************************
;
; WriteControlRegister
;
; This procedure will send a command byte to the 8042's control register.
; Note that nothing will be sent as long as the 8042's input or
; output buffer is full.
;
; Note that only 15*64K attempts will be made before timing out.
;
; ENTRY AL Command byte to be sent
;
; EXIT Carry clear Byte was written to 8042 successfully
; Interrupts disabled
;
; Carry set Byte could not be written to 8042
; Interrupts enabled
;
; ALTERS none
;
; CALLS none
;
WriteControlRegister PROC NEAR
push cx ; Save registers we use.
push ax
mov ah,15 ; Set up for looping 15*64K times.
xor cx,cx
;
; At this point, we wait until the input and output buffers are empty.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -