?? ps2main.asm
字號:
;========================================================================
; FILE: ps2main.asm
;
; This file contains the code that implements the ps2 interface to the
; host.
;
;REVISION_HISTORY:
;
;3/26/99 replaced command processor jump table "calls" with "jmps"
;
;2/10/99 Added XPAGEOFF,XPAGEON around command processor jump table
;
;8/25/98 Added a 250 usec delay after the reception of a RESET command but
;prior to the ACK of the command. Some PC's did not like it without this delay.
;
;6/16/99 alpha bug repairs
;
;========================================================================
XPAGEON
;========================================================================
; FUNCTION: ps2_do_command
;
; host command processor switch statement
;
; Returns: nothing
;========================================================================
ps2_do_command:
call ps2_xmt_flush ;new command cancels any pending transmission
cmp A,0f3h ;check for possible id command sequence
jz ps2_start_command
push A ;not part of id sequence,
mov A,ID_TABLE_LEN-1 ;reset id sequence state variable
mov [ps2_id_state],A
pop A
ps2_start_command:
sub A,0EDh ;subtract off base of command
jc ps2_invalid_command ;whoops, bad command
mov X,A ;else save zero-based command in X
mov A,X ;get back zero-based command
rlc ;prepare for case jump
;to proper routine
jacc switch
XPAGEOFF
switch:
jmp ps2_set_status_indicators
jmp ps2_echo_enable
jmp ps2_invalid_command
jmp ps2_select_alternate_scan_code
jmp ps2_invalid_command
jmp ps2_read_id
jmp ps2_set_typematic_rate_delay
jmp ps2_enable
jmp ps2_default_disable
jmp ps2_set_default
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_invalid_command
jmp ps2_resend
jmp ps2_reset
XPAGEON
endswitch:
ret
;-------------------------------------------------------------------------
; PS2 Initialization ( BAT, FLAG, ... )
;-------------------------------------------------------------------------
PS2_Init:
; PUSH A
MOV A, [p3_shadow]
; OR A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT) ;Keep PS2_CONNECT and PS2_CLOCK high
AND A, ~(PS2_DATA_BIT)
MOV [p3_shadow], A
iowr PS2_PORT
;clear variables local to this module
mov A,0
mov [dual_ifc_1ms],A
mov A,ID_TABLE_LEN-1 ;reset id sequence state variable
mov [ps2_id_state],A
call ksc_init_keyscan ;initialize the key scanner
call ps2key_init ;and ps2-specific key scanning routines
mov A,PS2_KEYBOARD
mov [dual_ifc_keyboard],A
; PS2 BAT
DI
mov A,178
mov [ps2_delay],A ;set up BAT timeout to 356 msec
;(contents of ps2_delay * 2)
EI
call ps2_BAT ;test the system
call ps2_put_byte ;queue BAT result for transmission
SETBIT PS2_SCAN_KBD,ps2_flags ;enable scanning
mov A,PS2_SCAN_INTERVAL ;initialize scan timer
mov [ps2_scan_timeout],A
mov A,PS2_SEND_INTERVAL ;init transmission timer
mov [ps2_send_timeout],a
; POP A
RET
;========================================================================
; FUNCTION: ps2_wait_byte
;
;
; waits for reception of a byte from the host. This is called to get
; extra bytes in a command from the host. While the byte is waited for,
; the idle loop is called to keep other tasks going.
;
; Returns: A: received byte from host
; C: 1
;
;
;========================================================================
ps2_wait_byte:
call ps2_idle_loop ;operate the transmitter if necessary
call ps2_get_byte ;see if host has sent us something
jnc ps2_wait_byte ;no, continue to wait
ret ;yes, return with carry set
;========================================================================
; FUNCTION: ps2_get_byte
;
;
; tries to get a byte from the host
;
; Returns: A: received byte from host
; C: 1 if A is valid, 0 if no byte received
;
;========================================================================
ps2_get_byte:
iord PS2_PORT ;if host inhibit condition,
and A,PS2_CLOCK_BIT
jz .no ;skip this whole operation
iord PS2_PORT ;if no start bit
and A,PS2_DATA_BIT ;skip too
jnz .no
iord PS2_PORT ;check for inhibit again
and A,PS2_CLOCK_BIT
jz .no
call ps2_xmt_flush ;received byte flushes xmit buffer
IFDEF CombiKB
DI
ENDIF
call ps2_receive ;receive a byte
IFDEF CombiKB
EI
ENDIF
jc .no1 ;branch on receive error
SETC ;else, set carry and exit
ret
.no1: ;something went awry - request a resend
mov A,PS2_RSND ;queue a resend
call ps2_put_byte
.no:
CLEARC ;indicate nothing gotten, gained
ret
;========================================================================
; FUNCTION: ps2_idle_loop
;
; the idle loop does the things that must be done during times when nothing
; else is happening.
;
; Returns: nothing
;========================================================================
ps2_idle_loop:
; iowr WATCHDOG_REG
TSTBIT PS2_1MS,ps2_flags ;1mS tick?
jz .pi2 ;branch if not
;* service 1mS tick counters
CLRBIT PS2_1MS,ps2_flags ;else, clear it
dec [ps2_scan_timeout] ;decrement scan time counter
jnc .pi1 ;branch if not underflow
inc [ps2_scan_timeout] ;don't let it underflow
.pi1: dec [ps2_send_timeout] ;decrement key send timer
jnc .pi2 ;branch if no underflow
inc [ps2_send_timeout] ;don't let it underflow
.pi2:
call ps2_send_byte ;send anything that may be queued
ret ;that is it
;========================================================================
; FUNCTION: ps2_invalid_command
;
; handles invalid commands
;
;
; Returns:
; C = 0 for success
;========================================================================
ps2_invalid_command:
mov A,PS2_RSND ;ask for a resend
call ps2_put_byte
ret
;========================================================================
; FUNCTION: ps2_set_status_indicators
;
; sets indicator leds
;
; Returns:
;
; C: 0 if command was sucessful
; C: 1 if command failed
;
;========================================================================
ps2_set_status_indicators:
call ps2_ack_byte ;ack this command
.ed00:
call ps2_wait_byte ;wait for 2nd byte
cmp A,0EDh ;is it another command?
jnc ps2_start_command ;yes, go process it
cmp A,8 ;if 2nd byte invalid
jc .ed0
call ps2_invalid_command ;tell the host and
jmp .ed00 ;wait for another try
.ed0: ;else
and A,7 ;mask off all but 3 ls bits
index ps2_led_tbl ;use translation table
push A ;save it
call ksc_writeLED ;write the leds
pop A ;get it back
and A,NUM_LOCK_LED ;save state of numlock
mov [ps2key_numlock],A ;locally
call ps2_ack_byte ;ack this byte too
jmp endswitch
;table to translate ps2-command enumeration of leds into our own bits
XPAGEOFF
ps2_led_tbl:
db 0
db SCROLL_LOCK_LED
db NUM_LOCK_LED
db SCROLL_LOCK_LED + NUM_LOCK_LED
db CAPS_LOCK_LED
db CAPS_LOCK_LED + SCROLL_LOCK_LED
db CAPS_LOCK_LED + NUM_LOCK_LED
db CAPS_LOCK_LED + NUM_LOCK_LED + SCROLL_LOCK_LED
XPAGEON
;========================================================================
;
; FUNCTION: ps2_echo_enable -- burps back an echo byte
;
; Returns:
;
; C: 0 command can't fail
;========================================================================
ps2_echo_enable:
mov A,PS2_ECHO ;send echo response
call ps2_put_byte ;and respond
jmp endswitch
;========================================================================
; FUNCTION: ps2_select_alternate_scan_code
;
; Returns:
;
; C: 0 if command was sucessful
; C: 1 if command failed
;========================================================================
ps2_select_alternate_scan_code:
call ps2_ack_byte ;ack this byte
.sas00:
call ps2_wait_byte ;wait for alternate code byte
cmp A,0EDh ;is it another command?
jnc ps2_start_command ;yes, go process it
cmp A,3 ;if not out of range
jc .sas0 ;keep going
call ps2_invalid_command ;else tell the host and
jmp .sas00 ;wait for another try
.sas0:
call ps2key_clear_key_buffer ;clear out buffer and stop any typematic stuff
call ps2key_disable_typematic_action
or A,0 ;else if 1-2
jz .send
mov [ps2key_scan_set],A ; save it
call ps2_ack_byte ; ack the byte
jmp .exit
.send: ;else, a 0 indicates to send back current scan set
call ps2_ack_byte ;ack the byte
mov A,[ps2key_scan_set] ;return current scan set
call ps2_put_byte
.exit:
jmp endswitch
;========================================================================
; FUNCTION: ps2_read_id
;
;
; Returns:
; C: 0, command can't fail
;========================================================================
ps2_read_id:
call ps2_ack_byte ;ack the byte
mov A,0abh ;respond with hard coded id bytes
call ps2_put_byte
mov A,83h
call ps2_put_byte
;special case! wait for both of these bytes to be sent.
.loop:
call ps2_idle_loop
TSTBIT PS2_XMIT,ps2_flags ;wait for these to go out
jnz .loop
call ps2key_clear_key_buffer ;clear the key buffer
SETBIT PS2_SCAN_KBD,ps2_flags ;enable scanning
.exit:
jmp endswitch
;========================================================================
; FUNCTION: ps2_set_typematic_rate_delay
;
; sets the global typematic rate and delay settings.
; this routine uses 2 lookups to convert the values sent by the host,
; into the proper 4ms counts that will be used to achieve the rate and delay
; functions. the rate table was derived from an excel spreadsheet rate.xls;
; the shorter delay table was derived by hand
;
; Returns:
;
; C: 0 if command was sucessful
; C: 1 if command failed
;
;========================================================================
XPAGEOFF
ps2_typematic_rate_table: ;table of 4ms counts to achieve rate
db 8,9,10,11,14,14,15,16
db 17,19,21,23,25,27,29,31
db 33,38,42,46,50,54,58,63
db 67,75,83,92,100,108,117,125
ps2_typematic_delay_table: ;table of 4ms counts to achieve delay
db 62,125,187,250
XPAGEON
ps2_set_typematic_rate_delay:
call ps2_ack_byte ;ack the byte
.strd0:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -