From 51a33aaf0bde6aff064d3d0db944333ef193ff5b Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Tue, 7 Nov 2017 18:21:11 -0800 Subject: [PATCH] SIO Driver Interrupt Based Receive --- Source/Apps/XM/xmdm125.asm | 2 +- Source/Apps/XM/xmhb.180 | 338 ++++++++++++++++++++++++++++++------ Source/HBIOS/cfg_rc.asm | 2 +- Source/HBIOS/hbios.asm | 53 +++++- Source/HBIOS/ide.asm | 2 +- Source/HBIOS/sio.asm | 209 +++++++++++++++++++--- Source/HBIOS/std.asm | 1 + Source/HBIOS/uart.asm | 1 - Source/RomDsk/RC/XMODEM.COM | Bin 0 -> 4224 bytes 9 files changed, 526 insertions(+), 82 deletions(-) create mode 100644 Source/RomDsk/RC/XMODEM.COM diff --git a/Source/Apps/XM/xmdm125.asm b/Source/Apps/XM/xmdm125.asm index 1e375bc8..bd455f4b 100644 --- a/Source/Apps/XM/xmdm125.asm +++ b/Source/Apps/XM/xmdm125.asm @@ -328,7 +328,7 @@ MAXMIN EQU 60 ; Minutes for maximum file transfer time. ; Length of external patch program. If over 128 bytes, get/set size ; LARGEIO EQU YES ; Yes, if modem patch area over 128 bytes -LARSIZE EQU 180H ; If 'LARGEIO' set patch area size (bytes) here +LARSIZE EQU 500H ; If 'LARGEIO' set patch area size (bytes) here ; ;======================================================================= ; diff --git a/Source/Apps/XM/xmhb.180 b/Source/Apps/XM/xmhb.180 index f881d2f3..c8cd9f02 100644 --- a/Source/Apps/XM/xmhb.180 +++ b/Source/Apps/XM/xmhb.180 @@ -67,95 +67,182 @@ MINIT: LD C,9 ; BDOS string display function CALL BDOS ; Do it ; - ; Get system type + ; 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,BIOERR ; BIOS error message + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + JP 0 ; Bail out! +; +HINIT: +; + ; Display RomWBW notification string + LD DE,HBIOS ; BIOS notification string + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Get platform id from RomWBW HBIOS and save it + LD B,0F1H ; HBIOS VER function 0xF1 + LD C,0 ; Required reserved value + RST 08 ; Do it, L := Platform ID + LD A,L ; Move to A + LD (PLTID),A ; Save 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 + JR MINIT1 ; Continue general initialization +; +UINIT: +; + ; Display UNA notification string + LD DE,UBIOS ; 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 + JR MINIT1 ; Continue general initialization +; +MINIT1: + ; NOTE: PLTID is only set if RomWBW HBIOS is active. This is OK + ; because RC2014 is only support by RomWBW HBIOS at this point. + LD A,(PLTID) ; Get the platform id + CP 7 ; Check for RC2014 + JR Z,RCINIT ; Handle RC2014 special +; + ; Check for Z180 which implies ASCI serial port LD DE,00202H ; D := 2, E := 2 MLT DE ; DE := D * E == 4 BIT 2,E ; Bit 2 wil be set if mlt happend - LD HL,U_JPTBL ; Assume Z80 (UART) - LD DE,UART ; UART port notification string - JR Z,MINIT2 ; Yes, Z80, do vector copy - LD HL,A_JPTBL ; Otherwise Z180 (ASCI) + 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: - ; Display port notification string + ; 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: + ; Check for SIO/2 serial port + LD C,080H ; SIO command port + XOR A ; RD0 + OUT (C),A ; Access RD0 + IN A,(C) ; Get RD0 value + LD B,A ; Save it + LD A,1 ; RD1 + OUT (C),A ; Access RD1 + IN A,(C) ; Get RD1 value + CP B ; Compare + JR Z,RCINIT1 ; If equal, no SIO port there + LD HL,SIO_JPTBL ; SIO jump table address + LD DE,SIO ; SIO port notification string + JR MINIT3 ; Complete the initialization +; +RCINIT1: + ; Assume RC2014 ACIA port + LD HL,ACIA_JPTBL ; ACIA jump table address + LD DE,ACIA ; ACIA port 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 - POP HL ; Recover HL +; + ; 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) ; Get CPU speed saved above + RET ; and return +; +; 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,MINIT3 ; if not, not UNA + 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,MINIT3 ; if not, not UNA + 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,MINIT3 ; if not, not UNA -; - ; Display UNA notification string - LD DE,UBIOS ; BIOS notification string - LD C,9 ; BDOS string display function - CALL BDOS + JR NZ,IDBIO1 ; if not, not UNA, check others + LD A,2 ; UNA BIOS id = 2 + RET ; and done ; - ; Get CPU speed from UNA and return - 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 -MINIT2A: - SRL D ; ... to get approx CPU speed in - RR E ; ...MHz. Throw away HL, and - DJNZ MINIT2A ; ...right shift DE by 4. - INC E ; Fix up for value truncation - LD A,E ; Put in A - RET ; Done -; -MINIT3: - ; Not UNA, try RomwBW HBIOS for CPU speed lookup +IDBIO1: + ; Check for RomWBW (HBIOS) LD HL,(0FFFEH) ; HL := HBIOS ident location LD A,'W' ; First byte of ident CP (HL) ; Compare - JR NZ,MINIT4 ; Not HBIOS + JR NZ,IDBIO2 ; Not HBIOS INC HL ; Next byte of ident LD A,~'W' ; Second byte of ident CP (HL) ; Compare - JR NZ,MINIT4 ; Not HBIOS + JR NZ,IDBIO2 ; Not HBIOS + LD A,1 ; HBIOS BIOS id = 1 + RET ; and done ; - ; Display RomWBW notification string - LD DE,HBIOS ; BIOS notification string - LD C,9 ; BDOS string display function - CALL BDOS ; Do it +IDBIO2: + ; No idea what this is + XOR A ; Setup return value of 0 + RET ; and done ; - ; Get CPU speed from RomWBW HBIOS and return - 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 - RET ; Done ; -MINIT4: - ; Neither UNA nor RomWBW - LD DE,BIOERR ; BIOS error message - LD C,9 ; BDOS string display function - CALL BDOS ; Do it - JP 0 ; Bail out! ; -RBC DB "RBC, 28-Aug-2017, $" +BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS +PLTID DB 0 ; Platform ID +CPUSPD DB 0 ; CPU speed in MHz ; -UART DB "UART0$" -ASCI DB "ASCI0$" +RBC DB "RBC, 06-Nov-2017$" ; -UBIOS DB " [UNA]", 13, 10, "$" -HBIOS DB " [WBW]", 13, 10, "$" +UART DB ", UART0$" +ASCI DB ", ASCI0$" +SIO DB ", SIO0$" +ACIA DB ", ACIA0$" +; +UBIOS DB " [UNA]$" +HBIOS DB " [WBW]$" +; +CRLF DB 13, 10, "$" ; BIOERR DB 13, 10, 13, 10, "*** Unknown BIOS ***", 13, 10, "$" ; @@ -211,7 +298,7 @@ U_FRME EQU 08H ; bit for framing error ; table at program startup. See MINIT above. Note that only a ; subset of the jump table is overlaid (SENDR to SPEED). ; -U_JPTBL: +UART_JPTBL: JP U_SENDR ; send character (via pop psw) JP U_CAROK ; test for carrier JP U_MDIN ; receive data byte @@ -325,7 +412,7 @@ A_FRME EQU 10H ;Z180 STAT:FE - framing error bit ; table at program startup. See MINIT above. Note that only a ; subset of the jump table is overlaid (SENDR to SPEED). ; -A_JPTBL: +ASCI_JPTBL: JP A_SENDR ;send character (via pop psw) JP A_CAROK ;test for carrier JP A_MDIN ;receive data byte @@ -408,5 +495,148 @@ A_SNDRDY: A_SPEED: LD A,8 ; arbitrarily return 9600 baud RET +; +;======================================================================= +;======================================================================= +; +; RC2014 SIO/2 +; +;======================================================================= +;======================================================================= +; +; SIO port constants +; +S_CMD EQU 80H ; SIO Command port +S_DAT EQU 81H ; SIO Data 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). +; +SIO_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 +; +;----------------------------------------------------------------------- +; +; Send character on top of stack +; +S_SENDR: + POP AF ; get character to send from stack + OUT (S_DAT),A ; send to port + RET +; +;----------------------------------------------------------------------- +; +; Test and rep;ort 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_DAT) ; 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 ; A := 0 + OUT (S_CMD),A ; Access RD0 + IN A,(S_CMD) ; Get RD0 + AND 00000001B ; Isolate rx ready bit + CP 00000001B ; ZF = rx ready +; + IF ERRDET +; + ; With error detection (slower) + PUSH BC ; save BC + PUSH AF ; save AF + LD A,1 ; A := 1 + OUT (S_CMD),A ; Access RD1 + IN A,(S_CMD) ; Get RD1 + AND 01110000B ; isolate line err bits + POP AF ; restore AF + LD A,B ; err bits (B) to A + POP BC ; restore BC +; + ELSE +; + ; No error detection (faster) + LD A,0 ; report no line errors +; + ENDIF +; + RET +; +;----------------------------------------------------------------------- +; +; Test for ready to send a character, Z = ready +; +S_SNDRDY: + XOR A ; A := 0 + OUT (S_CMD),A ; Access RD0 + IN A,(S_CMD) ; Get RD0 + AND 00000100B ; Isolate tx empty bit + CP 00000100B ; ZF = tx empty + RET +; +;----------------------------------------------------------------------- +; +; Report baud rate (index into SPTBL returned in regsiter A) +; +S_SPEED: + LD A,8 ; arbitrarily return 9600 baud + RET +; +;======================================================================= +;======================================================================= +; +; RC2014 ACIA +; +;======================================================================= +;======================================================================= +; +; ACIA port constants +; +C_CMD EQU 80H ; SIO Command port +C_DAT EQU 81H ; SIO Data 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). +; +ACIA_JPTBL: + JP C_SENDR ;send character (via pop psw) + JP C_CAROK ;test for carrier + JP C_MDIN ;receive data byte + JP C_GETCHR ;get character from modem + JP C_RCVRDY ;check receive ready + JP C_SNDRDY ;check send ready + JP C_SPEED ;get speed value for file transfer time +; +C_SENDR: +C_CAROK: +C_MDIN: +C_GETCHR: +C_RCVRDY: +C_SNDRDY: +C_SPEED: + ; Not yet implemeted... + JP 0 ; END diff --git a/Source/HBIOS/cfg_rc.asm b/Source/HBIOS/cfg_rc.asm index 5686d561..ac65a734 100644 --- a/Source/HBIOS/cfg_rc.asm +++ b/Source/HBIOS/cfg_rc.asm @@ -8,7 +8,7 @@ CPUOSC .EQU 7372800 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_NONE ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTTYPE .EQU IT_RC ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 0a35e7c9..ccca08c4 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -476,8 +476,24 @@ INT_TIMER: ; TIMER INTERRUPT HANDLER ; INT_BAD: ; BAD INTERRUPT HANDLER PUSH HL ; SAVE HL - LD HL,HB_BADINT - JR HBX_INT + LD HL,HB_BADINT ; HL := INT HANDLER IN BIOS BANK + JR HBX_INT ; TO TO ROUTING CODE +; +#IF (SIOENABLE) +INT_SIO: ; SIO DEVICE INTERRUPT HANDLER + ;PUSH AF + ;IN A,(SIOA_DAT) + ;LD A,'=' + ;OUT (SIOA_DAT),A + ;POP AF + ;EI + ;RETI + + + PUSH HL ; SAVE HL + LD HL,SIO_INT ; HL := SIO INT HANDLER IN BIOS BANK + JR HBX_INT ; TO TO ROUTING CODE +#ENDIF ; ; COMMON INTERRUPT DISPATCHING CODE ; SETUP AND CALL HANDLER IN BIOS BANK @@ -791,8 +807,39 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; #ENDIF ; +#IF (INTTYPE == IT_RC) +; + ; SETUP Z80 IVT + LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS + LD I,A ; ... AND PLACE IT IN I REGISTER +; + IM 2 ; SWITCH TO INT MODE 2 +; +#IF (SIOENABLE) + ; SETUP SIO INTERRUPT VECTOR IN IVT + LD HL,INT_SIO + LD (HBX_IVT + 4),HL +#ENDIF + + + + +; +; IM 1 +; +;#IF (SIOENABLE) +;; +; ; SETUP SIO INT VECTOR VIA INT MODE 1 IN PAGE ZERO +; ;LD A,$C3 ; JP OPCODE +; ;LD ($38),A ; ... AT INT VECTOR ADDRESS +; ;LD HL,INT_SIO ; ADDRESS OF SIO INT HANDLER +; ;LD ($39),HL ; ... IS TARGET OF JP +;; +;#ENDIF +; +#ENDIF +; #ENDIF - HB_EI ; END OF CRITICAL SECTION ; ; DISPLAY PLATFORM INFORMATION diff --git a/Source/HBIOS/ide.asm b/Source/HBIOS/ide.asm index d3d7d94e..38536f97 100644 --- a/Source/HBIOS/ide.asm +++ b/Source/HBIOS/ide.asm @@ -38,7 +38,7 @@ ; | IDE_IO_STAT | 0x07 | R | STATUS REGISTER | ; | IDE_IO_CMD | 0x07 | W | COMMAND REGISTER (EXECUTE) | ; +-----------------------+-------+-------+-------------------------------+ -; * LBA0-4 ARE ALTERNATE DEFINITIONS OF SECT, CYL, AND DRVHD PORTS +; * LBA0-3 ARE ALTERNATE DEFINITIONS OF SECT, CYL, AND DRVHD PORTS ; ; === STATUS REGISTER === ; diff --git a/Source/HBIOS/sio.asm b/Source/HBIOS/sio.asm index ad78ebcf..3800c694 100644 --- a/Source/HBIOS/sio.asm +++ b/Source/HBIOS/sio.asm @@ -11,10 +11,17 @@ ; F E D C B A 9 8 7 6 5 4 3 2 1 0 ; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- ; -SIO_DEBUG .EQU FALSE -; -SIO_NONE .EQU 0 -SIO_SIO .EQU 1 +SIO_DEBUG .EQU FALSE +; +SIO_NONE .EQU 0 +SIO_SIO .EQU 1 +; +; +; +SIOA_CMD .EQU $80 +SIOA_DAT .EQU $81 +SIOB_CMD .EQU $82 +SIOB_DAT .EQU $83 ; ; ; @@ -24,6 +31,8 @@ SIO_PREINIT: ; LD B,SIO_CNT ; LOOP CONTROL LD C,0 ; PHYSICAL UNIT INDEX + XOR A ; ZERO TO ACCUM + LD (SIO_DEV),A ; CURRENT DEVICE NUMBER SIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL LD A,C ; PHYSICAL UNIT TO A @@ -51,10 +60,11 @@ SIO_PREINIT0: SIO_PREINIT2: INC C ; NEXT PHYSICAL UNIT DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE +; XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; -; +; SIO INITIALIZATION ROUTINE ; SIO_INITUNIT: CALL SIO_DETECT ; DETERMINE SIO TYPE @@ -89,6 +99,8 @@ SIO_INIT1: PUSH HL ; COPY CFG DATA PTR POP IY ; ... TO IY + LD A,(IY + 1) ; GET SIO TYPE + OR A ; SET FLAGS CALL NZ,SIO_PRTCFG ; PRINT IF NOT ZERO POP BC ; RESTORE LOOP CONTROL @@ -98,6 +110,78 @@ SIO_INIT1: XOR A ; SIGNAL SUCCESS RET ; DONE ; +; INTERRUPT HANDLER +; +SIO_INT: + ; CHECK FOR RECEIVE PENDING ON CHANNEL A + XOR A ; A := 0 + OUT (SIOA_CMD),A ; ADDRESS RD0 + IN A,(SIOA_CMD) ; GET RD0 + RRA ; RECEIVE READY BIT TO CF + JR NC,SIOB_INT ; NOTHING HERE, TRY B CHANNEL +; + ; HANDLE CHANNEL A + IN A,(SIOA_DAT) ; READ PORT + LD E,A ; SAVE BYTE READ + LD A,(SIOA_CNT) ; GET CURRENT BUFFER USED COUNT + CP SIOA_BUFSZ ; COMPARE TO BUFFER SIZE + RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED + INC A ; INCREMENT THE COUNT + LD (SIOA_CNT),A ; AND SAVE IT + CP SIOA_BUFSZ - 5 ; BUFFER GETTING FULL? + JR NZ,SIOA_INT0 ; IF NOT, BYPASS CLEARING RTS + LD A,5 ; RTS IS IN WR5 + OUT (SIOA_CMD),A ; ADDRESS WR5 + LD A,$E8 ; VALUE TO CLEAR RTS + OUT (SIOA_CMD),A ; DO IT +SIOA_INT0: + LD HL,(SIOA_HD) ; GET HEAD POINTER + LD A,L ; GET LOW BYTE + CP SIOA_BUFEND & $FF ; PAST END? + JR NZ,SIO_INT1 ; IF NOT, BYPASS POINTER RESET + LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER +SIO_INT1: + LD A,E ; RECOVER BYTE READ + LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION + INC HL ; INCREMENT HEAD POINTER + LD (SIOA_HD),HL ; SAVE IT + RET ; AND RETURN +; +SIOB_INT: + ; CHECK FOR RECEIVE PENDING ON CHANNEL B + XOR A ; A := 0 + OUT (SIOB_CMD),A ; ADDRESS RD0 + IN A,(SIOB_CMD) ; GET RD0 + RRA ; RECEIVE READY BIT TO CF + RET NC ; NOTHING HERE, GIVE UP +; + ; HANDLE CHANNEL B + IN A,(SIOB_DAT) ; READ PORT + LD E,A ; SAVE BYTE READ + LD A,(SIOB_CNT) ; GET CURRENT BUFFER USED COUNT + CP SIOB_BUFSZ ; COMPARE TO BUFFER SIZE + RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED + INC A ; INCREMENT THE COUNT + LD (SIOB_CNT),A ; AND SAVE IT + CP SIOB_BUFSZ - 5 ; BUFFER GETTING FULL? + JR NZ,SIOB_INT0 ; IF NOT, BYPASS CLEARING RTS + LD A,5 ; RTS IS IN WR5 + OUT (SIOB_CMD),A ; ADDRESS WR5 + LD A,$E8 ; VALUE TO CLEAR RTS + OUT (SIOB_CMD),A ; DO IT +SIOB_INT0: + LD HL,(SIOB_HD) ; GET HEAD POINTER + LD A,L ; GET LOW BYTE + CP SIOB_BUFEND & $FF ; PAST END? + JR NZ,SIOB_INT1 ; IF NOT, BYPASS POINTER RESET + LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER +SIOB_INT1: + LD A,E ; RECOVER BYTE READ + LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION + INC HL ; INCREMENT HEAD POINTER + LD (SIOB_HD),HL ; SAVE IT + RET ; AND RETURN +; ; ; SIO_DISPATCH: @@ -127,10 +211,65 @@ SIO_FTBL: ; ; SIO_IN: - CALL SIO_IST ; RECEIVED CHAR READY? - JR Z,SIO_IN ; LOOP IF NOT - LD C,(IY + 2) ; C := BASE SIO PORT (WHICH IS ALSO RBR REG) - IN E,(C) ; CHAR READ TO E + LD A,(IY + 0) ; GET DEVICE NUMBER + OR A ; SET FLAGS + JR Z,SIOA_IN ; HANDLE CHANNEL A + DEC A ; TEST FOR NEXT DEVICE + JR Z,SIOB_IN ; HANDLE CHANNEL B + CALL PANIC ; ELSE FATAL ERROR + RET ; ... AND RETURN +; +SIOA_IN: + CALL SIOA_IST ; RECEIVED CHAR READY? + JR Z,SIOA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER + DI ; AVOID COLLISION WITH INT HANDLER + LD A,(SIOA_CNT) ; GET COUNT + DEC A ; DECREMENT COUNT + LD (SIOA_CNT),A ; SAVE SAVE IT + CP 5 ; BUFFER LOW THRESHOLD + JR NZ,SIOA_IN0 ; IF NOT, BYPASS SETTING RTS + LD A,5 ; RTS IS IN WR5 + OUT (SIOA_CMD),A ; ADDRESS WR5 + LD A,$EA ; VALUE TO SET RTS + OUT (SIOA_CMD),A ; DO IT +SIOA_IN0: + LD HL,(SIOA_TL) ; GET BUFFER TAIL POINTER + LD E,(HL) ; GET BYTE + INC HL ; BUMP TAIL POINTER + LD A,L ; GET LOW BYTE + CP SIOA_BUFEND & $FF ; PAST END? + JR NZ,SIOA_IN1 ; IF NOT, BYPASS POINTER RESET + LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER +SIOA_IN1: + LD (SIOA_TL),HL ; SAVE UPDATED TAIL POINTER + EI ; INTERRUPTS OK AGAIN + XOR A ; SIGNAL SUCCESS + RET ; AND DONE +; +SIOB_IN: + CALL SIOB_IST ; RECEIVED CHAR READY? + JR Z,SIOB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER + DI ; AVOID COLLISION WITH INT HANDLER + LD A,(SIOB_CNT) ; GET COUNT + DEC A ; DECREMENT COUNT + LD (SIOB_CNT),A ; SAVE SAVE IT + CP 5 ; BUFFER LOW THRESHOLD + JR NZ,SIOB_IN0 ; IF NOT, BYPASS SETTING RTS + LD A,5 ; RTS IS IN WR5 + OUT (SIOA_CMD),A ; ADDRESS WR5 + LD A,$EA ; VALUE TO SET RTS + OUT (SIOA_CMD),A ; DO IT +SIOB_IN0: + LD HL,(SIOB_TL) ; GET BUFFER TAIL POINTER + LD E,(HL) ; GET BYTE + INC HL ; BUMP TAIL POINTER + LD A,L ; GET LOW BYTE + CP SIOB_BUFEND & $FF ; PAST END? + JR NZ,SIOB_IN1 ; IF NOT, BYPASS POINTER RESET + LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER +SIOB_IN1: + LD (SIOB_TL),HL ; SAVE UPDATED TAIL POINTER + EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; @@ -147,14 +286,24 @@ SIO_OUT: ; ; SIO_IST: - LD C,(IY + 3) ; CMD PORT - XOR A ; WR0 - OUT (C),A ; DO IT - IN A,(C) ; GET STATUS - AND $01 ; ISOLATE BIT 0 (RECEIVE DATA READY) + LD A,(IY + 0) ; GET DEVICE NUMBER + OR A ; SET FLAGS + JR Z,SIOA_IST ; HANDLE CHANNEL A + DEC A ; TEST FOR NEXT DEVICE + JR Z,SIOB_IST ; HANDLE CHANNEL B + CALL PANIC ; ELSE FATAL ERROR + RET ; ... AND RETURN +; +SIOA_IST: + LD A,(SIOA_CNT) ; GET BUFFER UTILIZATION COUNT + OR A ; SET FLAGS + JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING + RET ; AND DONE +; +SIOB_IST: + LD A,(SIOB_CNT) ; GET BUFFER UTILIZATION COUNT + OR A ; SET FLAGS JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING - XOR A ; ZERO ACCUM - INC A ; ACCUM := 1 TO SIGNAL 1 CHAR WAITING RET ; DONE ; ; @@ -183,7 +332,9 @@ SIO_INITDEV: SIO_INITVALS: .DB $00, $18 ; WR0: CHANNEL RESET .DB $04, $C4 ; WR4: CLK/64=115200 BAUD, NO PARITY, 1 STOP BIT - .DB $01, $00 ; WR1: NO INTERRUPTS +; .DB $01, $00 ; WR1: NO INTERRUPTS + .DB $01, $18 ; WR1: INTERRUPT ON ALL RECEIVE CHARACTERS + .DB $02, $04 ; WR2: INTERRUPT VECTOR OFFSET .DB $03, $C1 ; WR3: 8 BIT RCV, RX ENABLE .DB $05, $EA ; WR5: DTR, 8 BITS SEND, TX ENABLE, RTS SIO_INITLEN .EQU $ - SIO_INITVALS @@ -270,22 +421,38 @@ SIO_STR_SIO .DB "SIO$" ; SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT ; +; CHANNEL A RECEIVE BUFFER +SIOA_CNT .DB 0 ; CHARACTERS IN RING BUFFER +SIOA_BUF .FILL 32,'%' ; RECEIVE RING BUFFER +SIOA_BUFEND .EQU $ ; END OF BUFFER +SIOA_BUFSZ .EQU $ - SIOA_BUF ; SIZE OF RING BUFFER +SIOA_HD .DW SIOA_BUF ; BUFFER HEAD POINTER +SIOA_TL .DW SIOA_BUF ; BUFFER TAIL POINTER +; +; CHANNEL B RECEIVE BUFFER +SIOB_CNT .DB 0 ; CHARACTERS IN RING BUFFER +SIOB_BUF .FILL 32,'%' ; RECEIVE RING BUFFER +SIOB_BUFEND .EQU $ ; END OF BUFFER +SIOB_BUFSZ .EQU $ - SIOB_BUF ; SIZE OF RING BUFFER +SIOB_HD .DW SIOB_BUF ; BUFFER HEAD POINTER +SIOB_TL .DW SIOB_BUF ; BUFFER TAIL POINTER +; ; SIO PORT TABLE ; SIO_CFG: ; SIO/2 CHANNEL A .DB 0 ; DEVICE NUMBER (UPDATED DURING INIT) .DB 0 ; SIO TYPE - .DB $81 ; DATA PORT - .DB $80 ; CMD PORT + .DB SIOA_DAT ; DATA PORT + .DB SIOA_CMD ; CMD PORT .DW DEFSERCFG ; LINE CONFIGURATION .FILL 2,$FF ; FILLER ; ; SIO/2 CHANNEL B .DB 0 ; DEVICE NUMBER (UPDATED DURING INIT) .DB 0 ; SIO TYPE - .DB $83 ; DATA PORT - .DB $82 ; CMD PORT + .DB SIOB_DAT ; DATA PORT + .DB SIOB_CMD ; CMD PORT .DW DEFSERCFG ; LINE CONFIGURATION .FILL 2,$FF ; FILLER ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 87d0576b..4d247bf7 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -163,6 +163,7 @@ IT_NONE .EQU 0 IT_SIMH .EQU 1 IT_Z180 .EQU 2 IT_CTC .EQU 3 +IT_RC .EQU 4 ; #INCLUDE "build.inc" ; INCLUDE USER CONFIG, ADD VARIANT, TIMESTAMP, & ROMSIZE ; diff --git a/Source/HBIOS/uart.asm b/Source/HBIOS/uart.asm index c1fa7f13..ad1dec81 100644 --- a/Source/HBIOS/uart.asm +++ b/Source/HBIOS/uart.asm @@ -116,7 +116,6 @@ UART_INITUNIT: ; ; ; -; UART_INIT: LD B,UART_CNT ; COUNT OF POSSIBLE UART UNITS LD C,0 ; INDEX INTO UART CONFIG TABLE diff --git a/Source/RomDsk/RC/XMODEM.COM b/Source/RomDsk/RC/XMODEM.COM new file mode 100644 index 0000000000000000000000000000000000000000..a50fd5753d5c377ed2418bdb3985e8beba5c1d75 GIT binary patch literal 4224 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 ZZJPB=`I`Bg`iK~gBY@)mX8Zpc{{ut?;Ftga literal 0 HcmV?d00001