Browse Source

UART Driver Interrupt Driven Receive

- The UART driver has been enhanced to allow use of interrupt driven receive buffer and RTS flow control.  It will only be used if enabled and the chip detected has no auto-flow control capability.
pull/246/head
Wayne Warthen 4 years ago
parent
commit
14b005d64e
  1. 2
      Doc/ChangeLog.txt
  2. 13
      Source/Apps/XM/xmhb.180
  3. 1
      Source/HBIOS/cfg_ezz80.asm
  4. 1
      Source/HBIOS/cfg_master.asm
  5. 9
      Source/HBIOS/cfg_mbc.asm
  6. 1
      Source/HBIOS/cfg_mk4.asm
  7. 1
      Source/HBIOS/cfg_n8.asm
  8. 1
      Source/HBIOS/cfg_rcz180.asm
  9. 1
      Source/HBIOS/cfg_rcz280.asm
  10. 1
      Source/HBIOS/cfg_rcz80.asm
  11. 1
      Source/HBIOS/cfg_sbc.asm
  12. 1
      Source/HBIOS/cfg_scz180.asm
  13. 1
      Source/HBIOS/cfg_zeta.asm
  14. 1
      Source/HBIOS/cfg_zeta2.asm
  15. 3
      Source/HBIOS/hbios.asm
  16. 478
      Source/HBIOS/uart.asm
  17. 2
      Source/ver.inc
  18. 2
      Source/ver.lib

2
Doc/ChangeLog.txt

@ -51,6 +51,8 @@ Version 3.1.1
- WBW: Added ROM verification to boot process
- WBW: Added Z80 instruction test apps to user area 5 in CP/M & ZSDOS
- WBW: Add support for LINC sound card
- WBW: Add interrupt receive support to UART driver
- PMS: Add XModem transfer within Debug Monitor
Version 3.1
-----------

13
Source/Apps/XM/xmhb.180

@ -112,11 +112,22 @@ MINIT_HB1:
RST 08 ; Do it, D=device type
LD A,D ; Put result in A
CP 00H ; UART?
JP Z,UA_INIT ; If so, do UART H/W init
JP Z,MINIT_HB2 ; If so, do UART H/W init
CP 80H ; USB-FIFO?
JP Z,UF_INIT ; If so, do USB-FIFO H/W init
JP HB_INIT ; Otherwise, use BIOS I/O
;
MINIT_HB2:
; Handle UART driver special. If receive interrupts active,
; we must use BIOS I/O. Otherwise, direct UART I/O is best
LD B,06H ; Serial device function
LD A,(UNIT) ; Get xfer unit
LD C,A ; Put in C
RST 08 ; Do it, H = UART TYPE
BIT 7,H ; Check for interrupt driven receive
JP Z,UA_INIT ; If not, do direct UART I/O
JP HB_INIT ; else use BIOS I/O
;
MINIT_UB:
; Display UNA notification string
LD DE,UB_TAG ; BIOS notification string

1
Source/HBIOS/cfg_ezz80.asm

@ -105,6 +105,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART

1
Source/HBIOS/cfg_master.asm

@ -138,6 +138,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU FALSE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

9
Source/HBIOS/cfg_mbc.asm

@ -101,12 +101,13 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU TRUE ; UART: AUTO-DETECT ECB CASSETTE UART
UARTMFP .EQU TRUE ; UART: AUTO-DETECT MF/PIC UART
UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
UARTRC .EQU FALSE ; UART: AUTO-DETECT RC UART
;
ASCIENABLE .EQU FALSE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM)
@ -115,7 +116,7 @@ Z2UENABLE .EQU FALSE ; Z2U: ENABLE Z280 UART SERIAL DRIVER (Z2U.ASM)
;
ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM)
;
SIOENABLE .EQU TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
SIOENABLE .EQU FALSE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
SIODEBUG .EQU FALSE ; SIO: ENABLE DEBUG OUTPUT
SIOBOOT .EQU 0 ; SIO: REBOOT ON RCV CHAR (0=DISABLED)
SIOCNT .EQU 1 ; SIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP

1
Source/HBIOS/cfg_mk4.asm

@ -107,6 +107,7 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

1
Source/HBIOS/cfg_n8.asm

