diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 858d41c7..93785db4 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -97,3 +97,6 @@ BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 4e3d9a27..933c17e6 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -110,3 +110,6 @@ Z180_IOWAIT .EQU 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index 44e0d46e..8dc7498d 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -99,3 +99,6 @@ Z180_IOWAIT .EQU 3 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index 101319c1..fa6dabf3 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -103,3 +103,6 @@ Z180_IOWAIT .EQU 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index ff24bf39..6beed599 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -97,3 +97,6 @@ BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index a35b649a..1b9079bb 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -109,3 +109,6 @@ BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 6a3888fa..3279cbd0 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -82,3 +82,6 @@ BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT PIO_4P .EQU FALSE ; TRUE FOR ECB-4PIO PIO SUPPORT PIO_ZP .EQU FALSE ; TRUE FOR ECB-ZILOG PERIPHERALS BOARD PPI_SBC .EQU FALSE ; TRUE FOR SBC V2 8255 (IF NOT BEING USED FOR PPIDE) +; +UFENABLE .EQU FALSE ; TRUE FOR ECB USB-FIFO SUPPORT + diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 5792a18b..619d6bdc 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -1044,9 +1044,6 @@ HB_CPU1: CALL FILL ; DO IT ; DIAG(%00111111) -; -; PRE-CONSOLE INITIALIZATION -; #IF 0 ; ; TEST DEBUG *************************************************************************************** @@ -1058,21 +1055,28 @@ HB_CPU1: ; #ENDIF ; -#IF (ASCIENABLE) - CALL ASCI_PREINIT -#ENDIF -#IF (UARTENABLE) - CALL UART_PREINIT -#ENDIF -#IF (SIOENABLE) - CALL SIO_PREINIT -#ENDIF -#IF (ACIAENABLE) - CALL ACIA_PREINIT -#ENDIF -#IF (PIO_4P | PIO_ZP) - CALL PIO_PREINIT -#ENDIF +; PRE-CONSOLE INITIALIZATION +; + LD A,FORCECON ; CALCULATE PRE-INIT TABLE + RLCA ; ENTRY THAT WE WANT TO + LD DE,(PC_INITTBL) ; EXECUTE FIRST + LD HL,PC_INITTBL + PUSH HL + PUSH DE + PUSH HL + CALL ADDHLA + POP DE ; PLACE IT AT THE TOP OF THE + PUSH HL ; TABLE BY SWAPPING IT + LDI ; WITH THE FIRST (DUMMY) + LDI ; ENTRY + POP HL + POP DE + LD (HL),D + INC HL + LD (HL),E + LD B,PC_INITTBLLEN + POP DE + CALL CALLLIST ; PROCESS THE PRE-INIT CALL TABLE ; #IF 0 ; @@ -1437,19 +1441,7 @@ HB_PCPU: CALL NEWLINE LD B,HB_INITTBLLEN LD DE,HB_INITTBL -INITSYS1: - LD A,(DE) - LD L,A - INC DE - LD A,(DE) - LD H,A - INC DE - PUSH DE - PUSH BC - CALL JPHL - POP BC - POP DE - DJNZ INITSYS1 + CALL CALLLIST ; ; RECORD HEAP CURB AT THE CURRENT VALUE OF HEAP TOP. HEAP CURB ; MARKS THE POINT IN THE HEAP AFTER WHICH MEMORY IS RELEASED @@ -1532,6 +1524,50 @@ INITSYS3: ; RET ; +; CALL A LIST OF ROUTINES POINTED TO BY DE OF LENGTH B. +; +CALLLIST: + LD A,(DE) + LD L,A + INC DE + LD A,(DE) + LD H,A + INC DE + PUSH DE + PUSH BC + CALL JPHL + POP BC + POP DE + DJNZ CALLLIST +CALLDUMMY: + RET +; +;================================================================================================== +; TABLE OF PRE-CONSOLE INITIALIZATION ENTRY POINTS +;================================================================================================== + +PC_INITTBL: + .DW CALLDUMMY ; RESERVED FOR FORCING PRIMARY CONSOLE +#IF (ASCIENABLE) + .DW ASCI_PREINIT +#ENDIF +#IF (UARTENABLE) + .DW UART_PREINIT +#ENDIF +#IF (SIOENABLE) + .DW SIO_PREINIT +#ENDIF +#IF (ACIAENABLE) + .DW ACIA_PREINIT +#ENDIF +#IF (PIO_4P | PIO_ZP) + .DW PIO_PREINIT +#ENDIF +#IF (UFENABLE) + .DW UF_PREINIT +#ENDIF +PC_INITTBLLEN .EQU (($ - PC_INITTBL) / 2) + ;================================================================================================== ; TABLE OF INITIALIZATION ENTRY POINTS ;================================================================================================== @@ -1609,6 +1645,9 @@ HB_INITTBL: #IF (PIO_4P | PIO_ZP) .DW PIO_INIT #ENDIF +#IF (UFENABLE) + .DW UF_INIT +#ENDIF ; HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2) ; @@ -2702,7 +2741,7 @@ SIZ_MD .EQU $ - ORG_MD .ECHO SIZ_MD .ECHO " bytes.\n" #ENDIF - +; #IF (FDENABLE) ORG_FD .EQU $ #INCLUDE "fd.asm" @@ -2711,7 +2750,7 @@ SIZ_FD .EQU $ - ORG_FD .ECHO SIZ_FD .ECHO " bytes.\n" #ENDIF - +; #IF (RFENABLE) ORG_RF .EQU $ #INCLUDE "rf.asm" @@ -2720,7 +2759,7 @@ SIZ_RF .EQU $ - ORG_RF .ECHO SIZ_RF .ECHO " bytes.\n" #ENDIF - +; #IF (IDEENABLE) ORG_IDE .EQU $ #INCLUDE "ide.asm" @@ -2729,7 +2768,7 @@ SIZ_IDE .EQU $ - ORG_IDE .ECHO SIZ_IDE .ECHO " bytes.\n" #ENDIF - +; #IF (PPIDEENABLE) ORG_PPIDE .EQU $ #INCLUDE "ppide.asm" @@ -2738,7 +2777,7 @@ SIZ_PPIDE .EQU $ - ORG_PPIDE .ECHO SIZ_PPIDE .ECHO " bytes.\n" #ENDIF - +; #IF (SDENABLE) ORG_SD .EQU $ #INCLUDE "sd.asm" @@ -2747,7 +2786,7 @@ SIZ_SD .EQU $ - ORG_SD .ECHO SIZ_SD .ECHO " bytes.\n" #ENDIF - +; #IF (HDSKENABLE) ORG_HDSK .EQU $ #INCLUDE "hdsk.asm" @@ -2756,7 +2795,7 @@ SIZ_HDSK .EQU $ - ORG_HDSK .ECHO SIZ_HDSK .ECHO " bytes.\n" #ENDIF - +; #IF (TERMENABLE) ORG_TERM .EQU $ #INCLUDE "term.asm" @@ -2783,6 +2822,7 @@ SIZ_AY .EQU $ - ORG_AY .ECHO SIZ_AY .ECHO " bytes.\n" #ENDIF +; #IF (PIO_4P | PIO_ZP | PPI_SBC) ORG_PIO .EQU $ #INCLUDE "pio.asm" @@ -2791,7 +2831,15 @@ SIZ_PIO .EQU $ - ORG_PIO .ECHO SIZ_PIO .ECHO " bytes.\n" #ENDIF - +; +#IF (UFENABLE) +ORG_UF .EQU $ + #INCLUDE "usbfifo.asm" +SIZ_UF .EQU $ - ORG_UF + .ECHO "USB-FIFO occupies " + .ECHO SIZ_UF + .ECHO " bytes.\n" +#ENDIF ; #DEFINE USEDELAY #INCLUDE "util.asm" diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index e9327111..c5a2314b 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -3,46 +3,58 @@ ; ; HBIOS initializes driver by: ; -; 1) Performing Pre-initialization +; 1) Calling Pre-initialization ; -; This involves setting up all the data structures decribing the devices. +; This involves setting up all the data structures describing the devices. ; If possible, do a hardware test to verify it is available for adding to available devices. ; -; 2) Performing individual device/unit initialization. +; 2) Calling device initialization. ; ; Hardware initialization. ; Configure to initial state or to a new state. +; ; Implementation limitations: ; ; The fully functionality of the Z80 PIO can only be realized by using Z80 interrupt mode 2. ; Registers cannot be interrogated for interrupts status and the originating interrupt ; device cannot be determine. ; -; Full implementation of IM2 functionality in an ECB-ZP and ECB-4P board would require the -; allocation of an interrupt handler for each chip channel. Thus, 10 interrupt handler +; Full implementation of IM2 functionality for an ECB-ZP and ECB-4P board would require the +; allocation of an interrupt handler for each chip channel. Thus, 12 interrupt handlers ; would be required to support this configuration. As the HBIOS only has an allocation of ; 16, a full implmentation is impractical. ; -; The compromise solution is for the driver to allow IM2 only on the first PIO on each board. -; So, a ECB-4PIO would be fully interrupt drived in all modes but a ECB-ZP would only allow -; PIO 0 to be interrupt drived and PIO 1,2,3 would be limited to Bit mode or blind read and -; writed to the input/output ports. +; The compromise solution is to allow 4 interrupts for the PIO driver.; All remaining PIO's +; are limited to Bit mode or blind read and writed to the input/output ports. ; ; Zilog PIO reset state: ; -; Both port mask registers are reset to inhibit All port data bits. -; Port data bus lines are set to a high-impedance state and the Ready "handshake" -; Mode 1 is automatically selected. -; The vector address registers are not reset. -; Both port interrupt enable flip-flops are reset. -; Both port output registers are reset. -; -; Program a channel -; -; LD C,PIOBC ; C -> PIO Channel B control -; LD B,5 ; 5 bytes to send -; LD HL,PT ; HL -> Initialization data -; OTIR ; send bytes +; Both port mask registers are reset to inhibit All port data bits. +; Port data bus lines are set to a high-impedance state and the Ready "handshake" +; Mode 1 (output) is automatically selected. +; The vector address registers are not reset. +; Both port interrupt enable flip-flops are reset. +; Both port output registers are reset. +; +; Register addressing for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +; +; PIO ----ZP---- ----4P---- +; 0 DATA 0 90h DATA 0 B8h +; 0 DATA 1 91h DATA 1 B9h +; 0 CMD 0 92h CMD 0 BAh +; 0 CMD 1 93h CMD 1 BBh +; 1 DATA 0 94h DATA 0 BCh +; 1 DATA 1 95h DATA 1 BDh +; 1 CMD 0 96h CMD 0 BEh +; 1 CMD 1 97h CMD 1 BFh +; 2 DATA 0 C0h +; 2 DATA 1 C1h +; 2 CMD 0 C2h +; 2 CMD 1 C3h +; 3 DATA 0 C4h +; 3 DATA 1 C5h +; 3 CMD 0 C6h +; 3 CMD 1 C7h ; PIODEBUG .EQU 1 ; @@ -58,307 +70,634 @@ PIO_ZPIO .EQU 1 PIO_8255 .EQU 2 PIO_PORT .EQU 3 -;INT_POOL .EQU HBX_IVT+IVT_PIO0 +; SET MAXIMUM NUMBER OF INTERRUPTS AVAILABLE FOR ALL +; ENSURE INTERRUPTS ARE NOT TURNED ON IF IM2 IS NOT SET. INT_ALLOC .DB 0 INT_N .EQU 00000000B #IF (INTMODE == 2) -INT_Y .EQU INT_N +INT_Y .EQU 00000100B INT_ALLOW .EQU 4 #ELSE -INT_Y .EQU 00000100B +INT_Y .EQU INT_N INT_ALLOW .EQU 0 #ENDIF - -INT_0 .EQU 00000000B -INT_1 .EQU 00000001B -INT_2 .EQU 00000010B -INT_3 .EQU 00000011B ; +INT0 .EQU 00000000B +INT1 .EQU 00000001B +INT2 .EQU 00000010B +INT3 .EQU 00000011B + ; ; SETUP THE DISPATCH TABLE ENTRIES ; -; WE CANT PRINT ANYTHING TO HBIOS CONSOLE AT THIS POINT ; PIO_CNT HOLDS THE NUMBER OF DEVICED CALCULATED FROM THE NUMBER OF DEFPIO MACROS ; PIO_CNT SHOULD INCREASE BY 2 FOR EVERY PIO CHIP ADDED. ; +; PIO_PREINIT WILL READ THROUGH ALL PIOCFG TABLES AND CONFIGURE EACH TABLE. +; IT WITH THEN CALL PIO_INITUNIT TO INITIALIZE EACH DEVICE TO ITS DEFAULT STATE +; +; EXPECTS NOTHING ON ENTRY +; PIO_PREINIT: + CALL NEWLINE ;D LD B,PIO_CNT ; LOOP CONTROL LD C,0 ; PHYSICAL UNIT INDEX XOR A ; ZERO TO ACCUM - LD (PIO_DEV),A ; CURRENT DEVICE NUMBER +; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER + LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED PIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS - PUSH HL ; SAVE IT - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE - POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE - POP BC ; RESTORE LOOP CONTROL -; +; LD A,C ; INITIALIZE THE UNIT + +; PUSH AF ;D +; LD A,'u' ;D +; CALL COUT ;D +; POP AF ;D +; CALL PRTHEXBYTE ;D UNIT +; CALL PC_SPACE ;D + +; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) +; RLCA ; ... +; RLCA ; ... TO GET OFFSET INTO CFG TABLE +; RLCA +;; RLCA +; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE +; PUSH AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; POP AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; PUSH HL ; SAVE IT +; POP IY ; ... TO IY + + CALL IDXCFG + + LD (HL),C + + PUSH AF ;D + LD A,'c' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + PUSH HL ;D + POP BC ;D + CALL PRTHEXWORD ;D CONFIG TABLE + CALL PC_SPACE ;D + POP BC ;D + LD A,(IY+1) ; GET THE PIO TYPE DETECTED - OR A ; SET FLAGS - JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND -; - PUSH BC ; SAVE LOOP CONTROL - PUSH AF - DEC A - LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D - DEC A - LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND - DEC A - LD BC,PRT_FNTBL - JR NZ,TYPDUN -TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE -TYPDUN: POP AF - POP BC ; RESTORE LOOP CONTROL -; -PIO_PREINIT2: + CP PIO_PORT ; SET FLAGS + + PUSH AF ;D + LD A,'t' ;D + CALL COUT ;D + POP AF ;D + CALL PRTHEXBYTE ;D TYPE + CALL PC_SPACE ;D + +; JR Z,BADINIT + +; PUSH BC ; SAVE LOOP CONTROL +; LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; SKIP IT IF NOTHING FOUND +; LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:DE +; LD BC,PRT_FNTBL +; DEC A +; JR Z,TYPFND +; POP BC +; JR BADINIT + + PUSH HL + LD DE,-1 ; INITIALIZE THIS DEVICE WITH + CALL PIO_INITDEV ; DEFAULT VALUES + POP HL + +; JR NZ,SKPINIT + + ; AT THIS POINT WE KNOW WE + ; HAVE A VALID DEVICE SO ADD IT + + LD A,8 ; CALCULATE THE FUNCTION TABLE + CALL ADDHLA ; POSITION WHICH FOLLOWS THE + PUSH HL ; CONFIGURATION TABLE OF EACH + POP BC ; DEVICE + +TYPFND: PUSH AF ;D + LD A,'f' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + CALL PRTHEXWORD ;D FUNCTION TABLE + POP BC ;D + CALL NEWLINE ;D + + PUSH IY ; ADD ENTRY IF PIO FOUND, BC:DE + POP DE ; BC: DRIVER FUNCTION TABLE + CALL CIO_ADDENT ; DE: ADDRESS OF UNIT INSTANCE DATA + +BADINIT:POP BC ; RESTORE LOOP CONTROL + INC C ; NEXT PHYSICAL UNIT - DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE -; -#IF (INTMODE == 2) - ; SETUP PIO INTERRUPT VECTOR IN IVT - LD HL,PIO0INT -; LD (HBX_IVT + IVT_PIO0),HL - LD (HB_IVT09 + 1),HL ; WW: IVT INDEX 9 FOR PIO0 -#ENDIF -PIO_PREINIT3: +SKPINIT:DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE + + PUSH AF ;D + PRTS("INTS=$") ;D + LD A,(INT_ALLOC) ;D + CALL PRTHEXBYTE ;D + POP AF ;D + PUSH DE ;D + LD DE,CIO_TBL-3 ;D + CALL DUMP_BUFFER ;D + POP DE ;D XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; -; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; X24 ; -PIO_INITUNIT: - LD A,C ; SET THE UNIT NUMBER - LD (IY),A - - LD DE,-1 ; LEAVE CONFIG ALONE - JP PIO_INITDEV ; IMPLEMENT IT AND RETURN -; XOR A ; SIGNAL SUCCESS -; RET ; AND RETURN ; -PIO_INIT: - LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS - LD C,0 ; INDEX INTO PIO CONFIG TABLE -PIO_INIT1: - PUSH BC ; SAVE LOOP CONTROL - - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS +CFG_SIZ .EQU 24 +; +IDXCFG: LD A,C + RLCA ; X 2 + RLCA ; X 4 + RLCA ; X 8 + LD H,0 + LD L,A ; HL = X 8 + PUSH HL + ADD HL,HL ; HL = X 16 + POP DE + ADD HL,DE ; HL = X 24 + LD DE,PIO_CFG + ADD HL,DE PUSH HL ; COPY CFG DATA PTR POP IY ; ... TO IY - - LD A,(IY+1) ; GET PIO TYPE - OR A ; SET FLAGS - CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO - - PUSH DE - LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL - CALL PIO_INITDEV ; BASED ON DPW - POP DE - - POP BC ; RESTORE LOOP CONTROL - INC C ; NEXT UNIT - DJNZ PIO_INIT1 ; LOOP TILL DONE -; - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -; EXAMPLE CODE -; -PIO_LPT: - IN A,($F6) ; get device status - AND $20 ; device ready? - JR Z,PIO_LPT ; no, busy wait - IN A,($F5) ; get transmit buffer register status ready? - AND $20 ; ready? - JR Z,PIO_LPT ; no, busy wait - LD A,C ; ready, char A for output through data port - OUT ($F0),A ; output char RET - - - -; ------------------------------------ -; ZILOG PIO FUNCTION TABLE ROUTINES -;------------------------------------- -PIO_IN: - LD C,(IY+3) - IN A,(C) - LD E,A - XOR A ; SIGNAL SUCCESS - RET - +; PIO_INITDEV - INITIALIZE DEVICE ; -PIO0INT: -PIO1INT: -PIO2INT: -PIO3INT: -PIO4INT: -PIO5INT: -PIO6INT: -PIO7INT: -PIO8INT: -PIO9INT: - OR $FF ; NZ SET TO INDICATE INT HANDLED - RET +; IF DE = FFFF THEN THE SETUP PARAMETER WORD WILL BE READ FROM THE DEVICE CONFIGURATION +; TABLE POINTED TO BY IY AND THE PIO PORT WILL BE PROGRAMMED BASED ON THAT CONFIGURATION. ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD -; E CONTAINS THE CHARACTER TO OUTPUT -; WE RETREIVE THE CMD PORT ADDRESS AND CALCULATE THE -; DATA PORT AND WRITE THE CHARACTER TO IT. +; OTHERWISE THE PIO PORT WILL BE PROGRAMMED BY THE SETUP PARAMETER WORD IN DE AND THIS +; WILL BE SAVED IN THE DEVICE CONFIGURATION TABLE POINTED TO BY IY. ; -PIO_OUT: - LD C,(IY+3) - OUT (C),E - XOR A ; SIGNAL SUCCESS - RET - - LD C,(IY+3) ; GET PORT - LD A,(IY+4) ; GET MODE (B7B6) +; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT - -PIO_IST: - RET -; -PIO_OST: - RET -; -; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. -; Otherwise use the configuration information in DE to program those settings and save them in the device table -; -; SETUP PARAMETER WORD: -; +-------------------------------+ +-------+-----------+---+-------+ -; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | -; +-------------------------------+ --------------------+-----------+ -; F E D C B A 9 8 7 6 5 4 3 2 1 0 -; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- -; -; -; MSB = BIT MAP USE IN MODE 3 -; MODE B7 B6 = 00 Mode 0 Output -; 01 Mode 1 Input -; 10 Mode 2 Bidir -; 11 Mode 3 Bit Mode -; CHIP CHANNEL B5 B4 B3 001 Channel 1 -; 010 Channel 2 -; 100 Channel 3 -; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED -; = 1 IS ALLOCATED -; -; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 -; 01 IVT_PIO1 -; 10 IVT_PIO2 -; 11 IVT_PIO3 PIO_INITDEV: ; TEST FOR -1 (FFFF) 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,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG -; - ; LOAD EXISTING CONFIG TO REINIT +PIO_INITDEV0: + ; LOAD EXISTING CONFIG (DCW) TO REINIT LD E,(IY+4) ; LOW BYTE LD D,(IY+5) ; HIGH BYTE ; -PIO_INITDEV1: - ; WHICH DEVICE TYPE? +PIO_INITDEV1: ; WHICH DEVICE TYPE? LD A,(IY+1) CP PIO_ZPIO - JR Z,SET_PIO + JR Z,SETPIO0 CP PIO_8255 - JR Z,SET_8255 + JP Z,SET_8255 CP PIO_PORT - JR Z,SET_PORT -PIO_BAD:OR $FF ; UNKNOWN DEVICE + JP Z,SET_PORT +BAD_SET:OR $FF ; UNKNOWN DEVICE RET -SET_PORT: - ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT - LD C,(IY+3) - OUT (C),A - XOR A +SETPIO0:LD A,E ; GET MODE + AND 11000000B ; BITS (B7B6) + CP 10000000B ; IS IT BIDIR? + JR NZ,SETPIO1 + LD A,(IY+2) ; GET CHANNEL + OR A + JR NZ,BAD_SET ; CAN'T DO ON CH1 + + ; VALIDATE INTERRUPT REQUEST + ; GRANT INTERRUPT IF THERE IS A FREE INTERRUPT + ; GRANT INTERRUPT IF AN INTERRUPT IS ALREADY ALLOCATED TO THIS UNIT + +SETPIO1:PUSH AF ;D + LD A,'[' ;D + CALL COUT ;D + LD A,(IY) ;D + CALL PRTHEXBYTE ;D + LD A,']' ;D + CALL COUT ;D + POP AF ;D + + BIT 2,E ; SKIP IF WE ARE NOT REQUESTING + JP Z,SETPIO2 ; AN INTERRUPT + + PRTS("[INTREQ]$") ;D + +; LD A,(IY+4) ; GET CURRENT INTERRUPT SETTING +; BIT 2,A ; SKIP IF IT IS ALREADY +; JP NZ,SETPIO2 ; ALLOCATED TO THIS UNIT + + LD A,(INT_ALLOC) ; WE NEED TO ALLOCATE AN + CP INT_ALLOW ; INTERRUPT. DO WE HAVE + JR NC,BAD_SET ; ONE FREE? + + PRTS("[ALLOCINT]$") ;D + + ; WHICH INTERRUPT IS FREE ? + ; SCAN THROUGH THE CFG TABLES + ; AND FIND A FREE ONE + + PUSH AF ; NESTED LOOP + LD DE,CFG_SIZ ; OUTSIDE LOOP IS INTERRUPT + LD B,INT_ALLOW ; INSIDE LOOP IS DEVICE +SETPIOP: LD C,B + DEC C + PUSH BC + LD B,PIO_CNT + LD HL,PIO_CFG+4 +SETPIOX: LD A,(HL) + BIT 2,A ; JUMP TO NEXT DEVICE + JR Z,SETPIOY ; IF NO INTERRUPT ON + AND 00000011B ; THIS DEVICE + + CP C ; IF WE MATCH AN INTERRUPT HERE THEN IT IS NOT FREE. + JR NZ,SETPIOY ; SO EXIT INSIDE LOOP AND TRY NEXT INTERRUPT + + XOR A ; WE MATCH INT 0 - IF WE ARE CHECKING FOR IT THEN + OR C ; WE REGARD IS AS FREE. + JR NZ,SETPIOZ + +SETPIOY: ADD HL,DE + DJNZ SETPIOX + + JR SETPIOQ ; WE GET HERE IF THE CURRENT INTERRUPT + ; WAS NOT MATCHED SO IT IS FREE +SETPIOZ: POP BC + DJNZ SETPIOP + POP AF + + PRTS("[NONEFREE]$") RET + +SETPIOQ:PUSH AF ; AVAILABLE INTERRUPT IS IN C + PRTS("[FREE]=$") + LD A,C + CALL PRTHEXBYTE + POP AF + + POP AF + POP AF + +SETPIOR:LD HL,INT_ALLOC ; INCREASE THE COUNT + INC (HL) ; OF USED INTERRUPTS + LD A,(HL) + +; LD A,(IY) ; IS THIS UNIT +; INC A ; UNITIALIZED? +; JR Z,SETPIO6 + + LD A,(IY+4) ; IT IS UNITIALIZED SO + OR C ; SAVE THE ALLOCATES + LD (IY+4),A ; INTERRUPT +; +; FOR THIS DEVICE AND INTERRUPT, UPDATE THE CONFIG TABLE FOR THIS DEVICE. +; PIO_IN, PIO_OUT, PIO_IST, PIO_OST ENTRIES NEED TO BE REDIRECTED. +; INTERRUPT VECTOR NEEDS TO BE UPDATED +; + LD A,(IY+0) + LD HL,0 + ; SETUP PIO INTERRUPT VECTOR IN IVT + LD HL,HBX_IV09+1 + + CALL SPK_BEEP +; +SETPIO6:RET + + ; EXIT WITH FREE INTERRUPT IN C + + LD A,C + LD (INT_ALLOC),A + + LD A,E + AND 11000000B + OR 00000100B + OR C + LD E,A + LD (IY+5),A +; + ; TODO: DEALLOCATE AN INTERRUPT +; +; LD A,(INT_ALLOC) +; DEC A +; LD (INT_ALLOC),A ; -SET_PIO: - ; DEVICE TYPE IS Z80 PIO SO DETERMINE MODE TO SET - ; BIDIR MODE CAN ONLY BE SET ON CHANNEL 0 - ; BITCTRL MODE REQUIRES A I/O DIRECTION TO BE SET +SETPIO2: + +; DE CONTAINS THE MODE IF INTERRUPT ROUTINE SKIPPED + + PRTS("[NOINTREQ]$") ;D + +; LD A,(IY+4) + LD A,E ; GET MODE AND CREATE COMMAND + AND 11000000B ; $B0 + OR 00001111B ; $0F + LD C,(IY+3) ; GET DATA PORT INC C ; POINT TO CMD - INC C ; PORT - LD A,(IY+4) ; GET MODE (B7B6) - AND 11010000B ; KEEP MODE & CHANNEL - CP 10010000B ; SET CH1 & BIDIR - JR Z,PIO_BAD ; CAN'T DO ON CH1 - AND 11000000B ; $B0 - OR 00001111B ; $0F + INC C ; PORT OUT (C),A ; SET MODE CP (M_BitCtrl | $0F) ; IF MODE 3 - JR NZ,SET_NM3 - LD A,(IY+5) ; SET I/O + JR NZ,SETPIO3 + LD A,(IY+5) ; SET I/O DIRECTION OUT (C),A ; FOR MODE 3 -SET_NM3:; INTERUPT HANDLING - LD A,(IY+4) ; CHECK IF INTERRUPT - BIT 2,A ; REQUEST BIT SET - JR Z,NOINT1 - - LD A,(INT_ALLOC) ; DO WE HAVE AN - CP INT_ALLOW+1 ; INTERRUPT FREE? - JR NC,BADSET - - INC A ; ONE INTERRUPT - LD (INT_ALLOC),A ; USED - ; THE TRICKY BIT - SETUP THE RIGHT INTERRUPT VECTOR +SETPIO3:; INTERUPT HANDLING -NOINT1: LD A,00000111B ; $07 - OUT (C),A ; NO INTERRUPTS - DEC C - DEC C - LD A,$FF ; DEFAULT VALUE + JP SETPIO4 + + ; SETUP THE INTERRUPT VECTOR + + LD A,E + AND 00000011B +; DEC A ; INDEX INTO THE + ADD A,A ; THE VECTOR TABLE + ADD A,A ; + LD C,A + LD B,0 + LD HL,HBX_IV09+1 + ADD HL,BC ; GET THE ADDRESS OF + PUSH DE + LD D,(HL) ; THAT INTERRUPT + INC HL ; HANDLER + LD E,(HL) + LD HL,0 ;HBX_IVT+IVT_PIO0 ; POPULATE THE + LD A,L ; GET LOW BYTE OF IVT ADDRESS + ADD HL,BC ; INTERRUPT TABLE + LD (HL),D ; WITH THE INTERRUPT + INC HL ; HANDLER ADDRESS FOR + LD (HL),E ; THIS UNIT + POP DE + LD HL,INT_ALLOC + LD C,(HL) + LD B,0 + LD HL,PRTTAB-1 ; SAVE THE DATA + ADD HL,BC ; PORT FOR EACH INTERRUPT + LD C,(IY+3) + LD (HL),C + + INC C ; POINT TO CMD PORT + INC C + DI ; SET THE VECTOR ADDRESS OUT (C),A + +; LD A,10000011B ; ENABLE INTERRUPTS ON + OUT (C),A ; THIS UNIT + EI +; JR GUD_SET +; +SETPIO4:LD A,00000111B ; $07 + OUT (C),A ; NO INTERRUPTS +; +; SUCCESSFULL SO SAVE DEVICE CONFIGURATION WORD (DCW) +; +GUD_SET:LD (IY+4),E ; LOW BYTE + LD (IY+5),D ; HIGH BYTE +; +; UPDATE THE DEVICE TABLE WITH THE ADDRESSES FOR THE CORRECT ROUTINE. +; + LD A,E + AND 00000111B + LD HL,INTMATRIX ; POINT TO EITHER THE INTERRUPT + JR NZ, USEIM + LD HL,POLMATRIX ; MATRIX OR THE POLLED MATRIX +USEIM: PUSH HL + + PUSH IY ; CALCULATE THE DESTINATION + POP HL ; ADDRESS IN THE PIO_CFG TABLE + LD BC,8 ; FOR THE FOUR ADDESSES TO BE + ADD HL,BC ; COPIED TO + +; LD B,0 ; 00000000 CALCULATE THE SOURCE ADDRESS + LD C,E ; XX?????? FROM THE MATRIX. EACH ENTRY + SRL C ; 0XX????? IN THE MATRIX IS 8 BYTES SO + SRL C ; 00XX???? SOURCE = MATRIX BASE + (8 * MODE) + SRL C ; 000XX??? + POP DE ; LOAD THE MATRIX BASE +; LD DE,POLMATRIX + EX DE,HL + ADD HL,BC ; HL = SOURCE + + LD C,8 ; COPY 8 BYTES + LDIR + +; PUSH IY +; POP DE +; CALL DUMP_BUFFER + XOR A RET -BADSET: LD A,$FF - RET -SET_8255: - RET +PRTTAB: .DB 0 + .DB 0 + .DB 0 + .DB 0 +; +;----------------------------------------------------------------------------- +; +; INPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +#DEFINE PIOMIVT(PIOIN,PIOIST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN WITH ERROR IF THERE IS \ +#DEFCONT ; ALREADY A CHARACTER IN BUFFER \ +#DEFCONT ;\ +#DEFCONT ; OTHERWISE CHANGE THE STATUS TO \ +#DEFCONT ; SHOW THERE IS ONE CHARACTER IN \ +#DEFCONT ; THE BUFFER AND READ IT IN AND \ +#DEFCONT ; AND STORE IT.RETURN GOOD STATUS.\ +#DEFCONT ;\ +#DEFCONT \ LD A,(_CIST) +#DEFCONT \ OR A +#DEFCONT \ JR NZ,_OVFL +#DEFCONT \ LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ LD A,1 +#DEFCONT \ LD (_CIST),A +#DEFCONT \ IN A,(C) +#DEFCONT \ LD (_CICH),A +#DEFCONT \ OR $FF +#DEFCONT \ RET +#DEFCONT \_OVFL:XOR A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT \PIOIN:CALL PIOIST +#DEFCONT \ JR Z,PIOIN +#DEFCONT \ LD A,(_CICH) +#DEFCONT \ LD E,A +#DEFCONT \ XOR A +#DEFCONT \ LD (_CIST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; If THERE A CHARACTER \ +#DEFCONT ; AVAILABLE? RETURN NUMBER \ +#DEFCONT ; IN A - 0 OR 1 \ +#DEFCONT ;\ +#DEFCONT \PIOIST:LD A,(_CIST) +#DEFCONT \ AND 00000001B +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; CIST : 01 = CHARACTER READY ELSE NOT READY \ +#DEFCONT ; CISH : CHARACTER STORED BY INTERRUPT \ +#DEFCONT ;\ +#DEFCONT \_CIST .DB 00 +#DEFCONT \_CICH .DB 00 +; +PIOIVT0:.MODULE PIOIVT0 +PIOMIVT(PIO0IN,PI0_IST,PRTTAB+0) +PIOIVT1:.MODULE PIOIVT1 +PIOMIVT(PIO1IN,PI1_IST,PRTTAB+1) +PIOIVT2:.MODULE PIOIVT2 +PIOMIVT(PIO2IN,PI2_IST,PRTTAB+2) +PIOIVT3:.MODULE PIOIVT3 +PIOMIVT(PIO3IN,PI3_IST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; OUTPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +; AN INTERRUPT IS GENERATED WHEN THE RECEIVING DEVICE CAN ACCEPT A CHARACTER +; +#DEFINE PIOMOVT(PIOOUT,PIOOST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTER (COST = 00) \ +#DEFCONT ;\ +#DEFCONT ; IF ZERO CHARACTERS READY +#DEFCONT ; (COST = 01) CHANGE STATUS TO \ +#DEFCONT ; WAITING FOR CHARACTER (COST 00) \ +#DEFCONT ;\ +#DEFCONT ; IF A CHARACTER IS READY THEN \ +#DEFCONT ; OUTPUT AND CHANGE STATUS TO \ +#DEFCONT ; ZERO CHARACTERS READY \ +#DEFCONT ;\ +#DEFCONT \ LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ RET M +#DEFCONT \ JR Z,_WFC +#DEFCONT \ LD A,(_COCH) +#DEFCONT \ LD E,A +#DEFCONT \_ONOW:LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ OUT (C),E +#DEFCONT \ LD A,1 +#DEFCONT \_WFC: LD (_COST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; WAIT FOR SPACE FOR THE CHARACTER\ +#DEFCONT ; IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTRE THEN OUTPUT IT NOW \ +#DEFCONT ; OTHERWISE STORE IT UNTIL THE \ +#DEFCONT ; INTERRUPT CALLS FOR IT \ +#DEFCONT ;\ +#DEFCONT \PIOOUT:LD A,(_COST) +#DEFCONT \ CP 2 +#DEFCONT \ JR C,_ONOW +#DEFCONT \ LD A,E +#DEFCONT \ LD (_COCH),A +#DEFCONT \ LD A,2 +#DEFCONT \ LD (_COST),A +#DEFCONT \ JR PIOOUT +#DEFCONT ;\ +#DEFCONT ; RETURN WITH NUMBER OF \ +#DEFCONT ; CHARACTERS AVAILABLE 0 or 1 \ +#DEFCONT ;\ +#DEFCONT \PIOOST:LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ DEC A +#DEFCONT \ RET Z +#DEFCONT \ LD A,1 +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; COST : 00 WAITING FOR CHARACTER\ +#DEFCONT ; 01 ZERO CHARACTERS READY\ +#DEFCONT ; 02 ONE CHARACTER READY \ +#DEFCONT ; COCH : CHARACTER TO OUTPUT \ +#DEFCONT ;\ +#DEFCONT \_COST .DB 01 +#DEFCONT \_COCH .DB 00 +; +PIOOVT0:.MODULE PIOOVT0 +PIOMOVT(PIO0OUT,PI0_OST,PRTTAB+0) +PIOOVT1:.MODULE PIOOVT1 +PIOMOVT(PIO1OUT,PI1_OST,PRTTAB+1) +PIOOVT2:.MODULE PIOOVT2 +PIOMOVT(PIO2OUT,PI2_OST,PRTTAB+2) +PIOOVT3:.MODULE PIOOVT3 +PIOMOVT(PIO3OUT,PI3_OST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT OUTPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS RETURN ERROR, CHARACTER RETURNED IS UNDEFINED. +; OUTPUT WILL ALWAYS RETURN SUCCESS +; INPUT-STATUS WILL ALWAYS RETURN 0 CHARACTERS IN BUFFER. +; OUTPUT-STATUS WILL ALWAYS RETURN 1 CHARACTER SPACE IN BUFFER. -SET_BYE: - XOR A ; SIGNAL SUCCESS +PIOSHO_IN: + LD A,1 RET -; -PIO_ZP0: -PIO_ZP1: -PIO_4P0: -PIO_4P1: -PIO_4P2: -PIO_4P3: -PIO_4P4: -PIO_4P5: -PIO_4P6: -PIO_4P7:OR $FF ; NZ SET TO INDICATE INT HANDLED +; +PIOSHO_OUT: + LD C,(IY+3) + OUT (C),E + XOR A + RET +; +PIOSHO_IST: XOR A + RET +; +PIOSH_OST: + LD A,1 + RET +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT INPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS A CHARACTER AND SUCCESS. +; OUTPUT WILL ALWAYS RETURN FAILURE +; INPUT STATUS WILL ALWAYS RETURN 1 CHARACTER IN BUFFER. +;OUTPUT-STATUS WILL ALWAYS RETURN 0 CHARACTER SPACE IN BUFFER. +; +PIOSHI_IN: + LD C,(IY+3) + IN A,(C) + LD E,A + XOR A + RET +; +PIOSHI_OUT: + LD A,1 + RET +; +PIOSH_IST: + LD A,1 + RET +; +PIOSHI_OST: + XOR A RET ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD -; WE GET AND RETURN THE CONFIGURATION WORD IN DE +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE ; PIO_QUERY: PPI_QUERY: @@ -367,18 +706,37 @@ PPI_QUERY: XOR A ; SIGNAL SUCCESS RET ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD -; FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE -; INDICATES PARALLEL PORT IF 1 SO WE SET IT. -; +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE +; INDICATES PARALLEL PORT IF 1 SO WE SET IT. COMMON TO ALL PORTS +; PIO_DEVICE: PPI_DEVICE: LD D,CIODEV_PIO ; D := DEVICE TYPE LD E,(IY) ; E := PHYSICAL UNIT LD C,$40 ; C := ATTRIBUTE XOR A ; SIGNAL SUCCESS - RET + RET +; +INTMATRIX: + .DW PIO0IN, PIO0OUT, PI0_IST, PI0_OST + .DW PIO1IN, PIO1OUT, PI1_IST, PI1_OST + .DW PIO2IN, PIO2OUT, PI2_IST, PI2_OST + .DW PIO3IN, PIO3OUT, PI3_IST, PI3_OST +POLMATRIX: + .DW PIOSHO_IN, PIOSHO_OUT, PIOSHO_IST, PIOSH_OST ; OUTPUT + .DW PIOSHI_IN, PIOSHI_OUT, PIOSH_IST, PIOSHI_OST ; INPUT + .DW 0,0,0,0 ; BIDIR + .DW 0,0,0,0 ; BIT MODE +SET_8255: + RET +; +SET_BYE: + XOR A ; SIGNAL SUCCESS + RET +; ; ------------------------------------ ; i8255 FUNCTION TABLE ROUTINES ;------------------------------------- @@ -429,7 +787,7 @@ PIO_PRTCFG: CALL WRITESTR ; PRINT IT ; ; ALL DONE IF NO PIO WAS DETECTED - LD A,(IY+1) ; GET SIO TYPE BYTE + LD A,(IY+1) ; GET PIO TYPE BYTE OR A ; SET FLAGS RET Z ; IF ZERO, NOT PRESENT ; @@ -438,7 +796,14 @@ PIO_PRTCFG: LD D,(IY+5) ; ... WORD TO DE CALL PS_PRTPC0 ; PRINT CONFIG ; - XOR A + LD A,(IY+4) ; PRINT + BIT 2,A ; ALLOCATED + JR Z,NOINT ; INTERRUPT + PRTS("/i$") + LD A,(IY+4) + AND 00000011B + CALL PRTDECB +NOINT: XOR A RET ; ; WORKING VARIABLES @@ -460,237 +825,178 @@ PIO_STR_PORT .DB "IO Port$" ; ; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS ; -#DEFINE DEFPIO(MPIO_TYPE,MPIO_BASE,MPIO_CH0,MPIO_CH1,MPIO_CH0X,MPIO_CH1X,MPIO_FT0,MPIO_FT1,MPIO_IN0,MPIO_IN1) \ +; 32 BYTE DATA STRUCTURE FOR EACH PORT +; +; .DB 0 ; IY+0 CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) +; .DB 0 ; IY+1 PIO TYPE (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+2 PIO CHANNEL (SET AT ASSEMBLY, FIXED) +; .DB PIOBASE+2 ; IY+3 BASE DATA PORT (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+4 SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) +; .DB 0 ; IY+5 SPW - MODE, INTERRUPT (SET AT ASSEMBLY, SET WITH INIT) +; .DW 0 ; IY+6/7 FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) +; .DW PIO_IN ; IY+8 ADDR FOR DEVICE INPUT (SET WITH INIT) +; .DW PIO_OUT ; IY+10 ADDR FOR DEVICE OUTPUT (SET WITH INIT) +; .DW PIO_IST ; IY+12 ADDR FOR DEVICE INPUT STATUS (SET WITH INIT) +; .DW PIO_OST ; IY+14 ADDR FOR DEVICE OUTPUT STATUS (SET WITH INIT) +; .DW PIO_INITDEV ; IY+16 ADDR FOR INITIALIZE DEVICE ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_QUERY ; IY+18 ADDR FOR QUERY DEVICE RECORD ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_DEVICE ; IY+20 ADDR FOR DEVICE TYPE ROUTINE (SET AT ASSEMBLY, FIXED) +; .FILL 10 +; +; SETUP PARAMETER WORD: +; +; +-------------------------------+ +-------+-----------+---+-------+ +; | BIT CONTROL | | MODE | | A | INT | +; +-------------------------------+ --------------------+-----------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- +; +; +; MSB = BIT CONTROL MAP USE IN MODE 3 +; +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; +; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED +; = 1 IS ALLOCATED +; +; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 +; 01 IVT_PIO1 +; 10 IVT_PIO2 +; 11 IVT_PIO3 +; +#DEFINE DEFPIO(MPIOBASE,MPIOCH0,MPIOCH1,MPIOCH0X,MPIOCH1X,MPIOIN0,MPIOIN1) \ #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB PIO_ZPIO #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_BASE -#DEFCONT \ .DB (MPIO_CH0 | 00001000B | MPIO_IN0) -#DEFCONT \ .DB MPIO_CH0X -#DEFCONT \ .DW MPIO_FT0 +#DEFCONT \ .DB MPIOBASE +#DEFCONT \ .DB (MPIOCH0|MPIOIN0) +#DEFCONT \ .DB MPIOCH0X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 2 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB PIO_ZPIO #DEFCONT \ .DB 1 -#DEFCONT \ .DB MPIO_BASE+1 -#DEFCONT \ .DB (MPIO_CH1 | 00010000B | MPIO_IN1) -#DEFCONT \ .DB MPIO_CH1X -#DEFCONT \ .DW MPIO_FT1 +#DEFCONT \ .DB MPIOBASE+1 +#DEFCONT \ .DB (MPIOCH1|MPIOIN1) +#DEFCONT \ .DB MPIOCH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 2 ; ; i8255 PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. THREE PORTS ; -#DEFINE DEFPPI(MPPI_TYPE,MPPI_BASE,MPPI_CH1,MPPI_CH2,MPPI_CH3,MPPI_CH1X,MPPI_CH2X,MPPI_CH3X) \ +#DEFINE DEFPPI(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_BASE+0 -#DEFCONT \ .DB (MPPI_CH1 | 00001000B) -#DEFCONT \ .DB MPPI_CH1X -#DEFCONT \ .DW +#DEFCONT \ .DB MPPIBASE +#DEFCONT \ .DB (MPPICH1|00001000B) +#DEFCONT \ .DB MPPICH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 1 -#DEFCONT \ .DB MPPI_BASE+2 -#DEFCONT \ .DB (MPPI_CH2 | 00010000B) -#DEFCONT \ .DB MPPI_CH2X +#DEFCONT \ .DB MPPIBASE+2 +#DEFCONT \ .DB (MPPICH2|00010000B) +#DEFCONT \ .DB MPPICH2X #DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 2 -#DEFCONT \ .DB MPPI_BASE+4 -#DEFCONT \ .DB (MPPI_CH3 | 00100000B) -#DEFCONT \ .DB MPPI_CH3X +#DEFCONT \ .DB MPPIBASE+4 +#DEFCONT \ .DB (MPPICH3|00100000B) +#DEFCONT \ .DB MPPICH3X #DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 2 ; ; HERE WE ACTUALLY DEFINE THE HARDWARE THAT THE HBIOS CAN ACCESS ; THE INIT ROUTINES READ AND SET THE INITIAL MODES FROM THIS INFO ; PIO_CFG: - -#IF PIO_ZP -DEFPIO(PIO_ZPIO,PIOZBASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) -DEFPIO(PIO_ZPIO,PIOZBASE+4,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) -#ENDIF +; #IF PIO_4P -DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO8FT,PIO9FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO10FT,PIO11FT,INT_N,INT_N) +DEFPIO(PIO4BASE+0,M_Output,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+4,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,INT_N,INT_N) +#ENDIF +#IF PIO_ZP +DEFPIO(PIOZBASE+0,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIOZBASE+4,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) #ENDIF ; PPI_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) #IF PPI_SBC -DEFPPI(PIO_8255,PPIBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) +DEFPPI(PPIBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) #ENDIF ; -; ; PIO CHANNEL A -; .DB 0 ; CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) -; .DB 0 ; PIO TYPE (SET AT ASSEMBLY, FIXED) -; .DB 0 ; FREE -; .DB PIOBASE+2 ; BASE DATA PORT (DATA PORT) (SET AT ASSEMBLY, FIXED) -; .DB 0 ; SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) - .DB 0 ; SPW - MODE, CHANNEL (SET AT ASSEMBLY, SET WITH INIT, CHANNEL FIXED) -; .DW 0 ; FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) - -PIO_CNT .EQU ($ - PIO_CFG) / 8 +PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ ; - -; DRIVER FUNCTION TABLE FOR Z80 PIO's -; EACH PIO NEEDS A FUNCTION TABLE -; ECB-ZP : PIO0FT-PIO3FT -; ECB-4P : PIO4FT-PIO11FT - -PIO_FNTBL: +;------------------------------------------------------------------- +; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; C IS THE UNIT NUMBER +;------------------------------------------------------------------- ; -#IF PIO_ZP -PIO0FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO0FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO1FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO1FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO2FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO2FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO3FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO3FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF +;PIO_INITUNIT: +; LD A,C ; SET THE UNIT NUMBER +; LD (IY),A ; -#IF PIO_4P -PIO4FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO4FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO5FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO5FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO6FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO6FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO7FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO7FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO8FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO8FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO9FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO9FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO10FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO10FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO11FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO11FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF +; LD DE,-1 ; LEAVE CONFIG ALONE +; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN ; -; DRIVER FUNCTION TABLE FOR i8255's -; -PPI_FNTBL: - .DW PPI_IN - .DW PPI_OUT - .DW PPI_IST - .DW PPI_OST - .DW PPI_INITDEV - .DW PPI_QUERY - .DW PPI_DEVICE -#IF (($ - PPI_FNTBL) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PPI FUNCTION TABLE ***\n" -#ENDIF +PIO_INIT: +; CALL SPK_BEEP + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + +; LD A,C ; PHYSICAL UNIT TO A +; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) +; RLCA ; ... +; RLCA ; ... TO GET OFFSET INTO CFG TABLE +; RLCA +;; RLCA +; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE +; PUSH AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; POP AF +; CALL ADDHLA ; HL := ENTRY ADDRESS +; PUSH HL ; COPY CFG DATA PTR +; POP IY ; ... TO IY + + CALL IDXCFG + + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + +; PUSH DE +; LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL +; CALL PIO_INITDEV ; BASED ON DPW +; POP DE + + POP BC ; RESTORE LOOP CONTROL + INC C ; NEXT UNIT + DJNZ PIO_INIT1 ; LOOP TILL DONE +; + XOR A ; SIGNAL SUCCESS + RET ; DONE ; -; DRIVER FUNCTION TABLE FOR I/O PORT -; -PRT_FNTBL: - .DW PPI_IN - .DW PPI_OUT - .DW PPI_IST - .DW PPI_OST - .DW PPI_INITDEV - .DW PPI_QUERY - .DW PPI_DEVICE -#IF (($ - PRT_FNTBL) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PPI FUNCTION TABLE ***\n" -#ENDIF \ No newline at end of file +SET_PORT: + ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT + LD C,(IY+3) + OUT (C),A + XOR A + RET diff --git a/Source/HBIOS/plt_sbc.inc b/Source/HBIOS/plt_sbc.inc index 008eac4e..ed472aae 100644 --- a/Source/HBIOS/plt_sbc.inc +++ b/Source/HBIOS/plt_sbc.inc @@ -20,4 +20,7 @@ MPGENA .EQU SBC_BASE + $1C ; PAGING ENABLE REGISTER - BIT 0 = 1 (WRITE ONLY) RTC .EQU SBC_BASE + $10 ; ADDRESS OF RTC LATCH AND INPUT PORT PPIBASE .EQU SBC_BASE + $00 ; PPI 82C55 I/O IS DECODED TO PORT 60-67 PIOZBASE .EQU $88 ; ZILOG PERIPHERALS DEFAULT PIO DEFAULT -PIO4BASE .EQU $90 ; ECB-4PIO DEFAULT PIO DEFAULT \ No newline at end of file +PIO4BASE .EQU $90 ; ECB-4PIO DEFAULT PIO DEFAULT +; +; +FIFO_BASE .EQU $0C ; ECB USB-FIFO DEFAULT PORT diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 35dad128..bf4a9323 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -269,6 +269,14 @@ IVT_PIO3 .EQU 24 IVT_SER2 .EQU 26 IVT_SER3 .EQU 28 ; +; +; DEVICE DRIVER TO BE INITIALIZED FIRST. FIRST CIO DRIVER, UNIT 0 INITIALIZED BECOMES PRIMARY CONSOLE. +; IS AN INDEX INTO THE ENABLED INITIALIZATION DRIVER LIST i.e. ASCI, UART, SIO, ACIA, PIO, UF ETC. +; EXAMPLE: IF ONLY UART, SIO AND PIO ARE ENABLE AND THE SIO IS DESIRED AS THE PRIMARY CONSOLE, +; SET FORCECON TO 2 IN YOUR CUSTOM CONFIGURATION FILE i.e. "FORCECON: .SET 2" +; +FORCECON .EQU 0 ; DEFAULT IS TO FOLLOW NORMAL SEQUENCE +; #INCLUDE "build.inc" ; INCLUDE USER CONFIG, ADD VARIANT, TIMESTAMP, & ROMSIZE ; #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RCZ180)) diff --git a/Source/HBIOS/usbfifo.asm b/Source/HBIOS/usbfifo.asm new file mode 100644 index 00000000..cf96aa68 --- /dev/null +++ b/Source/HBIOS/usbfifo.asm @@ -0,0 +1,181 @@ +;================================================================================================== +; ECB USB-FIFO DRIVER FOR WILL SOWERBUTTS ADAFRUIT BASED FT232H ECB-FIFO BOARD +; REFER https://www.retrobrewcomputers.org/doku.php?id=boards:ecb:usb-fifo:start +; PHIL SUMMERS (b1ackmai1er) +;================================================================================================== +; +; BASE PORT IS SET IN PLT_SBC.INC +; INTERRUPTS ARE NOT USED. +; ONLY ONE BOARD SUPPORTED. +; +; HBIOS CALLS: +; +; UF_PREINIT SETUP THE DISPATCH TABLE ENTRY AND INITIALIZE HARDWARE +; UF_INIT ANNOUNCE DEVICE DESCRIPTION AND PORT +; +FIFO_DATA .EQU (FIFO_BASE+0) ; READ/WRITE DATA +FIFO_STATUS .EQU (FIFO_BASE+1) ; READ/WRITE STATUS +FIFO_SEND_IMM .EQU (FIFO_BASE+2) ; WRITE PORT TO FORCE BUFFER FLUSH +FIFO_BUFFER .EQU FALSE ; OPTION TO BUFFER OUTPUT FOR 17ms +; +UF_USB_ACTIVE .DB 0 ; USB CABLE CONNECTED STATUS FLAG +; +; DEVICE DESCRIPTION TABLE +; +UF_CFG: .DW SER_9600_8N1 ; DUMMY CONFIGURATION +; +; SETUP THE DISPATCH TABLE ENTRY AND INITIALIZE HARDWARE +; +UF_PREINIT: + LD HL,UF_CFG ; POINT TO START OF CFG TABLE + PUSH HL ; COPY CFG DATA PTR + PUSH HL + POP IY ; ... TO IY + CALL UF_INITUNIT ; HAND OFF TO GENERIC INIT CODE + LD (UF_USB_ACTIVE),A ; SAVE USB CONNECTION STATUS + POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE +; JR Z,UF_FAIL ; EXIT IF NO USB CONNECTION + LD BC,UF_FNTBL ; BC := FUNCTION TABLE ADDRESS + CALL CIO_ADDENT ; ADD ENTRY IF FOUND, BC:DE + XOR A ; SIGNAL SUCCESS +UF_FAIL: + RET ; AND RETURN +; +; INITIALIZATION ROUTINE +; +UF_INITUNIT: + CALL UF_DETECT ; DETERMINE TYPE + OR A ; SET FLAGS + RET Z ; ABORT IF NOTHING THERE + + ; SET DEFAULT CONFIG + LD DE,-1 ; LEAVE CONFIG ALONE + JR UF_INITDEV ; IMPLEMENT IT AND RETURN +; +; ANNOUNCE DEVICE DESCRIPTION AND PORT +; +UF_INIT: + CALL NEWLINE ; PRINT DEVICE + PRTS("USB-FIFO: $") + PRTS("IO=0x$") + LD A,FIFO_BASE ; PRINT PORT + CALL PRTHEXBYTE + LD A,(UF_USB_ACTIVE) ; PRINT CABLE STATUS + OR A + RET NZ + PRTS(" No Cable$") + RET +; +; INPUT A CHARACTER AND RETURN IT IN E +; +UF_IN: + CALL UF_IST ; CHAR WAITING? + JR Z,UF_IN ; LOOP IF NOT + LD C,FIFO_DATA ; C := INPUT PORT + IN E,(C) ; GET CHAR + XOR A ; SIGNAL SUCCESS + RET +; +; OUTPUT THE CHARACTER IN E +; +UF_OUT: + CALL UF_OST ; READY FOR CHAR? + JR Z,UF_OUT ; LOOP IF NOT + LD C,FIFO_DATA + OUT (C),E ; WRITE TO FIFO +#IF (FIFO_BUFFER) + OUT (FIFO_SEND_IMM),A ; SEND IMMEDIATE +#ENDIF + XOR A ; SIGNAL SUCCESS + RET +; +; INPUT STATUS - CAN WE SEND A CHARACTER +; +UF_IST: + IN A,(FIFO_STATUS) ; IS THE QUEUE EMPTY? + RLCA + CPL + AND 00000001B + RET +; +; OUTPUT STATUS - CAN WE OUTPUT A CHARACTER +; +UF_OST: + IN A,(FIFO_STATUS) ; IS THE SEND BUFFER FULL? + CPL + AND 00000001B + RET +; +; INITIALIZATION THE SETUP PARAMETER WORD AND INITIALIZE DEVICE +; SAVE NEW SPW IF NOT A RE-INIT. ALWAYS INITIALIZE DEVICE. +; SPW IS NOT VALIDATED BUT IT IS NOT USED FOR ANYTHING. +; +UF_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,UF_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG +; + ; GET CURRENT PSW. WE ALWAYS RESAVE AT END + LD E,(IY+0) ; LOW BYTE + LD D,(IY+1) ; HIGH BYTE +; +UF_INITDEV1: + XOR A ; INTERRUPTS OFF + OUT (FIFO_STATUS),A +; +UF_FLUSH: + IN A,(FIFO_STATUS) ; IS THERE ANY DATA + RLCA ; IN THE BUFFER ? + JR C,UFBUFEMPTY ; EXIT IF EMPTY +; + IN A,(FIFO_DATA) ; CLEAR BUFFER BY READING + JR UF_FLUSH ; ALL THE DATA +UFBUFEMPTY: + LD (IY+0),E ; SAVE LOW WORD + LD (IY+1),D ; SAVE HI WORD + RET ; NZ STATUS HERE INDICATES FAIL. +; +; USB-FIFO WILL APPEAR AS A SERIAL DEVICE AT DEFAULT SERIAL MODE +; +UF_QUERY: + LD E,(IY+0) ; FIRST CONFIG BYTE TO E + LD D,(IY+1) ; SECOND CONFIG BYTE TO D + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; USB-FIFO WILL APPEAR AS A SERIAL DEVICE +; +UF_DEVICE: + LD D,CIODEV_SIO ; 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 + RET +; +; USB-FIFO DETECTION ROUTINE +; +UF_DETECT: + IN A,(FIFO_STATUS) + AND 10000001B + SUB 10000001B ; A=0 CABLE DISCONNECTED + RET Z + LD A,1 ; A=1 CABLE CONNECTED + RET +; +; DRIVER FUNCTION TABLE +; +UF_FNTBL: + .DW UF_IN + .DW UF_OUT + .DW UF_IST + .DW UF_OST + .DW UF_INITDEV + .DW UF_QUERY + .DW UF_DEVICE +#IF (($ - UF_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID USB-FIFO FUNCTION TABLE ***\n" +#ENDIF +;