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.
 
 
 
 
 
 

292 lines
7.0 KiB

;
;
;==================================================================================================
; SIO 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) --
;
SIO_DEBUG .EQU FALSE
;
SIO_NONE .EQU 0
SIO_SIO .EQU 1
;
;
;
SIO_PREINIT:
;
; SETUP THE DISPATCH TABLE ENTRIES
;
LD B,SIO_CNT ; LOOP CONTROL
LD C,0 ; PHYSICAL UNIT INDEX
SIO_PREINIT0:
PUSH BC ; SAVE LOOP CONTROL
LD A,C ; PHYSICAL UNIT TO A
RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES)
RLCA ; ...
RLCA ; ... TO GET OFFSET INTO CFG TABLE
LD HL,SIO_CFG ; POINT TO START OF CFG TABLE
CALL ADDHLA ; HL := ENTRY ADDRESS
PUSH HL ; SAVE IT
PUSH HL ; COPY CFG DATA PTR
POP IY ; ... TO IY
CALL SIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE
POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE
POP BC ; RESTORE LOOP CONTROL
;
LD A,(IY + 1) ; GET THE SIO TYPE DETECTED
OR A ; SET FLAGS
JR Z,SIO_PREINIT2 ; SKIP IT IF NOTHING FOUND
;
PUSH BC ; SAVE LOOP CONTROL
LD BC,SIO_DISPATCH ; BC := DISPATCH ADDRESS
CALL NZ,CIO_ADDENT ; ADD ENTRY IF SIO FOUND, BC:DE
POP BC ; RESTORE LOOP CONTROL
;
SIO_PREINIT2:
INC C ; NEXT PHYSICAL UNIT
DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE
XOR A ; SIGNAL SUCCESS
RET ; AND RETURN
;
;
;
SIO_INITUNIT:
CALL SIO_DETECT ; DETERMINE SIO TYPE
LD (IY + 1),A ; SAVE IN CONFIG TABLE
OR A ; SET FLAGS
RET Z ; ABORT IF NOTHING THERE
; UPDATE WORKING SIO DEVICE NUM
LD HL,SIO_DEV ; POINT TO CURRENT UART DEVICE NUM
LD A,(HL) ; PUT IN ACCUM
INC (HL) ; INCREMENT IT (FOR NEXT LOOP)
LD (IY),A ; UDPATE UNIT NUM
; SET DEFAULT CONFIG
LD DE,-1 ; LEAVE CONFIG ALONE
JP SIO_INITDEV ; IMPLEMENT IT AND RETURN
;
;
;
SIO_INIT:
LD B,SIO_CNT ; COUNT OF POSSIBLE SIO UNITS
LD C,0 ; INDEX INTO SIO CONFIG TABLE
SIO_INIT1:
PUSH BC ; SAVE LOOP CONTROL
LD A,C ; PHYSICAL UNIT TO A
RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES)
RLCA ; ...
RLCA ; ... TO GET OFFSET INTO CFG TABLE
LD HL,SIO_CFG ; POINT TO START OF CFG TABLE
CALL ADDHLA ; HL := ENTRY ADDRESS
PUSH HL ; COPY CFG DATA PTR
POP IY ; ... TO IY
CALL NZ,SIO_PRTCFG ; PRINT IF NOT ZERO
POP BC ; RESTORE LOOP CONTROL
INC C ; NEXT UNIT
DJNZ SIO_INIT1 ; LOOP TILL DONE
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
;
;
SIO_DISPATCH:
; DISPATCH TO FUNCTION HANDLER
PUSH HL ; SAVE HL FOR NOW
LD A,B ; GET FUNCTION
AND $0F ; ISOLATE LOW NIBBLE
RLCA ; X 2 FOR WORD OFFSET INTO FUNCTION TABLE
LD HL,SIO_FTBL ; START OF FUNC TABLE
CALL ADDHLA ; HL := ADDRESS OF ADDRESS OF FUNCTION
LD A,(HL) ; DEREF HL
INC HL ; ...
LD H,(HL) ; ...
LD L,A ; ... TO GET ADDRESS OF FUNCTION
EX (SP),HL ; RESTORE HL & PUT FUNC ADDRESS -> (SP)
RET ; EFFECTIVELY A JP TO TGT ADDRESS
SIO_FTBL:
.DW SIO_IN
.DW SIO_OUT
.DW SIO_IST
.DW SIO_OST
.DW SIO_INITDEV
.DW SIO_QUERY
.DW SIO_DEVICE
;
;
;
SIO_IN:
CALL SIO_IST ; RECEIVED CHAR READY?
JR Z,SIO_IN ; LOOP IF NOT
LD C,(IY + 2) ; C := BASE SIO PORT (WHICH IS ALSO RBR REG)
IN E,(C) ; CHAR READ TO E
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
;
;
SIO_OUT:
CALL SIO_OST ; READY FOR CHAR?
JR Z,SIO_OUT ; LOOP IF NOT
LD C,(IY + 2) ; C := BASE SIO PORT (WHICH IS ALSO THR REG)
OUT (C),E ; SEND CHAR FROM E
XOR A ; SIGNAL SUCCESS
RET
;
;
;
SIO_IST:
LD C,(IY + 3) ; CMD PORT
XOR A ; WR0
OUT (C),A ; DO IT
IN A,(C) ; GET STATUS
AND $01 ; ISOLATE BIT 0 (RECEIVE DATA READY)
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
XOR A ; ZERO ACCUM
INC A ; ACCUM := 1 TO SIGNAL 1 CHAR WAITING
RET ; DONE
;
;
;
SIO_OST:
LD C,(IY + 3) ; CMD PORT
XOR A ; WR0
OUT (C),A ; DO IT
IN A,(C) ; GET STATUS
AND $04 ; ISOLATE BIT 2 (TX EMPTY)
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
XOR A ; ZERO ACCUM
INC A ; ACCUM := 1 TO SIGNAL 1 BUFFER POSITION
RET ; DONE
;
;
;
SIO_INITDEV:
LD C,(IY + 3) ; COMMAND PORT
LD HL,SIO_INITVALS ; POINT TO INIT VALUES
LD B,SIO_INITLEN ; COUNT OF BYTES TO WRITE
OTIR ; WRITE ALL VALUES
XOR A ; SIGNAL SUCCESS
RET ; RETURN
;
SIO_INITVALS:
.DB $00, $18 ; WR0: CHANNEL RESET
.DB $04, $C4 ; WR4: CLK/64=115200 BAUD, NO PARITY, 1 STOP BIT
.DB $01, $00 ; WR1: NO INTERRUPTS
.DB $03, $C1 ; WR3: 8 BIT RCV, RX ENABLE
.DB $05, $EA ; WR5: DTR, 8 BITS SEND, TX ENABLE, RTS
SIO_INITLEN .EQU $ - SIO_INITVALS
;
;
;
SIO_QUERY:
LD E,(IY + 4) ; FIRST CONFIG BYTE TO E
LD D,(IY + 5) ; SECOND CONFIG BYTE TO D
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
;
;
SIO_DEVICE:
LD D,CIODEV_SIO ; D := DEVICE TYPE
LD E,(IY) ; E := PHYSICAL UNIT
XOR A ; SIGNAL SUCCESS
RET
;
; SIO DETECTION ROUTINE
;
SIO_DETECT:
LD C,(IY + 3) ; COMMAND PORT
XOR A
OUT (C),A ; ACCESS RD0
IN A,(C) ; GET RD0 VALUE
LD B,A ; SAVE IT
LD A,1
OUT (C),A ; ACCESS RD1
IN A,(C) ; GET RD1 VALUE
CP B ; COMPARE
LD A,SIO_NONE ; ASSUME NOTHING THERE
RET Z ; RD0=RD1 MEANS NOTHING THERE
LD A,SIO_SIO ; GUESS WE HAVE A VALID SIO HERE
RET ; DONE
;
;
;
SIO_PRTCFG:
; ANNOUNCE PORT
CALL NEWLINE ; FORMATTING
PRTS("SIO$") ; 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 SIO TYPE
CALL PC_SPACE ; FORMATTING
LD A,(IY + 1) ; GET SIO TYPE BYTE
RLCA ; MAKE IT A WORD OFFSET
LD HL,SIO_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
;
; ALL DONE IF NO SIO WAS DETECTED
LD A,(IY + 1) ; GET SIO TYPE BYTE
OR A ; SET FLAGS
RET Z ; IF ZERO, NOT PRESENT
;
PRTS(" MODE=$") ; FORMATTING
LD E,(IY + 4) ; LOAD CONFIG
LD D,(IY + 5) ; ... WORD TO DE
CALL PS_PRTSC0 ; PRINT CONFIG
;
XOR A
RET
;
;
;
SIO_TYPE_MAP:
.DW SIO_STR_NONE
.DW SIO_STR_SIO
SIO_STR_NONE .DB "<NOT PRESENT>$"
SIO_STR_SIO .DB "SIO$"
;
; WORKING VARIABLES
;
SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT
;
; SIO PORT TABLE
;
SIO_CFG:
; SIO/2 CHANNEL A
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; SIO TYPE
.DB $81 ; DATA PORT
.DB $80 ; CMD PORT
.DW DEFSERCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
;
; SIO/2 CHANNEL B
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; SIO TYPE
.DB $83 ; DATA PORT
.DB $82 ; CMD PORT
.DW DEFSERCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
;
SIO_CNT .EQU ($ - SIO_CFG) / 8