; ;================================================================================================== ; PIO DRIVER (PARALLEL PORT) ;================================================================================================== ; ; SETUP PARAMETER WORD: ; +-------+---+-------------------+ +---+---+-----------+---+-------+ ; | |RTS| ENCODED BAUD RATE | |DTR|XON| PARITY |STP| 8/7/6 | ; +-------+---+---+---------------+ ----+---+-----------+---+-------+ ; F E D C B A 9 8 7 6 5 4 3 2 1 0 ; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- ; ; THIS DRIVER IS JUST A STUB TO DETECT AND INITIALIZE PIO HARDWARE ; IF IT EXISTS. FOR NOW, IT DOES NOT REGISTER ANY OF THE PIO CHANNELS ; AS CHARACTER DEVICE UNITS. ; PIO_NONE .EQU 0 PIO_PIO .EQU 1 ; PIO0A_CTL .EQU PIO0BASE + $02 PIO0A_DAT .EQU PIO0BASE + $00 PIO0B_CTL .EQU PIO0BASE + $03 PIO0B_DAT .EQU PIO0BASE + $01 ; #IF (PIOCNT >= 2) ; PIO1A_CTL .EQU PIO1BASE + $02 PIO1A_DAT .EQU PIO1BASE + $00 PIO1B_CTL .EQU PIO1BASE + $03 PIO1B_DAT .EQU PIO1BASE + $01 ; #ENDIF ; PIO_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES ; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMAIN ; DISABLED. ; CALL PIO_PROBE ; PROBE FOR CHIPS ; LD B,PIO_CFGCNT ; LOOP CONTROL XOR A ; ZERO TO ACCUM LD (PIO_DEV),A ; CURRENT DEVICE NUMBER LD IY,PIO_CFG ; POINT TO START OF CFG TABLE PIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE POP BC ; RESTORE LOOP CONTROL ; LD A,(IY+1) ; GET THE PIO TYPE DETECTED OR A ; SET FLAGS JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND ; PUSH BC ; SAVE LOOP CONTROL PUSH IY ; CFG ENTRY ADDRESS POP DE ; ... TO DE LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS ; REGISTRATION OF CHARACTER UNIT IN HBIOS IS BYPASSED ; FOR NOW. NOT SURE WHAT TO DO WITH THIS HARDWARE YET. ;CALL NZ,CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE POP BC ; RESTORE LOOP CONTROL ; PIO_PREINIT2: LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY ADD IY,DE ; BUMP IY TO NEXT ENTRY DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE ; XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; PIO INITIALIZATION ROUTINE ; PIO_INITUNIT: CALL PIO_DETECT ; DETERMINE PIO TYPE LD (IY+1),A ; SAVE IN CONFIG TABLE OR A ; SET FLAGS RET Z ; ABORT IF NOTHING THERE ; ; UPDATE WORKING PIO DEVICE NUM LD HL,PIO_DEV ; POINT TO CURRENT UART DEVICE NUM LD A,(HL) ; PUT IN ACCUM INC (HL) ; INCREMENT IT (FOR NEXT LOOP) LD (IY),A ; UPDATE UNIT NUM ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE ; CALL INITDEVX TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! JP PIO_INITDEVX ; IMPLEMENT IT AND RETURN ; ; ; PIO_INIT: LD B,PIO_CFGCNT ; COUNT OF POSSIBLE PIO UNITS LD IY,PIO_CFG ; POINT TO START OF CFG TABLE PIO_INIT1: PUSH BC ; SAVE LOOP CONTROL LD A,(IY+1) ; GET PIO TYPE OR A ; SET FLAGS CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO POP BC ; RESTORE LOOP CONTROL LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY ADD IY,DE ; BUMP IY TO NEXT ENTRY DJNZ PIO_INIT1 ; LOOP TILL DONE ; XOR A ; SIGNAL SUCCESS RET ; DONE ; ; DRIVER FUNCTION TABLE ; PIO_FNTBL: .DW PIO_IN .DW PIO_OUT .DW PIO_IST .DW PIO_OST .DW PIO_INITDEV .DW PIO_QUERY .DW PIO_DEVICE #IF (($ - PIO_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" #ENDIF ; ; ; PIO_IN: LD E,0 ; DUMMY VALUE XOR A ; SIGNAL SUCCESS RET ; ; ; PIO_OUT: XOR A ; SIGNAL SUCCESS RET ; ; ; PIO_IST: XOR A ; NO CHARS WAITING RET ; ; ; PIO_OST: XOR A ; NO BUFFER SPACE AVAIL RET ; ; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS ; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE ; CAN AVOID ENABLING/DISABLING INTS. ; PIO_INITDEV: HB_DI ; DISABLE INTS CALL PIO_INITDEVX ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; PIO_INITDEVX: ; ; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY ; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! ; LD C,(IY+3) ; CONTROL PORT LD A,%00010111 ; CLEAR INTERRUPT CTL WORD OUT (C),A LD A,%11111111 ; CLEAR MASK OUT (C),A LD A,%00000000 ; CLEAR INTERRUPT VECTOR OUT (C),A LD A,%01001111 ; SET MODE 1 (INPUT) OUT (C),A RET ; ; ; PIO_QUERY: LD E,(IY+5) ; FIRST CONFIG BYTE TO E LD D,(IY+6) ; SECOND CONFIG BYTE TO D XOR A ; SIGNAL SUCCESS RET ; DONE ; ; ; PIO_DEVICE: LD D,CIODEV_PIO ; D := DEVICE TYPE LD E,(IY) ; E := PHYSICAL UNIT LD C,$40 ; C := DEVICE TYPE, 0x40 IS PIO LD H,(IY+1) ; H := MODE LD L,(IY+3) ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; PIO CHIP PROBE ; CHECK FOR PRESENCE OF PIO CHIPS AND POPULATE THE ; PIO_MAP BITMAP (ONE BIT PER CHIP). THIS DETECTS ; CHIPS, NOT CHANNELS. EACH CHIP HAS 2 CHANNELS. ; MAX OF TWO CHIPS CURRENTLY. INT VEC VALUE IS TRASHED! ; PIO_PROBE: ; CLEAR THE PRESENCE BITMAP LD HL,PIO_MAP ; HL POINTS TO BITMAP XOR A ; ZERO LD (PIO_MAP),A ; CLEAR CHIP PRESENT BITMAP ; ; FIRST POSSIBLE CHIP LD C,PIO0A_CTL ; FIRST CHIP CMD/STAT PORT CALL PIO_PROBECHIP ; PROBE IT JR NZ,PIO_PROBE1 ; IF NOT ZERO, NOT FOUND SET 0,(HL) ; SET BIT FOR FIRST CARD PIO_PROBE1: ; #IF (PIOCNT >= 2) LD C,PIO1A_CTL ; SECOND CHIP CMD/STAT PORT CALL PIO_PROBECHIP ; PROBE IT JR NZ,PIO_PROBE2 ; IF NOT ZERO, NOT FOUND SET 1,(HL) ; SET BIT FOR SECOND CARD PIO_PROBE2: #ENDIF ; RET ; PIO_PROBECHIP: ; PIO IS HARD TO DETECT DEFINITIVELY. BEST I CAN THINK ; OF IS TO CHECK THE VALUE READ FROM THE CONTROL PORT. ; IT APPEARS TO BE ZERO CONSISTENTLY IF CHIP EXISTS. IN A,(C) ; GET VALUE OR A ; COMPARE TO ZERO RET ; ; PIO DETECTION ROUTINE ; THERE IS ONLY ONE VARIATION OF PIO CHIP, SO HERE WE JUST CHECK THE ; CHIP PRESENCE BITMAP TO SET THE CHIP TYPE OF EITHER NONE OR PIO. ; PIO_DETECT: LD B,(IY+2) ; GET CHIP/CHANNEL SRL B ; SHIFT AWAY THE CHANNEL BIT INC B ; NUMBER OF TIMES TO ROTATE BITS LD A,(PIO_MAP) ; BIT MAP IN A PIO_DETECT1: ; ROTATE DESIRED CHIP BIT INTO CF RRA ; ROTATE NEXT BIT INTO CF DJNZ PIO_DETECT1 ; DO THIS UNTIL WE HAVE DESIRED BIT ; RETURN CHIP TYPE LD A,PIO_NONE ; ASSUME NOTHING HERE RET NC ; IF CF NOT SET, RETURN LD A,PIO_PIO ; CHIP TYPE IS PIO RET ; DONE ; ; ; PIO_PRTCFG: ; ANNOUNCE PORT CALL NEWLINE ; FORMATTING PRTS("PIO$") ; FORMATTING LD A,(IY) ; DEVICE NUM CALL PRTDECB ; PRINT DEVICE NUM PRTS(": IO=0x$") ; FORMATTING LD A,(IY+3) ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT ; PRINT THE PIO TYPE CALL PC_SPACE ; FORMATTING LD A,(IY+1) ; GET PIO TYPE BYTE RLCA ; MAKE IT A WORD OFFSET LD HL,PIO_TYPE_MAP ; POINT HL TO TYPE MAP TABLE CALL ADDHLA ; HL := ENTRY LD E,(HL) ; DEREFERENCE INC HL ; ... LD D,(HL) ; ... TO GET STRING POINTER CALL WRITESTR ; PRINT IT ; XOR A RET ; ; ; PIO_TYPE_MAP: .DW PIO_STR_NONE .DW PIO_STR_PIO PIO_STR_NONE .DB "$" PIO_STR_PIO .DB "PIO$" ; ; WORKING VARIABLES ; PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT PIO_MAP .DB 0 ; CHIP PRESENCE BITMAP ; PIO0A_RCVBUF .EQU 0 PIO0B_RCVBUF .EQU 0 ; #IF (PIOCNT >= 2) PIO1A_RCVBUF .EQU 0 PIO1B_RCVBUF .EQU 0 #ENDIF ; ; PIO PORT TABLE ; PIO_CFG: ; PIO0 CHANNEL A PIO0A_CFG: .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; PIO TYPE (SET DURING INIT) .DB $00 ; CHIP 0 / CHANNEL A (LOW BIT IS CHANNEL) .DB PIO0A_CTL ; CMD/STATUS PORT .DB PIO0A_DAT ; DATA PORT .DW DEFSERCFG ; LINE CONFIGURATION .DW PIO0A_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; PIO_CFGSIZ .EQU $ - PIO_CFG ; SIZE OF ONE CFG TABLE ENTRY ; ; PIO0 CHANNEL B PIO0B_CFG: .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; PIO TYPE (SET DURING INIT) .DB $01 ; CHIP 0 / CHANNEL B (LOW BIT IS CHANNEL) .DB PIO0B_CTL ; CMD/STATUS PORT .DB PIO0B_DAT ; DATA PORT .DW DEFSERCFG ; LINE CONFIGURATION .DW PIO0B_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; #IF (PIOCNT >= 2) ; ; PIO1 CHANNEL A PIO1A_CFG: .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; PIO TYPE (SET DURING INIT) .DB $02 ; CHIP 1 / CHANNEL A (LOW BIT IS CHANNEL) .DB PIO1A_CTL ; CMD/STATUS PORT .DB PIO1A_DAT ; DATA PORT .DW DEFSERCFG ; LINE CONFIGURATION .DW PIO1A_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; ; PIO1 CHANNEL B PIO1B_CFG: .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; PIO TYPE (SET DURING INIT) .DB $03 ; CHIP 1 / CHANNEL B (LOW BIT IS CHANNEL) .DB PIO1B_CTL ; CMD/STATUS PORT .DB PIO1B_DAT ; DATA PORT .DW DEFSERCFG ; LINE CONFIGURATION .DW PIO1B_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; #ENDIF ; PIO_CFGCNT .EQU ($ - PIO_CFG) / PIO_CFGSIZ