diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 7c18d183..e6e171fb 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -489,10 +489,10 @@ HBX_IVT: .DW INT_BAD ; IVT_CSIO .DW INT_BAD ; IVT_SER0 .DW INT_BAD ; IVT_SER1 - .DW INT_BAD ; - .DW INT_BAD ; - .DW INT_BAD ; - .DW INT_BAD ; + .DW INT_BAD ; IVT_PIO0 + .DW INT_BAD ; IVT_PIO1 + .DW INT_BAD ; IVT_PIO2 + .DW INT_BAD ; IVT_PIO3 .DW INT_BAD ; .DW INT_BAD ; .DW INT_BAD ; @@ -553,6 +553,28 @@ INT_SIO: ; SIO INTERRUPT HANDLER JR HBX_INT ; GO TO ROUTING CODE #ENDIF ; +#IF (PIO_ZP) +INT_ZP0: ; PIO INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,PIO_INT0 ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +INT_ZP1 + PUSH HL ; SAVE HL + LD HL,PIO_INT1 ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +#ENDIF +; +#IF (PIO_4P) +INT_4P0: ; PIO INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,PIO_INT2 ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +INT_4P1: + PUSH HL ; SAVE HL + LD HL,PIO_INT3 ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +#ENDIF +; #ENDIF ; #IF (INTMODE > 0) @@ -571,7 +593,7 @@ HBX_INT: ; COMMON INTERRUPT ROUTING CODE PUSH DE ; SAVE DE PUSH IY ; SAVE IY - LD A,BID_BIOS ; HBIOS BANK + LD A,BID_IMG0 ; HBIOS BANK CALL HBX_BNKSEL_INT ; SELECT IT CALL JPHL ; CALL INTERRUPT ROUTINE @@ -871,6 +893,9 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK #IF (ACIAENABLE) CALL ACIA_PREINIT #ENDIF +#IF (PIO_4P | PIO_ZP) + CALL PIO_PREINIT +#ENDIF ; DIAG(%01111111) ; @@ -1223,6 +1248,9 @@ HB_INITTBL: #IF (PPPENABLE) .DW PPP_INIT #ENDIF +#IF (PIO_4P | PIO_ZP) + .DW PIO_INIT +#ENDIF ; HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2) ; @@ -2414,6 +2442,15 @@ 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" +SIZ_PIO .EQU $ - ORG_PIO + .ECHO "PIO occupies " + .ECHO SIZ_PIO + .ECHO " bytes.\n" +#ENDIF + ; #DEFINE USEDELAY #INCLUDE "util.asm" @@ -2813,7 +2850,7 @@ PS_SERIAL: PUSH BC ; SAVE UNIT INDEX FOR LATER ; ; UNIT COLUMN - PRTS("Serial $") + PRTS("Char $" LD A,C ; MOVE UNIT NUM TO A CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT PRTS(" $") ; PAD TO NEXT COLUMN @@ -2834,9 +2871,12 @@ PS_SERIAL: CALL NEWLINE RET ; -; PRINT SERIAL TYPE (SERIAL ATTRIBUTE IN E) +; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN E) ; PS_PRTST: + LD HL,PS_STPPT + BIT 6,C + JR NZ,PS_PRTST1 ; PARALLEL TYPE? LD HL,PS_STRS232 ; ASSUME RS-232 BIT 7,C ; 0=RS-232, 1=TERMINAL JR Z,PS_PRTST1 ; HANDLE TERMINAL TYPE @@ -2852,8 +2892,11 @@ PS_PRTST1: ; PRINT SERIAL CONFIG (UNIT IN E, ATTRIBUTE IN C) ; PS_PRTSC: + BIT 6,C ; PARALLEL TYPE? + JR NZ,PSPRTPC0 + BIT 7,C ; 0=RS-232, 1=TERMINAL - JR NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG + JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG ; ; PRINT RS-232 CONFIG LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG @@ -2912,6 +2955,42 @@ PS_PRTSC0: ; RET ; +PSPRTPC0: + LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG + LD C,E ; SET PARALLEL UNIT NUM + RST 08 ; DE:HL := I/O SETTING + LD A,D ; TEST FOR $FF + AND E + INC A ; SET Z IF DE == $FF + JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED +; +PS_PRTPC0: + LD A,E + RLCA + RLCA + AND 00000011B + JR NZ,PSPRTPC1 + PRTS("Output$") + RET +PSPRTPC1: + DEC A + JR NZ,PSPRTPC2 + PRTS("Input$") + RET +PSPRTPC2: + DEC A + JR NZ,PSPRTPC3 + PRTS("Bidirectional$") + RET +PSPRTPC3: + DEC A + JR NZ,PSPRTPC4 + PRTS("BitCtrl$") + RET +PSPRTPC4: + PRTS("Undefined$") + RET + PS_PRTSC1: ; PRINT TERMINAL CONFIG LD A,C ; GET ATTRIBUTE VALUE @@ -3097,7 +3176,7 @@ PS_FLPED .TEXT "ED$" ; PS_SDSTRREF: .DW PS_SDUART, PS_SDASCI, PS_SDTERM, - .DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA + .DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA, PS_SDPIO ; PS_SDUART .TEXT "UART$" PS_SDASCI .TEXT "ASCI$" @@ -3106,11 +3185,13 @@ PS_SDPRPCON .TEXT "PRPCON$" PS_SDPPPCON .TEXT "PPPCON$" PS_SDSIO .TEXT "SIO$" PS_SDACIA .TEXT "ACIA$" +PS_SDPIO .TEXT "PORT$" ; ; SERIAL TYPE STRINGS ; PS_STRS232 .TEXT "RS-232$" PS_STTERM .TEXT "Terminal$" +PS_STPPT .TEXT "Parallel$" ; PS_STPARMAP .DB "NONENMNS" diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index 580f0f73..f77db80f 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -1,92 +1,155 @@ - -PIO0A .EQU ; ECB-ZP -PIO0B .EQU ; ECB-ZP -PIO1A .EQU ; ECB-ZP -PIO1B .EQU ; ECB-ZP - -PIO2A .EQU ; ECB-4PIO -PIO2B .EQU ; ECB-4PIO -PIO3A .EQU ; ECB-4PIO -PIO3B .EQU ; ECB-4PIO -PIO4A .EQU ; ECB-4PIO -PIO4B .EQU ; ECB-4PIO -PIO5A .EQU ; ECB-4PIO -PIO5B .EQU ; ECB-4PIO - -PIO_Input .EQU $0000 -PIO_Output .EQU $0001 -PIO_BiDir .Equ $0002 - -DEFPIOCFGA .EQU $8000 + PIO_Input -DEFPIOCFGB .EQU $8000 + PIO_Output -DEFPIOCFGX .EQU $8000 + PIO_BiDir - +; PIO driver sets up the parallel port as a subtype of Serial/Char device. +; +; +; HBIOS initializes driver by: +; +; 1) Performing Pre-initialization +; +; This involves setting up all the data structures decribing the devices. +; If possible, do a hardware test to verify it is available for adding to available devices. +; +; 2) Performing individual device/unit 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 +; 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. +; +; 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 +; +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 + +;INT_POOL .EQU HBX_IVT+IVT_PIO0 + +INT_ALLOC .DB 0 +INT_N .EQU 00000000B +#IF (INTMODE == 2) +INT_Y .EQU INT_N +INT_ALLOW .EQU 4 +#ELSE +INT_Y .EQU 00000100B +INT_ALLOW .EQU 0 +#ENDIF + +INT_0 .EQU 00000000B +INT_1 .EQU 00000001B +INT_2 .EQU 00000010B +INT_3 .EQU 00000011B ; -PIO_PREINIT: ; ; 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: LD B,PIO_CNT ; LOOP CONTROL - LD C,0 ; PHYSICAL UNIT INDEX - XOR A ; ZERO TO ACCUM + LD C,0 ; PHYSICAL UNIT INDEX + XOR A ; ZERO TO ACCUM LD (PIO_DEV),A ; CURRENT DEVICE NUMBER PIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL - LD A,C ; PHYSICAL UNIT TO A + 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 + CALL ADDHLA ; HL := ENTRY ADDRESS PUSH HL ; SAVE IT PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY + 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 + POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE + POP BC ; RESTORE LOOP CONTROL ; LD A,(IY+1) ; GET THE PIO TYPE DETECTED - OR A ; SET FLAGS + 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 - CALL NZ,CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE + 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: INC C ; NEXT PHYSICAL UNIT DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE ; -;#IF (INTMODE == 1) -; ; ADD IM1 INT CALL LIST ENTRY IF APPROPRIATE -; LD A,(SIO_DEV) ; GET NEXT DEVICE NUM -; OR A ; SET FLAGS -; JR Z,PIO_PREINIT3 ; IF ZERO, NO SIO DEVICES -; LD HL,PIO_INT ; GET INT VECTOR -; CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST -;#ENDIF -; -;#IF (INTMODE == 2) -; ; SETUP SIO INTERRUPT VECTOR IN IVT -; LD HL,INT_PIO -; LD (HBX_IVT + IVT_SER0),HL -;#ENDIF -; +#IF (INTMODE == 2) + ; SETUP PIO INTERRUPT VECTOR IN IVT + LD HL,INT_PIO + LD (HBX_IVT + IVT_PIO0),HL +#ENDIF PIO_PREINIT3: XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; +; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; PIO_INITUNIT: - XOR A ; SIGNAL SUCCESS - RET ; AND RETURN + 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 SIO UNITS - LD C,0 ; INDEX INTO SIO CONFIG TABLE + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE PIO_INIT1: PUSH BC ; SAVE LOOP CONTROL @@ -103,204 +166,228 @@ PIO_INIT1: 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? + AND $20 ; device ready? JR Z,PIO_LPT ; no, busy wait - IN A,($F5) ; get transmit buffer register status ready? - AND $20 ; ready? + 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 + 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 PORT TABLE -; -PIO_CFG: - ; PIO CHANNEL A - .DB 0 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB PIOBASE+2 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 1 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB PIOBASE+3 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL A - .DB 2 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB PIOBASE+6 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 3 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB PIOBASE+7 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT - ; PIO CHANNEL A - .DB 4 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB 4PIOBASE+2 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGX ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 5 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB 4PIOBASE+3 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL A - .DB 6 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB 4PIOBASE+6 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 7 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB 4PIOBASE+7 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL A - .DB 8 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB 4PIOBASE+10 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 9 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB 4PIOBASE+11 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL A - .DB 10 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB 4PIOBASE+14 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 11 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB 4PIOBASE+15 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL A - .DB 12 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_ZPIO ; PIO TYPE (SET DURING INIT) - .DB 0 ; PIO CHANNEL (A) - .DB 4PIOBASE+14 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGA ; LINE CONFIGURATION - .DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT -; - ; PIO CHANNEL B - .DB 13 ; DEVICE NUMBER (SET DURING INIT) - .DB PIO_8255 ; PIO TYPE (SET DURING INIT) - .DB 1 ; PIO CHANNEL (B) - .DB 4PIOBASE+15 ; BASE PORT (CMD PORT) - .DW DEFPIOCFGB ; LINE CONFIGURATION - .DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT - ; -; -PIO_CNT .EQU ($ - PIO_CFG) / 8 -; -; DRIVER FUNCTION TABLE +PIO_INT0: +PIO_INT1: +PIO_INT2: +PIO_INT3: +PIO_INT4: +PIO_INT5: +PIO_INT6: +PIO_INT7: +PIO_INT8: +PIO_INT9:OR $FF ; NZ SET TO INDICATE INT HANDLED + RET ; -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 SIO FUNCTION TABLE ***\n" -#ENDIF +; 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. ; PIO_OUT: + LD C,(IY+3) + OUT (C),E XOR A ; SIGNAL SUCCESS RET -; -PIO_IN: - XOR A ; SIGNAL SUCCESS - RET -; + + LD C,(IY+3) ; GET PORT + LD A,(IY+4) ; GET MODE (B7B6) + + PIO_IST: RET ; PIO_OST: - RET + RET ; ; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuratio information from the table of devices and program the device using those settings. +; 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) -- +; PIO_INITDEV: - XOR A ; SIGNAL SUCCESS - RET + ; 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 + 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,SET_PIO + CP PIO_8255 + JR Z,SET_8255 + CP PIO_PORT + JR Z,SET_PORT +PIO_BAD: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 + RET ; -PIO_QUERY: - LD E,(IY+4) ; FIRST CONFIG BYTE TO E - LD D,(IY+5) ; SECOND CONFIG BYTE TO D +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 + 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 + OUT (C),A ; SET MODE + CP (M_BitCtrl | $0F) ; IF MODE 3 + JR NZ,SET_NM3 + LD A,(IY+5) ; SET I/O + 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 + +NOINT1: LD A,00000111B ; $07 + OUT (C),A ; NO INTERRUPTS + DEC C + DEC C + LD A,$FF ; DEFAULT VALUE + OUT (C),A + XOR A + RET +BADSET: LD A,$FF + RET + +SET_8255: + RET + +SET_BYE: XOR A ; SIGNAL SUCCESS 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 + RET ; +; ON ENTRY IY POINTS TO THE DEVICE RECORD +; WE GET AND RETURN THE CONFIGURATION WORD IN DE ; -;TTY_DEVICE: -; LD D,CIODEV_TERM ; TYPE IS TERMINAL -; LD A,(TTY_DEVNUM) ; GET DEVICE NUMBER -; LD E,A ; PUT IT IN E -; LD A,(TTY_VDAUNIT) ; GET VDA UNIT NUM -; SET 7,A ; SET BIT 7 TO INDICATE TERMINAL TYPE -; LD C,A ; PUT IT IN C -; XOR A ; SIGNAL SUCCESS -; RET -; +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. +; PIO_DEVICE: - LD D,CIODEV_PIO ; D := DEVICE TYPE +PPI_DEVICE: + LD D,CIODEV_PIO ; D := DEVICE TYPE LD E,(IY) ; E := PHYSICAL UNIT - LD A,E - SET 7,A - LD C,A + LD C,$40 ; C := ATTRIBUTE + 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 configuratio 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 @@ -340,11 +427,229 @@ PIO_PRTCFG: ; PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT ; +; DESCRIPTION OF DIFFERENT PORT TYPES +; PIO_TYPE_MAP: .DW PIO_STR_NONE .DW PIO_STR_PIO - .DW PIO_STR_8255 + .DW PIO_STR_8255 + .DW PIO_STR_PORT PIO_STR_NONE .DB "$" -PIO_STR_PIO .DB "Zilog PIO$" -PIO_STR_8255 .DB "i8255 PIO$" \ No newline at end of file +PIO_STR_PIO .DB "Zilog PIO$" +PIO_STR_8255 .DB "i8255 PPI$" +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) \ +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPIO_BASE +#DEFCONT \ .DB (MPIO_CH0 | 00001000B | MPIO_IN0) +#DEFCONT \ .DB MPIO_CH0X +#DEFCONT \ .DW MPIO_FT0 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB 1 +#DEFCONT \ .DB MPIO_BASE+1 +#DEFCONT \ .DB (MPIO_CH1 | 00010000B | MPIO_IN1) +#DEFCONT \ .DB MPIO_CH1X +#DEFCONT \ .DW MPIO_FT1 +; +; 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) \ +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPPI_BASE+0 +#DEFCONT \ .DB (MPPI_CH1 | 00001000B) +#DEFCONT \ .DB MPPI_CH1X +#DEFCONT \ .DW +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB 1 +#DEFCONT \ .DB MPPI_BASE+2 +#DEFCONT \ .DB (MPPI_CH2 | 00010000B) +#DEFCONT \ .DB MPPI_CH2X +#DEFCONT \ .DW 0 +#DEFCONT \ .DB 0 +#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB 2 +#DEFCONT \ .DB MPPI_BASE+4 +#DEFCONT \ .DB (MPPI_CH3 | 00100000B) +#DEFCONT \ .DB MPPI_CH3X +#DEFCONT \ .DW 0 +; +; 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,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) +#ENDIF +#IF PIO_4P +DEFPIO(PIO_ZPIO,PIO4BASE+0,M_BitCtrl,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+4,M_BitCtrl,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+8,M_BitCtrl,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+12,M_BitCtrl,M_BitCtrl,M_BitAllOut,M_Output,PIO8FT,PIO9FT,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) +#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 +; + +; DRIVER FUNCTION TABLE FOR Z80 PIO's +; +; +PIO_FNTBL: +; +#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 +#ENDIF + +#IF PIO_4P +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 +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 +#ENDIF +; +; 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 +; +; 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 diff --git a/Source/HBIOS/plt_sbc.inc b/Source/HBIOS/plt_sbc.inc index 341b2401..d64bc4fa 100644 --- a/Source/HBIOS/plt_sbc.inc +++ b/Source/HBIOS/plt_sbc.inc @@ -19,4 +19,6 @@ 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 -SIOBASE .EQU $B0 ; ZILOG PERIPHERALS DEFAULT ;PS +SIOBASE .EQU $B0 ; ZILOG PERIPHERALS DEFAULT +PIOZBASE .EQU SIOBASE+8 ; ZILOG PERIPHERALS DEFAULT PIO DEFAULT +PIO4BASE .EQU $90 ; ECB-4PIO DEFAULT PIO DEFAULT \ No newline at end of file