diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index c0b466ee..71983d85 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -179,6 +179,8 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index 1ac317dc..022236ca 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -221,6 +221,8 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index a507dee1..8e17d028 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -286,6 +286,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_mbc.asm b/Source/HBIOS/cfg_mbc.asm index 2824bd83..e17de8c3 100644 --- a/Source/HBIOS/cfg_mbc.asm +++ b/Source/HBIOS/cfg_mbc.asm @@ -218,6 +218,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU TRUE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 1a4910bd..14f9a8f2 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -219,6 +219,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index a867f64b..070298a6 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -217,6 +217,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index d01e14e6..d9306673 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -233,6 +233,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 480f6724..65214adc 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -249,6 +249,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 19fbb10c..00e56501 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -238,6 +238,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 95ee53ad..f55d0b5d 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -218,6 +218,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO4BASE .EQU $90 ; PIO: PIO REGISTERS BASE ADR FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 6505fad7..3e4bdd4e 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -228,6 +228,11 @@ PPPENABLE .EQU FALSE ; PPP: ENABLE ZETA PARALLEL PORT PROPELLER BOARD DRIVER (P ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 6deb725a..198a5985 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -162,6 +162,11 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP +PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR +PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 9778f105..42970e1b 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -173,6 +173,8 @@ PPPCONENABLE .EQU TRUE ; PPP: ENABLE PPP DRIVER VIDEO/KBD SUPPORT ; HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM) ; +PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM) +; PIO_4P .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB 4P BOARD PIO_ZP .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR ECB ZILOG PERIPHERALS BOARD (PIO.ASM) PIO_SBC .EQU FALSE ; PIO: ENABLE PARALLEL PORT DRIVER FOR 8255 CHIP diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index f6579df9..abb3ae04 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -2825,6 +2825,9 @@ HB_PCINITTBL: #IF (ACIAENABLE) .DW ACIA_PREINIT #ENDIF +#IF (PIOENABLE) + .DW PIO_PREINIT +#ENDIF #IF (PIO_4P | PIO_ZP) .DW PIO_PREINIT #ENDIF @@ -2944,6 +2947,9 @@ HB_INITTBL: #IF (PPPENABLE) .DW PPP_INIT #ENDIF +#IF (PIOENABLE) + .DW PIO_INIT +#ENDIF #IF (PIO_4P | PIO_ZP) .DW PIO_INIT #ENDIF @@ -5897,6 +5903,15 @@ SIZ_SPK .EQU $ - ORG_SPK .ECHO " bytes.\n" #ENDIF ; +#IF (PIOENABLE) +ORG_PIO .EQU $ + #INCLUDE "pio.asm" +SIZ_PIO .EQU $ - ORG_PIO + .ECHO "PIO occupies " + .ECHO SIZ_PIO + .ECHO " bytes.\n" +#ENDIF +; #IF (PIO_4P | PIO_ZP | PIO_SBC) ORG_PIO .EQU $ #INCLUDE "pio.asm" @@ -6747,7 +6762,7 @@ PS_SDPRPCON .TEXT "PRPCON$" PS_SDPPPCON .TEXT "PPPCON$" PS_SDSIO .TEXT "SIO$" PS_SDACIA .TEXT "ACIA$" -PS_SDPIO .TEXT "PORT$" +PS_SDPIO .TEXT "PIO$" PS_SDUF .TEXT "UF$" PS_SDDUART .TEXT "DUART$" PS_SDZ2U .TEXT "Z2U$" diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index f198f25a..90a27864 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -1,776 +1,254 @@ -; PIO driver sets up the parallel port as a subtype of Serial/Char device. ; +;================================================================================================== +; PIO DRIVER (SERIAL PORT) +;================================================================================================== ; -; HBIOS initializes driver by: +; SETUP PARAMETER WORD: +; +-------+---+-------------------+ +---+---+-----------+---+-------+ +; | |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) -- ; -; 1) Calling Pre-initialization +; THIS DRIVER IS JUST A STUB TO DETECT AND INITIALIZE PIO HARDWARE +; IF IT EXISTS. FOR NOW, IT DOES NOT REGISTER ANY OF THE PIO CHANNELS +; AS CHARCTER DEVICE UNITS. ; -; 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) 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 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 to allow 4 interrupts for the PIO driver. All remaining PIO's -; are limited to Bit mode or blind read and write 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 (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 example for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +PIO_NONE .EQU 0 +PIO_PIO .EQU 1 ; -; 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 +PIO0A_CTL .EQU PIO0BASE + $02 +PIO0A_DAT .EQU PIO0BASE + $00 +PIO0B_CTL .EQU PIO0BASE + $03 +PIO0B_DAT .EQU PIO0BASE + $01 ; -PIODEBUG .EQU 1 +#IF (PIOCNT >= 2) ; -M_Output .EQU $00 << 6 -M_Input .EQU $01 << 6 -M_Bidir .EQU $02 << 6 -M_BitCtrl .EQU $03 << 6 -M_BitAllIn .EQU $FF -M_BitAllOut .EQU $00 +PIO1A_CTL .EQU PIO1BASE + $02 +PIO1A_DAT .EQU PIO1BASE + $00 +PIO1B_CTL .EQU PIO1BASE + $03 +PIO1B_DAT .EQU PIO1BASE + $01 ; -PIO_NONE .EQU 0 -PIO_ZPIO .EQU 1 -PIO_8255 .EQU 2 -PIO_PORT .EQU 3 - -; 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 00000100B -INT_ALLOW .EQU 4 -#ELSE -INT_Y .EQU INT_N -INT_ALLOW .EQU 0 #ENDIF ; -INT0 .EQU 00000000B -INT1 .EQU 00000001B -INT2 .EQU 00000010B -INT3 .EQU 00000011B - +PIO_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES +; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN +; DISABLED. ; -; 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. + CALL PIO_PROBE ; PROBE FOR CHIPS ; -; 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 + LD B,PIO_CFGCNT ; LOOP CONTROL XOR A ; ZERO TO ACCUM -; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER - LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED + LD (PIO_DEV),A ; CURRENT DEVICE NUMBER + LD IY,PIO_CFG ; POINT TO START OF CFG TABLE PIO_PREINIT0: PUSH BC ; SAVE 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 - + CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE + POP BC ; RESTORE LOOP CONTROL +; LD A,(IY+1) ; GET THE PIO TYPE DETECTED - 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 -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 + OR A ; SET FLAGS + JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND +; + PUSH BC ; SAVE LOOP CONTROL + PUSH IY ; CFG ENTRY ADDRESS + POP DE ; ... TO DE + LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS + ; REGISTRATION OF CHARACTER UNIT IN HBIOS IS BYPASSED + ; FOR NOW. NOT SURE WHAT TO DO WITH THIS HARDWARE YET. + ;CALL NZ,CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE + POP BC ; RESTORE LOOP CONTROL +; +PIO_PREINIT2: + LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE +; XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; -; INDEX INTO THE CONFIG TABLE -; ON ENTRY C = UNIT NUMBER -; ON EXIT IY = CONFIG DATA POINTER -; ON EXIT DE = CONFIG TABLE START -; -; EACH CONFIG TABLE IS 24 BYTES LONG -; -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 - RET - -; PIO_INITDEV - INITIALIZE DEVICE +; PIO INITIALIZATION ROUTINE ; -; 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. +PIO_INITUNIT: + CALL PIO_DETECT ; DETERMINE PIO TYPE + LD (IY+1),A ; SAVE IN CONFIG TABLE + OR A ; SET FLAGS + RET Z ; ABORT IF NOTHING THERE ; -; 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. + ; UPDATE WORKING PIO DEVICE NUM + LD HL,PIO_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 +; + ; SET DEFAULT CONFIG + LD DE,-1 ; LEAVE CONFIG ALONE + ; CALL INITDEVX TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL + ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! + JP PIO_INITDEVX ; IMPLEMENT IT AND RETURN ; -; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT - -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 -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? - LD A,(IY+1) - CP PIO_ZPIO - JR Z,SETPIO0 - CP PIO_8255 - JP Z,SET_8255 - CP PIO_PORT - JP Z,SET_PORT -BAD_SET:OR $FF ; UNKNOWN DEVICE - RET - -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 +PIO_INIT: + LD B,PIO_CFGCNT ; COUNT OF POSSIBLE PIO UNITS + LD IY,PIO_CFG ; POINT TO START OF CFG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + POP BC ; RESTORE LOOP CONTROL + LD DE,PIO_CFGSIZ ; SIZE OF CFG ENTRY + ADD IY,DE ; BUMP IY TO NEXT ENTRY + DJNZ PIO_INIT1 ; LOOP TILL DONE ; -; LD A,(INT_ALLOC) -; DEC A -; LD (INT_ALLOC),A + XOR A ; SIGNAL SUCCESS + RET ; DONE ; -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 - OUT (C),A ; SET MODE - CP (M_BitCtrl | $0F) ; IF MODE 3 - JR NZ,SETPIO3 - LD A,(IY+5) ; SET I/O DIRECTION - OUT (C),A ; FOR MODE 3 - -SETPIO3:; INTERUPT HANDLING - - 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 +; DRIVER FUNCTION TABLE +; +PIO_FNTBL: + .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF ; -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 +PIO_IN: + LD E,0 ; DUMMY VALUE + XOR A ; SIGNAL SUCCESS + RET ; -; 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 - -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. - -PIOSHO_IN: - LD A,1 - RET ; -PIOSHO_OUT: - LD C,(IY+3) - OUT (C),E - XOR A +PIO_OUT: + XOR A ; SIGNAL SUCCESS RET ; -PIOSHO_IST: XOR A - RET ; -PIOSH_OST: - LD A,1 - RET ; -;----------------------------------------------------------------------------- +PIO_IST: + XOR A ; NO CHARS WAITING + 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 +PIO_OST: + XOR A ; NO BUFFER SPACE AVAIL RET ; -PIOSHI_OUT: - LD 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. ; -PIOSH_IST: - LD A,1 - RET +PIO_INITDEV: + HB_DI ; DISABLE INTS + CALL PIO_INITDEVX ; DO THE WORK + HB_EI ; INTS BACK ON + RET ; DONE ; -PIOSHI_OST: - XOR A +PIO_INITDEVX: +; +; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY +; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! +; + LD C,(IY+3) ; CONTROL PORT + LD A,%00010111 ; CLEAR INTERRUPT CTL WORD + OUT (C),A + LD A,%11111111 ; CLEAR MASK + OUT (C),A + LD A,%00000000 ; CLEAR INTERRUPT VECTOR + OUT (C),A + LD A,%01001111 ; SET MODE 1 (INPUT) + OUT (C),A RET ; -;----------------------------------------------------------------------------- ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE ; PIO_QUERY: -PPI_QUERY: - LD E,(IY+4) ; FIRST CONFIG BYTE TO E - LD D,(IY+5) ; SECOND CONFIG BYTE TO D + LD E,(IY+5) ; FIRST CONFIG BYTE TO E + LD D,(IY+6) ; SECOND CONFIG BYTE TO D XOR A ; SIGNAL SUCCESS - RET + RET ; DONE ; -;----------------------------------------------------------------------------- ; -; 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 - LD H,0 ; H := 0, DRIVER HAS NO MODES + LD C,$40 ; C := DEVICE TYPE, 0x40 IS PIO + LD H,(IY+1) ; H := MODE LD L,(IY+3) ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS 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 +; PIO CHIP PROBE +; CHECK FOR PRESENCE OF PIO CHIPS AND POPULATE THE +; PIO_MAP BITMAP (ONE BIT PER CHIP). THIS DETECTS +; CHIPS, NOT CHANNELS. EACH CHIP HAS 2 CHANNELS. +; MAX OF TWO CHIPS CURRENTLY. INT VEC VALUE IS TRASHED! +; +PIO_PROBE: + ; CLEAR THE PRESENCE BITMAP + LD HL,PIO_MAP ; HL POINTS TO BITMAP + XOR A ; ZERO + LD (PIO_MAP),A ; CLEAR CHIP PRESENT BITMAP +; + ; FIRST POSSIBLE CHIP + LD C,PIO0A_CTL ; FIRST CHIP CMD/STAT PORT + CALL PIO_PROBECHIP ; PROBE IT + JR NZ,PIO_PROBE1 ; IF NOT ZERO, NOT FOUND + SET 0,(HL) ; SET BIT FOR FIRST CARD +PIO_PROBE1: +; +#IF (PIOCNT >= 2) + LD C,PIO1A_CTL ; SECOND CHIP CMD/STAT PORT + CALL PIO_PROBECHIP ; PROBE IT + JR NZ,PIO_PROBE2 ; IF NOT ZERO, NOT FOUND + SET 1,(HL) ; SET BIT FOR SECOND CARD +PIO_PROBE2: +#ENDIF ; -SET_BYE: - XOR A ; SIGNAL SUCCESS RET ; -; ------------------------------------ -; i8255 FUNCTION TABLE ROUTINES -;------------------------------------- - -PPI_IN: - XOR A ; SIGNAL SUCCESS - RET -; -PPI_OUT: - XOR A ; SIGNAL SUCCESS - RET -; -PPI_IST: - RET -; -PPI_OST: +PIO_PROBECHIP: + ; PIO IS HRD TO DETECT DEFINITIVELY. BEST I CAN THINK + ; OF IS TO CHECK THE VALUE READ FROM THE CONTROL PORT. + ; IT APPEARS TO BE ZERO CONSISTENTLY IF CHIP EXISTS. + IN A,(C) ; GET VALUE + OR A ; COMPARE TO ZERO 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 - -PPI_INITDEV: - XOR A ; SIGNAL SUCCESS - RET -PPI_INT:OR $FF ; NZ SET TO INDICATE INT HANDLED - RET -; +; PIO DETECTION ROUTINE +; THERE IS ONLY ONE VARIATION OF PIO CHIP, SO HERE WE JUST CHECK THE +; CHIP PRESENCE BITMAP TO SET THE CHIP TYPE OF EITHER NONE OR PIO. +; +PIO_DETECT: + LD B,(IY+2) ; GET CHIP/CHANNEL + SRL B ; SHIFT AWAY THE CHANNEL BIT + INC B ; NUMBER OF TIMES TO ROTATE BITS + LD A,(PIO_MAP) ; BIT MAP IN A +PIO_DETECT1: + ; ROTATE DESIRED CHIP BIT INTO CF + RRA ; ROTATE NEXT BIT INTO CF + DJNZ PIO_DETECT1 ; DO THIS UNTIL WE HAVE DESIRED BIT + ; RETURN CHIP TYPE + LD A,PIO_NONE ; ASSUME NOTHING HERE + RET NC ; IF CF NOT SET, RETURN + LD A,PIO_PIO ; CHIP TYPE IS PIO + RET ; DONE +; +; +; PIO_PRTCFG: ; ANNOUNCE PORT CALL NEWLINE ; FORMATTING @@ -780,220 +258,90 @@ PIO_PRTCFG: PRTS(": IO=0x$") ; FORMATTING LD A,(IY+3) ; GET BASE PORT CALL PRTHEXBYTE ; PRINT BASE PORT -; + ; PRINT THE PIO TYPE CALL PC_SPACE ; FORMATTING LD A,(IY+1) ; GET PIO TYPE BYTE - LD DE,PIO_TYPE_STR ; POINT HL TO TYPE MAP TABLE - CALL PRTIDXDEA - - ; ALL DONE IF NO PIO WAS DETECTED - LD A,(IY+1) ; GET PIO 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_PRTPC0 ; PRINT CONFIG -; - 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 + RLCA ; MAKE IT A WORD OFFSET + LD HL,PIO_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 +; + XOR A RET ; -; WORKING VARIABLES ; -PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT -; -; DESCRIPTION OF DIFFERENT PORT TYPES -; -PIO_TYPE_STR: - .TEXT "$" ; IDX 0 - .TEXT "Zilog PIO$" ; IDX 1 - .TEXT "i8255 PPI$" ; IDX 2 - .TEXT "IO Port$" ; IDX 3 -; -; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS -; -; 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 PIO_ZPIO -#DEFCONT \ .DB 0 -#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 PIO_ZPIO -#DEFCONT \ .DB 1 -#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(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ -#DEFCONT \ .DB 0 -#DEFCONT \ .DB PIO_8255 -#DEFCONT \ .DB 0 -#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 PIO_8255 -#DEFCONT \ .DB 1 -#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 PIO_8255 -#DEFCONT \ .DB 2 -#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_4P -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 -; PIO_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) +PIO_TYPE_MAP: + .DW PIO_STR_NONE + .DW PIO_STR_PIO -#IF PIO_SBC -DEFPPI(PIOSBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) -#ENDIF +PIO_STR_NONE .DB "$" +PIO_STR_PIO .DB "PIO$" ; -PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ +; WORKING VARIABLES ; -;------------------------------------------------------------------- -; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. -; C IS THE UNIT NUMBER -;------------------------------------------------------------------- +PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT +PIO_MAP .DB 0 ; CHIP PRESENCE BITMAP ; -;PIO_INITUNIT: -; LD A,C ; SET THE UNIT NUMBER -; LD (IY),A +PIO0A_RCVBUF .EQU 0 +PIO0B_RCVBUF .EQU 0 ; -; LD DE,-1 ; LEAVE CONFIG ALONE -; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN -; XOR A ; SIGNAL SUCCESS -; RET ; AND RETURN +#IF (PIOCNT >= 2) +PIO1A_RCVBUF .EQU 0 +PIO1B_RCVBUF .EQU 0 +#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 -; 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 +; PIO PORT TABLE ; - XOR A ; SIGNAL SUCCESS - RET ; DONE +PIO_CFG: + ; PIO0 CHANNEL A +PIO0A_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $00 ; CHIP 0 / CHANNEL A (LOW BIT IS CHANNEL) + .DB PIO0A_CTL ; CMD/STATUS PORT + .DB PIO0A_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO0A_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +PIO_CFGSIZ .EQU $ - PIO_CFG ; SIZE OF ONE CFG TABLE ENTRY +; + ; PIO0 CHANNEL B +PIO0B_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $01 ; CHIP 0 / CHANNEL B (LOW BIT IS CHANNEL) + .DB PIO0B_CTL ; CMD/STATUS PORT + .DB PIO0B_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO0B_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; +#IF (PIOCNT >= 2) +; + ; PIO1 CHANNEL A +PIO1A_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $02 ; CHIP 1 / CHANNEL A (LOW BIT IS CHANNEL) + .DB PIO1A_CTL ; CMD/STATUS PORT + .DB PIO1A_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO1A_RCVBUF ; POINTER TO RCV BUFFER STRUCT +; + ; PIO1 CHANNEL B +PIO1B_CFG: + .DB 0 ; DEVICE NUMBER (SET DURING INIT) + .DB 0 ; PIO TYPE (SET DURING INIT) + .DB $03 ; CHIP 1 / CHANNEL B (LOW BIT IS CHANNEL) + .DB PIO1B_CTL ; CMD/STATUS PORT + .DB PIO1B_DAT ; DATA PORT + .DW DEFSERCFG ; LINE CONFIGURATION + .DW PIO1B_RCVBUF ; POINTER TO RCV BUFFER STRUCT ; -SET_PORT: - ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT - LD C,(IY+3) - OUT (C),A - XOR A - RET +#ENDIF +; +PIO_CFGCNT .EQU ($ - PIO_CFG) / PIO_CFGSIZ diff --git a/Source/HBIOS/pio_ps.asm b/Source/HBIOS/pio_ps.asm new file mode 100644 index 00000000..f198f25a --- /dev/null +++ b/Source/HBIOS/pio_ps.asm @@ -0,0 +1,999 @@ +; PIO driver sets up the parallel port as a subtype of Serial/Char device. +; +; +; HBIOS initializes driver by: +; +; 1) Calling Pre-initialization +; +; 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) 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 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 to allow 4 interrupts for the PIO driver. All remaining PIO's +; are limited to Bit mode or blind read and write 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 (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 example 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 +; +M_Output .EQU $00 << 6 +M_Input .EQU $01 << 6 +M_Bidir .EQU $02 << 6 +M_BitCtrl .EQU $03 << 6 +M_BitAllIn .EQU $FF +M_BitAllOut .EQU $00 +; +PIO_NONE .EQU 0 +PIO_ZPIO .EQU 1 +PIO_8255 .EQU 2 +PIO_PORT .EQU 3 + +; 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 00000100B +INT_ALLOW .EQU 4 +#ELSE +INT_Y .EQU INT_N +INT_ALLOW .EQU 0 +#ENDIF +; +INT0 .EQU 00000000B +INT1 .EQU 00000001B +INT2 .EQU 00000010B +INT3 .EQU 00000011B + +; +; SETUP THE DISPATCH TABLE ENTRIES +; +; 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 (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED +PIO_PREINIT0: + PUSH BC ; SAVE 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 + 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 +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 +; +; INDEX INTO THE CONFIG TABLE +; ON ENTRY C = UNIT NUMBER +; ON EXIT IY = CONFIG DATA POINTER +; ON EXIT DE = CONFIG TABLE START +; +; EACH CONFIG TABLE IS 24 BYTES LONG +; +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 + RET + +; PIO_INITDEV - INITIALIZE DEVICE +; +; 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. +; +; 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. +; +; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT + +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 +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? + LD A,(IY+1) + CP PIO_ZPIO + JR Z,SETPIO0 + CP PIO_8255 + JP Z,SET_8255 + CP PIO_PORT + JP Z,SET_PORT +BAD_SET:OR $FF ; UNKNOWN DEVICE + RET + +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 +; +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 + OUT (C),A ; SET MODE + CP (M_BitCtrl | $0F) ; IF MODE 3 + JR NZ,SETPIO3 + LD A,(IY+5) ; SET I/O DIRECTION + OUT (C),A ; FOR MODE 3 + +SETPIO3:; INTERUPT HANDLING + + 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 + +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. + +PIOSHO_IN: + LD A,1 + RET +; +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. GET AND RETURN THE CONFIGURATION WORD IN DE +; +PIO_QUERY: +PPI_QUERY: + LD E,(IY+4) ; FIRST CONFIG BYTE TO E + LD D,(IY+5) ; SECOND CONFIG BYTE TO D + 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. 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 + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L,(IY+3) ; L := BASE I/O ADDRESS + XOR A ; SIGNAL SUCCESS + 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 +;------------------------------------- + +PPI_IN: + XOR A ; SIGNAL SUCCESS + RET +; +PPI_OUT: + XOR A ; SIGNAL SUCCESS + RET +; +PPI_IST: + RET +; +PPI_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 + +PPI_INITDEV: + XOR A ; SIGNAL SUCCESS + RET +PPI_INT:OR $FF ; NZ SET TO INDICATE INT HANDLED + RET +; +PIO_PRTCFG: + ; ANNOUNCE PORT + CALL NEWLINE ; FORMATTING + PRTS("PIO$") ; 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 PIO TYPE + CALL PC_SPACE ; FORMATTING + LD A,(IY+1) ; GET PIO TYPE BYTE + LD DE,PIO_TYPE_STR ; POINT HL TO TYPE MAP TABLE + CALL PRTIDXDEA + + ; ALL DONE IF NO PIO WAS DETECTED + LD A,(IY+1) ; GET PIO 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_PRTPC0 ; PRINT CONFIG +; + 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 +; +PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT +; +; DESCRIPTION OF DIFFERENT PORT TYPES +; +PIO_TYPE_STR: + .TEXT "$" ; IDX 0 + .TEXT "Zilog PIO$" ; IDX 1 + .TEXT "i8255 PPI$" ; IDX 2 + .TEXT "IO Port$" ; IDX 3 +; +; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS +; +; 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 PIO_ZPIO +#DEFCONT \ .DB 0 +#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 PIO_ZPIO +#DEFCONT \ .DB 1 +#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(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ +#DEFCONT \ .DB 0 +#DEFCONT \ .DB PIO_8255 +#DEFCONT \ .DB 0 +#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 PIO_8255 +#DEFCONT \ .DB 1 +#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 PIO_8255 +#DEFCONT \ .DB 2 +#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_4P +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 +; PIO_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) + +#IF PIO_SBC +DEFPPI(PIOSBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) +#ENDIF +; +PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ +; +;------------------------------------------------------------------- +; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; C IS THE UNIT NUMBER +;------------------------------------------------------------------- +; +;PIO_INITUNIT: +; LD A,C ; SET THE UNIT NUMBER +; LD (IY),A +; +; LD DE,-1 ; LEAVE CONFIG ALONE +; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN +; +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 +; 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 +; +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/ver.inc b/Source/ver.inc index ea9cd84d..3b25aa3f 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.159" +#DEFINE BIOSVER "3.1.1-pre.160" diff --git a/Source/ver.lib b/Source/ver.lib index 42a77a7b..364713e9 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.159" + db "3.1.1-pre.160" endm