forked from MirrorRepos/RomWBW
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.
920 lines
25 KiB
920 lines
25 KiB
;=======================================================================
|
|
;
|
|
; XMHB.Z80 - XMODEM12 PATCH FILE FOR ROMWBW HBIOS
|
|
;
|
|
; Wayne Warthen - wwarthen@gmail.com
|
|
;
|
|
; 2018-06-06 WBW Added support for RCBus w/ Z180
|
|
; 2019-08-17 WBW Refactored and merged Phil's ECB-FIFO support
|
|
; 2019-08-28 WBW Refactored ASCI support
|
|
;
|
|
;=======================================================================
|
|
;
|
|
ASEG
|
|
;
|
|
NO EQU 0
|
|
YES EQU NOT NO
|
|
;
|
|
ERRDET EQU NO ; detect parity/framing/overrun errs
|
|
;
|
|
BASE EQU 100H ; start of cp/m normal program area
|
|
;
|
|
BDOS EQU 00005H ; BDOS function dispatch vector
|
|
;
|
|
;=======================================================================
|
|
;
|
|
; Jump table: The jump table must be in exactly the same sequence as the
|
|
; one in XMODEM. Note the ORG of 103H - This jump table has no jump to
|
|
; 'BEGIN'.
|
|
;
|
|
ORG BASE + 3 ; start after 'JMP BEGIN'
|
|
;
|
|
JP CONOUT ; must be 00000h if not used, see below
|
|
JP MINIT ; initialization routine (if needed)
|
|
JP UNINIT ; undo whatever 'MINIT' did (or return)
|
|
JPTBL:
|
|
JP SENDR ; send character (via pop psw)
|
|
JP CAROK ; test for carrier
|
|
JP MDIN ; receive data byte
|
|
JP GETCHR ; get character from modem
|
|
JP RCVRDY ; check receive ready
|
|
JP SNDRDY ; check send ready
|
|
JP SPEED ; get speed value for file transfer time
|
|
JP EXTRA1 ; extra for custom routine
|
|
JP EXTRA2 ; extra for custom routine
|
|
JP EXTRA3 ; extra for custom routine
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Output character to console
|
|
;
|
|
CONOUT EQU 0 ; not used
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Initialize modem
|
|
;
|
|
; This procedure has been usurped to dynamically detect the type
|
|
; of system we are running on and install the *real* jump table
|
|
; entries as appropriate.
|
|
;
|
|
MINIT:
|
|
; Announce
|
|
LD DE,RBC ; RetroBrew Computers
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
;
|
|
; Identify BIOS (RomWBW HBIOS or UNA UBIOS)
|
|
CALL IDBIO ; 1=HBIOS, 2=UBIOS
|
|
LD (BIOID),A ; Save it
|
|
DEC A ; Test for HBIOS
|
|
JR Z,HINIT ; Do HBIOS setup
|
|
DEC A ; Test for UBIOS
|
|
JR Z,UINIT ; Do UBIOS setup
|
|
;
|
|
; Neither UNA nor RomWBW
|
|
LD DE,ERR_BIO ; BIOS error message
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
JP 0 ; Bail out!
|
|
;
|
|
MINIT_RET:
|
|
PUSH HL ; Save HL (JP table adr)
|
|
|
|
; Display port notification string
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
;
|
|
; Newline
|
|
LD C,9 ; BDOS string display function
|
|
LD DE,CRLF ; Newline
|
|
CALL BDOS ; Do it
|
|
;
|
|
; Copy real vectors into active jump table
|
|
POP HL ; Recover HL
|
|
LD DE,JPTBL ; Real jump table is destination
|
|
LD BC,7 * 3 ; Copy 7 3-byte entries
|
|
LDIR ; Do the copy
|
|
;
|
|
; Return with CPU speed in A
|
|
LD A,(CPUSPD) ; A := CPU speed in MHz
|
|
LD HL,(RCVSCL) ; HL := receive scalar
|
|
RET ; and return
|
|
;
|
|
HINIT:
|
|
; Display RomWBW notification string
|
|
LD DE,HBTAG ; BIOS notification string
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
;
|
|
; Get CPU speed from RomWBW HBIOS and save it
|
|
LD B,0F8H ; HBIOS SYSGET function 0xF8
|
|
LD C,0F0H ; CPUINFO subfunction 0xF0
|
|
RST 08 ; Do it, L := CPU speed in MHz
|
|
LD A,L ; Move it to A
|
|
LD (CPUSPD),A ; Save it
|
|
;
|
|
; Get HBIOS character 0 device type
|
|
LD B,006H ; HBIOS DEVICE function 0x06
|
|
LD C,000H ; HBIOS char 0 device
|
|
RST 08 ; Do it, D=device type
|
|
LD A,D ; Put result in A
|
|
CP 000H ; UART?
|
|
JP Z,U_INIT ; If so, do UART init
|
|
CP 010H ; ASCI?
|
|
JP Z,A_INIT ; If so, do ASCI init
|
|
CP 080H ; USB-FIFO?
|
|
JP Z,UF_INIT ; If so, do USB-FIFO init
|
|
JP H_INIT ; Otherwise, use HBIOS I/O
|
|
;
|
|
UINIT:
|
|
; Display UNA notification string
|
|
LD DE,UBTAG ; BIOS notification string
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
;
|
|
; Get CPU speed from UNA and save it
|
|
LD C,0F8H ; UNA BIOS Get PHI function
|
|
RST 08 ; Returns speed in Hz in DE:HL
|
|
LD B,4 ; Divide MHz in DE:HL by 100000H
|
|
UINIT1:
|
|
SRL D ; ... to get approx CPU speed in
|
|
RR E ; ...MHz. Throw away HL, and
|
|
DJNZ UINIT1 ; ...right shift DE by 4.
|
|
INC E ; Fix up for value truncation
|
|
LD A,E ; Put in A
|
|
LD (CPUSPD),A ; Save it
|
|
;
|
|
; Check CPU, Z80=UART, Z180=ASCI
|
|
LD DE,00202H ; D := 2, E := 2
|
|
MLT DE ; DE := D * E == 4
|
|
BIT 2,E ; Bit 2 wil be set if mlt happend
|
|
JP Z,U_INIT ; UART initialization
|
|
JP A_INIT ; otherwise, ASCI
|
|
;
|
|
HWERR:
|
|
; Failed to identify target comm hardware
|
|
LD DE,ERR_HW ; Hardware error message
|
|
LD C,9 ; BDOS string display function
|
|
CALL BDOS ; Do it
|
|
JP 0 ; Bail out!
|
|
;
|
|
; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0
|
|
;
|
|
IDBIO:
|
|
;
|
|
; Check for UNA (UBIOS)
|
|
LD A,(0FFFDH) ; fixed location of UNA API vector
|
|
CP 0C3H ; jp instruction?
|
|
JR NZ,IDBIO1 ; if not, not UNA
|
|
LD HL,(0FFFEH) ; get jp address
|
|
LD A,(HL) ; get byte at target address
|
|
CP 0FDH ; first byte of UNA push ix instruction
|
|
JR NZ,IDBIO1 ; if not, not UNA
|
|
INC HL ; point to next byte
|
|
LD A,(HL) ; get next byte
|
|
CP 0E5H ; second byte of UNA push ix instruction
|
|
JR NZ,IDBIO1 ; if not, not UNA, check others
|
|
LD A,2 ; UNA BIOS id = 2
|
|
RET ; and done
|
|
;
|
|
IDBIO1:
|
|
; Check for RomWBW (HBIOS)
|
|
LD HL,(0FFFEH) ; HL := HBIOS ident location
|
|
LD A,'W' ; First byte of ident
|
|
CP (HL) ; Compare
|
|
JR NZ,IDBIO2 ; Not HBIOS
|
|
INC HL ; Next byte of ident
|
|
LD A,~'W' ; Second byte of ident
|
|
CP (HL) ; Compare
|
|
JR NZ,IDBIO2 ; Not HBIOS
|
|
LD A,1 ; HBIOS BIOS id = 1
|
|
RET ; and done
|
|
;
|
|
IDBIO2:
|
|
; No idea what this is
|
|
XOR A ; Setup return value of 0
|
|
RET ; and done
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Uninitialize modem
|
|
;
|
|
UNINIT:
|
|
LD A,(BIOID)
|
|
CP 1 ; Is HBIOS?
|
|
JR Z,H_UNINIT ; Handle HBIOS
|
|
CP 2 ; Is UBIOS?
|
|
JR Z,U_UNINIT ; Handle UBIOS
|
|
RET ; Just return
|
|
;
|
|
H_UNINIT:
|
|
; HBIOS: Reset character device 0
|
|
LD B,04H ; HBIOS CIOINIT function 0x04
|
|
LD C,0 ; Unit = 0
|
|
LD DE,-1 ; Reset w/ current settings
|
|
RST 08 ; Do it
|
|
RET ; not initialized, so no 'UN-INITIALIZE'
|
|
;
|
|
U_UNINIT:
|
|
; UBIOS: Reset character device 0
|
|
LD C,10H ; UNA INIT function 0x10
|
|
LD B,0 ; Unit = 0
|
|
LD DE,-1 ; Reset w/ current settings
|
|
RST 08 ; Do it
|
|
RET ; not initialized, so no 'UN-INITIALIZE'
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; The following are all dummy routines that are unused because MINIT
|
|
; dynamically installs the real jump table.
|
|
;
|
|
SENDR:
|
|
CAROK:
|
|
MDIN:
|
|
GETCHR:
|
|
RCVRDY:
|
|
SNDRDY:
|
|
SPEED:
|
|
EXTRA1:
|
|
EXTRA2:
|
|
EXTRA3:
|
|
RET
|
|
;
|
|
BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS
|
|
CPUSPD DB 10 ; CPU speed in MHz
|
|
RCVSCL DW 6600 ; RECV loop timeout scalar
|
|
;
|
|
RBC DB "RBC, 28-Aug-2019$"
|
|
;
|
|
U_LBL DB ", UART$"
|
|
A_LBL DB ", ASCI$"
|
|
S_LBL DB ", SIO$"
|
|
H_LBL DB ", COM$"
|
|
UF_LBL DB ", USB-FIFO$"
|
|
;
|
|
UBTAG DB " [UNA]$"
|
|
HBTAG DB " [WBW]$"
|
|
;
|
|
CRLF DB 13, 10, "$"
|
|
;
|
|
ERR_BIO DB 13, 10, 13, 10, "++ Unknown BIOS ++", 13, 10, "$"
|
|
ERR_HW DB 13, 10, 13, 10, "++ Unknown Hardware ++", 13, 10, "$"
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; 8250-like UART @ Port 68H
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; UART port constants
|
|
;
|
|
U_BASE EQU 68H ; UART base port
|
|
U_DATP EQU U_BASE + 0 ; data in port
|
|
U_DATO EQU U_BASE + 0 ; data out port
|
|
U_CTLP EQU U_BASE + 5 ; control/status port
|
|
U_SNDB EQU 20H ; bit to test for send ready
|
|
U_SNDR EQU 20H ; value when ready to send
|
|
U_RCVB EQU 01H ; bit to test for receive ready
|
|
U_RCVR EQU 01H ; value when ready to receive
|
|
U_PARE EQU 04H ; bit for parity error
|
|
U_OVRE EQU 02H ; bit for overrun error
|
|
U_FRME EQU 08H ; bit for framing error
|
|
U_ERRS EQU U_FRME | U_OVRE | U_PARE
|
|
;
|
|
; Following jump table is dynamically patched into real jump
|
|
; table at program startup. See MINIT above. Note that only a
|
|
; subset of the jump table is overlaid (SENDR to SPEED).
|
|
;
|
|
U_JPTBL:
|
|
JP U_SENDR ; send character (via pop psw)
|
|
JP U_CAROK ; test for carrier
|
|
JP U_MDIN ; receive data byte
|
|
JP U_GETCHR ; get character from modem
|
|
JP U_RCVRDY ; check receive ready
|
|
JP U_SNDRDY ; check send ready
|
|
JP U_SPEED ; get speed value for file transfer time
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; UART initialization
|
|
;
|
|
U_INIT:
|
|
LD HL,13000 ; Receive loop timeout scalar
|
|
LD (RCVSCL),HL ; ... for UART RCVRDY timing
|
|
;
|
|
LD HL,U_JPTBL
|
|
LD DE,U_LBL
|
|
JP MINIT_RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Send character on top of stack
|
|
;
|
|
U_SENDR:
|
|
POP AF ; get character to send from stack
|
|
OUT (U_DATO),A ; send to port
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test and report carrier status, Z set if carrier present
|
|
;
|
|
U_CAROK:
|
|
XOR A ; not used, always indicate present
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get a character (assume character ready has already been tested)
|
|
;
|
|
U_MDIN:
|
|
U_GETCHR:
|
|
IN A,(U_DATP) ; read character from port
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for character ready to receive, Z = ready
|
|
; Error code returned in A register
|
|
; *** Error code does not seem to be used ***
|
|
;
|
|
U_RCVRDY:
|
|
IN A,(U_CTLP) ; get modem status
|
|
;
|
|
IF ERRDET
|
|
;
|
|
; With error detection (slower)
|
|
PUSH BC ; save scratch register
|
|
PUSH AF ; save full status on stack
|
|
AND U_ERRS ; isolate line err bits
|
|
LD B,A ; save err status in B
|
|
POP AF ; get full status back
|
|
AND U_RCVB ; isolate ready bit
|
|
CP U_RCVR ; test it (set flags)
|
|
LD A,B ; get the error code back
|
|
POP BC ; restore scratch register
|
|
;
|
|
ELSE
|
|
;
|
|
; No error detection (faster)
|
|
AND U_RCVB ; isolate ready bit
|
|
CP U_RCVR ; test it (set flags)
|
|
LD A,0 ; report no line errors
|
|
;
|
|
ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for ready to send a character, Z = ready
|
|
;
|
|
U_SNDRDY:
|
|
IN A,(U_CTLP) ; get status
|
|
AND U_SNDB ; isolate transmit ready bit
|
|
CP U_SNDR ; test for ready value
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Report baud rate (index into SPTBL returned in register A)
|
|
;
|
|
U_SPEED:
|
|
LD A,8 ; arbitrarily return 9600 baud
|
|
RET
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; Z180 Primary ASCI
|
|
;
|
|
; - Port is determined dynamically in A_INIT
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; ASCI port constants
|
|
;
|
|
A_DATP EQU 08H ; Z180 TSR - ASCI receive data port
|
|
A_DATO EQU 06H ; Z180 TDR - ASCI transmit data port
|
|
A_CTLP EQU 04H ; Z180 STAT - ASCI status port
|
|
A_CTL2 EQU 00H ; Z180 CNTLA - ASCI control port
|
|
;
|
|
A_SNDB EQU 02H ; Z180 STAT:TDRE - xmit data reg empty bit
|
|
A_SNDR EQU 02H ; Z180 STAT:TDRE - xmit data reg empty value
|
|
A_RCVB EQU 80H ; Z180 STAT:RDRF - rcv data reg full bit
|
|
A_RCVR EQU 80H ; Z180 STAT:RDRF - rcv data reg full value
|
|
A_PARE EQU 20H ; Z180 STAT:PE - parity error bit
|
|
A_OVRE EQU 40H ; Z180 STAT:OVRN - overrun error bit
|
|
A_FRME EQU 10H ; Z180 STAT:FE - framing error bit
|
|
A_ERRS EQU A_FRME | A_OVRE | A_PARE
|
|
;
|
|
A_BASE DB 00H ; internal IO base address for Z180
|
|
;
|
|
; Following jump table is dynamically patched over initial jump
|
|
; table at program startup. See MINIT above. Note that only a
|
|
; subset of the jump table is overlaid (SENDR to SPEED).
|
|
;
|
|
A_JPTBL:
|
|
JP A_SENDR ; send character (via pop psw)
|
|
JP A_CAROK ; test for carrier
|
|
JP A_MDIN ; receive data byte
|
|
JP A_GETCHR ; get character from modem
|
|
JP A_RCVRDY ; check receive ready
|
|
JP A_SNDRDY ; check send ready
|
|
JP A_SPEED ; get speed value for file transfer time
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; ASCI initialization
|
|
;
|
|
A_INIT:
|
|
LD HL,7500 ; Receive loop timeout scalar
|
|
LD (RCVSCL),HL ; ... for ASCI RCVRDY timing
|
|
;
|
|
; Test for location of Z180 internal registers
|
|
; and use appropriate I/O address.
|
|
LD B,0 ; set MSB for 16 bit I/O
|
|
LD C,040H|3FH ; internal registers @ 40H?
|
|
IN A,(C) ; read
|
|
CP 040H|01FH ; same value except for bit 5?
|
|
JR Z,A_INIT1 ; do ASCI init (port in C)
|
|
LD C,0C0H|3FH ; internal registers @ C0H?
|
|
IN A,(C) ; read
|
|
CP 0C0H|1FH ; same value except for bit 5?
|
|
JR Z,A_INIT1 ; do ASCI init (port in C)
|
|
JP HWERR ; unknown hardware error
|
|
;
|
|
A_INIT1:
|
|
LD A,C ; test port value to A
|
|
AND 0C0H ; only top two bits relevant
|
|
LD (A_BASE),A ; save it
|
|
ADD A,A_CTLP ; status port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
XOR A ; clear interrupt enable flags
|
|
OUT (C),A ; do it
|
|
;
|
|
LD HL,A_JPTBL
|
|
LD DE,A_LBL
|
|
JP MINIT_RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Send character on top of stack
|
|
;
|
|
A_SENDR:
|
|
EX (SP),HL ; save HL, HL := char to send
|
|
PUSH BC ; save scratch register
|
|
LD A,(A_BASE) ; IO base address
|
|
ADD A,A_DATO ; data out port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
OUT (C),H ; send to port
|
|
POP BC ; restore scratch reg
|
|
POP HL ; restore HL
|
|
RET ; done
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test and report carrier status, Z set if carrier present
|
|
;
|
|
A_CAROK:
|
|
XOR A ; not used, always indicate present
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get a character (assume character ready has already been tested)
|
|
;
|
|
A_MDIN:
|
|
A_GETCHR:
|
|
PUSH BC ; save scratch register
|
|
LD A,(A_BASE) ; IO base address
|
|
ADD A,A_DATP ; data in port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
IN A,(C) ; read character from port
|
|
POP BC ; restore scratch reg
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for character ready to receive, Z = ready
|
|
; Error code returned in A register
|
|
; *** Error code does not seem to be used ***
|
|
;
|
|
A_RCVRDY:
|
|
PUSH BC ; save scratch register
|
|
LD A,(A_BASE) ; IO base address
|
|
ADD A,A_CTLP ; status port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
IN A,(C) ; get modem status
|
|
PUSH AF ; save full status on stack
|
|
AND A_ERRS ; isolate line err bits
|
|
LD B,A ; save err status in B
|
|
|
|
; Z180 ASCI ports will stall if there are errors.
|
|
; Error bits are NOT cleared by merely reading
|
|
; the status register. Below, bit 3 of ASCI
|
|
; control register is written with a zero to
|
|
; clear error(s) if needed.
|
|
JR Z,A_RCVRDY2 ; if no errs, continue
|
|
PUSH BC ; save scratch reg
|
|
LD A,(A_BASE) ; IO base address
|
|
ADD A,A_CTL2 ; status port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
IN A,(C) ; get current control reg value
|
|
AND 0F7H ; force err reset bit to zero
|
|
OUT (C),A ; write control register
|
|
POP BC ; restore scratch reg
|
|
;
|
|
A_RCVRDY2:
|
|
POP AF ; get full status back
|
|
AND A_RCVB ; isolate ready bit
|
|
CP A_RCVR ; test it (set flags)
|
|
LD A,B ; get the error code back
|
|
POP BC ; restore scratch register
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for ready to send a character, Z = ready
|
|
;
|
|
A_SNDRDY:
|
|
PUSH BC ; save scratch register
|
|
LD A,(A_BASE) ; IO base address
|
|
ADD A,A_CTLP ; status port offset
|
|
LD C,A ; put in C for I/O
|
|
LD B,0 ; MSB for 16 bit I/O
|
|
IN A,(C) ; get modem status
|
|
AND A_SNDB ; isolate transmit ready bit
|
|
CP A_SNDR ; test for ready value
|
|
POP BC ; restore scratch register
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Report baud rate (index into SPTBL returned in register A)
|
|
;
|
|
A_SPEED:
|
|
LD A,8 ; arbitrarily return 9600 baud
|
|
RET
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; Zilog SIO @ Port 80H
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; Currently assumes the port address and ordering conventions of the
|
|
; official RCBus SIO module. Will not work with others such as EZZ80
|
|
; or ZP.
|
|
;
|
|
; SIO port constants
|
|
;
|
|
S_BASE EQU 80H ; SIO base port
|
|
S_DATP EQU S_BASE + 1 ; data in port
|
|
S_DATO EQU S_BASE + 1 ; data out port
|
|
S_CTLP EQU S_BASE + 0 ; control/status port
|
|
S_SNDB EQU 04H ; bit to test for send ready
|
|
S_SNDR EQU 04H ; value when ready to send
|
|
S_RCVB EQU 01H ; bit to test for receive ready
|
|
S_RCVR EQU 01H ; value when ready to receive
|
|
;
|
|
; Following jump table is dynamically patched into real jump
|
|
; table at program startup. See MINIT above. Note that only a
|
|
; subset of the jump table is overlaid (SENDR to SPEED).
|
|
;
|
|
S_JPTBL:
|
|
JP S_SENDR ; send character (via pop psw)
|
|
JP S_CAROK ; test for carrier
|
|
JP S_MDIN ; receive data byte
|
|
JP S_GETCHR ; get character from modem
|
|
JP S_RCVRDY ; check receive ready
|
|
JP S_SNDRDY ; check send ready
|
|
JP S_SPEED ; get speed value for file transfer time
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; SIO initialization
|
|
;
|
|
S_INIT:
|
|
LD HL,12000 ; Receive loop timeout scalar
|
|
LD (RCVSCL),HL ; ... for UART RCVRDY timing
|
|
;
|
|
; Suppress interrupts
|
|
LD A,01H ; WR1
|
|
OUT (S_CTLP),A ; Select WR1
|
|
XOR A ; No interrupts
|
|
OUT (S_CTLP),A ; Do it
|
|
;
|
|
LD HL,S_JPTBL
|
|
LD DE,S_LBL
|
|
JP MINIT_RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Send character on top of stack
|
|
;
|
|
S_SENDR:
|
|
POP AF ; get character to send from stack
|
|
OUT (S_DATO),A ; send to port
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test and report carrier status, Z set if carrier present
|
|
;
|
|
S_CAROK:
|
|
XOR A ; not used, always indicate present
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get a character (assume character ready has already been tested)
|
|
;
|
|
S_MDIN:
|
|
S_GETCHR:
|
|
IN A,(S_DATP) ; read character from port
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for character ready to receive, Z = ready
|
|
; Error code returned in A register
|
|
; *** Error code does not seem to be used ***
|
|
;
|
|
S_RCVRDY:
|
|
;XOR A
|
|
;OUT (S_CTLP),A ; select WR0
|
|
IN A,(S_CTLP) ; get status
|
|
AND S_RCVB ; isolate ready bit
|
|
CP S_RCVR ; test it (set flags)
|
|
LD A,0 ; report no line errors
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for ready to send a character, Z = ready
|
|
;
|
|
S_SNDRDY:
|
|
;XOR A
|
|
;OUT (S_CTLP),A ; select WR0
|
|
IN A,(S_CTLP) ; get status
|
|
AND S_SNDB ; isolate ready bit
|
|
CP S_SNDR ; test it (set flags)
|
|
LD A,0 ; report no line errors
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Report baud rate (index into SPTBL returned in register A)
|
|
;
|
|
S_SPEED:
|
|
LD A,8 ; arbitrarily return 9600 baud
|
|
RET
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; HBIOS Console (COM0:)
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; Following jump table is dynamically patched over initial jump
|
|
; table at program startup. See MINIT above. Note that only a
|
|
; subset of the jump table is overlaid (SENDR to SPEED).
|
|
;
|
|
H_JPTBL:
|
|
JP H_SENDR ; send character (via pop psw)
|
|
JP H_CAROK ; test for carrier
|
|
JP H_MDIN ; receive data byte
|
|
JP H_GETCHR ; get character from modem
|
|
JP H_RCVRDY ; check receive ready
|
|
JP H_SNDRDY ; check send ready
|
|
JP H_SPEED ; get speed value for file transfer time
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; HBIOS initialization
|
|
;
|
|
H_INIT:
|
|
LD HL,1250 ; Smaller receive loop timeout scalar
|
|
LD (RCVSCL),HL ; ... to compensate for BIOS overhead
|
|
;
|
|
LD HL,H_JPTBL
|
|
LD DE,H_LBL
|
|
JP MINIT_RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Send character on top of stack
|
|
;
|
|
H_SENDR:
|
|
POP AF ; get character to send from stack
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD B,01H ; HBIOS OUT function
|
|
LD C,0 ; console is unit 0 by fiat
|
|
LD E,A ; character to E
|
|
RST 08 ; HBIOS call
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test and report carrier status, Z set if carrier present
|
|
;
|
|
H_CAROK:
|
|
XOR A ; not used, always indicate present
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get a character (assume character ready has already been tested)
|
|
;
|
|
; This routine must NOT block.
|
|
;
|
|
H_MDIN:
|
|
H_GETCHR:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD B,02H ; HBIOS IST function
|
|
LD C,0 ; console is unit 0 by fiat
|
|
RST 08 ; HBIOS call, A := bytes pending
|
|
JR NZ,H_MDIN1 ; If char(s) waiting, go get it
|
|
XOR A ; otherwise, return null
|
|
JR H_MDIN2 ; and done
|
|
H_MDIN1:
|
|
LD B,00H ; HBIOS IN function
|
|
LD C,0 ; console is unit 0 by fiat
|
|
RST 08 ; HBIOS call
|
|
LD A,E ; byte received to A
|
|
H_MDIN2:
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for character ready to receive, Z = ready
|
|
; Error code returned in A register
|
|
; *** Error code does not seem to be used ***
|
|
;
|
|
H_RCVRDY:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD B,02H ; HBIOS IST function
|
|
LD C,0 ; console is unit 0 by fiat
|
|
RST 08 ; HBIOS call, A := bytes pending
|
|
SUB 1 ; CF set IFF zero
|
|
RL A ; CF to bit 0 of A
|
|
AND 01H ; set Z flag as needed
|
|
LD A,0 ; report no line errors
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for ready to send a character, Z = ready
|
|
;
|
|
H_SNDRDY:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD B,03H ; HBIOS OST function
|
|
LD C,0 ; console is unit 0 by fiat
|
|
RST 08 ; HBIOS call, A := xmit buf bytes avail
|
|
SUB 1 ; CF set IFF zero
|
|
RL A ; CF to bit 0 of A
|
|
AND 01H ; set Z flag as needed
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Report baud rate (index into SPTBL returned in register A)
|
|
;
|
|
H_SPEED:
|
|
LD A,8 ; arbitrarily return 9600 baud
|
|
RET
|
|
;
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
; WILL SOWERBUTTS ECB USB-FIFO
|
|
;
|
|
;=======================================================================
|
|
;=======================================================================
|
|
;
|
|
UF_BASE EQU 0CH
|
|
UF_DATA EQU (UF_BASE+0)
|
|
UF_STATUS EQU (UF_BASE+1)
|
|
UF_SEND_IMM EQU (UF_BASE+2)
|
|
;
|
|
; Following jump table is dynamically patched over initial jump
|
|
; table at program startup. See MINIT above. Note that only a
|
|
; subset of the jump table is overlaid (SENDR to SPEED).
|
|
;
|
|
UF_JPTBL:
|
|
JP UF_SENDR ; send character (via pop psw)
|
|
JP UF_CAROK ; test for carrier
|
|
JP UF_MDIN ; receive data byte
|
|
JP UF_GETCHR ; get character from modem
|
|
JP UF_RCVRDY ; check receive ready
|
|
JP UF_SNDRDY ; check send ready
|
|
JP UF_SPEED ; get speed value for file transfer time
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; USB-FIFO initialization
|
|
;
|
|
UF_INIT:
|
|
LD HL,12000 ; Receive loop timeout scalar
|
|
LD (RCVSCL),HL ; ... for UART RCVRDY timing
|
|
;
|
|
LD HL,UF_JPTBL
|
|
LD DE,UF_LBL
|
|
JP MINIT_RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Send character on top of stack
|
|
;
|
|
UF_SENDR:
|
|
|
|
POP AF ; get character to send from stack
|
|
OUT (UF_DATA),A ; WRITE TO FIFO
|
|
OUT (UF_SEND_IMM),A ; SEND IMMEDIATE
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test and report carrier status, Z set if carrier present
|
|
;
|
|
UF_CAROK:
|
|
XOR A ; not used, always indicate present
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get a character (assume character ready has already been tested)
|
|
;
|
|
; This routine must NOT block.
|
|
;
|
|
UF_MDIN:
|
|
UF_GETCHR:
|
|
IN A,(UF_DATA) ; GET CHAR
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for character ready to receive, Z = ready
|
|
; Error code returned in A register
|
|
; *** Error code does not seem to be used ***
|
|
;
|
|
UF_RCVRDY:
|
|
IN A,(UF_STATUS) ; B7=0 IF CHAR AVAIL, =1 IF NO CHAR.
|
|
RLCA ; B0=0 IF CHAR AVAIL, =1 IF NO CHAR.
|
|
AND 00000001B ; A=0, ZF=1 IF NO CHAR, A=1, ZF=0 IF CHAR AVAIL,
|
|
LD A,0
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Test for ready to send a character, Z = ready
|
|
;
|
|
UF_SNDRDY:
|
|
IN A,(UF_STATUS) ; Bit 0=0 IF SPACE AVAIL, =1 IF FULL
|
|
AND 00000001B ; A=0, ZF=1 IF SPACE AVAIL, A=1, ZF=0 IF FULL.
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Report baud rate (index into SPTBL returned in register A)
|
|
;
|
|
UF_SPEED:
|
|
LD A,8 ; arbitrarily return 9600 baud
|
|
RET
|
|
;
|
|
END
|
|
|