; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > KbdResPC ; This file contains the minimal PC keyboard control stuff that the kernel does on reset. ; The only two hooks in this file used externally are IRQ_Test_CTRL_or_R_Pressed ; and SetUpKbd. ; For now, use development podule in slot 0. [ IO_Type = "IOMD" IOBase * IOMD_Base IOData * IOCSERTX IOStatus * IOMD_KBDCR IOControl * IOMD_KBDCR stat_RXF * IOMD_KBDCR_RxF stat_TXE * IOMD_KBDCR_TxE ctl_Enable * IOMD_KBDCR_Enable ctl_EnableIRQ * 0 ; not needed on IOMD | IOBase * &03000000 IOData * 0 IOStatus * 4 IOControl * 4 stat_RXF * &20 stat_TXE * &80 ctl_Enable * &08 ctl_EnableIRQ * &80 ] ; PC keyboard codes we are interested in. PCReset * &AA PCSpecial * &E0 PCCTRLL * &14 PCCTRLR * &14 ; Preceded by &E0 PCSHIFTL * &12 PCSHIFTR * &59 PCR * &2D PCT * &2C PCDelete * &71 ; Preceded by &E0 PCEnd * &69 ; Preceded by &E0 KeyData DCB PCCTRLL, CTRL_Down_Flag DCB PCSHIFTL, SHIFT_Down_Flag DCB PCSHIFTR, SHIFT_Down_Flag DCB PCR, R_Down_Flag DCB PCT, T_Down_Flag DCB 0 ALIGN SpecialData DCB PCCTRLR, CTRL_Down_Flag DCB PCDelete, Del_Down_Flag DCB PCEnd, Copy_Down_Flag DCB 0 ALIGN ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ [ 1 = 1 SetUpKbd MOV r0, #IOBase [ MorrisSupport LDRB R1, [R0, #IOMD_ID0] ;Are we running on Medusa CMP R1, #&E7 LDRB R1, [R0, #IOMD_ID1] CMPEQ R1, #&D4 BEQ %FT30 ;EQ: yes, it is IOMD, so only one PS2 port [ 1 = 1 ; ; Addresses and bit meanings for the Stork keyboard/battery-manager controller ; uC_Base EQU &302B800 uC_DataRxReg EQU uC_Base ;Read only uC_KeyDataTxReg EQU uC_Base ;Write only uC_StatusReg EQU uC_Base + 4 ;Read only ;Status register bits uC_Status_IBF EQU 1 :SHL: 0 ;Set data waiting in DataRxReg uC_Status_OBF EQU 1 :SHL: 1 ; ; ; On Kryten, Morris pin Event2 is tied low so bit Nevent2 is a ONE ; On Stork, Morris pin Event2 is tied high so bit Nevent2 is a ZERO ; ;MOV r0, #IOBase LDRB R1, [R0, #IOMD_IRQSTD] TST R1, #IOMD_Nevent2_bit BNE %FT35 ;NE: Not Stork, so two PS2 ports ;EQ, Stork ; ; Must ensure external keyboard and mouse are selected and powered ; LDR r0, =HWLatchPB MOV r1, #InitLatchPB STRB r1, [r0] MOV r0, #IOBase LDR R0, =uC_StatusReg ;Get Tx buffer status bit 25 ; LDRB R1, [R0] ; TST R1, #uC_Status_OBF ; BNE %BT25 ;Loop until buffer empties MOV R1, #&FF ;EQ: port ready, so send 'reset' command LDR R0, =uC_KeyDataTxReg STRB R1, [R0] ;Write byte to keyboard MOV R0, #IOBase ;Enable Ints from Storks keyboard/battery MOV R1, #IOMD_Network_IRQ_bit ; manager STRB R1, [R0, #IOCIRQMSKB] MOV R0, #InitKbdWs MOV R1, #4 STRB R1, [R0, #Port3Present] 35 ] MOV r0, #IOBase MOV R1, #IOMD_MSECR_Enable ;initialise 2nd PS2 (mouse) port cos STRB R1, [R0, #IOMD_MSECR] ;keyboard may be connected there 20 LDRB R1, [R0, #IOMD_MSECR] TST R1, #IOMD_MSECR_TxE ;Is port ready to accept data MOVNE R1, #&FF ;NE: port ready, so send 'reset' command STRNEB R1, [R0, #IOMD_MSEDAT] ; BEQ %BT20 ;EQ: loop til port ready MOV R1, #IOMD_MouseRxFull_IRQ_bit STRB R1, [R0, #IOMD_IRQMSKD] MOV R0, #InitKbdWs MOV R1, #2 STRB R1, [R0, #Port2Present] 30 ] MOV r0, #IOBase MOV r1, #ctl_Enable + ctl_EnableIRQ STRB r1, [r0, #IOControl] 10 LDRB r1, [r0, #IOStatus] TST r1, #stat_TXE MOVNE r1, #&FF STRNEB r1, [r0, #IOData] BEQ %BT10 MOV r0, #InitKbdWs ADR r1, KeyData STR r1, [r0, #KeyDataPtr] B SetUpKbdReturn | SetUpKbd MOV r0, #IOBase MOV r1, #ctl_Enable + ctl_EnableIRQ STRB r1, [r0, #IOControl] 10 LDRB r1, [r0, #IOStatus] TST r1, #stat_TXE MOVNE r1, #&FF STRNEB r1, [r0, #IOData] BEQ %BT10 [ MorrisSupport LDRB R1, [R0, #IOMD_ID0] ;Are we running on Morris CMP R1, #&E7 LDRB R1, [R0, #IOMD_ID1] CMPEQ R1, #&D4 BEQ %FT30 ;EQ: yes, it is IOMD, so only one PS2 port MOV R1, #IOMD_MSECR_Enable ;yes, so initialise 2nd PS2 (mouse) port cos STRB R1, [R0, #IOMD_MSECR] ;keyboard may be connected there instead 20 LDRB R1, [R0, #IOMD_MSECR] TST R1, #IOMD_MSECR_TxE ;Is port ready to accept data MOVNE R1, #&FF ;NE: port ready, so send 'reset' command STRNEB R1, [R0, #IOMD_MSEDAT] ; BEQ %BT20 ;EQ: loop til port ready MOV R1, #IOMD_MouseRxFull_IRQ_bit STRB R1, [R0, #IOMD_IRQMSKD] MOV R0, #InitKbdWs MOV R1, #2 STRB R1, [R0, #Port2Present] [ 1 = 1 ; ; Addresses and bit meanings for the Stork keyboard/battery-manager controller ; uC_Base EQU &302B800 uC_DataRxReg EQU uC_Base ;Read only uC_KeyDataTxReg EQU uC_Base ;Write only uC_StatusReg EQU uC_Base + 4 ;Read only ;Status register bits uC_Status_IBF EQU 1 :SHL: 0 ;Set data waiting in DataRxReg uC_Status_OBF EQU 1 :SHL: 1 ; ; ; On Kryten, Morris pin Event2 is tied low so bit Nevent2 is a ONE ; On Stork, Morris pin Event2 is tied high so bit Nevent2 is a ZERO ; MOV r0, #IOBase LDRB R1, [R0, #IOMD_IRQSTD] TST R1, #IOMD_Nevent2_bit BNE %FT30 ;NE: Not Stork, so two PS2 ports (which we've dealt with) ;EQ, Stork LDR R0, =uC_StatusReg ;Get Tx buffer status bit 25 ; LDRB R1, [R0] ; TST R1, #uC_Status_OBF ; BNE %BT25 ;Loop until buffer empties MOV R1, #&FF ;EQ: port ready, so send 'reset' command LDR R0, =uC_KeyDataTxReg STRB R1, [R0] ;Write byte to keyboard MOV R0, #IOBase ;Enable Ints from Storks keyboard/battery MOV R1, #IOMD_Network_IRQ_bit ; manager STRB R1, [R0, #IOCIRQMSKB] MOV R0, #InitKbdWs MOV R1, #4 STRB R1, [R0, #Port3Present] ] 30 ] MOV r0, #InitKbdWs ADR r1, KeyData STR r1, [r0, #KeyDataPtr] B SetUpKbdReturn ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; On ARM600, this routine must work in IRQ32 mode IRQ_Test_CTRL_or_R_Pressed ROUT [ CPU_Type = "ARM600" BIC pc, pc, #&FC000000 ; take us out of the shadow ROM area NOP ; (this instruction skipped) ] SUB lr, lr, #4 Push "r0-r2,lr" MOV r2, #IOBase [ MorrisSupport [ 1 = 1 MOV lr, #InitKbdWs LDRB r1, [lr, #Port3Present] ;Check if 3rd PS2 port (battery micro) is available TEQ r1, #0 LDRNE lr, =uC_StatusReg ;NE: yes, so check if interrupt is from it LDRNEB r1, [lr] ; TSTNE r1, #uC_Status_IBF ; LDRNE r2, =uC_DataRxReg ; LDRNEB r2, [r2] ;NE: 3rd port present and interrupting, get scan code MOVNE r1, #4 ;NE: indicate which port BNE %FT5 ;NE: process it ;EQ: 3rd port not present or not interrupting ; drop through and check 2nd port ] MOV lr, #InitKbdWs LDRB r1, [lr, #Port2Present] ;Check if 2nd PS2 port (in Morris) is available TEQ r1, #0 LDRNEB r0, [r2, #IOMD_MSECR] ;NE: yes, so check if interrupt is from it TSTNE r0, #IOMD_MSECR_RxF ; LDRNEB r2, [r2, #IOMD_MSEDAT] ;NE: 2nd port present and interrupting, get scan code MOVNE r1, #2 ;NE: indicate which port BNE %FT5 ;NE: process it ;EQ: 2nd port not present or not interrupting ; drop through and check 1st port ] LDRB r0, [r2, #IOStatus] TST r0, #stat_RXF ; If not keyboard then Pull "r0-r2,pc",EQ,^ ; exit. LDRB r2, [r2, #IOData] ; Get scan code. [ MorrisSupport MOV r1, #1 5 LDRB r0, [lr, #KB_There_Flag] TEQ r2, #0 ;Assume that zero is the end of a mouse AA 00 start up BICEQ r0, r0, r1 ; sequence, so clear keyboard present indication. STREQB r0, [lr, #KB_There_Flag] Pull "r0-r2,pc",EQ,^ ; and exit ORRNE r0, r0, r1 ;Not zero, mark keyboard present ] MOV lr, #InitKbdWs STRB r0, [lr, #KB_There_Flag] ; Keyboard must be there (r0<>0 from above). ADR r1, SpecialData TEQ r2, #PCSpecial ; If special code then STREQ r1, [lr, #KeyDataPtr] ; switch tables Pull "r0-r2,pc",EQ,^ ; and exit. LDR r0, [lr, #KeyDataPtr] ; Get pointer to current table. TEQ r0, r1 ; Only use special table once, then ADREQ r1, KeyData ; switch back to normal table. STREQ r1, [lr, #KeyDataPtr] 10 LDRB r1, [r0], #2 ; Get key code from table. TEQ r1, #0 ; If at end of table then Pull "r0-r2,pc",EQ,^ ; ignore key. TEQ r1, r2 ; If not this key then BNE %BT10 ; try the next. LDRB r1, [r0, #-1] ; Get flag. STRB r1, [lr, r1] ; Non-zero means pressed. Pull "r0-r2,pc",,^ END