mirror of https://github.com/wwarthen/RomWBW.git
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.
347 lines
8.7 KiB
347 lines
8.7 KiB
;
|
|
;==================================================================================================
|
|
; PIO DRIVER (SERIAL 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 CHARCTER 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 REMIAIN
|
|
; 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
|
|
;
|
|
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
|
|
|