⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 md.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
        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 + -