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.
600 lines
15 KiB
600 lines
15 KiB
;
|
|
;==================================================================================================
|
|
; ACIA 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) --
|
|
;
|
|
; CURRENTLY ONLY SUPPORTS A SINGLE CHIP IN SYSTEM
|
|
;
|
|
ACIA_DEBUG .EQU FALSE
|
|
;
|
|
ACIA_NONE .EQU 0
|
|
ACIA_ACIA .EQU 1
|
|
;
|
|
; POSSIBLE BASE I/O ADDRESSES
|
|
; NOTE THAT THE ACIA ONLY QUALIFIES ADDRESS BITS 7 & 6, SO
|
|
; THE ACIA'S TWO PORTS APPEAR REPEATEDLY OVER AN ADDRESS RANGE
|
|
; OF $40 STARTING FROM THE REAL BASE PORT.
|
|
; WE TAKE ADVANTAGE OF THIS TO AVOID CONFLICTING WITH SIO
|
|
; AND COMPACT FLASH MODULES DURING DETECTION PROBES.
|
|
;
|
|
ACIAA_BASE .EQU $80 + $20 ; MODULE A
|
|
ACIAB_BASE .EQU $40 + $20 ; MODULE B
|
|
;
|
|
#IF (INTMODE == 0)
|
|
;
|
|
ACIA_RTSON .EQU %00010110 ; NO RCV INT, RTS ASSERTED, 8N1, CLK/64 BAUD
|
|
ACIA_RTSOFF .EQU %01010110 ; NO RCV INT, RTS DEASSERTED, 8N1, CLK/64 BAUD
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE == 1)
|
|
;
|
|
ACIA_RTSON .EQU %10010110 ; RCV INT, RTS ASSERTED, 8N1, CLK/64 BAUD
|
|
ACIA_RTSOFF .EQU %11010110 ; RCV INT, RTS DEASSERTED, 8N1, CLK/64 BAUD
|
|
;
|
|
#ENDIF
|
|
|
|
#IF (INTMODE > 1)
|
|
.ECHO "*** ERROR: UNSUPPORTED INTMODE FOR ACIA DRIVER!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
ACIA_PREINIT:
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN
|
|
; DISABLED.
|
|
;
|
|
LD B,ACIA_CNT ; LOOP CONTROL
|
|
LD C,0 ; PHYSICAL UNIT INDEX
|
|
XOR A ; ZERO TO ACCUM
|
|
LD (ACIA_DEV),A ; CURRENT DEVICE NUMBER
|
|
ACIA_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,ACIA_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 ACIA_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 ACIA TYPE DETECTED
|
|
OR A ; SET FLAGS
|
|
JR Z,ACIA_PREINIT2 ; SKIP IT IF NOTHING FOUND
|
|
;
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
LD BC,ACIA_FNTBL ; BC := FUNCTION TABLE ADDRESS
|
|
CALL NZ,CIO_ADDENT ; ADD ENTRY IF ACIA FOUND, BC:DE
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
;
|
|
ACIA_PREINIT2:
|
|
INC C ; NEXT PHYSICAL UNIT
|
|
DJNZ ACIA_PREINIT0 ; LOOP UNTIL DONE
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
; ACIA INITIALIZATION ROUTINE
|
|
;
|
|
ACIA_INITUNIT:
|
|
CALL ACIA_DETECT ; DETERMINE ACIA TYPE
|
|
LD (IY+1),A ; SAVE IN CONFIG TABLE
|
|
OR A ; SET FLAGS
|
|
RET Z ; ABORT IF NOTHING THERE
|
|
|
|
; UPDATE WORKING ACIA DEVICE NUM
|
|
LD HL,ACIA_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
|
|
;
|
|
#IF (INTMODE == 1)
|
|
; ADD IM1 INT CALL LIST ENTRY
|
|
LD L,(IY+6) ; GET RCVBUF PTR
|
|
LD H,(IY+7) ; ... INTO HL
|
|
LD A,5 ; OFFSET OF INT HANDLER PTR
|
|
CALL ADDHLA ; ADD TO HL
|
|
LD A,(HL) ; DEREFERENCE
|
|
INC HL ; ...
|
|
LD H,(HL) ; ...
|
|
LD L,A ; ...
|
|
CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST
|
|
#ENDIF
|
|
|
|
; SET DEFAULT CONFIG
|
|
LD DE,-1 ; LEAVE CONFIG ALONE
|
|
; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL
|
|
; THE INITDEV ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS!
|
|
JP ACIA_INITDEVX ; IMPLEMENT IT AND RETURN
|
|
;
|
|
;
|
|
;
|
|
ACIA_INIT:
|
|
LD B,ACIA_CNT ; COUNT OF POSSIBLE ACIA UNITS
|
|
LD C,0 ; INDEX INTO ACIA CONFIG TABLE
|
|
ACIA_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,ACIA_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 ACIA TYPE
|
|
OR A ; SET FLAGS
|
|
CALL NZ,ACIA_PRTCFG ; PRINT IF NOT ZERO
|
|
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; NEXT UNIT
|
|
DJNZ ACIA_INIT1 ; LOOP TILL DONE
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; INTERRUPT HANDLERS
|
|
;
|
|
#IF (INTMODE > 0)
|
|
;
|
|
ACIAA_INT:
|
|
LD IY,ACIAA_CFG ; POINT TO CONFIG
|
|
;
|
|
; CHECK FOR RECEIVE PENDING
|
|
LD C,(IY+3) ; STATUS PORT
|
|
IN A,(C) ; GET STATUS
|
|
AND $01 ; ISOLATE RECEIVE READY BIT
|
|
RET Z ; IF NOT, RETURN WITH Z SET
|
|
;
|
|
ACIAA_INT00:
|
|
; HANDLE PENDING RECEIVE
|
|
INC C ; DATA PORT
|
|
IN A,(C) ; READ PORT
|
|
DEC C ; BACK TO CONTROL PORT
|
|
LD E,A ; SAVE BYTE READ
|
|
LD A,(ACIAA_BUFCNT) ; GET CURRENT BUFFER USED COUNT
|
|
CP ACIAA_BUFSZ ; COMPARE TO BUFFER SIZE
|
|
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
|
|
JR Z,ACIAA_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
|
|
INC A ; INCREMENT THE COUNT
|
|
LD (ACIAA_BUFCNT),A ; AND SAVE IT
|
|
CP ACIAA_BUFSZ - 5 ; BUFFER GETTING FULL?
|
|
JR NZ,ACIAA_INT0 ; IF NOT, BYPASS DEASSERTING RTS
|
|
LD A,ACIA_RTSOFF ; VALUE TO DEASSERT RTS
|
|
OUT (C),A ; DO IT
|
|
ACIAA_INT0:
|
|
LD HL,(ACIAA_HD) ; GET HEAD POINTER
|
|
LD A,L ; GET LOW BYTE
|
|
CP ACIAA_BUFEND & $FF ; PAST END?
|
|
JR NZ,ACIAA_INT1 ; IF NOT, BYPASS POINTER RESET
|
|
LD HL,ACIAA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
|
|
ACIAA_INT1:
|
|
LD A,E ; RECOVER BYTE READ
|
|
LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION
|
|
INC HL ; INCREMENT HEAD POINTER
|
|
LD (ACIAA_HD),HL ; SAVE IT
|
|
;
|
|
ACIAA_INT2:
|
|
; CHECK FOR MORE PENDING...
|
|
IN A,(C) ; GET STATUS
|
|
RRA ; READY BIT TO CF
|
|
JR C,ACIAA_INT00 ; IF SET, DO SOME MORE
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED
|
|
RET ; AND RETURN
|
|
;
|
|
ACIAB_INT:
|
|
LD IY,ACIAB_CFG ; POINT TO CONFIG
|
|
;
|
|
; CHECK FOR RECEIVE PENDING
|
|
LD C,(IY+3) ; STATUS PORT
|
|
IN A,(C) ; GET STATUS
|
|
AND $01 ; ISOLATE RECEIVE READY BIT
|
|
RET Z ; IF NOT, RETURN WITH Z SET
|
|
;
|
|
ACIAB_INT00:
|
|
; HANDLE PENDING RECEIVE
|
|
INC C ; DATA PORT
|
|
IN A,(C) ; READ PORT
|
|
DEC C ; BACK TO CONTROL PORT
|
|
LD E,A ; SAVE BYTE READ
|
|
LD A,(ACIAB_BUFCNT) ; GET CURRENT BUFFER USED COUNT
|
|
CP ACIAB_BUFSZ ; COMPARE TO BUFFER SIZE
|
|
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
|
|
JR Z,ACIAB_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
|
|
INC A ; INCREMENT THE COUNT
|
|
LD (ACIAB_BUFCNT),A ; AND SAVE IT
|
|
CP ACIAB_BUFSZ - 5 ; BUFFER GETTING FULL?
|
|
JR NZ,ACIAB_INT0 ; IF NOT, BYPASS DEASSERTING RTS
|
|
LD A,ACIA_RTSOFF ; VALUE TO DEASSERT RTS
|
|
OUT (C),A ; DO IT
|
|
ACIAB_INT0:
|
|
LD HL,(ACIAB_HD) ; GET HEAD POINTER
|
|
LD A,L ; GET LOW BYTE
|
|
CP ACIAB_BUFEND & $FF ; PAST END?
|
|
JR NZ,ACIAB_INT1 ; IF NOT, BYPASS POINTER RESET
|
|
LD HL,ACIAB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
|
|
ACIAB_INT1:
|
|
LD A,E ; RECOVER BYTE READ
|
|
LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION
|
|
INC HL ; INCREMENT HEAD POINTER
|
|
LD (ACIAB_HD),HL ; SAVE IT
|
|
;
|
|
ACIAB_INT2:
|
|
; CHECK FOR MORE PENDING...
|
|
IN A,(C) ; GET STATUS
|
|
RRA ; READY BIT TO CF
|
|
JR C,ACIAB_INT00 ; IF SET, DO SOME MORE
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED
|
|
RET ; AND RETURN
|
|
;
|
|
#ENDIF
|
|
;
|
|
; DRIVER FUNCTION TABLE
|
|
;
|
|
ACIA_FNTBL:
|
|
.DW ACIA_IN
|
|
.DW ACIA_OUT
|
|
.DW ACIA_IST
|
|
.DW ACIA_OST
|
|
.DW ACIA_INITDEV
|
|
.DW ACIA_QUERY
|
|
.DW ACIA_DEVICE
|
|
#IF (($ - ACIA_FNTBL) != (CIO_FNCNT * 2))
|
|
.ECHO "*** INVALID ACIA FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
#IF (INTMODE == 0)
|
|
;
|
|
ACIA_IN:
|
|
CALL ACIA_IST ; CHAR WAITING?
|
|
JR Z,ACIA_IN ; LOOP IF NOT
|
|
LD C,(IY+3) ; C := ACIA BASE PORT
|
|
INC C ; BUMP TO DATA PORT
|
|
IN E,(C) ; GET BYTE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
#ELSE
|
|
;
|
|
ACIA_IN:
|
|
LD A,(IY+2) ; GET MODULE ID
|
|
OR A ; SET FLAGS
|
|
JR Z,ACIAA_IN ; HANDLE MODULE 0
|
|
DEC A ; TEST FOR NEXT
|
|
JR Z,ACIAB_IN ; HANDLE MODULE 1
|
|
CALL PANIC ; ELSE FATAL ERROR
|
|
RET
|
|
;
|
|
ACIAA_IN:
|
|
CALL ACIAA_IST ; RECEIVED CHAR READY?
|
|
JR Z,ACIAA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER
|
|
HB_DI ; AVOID COLLISION WITH INT HANDLER
|
|
LD A,(ACIAA_BUFCNT) ; GET COUNT
|
|
DEC A ; DECREMENT COUNT
|
|
LD (ACIAA_BUFCNT),A ; SAVE SAVE IT
|
|
CP 5 ; BUFFER LOW THRESHOLD
|
|
JR NZ,ACIAA_IN0 ; IF NOT, BYPASS SETTING RTS
|
|
|
|
LD C,(IY+3) ; C := ACIA CMD PORT
|
|
LD A,ACIA_RTSON ; ASSERT RTS
|
|
OUT (C),A ; DO IT
|
|
ACIAA_IN0:
|
|
LD HL,(ACIAA_TL) ; GET BUFFER TAIL POINTER
|
|
LD E,(HL) ; GET BYTE
|
|
INC HL ; BUMP TAIL POINTER
|
|
LD A,L ; GET LOW BYTE
|
|
CP ACIAA_BUFEND & $FF ; PAST END?
|
|
JR NZ,ACIAA_IN1 ; IF NOT, BYPASS POINTER RESET
|
|
LD HL,ACIAA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
|
|
ACIAA_IN1:
|
|
LD (ACIAA_TL),HL ; SAVE UPDATED TAIL POINTER
|
|
HB_EI ; INTERRUPTS OK AGAIN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND DONE
|
|
;
|
|
ACIAB_IN:
|
|
CALL ACIAB_IST ; RECEIVED CHAR READY?
|
|
JR Z,ACIAB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER
|
|
HB_DI ; AVOID COLLISION WITH INT HANDLER
|
|
LD A,(ACIAB_BUFCNT) ; GET COUNT
|
|
DEC A ; DECREMENT COUNT
|
|
LD (ACIAB_BUFCNT),A ; SAVE SAVE IT
|
|
CP 5 ; BUFFER LOW THRESHOLD
|
|
JR NZ,ACIAB_IN0 ; IF NOT, BYPASS SETTING RTS
|
|
|
|
LD C,(IY+3) ; C := ACIA CMD PORT
|
|
LD A,ACIA_RTSON ; ASSERT RTS
|
|
OUT (C),A ; DO IT
|
|
ACIAB_IN0:
|
|
LD HL,(ACIAB_TL) ; GET BUFFER TAIL POINTER
|
|
LD E,(HL) ; GET BYTE
|
|
INC HL ; BUMP TAIL POINTER
|
|
LD A,L ; GET LOW BYTE
|
|
CP ACIAB_BUFEND & $FF ; PAST END?
|
|
JR NZ,ACIAB_IN1 ; IF NOT, BYPASS POINTER RESET
|
|
LD HL,ACIAB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
|
|
ACIAB_IN1:
|
|
LD (ACIAB_TL),HL ; SAVE UPDATED TAIL POINTER
|
|
HB_EI ; INTERRUPTS OK AGAIN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND DONE
|
|
;
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
ACIA_OUT:
|
|
CALL ACIA_OST ; READY FOR CHAR?
|
|
JR Z,ACIA_OUT ; LOOP IF NOT
|
|
LD C,(IY+3) ; C := ACIA CMD PORT
|
|
INC C ; BUMP TO DATA PORT
|
|
OUT (C),E ; SEND CHAR FROM E
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
#IF (INTMODE == 0)
|
|
;
|
|
ACIA_IST:
|
|
LD C,(IY+3) ; STATUS PORT
|
|
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
|
|
;
|
|
ACIA_IST:
|
|
LD A,(IY+2) ; GET MODULE ID
|
|
OR A ; SET FLAGS
|
|
JR Z,ACIAA_IST ; HANDLE MODULE 0
|
|
DEC A ; TEST FOR NEXT
|
|
JR Z,ACIAB_IST ; HANDLE MODULE 1
|
|
CALL PANIC ; ELSE FATAL ERROR
|
|
RET
|
|
;
|
|
ACIAA_IST:
|
|
LD A,(ACIAA_BUFCNT) ; GET BUFFER UTILIZATION COUNT
|
|
OR A ; SET FLAGS
|
|
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
|
|
RET ; AND DONE
|
|
;
|
|
ACIAB_IST:
|
|
LD A,(ACIAB_BUFCNT) ; GET BUFFER UTILIZATION COUNT
|
|
OR A ; SET FLAGS
|
|
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
|
|
RET ; AND DONE
|
|
;
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
ACIA_OST:
|
|
LD C,(IY+3) ; CMD PORT
|
|
IN A,(C) ; GET STATUS
|
|
AND $02 ; 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
|
|
;
|
|
;
|
|
;
|
|
ACIA_INITDEV:
|
|
HB_DI ; AVOID CONFLICTS
|
|
CALL ACIA_INITDEVX ; DO THE REAL WORK
|
|
HB_EI ; INTS BACK ON
|
|
RET ; DONE
|
|
;
|
|
ACIA_INITDEVX:
|
|
;
|
|
; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY
|
|
; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS!
|
|
;
|
|
; PROGRAM THE ACIA CHIP
|
|
LD C,(IY+3) ; COMMAND PORT
|
|
LD A,$FF ; MASTER RESET
|
|
OUT (C),A ; DO IT
|
|
LD A,ACIA_RTSON ; NORMAL OPERATION
|
|
OUT (C),A ; DO IT
|
|
;
|
|
#IF (INTMODE > 0)
|
|
;
|
|
; 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
|
|
;
|
|
#ENDIF
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; RETURN
|
|
;
|
|
;
|
|
;
|
|
ACIA_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
|
|
;
|
|
;
|
|
;
|
|
ACIA_DEVICE:
|
|
LD D,CIODEV_ACIA ; D := DEVICE TYPE
|
|
LD E,(IY) ; E := PHYSICAL UNIT
|
|
LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; ACIA DETECTION ROUTINE
|
|
;
|
|
ACIA_DETECT:
|
|
;LD C,ACIA_BASE ; BASE PORT ADDRESS
|
|
LD C,(IY+3) ; BASE PORT ADDRESS
|
|
CALL ACIA_DETECT2 ; CHECK IT
|
|
JR Z,ACIA_DETECT1 ; FOUND IT, RECORD IT
|
|
;LD C,ACIA_ALTBASE ; ALT BASE PORT ADDRESS
|
|
;CALL ACIA_DETECT2 ; CHECK IT
|
|
;JR Z,ACIA_DETECT1 ; FOUND IT, RECORD IT
|
|
LD A,ACIA_NONE ; NOTHING FOUND
|
|
RET ; DONE
|
|
;
|
|
ACIA_DETECT1:
|
|
; ACIA FOUND, RECORD IT
|
|
;LD A,C ; BASE PORT ADDRESS TO A
|
|
;LD (IY+3),A ; SAVE ACTIVE BASE PORT
|
|
LD A,ACIA_ACIA ; RETURN CHIP TYPE
|
|
RET ; DONE
|
|
;
|
|
ACIA_DETECT2:
|
|
; LOOK FOR ACIA AT PORT ADDRESS IN C
|
|
LD A,$03 ; MASTER RESET
|
|
OUT (C),A ; DO IT
|
|
IN A,(C) ; GET STATUS
|
|
OR A ; CHECK FOR ZERO
|
|
RET NZ ; RETURN IF NOT ZERO
|
|
LD A,$02 ; CLEAR MASTER RESET
|
|
OUT (C),A ; DO IT
|
|
; CHECK FOR EXPECTED BITS:
|
|
; TDRE=1, DCD & CTS = 0
|
|
AND %00001110 ; BIT MASK FOR "STABLE" BITS
|
|
CP %00000010 ; EXPECTED VALUE
|
|
RET ; RETURN RESULT, Z = CHIP FOUND
|
|
;
|
|
;
|
|
;
|
|
ACIA_PRTCFG:
|
|
; ANNOUNCE PORT
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("ACIA$") ; 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 ACIA TYPE
|
|
CALL PC_SPACE ; FORMATTING
|
|
LD A,(IY+1) ; GET ACIA TYPE BYTE
|
|
RLCA ; MAKE IT A WORD OFFSET
|
|
LD HL,ACIA_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 ACIA WAS DETECTED
|
|
LD A,(IY+1) ; GET ACIA 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
|
|
;
|
|
;
|
|
;
|
|
ACIA_TYPE_MAP:
|
|
.DW ACIA_STR_NONE
|
|
.DW ACIA_STR_ACIA
|
|
|
|
ACIA_STR_NONE .DB "<NOT PRESENT>$"
|
|
ACIA_STR_ACIA .DB "ACIA$"
|
|
;
|
|
; WORKING VARIABLES
|
|
;
|
|
ACIA_DEV .DB 0 ; DEVICE NUM USED DURING INIT
|
|
;
|
|
#IF (INTMODE == 0)
|
|
;
|
|
ACIAA_RCVBUF .EQU 0
|
|
ACIAB_RCVBUF .EQU 0
|
|
;
|
|
#ELSE
|
|
;
|
|
; RECEIVE BUFFERS
|
|
;
|
|
ACIAA_RCVBUF:
|
|
ACIAA_BUFCNT .DB 0 ; CHARACTERS IN RING BUFFER
|
|
ACIAA_HD .DW ACIAA_BUF ; BUFFER HEAD POINTER
|
|
ACIAA_TL .DW ACIAA_BUF ; BUFFER TAIL POINTER
|
|
ACIAA_INTP .DW ACIAA_INT ; INT HANDLER POINTER
|
|
ACIAA_BUF .FILL 32,0 ; RECEIVE RING BUFFER
|
|
ACIAA_BUFEND .EQU $ ; END OF BUFFER
|
|
ACIAA_BUFSZ .EQU $ - ACIAA_BUF ; SIZE OF RING BUFFER
|
|
;
|
|
ACIAB_RCVBUF:
|
|
ACIAB_BUFCNT .DB 0 ; CHARACTERS IN RING BUFFER
|
|
ACIAB_HD .DW ACIAB_BUF ; BUFFER HEAD POINTER
|
|
ACIAB_TL .DW ACIAB_BUF ; BUFFER TAIL POINTER
|
|
ACIAB_INTP .DW ACIAB_INT ; INT HANDLER POINTER
|
|
ACIAB_BUF .FILL 32,0 ; RECEIVE RING BUFFER
|
|
ACIAB_BUFEND .EQU $ ; END OF BUFFER
|
|
ACIAB_BUFSZ .EQU $ - ACIAB_BUF ; SIZE OF RING BUFFER
|
|
;
|
|
#ENDIF
|
|
;
|
|
; ACIA PORT TABLE
|
|
;
|
|
ACIA_CFG:
|
|
ACIAA_CFG:
|
|
; ACIA MODULE A CONFIG
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
|
|
.DB 0 ; ACIA TYPE (SET DURING INIT)
|
|
.DB 0 ; MODULE ID
|
|
.DB ACIAA_BASE ; BASE PORT (SET DURING DETECT)
|
|
.DW DEFSERCFG ; LINE CONFIGURATION
|
|
.DW ACIAA_RCVBUF ; POINTER TO RCV BUFFER STRUCT
|
|
ACIAB_CFG:
|
|
; ACIA MODULE B CONFIG
|
|
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
|
|
.DB 0 ; ACIA TYPE (SET DURING INIT)
|
|
.DB 1 ; MODULE ID
|
|
.DB ACIAB_BASE ; BASE PORT (SET DURING DETECT)
|
|
.DW DEFSERCFG ; LINE CONFIGURATION
|
|
.DW ACIAB_RCVBUF ; POINTER TO RCV BUFFER STRUCT
|
|
;
|
|
ACIA_CNT .EQU ($ - ACIA_CFG) / 8
|
|
|