@ -109,6 +109,7 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

1
Source/HBIOS/cfg_rcz180.asm

@ -107,6 +107,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART

1
Source/HBIOS/cfg_rcz280.asm

@ -112,6 +112,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART

1
Source/HBIOS/cfg_rcz80.asm

@ -106,6 +106,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART

1
Source/HBIOS/cfg_sbc.asm

@ -101,6 +101,7 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

1
Source/HBIOS/cfg_scz180.asm

@ -102,6 +102,7 @@ DUART1BCFG .EQU DEFSERCFG ; DUART 1B: SERIAL LINE CONFIG
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART

1
Source/HBIOS/cfg_zeta.asm

@ -88,6 +88,7 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

1
Source/HBIOS/cfg_zeta2.asm

@ -99,6 +99,7 @@ DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
;
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART

3
Source/HBIOS/hbios.asm

@ -757,7 +757,8 @@ HBX_INTSTKSIZ .EQU $FF00 - $
.FILL HBX_INTSTKSIZ,$FF
HBX_INTSTK .EQU $
;
#IF (HBX_INTSTKSIZ < 24)
;#IF (HBX_INTSTKSIZ < 24)
#IF (HBX_INTSTKSIZ < 22)
.ECHO "*** ERROR: INTERRUPT STACK IS TOO SMALL!!!\n"
!!! ; FORCE AN ASSEMBLY ERROR
#ENDIF

478
Source/HBIOS/uart.asm

