; ;================================================================================================== ; 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) -- ; ; FOR THE ECB-ZILOG-PERIPHERALS BOARD, INFORMATION ON JUMPER SETTINGS ; AND BAUD RATES CAN BE FOUND HERE: ; https://www.retrobrewcomputers.org/doku.php?id=boards:ecb:zilog-peripherals:clock-divider ; ; SIO PORT A (COM1:) and SIO PORT B (COM2:) ARE MAPPED TO DEVICE UC1: AND UL1: IN CP/M. ; SIO_NONE .EQU 0 SIO_SIO .EQU 1 ; #IF (SIOMODE == SIOMODE_RC) SIOA_CMD .EQU SIOBASE + $00 SIOA_DAT .EQU SIOBASE + $01 SIOB_CMD .EQU SIOBASE + $02 SIOB_DAT .EQU SIOBASE + $03 #ENDIF ; #IF (SIOMODE == SIOMODE_SMB) SIOA_CMD .EQU SIOBASE + $02 SIOA_DAT .EQU SIOBASE + $00 SIOB_CMD .EQU SIOBASE + $03 SIOB_DAT .EQU SIOBASE + $01 #ENDIF ; #IF (SIOMODE == SIOMODE_ZP) SIOA_CMD .EQU SIOBASE + $06 SIOA_DAT .EQU SIOBASE + $04 SIOB_CMD .EQU SIOBASE + $07 SIOB_DAT .EQU SIOBASE + $05 #ENDIF ; ; CONDITIONALS THAT DETERMINE THE ENCODED VALUE OF THE BAUD RATE ; #INCLUDE "siobaud.inc" ; SIO_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES ; LD B,SIO_CNT ; LOOP CONTROL LD C,0 ; PHYSICAL UNIT INDEX XOR A ; ZERO TO ACCUM LD (SIO_DEV),A ; CURRENT DEVICE NUMBER 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_FNTBL ; BC := FUNCTION TABLE 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 ; #IF (INTMODE == 1) ; ADD IM1 INT CALL LIST ENTRY IF APPROPRIATE LD A,(SIO_DEV) ; GET NEXT DEVICE NUM OR A ; SET FLAGS JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES LD HL,SIO_INT ; GET INT VECTOR CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST #ENDIF ; #IF (INTMODE == 2) ; SETUP SIO INTERRUPT VECTOR IN IVT LD HL,INT_SIO LD (HBX_IVT + IVT_SER0),HL #ENDIF ; SIO_PREINIT3: XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; SIO INITIALIZATION ROUTINE ; 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 ; UPDATE 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 LD A,(IY+1) ; GET SIO TYPE OR A ; SET FLAGS 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 ; ; RECEIVE INTERRUPT HANDLER ; #IF (INTMODE > 0) ; SIO_INT: SIOA_INT: ; CHECK FOR RECEIVE PENDING ON CHANNEL A XOR A ; A := 0 OUT (SIOA_CMD),A ; ADDRESS RD0 IN A,(SIOA_CMD) ; GET RD0 AND $01 ; ISOLATE RECEIVE READY BIT JR Z,SIOB_INT ; CHECK CHANNEL B ; SIOA_INT00: ; HANDLE CHANNEL A IN A,(SIOA_DAT) ; READ PORT LD E,A ; SAVE BYTE READ LD A,(SIOA_CNT) ; GET CURRENT BUFFER USED COUNT CP SIOA_BUFSZ ; COMPARE TO BUFFER SIZE RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED INC A ; INCREMENT THE COUNT LD (SIOA_CNT),A ; AND SAVE IT CP SIOA_BUFSZ - 5 ; BUFFER GETTING FULL? JR NZ,SIOA_INT0 ; IF NOT, BYPASS CLEARING RTS LD A,5 ; RTS IS IN WR5 OUT (SIOA_CMD),A ; ADDRESS WR5 LD A,$E8 ; VALUE TO CLEAR RTS OUT (SIOA_CMD),A ; DO IT SIOA_INT0: LD HL,(SIOA_HD) ; GET HEAD POINTER LD A,L ; GET LOW BYTE CP SIOA_BUFEND & $FF ; PAST END? JR NZ,SIOA_INT1 ; IF NOT, BYPASS POINTER RESET LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOA_INT1: LD A,E ; RECOVER BYTE READ LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION INC HL ; INCREMENT HEAD POINTER LD (SIOA_HD),HL ; SAVE IT ; ; CHECK FOR MORE PENDING... XOR A ; A := 0 OUT (SIOA_CMD),A ; ADDRESS RD0 IN A,(SIOA_CMD) ; GET RD0 RRA ; READY BIT TO CF JR C,SIOA_INT00 ; IF SET, DO SOME MORE OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; AND RETURN ; SIOB_INT: ; CHECK FOR RECEIVE PENDING ON CHANNEL B XOR A ; A := 0 OUT (SIOB_CMD),A ; ADDRESS RD0 IN A,(SIOB_CMD) ; GET RD0 AND $01 ; ISOLATE RECEIVE READY BIT RET Z ; IF NOT, RETURN WITH Z SET ; SIOB_INT00: ; HANDLE CHANNEL B IN A,(SIOB_DAT) ; READ PORT LD E,A ; SAVE BYTE READ LD A,(SIOB_CNT) ; GET CURRENT BUFFER USED COUNT CP SIOB_BUFSZ ; COMPARE TO BUFFER SIZE RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED INC A ; INCREMENT THE COUNT LD (SIOB_CNT),A ; AND SAVE IT CP SIOB_BUFSZ - 5 ; BUFFER GETTING FULL? JR NZ,SIOB_INT0 ; IF NOT, BYPASS CLEARING RTS LD A,5 ; RTS IS IN WR5 OUT (SIOB_CMD),A ; ADDRESS WR5 LD A,$E8 ; VALUE TO CLEAR RTS OUT (SIOB_CMD),A ; DO IT SIOB_INT0: LD HL,(SIOB_HD) ; GET HEAD POINTER LD A,L ; GET LOW BYTE CP SIOB_BUFEND & $FF ; PAST END? JR NZ,SIOB_INT1 ; IF NOT, BYPASS POINTER RESET LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOB_INT1: LD A,E ; RECOVER BYTE READ LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION INC HL ; INCREMENT HEAD POINTER LD (SIOB_HD),HL ; SAVE IT ; ; CHECK FOR MORE PENDING... XOR A ; A := 0 OUT (SIOB_CMD),A ; ADDRESS RD0 IN A,(SIOB_CMD) ; GET RD0 RRA ; READY BIT TO CF JR C,SIOB_INT00 ; IF SET, DO SOME MORE OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; AND RETURN ; #ENDIF ; ; DRIVER FUNCTION TABLE ; SIO_FNTBL: .DW SIO_IN .DW SIO_OUT .DW SIO_IST .DW SIO_OST .DW SIO_INITDEV .DW SIO_QUERY .DW SIO_DEVICE #IF (($ - SIO_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID SIO FUNCTION TABLE ***\n" #ENDIF ; ; ; #IF (INTMODE == 0) ; SIO_IN: CALL SIO_IST ; CHAR WAITING? JR Z,SIO_IN ; LOOP IF NOT LD C,(IY+3) ; C := SIO CMD PORT #IF (SIOMODE == SIOMODE_RC) INC C ; BUMP TO DATA PORT #ENDIF #IF ((SIOMODE == SIOMODE_SMB) | (SIOMODE == SIOMODE_ZP)) DEC C ; DECREMENT CMD PORT TWICE TO GET DATA PORT DEC C #ENDIF IN E,(C) ; GET CHAR XOR A ; SIGNAL SUCCESS RET ; #ELSE ; SIO_IN: LD A,(IY+2) ; GET CHANNEL OR A ; SET FLAGS JR Z,SIOA_IN ; HANDLE CHANNEL A DEC A ; TEST FOR NEXT DEVICE JR Z,SIOB_IN ; HANDLE CHANNEL B CALL PANIC ; ELSE FATAL ERROR RET ; ... AND RETURN ; SIOA_IN: CALL SIOA_IST ; RECEIVED CHAR READY? JR Z,SIOA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(SIOA_CNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (SIOA_CNT),A ; SAVE SAVE IT CP 5 ; BUFFER LOW THRESHOLD JR NZ,SIOA_IN0 ; IF NOT, BYPASS SETTING RTS LD A,5 ; RTS IS IN WR5 OUT (SIOA_CMD),A ; ADDRESS WR5 LD A,$EA ; VALUE TO SET RTS OUT (SIOA_CMD),A ; DO IT SIOA_IN0: LD HL,(SIOA_TL) ; GET BUFFER TAIL POINTER LD E,(HL) ; GET BYTE INC HL ; BUMP TAIL POINTER LD A,L ; GET LOW BYTE CP SIOA_BUFEND & $FF ; PAST END? JR NZ,SIOA_IN1 ; IF NOT, BYPASS POINTER RESET LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOA_IN1: LD (SIOA_TL),HL ; SAVE UPDATED TAIL POINTER HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; SIOB_IN: CALL SIOB_IST ; RECEIVED CHAR READY? JR Z,SIOB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(SIOB_CNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (SIOB_CNT),A ; SAVE SAVE IT CP 5 ; BUFFER LOW THRESHOLD JR NZ,SIOB_IN0 ; IF NOT, BYPASS SETTING RTS LD A,5 ; RTS IS IN WR5 OUT (SIOB_CMD),A ; ADDRESS WR5 LD A,$EA ; VALUE TO SET RTS OUT (SIOB_CMD),A ; DO IT SIOB_IN0: LD HL,(SIOB_TL) ; GET BUFFER TAIL POINTER LD E,(HL) ; GET BYTE INC HL ; BUMP TAIL POINTER LD A,L ; GET LOW BYTE CP SIOB_BUFEND & $FF ; PAST END? JR NZ,SIOB_IN1 ; IF NOT, BYPASS POINTER RESET LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOB_IN1: LD (SIOB_TL),HL ; SAVE UPDATED TAIL POINTER HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; #ENDIF ; ; ; SIO_OUT: CALL SIO_OST ; READY FOR CHAR? JR Z,SIO_OUT ; LOOP IF NOT LD C,(IY+3) ; C := SIO CMD PORT #IF (SIOMODE == SIOMODE_RC) INC C ; BUMP TO DATA PORT #ENDIF #IF ((SIOMODE == SIOMODE_SMB) | (SIOMODE == SIOMODE_ZP)) DEC C ; DECREMENT CMD PORT TWICE TO GET DATA PORT DEC C #ENDIF OUT (C),E ; SEND CHAR FROM E XOR A ; SIGNAL SUCCESS RET ; ; ; #IF (INTMODE == 0) ; 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 (RX READY) JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING XOR A ; ZERO ACCUM INC A ; ASCCUM := 1 TO SIGNAL 1 CHAR WAITING RET ; DONE ; #ELSE ; SIO_IST: LD A,(IY+2) ; GET CHANNEL OR A ; SET FLAGS JR Z,SIOA_IST ; HANDLE CHANNEL A DEC A ; TEST FOR NEXT DEVICE JR Z,SIOB_IST ; HANDLE CHANNEL B CALL PANIC ; ELSE FATAL ERROR RET ; ... AND RETURN ; SIOA_IST: LD A,(SIOA_CNT) ; GET BUFFER UTILIZATION COUNT OR A ; SET FLAGS JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING RET ; AND DONE ; SIOB_IST: LD A,(SIOB_CNT) ; GET BUFFER UTILIZATION COUNT OR A ; SET FLAGS JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING RET ; DONE ; #ENDIF ; ; ; 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 ; ; AT INITIALIZATION THE SETUP PARAMETER WORD IS TRANSLATED TO THE FORMAT ; REQUIRED BY THE SIO AND STORED IN A PORT/REGISTER INITIALIZATION TABLE, ; WHICH IS THEN LOADED INTO THE SIO. ; ; RTS, DTR AND XON SETTING IS NOT CURRENTLY SUPPORTED. ; MARK & SPACE PARITY AND 1.5 STOP BITS IS NOT SUPPORTED BY THE SIO. ; INITIALIZATION WILL NOT BE COMPLETED IF AN INVALID SETTING IS DETECTED. ; SIO_INITDEV: ; ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR AND E ; ... VALUE OF -1 INC A ; ... SO Z SET IF -1 JR NZ,SIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG ; ; LOAD EXISTING CONFIG TO REINIT LD E,(IY+4) ; LOW BYTE LD D,(IY+5) ; HIGH BYTE ; SIO_INITDEV1: PUSH DE ; SAVE CONFIG LD A,D ; GET CONFIG MSB AND $1F ; ISOLATE ENCODED BAUD RATE #IF (SIODEBUG) PUSH AF PRTS(" ENCODE[$") CALL PRTHEXBYTE PRTC(']') POP AF #ENDIF ; ; ONLY FOUR BAUD RATES ARE POSSIBLE WITH A FIXED CLOCK. ; THESE ARE PREDETERMINED BY HARDWARE SETTINGS AND MATCHING ; CONFIGURATION SETTINGS. WE PRECALCULATED THE FOUR ; POSSIBLE ENCODED VALUES. ; CP SIOBAUD1 ; We set the divider and the lower bit (d2) of the stop bits LD D,$04 ; /1 N,8,1 JR Z,BROK CP SIOBAUD2 LD D,$44 ; /16 N,8,1 JR Z,BROK CP SIOBAUD3 LD D,$84 ; /32 N,8,1 JR Z,BROK CP SIOBAUD4 LD D,$C4 ; /64 N,8,1 JR Z,BROK #IF (SIODEBUG) PUSH AF PRTS(" BR FAIL[$") CALL PRTHEXBYTE PRTC(']') POP AF #ENDIF ; EXITINIT: POP DE RET ; NZ status here indicating fail / invalid baud rate. BROK: LD A,E AND $E0 JR NZ,EXITINIT ; NZ status here indicates dtr, xon, parity mark or space so return LD A,E ; set stop bit (d3) and add divider AND $04 RLA OR D ; carry gets reset here LD D,A LD A,E ; get the parity bits SRL A ; move them to bottom two bits SRL A ; we know top bits are zero from previous test SRL A ; add stop bits OR D ; carry = 0 ; ; SET DIVIDER, STOP AND PARITY WR4 ; LD BC,SIO_INITVALS+3 LD (BC),A #IF (SIODEBUG) PUSH AF PRTS(" WR4[$") CALL PRTHEXBYTE PRTC(']') POP AF #ENDIF LD A,E ; 112233445566d1d0 CC RRA ; CC112233445566d1 d0 RRA ; d0CC112233445566 d1 RRA ; d1d0CC1122334455 66 LD D,A RRA ; 66d1d0CC11223344 55 AND $60 ; 0011110000000000 00 OR $8a ; ; SET TRANSMIT DATA BITS WR5 ; LD BC,SIO_INITVALS+11 LD (BC),A #IF (SIODEBUG) PUSH AF PRTS(" WR5[$") CALL PRTHEXBYTE PRTC(']') POP AF #ENDIF ; ; SET RECEIVE DATA BITS WR3 ; LD A,D AND $C0 OR $01 LD BC,SIO_INITVALS+9 LD (BC),A #IF (SIODEBUG) PUSH AF PRTS(" WR3[$") CALL PRTHEXBYTE PRTC(']') POP AF #ENDIF POP DE ; RESTORE CONFIG LD (IY+4),E ; SAVE LOW WORD LD (IY+5),D ; SAVE HI WORD HB_DI ; AVOID CONFLICTS ; ; PROGRAM THE SIO CHIP CHANNEL 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 ; ; RESET THE RECEIVE BUFFER LD E,(IY+6) LD D,(IY+7) ; DE := _CNT XOR A ; A := 0 LD (DE),A ; _CNT = 0 INC DE ; DE := ADR OF _HD PUSH DE ; SAVE IT INC DE INC DE INC DE INC DE ; DE := ADR OF _BUF POP HL ; HL := ADR OF _HD LD (HL),E INC HL LD (HL),D ; _HD := _BUF INC HL LD (HL),E INC HL LD (HL),D ; _TL := _BUF ; HB_EI ; READY FOR INTS AGAIN XOR A ; SIGNAL SUCCESS RET ; RETURN ; ; SIO_INITVALS: .DB $00, $18 ; WR0: CHANNEL RESET .DB $04, $00 ; WR4: CLK BAUD PARITY STOP BIT #IF (INTMODE == 0) .DB $01, $00 ; WR1: NO INTERRUPTS #ELSE .DB $01, $18 ; WR1: INTERRUPT ON ALL RECEIVE CHARACTERS #ENDIF .DB $02, IVT_SER0 ; WR2: INTERRUPT VECTOR OFFSET .DB $03, $C1 ; WR3: 8 BIT RCV, RX ENABLE .DB $05, $EA ; WR5: DTR, 8 BITS SEND, TX ENABLE, RTS 1 11 0 1 0 1 0 (1=DTR,11=8bits,0=sendbreak,1=TxEnable,0=sdlc,1=RTS,0=txcrc) 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 "$" SIO_STR_SIO .DB "SIO$" ; ; WORKING VARIABLES ; SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT ; #IF (INTMODE == 0) ; SIOA_RCVBUF .EQU 0 SIOB_RCVBUF .EQU 0 ; #ELSE ; ; CHANNEL A RECEIVE BUFFER SIOA_RCVBUF: SIOA_CNT .DB 0 ; CHARACTERS IN RING BUFFER SIOA_HD .DW SIOA_BUF ; BUFFER HEAD POINTER SIOA_TL .DW SIOA_BUF ; BUFFER TAIL POINTER SIOA_BUF .FILL 32,0 ; RECEIVE RING BUFFER SIOA_BUFEND .EQU $ ; END OF BUFFER SIOA_BUFSZ .EQU $ - SIOA_BUF ; SIZE OF RING BUFFER ; ; CHANNEL B RECEIVE BUFFER SIOB_RCVBUF: SIOB_CNT .DB 0 ; CHARACTERS IN RING BUFFER SIOB_HD .DW SIOB_BUF ; BUFFER HEAD POINTER SIOB_TL .DW SIOB_BUF ; BUFFER TAIL POINTER SIOB_BUF .FILL 32,0 ; RECEIVE RING BUFFER SIOB_BUFEND .EQU $ ; END OF BUFFER SIOB_BUFSZ .EQU $ - SIOB_BUF ; SIZE OF RING BUFFER ; #ENDIF ; ; SIO PORT TABLE ; SIO_CFG: ; SIO CHANNEL A .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; SIO TYPE (SET DURING INIT) .DB 0 ; SIO CHANNEL (A) .DB SIOA_CMD ; BASE PORT (CMD PORT) .DW DEFSIOACFG ; LINE CONFIGURATION .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; ; SIO CHANNEL B .DB 0 ; DEVICE NUMBER (SET DURING INIT) .DB 0 ; SIO TYPE (SET DURING INIT) .DB 1 ; SIO CHANNEL (B) .DB SIOB_CMD ; BASE PORT (CMD PORT) .DW DEFSIOBCFG ; LINE CONFIGURATION .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; SIO_CNT .EQU ($ - SIO_CFG) / 8