You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

363 lines
9.0 KiB

;
;==================================================================================================
; 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 "<NOT PRESENT>$"
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
;
.ECHO "PIO: IO="
.ECHO PIO0BASE
.ECHO ", CHANNEL A\n"
;
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
;
.ECHO "PIO: IO="
.ECHO PIO0BASE
.ECHO ", CHANNEL B\n"
;
#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
;
.ECHO "PIO: IO="
.ECHO PIO1BASE
.ECHO ", CHANNEL A\n"
;
; 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
;
.ECHO "PIO: IO="
.ECHO PIO1BASE
.ECHO ", CHANNEL B\n"
;
#ENDIF
;
PIO_CFGCNT .EQU ($ - PIO_CFG) / PIO_CFGSIZ