@ -20,6 +20,8 @@
;
UART_DEBUG .EQU FALSE
;
UART_BUFSZ .EQU 32 ; RECEIVE RING BUFFER SIZE
;
UART_NONE .EQU 0 ; UNKNOWN OR NOT PRESENT
UART_8250 .EQU 1
UART_16450 .EQU 2
@ -43,9 +45,13 @@ UART_SCR .EQU 7 ; SCRATCH REGISTER (READ/WRITE)
UART_DLL .EQU 0 ; DLAB=1: DIVISOR LATCH (LS) (READ/WRITE)
UART_DLM .EQU 1 ; DLAB=1: DIVISOR LATCH (MS) (READ/WRITE)
UART_EFR .EQU 2 ; LCR=$BF: ENHANCED FEATURE REG (READ/WRITE)
;;
;UART_FIFO .EQU 0 ; FIFO ENABLE BIT
;UART_AFC .EQU 1 ; AUTO FLOW CONTROL ENABLE BIT
;
; THESE BITS ARE SET IN THE UART TYPE BYTE TO FURTHER
; IDENTIFY THE FEATURES OF THE CHIP
;
UART_INTACT .EQU 7 ; INT RCV ACTIVE BIT
UART_FIFOACT .EQU 6 ; FIFO ACTIVE BIT
UART_AFCACT .EQU 5 ; AUTO FLOW CONTROL ACTIVE BIT
;
UARTSBASE .EQU $68
UARTCBASE .EQU $80
@ -98,6 +104,29 @@ UART_PREINIT0:
UART_PREINIT2:
INC C ; NEXT PHYSICAL UNIT
DJNZ UART_PREINIT0 ; LOOP UNTIL DONE
;
#IF ((UARTINTS) & (INTMODE > 0))
; *** FIXME *** WE SHOULD CHECK TO SEE IF ANY UNITS ARE ACTUALLY
; USING INT RCV. IF NOT, WE SHOULD NOT HOOK IM1!!!
;
; SETUP INT VECTORS AS APPROPRIATE
LD A,(UART_DEV) ; GET DEVICE COUNT
OR A ; SET FLAGS
JR Z,UART_PREINIT3 ; IF ZERO, NO UART DEVICES, ABORT
;
#IF (INTMODE == 1)
; ADD IM1 INT CALL LIST ENTRY
LD HL,UART_INT ; GET INT VECTOR
CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST
#ENDIF
;
#IF ((INTMODE == 2) | (INTMODE == 3))
; *** FIXME *** IMPLEMENT THIS!!!
#ENDIF
;
#ENDIF
;
UART_PREINIT3:
XOR A ; SIGNAL SUCCESS
RET ; AND RETURN
;
@ -106,19 +135,19 @@ UART_PREINIT2:
UART_INITUNIT:
; DETECT THE UART TYPE
CALL UART_DETECT ; DETERMINE UART TYPE
LD (IY + 1),A ; ALSO SAVE IN CONFIG TABLE
LD (IY+1),A ; AND SAVE IN CONFIG TABLE
OR A ; SET FLAGS
RET Z ; ABORT IF NOTHING THERE
;
; UPDATE WORKING UART DEVICE NUM
LD HL,UART_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 UART_INITDEV ; IMPLEMENT IT AND RETURN
JP UART_INITDEVX ; IMPLEMENT IT AND RETURN
;
;
;
@ -148,6 +177,116 @@ UART_INIT1:
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; RECEIVE INTERRUPT HANDLER
;
#IF ((UARTINTS) & (INTMODE > 0))
;
; IM1 ENTRY POINT
;
; POLL ALL DEVICES THAT MIGHT ENABLE INTERRUPT DRIVEN
; RECEIVE. HANDLE FIRST INTERRUPT ENCOUNTERED (IF ANY).
; MOST BOARDS REQUIRE UARTS THAT WILL HAVE AFC. THE
; ONLY BOARDS THAT MAY NOT ARE THE SBC AND THE CAS.
;
; THIS COULD BE IMPROVED BY DYNAMICALLY SETTING UP THE
; POLLING CHAIN WHEN DEVICES ARE INITIALIZED SUCH THAT
; ONLY DEVICES ACTUALLY USING INTS ARE POLLED HERE.
;
UART_INT:
;
#IF (UARTSBC)
LD IY,UART_CFG_SBC
CALL UART_INTRCV
RET NZ
#ENDIF
;
#IF (UARTCAS)
LD IY,UART_CFG_CAS
CALL UART_INTRCV
RET NZ
#ENDIF
;
XOR A ; CLEAR ACCUM (INT NOT HANDLED)
RET ; DONE
;
; HANDLE INT FOR A SPECIFIC CHANNEL
; BASED ON UNIT CFG POINTED TO BY IY
;
UART_INTRCV:
; ARE INTERRUPTS IN USE ON THIS DEVICE?
LD A,(IY+1) ; GET UART TYPE
AND %10000000 ; ISOLATE INT RCV BIT
RET Z ; INTS NOT SUPPORTED
; CHECK TO SEE IF SOMETHING IS ACTUALLY THERE
LD C,(IY+3) ; STATUS PORT TO C
IN A,(C) ; GET LSR
AND $01 ; ISOLATE RECEIVE READY BIT
RET Z ; NOTHING AVAILABLE ON CURRENT CHANNEL
;
UART_INTRCV1:
; RECEIVE CHARACTER INTO BUFFER
LD C,(IY+2) ; DATA PORT TO C
IN A,(C) ; READ PORT
LD B,A ; SAVE BYTE READ
LD L,(IY+6) ; SET HL TO
LD H,(IY+7) ; ... START OF BUFFER STRUCT
LD A,(HL) ; GET COUNT
CP UART_BUFSZ ; COMPARE TO BUFFER SIZE
JR Z,UART_INTRCV4 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
INC A ; INCREMENT THE COUNT
LD (HL),A ; AND SAVE IT
; *** FIXME *** THE FOLLOWING SHOULD ONLY BE DONE IF RTS FLOW CONTROL IS ON!!!
; SOMETHING LIKE THIS MAY WORK...
;BIT 5,(IY+5)
;JR Z,UART_INTRCV2
CP UART_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,UART_INTRCV2 ; IF NOT, BYPASS CLEARING RTS
LD C,(IY+3) ; LSR PORT TO C
DEC C ; POINT TO MCR PORT
IN A,(C) ; GET MCR VALUE
AND ~%00000010 ; CLEAR RTS
OUT (C),A ; AND SAVE IT
;
UART_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
SUB UART_BUFSZ+4 ; SUBTRACT SIZE OF BUFFER AND POINTER
CP E ; IF EQUAL TO START, HEAD PTR IS PAST BUF END
JR NZ,UART_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
UART_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...
LD C,(IY+3) ; STATUS PORT TO C
IN A,(C) ; GET LSR
AND $01 ; ISOLATE RECEIVE READY BIT
JR NZ,UART_INTRCV1 ; IF SET, DO SOME MORE
UART_INTRCV4:
OR $FF ; NZ SET TO INDICATE INT HANDLED
RET
;
#ENDIF
;
; DRIVER FUNCTION TABLE
;
UART_FNTBL:
@ -167,11 +306,75 @@ UART_FNTBL:
UART_IN:
CALL UART_IST ; RECEIVED CHAR READY?
JR Z,UART_IN ; LOOP IF NOT
#IF ((UARTINTS) & (INTMODE > 0))
BIT UART_INTACT,(IY+1) ; INT RCV BIT
JR Z,UART_IN1 ; NORMAL INPUT IF NOT SET
JR UART_INTIN ; INT RCV INPUT
#ENDIF
;
UART_IN1:
LD C,(IY+2) ; C := BASE UART PORT (WHICH IS ALSO RBR REG)
IN E,(C) ; CHAR READ TO E
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
#IF ((UARTINTS) & (INTMODE > 0))
;
UART_INTIN:
HB_DI ; AVOID COLLISION WITH INT HANDLER
LD L,(IY+6) ; SET HL TO
LD H,(IY+7) ; ... START OF BUFFER STRUCT
LD A,(HL) ; GET COUNT
DEC A ; DECREMENT COUNT
LD (HL),A ; SAVE UPDATED COUNT
; *** FIXME *** THE FOLLOWING SHOULD ONLY BE DONE IF RTS FLOW CONTROL IS ON!!!
; SOMETHING LIKE THIS MAY WORK...
;BIT 5,(IY+5)
;JR Z,UART_INTIN1
CP UART_BUFSZ / 4 ; BUFFER LOW THRESHOLD
JR NZ,UART_INTIN1 ; IF NOT, BYPASS SETTING RTS
LD C,(IY+3) ; LSR PORT TO C
DEC C ; POINT TO MCR PORT
IN A,(C) ; GET MCR VALUE
OR %00000010 ; SET RTS
OUT (C),A ; AND SAVE IT
;
UART_INTIN1:
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
SUB UART_BUFSZ+2 ; SUBTRACT SIZE OF BUFFER AND POINTER
CP E ; IF EQUAL TO START, TAIL PTR IS PAST BUF END
JR NZ,UART_INTIN2 ; 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
UART_INTIN2:
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
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
#ENDIF
;
;
;
UART_OUT:
@ -185,6 +388,13 @@ UART_OUT:
;
;
UART_IST:
#IF ((UARTINTS) & (INTMODE > 0))
BIT UART_INTACT,(IY+1) ; INT RCV BIT
JR Z,UART_IST1 ; NORMAL INPUT IF NOT SET
JR UART_INTIST ; ELSE INT RCV
#ENDIF
;
UART_IST1:
LD C,(IY+3) ; C := LINE STATUS REG (LSR)
IN A,(C) ; GET STATUS
AND $01 ; ISOLATE BIT 0 (RECEIVE DATA READY)
@ -193,6 +403,18 @@ UART_IST:
INC A ; ACCUM := 1 TO SIGNAL 1 CHAR WAITING
RET ; DONE
;
#IF ((UARTINTS) & (INTMODE > 0))
;
UART_INTIST:
LD L,(IY+6) ; GET ADDRESS
LD H,(IY+7) ; ... OF RECEIVE BUFFER
LD A,(HL) ; BUFFER UTILIZATION COUNT
OR A ; SET FLAGS
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
RET
;
#ENDIF
;
;
;
UART_OST:
@ -206,7 +428,18 @@ UART_OST:
;
;
;
;
; 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.
;
UART_INITDEV:
HB_DI ; DISABLE INTS
CALL UART_INITDEVX ; DO THE WORK
HB_EI ; INTS BACK ON
RET ; DONE
;
UART_INITDEVX:
; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT)
LD A,D ; TEST DE FOR
AND E ; ... VALUE OF -1
@ -245,6 +478,20 @@ UART_INITDEV1:
;
XOR A ; DLAB OFF NOW
UART_OUTP(UART_LCR) ; DO IT
;
XOR A ; IER VALUE FOR NO INTS
;
#IF ((UARTINTS) & (INTMODE > 0))
;
BIT UART_INTACT,(IY+1) ; CHECK INT RCV BIT
JR Z,UART_INITDEV1A ; SKIP IF NOT SET
INC A ; DATA RCVD INT BIT OF IER
;
UART_INITDEV1A:
;
#ENDIF
;
UART_OUTP(UART_IER) ; SETUP IER REGISTER
;
; SETUP FCR, BIT 5 IS KEPT ON EVEN THOUGH IT IS PROBABLY
; IRRELEVANT BECAUSE IT ONLY APPLIES TO 750 AND DLAB IS
@ -261,7 +508,18 @@ UART_INITDEV1:
LD A,(IY+5) ; GET CONFIG BYTE
AND ~$1F ; REMOVE ENCODED BAUD RATE BITS
OR $03 ; FORCE RTS & DTR
UART_OUTP(UART_MCR) ; SAVE IT
;
; THE MCR REGISTER AFE BIT WILL NORMALLY BE SET/RESET BY THE
; VALUE OF THE CONFIG BYTE. HOWEVER, IF THE CHIP IS NOT AFC CAPABLE
; WE ARE PROBABLY USING INT RCV FOR FLOW CONTROL. ALTHOUGH THE
; CHIP PROBABLY IGNORES THE AFE BIT, WE FORCE CLEAR IT ANYWAY. IT WOULD
; BE BAD IF AFC AND INT RCV ARE ACTIVE AT THE SAME TIME.
BIT UART_AFCACT,(IY+1) ; IS AFC SUPPOSED TO BE ON?
JR NZ,UART_INITDEV1B ; IF SO, AFE BIT IS OK BASED ON CONFIG BYTE
RES 5,A ; ELSE FORCE IT OFF
;
UART_INITDEV1B:
UART_OUTP(UART_MCR) ; SAVE MCR VALUE
;
; TEST FOR EFR CAPABLE CHIPS
LD A,(IY+1) ; GET UART TYPE
@ -289,6 +547,37 @@ UART_INITDEV3:
UART_OUTP(UART_LCR) ; AND PUT IT BACK
;
UART_INITDEV4:
;
#IF ((UARTINTS) & (INTMODE > 0))
;
LD A,(IY+7) ; MSB OF BUFFER
OR A ; SET FLAGS
JR Z,UART_INITDEV5 ; BYPASS IF NO BUFFER
; 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
;
UART_INITDEV5:
;
#ENDIF
;
;
#IF (UART_DEBUG)
PRTS(" [$")
@ -345,7 +634,7 @@ UART_DEVICE:
LD D,CIODEV_UART ; D := DEVICE TYPE
LD E,(IY) ; E := PHYSICAL UNIT
LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232
LD H,0 ; H := 0, DRIVER HAS NO MODES
LD H,(IY+1) ; H := UART TYPE BYTE
LD L,(IY+2) ; L := BASE I/O ADDRESS
XOR A ; SIGNAL SUCCESS
RET
@ -353,6 +642,49 @@ UART_DEVICE:
; UART DETECTION ROUTINE
;
UART_DETECT:
CALL UART_CHIP ; DETECT CHIP VARIANT
RET Z ; DONE IF NO CHIP
;LD A,UART_16550A ; *DEBUG*
LD C,A ; PUT CHIP VARIANT IN C
;
; *** FIXME *** THIS NEEDS TO CHANGE WHEN INTMODE 2/3 IS IMPLEMENTED. AT THIS
; POINT, WE ONLY SET THE INT RCV FEATURE BIT FOR IM1 BECAUSE THAT IS ALL
; THAT IS IMPLEMENTED.
;
;#IF ((UARTINTS) & (INTMODE > 0))
#IF ((UARTINTS) & (INTMODE == 1))
;
; CHECK TO SEE IF INT RCV WANTED ON THIS DEVICE
PUSH AF ; SAVE CHIP ID
CP UART_16550C ; 16550C OR LATER?
JR NC,UART_DETECT1 ; NO INTS, USE AFC INSTEAD
LD A,(IY+7) ; MSB OF RING BUFFER
OR A ; SET FLAGS
JR Z,UART_DETECT1 ; NO BUFFER, NO INTS ALLOWED
SET UART_INTACT,C ; SET INT RCV BIT
;
UART_DETECT1:
POP AF ; RESTORE CHIP ID
;
#ENDIF
;
CP UART_16550 ; 16550 OR GREATER?
JR C,UART_DETECT2 ; NO MORE FEATURES
SET UART_FIFOACT,C ; RECORD FIFO FEATURE
CP UART_16550C ; 16550C OR GREATER?
JR C,UART_DETECT2 ; NO MORE FEATURES
SET UART_AFCACT,C ; RECORD AFC FEATURE
;
UART_DETECT2:
LD A,C ; RETURN RESULT IN A
CALL PRTHEXBYTE
RET
;
; DETERMINE TEH UART CHIP VARIANT AND RETURN IN A
;
UART_CHIP:
;
; SEE IF UART IS THERE BY CHECKING DLAB FUNCTIONALITY
XOR A ; ZERO ACCUM
@ -363,26 +695,26 @@ UART_DETECT:
UART_OUTP(UART_DLM) ; OUTPUT TO DLM
UART_INP(UART_DLM) ; READ IT BACK
CP $5A ; CHECK FOR TEST VALUE
JP NZ,UART_DETECT_NONE ; NOPE, UNKNOWN UART OR NOT PRESENT
JP NZ,UART_CHIP_NONE ; NOPE, UNKNOWN UART OR NOT PRESENT
XOR A ; DLAB BIT OFF
UART_OUTP(UART_LCR) ; OUTPUT TO LCR (DLAB REGS NOW INACTIVE)
UART_INP(UART_IER) ; READ IER
CP $5A ; CHECK FOR TEST VALUE
JP Z,UART_DETECT_NONE ; IF STILL $5A, UNKNOWN OR NOT PRESENT
JP Z,UART_CHIP_NONE ; IF STILL $5A, UNKNOWN OR NOT PRESENT
;
; TEST FOR FUNCTIONAL SCRATCH REG, IF NOT, WE HAVE AN 8250
LD A,$5A ; LOAD TEST VALUE
UART_OUTP(UART_SCR) ; PUT IT IN SCRATCH REGISTER
UART_INP(UART_SCR) ; READ IT BACK
CP $5A ; CHECK IT
JR NZ,UART_DETECT_8250 ; STUPID 8250
JR NZ,UART_CHIP_8250 ; STUPID 8250
;
; TEST FOR EFR REGISTER WHICH IMPLIES 16650/850
LD A,$BF ; VALUE TO ENABLE EFR
UART_OUTP(UART_LCR) ; WRITE IT TO LCR
UART_INP(UART_SCR) ; READ SCRATCH REGISTER
CP $5A ; SPR STILL THERE?
JR NZ,UART_DETECT1 ; NOPE, HIDDEN, MUST BE 16650/850
JR NZ,UART_CHIP1 ; NOPE, HIDDEN, MUST BE 16650/850
;
; RESET LCR TO DEFAULT (DLAB OFF)
;LD A,$80 ; DLAB BIT ON
@ -394,22 +726,21 @@ UART_DETECT:
UART_OUTP(UART_FCR) ; PUT IT IN FCR
UART_INP(UART_IIR) ; READ BACK FROM IIR
BIT 6,A ; BIT 6 IS FIFO ENABLE, LO BIT
JR Z,UART_DETECT_16450 ; IF NOT SET, MUST BE 16450
JR Z,UART_CHIP_16450 ; IF NOT SET, MUST BE 16450
BIT 7,A ; BIT 7 IS FIFO ENABLE, HI BIT
JR Z,UART_DETECT_16550 ; IF NOT SET, MUST BE 16550
JR Z,UART_CHIP_16550 ; IF NOT SET, MUST BE 16550
BIT 5,A ; BIT 5 IS 64 BYTE FIFO
JR Z,UART_DETECT2 ; IF NOT SET, MUST BE 16550A/C
JR UART_DETECT_16750 ; ONLY THING LEFT IS 16750
JR Z,UART_CHIP2 ; IF NOT SET, MUST BE 16550A/C
JR UART_CHIP_16750 ; ONLY THING LEFT IS 16750
;
UART_DETECT1: ; PICK BETWEEN 16650/850
UART_CHIP1: ; PICK BETWEEN 16650/850
; RESET LCR TO DEFAULT (DLAB OFF)
XOR A ; DLAB BIT OFF
UART_OUTP(UART_LCR) ; RESET LCR
; NOT SURE HOW TO DIFFERENTIATE 16650 FROM 16850 YET
JR UART_DETECT_16650 ; ASSUME 16650
RET
JR UART_CHIP_16650 ; ASSUME 16650
;
UART_DETECT2: ; PICK BETWEEN 16550A/C
UART_CHIP2: ; PICK BETWEEN 16550A/C
; SET AFC BIT IN FCR
LD A,$20 ; SET AFC BIT, MCR:5
UART_OUTP(UART_MCR) ; WRITE NEW FCR VALUE
@ -417,45 +748,45 @@ UART_DETECT2: ; PICK BETWEEN 16550A/C
; READ IT BACK, IF SET, WE HAVE 16550C
UART_INP(UART_MCR) ; READ BACK MCR
BIT 5,A ; CHECK AFC BIT
JR Z,UART_DETECT_16550A ; NOT SET, SO 16550A
JR UART_DETECT_16550C ; IS SET, SO 16550C
JR Z,UART_CHIP_16550A ; NOT SET, SO 16550A
JR UART_CHIP_16550C ; IS SET, SO 16550C
;
UART_DETECT_NONE:
UART_CHIP_NONE:
LD A,(IY+2) ; BASE IO PORT
CP UARTSBASE ; IS THIS PRIMARY SBC PORT?
JR Z,UART_DETECT_8250 ; SPECIAL CASE FOR PRIMARY UART!
JR Z,UART_CHIP_8250 ; SPECIAL CASE FOR PRIMARY UART!
LD A,UART_NONE ; IF SO, TREAT AS 8250 NO MATTER WHAT
RET
;
UART_DETECT_8250:
UART_CHIP_8250:
LD A,UART_8250
RET
;
UART_DETECT_16450:
UART_CHIP_16450:
LD A,UART_16450
RET
;
UART_DETECT_16550:
UART_CHIP_16550:
LD A,UART_16550
RET
;
UART_DETECT_16550A:
UART_CHIP_16550A:
LD A,UART_16550A
RET
;
UART_DETECT_16550C:
UART_CHIP_16550C:
LD A,UART_16550C
RET
;
UART_DETECT_16650:
UART_CHIP_16650:
LD A,UART_16650
RET
;
UART_DETECT_16750:
UART_CHIP_16750:
LD A,UART_16750
RET
;
UART_DETECT_16850:
UART_CHIP_16850:
LD A,UART_16850
RET
;
@ -498,6 +829,7 @@ UART_PRTCFG:
; PRINT THE UART TYPE
CALL PC_SPACE ; FORMATTING
LD A,(IY+1) ; GET UART TYPE BYTE
AND $0F ; LOW BITS ONLY
RLCA ; MAKE IT A WORD OFFSET
LD HL,UART_TYPE_MAP ; POINT HL TO TYPE MAP TABLE
CALL ADDHLA ; HL := ENTRY
@ -516,16 +848,22 @@ UART_PRTCFG:
LD D,(IY+5) ; ... WORD TO DE
CALL PS_PRTSC0 ; PRINT CONFIG
;
; ; PRINT FEATURES ENABLED
; LD A,(UART_FEAT)
; BIT UART_FIFO,A
; JR Z,UART_INITUNIT2
; PRTS(" FIFO$")
;UART_INITUNIT2:
; BIT UART_AFC,A
; JR Z,UART_INITUNIT3
; PRTS(" AFC$")
;UART_INITUNIT3:
; PRINT FEATURES ENABLED
BIT UART_INTACT,(IY+1) ; GET INT RCV BIT
JR Z,UART_PRTCFG1
PRTS(" INT$")
;
UART_PRTCFG1:
BIT UART_FIFOACT,(IY+1) ; GET FIFO BIT
JR Z,UART_PRTCFG2
PRTS(" FIFO$")
;
UART_PRTCFG2:
BIT UART_AFCACT,(IY+1) ; GET AFC BIT
JR Z,UART_PRTCFG3
PRTS(" AFC$")
;
UART_PRTCFG3:
;
XOR A
RET
@ -594,31 +932,34 @@ UART_DEV .DB 0 ; DEVICE NUM USED DURING INIT
;
UART_CFG:
#IF (UARTSBC)
UART_CFG_SBC:
; SBC/ZETA ONBOARD SERIAL PORT
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UARTSBASE ; IO PORT BASE (RBR, THR)
.DB UARTSBASE + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW UARTSBC_RCVBUF ; POINTER TO RCV BUFFER STRUCT
#ENDIF
#IF (UARTCAS)
UART_CFG_CAS:
; CASSETTE INTERFACE SERIAL PORT
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UARTCBASE ; IO PORT BASE (RBR, THR)
.DB UARTCBASE + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCASSPD ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW UARTCAS_RCVBUF ; POINTER TO RCV BUFFER STRUCT
#ENDIF
#IF (UARTMFP)
UART_CFG_MFP:
; MF/PIC SERIAL PORT
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UARTMBASE ; IO PORT BASE (RBR, THR)
.DB UARTMBASE + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
#ENDIF
#IF (UART4)
; 4UART SERIAL PORT A
@ -627,28 +968,28 @@ UART_CFG:
.DB UART4BASE+0 ; IO PORT BASE (RBR, THR)
.DB UART4BASE+0 + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
; 4UART SERIAL PORT B
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UART4BASE+8 ; IO PORT BASE (RBR, THR)
.DB UART4BASE+8 + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
; 4UART SERIAL PORT C
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UART4BASE+16 ; IO PORT BASE (RBR, THR)
.DB UART4BASE+16 + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
; 4UART SERIAL PORT D
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UART4BASE+24 ; IO PORT BASE (RBR, THR)
.DB UART4BASE+24 + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
#ENDIF
#IF (UARTRC)
; UARTRC SERIAL PORT A
@ -657,14 +998,47 @@ UART_CFG:
.DB UARTRBASE ; IO PORT BASE (RBR, THR)
.DB UARTRBASE + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
; UARTRC SERIAL PORT B
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
.DB 0 ; UART TYPE
.DB UARTRBASE+8 ; IO PORT BASE (RBR, THR)
.DB UARTRBASE+8 + UART_LSR ; LINE STATUS PORT (LSR)
.DW UARTCFG ; LINE CONFIGURATION
.FILL 2,$FF ; FILLER
.DW 0 ; SHOULD NEVER NEED INT HANDLER
#ENDIF
;
UART_CNT .EQU ($ - UART_CFG) / 8
;
#IF ((!UARTINTS) | (INTMODE == 0))
;
UARTSBC_RCVBUF .EQU 0
UARTCAS_RCVBUF .EQU 0
;
#ELSE
;
; UART SBC RECEIVE BUFFER
;
#IF (UARTSBC)
;
UARTSBC_RCVBUF:
UARTSBC_CNT .DB 0 ; CHARACTERS IN RING BUFFER
UARTSBC_HD .DW UARTSBC_BUF ; BUFFER HEAD POINTER
UARTSBC_TL .DW UARTSBC_BUF ; BUFFER TAIL POINTER
UARTSBC_BUF .FILL UART_BUFSZ,0 ; RECEIVE RING BUFFER
;
#ENDIF
;
; UART CASSETTE RECEIVE BUFFER
;
#IF (UARTCAS)
;
UARTCAS_RCVBUF:
UARTCAS_CNT .DB 0 ; CHARACTERS IN RING BUFFER
UARTCAS_HD .DW UARTCAS_BUF ; BUFFER HEAD POINTER
UARTCAS_TL .DW UARTCAS_BUF ; BUFFER TAIL POINTER
UARTCAS_BUF .FILL UART_BUFSZ,0 ; RECEIVE RING BUFFER
;
#ENDIF
;
#ENDIF

2
Source/ver.inc

@ -2,4 +2,4 @@
#DEFINE RMN 1
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "3.1.1-pre.112"
#DEFINE BIOSVER "3.1.1-pre.113"

2
Source/ver.lib

@ -3,5 +3,5 @@ rmn equ 1
rup equ 1
rtp equ 0
biosver macro
db "3.1.1-pre.112"
db "3.1.1-pre.113"
endm

Loading…
Cancel
Save