diff --git a/Source/Apps/XM/xmhb.180 b/Source/Apps/XM/xmhb.180 index b97886b5..7e33e4ac 100644 --- a/Source/Apps/XM/xmhb.180 +++ b/Source/Apps/XM/xmhb.180 @@ -1,19 +1,14 @@ ;======================================================================= ; -; XMHB.Z80 - XMODEMXX PATCH FILE FOR ROMWBW HBIOS +; XMHB.Z80 - XMODEM12 PATCH FILE FOR ROMWBW HBIOS ; ; Wayne Warthen - wwarthen@gmail.com -; Updated: 2018-06-06 ; ; 2018-06-06 WBW Added support for RC2014 w/ Z180 +; 2019-08-17 WBW Refactored and merged Phil's ECB-FIFO support ; ;======================================================================= ; -; Overlay file is Z80, build with M80: -; M80 =XMHB -; L80 XMHB,XMHB/N/X/E -; - .Z80 ASEG ; NO EQU 0 @@ -31,22 +26,22 @@ BDOS EQU 00005H ; BDOS function dispatch vector ; one in XMODEM. Note the ORG of 103H - This jump table has no jump to ; 'BEGIN'. ; - ORG BASE + 3 ;start after 'JMP 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) + 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 + 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 ; ;----------------------------------------------------------------------- ; @@ -63,7 +58,6 @@ CONOUT EQU 0 ; not used ; entries as appropriate. ; MINIT: -; ; Announce LD DE,RBC ; RetroBrew Computers LD C,9 ; BDOS string display function @@ -78,13 +72,35 @@ MINIT: JR Z,UINIT ; Do UBIOS setup ; ; Neither UNA nor RomWBW - LD DE,BIOERR ; BIOS error message + LD DE,ERR_BIO ; BIOS error message LD C,9 ; BDOS string display function CALL BDOS ; Do it JP 0 ; Bail out! ; -HINIT: +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 @@ -103,10 +119,34 @@ HINIT: RST 08 ; Do it, L := CPU speed in MHz LD A,L ; Move it to A LD (CPUSPD),A ; Save it - JR MINIT1 ; Continue general initialization ; -UINIT: + ; 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 HINIT1 ; If so, handle it below + CP 080H ; USB-FIFO? + JP UF_INIT ; If so, do USB-FIFO init + JR HWERR ; Unknown hardware error +; +HINIT1: + ; Use platform to select ASCI driver + LD A,(PLTID) ; Get platform id + CP 4 ; N8? + JP Z,A4_INIT ; Init ASCI @ $40 + CP 5 ; Mark IV? + JP Z,A4_INIT ; Init ASCI @ $40 + CP 8 ; RCZ180? + JP Z,AC_INIT ; Init ASCI @ $C0 + CP 10 ; SC126? + JP Z,AC_INIT ; Init ASCI @ $C0 + JR HWERR ; Unknown hardware error ; +UINIT: ; Display UNA notification string LD DE,UBTAG ; BIOS notification string LD C,9 ; BDOS string display function @@ -115,7 +155,7 @@ UINIT: ; 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 + 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 @@ -123,85 +163,22 @@ UINIT1: INC E ; Fix up for value truncation LD A,E ; Put in A LD (CPUSPD),A ; Save it - JR MINIT1 ; Continue general initialization -; -MINIT1: - ; NOTE: PLTID is only set if RomWBW HBIOS is active. This is OK - ; because RC2014 is only supported by RomWBW HBIOS at this point. - LD A,(PLTID) ; Get the platform id - CP 7 ; Check for RC2014 - JR Z,RCINIT ; Handle RC2014 special - CP 8 ; Check for RC2014 w/ Z180 - JR Z,ARCINIT ; Handle RC2014 w/ Z180 - CP 9 ; Check for Easy Z80 - JR Z,RCINIT ; Treat same as RC2014 for now - CP 10 ; Check for SC126 w/ Z180 - JR Z,ARCINIT ; Handle SC126 w/ Z180 -; - ; Check for Z180 which implies ASCI serial port +; + ; Check CPU, Z80=UART, A180=ASCI @ $40 LD DE,00202H ; D := 2, E := 2 MLT DE ; DE := D * E == 4 BIT 2,E ; Bit 2 wil be set if mlt happend - JR Z,MINIT2 ; Not Z180 (ASCI), look for others - LD HL,ASCI_JPTBL ; Point to Z180 (ASCI) jump table - LD DE,ASCI ; ASCI port notification string - JR MINIT3 ; Complete the initialization -; -MINIT2: - ; Not a Z180, so assume RBC standard UART serial port - LD HL,UART_JPTBL ; Assume Z80 (UART) - LD DE,UART ; UART port notification string - JR MINIT3 ; Complete the initialization -; -RCINIT: - ;; RC2014, use SIO - ;; Suppress interrupts - ;LD A,01H ; WR1 - ;OUT (S_CTLP),A ; Select WR1 - ;XOR A ; No interrupts - ;OUT (S_CTLP),A ; Do it - ;; Setup JP table - ;LD HL,SIO_JPTBL ; HBIOS jump table address - ;LD DE,SIO ; HBIOS console notification string - ;JR MINIT3 ; Complete the initialization - - ; RC2014, use HBIOS calls - LD HL,1250 ; Smaller receive loop tiemout scalar - LD (RCVSCL),HL ; ... to compensate for BIOS overhead - LD HL,HBIOS_JPTBL ; HBIOS jump table address - LD DE,COMX ; HBIOS console notification string - JR MINIT3 ; Complete the initialization -; -ARCINIT: - ; RC2014 running Z180 - LD HL,ARC_JPTBL ; ASCI RC2014 jump table address - LD DE,ASCIRC ; ASCI RC2014 console notification string - JR MINIT3 ; Complete the initialization -; -MINIT3: - PUSH HL ; Save HL - - ; Display port notification string - LD C,9 ; BDOS string display function - CALL BDOS ; Do it + JP Z,U_INIT ; UART initialization + JP A4_INIT ; ASCI @ $40 initialization ; - ; Newline +HWERR: + ; Failed to identify target comm hardware + LD DE,ERR_HW ; Hardware error message LD C,9 ; BDOS string display function - LD DE,CRLF ; Newline CALL BDOS ; Do it + JP 0 ; Bail out! ; - ; 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 -; -; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 +; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 ; IDBIO: ; @@ -238,28 +215,6 @@ IDBIO2: XOR A ; Setup return value of 0 RET ; and done ; -; -; -BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS -PLTID DB 0 ; Platform ID -CPUSPD DB 10 ; CPU speed in MHz -RCVSCL DW 2800 ; RECV loop timeout scalar -; -RBC DB "RBC, 11-Aug-2019$" -; -UART DB ", UART0$" -ASCI DB ", ASCI0$" -ASCIRC DB ", ASCI0 (RC2014)$" -SIO DB ", SIO$" -COMX DB ", COM0$" -; -UBTAG DB " [UNA]$" -HBTAG DB " [WBW]$" -; -CRLF DB 13, 10, "$" -; -BIOERR DB 13, 10, 13, 10, "++ Unknown BIOS ++", 13, 10, "$" -; ;----------------------------------------------------------------------- ; ; Uninitialize modem @@ -267,15 +222,27 @@ BIOERR DB 13, 10, 13, 10, "++ Unknown BIOS ++", 13, 10, "$" UNINIT: LD A,(BIOID) CP 1 ; Is HBIOS? - RET NZ ; If not, just return - - ; Reset character device 0 + 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 @@ -293,13 +260,33 @@ EXTRA2: EXTRA3: RET ; +BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS +PLTID DB 0 ; Platform ID +CPUSPD DB 10 ; CPU speed in MHz +RCVSCL DW 2800 ; RECV loop timeout scalar +; +RBC DB "RBC, 17-Aug-2019$" +; +U_LBL DB ", UART$" +A4_LBL DB ", ASCI @ 40H$" +AC_LBL DB ", ASCI @ C0H$" +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, "$" +; ;======================================================================= ;======================================================================= ; ; Standard RBC Projects 8250-like UART port @ 68H ; -; Will be used for all RBC Z80 systems. -; ;======================================================================= ;======================================================================= ; @@ -316,12 +303,13 @@ 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). ; -UART_JPTBL: +U_JPTBL: JP U_SENDR ; send character (via pop psw) JP U_CAROK ; test for carrier JP U_MDIN ; receive data byte @@ -332,6 +320,15 @@ UART_JPTBL: ; ;----------------------------------------------------------------------- ; +; UART initialization +; +U_INIT: + LD HL,U_JPTBL + LD DE,U_LBL + JP MINIT_RET +; +;----------------------------------------------------------------------- +; ; Send character on top of stack ; U_SENDR: @@ -370,7 +367,7 @@ U_RCVRDY: ; With error detection (slower) PUSH BC ; save scratch register PUSH AF ; save full status on stack - AND U_FRME | U_OVRE | U_PARE ; isolate line err bits + 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 @@ -410,19 +407,17 @@ U_SPEED: ;======================================================================= ;======================================================================= ; -; Standard RBC Projects Z180 primary ASCI port -; -; Will be used for all RBC Z180 systems. +; Standard RBC Projects Z180 primary ASCI port @ 40H ; ;======================================================================= ;======================================================================= ; ; ASCI port constants ; -A_DATP EQU 48H ;Z180 TSR - ASCI receive data port -A_DATO EQU 46H ;Z180 TDR - ASCI transmit data port -A_CTLP EQU 44H ;Z180 STAT - ASCI status port -A_CTL2 EQU 40H ;Z180 CNTLA - ASCI control port +A4_DATP EQU 48H ;Z180 TSR - ASCI receive data port +A4_DATO EQU 46H ;Z180 TDR - ASCI transmit data port +A4_CTLP EQU 44H ;Z180 STAT - ASCI status port +A4_CTL2 EQU 40H ;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 @@ -431,34 +426,47 @@ 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 ; ; 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). ; -ASCI_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 +A4_JPTBL: + JP A4_SENDR ; send character (via pop psw) + JP A4_CAROK ; test for carrier + JP A4_MDIN ; receive data byte + JP A4_GETCHR ; get character from modem + JP A4_RCVRDY ; check receive ready + JP A4_SNDRDY ; check send ready + JP A4_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; ASCI initialization +; +A4_INIT: + XOR A ; Clear interrupt enable flags + OUT0 (A4_CTLP),A ; Do it +; + LD HL,A4_JPTBL + LD DE,A4_LBL + JP MINIT_RET ; ;----------------------------------------------------------------------- ; ; Send character on top of stack ; -A_SENDR: +A4_SENDR: POP AF ; get character to send from stack - OUT0 (A_DATO),A ; send to port + OUT0 (A4_DATO),A ; send to port RET ; ;----------------------------------------------------------------------- ; ; Test and report carrier status, Z set if carrier present ; -A_CAROK: +A4_CAROK: XOR A ; not used, always indicate present RET ; @@ -466,9 +474,9 @@ A_CAROK: ; ; Get a character (assume character ready has already been tested) ; -A_MDIN: -A_GETCHR: - IN0 A,(A_DATP) ; read character from port +A4_MDIN: +A4_GETCHR: + IN0 A,(A4_DATP) ; read character from port RET ; ;----------------------------------------------------------------------- @@ -477,24 +485,24 @@ A_GETCHR: ; Error code returned in A register ; *** Error code does not seem to be used *** ; -A_RCVRDY: - IN0 A,(A_CTLP) ; get modem status +A4_RCVRDY: + IN0 A,(A4_CTLP) ; get modem status PUSH BC ; save scratch register PUSH AF ; save full status on stack - AND A_FRME | A_OVRE | A_PARE ; isolate line err bits + 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 + ; the status register. Below, bit 3 of ASCI + ; control register is written with a zero to ; clear error(s) if needed. - JP Z,A_RCVRDY2 ; if no errs, continue - IN0 A,(A_CTL2) ; get current control register + JP Z,A4_RCVRDY2 ; if no errs, continue + IN0 A,(A4_CTL2) ; get current control register AND 0F7H ; force err reset bit to zero - OUT0 (A_CTL2),A ; write control register + OUT0 (A4_CTL2),A ; write control register -A_RCVRDY2: +A4_RCVRDY2: POP AF ; get full status back AND A_RCVB ; isolate ready bit CP A_RCVR ; test it (set flags) @@ -506,8 +514,8 @@ A_RCVRDY2: ; ; Test for ready to send a character, Z = ready ; -A_SNDRDY: - IN A,(A_CTLP) ; get status +A4_SNDRDY: + IN A,(A4_CTLP) ; get status AND A_SNDB ; isolate transmit ready bit CP A_SNDR ; test for ready value RET @@ -516,7 +524,7 @@ A_SNDRDY: ; ; Report baud rate (index into SPTBL returned in register A) ; -A_SPEED: +A4_SPEED: LD A,8 ; arbitrarily return 9600 baud RET ; @@ -532,38 +540,50 @@ A_SPEED: ; ; ASCI port constants for RC2014 ; -AR_DATP EQU 0C8H ;Z180 TSR - ASCI receive data port -AR_DATO EQU 0C6H ;Z180 TDR - ASCI transmit data port -AR_CTLP EQU 0C4H ;Z180 STAT - ASCI status port -AR_CTL2 EQU 0C0H ;Z180 CNTLA - ASCI control port +AC_DATP EQU 0C8H ; Z180 TSR - ASCI receive data port +AC_DATO EQU 0C6H ; Z180 TDR - ASCI transmit data port +AC_CTLP EQU 0C4H ; Z180 STAT - ASCI status port +AC_CTL2 EQU 0C0H ; Z180 CNTLA - ASCI control port ; ; 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). ; -ARC_JPTBL: - JP AR_SENDR ;send character (via pop psw) - JP AR_CAROK ;test for carrier - JP AR_MDIN ;receive data byte - JP AR_GETCHR ;get character from modem - JP AR_RCVRDY ;check receive ready - JP AR_SNDRDY ;check send ready - JP AR_SPEED ;get speed value for file transfer time +AC_JPTBL: + JP AC_SENDR ; send character (via pop psw) + JP AC_CAROK ; test for carrier + JP AC_MDIN ; receive data byte + JP AC_GETCHR ; get character from modem + JP AC_RCVRDY ; check receive ready + JP AC_SNDRDY ; check send ready + JP AC_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; ASCI initialization +; +AC_INIT: + XOR A ; Clear interrupt enable flags + OUT0 (AC_CTLP),A ; Do it +; + LD HL,AC_JPTBL + LD DE,AC_LBL + JP MINIT_RET ; ;----------------------------------------------------------------------- ; ; Send character on top of stack ; -AR_SENDR: +AC_SENDR: POP AF ; get character to send from stack - OUT0 (AR_DATO),A ; send to port + OUT0 (AC_DATO),A ; send to port RET ; ;----------------------------------------------------------------------- ; ; Test and report carrier status, Z set if carrier present ; -AR_CAROK: +AC_CAROK: XOR A ; not used, always indicate present RET ; @@ -571,9 +591,9 @@ AR_CAROK: ; ; Get a character (assume character ready has already been tested) ; -AR_MDIN: -AR_GETCHR: - IN0 A,(AR_DATP) ; read character from port +AC_MDIN: +AC_GETCHR: + IN0 A,(AC_DATP) ; read character from port RET ; ;----------------------------------------------------------------------- @@ -582,24 +602,24 @@ AR_GETCHR: ; Error code returned in A register ; *** Error code does not seem to be used *** ; -AR_RCVRDY: - IN0 A,(AR_CTLP) ; get modem status +AC_RCVRDY: + IN0 A,(AC_CTLP) ; get modem status PUSH BC ; save scratch register PUSH AF ; save full status on stack - AND A_FRME | A_OVRE | A_PARE ; isolate line err bits + AND A_ERRS ; isolate line err bits LD B,A ; save err status in B - + ; Z8S180 Rev. N ASCI ports will stall if there are line 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 + ; the status register. Below, bit 3 of ASCI + ; control register is written with a zero to ; clear error(s) if needed. - JP Z,A_RCVRDY2 ; if no errs, continue - IN0 A,(AR_CTL2) ; get current control register + JP Z,AC_RCVRDY2 ; if no errs, continue + IN0 A,(AC_CTL2) ; get current control register AND 0F7H ; force err reset bit to zero - OUT0 (AR_CTL2),A ; write control register + OUT0 (AC_CTL2),A ; write control register -AR_RCVRDY2: +AC_RCVRDY2: POP AF ; get full status back AND A_RCVB ; isolate ready bit CP A_RCVR ; test it (set flags) @@ -611,8 +631,8 @@ AR_RCVRDY2: ; ; Test for ready to send a character, Z = ready ; -AR_SNDRDY: - IN A,(AR_CTLP) ; get status +AC_SNDRDY: + IN A,(AC_CTLP) ; get status AND A_SNDB ; isolate transmit ready bit CP A_SNDR ; test for ready value RET @@ -621,7 +641,7 @@ AR_SNDRDY: ; ; Report baud rate (index into SPTBL returned in register A) ; -AR_SPEED: +AC_SPEED: LD A,8 ; arbitrarily return 9600 baud RET ; @@ -633,6 +653,10 @@ AR_SPEED: ;======================================================================= ;======================================================================= ; +; Currently assumes the port address and ordering conventions of the +; official RC2014 SIO module. Will not work with others such as EZZ80 +; or ZP. +; ; SIO port constants ; S_BASE EQU 80H ; SIO base port @@ -648,7 +672,7 @@ S_RCVR EQU 01H ; value when ready to receive ; table at program startup. See MINIT above. Note that only a ; subset of the jump table is overlaid (SENDR to SPEED). ; -SIO_JPTBL: +S_JPTBL: JP S_SENDR ; send character (via pop psw) JP S_CAROK ; test for carrier JP S_MDIN ; receive data byte @@ -659,6 +683,21 @@ SIO_JPTBL: ; ;----------------------------------------------------------------------- ; +; SIO initialization +; +S_INIT: + ; 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: @@ -733,20 +772,32 @@ S_SPEED: ; table at program startup. See MINIT above. Note that only a ; subset of the jump table is overlaid (SENDR to SPEED). ; -HBIOS_JPTBL: - JP HB_SENDR ;send character (via pop psw) - JP HB_CAROK ;test for carrier - JP HB_MDIN ;receive data byte - JP HB_GETCHR ;get character from modem - JP HB_RCVRDY ;check receive ready - JP HB_SNDRDY ;check send ready - JP HB_SPEED ;get speed value for file transfer time +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 ; -HB_SENDR: +H_SENDR: POP AF ; get character to send from stack PUSH BC PUSH DE @@ -764,7 +815,7 @@ HB_SENDR: ; ; Test and report carrier status, Z set if carrier present ; -HB_CAROK: +H_CAROK: XOR A ; not used, always indicate present RET ; @@ -774,23 +825,23 @@ HB_CAROK: ; ; This routine must NOT block. ; -HB_MDIN: -HB_GETCHR: +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,HB_MDIN1 ; If char(s) waiting, go get it + JR NZ,H_MDIN1 ; If char(s) waiting, go get it XOR A ; otherwise, return null - JR HB_MDIN2 ; and done -HB_MDIN1: + 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 -HB_MDIN2: +H_MDIN2: POP HL POP DE POP BC @@ -802,7 +853,7 @@ HB_MDIN2: ; Error code returned in A register ; *** Error code does not seem to be used *** ; -HB_RCVRDY: +H_RCVRDY: PUSH BC PUSH DE PUSH HL @@ -822,7 +873,7 @@ HB_RCVRDY: ; ; Test for ready to send a character, Z = ready ; -HB_SNDRDY: +H_SNDRDY: PUSH BC PUSH DE PUSH HL @@ -841,8 +892,104 @@ HB_SNDRDY: ; ; Report baud rate (index into SPTBL returned in register A) ; -HB_SPEED: +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,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 diff --git a/Source/HBIOS/asci.asm b/Source/HBIOS/asci.asm index 13ea9528..788a705a 100644 --- a/Source/HBIOS/asci.asm +++ b/Source/HBIOS/asci.asm @@ -5,10 +5,10 @@ ; ; SETUP PARAMETER WORD: ; +-------+---+-------------------+ +---+---+-----------+---+-------+ -; | |RTS| ENCODED BAUD RATE | |DTR|XON| PARITY |STP| 8/7/6 | +; | |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) -- +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- ; ; STAT: ; 7 6 5 4 3 2 1 0 @@ -18,7 +18,7 @@ ; | | | | | | | +-- TIE: TRANSMIT INTERRUPT ENABLE ; | | | | | | +---- TDRE: TRANSMIT DATA REGISTER EMPTY ; | | | | | +------ DCD0/CTS1E: CH0 CARRIER DETECT, CH1 CTS ENABLE -; | | | | +-------- RIE: RECEIVE INTERRUPT ENABLE +; | | | | +-------- RIE: RECEIVE INTERRUPT ENABLE ; | | | +---------- FE: FRAMING ERROR ; | | +------------ PE: PARITY ERROR ; | +-------------- OVRN: OVERRUN ERROR @@ -33,7 +33,7 @@ ; | | | | | | +---- MOD1: PARITY: 0=NONE, 1=ENABLED ; | | | | | +------ MOD2: DATA BITS: 0=7 BITS, 1=8 BITS ; | | | | +-------- MPBR/EFR: MULTIPROCESSOR BIT RECEIVE / ERROR FLAG RESET -; | | | +---------- RTS0/CKA1D: CH0 RTS, CH1 CLOCK DISABLE +; | | | +---------- RTS0/CKA1D: CH0 ~RTS, CH1 CLOCK DISABLE ; | | +------------ TE: TRANSMITTER ENABLE ; | +-------------- RE: RECEIVER ENABLE ; +---------------- MPE: MULTI-PROCESSOR MODE ENABLE @@ -64,356 +64,536 @@ ; | +-------------- DCD0 DISABLE ; +---------------- RDRF INT INHIBIT ; +ASCI_BUFSZ .EQU 32 ; RECEIVE RING BUFFER SIZE +; +ASCI_NONE .EQU 0 ; NOT PRESENT +ASCI_ASCI .EQU 1 ; ORIGINAL ASCI (Z8S180 REV. K) +ASCI_ASCIB .EQU 2 ; REVISED ASCI W/ BRG & FIFO (Z8S180 REV. N) +; +ASCI0_BASE .EQU Z180_BASE ; RELATIVE TO Z180 INTERNAL IO PORTS +ASCI1_BASE .EQU Z180_BASE + 1 ; RELATIVE TO Z180 INTERNAL IO PORTS +; +ASCI_RTS .EQU %00010000 ; ~RTS BIT OF CNTLA REG +; +#IF (INTMODE == 2) +; +ASCI0_IVT .EQU IVT(INT_SER0) +ASCI1_IVT .EQU IVT(INT_SER1) +; +#ENDIF +; +; +; ASCI_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES +; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN +; DISABLED. +; + LD B,ASCI_CFGCNT ; LOOP CONTROL + XOR A ; ZERO TO ACCUM + LD (ASCI_DEV),A ; CURRENT DEVICE NUMBER + LD IY,ASCI_CFG ; POINT TO START OF CFG TABLE +ASCI_PREINIT0: + PUSH BC ; SAVE LOOP CONTROL + CALL ASCI_INITUNIT ; HAND OFF TO GENERIC INIT CODE + POP BC ; RESTORE LOOP CONTROL +; + LD A,(IY+1) ; GET THE ASCI TYPE DETECTED + OR A ; SET FLAGS + JR Z,ASCI_PREINIT2 ; SKIP IT IF NOTHING FOUND +; + PUSH BC ; SAVE LOOP CONTROL + PUSH IY ; CFG ENTRY ADDRESS + POP DE ; ... TO DE + LD BC,ASCI_FNTBL ; BC := FUNCTION TABLE ADDRESS + CALL NZ,CIO_ADDENT ; ADD ENTRY IF ASCI FOUND, BC:DE + POP BC ; RESTORE LOOP CONTROL +; +ASCI_PREINIT2: + LD DE,ASCI_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ ASCI_PREINIT0 ; LOOP UNTIL DONE +; +#IF (INTMODE >= 1) + ; SETUP INT VECTORS AS APPROPRIATE + LD A,(ASCI_DEV) ; GET DEVICE COUNT + OR A ; SET FLAGS + JR Z,ASCI_PREINIT3 ; IF ZERO, NO ASCI DEVICES, ABORT +; +#IF (INTMODE == 1) + ; ADD IM1 INT CALL LIST ENTRY + LD HL,ASCI_INT ; GET INT VECTOR + CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST +#ENDIF ; -; LD B,2 ; ALWAYS 2 ASCI UNITS ON Z180 -; LD C,0 ; PHYSICAL UNIT INDEX -;ASCI_PREINIT1: -; PUSH BC ; SAVE LOOP CONTROL -; LD D,C ; PHYSICAL UNIT -; LD E,CIODEV_ASCI ; DEVICE TYPE -; LD BC,ASCI_FNTBL ; BC := FUNCTION TABLE ADDRESS -; CALL CIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED -; POP BC ; RESTORE LOOP CONTROL -; INC C ; NEXT PHYSICAL UNIT -; DJNZ ASCI_PREINIT1 ; LOOP UNTIL DONE -; - ; ASCI0 CHANNEL - LD D,0 ; DEVICE ID - LD E,CIODEV_ASCI ; DEVICE TYPE - LD BC,ASCI0_FNTBL ; ASCI0 FUNCTION TABLE PTR - CALL CIO_ADDENT - LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG - CALL ASCI0_INITDEV ; INIT DEVICE -; - ; ASCI1 CHANNEL - LD D,1 ; DEVICE ID - LD E,CIODEV_ASCI ; DEVICE TYPE - LD BC,ASCI1_FNTBL ; ASCI1 FUNCTION TABLE PTR - CALL CIO_ADDENT - LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG - CALL ASCI1_INITDEV ; INIT DEVICE +#IF (INTMODE == 2) + ; SETUP IM2 VECTORS + LD HL,ASCI_INT0 + LD (ASCI0_IVT),HL ; IVT INDEX + LD HL,ASCI_INT1 + LD (ASCI1_IVT),HL ; IVT INDEX +#ENDIF +; +#ENDIF ; +ASCI_PREINIT3: XOR A ; SIGNAL SUCCESS - RET + RET ; AND RETURN ; +; ASCI INITIALIZATION ROUTINE ; +ASCI_INITUNIT: + CALL ASCI_DETECT ; DETERMINE ASCI TYPE + LD (IY+1),A ; SAVE IN CONFIG TABLE + OR A ; SET FLAGS + RET Z ; ABORT IF NOTHING THERE + + ; UPDATE WORKING ASCI DEVICE NUM + LD HL,ASCI_DEV ; POINT TO CURRENT UART DEVICE NUM + LD A,(HL) ; PUT IN ACCUM + INC (HL) ; INCREMENT IT (FOR NEXT LOOP) + LD (IY),A ; UPDATE UNIT NUM ; -ASCI_INIT: + ; IT IS EASY TO SPECIFY A SERIAL CONFIG THAT CANNOT BE IMPLEMENTED + ; DUE TO THE CONSTRAINTS OF THE ASCI. HERE WE FORCE A GENERIC + ; FAILSAFE CONFIG ONTO THE CHANNEL. IF THE SUBSEQUENT "REAL" + ; CONFIG FAILS, AT LEAST THE CHIP WILL BE ABLE TO SPIT DATA OUT + ; AT A RATIONAL BAUD/DATA/PARITY/STOP CONFIG. + CALL ASCI_INITSAFE ; - ; ASCI0 - CALL NEWLINE ; FORMATTING - PRTS("ASCI0: IO=0x$") ; PREFIX - LD A,Z180_TDR0 ; LOAD TDR PORT ADDRESS - CALL PRTHEXBYTE ; PRINT IT - - CALL PC_COMMA ; FORMATTING - LD A,Z180_RDR0 ; LOAD RDR PORT ADDRESS - CALL PRTHEXBYTE ; PRINT IT - - PRTS(" MODE=$") ; FORMATTING - LD DE,(ASCI0_CONFIG) ; LOAD CONFIG - CALL PS_PRTSC0 ; PRINT IT + ; SET DEFAULT CONFIG + LD DE,-1 ; LEAVE CONFIG ALONE + ; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL + ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! + JP ASCI_INITDEVX ; IMPLEMENT IT AND RETURN ; - ; ASCI1 - CALL NEWLINE ; FORMATTING - PRTS("ASCI1: IO=0x$") ; PREFIX - LD A,Z180_TDR1 ; LOAD TDR PORT ADDRESS - CALL PRTHEXBYTE ; PRINT IT - - CALL PC_COMMA ; FORMATTING - LD A,Z180_RDR1 ; LOAD RDR PORT ADDRESS - CALL PRTHEXBYTE ; PRINT IT - - PRTS(" MODE=$") ; FORMATTING - LD DE,(ASCI1_CONFIG) ; LOAD CONFIG - CALL PS_PRTSC0 ; PRINT IT ; - XOR A - RET ; -; DRIVER ASCI0 FUNCTION TABLE -; -ASCI0_FNTBL: - .DW ASCI0_IN - .DW ASCI0_OUT - .DW ASCI0_IST - .DW ASCI0_OST - .DW ASCI0_INITDEV - .DW ASCI0_QUERY - .DW ASCI0_DEVICE -#IF (($ - ASCI0_FNTBL) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID ASCI0 FUNCTION TABLE ***\n" -#ENDIF +ASCI_INIT: + LD B,ASCI_CFGCNT ; COUNT OF POSSIBLE ASCI UNITS + LD IY,ASCI_CFG ; POINT TO START OF CFG TABLE +ASCI_INIT1: + PUSH BC ; SAVE LOOP CONTROL + LD A,(IY+1) ; GET ASCI TYPE + OR A ; SET FLAGS + CALL NZ,ASCI_PRTCFG ; PRINT IF NOT ZERO + POP BC ; RESTORE LOOP CONTROL + LD DE,ASCI_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ ASCI_INIT1 ; LOOP TILL DONE ; -ASCI0_IN: - CALL ASCI0_IST - OR A - JR Z,ASCI0_IN - IN0 A,(Z180_RDR0) ; READ THE CHAR - LD E,A - RET + XOR A ; SIGNAL SUCCESS + RET ; DONE ; -ASCI0_IST: - ; CHECK FOR ERROR FLAGS - IN0 A,(Z180_STAT0) - AND 70H ; PARITY, FRAMING, OR OVERRUN ERROR - JR Z,ASCI0_IST1 ; ALL IS WELL, CHECK FOR DATA +; RECEIVE INTERRUPT HANDLER ; - ; CLEAR ERROR(S) OR NOTHING FURTHER CAN BE RECEIVED!!! - IN0 A,(Z180_CNTLA0) - RES 3,A ; CLEAR EFR (ERROR FLAG RESET) - OUT0 (Z180_CNTLA0),A +#IF (INTMODE > 0) ; -ASCI0_IST1: - ; CHECK FOR STAT0.RDRF (DATA READY) - IN0 A,(Z180_STAT0) ; READ LINE STATUS REGISTER - AND $80 ; TEST IF DATA IN RECEIVE BUFFER - JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN - XOR A - INC A ; SIGNAL CHAR READY, A = 1 - RET +; IM1 ENTRY POINT ; -ASCI0_OUT: - CALL ASCI0_OST - OR A - JR Z,ASCI0_OUT - LD A,E - OUT0 (Z180_TDR0),A - RET +ASCI_INT: + ; CHECK/HANDLE FIRST PORT + LD A,(ASCI0_CFG + 1) ; GET ASCI TYPE FOR FIRST ASCI + OR A ; SET FLAGS + CALL NZ,ASCI_INT0 ; CALL IF EXISTS + RET NZ ; DONE IF INT HANDLED ; -ASCI0_OST: - IN0 A,(Z180_STAT0) - AND $02 - JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN - XOR A - INC A ; SIGNAL BUFFER EMPTY, A = 1 - RET + ; CHECK/HANDLE SECOND PORT + LD A,(ASCI1_CFG + 1) ; GET ASCI TYPE FOR SECOND ASCI + OR A ; SET FLAGS + CALL NZ,ASCI_INT1 ; CALL IF EXISTS ; -ASCI0_INITDEV: - ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) - LD A,D ; TEST DE FOR - AND E ; ... VALUE OF -1 - INC A ; ... SO Z SET IF -1 - JR NZ,ASCI0_INITDEV1 ; IF NEW CONFIG (NOT -1), IMPLEMENT IT - LD DE,(ASCI0_CONFIG) ; OTHERWISE, LOAD EXISTING CONFIG + RET ; DONE ; -ASCI0_INITDEV1: - ; DETERMINE APPROPRIATE CNTLB VALUE (BASED ON BAUDRATE & CPU SPEED) - LD A,D ; BYTE W/ ENCODED BAUD RATE - AND $1F ; ISOLATE BITS - LD L,A ; MOVE TO L - LD H,0 ; CLEAR MSB - PUSH DE ; SAVE CONFIG - CALL ASCI_CNTLB ; DERIVE CNTLB VALUE IN C - POP DE ; RESTORE CONFIG - ;CALL TSTPT - RET NZ ; ABORT ON ERROR +; IM2 ENTRY POINTS +; +ASCI_INT0: + ; INTERRUPT HANDLER FOR FIRST ASCI (ASCI0) + LD IY,ASCI0_CFG ; POINT TO ASCI0 CFG + JR ASCI_INTRCV +; +ASCI_INT1: + ; INTERRUPT HANDLER FOR SECOND ASCI (ASCI1) + LD IY,ASCI1_CFG ; POINT TO ASCI1 CFG + JR ASCI_INTRCV +; +; HANDLE INT FOR A SPECIFIC CHANNEL +; BASED ON UNIT CFG POINTED TO BY IY +; +ASCI_INTRCV: + ; CHECK TO SEE IF SOMETHING IS ACTUALLY THERE + CALL ASCI_ICHK ; CHECK FOR CHAR PENDING + RET Z ; RETURN IF NOTHING AVAILABLE +; +ASCI_INTRCV1: + ; RECEIVE CHARACTER INTO BUFFER + LD A,(IY+3) ; BASE PORT TO A + ADD A,8 ; BUMP TO RDR PORT + LD C,A ; PUT IN C, B IS STILL ZERO + 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 ASCI_BUFSZ ; COMPARE TO BUFFER SIZE + JR Z,ASCI_INTRCV4 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED + INC A ; INCREMENT THE COUNT + LD (HL),A ; AND SAVE IT + CP ASCI_BUFSZ / 2 ; BUFFER GETTING FULL? + JR NZ,ASCI_INTRCV2 ; IF NOT, BYPASS CLEARING RTS + ; CLEAR RTS + ; THE SECONDARY ASCI PORT ON Z180 ACTUALLY HAS NO RTS LINE + ; AND THE CNTLA BIT FOR THIS PORT CONTROLS THE FUNCTION OF THE + ; MULTIPLEXED CKA1/~TEND0 LINE. BELOW, WE TEST REG C TO SEE IF + ; IT IS AN ODD NUMBERED PORT. IF SO, WE MUST BE ON THE SECONDARY + ; SERIAL PORT, SO WE NEED TO BYPASS MANIPULATING THE RTS BIT. + BIT 0,C ; IS C ADDRESSING AN ODD NUMBERED PORT? + JR NZ,ASCI_INTRCV2 ; IF SO, THIS IS SEC SERIAL, NO RTS! + PUSH BC ; PRESERVE READ CHAR + LD C,(IY+3) ; CNTLA PORT ADR + LD B,0 ; MSB FOR 16 BIT I/O + IN A,(C) ; GET CUR CNTLA VAL + OR ASCI_RTS ; DEASSERT ~RTS + OUT (C),A ; DO IT + POP BC ; RESTORE READ CHAR +ASCI_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 ASCI_BUFSZ+4 ; SUBTRACT SIZE OF BUFFER AND POINTER + CP E ; IF EQUAL TO START, HEAD PTR IS PAST BUF END + JR NZ,ASCI_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 +ASCI_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... + CALL ASCI_ICHK ; CHECK FOR CHAR PENDING + JR NZ,ASCI_INTRCV1 ; IF SO, LOOP TO HANDLE +ASCI_INTRCV4: + OR $FF ; NZ SET TO INDICATE INT HANDLED + RET ; AND RETURN ; - LD B,$64 ; B := DEFAULT CNTLB VALUE - - ; DATA BITS - LD A,E ; LOAD CONFIG BYTE - AND $03 ; ISOLATE DATA BITS - CP $03 ; 8 DATA BITS? - JR Z,ASCI0_INITDEV2 ; IF SO, NO CHG, CONTINUE - RES 2,B ; RESET CNTLA BIT 2 FOR 7 DATA BITS - -ASCI0_INITDEV2: - ; STOP BITS - BIT 2,E ; TEST STOP BITS CONFIG BIT - JR Z,ASCI0_INITDEV3 ; IF CLEAR, NO CHG, CONTINUE - SET 0,B ; SET CNTLA BIT 0 FOR 2 STOP BITS - -ASCI0_INITDEV3: - ; PARITY ENABLE - BIT 3,E ; TEST PARITY ENABLE CONFIG BIT - JR Z,ASCI0_INITDEV4 ; NO PARITY, SKIP ALL PARITY CHGS - SET 1,B ; SET CNTLA BIT 1 FOR PARITY ENABLE - - ; PARITY EVEN/ODD - BIT 4,E ; TEST EVEN PARITY CONFIG BIT - JR NZ,ASCI0_INITDEV4 ; EVEN PARITY, NO CHG, CONTINUE - SET 4,C ; SET CNTLB BIT 4 FOR ODD PARITY - -ASCI0_INITDEV4: - ; IMPLEMENT CONFIGURATION - LD A,$66 ; LOAD DEFAULT ASEXT VALUE - OUT0 (Z180_ASEXT0),A ; SET IT - LD A,B ; FINAL CNTLA VALUE TO ACCUM - OUT0 (Z180_CNTLA0),A ; WRITE TO CNTLA REGISTER - LD A,C ; FINAL CNTLB VALUE TO ACCUM - OUT0 (Z180_CNTLB0),A ; WRITE TO CNTLA REGISTER -; - LD (ASCI0_CONFIG),DE ; RECORD UPDATED CONFIG +#ENDIF +; +; DRIVER FUNCTION TABLE +; +ASCI_FNTBL: + .DW ASCI_IN + .DW ASCI_OUT + .DW ASCI_IST + .DW ASCI_OST + .DW ASCI_INITDEV + .DW ASCI_QUERY + .DW ASCI_DEVICE +#IF (($ - ASCI_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID ASCI FUNCTION TABLE ***\n" +#ENDIF +; +#IF (INTMODE == 0) +; +ASCI_IN: + CALL ASCI_IST ; CHECK FOR CHAR READY + JR Z,ASCI_IN ; IF NOT, LOOP + LD A,(IY+3) ; BASE REG + ADD A,8 ; Z180 RDR REG OFFSET + LD C,A ; PUT IN C FOR I/O + LD B,0 ; MSB FOR 16 BIT I/O + IN E,(C) ; GET CHAR XOR A ; SIGNAL SUCCESS RET ; DONE ; -ASCI0_QUERY: - LD DE,(ASCI0_CONFIG) - XOR A - RET +#ELSE +; +ASCI_IN: + CALL ASCI_IST ; SEE IF CHAR AVAILABLE + JR Z,ASCI_IN ; LOOP UNTIL SO + 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 + CP ASCI_BUFSZ / 4 ; BUFFER LOW THRESHOLD + JR NZ,ASCI_IN1 ; IF NOT, BYPASS SETTING RTS + ; SET RTS + ; THE SECONDARY ASCI PORT ON Z180 ACTUALLY HAS NO RTS LINE + ; AND THE CNTLA BIT FOR THIS PORT CONTROLS THE FUNCTION OF THE + ; MULTIPLEXED CKA1/~TEND0 LINE. BELOW, WE TEST REG C TO SEE IF + ; IT IS AN ODD NUMBERED PORT. IF SO, WE MUST BE ON THE SECONDARY + ; SERIAL PORT, SO WE NEED TO BYPASS MANIPULATING THE RTS BIT. + LD C,(IY+3) ; CNTLA PORT ADR + BIT 0,C ; IS C ADDRESSING AN ODD NUMBERED PORT? + JR NZ,ASCI_IN1 ; IF SO, THIS IS SEC SERIAL, NO RTS! + LD B,0 ; MSB FOR 16 BIT I/O + IN A,(C) ; GET CUR CNTLA VAL + AND ~ASCI_RTS ; ASSERT ~RTS + OUT (C),A ; DO IT +ASCI_IN1: + INC HL ; HL := ADR OF TAIL PTR + INC HL ; " + INC HL ; " + 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 ASCI_BUFSZ+2 ; SUBTRACT SIZE OF BUFFER AND POINTER + CP E ; IF EQUAL TO START, TAIL PTR IS PAST BUF END + JR NZ,ASCI_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 +ASCI_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 + XOR A ; SIGNAL SUCCESS + RET ; AND DONE ; -ASCI0_DEVICE: - LD D,CIODEV_ASCI ; D := DEVICE TYPE - LD E,0 ; E := PHYSICAL UNIT - LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232 +#ENDIF +; +; +; +ASCI_OUT: + CALL ASCI_OST ; CHECK IF OUTPUT REGISTER READY + JR Z,ASCI_OUT ; LOOP UNTIL SO + LD A,(IY+3) ; GET ASCI BASE REG + ADD A,6 ; Z180 TDR REG OFFSET + LD C,A ; PUT IN C FOR I/O + LD B,0 ; MSB FOR 16 BIT I/O + OUT (C),E ; WRITE CHAR XOR A ; SIGNAL SUCCESS - RET + RET ; DONE +; +; +; +#IF (INTMODE == 0) +; +ASCI_IST: + CALL ASCI_ICHK ; ASCI INPUT CHECK + JP Z,CIO_IDLE ; IF NOT READY, RETURN VIA IDLE PROCESSING + RET ; NORMAL RETURN +; +#ELSE +; +ASCI_IST: + 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 ; DONE ; -; DRIVER ASCI1 FUNCTION TABLE -; -ASCI1_FNTBL: - .DW ASCI1_IN - .DW ASCI1_OUT - .DW ASCI1_IST - .DW ASCI1_OST - .DW ASCI1_INITDEV - .DW ASCI1_QUERY - .DW ASCI1_DEVICE -#IF (($ - ASCI1_FNTBL) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID ASCI1 FUNCTION TABLE ***\n" #ENDIF -ASCI1: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JR Z,ASCI1_IN - DEC A - JR Z,ASCI1_OUT - DEC A - JR Z,ASCI1_IST - DEC A - JR Z,ASCI1_OST - DEC A - JP Z,ASCI1_INITDEV - DEC A - JP Z,ASCI1_QUERY - DEC A - JP Z,ASCI1_DEVICE - CALL PANIC -; -ASCI1_IN: - CALL ASCI1_IST - OR A - JR Z,ASCI1_IN - IN0 A,(Z180_RDR1) ; READ THE CHAR - LD E,A - RET ; -ASCI1_IST: - ; CHECK FOR ERROR FLAGS - IN0 A,(Z180_STAT1) - AND 70H ; PARITY, FRAMING, OR OVERRUN ERROR - JR Z,ASCI1_IST1 ; ALL IS WELL, CHECK FOR DATA ; - ; CLEAR ERROR(S) OR NOTHING FURTHER CAN BE RECEIVED!!! - IN0 A,(Z180_CNTLA1) - RES 3,A ; CLEAR EFR (ERROR FLAG RESET) - OUT0 (Z180_CNTLA1),A ; -ASCI1_IST1: ; CHECK FOR STAT0.RDRF (DATA READY) - IN0 A,(Z180_STAT1) ; READ LINE STATUS REGISTER - AND $80 ; TEST IF DATA IN RECEIVE BUFFER - JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN - XOR A - INC A ; SIGNAL CHAR READY, A = 1 - RET +ASCI_OST: + LD A,(IY+3) ; GET ASCI BASE REG + ADD A,4 ; Z180 STAT REG OFFSET + LD C,A ; PUT IN C FOR I/O + LD B,0 ; MSB FOR 16 BIT I/O + IN A,(C) ; READ STATUS + AND $02 ; CHECK BIT FOR OUTPUT READY + JP Z,CIO_IDLE ; IF NOT, DO IDLE PROCESSING AND RETURN + XOR A ; OTHERWISE SIGNAL + INC A ; ... BUFFER EMPTY, A = 1 + RET ; DONE ; -ASCI1_OUT: - CALL ASCI1_OST - OR A - JR Z,ASCI1_OUT - LD A,E - OUT0 (Z180_TDR1),A - RET +; AT INITIALIZATION THE SETUP PARAMETER WORD IS TRANSLATED TO THE FORMAT +; REQUIRED BY THE ASCI AND STORED IN A PORT/REGISTER INITIALIZATION TABLE, +; WHICH IS THEN LOADED INTO THE ASCI. ; -ASCI1_OST: - IN0 A,(Z180_STAT1) - AND $02 - JR Z,ASCI1_OST - JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN - XOR A - INC A ; SIGNAL BUFFER EMPTY, A = 1 - RET +; 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. +; +ASCI_INITDEV: + HB_DI ; DISABLE INTS + CALL ASCI_INITDEVX ; DO THE WORK + HB_EI ; INTS BACK ON + RET ; DONE +; +ASCI_INITDEVX: +; +; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY +; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! ; -ASCI1_INITDEV: ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR AND E ; ... VALUE OF -1 INC A ; ... SO Z SET IF -1 - JR NZ,ASCI1_INITDEV1 ; IF NEW CONFIG (NOT -1), IMPLEMENT IT - LD DE,(ASCI1_CONFIG) ; OTHERWISE, LOAD EXISTING CONFIG -; -ASCI1_INITDEV1: + JR NZ,ASCI_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG +; + ; LOAD EXISTING CONFIG TO REINIT + LD E,(IY+4) ; LOW BYTE + LD D,(IY+5) ; HIGH BYTE +; +ASCI_INITDEV1: +; + LD A,E ; GET CONFIG LSB + AND $E0 ; CHECK FOR DTR, XON, PARITY=MARK/SPACE + JR NZ,ASCI_INITFAIL ; IF ANY BIT SET, FAIL, NOT SUPPORTED +; ; DETERMINE APPROPRIATE CNTLB VALUE (BASED ON BAUDRATE & CPU SPEED) LD A,D ; BYTE W/ ENCODED BAUD RATE AND $1F ; ISOLATE BITS LD L,A ; MOVE TO L LD H,0 ; CLEAR MSB PUSH DE ; SAVE CONFIG - CALL ASCI_CNTLB ; DERIVE CNTLB VALUE + CALL ASCI_CNTLB ; DERIVE CNTLB VALUE TO C POP DE ; RESTORE CONFIG - ;CALL TSTPT - RET NZ ; ABORT ON ERROR + JR NZ,ASCI_INITFAIL ; ABORT ON ERROR +; + ; BUILD CNTLA VALUE IN REGISTER B + LD B,$64 ; START WITH DEFAULT CNTLA VALUE ; - LD B,$64 ; B := DEFAULT CNTLB VALUE - ; DATA BITS LD A,E ; LOAD CONFIG BYTE AND $03 ; ISOLATE DATA BITS CP $03 ; 8 DATA BITS? - JR Z,ASCI1_INITDEV2 ; IF SO, NO CHG, CONTINUE + JR Z,ASCI_INITDEV2 ; IF SO, NO CHG, CONTINUE RES 2,B ; RESET CNTLA BIT 2 FOR 7 DATA BITS - -ASCI1_INITDEV2: +; +ASCI_INITDEV2: ; STOP BITS BIT 2,E ; TEST STOP BITS CONFIG BIT - JR Z,ASCI1_INITDEV3 ; IF CLEAR, NO CHG, CONTINUE + JR Z,ASCI_INITDEV3 ; IF CLEAR, NO CHG, CONTINUE SET 0,B ; SET CNTLA BIT 0 FOR 2 STOP BITS - -ASCI1_INITDEV3: +; +ASCI_INITDEV3: ; PARITY ENABLE BIT 3,E ; TEST PARITY ENABLE CONFIG BIT - JR Z,ASCI1_INITDEV4 ; NO PARITY, SKIP ALL PARITY CHGS + JR Z,ASCI_INITDEV4 ; NO PARITY, SKIP ALL PARITY CHGS SET 1,B ; SET CNTLA BIT 1 FOR PARITY ENABLE ; PARITY EVEN/ODD BIT 4,E ; TEST EVEN PARITY CONFIG BIT - JR NZ,ASCI1_INITDEV4 ; EVEN PARITY, NO CHG, CONTINUE + JR NZ,ASCI_INITDEV4 ; EVEN PARITY, NO CHG, CONTINUE SET 4,C ; SET CNTLB BIT 4 FOR ODD PARITY - -ASCI1_INITDEV4: +; +ASCI_INITDEV4: + ; SAVE CONFIG PERMANENTLY NOW + LD (IY+4),E ; SAVE LOW WORD + LD (IY+5),D ; SAVE HI WORD + JR ASCI_INITGO +; +ASCI_INITSAFE: + LD B,$64 ; CNTLA FAILSAFE VALUE + LD C,$20 ; CNTLB FAILSAFE VALUE +; +ASCI_INITGO: ; IMPLEMENT CONFIGURATION - LD A,$66 ; LOAD DEFAULT ASEXT VALUE - OUT0 (Z180_ASEXT1),A ; SET IT - LD A,B ; FINAL CNTLA VALUE TO ACCUM - OUT0 (Z180_CNTLA1),A ; WRITE TO CNTLA REGISTER - LD A,C ; FINAL CNTLB VALUE TO ACCUM - OUT0 (Z180_CNTLB1),A ; WRITE TO CNTLA REGISTER -; - LD (ASCI1_CONFIG),DE ; RECORD UPDATED CONFIG + LD H,B ; H := CNTLA VAL + LD L,C ; L := CNTLB VAL + LD B,0 ; MSB OF PORT MUST BE ZERO! + LD C,(IY+3) ; GET ASCI BASE REG (CNTLA) + OUT (C),H ; WRITE CNTLA VALUE + INC C ; BUMP TO + INC C ; ... CNTLB REG, B IS STILL 0 + OUT (C),L ; WRITE CNTLB VALUE + INC C ; BUMP TO + INC C ; ... STAT REG, B IS STILL 0 +#IF (INTMODE > 0) + LD A,$08 ; SET RIE BIT ON + OUT (C),A ; WRITE STAT REG +#ENDIF + LD A,$0E ; BUMP TO + ADD A,C ; ... ASEXT REG + LD C,A ; PUT IN C FOR I/O, B IS STILL 0 + LD A,$66 ; STATIC VALUE FOR ASEXT + OUT (C),A ; WRITE ASEXT REG +; +#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 ; DONE ; -ASCI1_QUERY: - LD DE,(ASCI1_CONFIG) - XOR A - RET +ASCI_INITFAIL: + OR $FF ; SIGNAL FAILURE + RET ; RETURN +; +; +; +ASCI_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 ; -ASCI1_DEVICE: +; +; +ASCI_DEVICE: LD D,CIODEV_ASCI ; D := DEVICE TYPE - LD E,1 ; E := PHYSICAL UNIT + LD E,(IY) ; E := PHYSICAL UNIT + LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232 XOR A ; SIGNAL SUCCESS RET ; -; LOCAL DATA -; -ASCI0_CONFIG .DW DEFSERCFG ; SAVED CONFIG FOR ASCI0 -ASCI1_CONFIG .DW DEFSERCFG ; SAVED CONFIG FOR ASCI1 +; ASCI DETECTION ROUTINE +; ALWAYS PRESENT, JUST SAY SO. +; +ASCI_DETECT: + LD A,(IY+3) ; BASE PORT ADR + ADD A,$1A ; BUMP TO ASCI CONSTANT LOW + LD C,A ; PUT IN C + LD B,0 ; MSB FOR 16 BIT I/O + XOR A ; ZERO TO ACCUM + OUT (C),A ; WRITE TO REG + IN A,(C) ; READ IT BACK + INC A ; FF -> 0 + LD A,ASCI_ASCI ; ASSUME ORIG ASCI, NO BRG + RET Z ; IF SO, RETURN + LD A,ASCI_ASCIB ; MUST BE NEWER ASCI W/ BRG + RET ; DONE ; -; DERIVE A CNTLB VALUE BASED ON AN ENCODED BAUD RATE AND CURRENT CPU SPEED +; DERIVE CNTLB VALUE BASED ON AN ENCODED BAUD RATE AND CURRENT CPU SPEED ; ENTRY: HL = ENCODED BAUD RATE ; EXIT: C = CNTLB VALUE, A=0/Z IFF SUCCESS ; @@ -421,24 +601,21 @@ ASCI1_CONFIG .DW DEFSERCFG ; SAVED CONFIG FOR ASCI1 ; DUE TO ENCODING BAUD IS ALWAYS DIVISIBLE BY 75 ; Z180 DIVISOR IS ALWAYS A FACTOR OF 160 ; -; X = CPU_HZ / 160 / 75 ==> SIMPLIFIED ==> X = CPU_KHZ / 12 -; X = X / (BAUD / 75) -; IF X % 3 == 0, THEN (PS=1, X := X / 3) ELSE PS=0 -; IF X % 4 == 0, THEN (DR=1, X := X / 4) ELSE DR=0 +; X := CPU_HZ / 160 / 75 ==> SIMPLIFIED ==> X := CPU_KHZ / 12 +; X := X / (BAUD / 75) +; IF X % 3 == 0, THEN (PS := 1, X := X / 3) ELSE PS=0 +; IF X % 4 == 0, THEN (DR := 1, X := X / 4) ELSE DR=0 ; SS := LOG2(X) ; ASCI_CNTLB: LD DE,1 ; USE DECODE CONSTANT OF 1 TO GET BAUD RATE ALREADY DIVIDED BY 75 CALL DECODE ; DECODE THE BAUDATE INTO DE:HL, DE IS DISCARDED - ;CALL TSTPT RET NZ ; ABORT ON ERROR PUSH HL ; HL HAS (BAUD / 75), SAVE IT LD HL,(CB_CPUKHZ) ; GET CPU CLK IN KHZ - ;LD HL,CPUKHZ ; CPU CLK IN KHZ - ;LD HL,9216 ; *DEBUG* - +; ; DUE TO THE LIMITED DIVISORS POSSIBLE WITH CNTLB, YOU PRETTY MUCH - ; NEED TO USE A CPU SPEED THAT IS A MULTIPLE OF 128KHZ. BELOW, WE + ; NEED TO USE A CPU SPEED THAT IS A MULTIPLE OF 128KHZ. BELOW, WE ; ATTEMPT TO ROUND THE CPU SPEED DETECTED TO A MULTIPLE OF 128KHZ ; WITH ROUNDING. THIS JUST MAXIMIZES POSSIBILITY OF SUCCESS COMPUTING ; THE DIVISOR. @@ -447,25 +624,22 @@ ASCI_CNTLB: LD A,L ; MOVE TO ACCUM AND $80 ; STRIP LOW ORDER 7 BITS LD L,A ; ... AND PUT IT BACK - +; LD DE,12 ; PREPARE TO DIVIDE BY 12 CALL DIV16 ; BC := (CPU_KHZ / 12), REM IN HL, ZF - ;CALL TSTPT POP DE ; RESTORE (BAUD / 75) RET NZ ; ABORT IF REMAINDER PUSH BC ; MOVE WORKING VALUE POP HL ; ... BACK TO HL CALL DIV16 ; BC := X / (BAUD / 75) - ;CALL TSTPT RET NZ ; ABORT IF REMAINDER -; +; ; DETERMINE PS BIT BY ATTEMPTING DIVIDE BY 3 PUSH BC ; SAVE WORKING VALUE ON STACK PUSH BC ; MOVE WORKING VALUE POP HL ; ... TO HL LD DE,3 ; SETUP TO DIVIDE BY 3 CALL DIV16 ; BC := X / 3, REM IN HL, ZF - ;CALL TSTPT POP HL ; HL := PRIOR WORKING VALUE LD E,0 ; INIT E := 0 AS WORKING CNTLB VALUE JR NZ,ASCI_CNTLB1 ; DID NOT WORK, LEAVE PS==0, SKIP AHEAD @@ -474,7 +648,6 @@ ASCI_CNTLB: POP HL ; ... VALUE TO HL ; ASCI_CNTLB1: - ;CALL TSTPT ; DETERMINE DR BIT BY ATTEMPTING DIVIDE BY 4 LD A,L ; LOAD LSB OF WORKING VALUE AND $03 ; ISOLATE LOW ORDER BITS @@ -486,7 +659,6 @@ ASCI_CNTLB1: RR L ; ... ; ASCI_CNTLB2: - ;CALL TSTPT ; DETERMINE SS BITS BY RIGHT SHIFTING AND INCREMENTING LD B,7 ; LOOP COUNTER, MAX VALUE OF SS IS 7 LD C,E ; MOVE WORKING CNTLB VALUE TO C @@ -505,7 +677,139 @@ ASCI_CNTLB3: RET NZ ; ABORT IF NOT ZERO ; ASCI_CNTLB4: - ;CALL TSTPT + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; SPECIAL INPUT STATUS CHECK ROUTINE FOR ASCI. IF THE ASCI PORT DETECTS A LINE +; ERROR (PARITY, OVERRUN, ETC.) IT WILL STALL UNTIL THE ERROR IS EXPLICITY +; ACKNOWLEDGED. THIS ROUTINE HANDLES ALL OF THAT AND RETURNS WITH A=1 IF CHAR +; READY, ELSE A=0. ZF SET OR CLEARED. +; +ASCI_ICHK: + LD A,(IY+3) ; GET ASCI BASE REG + ADD A,4 ; Z180 STAT REG OFFSET + LD C,A ; PUT IN C FOR I/O + LD B,0 ; MSB FOR 16 BIT I/O + IN A,(C) ; READ STAT REG + PUSH AF ; SAVE STATUS + AND $70 ; PARITY, FRAMING, OR OVERRUN ERROR? + JR Z,ASCI_ICHK1 ; JUMP AHEAD IF NO ERRORS +; + ; CLEAR ERROR(S) OR NOTHING FURTHER CAN BE RECEIVED!!! + LD C,(IY+3) ; GET ASCI BASE REG (CNTLA) + LD B,0 ; MSB FOR 16 BIT I/O + IN A,(C) ; READ CNTLA + RES 3,A ; CLEAR EFR (ERROR FLAG RESET) + OUT (C),A ; WRITE UPDATED CNTLA +; +ASCI_ICHK1: + POP AF ; RESTORE STATUS VALUE + AND $80 ; DATA READY? + JP Z,CIO_IDLE ; IF NOT, DO IDLE PROCESSING AND RETURN + XOR A ; SIGNAL CHAR WAITING + INC A ; ... BY SETTING A TO 1 + RET ; DONE +; +; +; +ASCI_PRTCFG: + ; ANNOUNCE PORT + CALL NEWLINE ; FORMATTING + PRTS("ASCI$") ; 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 ASCI TYPE + CALL PC_SPACE ; FORMATTING + LD A,(IY+1) ; GET ASCI TYPE BYTE + RLCA ; MAKE IT A WORD OFFSET + LD HL,ASCI_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 ASCI WAS DETECTED + LD A,(IY+1) ; GET ASCI 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 ; +; +; +ASCI_TYPE_MAP: + .DW ASCI_STR_NONE + .DW ASCI_STR_ASCI + .DW ASCI_STR_ASCIB + +ASCI_STR_NONE .DB "$" +ASCI_STR_ASCI .DB "ASCI$" +ASCI_STR_ASCIB .DB "ASCI W/BRG$" +; +; WORKING VARIABLES +; +ASCI_DEV .DB 0 ; DEVICE NUM USED DURING INIT +; +#IF (INTMODE == 0) +; +ASCI0_RCVBUF .EQU 0 +ASCI1_RCVBUF .EQU 0 +; +#ELSE +; +; RECEIVE BUFFERS +; +ASCI0_RCVBUF: +ASCI0_BUFCNT .DB 0 ; CHARACTERS IN RING BUFFER +ASCI0_HD .DW ASCI0_BUF ; BUFFER HEAD POINTER +ASCI0_TL .DW ASCI0_BUF ; BUFFER TAIL POINTER +ASCI0_BUF .FILL 32,0 ; RECEIVE RING BUFFER +ASCI0_BUFEND .EQU $ ; END OF BUFFER +ASCI0_BUFSZ .EQU $ - ASCI0_BUF ; SIZE OF RING BUFFER +; +ASCI1_RCVBUF: +ASCI1_BUFCNT .DB 0 ; CHARACTERS IN RING BUFFER +ASCI1_HD .DW ASCI1_BUF ; BUFFER HEAD POINTER +ASCI1_TL .DW ASCI1_BUF ; BUFFER TAIL POINTER +ASCI1_BUF .FILL 32,0 ; RECEIVE RING BUFFER +ASCI1_BUFEND .EQU $ ; END OF BUFFER +ASCI1_BUFSZ .EQU $ - ASCI1_BUF ; SIZE OF RING BUFFER +; +#ENDIF +; +; ASCI PORT TABLE +; +ASCI_CFG: +; +ASCI0_CFG: + ; ASCI MODULE A CONFIG + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; ASCI TYPE (SET DURING INIT) + .DB 0 ; MODULE ID + .DB ASCI0_BASE ; BASE PORT + .DW ASCI0CFG ; LINE CONFIGURATION + .DW ASCI0_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +ASCI_CFGSIZ .EQU $ - ASCI_CFG ; SIZE OF ONE CFG TABLE ENTRY +; +ASCI1_CFG: + ; ASCI MODULE B CONFIG + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; ASCI TYPE (SET DURING INIT) + .DB 1 ; MODULE ID + .DB ASCI1_BASE ; BASE PORT + .DW ASCI1CFG ; LINE CONFIGURATION + .DW ASCI1_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +ASCI_CFGCNT .EQU ($ - ASCI_CFG) / ASCI_CFGSIZ diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index ed5dec9e..1b30e678 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -85,6 +85,8 @@ UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART ; ASCIENABLE .EQU FALSE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM) +ASCI0CFG .EQU DEFSERCFG ; ASCI 0: SERIAL LINE CONFIG +ASCI1CFG .EQU DEFSERCFG ; ASCI 1: SERIAL LINE CONFIG ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ACIADEBUG .EQU FALSE ; ACIA: ENABLE DEBUG OUTPUT diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index de970391..b371a112 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -71,6 +71,8 @@ UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART ; ASCIENABLE .EQU TRUE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM) +ASCI0CFG .EQU DEFSERCFG ; ASCI 0: SERIAL LINE CONFIG +ASCI1CFG .EQU DEFSERCFG ; ASCI 1: SERIAL LINE CONFIG ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ; diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index cc9778fd..86fab36f 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -74,6 +74,8 @@ UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART ; ASCIENABLE .EQU TRUE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM) +ASCI0CFG .EQU DEFSERCFG ; ASCI 0: SERIAL LINE CONFIG +ASCI1CFG .EQU DEFSERCFG ; ASCI 1: SERIAL LINE CONFIG ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ; diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index 5987a61b..3eb86317 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -62,6 +62,8 @@ DSRTCCHG .EQU FALSE ; DSRTC: FORCE BATTERY CHARGE ON (USE WITH CAUTION!!!) UARTENABLE .EQU FALSE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM) ; ASCIENABLE .EQU TRUE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM) +ASCI0CFG .EQU DEFSERCFG ; ASCI 0: SERIAL LINE CONFIG +ASCI1CFG .EQU DEFSERCFG ; ASCI 1: SERIAL LINE CONFIG ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ; diff --git a/Source/HBIOS/cfg_sc126.asm b/Source/HBIOS/cfg_sc126.asm index 10624ad6..d897fcda 100644 --- a/Source/HBIOS/cfg_sc126.asm +++ b/Source/HBIOS/cfg_sc126.asm @@ -57,6 +57,8 @@ DSRTCCHG .EQU FALSE ; DSRTC: FORCE BATTERY CHARGE ON (USE WITH CAUTION!!!) UARTENABLE .EQU FALSE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM) ; ASCIENABLE .EQU TRUE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM) +ASCI0CFG .EQU DEFSERCFG ; ASCI 0: SERIAL LINE CONFIG +ASCI1CFG .EQU DEFSERCFG ; ASCI 1: SERIAL LINE CONFIG ; ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) ; diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index d3dad664..8ce3088b 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -969,7 +969,7 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; THIS CODE IS DERIVED FROM UNA BY JOHN COFFMAN ; ; 0: Z80 -; 1: Z80180 - ORIGINAL Z180 IDENTICAL TO HD64180 +; 1: Z80180 - ORIGINAL Z180 (EQUIVALENT TO HD64180) ; 2: Z8S180 - ORIGINAL S-CLASS, REV. K, AKA SL1960, NO ASCI BRG ; 3: Z8S180 - REVISED S-CLASS, REV. N, W/ ASCI BRG ; @@ -992,8 +992,10 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK INC L ; FLAG Z8S180 REV K (SL1960) OR BETTER ; ; TEST FOR NEWER S-CLASS (REV N) + ; ON OLDER S-CLASS, ASCI TIME CONSTANT REG DOES NOT EXIST + ; AND WILL ALWYAS READ BACK AS $FF OUT0 (Z180_ASTC1L),D ; D = 0 AT THIS POINT - IN0 A,(Z180_ASTC1L) ; COUNTER REG + IN0 A,(Z180_ASTC1L) ; ASCI TIME CONSTANT REG INC A ; FF -> 0 JR Z,HB_CPU1 INC L ; FLAG Z8S180 REV N W/ ASCI BRG diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index 50e06531..6eeeae25 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -92,8 +92,9 @@ CIODEV_PRPCON .EQU $30 CIODEV_PPPCON .EQU $40 CIODEV_SIO .EQU $50 CIODEV_ACIA .EQU $60 -CIODEV_CONSOLE .EQU $D0 CIODEV_PIO .EQU $70 +CIODEV_UF .EQU $80 +CIODEV_CONSOLE .EQU $D0 ; ; SUB TYPES OF CHAR DEVICES ; diff --git a/Source/HBIOS/sio.asm b/Source/HBIOS/sio.asm index 9a6abaae..1d3d8791 100644 --- a/Source/HBIOS/sio.asm +++ b/Source/HBIOS/sio.asm @@ -134,15 +134,12 @@ SIO_PREINIT2: ; #IF (INTMODE >= 1) ; SETUP INT VECTORS AS APPROPRIATE - LD A,(SIO_DEV) ; GET NEXT DEVICE NUM + LD A,(SIO_DEV) ; GET DEVICE COUNT OR A ; SET FLAGS JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES, ABORT ; #IF (INTMODE == 1) ; ADD IM1 INT CALL LIST ENTRY - LD A,(SIO_DEV) ; GET NEXT DEVICE NUM - OR A ; SET FLAGS - JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES LD HL,SIO_INT ; GET INT VECTOR CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST #ENDIF @@ -214,7 +211,7 @@ SIO_INIT1: ; #IF (INTMODE > 0) ; -; IM0 ENTRY POINT +; IM1 ENTRY POINT ; SIO_INT: ; CHECK/HANDLE FIRST CARD (SIO0) IF IT EXISTS @@ -232,7 +229,7 @@ SIO_INT: ; RET ; DONE ; -; IM1 ENTRY POINTS +; IM2 ENTRY POINTS ; SIO_INT0: ; INTERRUPT HANDLER FOR FIRST SIO (SIO0) diff --git a/Source/HBIOS/uf.asm b/Source/HBIOS/uf.asm index e12969b5..4e2d7ce5 100644 --- a/Source/HBIOS/uf.asm +++ b/Source/HBIOS/uf.asm @@ -149,7 +149,7 @@ UF_QUERY: ; USB-FIFO WILL APPEAR AS A SERIAL DEVICE ; UF_DEVICE: - LD D,CIODEV_SIO ; D := DEVICE TYPE + LD D,CIODEV_UF ; D := DEVICE TYPE XOR A ; SIGNAL SUCCESS LD E,A ; E := PHYSICAL UNIT, ALWAYS 0 LD C,A ; C := DEVICE TYPE, 0x00 IS RS-232