From f4ab972e3a2434b3a928aab01daaf7272c86fce8 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 23 Dec 2021 09:59:14 -0800 Subject: [PATCH] Update kbdinfo.asm Final round of updates to KBDINFO. Done with it for now unless there are issues. --- Source/Apps/Test/kbdinfo/kbdinfo.asm | 502 ++++++++++++++++++--------- 1 file changed, 336 insertions(+), 166 deletions(-) diff --git a/Source/Apps/Test/kbdinfo/kbdinfo.asm b/Source/Apps/Test/kbdinfo/kbdinfo.asm index fc6701c0..151db818 100644 --- a/Source/Apps/Test/kbdinfo/kbdinfo.asm +++ b/Source/Apps/Test/kbdinfo/kbdinfo.asm @@ -13,11 +13,14 @@ iocmd .equ $E3 ; keyboard controller command port address iodat .equ $E2 ; keyboard controller data port address ; +cpumhz .equ 8 ; for time delay calculations (not critical) +; ; General operational equates (should not requre adjustment) ; stksiz .equ $40 ; Working stack size ; -timeout .equ $00 ; Controller timeout constant +ltimout .equ 0 ; 256*10ms = 2.56s +stimout .equ 10 ; 10*10ms = 100ms ; restart .equ $0000 ; CP/M restart vector bdos .equ $0005 ; BDOS invocation vector @@ -36,12 +39,15 @@ bdos .equ $0005 ; BDOS invocation vector call prtstr ; call main ; do the real work + jr z,exit ; completed all tests + ld de,str_run_failed + call crlf2 + call prtstr ; exit: call crlf2 ld de,str_exit call prtstr - ;call crlf ; clean up and return to command processor call crlf ; formatting @@ -68,202 +74,307 @@ main: ld a,iodat call prthex ; +; First, we attempt to contact the controller and keyboard, then +; print the keyboard identity and scan codes scupported +; + ; Run test series with translation off + call crlf2 + ld de,str_basic + call prtstr +; + call do_basic + ret nz +; +; We make two passes through the test series with different controller +; setup values. The first time is with scan code translation off and +; the second time with it on. +; + ; Run test series with translation off + call crlf2 + ld de,str_trans_off + call prtstr +; + ld a,$20 ; xlat disabled, mouse disabled, no ints + ld (ctlr_cfgval),a + call do_tests +; + ; Run test series with translation on + call crlf2 + ld de,str_trans_on + call prtstr +; + ld a,$60 ; xlat enabled, mouse disabled, no ints + ld (ctlr_cfgval),a + call do_tests + + xor a ; signal success + ret +; +; Perform basic keyboard tests, display keyboard identity, and +; inventory the supported scan code sets. +; +do_basic: + call ctlr_test + ret nz +; + ld a,$20 ; Xlat off for this checking + call ctlr_setup + ret nz +; + call kbd_reset + ret nz +; + call kbd_ident + ;ret nz +; + ld b,3 ; Loop control, 3 scan code sets + ld c,1 ; Current scan code number +do_basic1: + ld a,c ; Scan code set to A + push bc + call kbd_setsc ; Attempt to set it + pop bc + push af ; save result + call crlf2 + ld de,str_sc_tag + call prtstr + ld a,c + call prtdecb + pop af ; restore result + ld de,str_sc_ok + jr z,do_basic2 + ld de,str_sc_fail +do_basic2: + call prtstr + inc c + djnz do_basic1 +; + xor a ; signal success + ret +; +; This routine runs a series of controller and keyboard tests. The +; desired controller setup value should be placed in ctlr_cfgval +; prior to invoking this routine. +; +do_tests: + call ctlr_test + ret nz +; + ld a,(ctlr_cfgval) + call ctlr_setup + ret nz +; + call kbd_reset + ret nz +; + call kbd_ident + ;ret nz +; + ld a,2 + call kbd_setsc + ;ret nz +; + call kbd_dispsc + ;ret nz +; + call kbd_showkeys + ;ret nz +; + xor a ; signal success + ret +; +;======================================================================= +; Keyboard/Controller Test Routines +;======================================================================= +; ; Attempt self-test command on keyboard controller ; ; Keyboard controller should respond with an 0x55 on data port ; after being sent a 0xAA on the command port. ; +ctlr_test: call crlf2 - ld de,str_ctrl_test + ld de,str_ctlr_test call prtstr ld a,$aa ; self-test command call put_cmd_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $55 ; expected value? jp nz,err_ctlr_test ; handle self-test error call crlf - ld de,str_ctrl_test_ok + ld de,str_ctlr_test_ok call prtstr + xor a + ret ; -; Disable translation on keyboard controller to get raw scan codes! -; - call crlf2 - ld de,str_trans_off - call prtstr - ld a,$60 ; write to command register 0 - call put_cmd_dbg - jp c,err_ctlr_io ; handle controller error - ld a,$20 ; xlat disabled, mouse disabled, no ints - call put_data_dbg - jp c,err_ctlr_io ; handle controller error -; -; -; - call test2 +; Keyboard controller setup ; -; Enable translation on keyboard controller +; Set keyboard controller command register to value in A ; +ctlr_setup: + push af ; save incoming value call crlf2 - ld de,str_trans_on + ld de,str_ctlr_setup call prtstr ld a,$60 ; write to command register 0 call put_cmd_dbg - jp c,err_ctlr_io ; handle controller error - ld a,$60 ; xlat disabled, mouse disabled, no ints + pop bc ; recover incoming to B + jp c,err_ctlr_to ; handle controller error + ld a,b call put_data_dbg - jp c,err_ctlr_io ; handle controller error -; - ; fall thru -; -test2: + jp c,err_ctlr_to ; handle controller error + xor a + ret ; ; Perform a keyboard reset ; +kbd_reset: call crlf2 ld de,str_kbd_reset call prtstr ld a,$ff ; Keyboard reset call put_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $FA ; Is it an ack as expected? jp nz,err_kbd_reset call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $AA ; Success? jp nz,err_kbd_reset call crlf ld de,str_kbd_reset_ok call prtstr + xor a + ret ; ; Identify keyboard ; +kbd_ident: call crlf2 ld de,str_kbd_ident call prtstr ld a,$f2 ; Identify keyboard command call put_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $FA ; Is it an ack as expected? jp nz,err_kbd_ident ; Now we need to receive 0-2 bytes. There is no way to know ; how many are coming, so we receive bytes until there is a - ; timeout error. + ; timeout error. Timeout is shortened here so that we don't + ; have to wait seconds for the routine to complete normally. + ; A short timeout is more than sufficient here. ld ix,workbuf - ld iy,workbuf_len - xor a - ld (iy),a -ident_loop: + ld a,(timeout) ; save current timeout + push af + ld a,stimout ; set a short timeout + ld (timeout),a + ld b,8 ; buf max + ld c,0 ; buf len +kbd_ident1: + push bc call get_data_dbg - jr c,ident_done + pop bc + jr c,kbd_ident2 ld (ix),a inc ix - inc (iy) - jr ident_loop -ident_done: + inc c + djnz kbd_ident1 +kbd_ident2: + pop af ; restore original timeout + ld (timeout),a call crlf ld de,str_kbd_ident_disp call prtstr ld a,'[' call prtchr ld ix,workbuf - ld b,(iy) - xor a - cp b - jr z,ident_done2 -ident_done1: + ld a,c ; bytes to print + or a ; check for zero + jr z,kbd_ident4 ; handle zero + ld b,a ; setup loop counter + jr kbd_ident3a +kbd_ident3: + ld a,',' + call prtchr +kbd_ident3a: ld a,(ix) call prthex inc ix - djnz ident_done1 -ident_done2: + djnz kbd_ident3 +kbd_ident4: ld a,']' call prtchr + xor a + ret ; -; Get active scan code set being used +; Display active scan code set being used ; +kbd_dispsc: call crlf2 ld de,str_kbd_getsc call prtstr ld a,$f0 ; Keyboard get/set scan code call put_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $FA ; Is it an ack as expected? jp nz,err_kbd_getsc ld a,$00 ; Get active scan code set call put_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error cp $FA ; Is it an ack as expected? jp nz,err_kbd_getsc call get_data_dbg - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error push af call crlf ld de,str_kbd_dispsc call prtstr pop af call prtdecb -;;;; -;;;; Set active scan code set to 2 -;;;; -;;; call crlf2 -;;; ld de,str_kbd_setsc -;;; call prtstr -;;; ld a,$f0 ; Keyboard get/set scan code -;;; call put_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; call get_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; cp $FA ; Is it an ack as expected? -;;; jp nz,err_kbd_getsc -;;; ld a,$02 ; Set scan code set to 2 -;;; call put_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; call get_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; cp $FA ; Is it an ack as expected? -;;; jp nz,err_kbd_getsc -;;;; -;;;; Get active scan code set being used -;;;; -;;; call crlf2 -;;; ld de,str_kbd_getsc -;;; call prtstr -;;; ld a,$f0 ; Keyboard get/set scan code -;;; call put_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; call get_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; cp $FA ; Is it an ack as expected? -;;; jp nz,err_kbd_getsc -;;; ld a,$00 ; Get active scan code set -;;; call put_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; call get_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; cp $FA ; Is it an ack as expected? -;;; jp nz,err_kbd_getsc -;;; call get_data_dbg -;;; jp c,err_ctlr_io ; handle controller error -;;; push af -;;; call crlf -;;; ld de,str_kbd_dispsc -;;; call prtstr -;;; pop af -;;; and $0f -;;; call prtdecb + xor a + ret +; +; Set active scan code set to value in A +; +kbd_setsc: + ld (kbd_setsc_val),a ; Save incoming value + call crlf2 + ld de,str_kbd_setsc + call prtstr + call prtdecb + ld a,$f0 ; Keyboard get/set scan code + call put_data_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $FA ; Is it an ack as expected? + jp nz,err_kbd_setsc + ld a,(kbd_setsc_val) ; Recover scan code set value + call put_data_dbg + jp c,err_ctlr_to ; handle controller error + call get_data_dbg + jp c,err_ctlr_to ; handle controller error + cp $FA ; Is it an ack as expected? + jp nz,err_kbd_setsc + xor a + ret +; +kbd_setsc_val .db 0 +; ; ; Read and display raw scan codes ; +kbd_showkeys: call crlf2 ld de,str_disp_scan_codes call prtstr @@ -272,11 +383,11 @@ read_loop: ld e,$FF ; Subfunction = read call bdos cp $1B ; Escape key? - jp z,done + ret z call check_read jr nz,read_loop call get_data - jp c,err_ctlr_io ; handle controller error + jp c,err_ctlr_to ; handle controller error push af ld a,' ' call prtchr @@ -287,9 +398,6 @@ read_loop: ld a,']' call prtchr jr read_loop - -done: - ret ; ;======================================================================= ; Keyboard Controller I/O Routines @@ -300,7 +408,8 @@ wait_write: ; Wait for keyboard controller to be ready for a write ; A=0 indicates success (ZF set) ; - ld b,timeout ; setup timeout constant + ld a,(timeout) ; setup timeout constant + ld b,a wait_write1: in a,(iocmd) ; get status ld c,a ; save status @@ -308,11 +417,11 @@ wait_write1: ret z ; 0 means ready, all done call delay ; wait a bit djnz wait_write1 ; loop until counter exhausted - ld de,str_timeout_write ; write timeout message - call crlf - call prtstr - ld a,c ; recover last status value - call prthex +; ld de,str_timeout_write ; write timeout message +; call crlf +; call prtstr +; ld a,c ; recover last status value +; call prthex or $ff ; signal error ret ; @@ -321,7 +430,8 @@ wait_read: ; Wait for keyboard controller to be ready to read a byte ; A=0 indicates success (ZF set) ; - ld b,timeout ; setup timeout constant + ld a,(timeout) ; setup timeout constant + ld b,a wait_read1: in a,(iocmd) ; get status ld c,a ; save status @@ -330,11 +440,11 @@ wait_read1: ret z ; if 0, all done call delay ; wait a bit djnz wait_read1 ; loop until counter exhausted - ld de,str_timeout_read ; write timeout message - call crlf - call prtstr - ld a,c ; recover last status value - call prthex +; ld de,str_timeout_read ; write timeout message +; call crlf +; call prtstr +; ld a,c ; recover last status value +; call prthex or $ff ; signal error ret ; @@ -368,10 +478,18 @@ put_cmd_dbg: call put_cmd ret c push af + call crlf ld de,str_put_cmd call prtstr call prthex + +; ld de,str_prefix ; " " +; call prtstr +; call prthex +; ld de,str_cmdout ; "->(CMD)" +; call prtstr + pop af ret ; @@ -395,10 +513,18 @@ put_data_dbg: call put_data ret c push af + call crlf ld de,str_put_data call prtstr call prthex + +; ld de,str_prefix ; " " +; call prtstr +; call prthex +; ld de,str_dataout ; "->(DATA)" +; call prtstr + pop af ret @@ -420,21 +546,27 @@ get_data_dbg: call get_data ret c push af + call crlf ld de,str_get_data call prtstr call prthex + +; ld de,str_datain ; " (DATA)->" +; call prtstr +; call prthex + pop af ret ; ; Error Handlers ; -err_ctlr_io: - ld de,str_err_ctrl_io +err_ctlr_to: + ld de,str_err_ctlr_to jr err_ret ; err_ctlr_test: - ld de,str_err_ctrl_test + ld de,str_err_ctlr_test jr err_ret ; err_kbd_reset: @@ -504,11 +636,25 @@ prtstr1: prtstr2: pop de ; restore registers pop af - ret + ret +; +; Print a hex value prefix "0x" +; +prthexpre: + push af + ld a,'0' + call prtchr + ld a,'x' + call prtchr + pop af + ret + ; ; Print the value in A in hex without destroying any registers ; prthex: + call prthexpre +prthex1: push af ; save AF push de ; save DE call hexascii ; convert value in A to hex chars in DE @@ -523,24 +669,27 @@ prthex: ; print the hex word value in hl ; prthexword: + call prthexpre +prthexword1: push af ld a,h - call prthex + call prthex1 ld a,l - call prthex + call prthex1 pop af ret ; ; print the hex dword value in de:hl ; prthex32: + call prthexpre push bc push de pop bc - call prthexword + call prthexword1 push hl pop bc - call prthexword + call prthexword1 pop bc ret ; @@ -630,58 +779,74 @@ crlf: pop af ; restore AF ret ; -; Brief delay +; Delay ~10ms ; delay: - push bc - ld b,0 + push af + push de + ld de,625 ; 10000us/16us +delay0: + ld a,(cpuscl) delay1: - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - ex (sp),hl - djnz delay1 - pop bc + dec a + jr nz,delay1 + dec de + ld a,d + or e + jp nz,delay0 + pop de + pop af ret ; +; +; ;======================================================================= ; Constants ;======================================================================= ; -str_banner .db "Keyboard Information, v0.1",0 -str_exit .db "Done, Thank you for using KBDINFO!",0 -str_cmdport .db "Keyboard Controller Command Port: 0x",0 -str_dataport .db "Keyboard Controller Data Port: 0x",0 -str_timeout_write .db "Keyboard Controller Write Timeout, Status: 0x",0 -str_timeout_read .db "Keyboard Controller Read Timeout, Status: 0x",0 -str_err_ctrl_io .db "Keyboard Controller I/O Failure",0 -str_err_ctrl_test .db "Keyboard Controller Self-Test Failed",0 -str_put_cmd .db "Sent Command 0x",0 -str_put_data .db "Sent Data 0x",0 -str_get_data .db "Got Data 0x",0 -str_ctrl_test .db "Attempting Controller Self-Test",0 -str_ctrl_test_ok .db "Controller Self-Test OK",0 -str_trans_off .db "Disabling Controller Translation",0 -str_trans_on .db "Enabling Controller Translation",0 +str_banner .db "Keyboard Information v0.2, 23-Dec-2021",0 +str_exit .db "Done, Thank you for using Keyboard Information!",0 +str_cmdport .db "Keyboard Controller Command Port: ",0 +str_dataport .db "Keyboard Controller Data Port: ",0 +;str_prefix .db " ",0 +;str_cmdout .db "->(CMD)",0 +;str_dataout .db "->(DATA)",0 +;str_datain .db " (DATA)->",0 +;str_timeout_write .db "Keyboard Controller Write Timeout, Status: ",0 +;str_timeout_read .db "Keyboard Controller Read Timeout, Status: ",0 +str_err_ctlr_to .db "Keyboard Controller I/O Timeout",0 +str_err_ctlr_test .db "Keyboard Controller Self-Test Failed",0 +str_put_cmd .db " Sent Command ",0 +str_put_data .db " Sent Data ",0 +str_get_data .db " Got Data ",0 +str_ctlr_test .db "Attempting Controller Self-Test",0 +str_ctlr_test_ok .db "Controller Self-Test OK",0 +str_ctlr_setup .db "Performing Controller Setup",0 +str_basic .db "***** Basic Keyboard Checks and Scan Code Inventory *****",0 +str_trans_off .db "***** Testing with Scan Code Translation DISABLED *****",0 +str_trans_on .db "***** Testing with Scan Code Translation ENABLED *****",0 str_kbd_reset .db "Attempting Keyboard Reset",0 str_kbd_reset_ok .db "Keyboard Reset OK",0 str_err_kbd_reset .db "Keyboard Reset Failed",0 - str_kbd_getsc .db "Requesting Active Scan Code Set from Keyboard",0 -str_kbd_dispsc .db "Active Keyboard Scan Code Set is ",0 -str_err_kbd_getsc .db "Error getting active keyboard scan code set",0 -str_kbd_setsc .db "Setting Active Keyboard Scan Code Set",0 -str_err_kbd_setsc .db "Error setting keyboard scan code set",0 +str_kbd_dispsc .db "Active Keyboard Scan Code Set is #",0 +str_err_kbd_getsc .db "Error getting Active Keyboard Scan Code Set",0 +str_kbd_setsc .db "Setting Active Keyboard Scan Code Set to #",0 +str_err_kbd_setsc .db "Error setting Active Keyboard Scan Code Set",0 str_kbd_ident .db "Keyboard Identification",0 -str_kbd_ident_disp .db "Keyboard Identify: ",0 +str_kbd_ident_disp .db "Keyboard Identity: ",0 +str_sc_tag .db "Scan Code Set #",0 +str_sc_ok .db " IS supported",0 +str_sc_fail .db " IS NOT supported",0 str_err_kbd_ident .db "Error performing Keyboard Identification",0 str_disp_scan_codes .db "Displaying Raw Scan Codes",13,10 - .db " Press keys on keyboard to display scan codes",13,10 + .db " Press keys on test keyboard to display scan codes",13,10 .db " Press on CP/M console to end",13,10,13,10,0 +str_run_failed .db "***** HARDWARE ERROR *****",13,10,13,10 + .db "A basic hardware or configuration issue prevented",13,10 + .db "Keyboard Information from completing the full set",13,10 + .db "of tests. Check your hardware and verify the port",13,10 + .db "addresses being used for the keyboard controller",0 ; ;======================================================================= ; Working data @@ -694,6 +859,11 @@ stack .equ $ ; stack top workbuf .fill 8 workbuf_len .db 0 ; +ctlr_cfgval .db 0 ; Value for controller cmd reg 0 +; +cpuscl .db cpumhz - 2 +timeout .db ltimout +; ;======================================================================= ; .end \ No newline at end of file