|
|
@ -15,38 +15,75 @@ |
|
|
; https://www.retrobrewcomputers.org/doku.php?id=boards:ecb:zilog-peripherals:clock-divider |
|
|
; 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 PORT A (COM1:) and SIO PORT B (COM2:) ARE MAPPED TO DEVICE UC1: AND UL1: IN CP/M. |
|
|
; |
|
|
|
|
|
|
|
|
; |
|
|
|
|
|
SIO_BUFSZ .EQU 32 ; RECEIVE RING BUFFER SIZE |
|
|
|
|
|
; |
|
|
SIO_NONE .EQU 0 |
|
|
SIO_NONE .EQU 0 |
|
|
SIO_SIO .EQU 1 |
|
|
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 |
|
|
|
|
|
|
|
|
; |
|
|
|
|
|
SIO_RTSON .EQU $EA |
|
|
|
|
|
SIO_RTSOFF .EQU $E8 |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIO0MODE == SIOMODE_RC) |
|
|
|
|
|
SIO0A_CMD .EQU SIO0BASE + $00 |
|
|
|
|
|
SIO0A_DAT .EQU SIO0BASE + $01 |
|
|
|
|
|
SIO0B_CMD .EQU SIO0BASE + $02 |
|
|
|
|
|
SIO0B_DAT .EQU SIO0BASE + $03 |
|
|
#ENDIF |
|
|
#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 |
|
|
|
|
|
|
|
|
#IF (SIO0MODE == SIOMODE_SMB) |
|
|
|
|
|
SIO0A_CMD .EQU SIO0BASE + $02 |
|
|
|
|
|
SIO0A_DAT .EQU SIO0BASE + $00 |
|
|
|
|
|
SIO0B_CMD .EQU SIO0BASE + $03 |
|
|
|
|
|
SIO0B_DAT .EQU SIO0BASE + $01 |
|
|
#ENDIF |
|
|
#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 |
|
|
|
|
|
|
|
|
#IF (SIO0MODE == SIOMODE_ZP) |
|
|
|
|
|
SIO0A_CMD .EQU SIO0BASE + $06 |
|
|
|
|
|
SIO0A_DAT .EQU SIO0BASE + $04 |
|
|
|
|
|
SIO0B_CMD .EQU SIO0BASE + $07 |
|
|
|
|
|
SIO0B_DAT .EQU SIO0BASE + $05 |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
#IF (SIOMODE == SIOMODE_EZZ80) |
|
|
|
|
|
SIOA_CMD .EQU SIOBASE + $01 |
|
|
|
|
|
SIOA_DAT .EQU SIOBASE + $00 |
|
|
|
|
|
SIOB_CMD .EQU SIOBASE + $03 |
|
|
|
|
|
SIOB_DAT .EQU SIOBASE + $02 |
|
|
|
|
|
|
|
|
#IF (SIO0MODE == SIOMODE_EZZ80) |
|
|
|
|
|
SIO0A_CMD .EQU SIO1BASE + $01 |
|
|
|
|
|
SIO0A_DAT .EQU SIO1BASE + $00 |
|
|
|
|
|
SIO0B_CMD .EQU SIO1BASE + $03 |
|
|
|
|
|
SIO0B_DAT .EQU SIO1BASE + $02 |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIO1MODE == SIOMODE_RC) |
|
|
|
|
|
SIO1A_CMD .EQU SIO1BASE + $00 |
|
|
|
|
|
SIO1A_DAT .EQU SIO1BASE + $01 |
|
|
|
|
|
SIO1B_CMD .EQU SIO1BASE + $02 |
|
|
|
|
|
SIO1B_DAT .EQU SIO1BASE + $03 |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
|
|
|
#IF (SIO1MODE == SIOMODE_SMB) |
|
|
|
|
|
SIO1A_CMD .EQU SIO1BASE + $02 |
|
|
|
|
|
SIO1A_DAT .EQU SIO1BASE + $00 |
|
|
|
|
|
SIO1B_CMD .EQU SIO1BASE + $03 |
|
|
|
|
|
SIO1B_DAT .EQU SIO1BASE + $01 |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIO1MODE == SIOMODE_ZP) |
|
|
|
|
|
SIO1A_CMD .EQU SIO1BASE + $06 |
|
|
|
|
|
SIO1A_DAT .EQU SIO1BASE + $04 |
|
|
|
|
|
SIO1B_CMD .EQU SIO1BASE + $07 |
|
|
|
|
|
SIO1B_DAT .EQU SIO1BASE + $05 |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIO1MODE == SIOMODE_EZZ80) |
|
|
|
|
|
SIO1A_CMD .EQU SIO1BASE + $01 |
|
|
|
|
|
SIO1A_DAT .EQU SIO1BASE + $00 |
|
|
|
|
|
SIO1B_CMD .EQU SIO1BASE + $03 |
|
|
|
|
|
SIO1B_DAT .EQU SIO1BASE + $02 |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
; CONDITIONALS THAT DETERMINE THE ENCODED VALUE OF THE BAUD RATE |
|
|
; CONDITIONALS THAT DETERMINE THE ENCODED VALUE OF THE BAUD RATE |
|
|
; |
|
|
; |
|
|
#INCLUDE "siobaud.inc" |
|
|
#INCLUDE "siobaud.inc" |
|
|
@ -57,23 +94,15 @@ SIO_PREINIT: |
|
|
; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN |
|
|
; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN |
|
|
; DISABLED. |
|
|
; DISABLED. |
|
|
; |
|
|
; |
|
|
LD B,SIO_CNT ; LOOP CONTROL |
|
|
|
|
|
LD C,0 ; PHYSICAL UNIT INDEX |
|
|
|
|
|
|
|
|
CALL SIO_PROBE ; PROBE FOR CHIPS |
|
|
|
|
|
; |
|
|
|
|
|
LD B,SIO_CFGCNT ; LOOP CONTROL |
|
|
XOR A ; ZERO TO ACCUM |
|
|
XOR A ; ZERO TO ACCUM |
|
|
LD (SIO_DEV),A ; CURRENT DEVICE NUMBER |
|
|
LD (SIO_DEV),A ; CURRENT DEVICE NUMBER |
|
|
|
|
|
LD IY,SIO_CFG ; POINT TO START OF CFG TABLE |
|
|
SIO_PREINIT0: |
|
|
SIO_PREINIT0: |
|
|
PUSH BC ; SAVE LOOP CONTROL |
|
|
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 |
|
|
CALL SIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE |
|
|
POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE |
|
|
|
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
; |
|
|
; |
|
|
LD A,(IY+1) ; GET THE SIO TYPE DETECTED |
|
|
LD A,(IY+1) ; GET THE SIO TYPE DETECTED |
|
|
@ -81,16 +110,25 @@ SIO_PREINIT0: |
|
|
JR Z,SIO_PREINIT2 ; SKIP IT IF NOTHING FOUND |
|
|
JR Z,SIO_PREINIT2 ; SKIP IT IF NOTHING FOUND |
|
|
; |
|
|
; |
|
|
PUSH BC ; SAVE LOOP CONTROL |
|
|
PUSH BC ; SAVE LOOP CONTROL |
|
|
|
|
|
PUSH IY ; CFG ENTRY ADDRESS |
|
|
|
|
|
POP DE ; ... TO DE |
|
|
LD BC,SIO_FNTBL ; BC := FUNCTION TABLE ADDRESS |
|
|
LD BC,SIO_FNTBL ; BC := FUNCTION TABLE ADDRESS |
|
|
CALL NZ,CIO_ADDENT ; ADD ENTRY IF SIO FOUND, BC:DE |
|
|
CALL NZ,CIO_ADDENT ; ADD ENTRY IF SIO FOUND, BC:DE |
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
; |
|
|
; |
|
|
SIO_PREINIT2: |
|
|
SIO_PREINIT2: |
|
|
INC C ; NEXT PHYSICAL UNIT |
|
|
|
|
|
|
|
|
LD DE,SIO_CFGSIZ ; SIZE OF CFG ENTRY |
|
|
|
|
|
ADD IY,DE ; BUMP IY TO NEXT ENTRY |
|
|
DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE |
|
|
DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE |
|
|
; |
|
|
; |
|
|
|
|
|
#IF (INTMODE >= 1) |
|
|
|
|
|
; SETUP INT VECTORS AS APPROPRIATE |
|
|
|
|
|
LD A,(SIO_DEV) ; GET NEXT DEVICE NUM |
|
|
|
|
|
OR A ; SET FLAGS |
|
|
|
|
|
JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES, ABORT |
|
|
|
|
|
; |
|
|
#IF (INTMODE == 1) |
|
|
#IF (INTMODE == 1) |
|
|
; ADD IM1 INT CALL LIST ENTRY IF APPROPRIATE |
|
|
|
|
|
|
|
|
; ADD IM1 INT CALL LIST ENTRY |
|
|
LD A,(SIO_DEV) ; GET NEXT DEVICE NUM |
|
|
LD A,(SIO_DEV) ; GET NEXT DEVICE NUM |
|
|
OR A ; SET FLAGS |
|
|
OR A ; SET FLAGS |
|
|
JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES |
|
|
JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES |
|
|
@ -99,9 +137,17 @@ SIO_PREINIT2: |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
#IF (INTMODE == 2) |
|
|
#IF (INTMODE == 2) |
|
|
; SETUP SIO INTERRUPT VECTOR IN IVT |
|
|
|
|
|
LD HL,SIO_INT |
|
|
|
|
|
|
|
|
; SETUP IM2 VECTORS |
|
|
|
|
|
LD HL,SIO_INT0 |
|
|
LD (HB_IVT07 + 1),HL ; IVT INDEX 7 |
|
|
LD (HB_IVT07 + 1),HL ; IVT INDEX 7 |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
LD HL,SIO_INT1 |
|
|
|
|
|
LD (HB_IVT08 + 1),HL ; IVT INDEX 8 |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
SIO_PREINIT3: |
|
|
SIO_PREINIT3: |
|
|
@ -131,26 +177,16 @@ SIO_INITUNIT: |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
SIO_INIT: |
|
|
SIO_INIT: |
|
|
LD B,SIO_CNT ; COUNT OF POSSIBLE SIO UNITS |
|
|
|
|
|
LD C,0 ; INDEX INTO SIO CONFIG TABLE |
|
|
|
|
|
|
|
|
LD B,SIO_CFGCNT ; COUNT OF POSSIBLE SIO UNITS |
|
|
|
|
|
LD IY,SIO_CFG ; POINT TO START OF CFG TABLE |
|
|
SIO_INIT1: |
|
|
SIO_INIT1: |
|
|
PUSH BC ; SAVE LOOP CONTROL |
|
|
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 |
|
|
LD A,(IY+1) ; GET SIO TYPE |
|
|
OR A ; SET FLAGS |
|
|
OR A ; SET FLAGS |
|
|
CALL NZ,SIO_PRTCFG ; PRINT IF NOT ZERO |
|
|
CALL NZ,SIO_PRTCFG ; PRINT IF NOT ZERO |
|
|
|
|
|
|
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
POP BC ; RESTORE LOOP CONTROL |
|
|
INC C ; NEXT UNIT |
|
|
|
|
|
|
|
|
LD DE,SIO_CFGSIZ ; SIZE OF CFG ENTRY |
|
|
|
|
|
ADD IY,DE ; BUMP IY TO NEXT ENTRY |
|
|
DJNZ SIO_INIT1 ; LOOP TILL DONE |
|
|
DJNZ SIO_INIT1 ; LOOP TILL DONE |
|
|
; |
|
|
; |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
@ -160,94 +196,110 @@ SIO_INIT1: |
|
|
; |
|
|
; |
|
|
#IF (INTMODE > 0) |
|
|
#IF (INTMODE > 0) |
|
|
; |
|
|
; |
|
|
|
|
|
; IM0 ENTRY POINT |
|
|
|
|
|
; |
|
|
SIO_INT: |
|
|
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 |
|
|
|
|
|
JR Z,SIOA_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED |
|
|
|
|
|
INC A ; INCREMENT THE COUNT |
|
|
|
|
|
LD (SIOA_CNT),A ; AND SAVE IT |
|
|
|
|
|
CP SIOA_BUFSZ / 2 ; 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 |
|
|
|
|
|
; |
|
|
|
|
|
SIOA_INT2: |
|
|
|
|
|
; 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 |
|
|
|
|
|
|
|
|
; CHECK/HANDLE FIRST CARD (SIO0) IF IT EXISTS |
|
|
|
|
|
LD A,(SIO0A_CFG + 1) ; GET SIO TYPE FOR FIRST CHANNEL OF FIRST SIO |
|
|
|
|
|
OR A ; SET FLAGS |
|
|
|
|
|
CALL NZ,SIO_INT0 ; CALL IF CARD EXISTS |
|
|
|
|
|
RET NZ ; DONE IF INT HANDLED |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
; CHECK/HANDLE SECOND CARD (SIO1) IF IT EXISTS |
|
|
|
|
|
LD A,(SIO1A_CFG + 1) ; GET SIO TYPE FOR FIRST CHANNEL OF SECOND SIO |
|
|
|
|
|
OR A ; SET FLAGS |
|
|
|
|
|
CALL NZ,SIO_INT1 ; CALL IF CARD EXISTS |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
RET ; DONE |
|
|
|
|
|
; |
|
|
|
|
|
; IM1 ENTRY POINTS |
|
|
|
|
|
; |
|
|
|
|
|
SIO_INT0: |
|
|
|
|
|
; INTERRUPT HANDLER FOR FIRST SIO (SIO0) |
|
|
|
|
|
LD IY,SIO0A_CFG ; POINT TO SIO0A CFG |
|
|
|
|
|
CALL SIO_INTRCV ; TRY TO RECEIVE FROM IT |
|
|
|
|
|
RET NZ ; DONE IF INT HANDLED |
|
|
|
|
|
LD IY,SIO0B_CFG ; POINT TO SIO0B CFG |
|
|
|
|
|
JR SIO_INTRCV ; TRY TO RECEIVE FROM IT AND RETURN |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
; |
|
|
; |
|
|
SIOB_INT: |
|
|
|
|
|
; CHECK FOR RECEIVE PENDING ON CHANNEL B |
|
|
|
|
|
|
|
|
SIO_INT1: |
|
|
|
|
|
; INTERRUPT HANDLER FOR SECOND SIO (SIO1) |
|
|
|
|
|
LD IY,SIO1A_CFG ; POINT TO SIO1A CFG |
|
|
|
|
|
CALL SIO_INTRCV ; TRY TO RECEIVE FROM IT |
|
|
|
|
|
RET NZ ; DONE IF INT HANDLED |
|
|
|
|
|
LD IY,SIO1B_CFG ; POINT TO SIO1B CFG |
|
|
|
|
|
JR SIO_INTRCV ; TRY TO RECEIVE FROM IT AND RETURN |
|
|
|
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
; HANDLE INT FOR A SPECIFIC CHANNEL |
|
|
|
|
|
; BASED ON UNIT CFG POINTED TO BY IY |
|
|
|
|
|
; |
|
|
|
|
|
SIO_INTRCV: |
|
|
|
|
|
; CHECK TO SEE IF SOMETHING IS ACTUALLY THERE |
|
|
|
|
|
LD C,(IY+3) ; CMD/STAT PORT TO C |
|
|
XOR A ; A := 0 |
|
|
XOR A ; A := 0 |
|
|
OUT (SIOB_CMD),A ; ADDRESS RD0 |
|
|
|
|
|
IN A,(SIOB_CMD) ; GET RD0 |
|
|
|
|
|
|
|
|
OUT (C),A ; ADDRESS RD0 |
|
|
|
|
|
IN A,(C) ; GET RD0 |
|
|
AND $01 ; ISOLATE RECEIVE READY BIT |
|
|
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 |
|
|
|
|
|
JR Z,SIOB_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED |
|
|
|
|
|
|
|
|
RET Z ; NOTHING AVAILABLE ON CURRENT CHANNEL |
|
|
|
|
|
; |
|
|
|
|
|
SIO_INTRCV1: |
|
|
|
|
|
; RECEIVE CHARACTER INTO BUFFER |
|
|
|
|
|
LD C,(IY+4) ; DATA PORT TO C |
|
|
|
|
|
IN A,(C) ; READ PORT |
|
|
|
|
|
LD B,A ; SAVE BYTE READ |
|
|
|
|
|
LD L,(IY+7) ; SET HL TO |
|
|
|
|
|
LD H,(IY+8) ; ... START OF BUFFER STRUCT |
|
|
|
|
|
LD A,(HL) ; GET COUNT |
|
|
|
|
|
CP SIO_BUFSZ ; COMPARE TO BUFFER SIZE |
|
|
|
|
|
JR Z,SIO_INTRCV4 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED |
|
|
INC A ; INCREMENT THE COUNT |
|
|
INC A ; INCREMENT THE COUNT |
|
|
LD (SIOB_CNT),A ; AND SAVE IT |
|
|
|
|
|
CP SIOB_BUFSZ / 2 ; BUFFER GETTING FULL? |
|
|
|
|
|
JR NZ,SIOB_INT0 ; IF NOT, BYPASS CLEARING RTS |
|
|
|
|
|
|
|
|
LD (HL),A ; AND SAVE IT |
|
|
|
|
|
CP SIO_BUFSZ / 2 ; BUFFER GETTING FULL? |
|
|
|
|
|
JR NZ,SIO_INTRCV2 ; IF NOT, BYPASS CLEARING RTS |
|
|
|
|
|
LD C,(IY+3) ; CMD/STAT PORT TO C |
|
|
LD A,5 ; RTS IS IN WR5 |
|
|
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 |
|
|
|
|
|
; |
|
|
|
|
|
SIOB_INT2: |
|
|
|
|
|
|
|
|
OUT (C),A ; ADDRESS WR5 |
|
|
|
|
|
LD A,SIO_RTSOFF ; VALUE TO CLEAR RTS |
|
|
|
|
|
OUT (C),A ; DO IT |
|
|
|
|
|
SIO_INTRCV2: |
|
|
|
|
|
INC HL ; HL NOW HAS ADR OF HEAD PTR |
|
|
|
|
|
PUSH HL ; SAVE ADR OF HEAD PTR |
|
|
|
|
|
LD A,(HL) ; DEREFERENCE HL |
|
|
|
|
|
INC HL |
|
|
|
|
|
LD H,(HL) |
|
|
|
|
|
LD L,A ; HL IS NOW ACTUAL HEAD PTR |
|
|
|
|
|
LD (HL),B ; SAVE CHARACTER RECEIVED IN BUFFER AT HEAD |
|
|
|
|
|
INC HL ; BUMP HEAD POINTER |
|
|
|
|
|
POP DE ; RECOVER ADR OF HEAD PTR |
|
|
|
|
|
LD A,L ; GET LOW BYTE OF HEAD PTR |
|
|
|
|
|
ADD A,-SIO_BUFSZ-4 ; SUBTRACT SIZE OF BUFFER AND POINTER |
|
|
|
|
|
CP E ; IF EQUAL TO START, HEAD PTR IS PAST BUF END |
|
|
|
|
|
JR NZ,SIO_INTRCV3 ; IF NOT, BYPASS |
|
|
|
|
|
LD H,D ; SET HL TO |
|
|
|
|
|
LD L,E ; ... HEAD PTR ADR |
|
|
|
|
|
INC HL ; BUMP PAST HEAD PTR |
|
|
|
|
|
INC HL |
|
|
|
|
|
INC HL |
|
|
|
|
|
INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START |
|
|
|
|
|
SIO_INTRCV3: |
|
|
|
|
|
EX DE,HL ; DE := HEAD PTR VAL, HL := ADR OF HEAD PTR |
|
|
|
|
|
LD (HL),E ; SAVE UPDATED HEAD PTR |
|
|
|
|
|
INC HL |
|
|
|
|
|
LD (HL),D |
|
|
; CHECK FOR MORE PENDING... |
|
|
; CHECK FOR MORE PENDING... |
|
|
|
|
|
LD C,(IY+3) ; CMD/STAT PORT TO C |
|
|
XOR A ; A := 0 |
|
|
XOR A ; A := 0 |
|
|
OUT (SIOB_CMD),A ; ADDRESS RD0 |
|
|
|
|
|
IN A,(SIOB_CMD) ; GET RD0 |
|
|
|
|
|
|
|
|
OUT (C),A ; ADDRESS RD0 |
|
|
|
|
|
IN A,(C) ; GET RD0 |
|
|
RRA ; READY BIT TO CF |
|
|
RRA ; READY BIT TO CF |
|
|
JR C,SIOB_INT00 ; IF SET, DO SOME MORE |
|
|
|
|
|
|
|
|
JR C,SIO_INTRCV1 ; IF SET, DO SOME MORE |
|
|
|
|
|
SIO_INTRCV4: |
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED |
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED |
|
|
RET ; AND RETURN |
|
|
RET ; AND RETURN |
|
|
; |
|
|
; |
|
|
@ -274,17 +326,7 @@ SIO_FNTBL: |
|
|
SIO_IN: |
|
|
SIO_IN: |
|
|
CALL SIO_IST ; CHAR WAITING? |
|
|
CALL SIO_IST ; CHAR WAITING? |
|
|
JR Z,SIO_IN ; LOOP IF NOT |
|
|
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 |
|
|
|
|
|
#IF (SIOMODE == SIOMODE_EZZ80) |
|
|
|
|
|
DEC C ; DECREMENT CMD PORT TO GET DATA PORT |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
|
|
|
LD C,(IY+4) ; DATA PORT |
|
|
IN E,(C) ; GET CHAR |
|
|
IN E,(C) ; GET CHAR |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
RET |
|
|
RET |
|
|
@ -292,68 +334,50 @@ SIO_IN: |
|
|
#ELSE |
|
|
#ELSE |
|
|
; |
|
|
; |
|
|
SIO_IN: |
|
|
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 |
|
|
|
|
|
|
|
|
CALL SIO_IST ; SEE IF CHAR AVAILABLE |
|
|
|
|
|
JR Z,SIO_IN ; LOOP UNTIL SO |
|
|
HB_DI ; AVOID COLLISION WITH INT HANDLER |
|
|
HB_DI ; AVOID COLLISION WITH INT HANDLER |
|
|
LD A,(SIOA_CNT) ; GET COUNT |
|
|
|
|
|
|
|
|
LD L,(IY+7) ; SET HL TO |
|
|
|
|
|
LD H,(IY+8) ; ... START OF BUFFER STRUCT |
|
|
|
|
|
LD A,(HL) ; GET COUNT |
|
|
DEC A ; DECREMENT COUNT |
|
|
DEC A ; DECREMENT COUNT |
|
|
LD (SIOA_CNT),A ; SAVE SAVE IT |
|
|
|
|
|
CP SIOA_BUFSZ / 4 ; BUFFER LOW THRESHOLD |
|
|
|
|
|
JR NZ,SIOA_IN0 ; IF NOT, BYPASS SETTING RTS |
|
|
|
|
|
|
|
|
LD (HL),A ; SAVE UPDATED COUNT |
|
|
|
|
|
CP SIO_BUFSZ / 4 ; BUFFER LOW THRESHOLD |
|
|
|
|
|
JR NZ,SIO_IN1 ; IF NOT, BYPASS SETTING RTS |
|
|
|
|
|
LD C,(IY+3) ; C IS CMD/STATUS PORT ADR |
|
|
LD A,5 ; RTS IS IN WR5 |
|
|
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 SIOB_BUFSZ / 4 ; 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 |
|
|
|
|
|
|
|
|
OUT (C),A ; ADDRESS WR5 |
|
|
|
|
|
LD A,SIO_RTSON ; VALUE TO SET RTS |
|
|
|
|
|
OUT (C),A ; DO IT |
|
|
|
|
|
SIO_IN1: |
|
|
|
|
|
INC HL |
|
|
|
|
|
INC HL |
|
|
|
|
|
INC HL ; HL NOW HAS ADR OF TAIL PTR |
|
|
|
|
|
PUSH HL ; SAVE ADR OF TAIL PTR |
|
|
|
|
|
LD A,(HL) ; DEREFERENCE HL |
|
|
|
|
|
INC HL |
|
|
|
|
|
LD H,(HL) |
|
|
|
|
|
LD L,A ; HL IS NOW ACTUAL TAIL PTR |
|
|
|
|
|
LD C,(HL) ; C := CHAR TO BE RETURNED |
|
|
|
|
|
INC HL ; BUMP TAIL PTR |
|
|
|
|
|
POP DE ; RECOVER ADR OF TAIL PTR |
|
|
|
|
|
LD A,L ; GET LOW BYTE OF TAIL PTR |
|
|
|
|
|
ADD A,-SIO_BUFSZ-2 ; SUBTRACT SIZE OF BUFFER AND POINTER |
|
|
|
|
|
CP E ; IF EQUAL TO START, TAIL PTR IS PAST BUF END |
|
|
|
|
|
JR NZ,SIO_IN2 ; IF NOT, BYPASS |
|
|
|
|
|
LD H,D ; SET HL TO |
|
|
|
|
|
LD L,E ; ... TAIL PTR ADR |
|
|
|
|
|
INC HL ; BUMP PAST TAIL PTR |
|
|
|
|
|
INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START |
|
|
|
|
|
SIO_IN2: |
|
|
|
|
|
EX DE,HL ; DE := TAIL PTR VAL, HL := ADR OF TAIL PTR |
|
|
|
|
|
LD (HL),E ; SAVE UPDATED TAIL PTR |
|
|
|
|
|
INC HL |
|
|
|
|
|
LD (HL),D |
|
|
|
|
|
LD E,C ; MOVE CHAR TO RETURN TO E |
|
|
HB_EI ; INTERRUPTS OK AGAIN |
|
|
HB_EI ; INTERRUPTS OK AGAIN |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
RET ; AND DONE |
|
|
RET ; AND DONE |
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
@ -361,17 +385,7 @@ SIOB_IN1: |
|
|
SIO_OUT: |
|
|
SIO_OUT: |
|
|
CALL SIO_OST ; READY FOR CHAR? |
|
|
CALL SIO_OST ; READY FOR CHAR? |
|
|
JR Z,SIO_OUT ; LOOP IF NOT |
|
|
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 |
|
|
|
|
|
#IF (SIOMODE == SIOMODE_EZZ80) |
|
|
|
|
|
DEC C ; DECREMENT CMD PORT TO GET DATA PORT |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
|
|
|
LD C,(IY+4) ; DATA PORT |
|
|
OUT (C),E ; SEND CHAR FROM E |
|
|
OUT (C),E ; SEND CHAR FROM E |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
RET |
|
|
RET |
|
|
@ -394,25 +408,12 @@ SIO_IST: |
|
|
#ELSE |
|
|
#ELSE |
|
|
; |
|
|
; |
|
|
SIO_IST: |
|
|
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 |
|
|
|
|
|
|
|
|
LD L,(IY+7) ; GET ADDRESS |
|
|
|
|
|
LD H,(IY+8) ; ... OF RECEIVE BUFFER |
|
|
|
|
|
LD A,(HL) ; BUFFER UTILIZATION COUNT |
|
|
OR A ; SET FLAGS |
|
|
OR A ; SET FLAGS |
|
|
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING |
|
|
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 |
|
|
|
|
|
|
|
|
RET |
|
|
; |
|
|
; |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
@ -459,8 +460,8 @@ SIO_INITDEVX: |
|
|
JR NZ,SIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG |
|
|
JR NZ,SIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG |
|
|
; |
|
|
; |
|
|
; LOAD EXISTING CONFIG TO REINIT |
|
|
; LOAD EXISTING CONFIG TO REINIT |
|
|
LD E,(IY+4) ; LOW BYTE |
|
|
|
|
|
LD D,(IY+5) ; HIGH BYTE |
|
|
|
|
|
|
|
|
LD E,(IY+5) ; LOW BYTE |
|
|
|
|
|
LD D,(IY+6) ; HIGH BYTE |
|
|
; |
|
|
; |
|
|
SIO_INITDEV1: |
|
|
SIO_INITDEV1: |
|
|
PUSH DE ; SAVE CONFIG |
|
|
PUSH DE ; SAVE CONFIG |
|
|
@ -573,12 +574,37 @@ BROK: |
|
|
CALL PRTHEXBYTE |
|
|
CALL PRTHEXBYTE |
|
|
PRTC(']') |
|
|
PRTC(']') |
|
|
POP AF |
|
|
POP AF |
|
|
#ENDIF |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
; SET INTERRUPT VECTOR OFFSET WR2 |
|
|
|
|
|
; |
|
|
|
|
|
#IF (INTMODE == 2) |
|
|
|
|
|
LD A,(IY+2) ; CHIP / CHANNEL |
|
|
|
|
|
SRL A ; SHIFT AWAY CHANNEL BIT |
|
|
|
|
|
LD E,IVT_SER0 ; ASSUME CHIP 0 |
|
|
|
|
|
JR Z,SIO_IVT1 ; IF SO, DO IT |
|
|
|
|
|
LD E,IVT_SER1 ; ASSUME CHIP 1 |
|
|
|
|
|
DEC A ; CHIP 1? |
|
|
|
|
|
JR Z,SIO_IVT1 ; IF SO, TO IT |
|
|
|
|
|
CALL PANIC ; IMPOSSIBLE SITUATION |
|
|
|
|
|
SIO_IVT1: |
|
|
|
|
|
LD A,E ; VALUE TO A |
|
|
|
|
|
LD (SIO_INITVALS+7),A ; SAVE IT |
|
|
|
|
|
|
|
|
|
|
|
#IF (SIODEBUG) |
|
|
|
|
|
PUSH AF |
|
|
|
|
|
PRTS(" WR2[$") |
|
|
|
|
|
CALL PRTHEXBYTE |
|
|
|
|
|
PRTC(']') |
|
|
|
|
|
POP AF |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
|
|
|
|
|
|
#ENDIF |
|
|
|
|
|
|
|
|
POP DE ; RESTORE CONFIG |
|
|
POP DE ; RESTORE CONFIG |
|
|
|
|
|
|
|
|
LD (IY+4),E ; SAVE LOW WORD |
|
|
|
|
|
LD (IY+5),D ; SAVE HI WORD |
|
|
|
|
|
|
|
|
LD (IY+5),E ; SAVE LOW WORD |
|
|
|
|
|
LD (IY+6),D ; SAVE HI WORD |
|
|
; |
|
|
; |
|
|
; PROGRAM THE SIO CHIP CHANNEL |
|
|
; PROGRAM THE SIO CHIP CHANNEL |
|
|
LD C,(IY+3) ; COMMAND PORT |
|
|
LD C,(IY+3) ; COMMAND PORT |
|
|
@ -589,8 +615,8 @@ BROK: |
|
|
#IF (INTMODE > 0) |
|
|
#IF (INTMODE > 0) |
|
|
; |
|
|
; |
|
|
; RESET THE RECEIVE BUFFER |
|
|
; RESET THE RECEIVE BUFFER |
|
|
LD E,(IY+6) |
|
|
|
|
|
LD D,(IY+7) ; DE := _CNT |
|
|
|
|
|
|
|
|
LD E,(IY+7) |
|
|
|
|
|
LD D,(IY+8) ; DE := _CNT |
|
|
XOR A ; A := 0 |
|
|
XOR A ; A := 0 |
|
|
LD (DE),A ; _CNT = 0 |
|
|
LD (DE),A ; _CNT = 0 |
|
|
INC DE ; DE := ADR OF _HD |
|
|
INC DE ; DE := ADR OF _HD |
|
|
@ -622,16 +648,16 @@ SIO_INITVALS: |
|
|
#ELSE |
|
|
#ELSE |
|
|
.DB $01, $18 ; WR1: INTERRUPT ON ALL RECEIVE CHARACTERS |
|
|
.DB $01, $18 ; WR1: INTERRUPT ON ALL RECEIVE CHARACTERS |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
.DB $02, IVT_SER0 ; WR2: INTERRUPT VECTOR OFFSET |
|
|
|
|
|
|
|
|
.DB $02, IVT_SER0 ; WR2: IM2 INTERRUPT VECTOR OFFSET |
|
|
.DB $03, $E1 ; WR3: 8 BIT RCV, CTS/DCD AUTO, RX ENABLE |
|
|
.DB $03, $E1 ; WR3: 8 BIT RCV, CTS/DCD AUTO, 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) |
|
|
|
|
|
|
|
|
.DB $05, SIO_RTSON ; 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_INITLEN .EQU $ - SIO_INITVALS |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
SIO_QUERY: |
|
|
SIO_QUERY: |
|
|
LD E,(IY+4) ; FIRST CONFIG BYTE TO E |
|
|
|
|
|
LD D,(IY+5) ; SECOND CONFIG BYTE TO D |
|
|
|
|
|
|
|
|
LD E,(IY+5) ; FIRST CONFIG BYTE TO E |
|
|
|
|
|
LD D,(IY+6) ; SECOND CONFIG BYTE TO D |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
RET ; DONE |
|
|
RET ; DONE |
|
|
; |
|
|
; |
|
|
@ -644,21 +670,86 @@ SIO_DEVICE: |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
XOR A ; SIGNAL SUCCESS |
|
|
RET |
|
|
RET |
|
|
; |
|
|
; |
|
|
|
|
|
; SIO CHIP PROBE |
|
|
|
|
|
; CHECK FOR PRESENCE OF SIO CHIPS AND POPULATE THE |
|
|
|
|
|
; SIO_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! |
|
|
|
|
|
; |
|
|
|
|
|
SIO_PROBE: |
|
|
|
|
|
; CLEAR THE PRESENCE BITMAP |
|
|
|
|
|
LD HL,SIO_MAP ; HL POINTS TO BITMAP |
|
|
|
|
|
XOR A ; ZERO |
|
|
|
|
|
LD (SIO_MAP),A ; CLEAR CHIP PRESENT BITMAP |
|
|
|
|
|
; INIT THE INT VEC REGISTER OF ALL POSSIBLE CHIPS |
|
|
|
|
|
; TO ZERO. A IS STILL ZERO. |
|
|
|
|
|
LD B,2 ; WR2 REGISTER (INT VEC) |
|
|
|
|
|
LD C,SIO0B_CMD ; FIRST CHIP |
|
|
|
|
|
CALL SIO_WR ; WRITE ZERO TO CHIP REG |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
LD C,SIO1B_CMD ; SECOND CHIP |
|
|
|
|
|
CALL SIO_WR ; WRITE ZERO TO CHIP REG |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; FIRST POSSIBLE CHIP |
|
|
|
|
|
LD C,SIO0B_CMD ; FIRST CHIP CMD/STAT PORT |
|
|
|
|
|
CALL SIO_PROBECHIP ; PROBE IT |
|
|
|
|
|
JR NZ,SIO_PROBE1 ; IF NOT ZERO, NOT FOUND |
|
|
|
|
|
SET 0,(HL) ; SET BIT FOR FIRST CARD |
|
|
|
|
|
SIO_PROBE1: |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
LD C,SIO1B_CMD ; SECOND CHIP CMD/STAT PORT |
|
|
|
|
|
CALL SIO_PROBECHIP ; PROBE IT |
|
|
|
|
|
JR NZ,SIO_PROBE2 ; IF NOT ZERO, NOT FOUND |
|
|
|
|
|
SET 1,(HL) ; SET BIT FOR SECOND CARD |
|
|
|
|
|
SIO_PROBE2: |
|
|
|
|
|
#ENDIF |
|
|
|
|
|
; |
|
|
|
|
|
RET |
|
|
|
|
|
; |
|
|
|
|
|
SIO_PROBECHIP: |
|
|
|
|
|
; READ WR2 TO ENSURE IT IS ZERO (AVOID PHANTOM PORTS) |
|
|
|
|
|
CALL SIO_RD ; GET VALUE |
|
|
|
|
|
AND $F0 ; ONLY TOP NIBBLE |
|
|
|
|
|
RET NZ ; ABORT IF NOT ZERO |
|
|
|
|
|
; WRITE INT VEC VALUE TO WR2 |
|
|
|
|
|
LD A,$FF ; TEST VALUE |
|
|
|
|
|
CALL SIO_WR ; WRITE IT |
|
|
|
|
|
; READ WR2 TO CONFIRM VALUE WRITTEN |
|
|
|
|
|
CALL SIO_RD ; REREAD VALUE |
|
|
|
|
|
AND $F0 ; ONLY TOP NIBBLE |
|
|
|
|
|
CP $F0 ; COMPARE |
|
|
|
|
|
RET ; DONE, Z IF FOUND, NZ IF MISCOMPARE |
|
|
|
|
|
; |
|
|
|
|
|
; READ/WRITE CHIP REGISTER. ENTER CHIP CMD/STAT PORT ADR IN C |
|
|
|
|
|
; AND CHIP REGISTER NUMBER IN B. VALUE TO WRITE IN A OR VALUE |
|
|
|
|
|
; RETURNED IN A. |
|
|
|
|
|
; |
|
|
|
|
|
SIO_WR: |
|
|
|
|
|
OUT (C),B ; SELECT CHIP REGISTER |
|
|
|
|
|
OUT (C),A ; WRITE VALUE |
|
|
|
|
|
RET |
|
|
|
|
|
; |
|
|
|
|
|
SIO_RD: |
|
|
|
|
|
OUT (C),B ; SELECT CHIP REGISTER |
|
|
|
|
|
IN A,(C) ; GET VALUE |
|
|
|
|
|
RET |
|
|
|
|
|
; |
|
|
; SIO DETECTION ROUTINE |
|
|
; SIO DETECTION ROUTINE |
|
|
; |
|
|
; |
|
|
SIO_DETECT: |
|
|
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 |
|
|
|
|
|
|
|
|
LD B,(IY+2) ; GET CHIP/CHANNEL |
|
|
|
|
|
SRL B ; SHIFT AWAY THE CHANNEL BIT |
|
|
|
|
|
INC B ; NUMBER OF TIMES TO ROTATE BITS |
|
|
|
|
|
LD A,(SIO_MAP) ; BIT MAP IN A |
|
|
|
|
|
SIO_DETECT1: |
|
|
|
|
|
; ROTATE DESIRED CHIP BIT INTO CF |
|
|
|
|
|
RRA ; ROTATE NEXT BIT INTO CF |
|
|
|
|
|
DJNZ SIO_DETECT1 ; DO THIS UNTIL WE HAVE DESIRED BIT |
|
|
|
|
|
; RETURN CHIP TYPE |
|
|
|
|
|
LD A,SIO_NONE ; ASSUME NOTHING HERE |
|
|
|
|
|
RET NC ; IF CF NOT SET, RETURN |
|
|
|
|
|
LD A,SIO_SIO ; CHIP TYPE IS SIO |
|
|
RET ; DONE |
|
|
RET ; DONE |
|
|
; |
|
|
; |
|
|
; |
|
|
; |
|
|
@ -690,8 +781,8 @@ SIO_PRTCFG: |
|
|
RET Z ; IF ZERO, NOT PRESENT |
|
|
RET Z ; IF ZERO, NOT PRESENT |
|
|
; |
|
|
; |
|
|
PRTS(" MODE=$") ; FORMATTING |
|
|
PRTS(" MODE=$") ; FORMATTING |
|
|
LD E,(IY+4) ; LOAD CONFIG |
|
|
|
|
|
LD D,(IY+5) ; ... WORD TO DE |
|
|
|
|
|
|
|
|
LD E,(IY+5) ; LOAD CONFIG |
|
|
|
|
|
LD D,(IY+6) ; ... WORD TO DE |
|
|
CALL PS_PRTSC0 ; PRINT CONFIG |
|
|
CALL PS_PRTSC0 ; PRINT CONFIG |
|
|
; |
|
|
; |
|
|
XOR A |
|
|
XOR A |
|
|
@ -709,51 +800,101 @@ SIO_STR_SIO .DB "SIO$" |
|
|
; WORKING VARIABLES |
|
|
; WORKING VARIABLES |
|
|
; |
|
|
; |
|
|
SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT |
|
|
SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT |
|
|
|
|
|
SIO_MAP .DB 0 ; CHIP PRESENCE BITMAP |
|
|
; |
|
|
; |
|
|
#IF (INTMODE == 0) |
|
|
#IF (INTMODE == 0) |
|
|
; |
|
|
; |
|
|
SIOA_RCVBUF .EQU 0 |
|
|
|
|
|
SIOB_RCVBUF .EQU 0 |
|
|
|
|
|
|
|
|
SIO0A_RCVBUF .EQU 0 |
|
|
|
|
|
SIO0B_RCVBUF .EQU 0 |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
SIO1A_RCVBUF .EQU 0 |
|
|
|
|
|
SIO1B_RCVBUF .EQU 0 |
|
|
|
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
#ELSE |
|
|
#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 |
|
|
|
|
|
|
|
|
; SIO0 CHANNEL A RECEIVE BUFFER |
|
|
|
|
|
SIO0A_RCVBUF: |
|
|
|
|
|
SIO0A_CNT .DB 0 ; CHARACTERS IN RING BUFFER |
|
|
|
|
|
SIO0A_HD .DW SIO0A_BUF ; BUFFER HEAD POINTER |
|
|
|
|
|
SIO0A_TL .DW SIO0A_BUF ; BUFFER TAIL POINTER |
|
|
|
|
|
SIO0A_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER |
|
|
|
|
|
; |
|
|
|
|
|
; SIO0 CHANNEL B RECEIVE BUFFER |
|
|
|
|
|
SIO0B_RCVBUF: |
|
|
|
|
|
SIO0B_CNT .DB 0 ; CHARACTERS IN RING BUFFER |
|
|
|
|
|
SIO0B_HD .DW SIO0B_BUF ; BUFFER HEAD POINTER |
|
|
|
|
|
SIO0B_TL .DW SIO0B_BUF ; BUFFER TAIL POINTER |
|
|
|
|
|
SIO0B_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
; |
|
|
|
|
|
; SIO1 CHANNEL A RECEIVE BUFFER |
|
|
|
|
|
SIO1A_RCVBUF: |
|
|
|
|
|
SIO1A_CNT .DB 0 ; CHARACTERS IN RING BUFFER |
|
|
|
|
|
SIO1A_HD .DW SIO1A_BUF ; BUFFER HEAD POINTER |
|
|
|
|
|
SIO1A_TL .DW SIO1A_BUF ; BUFFER TAIL POINTER |
|
|
|
|
|
SIO1A_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER |
|
|
|
|
|
; |
|
|
|
|
|
; SIO1 CHANNEL B RECEIVE BUFFER |
|
|
|
|
|
SIO1B_RCVBUF: |
|
|
|
|
|
SIO1B_CNT .DB 0 ; CHARACTERS IN RING BUFFER |
|
|
|
|
|
SIO1B_HD .DW SIO1B_BUF ; BUFFER HEAD POINTER |
|
|
|
|
|
SIO1B_TL .DW SIO1B_BUF ; BUFFER TAIL POINTER |
|
|
|
|
|
SIO1B_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER |
|
|
|
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
#ENDIF |
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
; SIO PORT TABLE |
|
|
; SIO PORT TABLE |
|
|
; |
|
|
; |
|
|
SIO_CFG: |
|
|
SIO_CFG: |
|
|
; SIO CHANNEL A |
|
|
|
|
|
|
|
|
; SIO0 CHANNEL A |
|
|
|
|
|
SIO0A_CFG: |
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
.DB 0 ; SIO TYPE (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 |
|
|
|
|
|
|
|
|
.DB $00 ; CHIP 0 / CHANNEL A (LOW BIT IS CHANNEL) |
|
|
|
|
|
.DB SIO0A_CMD ; CMD/STATUS PORT |
|
|
|
|
|
.DB SIO0A_DAT ; DATA PORT |
|
|
|
|
|
.DW DEFSIO0ACFG ; LINE CONFIGURATION |
|
|
|
|
|
.DW SIO0A_RCVBUF ; POINTER TO RCV BUFFER STRUCT |
|
|
; |
|
|
; |
|
|
; SIO CHANNEL B |
|
|
|
|
|
|
|
|
SIO_CFGSIZ .EQU $ - SIO_CFG ; SIZE OF ONE CFG TABLE ENTRY |
|
|
|
|
|
; |
|
|
|
|
|
; SIO0 CHANNEL B |
|
|
|
|
|
SIO0B_CFG: |
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
.DB 0 ; SIO TYPE (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 |
|
|
|
|
|
|
|
|
.DB $01 ; CHIP 0 / CHANNEL B (LOW BIT IS CHANNEL) |
|
|
|
|
|
.DB SIO0B_CMD ; CMD/STATUS PORT |
|
|
|
|
|
.DB SIO0B_DAT ; DATA PORT |
|
|
|
|
|
.DW DEFSIO0BCFG ; LINE CONFIGURATION |
|
|
|
|
|
.DW SIO0B_RCVBUF ; POINTER TO RCV BUFFER STRUCT |
|
|
|
|
|
; |
|
|
|
|
|
#IF (SIOCNT >= 2) |
|
|
|
|
|
; |
|
|
|
|
|
; SIO1 CHANNEL A |
|
|
|
|
|
SIO1A_CFG: |
|
|
|
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
|
|
|
.DB 0 ; SIO TYPE (SET DURING INIT) |
|
|
|
|
|
.DB $02 ; CHIP 1 / CHANNEL A (LOW BIT IS CHANNEL) |
|
|
|
|
|
.DB SIO1A_CMD ; CMD/STATUS PORT |
|
|
|
|
|
.DB SIO1A_DAT ; DATA PORT |
|
|
|
|
|
.DW DEFSIO1ACFG ; LINE CONFIGURATION |
|
|
|
|
|
.DW SIO1A_RCVBUF ; POINTER TO RCV BUFFER STRUCT |
|
|
|
|
|
; |
|
|
|
|
|
; SIO1 CHANNEL B |
|
|
|
|
|
SIO1B_CFG: |
|
|
|
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT) |
|
|
|
|
|
.DB 0 ; SIO TYPE (SET DURING INIT) |
|
|
|
|
|
.DB $03 ; CHIP 1 / CHANNEL B (LOW BIT IS CHANNEL) |
|
|
|
|
|
.DB SIO1B_CMD ; CMD/STATUS PORT |
|
|
|
|
|
.DB SIO1B_DAT ; DATA PORT |
|
|
|
|
|
.DW DEFSIO1BCFG ; LINE CONFIGURATION |
|
|
|
|
|
.DW SIO1B_RCVBUF ; POINTER TO RCV BUFFER STRUCT |
|
|
|
|
|
; |
|
|
|
|
|
#ENDIF |
|
|
; |
|
|
; |
|
|
SIO_CNT .EQU ($ - SIO_CFG) / 8 |
|
|
|
|
|
|
|
|
SIO_CFGCNT .EQU ($ - SIO_CFG) / SIO_CFGSIZ |
|
|
|