From de208491dc5263d96ccc02d0cbfefc129eb1d731 Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Fri, 5 Apr 2019 22:55:59 +0800 Subject: [PATCH 1/9] PIO build --- Source/HBIOS/hbios.asm | 99 +++++- Source/HBIOS/pio.asm | 735 +++++++++++++++++++++++++++------------ Source/HBIOS/plt_sbc.inc | 4 +- 3 files changed, 613 insertions(+), 225 deletions(-) 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 From 56150ef85f05577d68c8edb4c18e249c54edfd53 Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Mon, 8 Apr 2019 20:11:24 +0800 Subject: [PATCH 2/9] PIO Updates --- pio.asm | 671 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 671 insertions(+) create mode 100644 pio.asm diff --git a/pio.asm b/pio.asm new file mode 100644 index 00000000..f3ec74e5 --- /dev/null +++ b/pio.asm @@ -0,0 +1,671 @@ +; 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 +; +; +; 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 (PIO_DEV),A ; CURRENT DEVICE NUMBER +PIO_PREINIT0: + PUSH BC ; SAVE LOOP CONTROL + LD A,C ; PHYSICAL UNIT TO A + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) + RLCA ; ... + RLCA ; ... TO GET OFFSET INTO CFG TABLE + LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + CALL ADDHLA ; HL := ENTRY ADDRESS + PUSH HL ; SAVE IT + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE + POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE + POP BC ; RESTORE LOOP CONTROL +; + LD A,(IY+1) ; GET THE PIO TYPE DETECTED + OR A ; SET FLAGS + JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND +; + PUSH BC ; SAVE LOOP CONTROL + PUSH AF + DEC A + LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS + JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D + DEC A + LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS + JR Z,TYPFND + DEC A + LD BC,PRT_FNTBL + JR NZ,TYPDUN +TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE +TYPDUN: POP AF + POP BC ; RESTORE LOOP CONTROL +; +PIO_PREINIT2: + INC C ; NEXT PHYSICAL UNIT + DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE +; +#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: + LD A,C ; SET THE UNIT NUMBER + LD (IY),A + + LD DE,-1 ; LEAVE CONFIG ALONE + JP PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN +; +PIO_INIT: + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + + LD A,C ; PHYSICAL UNIT TO A + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) + RLCA ; ... + RLCA ; ... TO GET OFFSET INTO CFG TABLE + LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + CALL ADDHLA ; HL := ENTRY ADDRESS + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + + PUSH DE + LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL + CALL PIO_INITDEV ; BASED ON DPW + POP DE + + POP BC ; RESTORE LOOP CONTROL + INC C ; NEXT UNIT + DJNZ PIO_INIT1 ; LOOP TILL DONE +; + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; EXAMPLE CODE +; +PIO_LPT: + IN A,($F6) ; get device status + AND $20 ; device ready? + JR Z,PIO_LPT ; no, busy wait + IN A,($F5) ; get transmit buffer register status ready? + AND $20 ; ready? + JR Z,PIO_LPT ; no, busy wait + LD A,C ; ready, char A for output through data port + OUT ($F0),A ; output char + RET + + + +; ------------------------------------ +; ZILOG PIO FUNCTION TABLE ROUTINES +;------------------------------------- + +PIO_IN: + LD C,(IY+3) + IN A,(C) + LD E,A + XOR A ; SIGNAL SUCCESS + RET + +; +PIO_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 +; +; 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 + + LD C,(IY+3) ; GET PORT + LD A,(IY+4) ; GET MODE (B7B6) + + +PIO_IST: + RET +; +PIO_OST: + RET +; +; PIO_INITDEV - Configure device. +; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. +; Otherwise use the configuration information in DE to program those settings and save them in the device table +; +; SETUP PARAMETER WORD: +; +-------------------------------+ +-------+-----------+---+-------+ +; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | +; +-------------------------------+ --------------------+-----------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- +; +; +; MSB = BIT MAP USE IN MODE 3 +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; CHIP CHANNEL B5 B4 B3 001 Channel 1 +; 010 Channel 2 +; 100 Channel 3 +; +; INTERUPT B1 B0 00 IVT 1 +; 01 IVT 2 +; 10 IVT 3 +; 11 IVT 4 +PIO_INITDEV: + ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) + LD A,D ; TEST DE FOR + AND E ; ... VALUE OF -1 + INC A ; ... SO Z SET IF -1 + JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG +; + ; LOAD EXISTING CONFIG TO REINIT + 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 +; +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 +; +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: +PPI_DEVICE: + LD D,CIODEV_PIO ; D := DEVICE TYPE + LD E,(IY) ; E := PHYSICAL UNIT + LD C,$40 ; C := ATTRIBUTE + XOR A ; SIGNAL SUCCESS + RET + +; ------------------------------------ +; 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 + 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 + 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 +; + ; ALL DONE IF NO PIO WAS DETECTED + LD A,(IY+1) ; GET SIO 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 +; + XOR A + RET +; +; WORKING VARIABLES +; +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_PORT + +PIO_STR_NONE .DB "$" +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_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,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 From 1e7e28a06515245f9069008e1aefb052373689bb Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Mon, 8 Apr 2019 20:11:59 +0800 Subject: [PATCH 3/9] Delete pio.asm --- pio.asm | 671 -------------------------------------------------------- 1 file changed, 671 deletions(-) delete mode 100644 pio.asm diff --git a/pio.asm b/pio.asm deleted file mode 100644 index f3ec74e5..00000000 --- a/pio.asm +++ /dev/null @@ -1,671 +0,0 @@ -; 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 -; -; -; 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 (PIO_DEV),A ; CURRENT DEVICE NUMBER -PIO_PREINIT0: - PUSH BC ; SAVE LOOP CONTROL - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS - PUSH HL ; SAVE IT - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE - POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE - POP BC ; RESTORE LOOP CONTROL -; - LD A,(IY+1) ; GET THE PIO TYPE DETECTED - OR A ; SET FLAGS - JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND -; - PUSH BC ; SAVE LOOP CONTROL - PUSH AF - DEC A - LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D - DEC A - LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND - DEC A - LD BC,PRT_FNTBL - JR NZ,TYPDUN -TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE -TYPDUN: POP AF - POP BC ; RESTORE LOOP CONTROL -; -PIO_PREINIT2: - INC C ; NEXT PHYSICAL UNIT - DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE -; -#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: - LD A,C ; SET THE UNIT NUMBER - LD (IY),A - - LD DE,-1 ; LEAVE CONFIG ALONE - JP PIO_INITDEV ; IMPLEMENT IT AND RETURN -; XOR A ; SIGNAL SUCCESS -; RET ; AND RETURN -; -PIO_INIT: - LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS - LD C,0 ; INDEX INTO PIO CONFIG TABLE -PIO_INIT1: - PUSH BC ; SAVE LOOP CONTROL - - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - - LD A,(IY+1) ; GET PIO TYPE - OR A ; SET FLAGS - CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO - - PUSH DE - LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL - CALL PIO_INITDEV ; BASED ON DPW - POP DE - - POP BC ; RESTORE LOOP CONTROL - INC C ; NEXT UNIT - DJNZ PIO_INIT1 ; LOOP TILL DONE -; - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -; EXAMPLE CODE -; -PIO_LPT: - IN A,($F6) ; get device status - AND $20 ; device ready? - JR Z,PIO_LPT ; no, busy wait - IN A,($F5) ; get transmit buffer register status ready? - AND $20 ; ready? - JR Z,PIO_LPT ; no, busy wait - LD A,C ; ready, char A for output through data port - OUT ($F0),A ; output char - RET - - - -; ------------------------------------ -; ZILOG PIO FUNCTION TABLE ROUTINES -;------------------------------------- - -PIO_IN: - LD C,(IY+3) - IN A,(C) - LD E,A - XOR A ; SIGNAL SUCCESS - RET - -; -PIO_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 -; -; 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 - - LD C,(IY+3) ; GET PORT - LD A,(IY+4) ; GET MODE (B7B6) - - -PIO_IST: - RET -; -PIO_OST: - RET -; -; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. -; Otherwise use the configuration information in DE to program those settings and save them in the device table -; -; SETUP PARAMETER WORD: -; +-------------------------------+ +-------+-----------+---+-------+ -; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | -; +-------------------------------+ --------------------+-----------+ -; F E D C B A 9 8 7 6 5 4 3 2 1 0 -; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- -; -; -; MSB = BIT MAP USE IN MODE 3 -; MODE B7 B6 = 00 Mode 0 Output -; 01 Mode 1 Input -; 10 Mode 2 Bidir -; 11 Mode 3 Bit Mode -; CHIP CHANNEL B5 B4 B3 001 Channel 1 -; 010 Channel 2 -; 100 Channel 3 -; -; INTERUPT B1 B0 00 IVT 1 -; 01 IVT 2 -; 10 IVT 3 -; 11 IVT 4 -PIO_INITDEV: - ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) - LD A,D ; TEST DE FOR - AND E ; ... VALUE OF -1 - INC A ; ... SO Z SET IF -1 - JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG -; - ; LOAD EXISTING CONFIG TO REINIT - 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 -; -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 -; -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: -PPI_DEVICE: - LD D,CIODEV_PIO ; D := DEVICE TYPE - LD E,(IY) ; E := PHYSICAL UNIT - LD C,$40 ; C := ATTRIBUTE - XOR A ; SIGNAL SUCCESS - RET - -; ------------------------------------ -; 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 - 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 - 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 -; - ; ALL DONE IF NO PIO WAS DETECTED - LD A,(IY+1) ; GET SIO 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 -; - XOR A - RET -; -; WORKING VARIABLES -; -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_PORT - -PIO_STR_NONE .DB "$" -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_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,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 From 4594e990a6d1ce06c272e3ebab93ecacea924208 Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Mon, 8 Apr 2019 20:12:35 +0800 Subject: [PATCH 4/9] PIO Updates --- Source/HBIOS/pio.asm | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index f77db80f..f3ec74e5 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -191,6 +191,8 @@ PIO_LPT: OUT ($F0),A ; output char RET + + ; ------------------------------------ ; ZILOG PIO FUNCTION TABLE ROUTINES ;------------------------------------- @@ -239,7 +241,7 @@ PIO_OST: ; PIO_INITDEV - Configure device. ; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. ; Otherwise use the configuration information in DE to program those settings and save them in the device table - +; ; SETUP PARAMETER WORD: ; +-------------------------------+ +-------+-----------+---+-------+ ; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | @@ -247,6 +249,20 @@ PIO_OST: ; F E D C B A 9 8 7 6 5 4 3 2 1 0 ; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- ; +; +; MSB = BIT MAP USE IN MODE 3 +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; CHIP CHANNEL B5 B4 B3 001 Channel 1 +; 010 Channel 2 +; 100 Channel 3 +; +; INTERUPT B1 B0 00 IVT 1 +; 01 IVT 2 +; 10 IVT 3 +; 11 IVT 4 PIO_INITDEV: ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR @@ -492,10 +508,10 @@ PIO_CFG: 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) +DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO8FT,PIO9FT,INT_N,INT_N) #ENDIF ; PPI_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) From 6606baebe9eacd2a3e3a988343318afb855274be Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Tue, 9 Apr 2019 23:25:57 +0800 Subject: [PATCH 5/9] Fix IM2 assembly error. Add second ECB-ZP PIO chip. --- Source/HBIOS/hbios.asm | 8 ++--- Source/HBIOS/pio.asm | 78 +++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index e6e171fb..69f95dfb 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -556,22 +556,22 @@ INT_SIO: ; SIO INTERRUPT HANDLER #IF (PIO_ZP) INT_ZP0: ; PIO INTERRUPT HANDLER PUSH HL ; SAVE HL - LD HL,PIO_INT0 ; HL := PIO INT HANDLER IN BIOS BANK + LD HL,PIO0INT ; 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 + LD HL,PIO1INT ; 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 + LD HL,PIO2INT ; 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 + LD HL,PIO3INT ; HL := PIO INT HANDLER IN BIOS BANK JR HBX_INT ; GO TO ROUTING CODE #ENDIF ; diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index f3ec74e5..9a04177d 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -12,8 +12,6 @@ ; ; 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. @@ -129,7 +127,7 @@ PIO_PREINIT2: ; #IF (INTMODE == 2) ; SETUP PIO INTERRUPT VECTOR IN IVT - LD HL,INT_PIO + LD HL,PIO0INT LD (HBX_IVT + IVT_PIO0),HL #ENDIF PIO_PREINIT3: @@ -205,16 +203,17 @@ PIO_IN: RET ; -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 +PIO0INT: +PIO1INT: +PIO2INT: +PIO3INT: +PIO4INT: +PIO5INT: +PIO6INT: +PIO7INT: +PIO8INT: +PIO9INT: + OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; ; ON ENTRY IY POINTS TO THE DEVICE RECORD @@ -258,11 +257,13 @@ PIO_OST: ; CHIP CHANNEL B5 B4 B3 001 Channel 1 ; 010 Channel 2 ; 100 Channel 3 +; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED +; = 1 IS ALLOCATED ; -; INTERUPT B1 B0 00 IVT 1 -; 01 IVT 2 -; 10 IVT 3 -; 11 IVT 4 +; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 +; 01 IVT_PIO1 +; 10 IVT_PIO2 +; 11 IVT_PIO3 PIO_INITDEV: ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR @@ -505,13 +506,14 @@ PIO_STR_PORT .DB "IO Port$" PIO_CFG: #IF PIO_ZP -DEFPIO(PIO_ZPIO,PIOZBASE,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIOZBASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIOZBASE+4,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) #ENDIF #IF PIO_4P -DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO8FT,PIO9FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO8FT,PIO9FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO10FT,PIO11FT,INT_N,INT_N) #ENDIF ; PPI_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) @@ -532,8 +534,10 @@ PIO_CNT .EQU ($ - PIO_CFG) / 8 ; ; DRIVER FUNCTION TABLE FOR Z80 PIO's -; -; +; EACH PIO NEEDS A FUNCTION TABLE +; ECB-ZP : PIO0FT-PIO3FT +; ECB-4P : PIO4FT-PIO11FT + PIO_FNTBL: ; #IF PIO_ZP @@ -557,9 +561,6 @@ PIO1FT .DW PIO_IN #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 @@ -580,6 +581,9 @@ PIO3FT .DW PIO_IN #IF (($ - PIO3FT) != (CIO_FNCNT * 2)) .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" #ENDIF +#ENDIF +; +#IF PIO_4P PIO4FT .DW PIO_IN .DW PIO_OUT .DW PIO_IST @@ -640,6 +644,26 @@ PIO9FT .DW PIO_IN #IF (($ - PIO9FT) != (CIO_FNCNT * 2)) .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" #ENDIF +PIO10FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO10FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO11FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO11FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF #ENDIF ; ; DRIVER FUNCTION TABLE FOR i8255's From 328453309a9a4febbed5612d8e9fbb3b69f70c73 Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Tue, 9 Apr 2019 23:26:55 +0800 Subject: [PATCH 6/9] Fix IM2 assembly error. Add 2nd PIO on ECB-ZP --- hbios.asm | 3398 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pio.asm | 695 +++++++++++ 2 files changed, 4093 insertions(+) create mode 100644 hbios.asm create mode 100644 pio.asm diff --git a/hbios.asm b/hbios.asm new file mode 100644 index 00000000..69f95dfb --- /dev/null +++ b/hbios.asm @@ -0,0 +1,3398 @@ +; +;================================================================================================== +; HBIOS +;================================================================================================== +; +; THIS FILE CONTAINS THE HBIOS IMAGE THAT IS INTENDED TO RUN IN A DEDICATED RAM BANK. THE CODE IS +; CONSTRUCTED SUCH THAT IT CAN BE LAUNCHED IN A VARIETY OF MODES AND INSTALL ITSELF. A SMALL 512 +; BYTE PROXY IS PLACED AT THE TOP OF CPU MEMORY (FE00H-FFFFH). THIS PROXY CODE ALLOWS CODE +; RUNNING FROM ANY BANK TO INVOKE HBIOS FUNCTIONS. NORMALLY, ANY BANK THAT RUNS CODE WOULD SETUP +; THE RST 8 VECTOR TO POINT TO THE PROXY INVOKE ENTRY POINT AT FFF0H. CALLS VIA THE PROXY INVOKE +; ENTRY POINT TRANSPARENTLY SWAP IN THE HBIOS BANK, PERFORM THE REQUESTED FUNCTION, AND RETURN +; WITH THE ORIGINAL BANK ACTIVE. THE CODE USING HBIOS FUNCTIONS DOES NOT NEED TO BE AWARE OF +; THE BANK SWITCHING THAT OCCURS. +; +; THIS FILE CAN BE COMPILED TO BOOT IN ONE OF 3 MODES (ROM, APPLICATION, OR IMAGE) AS DESCRIBED +; BELOW. WHEN COMPILED, YOU MUST DEFINE EXACTLY ONE OF THE FOLLOWING MACROS: +; +; - ROMBOOT: BOOT FROM A ROM BANK +; +; WHEN ROMBOOT IS DEFINED, THE FILE IS ASSEMBLED TO BE IMBEDDED AT THE START OF A ROM +; ASSUMING THAT THE CPU WILL START EXECUTION AT ADDRESS 0. AFTER PERFORMING MINIMAL +; SYSTEM INITIALIZATION, THE IMAGE OF THE RUNNING ROM BANK IS COPIED TO A RAM BANK +; CREATING A SHADOW COPY IN RAM. EXECUTION IS THAN TRANSFERRED TO THE RAM SHADOW COPY. +; THIS IS ESSENTIAL BECAUSE THE HBIOS CODE DOES NOT SUPPORT RUNNING IN READ ONLY MEMORY +; (EXCEPT FOR THE INITIAL LAUNCHING CODE). IN THIS MODE, THE HBIOS INITIALIZATION WILL +; ALSO COPY THE OS IMAGES BANK IN ROM TO THE USER RAM BANK AND LAUNCH IT AFTER HBIOS +; IS INSTALLED. +; +; - APPBOOT: BOOT FROM A CP/M STYLE APPLICATION FILE +; +; WHEN APPBOOT IS DEFINED, THE FILE IS ASSEMBLED AS A CP/M APPLICATION ASSUMING +; THAT IT WILL BE LOADED AT 100H BY THE CP/M (OR COMPATIBLE) OS. NOTE THAT IN +; THIS CASE IT IS ASSUMED THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE +; HBIOS APPLICATION BINARY. THE APPENDED OS IMAGES ARE COPIED TO THE USER RAM +; BANK AND LAUNCHED AFTER HBIOS HAS INSTALLED ITSELF. +; +; - IMGBOOT: BOOT FROM AN IMAGE FILE THAT HAS BEEN PLACED IN THE USER BANK +; +; WHEN IMGBOOT IS DEFINED, THE FILE IS ASSEMBLED SUCH THAT IT CAN BE PRELOADED +; INTO THE RAM USER BANK BY AN EXTERNAL PROCESS THAT SUBSEQUENTLY LAUNCHES +; THE CODE AT ADDRESS 0. THE MOST COMMON EXAMPLE OF THIS IS THE UNA FSFAT +; TOOL WHICH CAN LOAD AN IMAGE FROM A DOS FAT FILESYSTEM PROVIDING A SIMPLE +; WAY TO LOAD A TEST COPY OF HBIOS. AS IS THE CASE WITH APPBOOT, IT IS ASSUMED +; THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE IMAGE AND IS LAUNCHED +; AFTER HBIOS IS INSTALLED. +; +; INCLUDE GENERIC STUFF +; +#INCLUDE "std.asm" +; +; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED. +; +MODCNT .EQU 0 +#IFDEF ROMBOOT +MODCNT .SET MODCNT + 1 +#ENDIF +#IFDEF APPBOOT +MODCNT .SET MODCNT + 1 +#ENDIF +#IFDEF IMGBOOT +MODCNT .SET MODCNT + 1 +#ENDIF +#IF (MODCNT != 1) + .ECHO "*** ERROR: PLEASE DEFINE ONE AND ONLY ONE OF ROMBOOT, APPBOOT, IMGBOOT!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; +; +; +#IF ((PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180)) +#DEFINE DIAGP $00 +#ENDIF +; +#IFDEF DIAGP +#DEFINE DIAG(N) PUSH AF + #DEFCONT \ LD A,N + #DEFCONT \ OUT (DIAGP),A + #DEFCONT \ POP AF +#ELSE +#DEFINE DIAG(N) \; +#ENDIF +; +; +; +#IF (INTMODE == 0) +; NO INTERRUPT HANDLING +#DEFINE HB_DI ; +#DEFINE HB_EI ; +#ENDIF +#IF ((INTMODE == 1) | (INTMODE == 2)) +; MODE 1 OR 2 INTERRUPT HANDLING +#DEFINE HB_DI DI +#DEFINE HB_EI EI +#ENDIF +#IF (INTMODE > 2) + .ECHO "*** ERROR: INVALID INTMODE SETTING!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; +; +; +#IFNDEF APPBOOT +; + .ORG 0 +; +;================================================================================================== +; NORMAL PAGE ZERO SETUP, RET/RETI/RETN AS APPROPRIATE, LEAVE INTERRUPTS DISABLED +;================================================================================================== +; + .FILL (000H - $),0FFH ; RST 0 + JP HB_START + .DW ROM_SIG + .FILL (008H - $),0FFH ; RST 8 + JP HB_INVOKE ; INVOKE HBIOS FUNCTION + .FILL (010H - $),0FFH ; RST 10 + RET + .FILL (018H - $),0FFH ; RST 18 + RET + .FILL (020H - $),0FFH ; RST 20 + RET + .FILL (028H - $),0FFH ; RST 28 + RET + .FILL (030H - $),0FFH ; RST 30 + RET + .FILL (038H - $),0FFH ; RST 38 / IM1 INT +#IF (INTMODE == 1) + JP INT_IM1 ; JP TO INTERRUPT HANDLER IN HI MEM +#ELSE + RETI ; RETURN W/ INTS DISABLED +#ENDIF + .FILL (066H - $),0FFH ; NMI + RETN +; + .FILL (070H - $),0FFH ; SIG STARTS AT $80 +; +ROM_SIG: + .DB $76, $B5 ; 2 SIGNATURE BYTES + .DB 1 ; STRUCTURE VERSION NUMBER + .DB 7 ; ROM SIZE (IN MULTIPLES OF 4KB, MINUS ONE) + .DW NAME ; POINTER TO HUMAN-READABLE ROM NAME + .DW AUTH ; POINTER TO AUTHOR INITIALS + .DW DESC ; POINTER TO LONGER DESCRIPTION OF ROM + .DB 0, 0, 0, 0, 0, 0 ; RESERVED FOR FUTURE USE; MUST BE ZERO +; +NAME .DB "ROMWBW v", BIOSVER, ", ", TIMESTAMP, 0 +AUTH .DB "WBW",0 +DESC .DB "ROMWBW v", BIOSVER, ", Copyright (C) 2015, Wayne Warthen, GNU GPL v3", 0 +; + .FILL ($100 - $),$FF ; PAD REMAINDER OF PAGE ZERO +; +#ENDIF +; +;================================================================================================== +; HBIOS CONFIGURATION BLOCK (HCB) +;================================================================================================== +; + .ORG HCB_LOC +HCB: + JP HB_START +; +CB_MARKER .DB 'W',~'W' ; MARKER +CB_VERSION .DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO + .DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO +; +CB_PLATFORM .DB PLATFORM +CB_CPUMHZ .DB CPUMHZ +CB_CPUKHZ .DW CPUKHZ +CB_RAMBANKS .DB RAMSIZE / 32 +CB_ROMBANKS .DB ROMSIZE / 32 +; +CB_BOOTVOL .DW 0 ; BOOT VOLUME IS UNIT/SLICE, SET BY LOADER +CB_BOOTBID .DB 0 ; BOOT BANK ID, SET BY LOADER +CB_SERDEV .DB 0 ; PRIMARY SERIAL UNIT IS UNIT #0 BY FIAT +CB_CRTDEV .DB $FF ; PRIMARY CRT UNIT, $FF UNTIL AFTER HBIOS INIT +CB_CONDEV .DB $FF ; CONSOLE UNIT, $FF UNTIL AFTER HBIOS INIT +; +; MEMORY MANAGEMENT VARIABLES START AT $20 +; + .FILL (HCB + $20 - $),0 +; +CB_HEAP .DW 0 +CB_HEAPTOP .DW 0 +; +; STANDARD BANK ID'S START AT $D8 +; + .FILL (HCB + $D8 - $),0 +; +CB_BIDCOM .DB BID_COM +CB_BIDUSR .DB BID_USR +CB_BIDBIOS .DB BID_BIOS +CB_BIDAUX .DB BID_AUX +CB_BIDRAMD0 .DB BID_RAMD0 +CB_BIDRAMDN .DB BID_RAMDN +CB_BIDROMD0 .DB BID_ROMD0 +CB_BIDROMDN .DB BID_ROMDN +; + .FILL (HCB + HCB_SIZ - $),0 ; PAD REMAINDER OF HCB +; +;================================================================================================== +; HBIOS UPPER MEMORY PROXY (RELOCATED TO RUN IN TOP 2 PAGES OF CPU RAM) +;================================================================================================== +; +; THE FOLLOWING CODE IS RELOCATED TO THE TOP OF MEMORY TO HANDLE INVOCATION DISPATCHING +; + .FILL (HBX_IMG - $) ; FILL TO START OF PROXY IMAGE START + .ORG HBX_LOC ; ADJUST FOR RELOCATION +; +; MEMORY LAYOUT: +; +; HBIOS PROXY CODE $FE00 (256 BYTES) +; INTERRUPT VECTORS $FF00 (32 BYTES, 16 ENTRIES) +; INTERRUPT HANDLER STUBS $FF20 (128 BYTES) +; HBIOS PROXY COPY BUFFER $FF80 (64 BYTES) +; HBIOS PROXY MGMT BLOCK $FFE0 (32 BYTES) +; +; DEFINITIONS +; +HBX_BUFSIZ .EQU $40 ; INTERBANK COPY BUFFER SIZE +; +; HBIOS IDENTIFICATION DATA BLOCK +; +HBX_IDENT: + .DB 'W',~'W' ; MARKER + .DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO + .DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO +; +;================================================================================================== +; HBIOS ENTRY FOR RST 08 PROCESSING +;================================================================================================== +; +HBX_INVOKE: + LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME + LD A,(HB_CURBNK) ; GET CURRENT BANK + LD (HB_INVBNK),A ; SAVE INVOCATION BANK + + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH + LD A,BID_BIOS ; HBIOS BANK + CALL HBX_BNKSEL ; SELECT IT + LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK + + CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER + + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH + PUSH AF ; SAVE AF (FUNCTION RETURN) + + LD A,(HB_INVBNK) ; LOAD ORIGINAL BANK + CALL HBX_BNKSEL ; SELECT IT + POP AF ; RESTORE AF + LD SP,0 ; RESTORE ORIGINAL STACK FRAME +HBX_INVSP .EQU $ - 2 + + RET ; RETURN TO CALLER +; +;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +;; BNKSEL - Switch Memory Bank to Bank in A. +;; Preserve all Registers including Flags. +;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +; +HBX_BNKSEL: + ; IF AN INTERRUPT OCCURS DURING THE BANK SWITCH CODE, + ; THE BANK WILL BE SET TO (CURBNK) AS THE INTERRUPT + ; RETURNS. SO, IT IS IMPORTANT THAT (HB_CURBNK) BE + ; SET AS THE FIRST STEP TO AVOID ISSUES IF AN INTERRUPT + ; OCCURS DURING PROCESSING. + LD (HB_CURBNK),A ; RECORD NEW CURRENT BANK +; +HBX_BNKSEL_INT: +; +#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) + #IF (INTMODE == 1) + ; THIS BIT OF ABSURDITY HANDLES A RARE (BUT FATAL) SITUATION + ; WHERE AN IM1 INTERRUPT OCCURS BETWEEN SETTING THE RAM AND + ; ROM SELECTORS. BRACKETING THE INSTRUCTIONS WITH DI/EI + ; IS CONTRAINDICATED BECAUSE THIS ROUTINE IS CALLED BY + ; OTHER ROUTINES THAT MUST CONTROL INT ENABLE AT A HIGHER + ; LEVEL. THE FOLLOWING TECHNIQUE ENSURES THAT YOU ALWAYS + ; SWITCH DIRECTLY FROM THE PREVIOUS BANK TO THE TARGET BANK + ; WITHOUT AN "ERRANT" BANK BEING ACTIVE BETWEEN THE TWO + ; BANK SELECTION I/O INSTRUCTIONS. THE TECHNIQUE IS ONLY + ; NEEDED WHEN USING INT MODE 1 BECAUSE THAT MODE REQUIRES + ; PAGE ONE TO HAVE A VALID INT HANDLER WHENEVER INTS ARE + ; ENABLED. + ;BIT 7,A ; [8] TEST RAM BIT + ;JR Z,HBX_ROM ; [12/7] IF NOT SET, JUST DO ROM + OR A ; [4] SET FLAGS + JP P,HBX_ROM ; [10] BIT 7 INDICATES RAM + #ENDIF + OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR +HBX_ROM: + OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR + RET ; DONE +#ENDIF +#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80)) + BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE + JR Z,HBX_ROM ; NOT SET, SELECT ROM PAGE + RES 7,A ; RAM PAGE REQUESTED: CLEAR ROM BIT + ADD A,16 ; ADD 16 x 32K - RAM STARTS FROM 512K +; +HBX_ROM: + RLCA ; TIMES 2 - GET 16K PAGE INSTEAD OF 32K + OUT (MPGSEL_0),A ; BANK_0: 0K - 16K + ;OUT (DIAGP),A ; *DEBUG* + INC A ; + OUT (MPGSEL_1),A ; BANK_1: 16K - 32K + RET ; DONE +#ENDIF +#IF (PLATFORM == PLT_N8) + BIT 7,A ; TEST BIT 7 FOR RAM VS. ROM + JR Z,HBX_ROM ; IF NOT SET, SELECT ROM PAGE +; +HBX_RAM: + RES 7,A ; CLEAR BIT 7 FROM ABOVE + RLCA ; SCALE SELECTOR TO + RLCA ; ... GO FROM Z180 4K PAGE SIZE + RLCA ; ... TO DESIRED 32K PAGE SIZE + OUT0 (Z180_BBR),A ; WRITE TO BANK BASE + LD A,N8_DEFACR | 80H ; SELECT RAM BY SETTING BIT 7 + OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER + RET ; DONE +; +HBX_ROM: + OUT0 (N8_RMAP),A ; BANK INDEX TO N8 RMAP REGISTER + XOR A ; ZERO ACCUM + OUT0 (Z180_BBR),A ; ZERO BANK BASE + LD A,N8_DEFACR ; SELECT ROM BY CLEARING BIT 7 + OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER + RET ; DONE +; +#ENDIF +#IF (PLATFORM == PLT_MK4) + RLCA ; RAM FLAG TO CARRY FLAG AND BIT 0 + JR NC,HBX_BNKSEL1 ; IF NC, WANT ROM PAGE, SKIP AHEAD + XOR %00100001 ; SET BIT FOR HI 512K, CLR BIT 0 +HBX_BNKSEL1: + RLCA ; CONTINUE SHIFTING TO SCALE SELECTOR + RLCA ; FOR Z180 4K PAGE -> DESIRED 32K PAGE + OUT0 (Z180_BBR),A ; WRITE TO BANK BASE + RET ; DONE +#ENDIF +; +;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Copy Data - Possibly between banks. This resembles CP/M 3, but +; usage of the HL and DE registers is reversed. +; Caller MUST ensure stack is already in high memory. +; Caller MUST preset HBX_SRCBNK and HBX_DSTBNK. +; Caller MUST disable ints if IM1 active +; Enter: +; HL = Source Address +; DE = Destination Address +; BC = Number of bytes to copy +; Exit : None +; Uses : AF,BC,DE,HL +; +;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +; +HBX_BNKCPY: + LD (HBX_BC_SP),SP ; PUT STACK + LD SP,HBX_TMPSTK ; ... IN HI MEM + + LD A,(HB_CURBNK) ; GET CURRENT BANK + PUSH AF ; AND SAVE TO RESTORE LATER + PUSH BC ; CUR LEN -> (SP) +; +HBX_BC_LOOP: + EX (SP),HL ; HL := CUR LEN, (SP) := CUR SRC + LD BC,HBX_BUFSIZ ; SET BC TO BOUNCE BUFFER SIZE + OR A ; CLEAR CARRY FLAG + SBC HL,BC ; CUR LEN := CUR LEN - BBUF SIZE + JR C,HBX_BC_LAST ; END GAME, LESS THAN BBUF BYTES LEFT + EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN + CALL HBX_BC_ITER ; DO A FULL BBUF SIZE CHUNK + JR HBX_BC_LOOP ; AND REPEAT TILL DONE +; +HBX_BC_LAST: + ; HL IS BETWEEN -(BBUF SIZE) AND -1, BC = BBUF SIZE + OR A ; CLEAR CARRY + ADC HL,BC ; HL := REM LEN (0 - 127) + EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN + POP BC ; BC := REM LEN + CALL NZ,HBX_BC_ITER ; DO FINAL CHUNK, IFF > 0 BYTES + POP AF ; RECOVER ORIGINAL BANK + CALL HBX_BNKSEL ; SWITCH + + LD SP,$FFFF ; RESTORE STACK +HBX_BC_SP .EQU $ - 2 ; ... TO ORIGINAL VALUE + RET +; +HBX_BC_ITER: + ; HL = SRC ADR, DE = DEST ADR, BC = LEN + PUSH BC ; SAVE COPY LEN + PUSH DE ; FINAL DEST ON STACK + LD DE,HBX_BUF ; SET DEST TO BUF + LD A,(HB_SRCBNK) ; GET SOURCE BANK + CALL HBX_BNKSEL ; SWITCH TO SOURCE BANK + LDIR ; HL -> BUF (DE), BC BYTES, HL UPDATED SRC ADR + POP DE ; DE := FINAL DEST + POP BC ; GET LEN BACK IN BC + PUSH HL ; SAVE UPDATED SRC ADR + LD HL,HBX_BUF ; SET SRC ADR TO BUF + LD A,(HB_DSTBNK) ; GET DEST BANK + CALL HBX_BNKSEL ; SWITCH TO DEST BANK + LDIR ; BUF (HL) -> DE, BC BYTES, DE UPDATED DEST ADR + POP HL ; RECOVER UPDATED SRC ADR + ; HL = UPDATED SRC, DE = UPDATED DEST, BC = 0 + RET +; +; CALL A ROUTINE IN ANOTHER BANK. +; CALLER MUST ENSURE STACK IS ALREADY IN HIGH MEMORY AND HAS ADEQUATE SPACE. +; IF IM1 INTERRUPTS ARE POSSIBLE, CALLER MUST EITHER DISABLE THEM PRIOR TO +; BNKCALL OR MAKE SURE THAT PAGE ZERO IN TARGTET BANK IS PREPARED FOR THEM. +; ON INPUT A=TARGET BANK, HL=TARGET ADDRESS +; +HBX_BNKCALL: + LD (HBX_TGTBNK),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW + LD (HBX_TGTADR),HL ; STUFF ADDRESS TO CALL INTO CODE BELOW + LD A,(HB_CURBNK) ; GET CURRENT BANK + PUSH AF ; SAVE FOR RETURN +HBX_TGTBNK .EQU $ + 1 + LD A,$FF ; LOAD BANK TO CALL ($FF OVERLAID AT ENTRY) + CALL HBX_BNKSEL ; ACTIVATE THE NEW BANK + +HBX_TGTADR .EQU $ + 1 + CALL $FFFF ; CALL ROUTINE ($FFFF IS OVERLAID ABOVE) + + EX (SP),HL ; SAVE HL AND GET BANK TO RESTORE IN HL + PUSH AF ; SAVE AF + LD A,H ; BANK TO RESTORE TO A + CALL HBX_BNKSEL ; RESTORE IT + POP AF ; RECOVER AF + POP HL ; RECOVER HL + RET +; +; PEEK & POKE ROUTINES +; ADDRESS IN HL, BANK IN D, VALUE IN/OUT IN E, A IS TRASHED +; CALLER MUST DISABLE INTS IF IM1 AND ACCESSING PAGE W/O IM1 INT VECTOR +; +HBX_PEEK: + LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM + LD A,(HB_CURBNK) + PUSH AF + LD A,D + CALL HBX_BNKSEL + LD E,(HL) + JR HBX_PPRET +; +HBX_POKE: + LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM + LD A,(HB_CURBNK) + PUSH AF + LD A,D + CALL HBX_BNKSEL + LD (HL),E +; +HBX_PPRET: + POP AF + CALL HBX_BNKSEL + LD SP,0 ; RESTORE ORIGINAL STACK FRAME +HBX_PPSP .EQU $ - 2 + RET +; +; SMALL TEMPORARY STACK FOR USE BY INVOKE, PEEK, AND POKE +; + .FILL 20,$CC ; 10 LEVEL STACK +HBX_TMPSTK .EQU $ +; +; PRIVATE STACK AT END OF HBIOS CODE +; OCCUPIES SPACE BEFORE IVT +; +HBX_STKSIZ .EQU $FF00 - $ + .ECHO "HBIOS PROXY STACK space: " + .ECHO HBX_STKSIZ + .ECHO " bytes.\n" + .FILL HBX_STKSIZ,$FF +HBX_STACK .EQU $ +; +#IF (INTMODE == 2) +; +; HBIOS INTERRUPT VECTOR TABLE (16 ENTRIES) +; +HBX_IVT: + .DW INT_BAD ; IVT_INT1 + .DW INT_BAD ; IVT_INT2 + .DW INT_BAD ; IVT_TIM0 + .DW INT_BAD ; IVT_TIM1 + .DW INT_BAD ; IVT_DMA0 + .DW INT_BAD ; IVT_DMA1 + .DW INT_BAD ; IVT_CSIO + .DW INT_BAD ; IVT_SER0 + .DW INT_BAD ; IVT_SER1 + .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 ; +; +HBX_IVTCNT .EQU ($ - HBX_IVT) / 2 +; +HBX_ITBL: + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT + .DW HB_BADINT +#ENDIF +; +; INTERRUPT HANDLER STUBS +; +; THE FOLLOWING INTERRUPT STUBS RECEIVE CONTROL FROM THE +; INTERRUPT, SETUP A HANDLER VECTOR IN HBIOS AND THEN +; BRANCH TO THE COMMON INTERRUPT DISPATCHER +; +; +INT_IM1: +#IF (INTMODE == 1) + PUSH HL ; SAVE HL + LD HL,HB_IM1INT ; HL := IM1 INT HANDLER IN BIOS BANK + JR HBX_INT ; TO TO ROUTING CODE +#ELSE + RETI ; UNEXPECTED INT, RET W/ INTS LEFT DISABLED +#ENDIF +; +#IF (INTMODE == 2) +; +INT_BAD: ; BAD INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,HB_BADINT ; HL := INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +; +INT_TIMER: ; TIMER INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,HB_TIMINT ; HL := INT ADR IN BIOS + JR HBX_INT ; GO TO ROUTING CODE +; + #IF (SIOENABLE) +INT_SIO: ; SIO INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,SIO_INT ; HL := SIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE + #ENDIF +; +#IF (PIO_ZP) +INT_ZP0: ; PIO INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,PIO0INT ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +INT_ZP1 + PUSH HL ; SAVE HL + LD HL,PIO1INT ; 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,PIO2INT ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +INT_4P1: + PUSH HL ; SAVE HL + LD HL,PIO3INT ; HL := PIO INT HANDLER IN BIOS BANK + JR HBX_INT ; GO TO ROUTING CODE +#ENDIF +; +#ENDIF +; +#IF (INTMODE > 0) +; +; COMMON INTERRUPT DISPATCHING CODE +; SETUP AND CALL HANDLER IN BIOS BANK +; +HBX_INT: ; COMMON INTERRUPT ROUTING CODE +; + LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME + LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM + + ; SAVE STATE (HL SAVED PREVIOUSLY ON ORIGINAL STACK FRAME) + PUSH AF ; SAVE AF + PUSH BC ; SAVE BC + PUSH DE ; SAVE DE + PUSH IY ; SAVE IY + + LD A,BID_IMG0 ; HBIOS BANK + CALL HBX_BNKSEL_INT ; SELECT IT + + CALL JPHL ; CALL INTERRUPT ROUTINE + + LD A,(HB_CURBNK) ; GET PRE-INT BANK + CALL HBX_BNKSEL ; SELECT IT + + ; RESTORE STATE + POP IY ; RESTORE IY + POP DE ; RESTORE DE + POP BC ; RESTORE BC + POP AF ; RESTORE AF + + LD SP,$FFFF ; RESTORE ORIGINAL STACK FRAME +HBX_INT_SP .EQU $ - 2 + + POP HL ; RESTORE HL + + HB_EI ; ENABLE INTERRUPTS + RETI ; AND RETURN +; +#ENDIF +; +; FILL TO START OF BOUNCE BUFFER +; +HBX_INTFILL .EQU (HBX_XFC - HBX_BUFSIZ - $) + .ECHO "HBIOS INT space remaining: " + .ECHO HBX_INTFILL + .ECHO " bytes.\n" + .FILL HBX_INTFILL,$FF +; +; INTERBANK COPY BUFFER (64 BYTES) +; +HBX_BUF .FILL HBX_BUFSIZ,0 +; +; HBIOS PROXY MGMT BLOCK (TOP 32 BYTES) +; +#IFDEF ROMBOOT + .DB BID_BOOT ; CURRENTLY ACTIVE LOW MEMORY BANK ID +#ELSE + .DB BID_USR ; CURRENTLY ACTIVE LOW MEMORY BANK ID +#ENDIF + .DB 0 ; BANK ACTIVE AT TIME OF HBIOS CALL INVOCATION + .DW 0 ; BNKCPY SOURCE ADDRESS + .DB BID_USR ; BNKCPY SOURCE BANK ID + .DW 0 ; BNKCPY DESTINATION ADDRESS + .DB BID_USR ; BNKCPY DESTINATION BANK ID + .DW 0 ; BNKCPY LENGTH + .FILL 6,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE + JP HBX_INVOKE ; FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08) + JP HBX_BNKSEL ; FIXED ADR ENTRY FOR HBX_BNKSEL + JP HBX_BNKCPY ; FIXED ADR ENTRY FOR HBX_BNKCPY + JP HBX_BNKCALL ; FIXED ADR ENTRY FOR HBX_BNKCALL + .DW HBX_IDENT ; ADDRESS OF HBIOS PROXY START (DEPRECATED) + .DW HBX_IDENT ; ADDRESS OF HBIOS IDENT INFO DATA BLOCK +; + .FILL $MEMTOP - $ ; FILL TO END OF MEMORY (AS NEEDED) + .ORG HBX_IMG + HBX_SIZ ; RESET ORG +; +;================================================================================================== +; HBIOS CORE +;================================================================================================== +; +;================================================================================================== +; ENTRY VECTORS (JUMP TABLE) AND INTERNAL PROCESSING STACK +;================================================================================================== +; +HB_ENTRYTBL .EQU $ +; + JP HB_START ; HBIOS INITIALIZATION + JP HB_DISPATCH ; VECTOR TO DISPATCHER +; +HB_STKSIZ .EQU HB_ENTRYTBL + 256 - $ +; + .FILL HB_STKSIZ,$FF ; USE REMAINDER OF PAGE FOR HBIOS STACK +HB_STACK .EQU $ ; TOP OF HBIOS STACK + +; +;================================================================================================== +; SYSTEM INITIALIZATION +;================================================================================================== +; +HB_START: + DI ; NO INTERRUPTS + IM 1 ; INTERRUPT MODE 1 +; +#IFDEF DIAGP + LD A,%00000001 + OUT (DIAGP),A +#ENDIF +; + LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY +; +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + ; SET BASE FOR CPU IO REGISTERS + LD A,Z180_BASE + OUT0 (Z180_ICR),A + + DIAG(%00000010) + + ; DISABLE REFRESH + XOR A + OUT0 (Z180_RCR),A + + ; MASK OFF TIMER INTERRUPTS + XOR A + OUT0 (Z180_TCR),A + + ; SET DEFAULT CPU CLOCK MULTIPLIERS (XTAL / 2) + XOR A + OUT0 (Z180_CCR),A + OUT0 (Z180_CMR),A + + ; SET DEFAULT WAIT STATES + LD A,$F0 + OUT0 (Z180_DCNTL),A + +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) + ; MMU SETUP + LD A,$80 + OUT0 (Z180_CBAR),A ; SETUP FOR 32K/32K BANK CONFIG +;#IFDEF ROMBOOT +; XOR A +; OUT0 (Z180_BBR),A ; BANK BASE = 0 +;#ENDIF + LD A,(RAMSIZE + RAMBIAS - 64) >> 2 + OUT0 (Z180_CBR),A ; COMMON BASE = LAST (TOP) BANK +#ENDIF + +#IF (Z180_CLKDIV >= 1) + ; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED + LD A,$80 + OUT0 (Z180_CCR),A +#ENDIF + +#IF (Z180_CLKDIV >= 2) + ; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED + LD A,$80 + OUT0 (Z180_CMR),A +#ENDIF + +#ENDIF +; +#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80)) + ; SET PAGING REGISTERS +#IFDEF ROMBOOT + XOR A + OUT (MPGSEL_0),A + INC A + OUT (MPGSEL_1),A +#ENDIF + LD A,62 + OUT (MPGSEL_2),A + INC A + OUT (MPGSEL_3),A + ; ENABLE PAGING + LD A,1 + OUT (MPGENA),A +#ENDIF +; + DIAG(%00000011) +; +; INSTALL PROXY IN UPPER MEMORY +; + +;X1 .EQU $8000 +;X2 .EQU X1 + 2 +;X3 .EQU X2 + 2 +;X4 .EQU X3 + 2 + +; LD HL,(HBX_IMG) +; LD (X1),HL + +; LD HL,(HBX_IMG) +; LD (X2),HL + + LD HL,HBX_IMG + LD DE,HBX_LOC + LD BC,HBX_SIZ + LDIR + +; LD HL,(HBX_IMG) +; LD (X3),HL + +; LD HL,(HBX_LOC) +; LD (X4),HL + +; +; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION +; + LD A,(HB_RAMFLAG) + OR A + JR NZ,HB_START1 +; +; INSTALL HBIOS IN RAM BANK +; + LD A,(HB_CURBNK) + LD (HB_SRCBNK),A + LD A,BID_BIOS + LD (HB_DSTBNK),A + LD HL,0 + LD DE,0 + LD BC,$8000 + CALL HBX_BNKCPY +; +; TRANSITION TO HBIOS IN RAM BANK +; + LD A,BID_BIOS ; BIOS BANK ID + LD HL,HB_START1 ; EXECUTION RESUMES HERE + CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN + HALT ; WE SHOULD NOT COME BACK HERE! +; +HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION +; +; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK +; +HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK +; + DIAG(%00000111) +; + LD SP,HBX_LOC ; RESET STACK SINCE WE DO NOT RETURN + LD A,TRUE ; ACCUM := TRUE + LD (HB_RAMFLAG),A ; SET RAMFLAG +; +; IF APPBOOT, WE NEED TO FIX UP A FEW THINGS IN PAGE ZERO +; +#IFDEF APPBOOT + ; MAKE SURE RST 08 VECTOR IS RIGHT + LD A,$C3 + LD ($0008),A + LD HL,HB_INVOKE + LD ($0009),HL +; + ; MAKE SURE IM1 INT VECTOR IS RIGHT + #IF (INTMODE == 1) + ; JP INT_IM1 IF INTERRUPT MODE ACTIVE + LD A,$C3 + LD ($0038),A + LD HL,INT_IM1 + LD ($0039),HL + #ELSE + ; RETI ($ED, $4D) IF NON-INTERRUPT MODE + LD HL,($0038) + LD (HL),$ED + INC HL + LD (HL),$4D + #ENDIF +#ENDIF +; + DIAG(%00001111) +; +#IF (DSKYENABLE) + LD HL,MSG_HBVER + CALL DSKY_SHOWSEG +#ENDIF +; +; PERFORM DYNAMIC CPU SPEED DERIVATION +; + CALL HB_CPUSPD ; CPU SPEED DETECTION +; +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) +; + ; SET DESIRED WAIT STATES + LD A,0 + (Z180_MEMWAIT << 6) | (Z180_IOWAIT << 4) + OUT0 (Z180_DCNTL),A +; +#ENDIF +; + CALL DELAY_INIT ; INITIALIZE SPEED COMPENSATED DELAY FUNCTIONS +; + DIAG(%00011111) +; +; INITIALIZE HEAP STORAGE +; + ; INITIALIZE POINTERS + LD HL,HB_END ; HEAP FOLLOWS HBIOS CODE + LD (CB_HEAP),HL ; INIT HEAP BASE ADDRESS + LD (CB_HEAPTOP),HL ; INIT HEAP TOP ADDRESS + ; CLEAR HEAP + LD BC,BNKTOP - HB_END ; MAX SIZE OF HEAP + LD A,$FF ; FILL WITH $FF + CALL FILL ; DO IT +; + DIAG(%00111111) +; +; PRE-CONSOLE INITIALIZATION +; +#IF (ASCIENABLE) + CALL ASCI_PREINIT +#ENDIF +#IF (UARTENABLE) + CALL UART_PREINIT +#ENDIF +#IF (SIOENABLE) + CALL SIO_PREINIT +#ENDIF +#IF (ACIAENABLE) + CALL ACIA_PREINIT +#ENDIF +#IF (PIO_4P | PIO_ZP) + CALL PIO_PREINIT +#ENDIF +; + DIAG(%01111111) +; +; PRIOR TO THIS POINT, CONSOLE I/O WAS DIRECTED TO HARDWARE (XIO.ASM). +; NOW THAT HBIOS IS READY, SET THE CONSOLE UNIT TO ACTIVATE CONSOLE I/O +; VIA HBIOS. +; + XOR A ; INITIALLY, FIRST SERIAL UNIT IS CONSOLE + LD (CB_CONDEV),A ; SAVE IT, ACTIVATES CONSOLE ON HBIOS +; +; ANNOUNCE HBIOS +; + CALL NEWLINE2 + PRTX(STR_BANNER) +; + DIAG(%11111111) +; +; IO PORT SCAN +; +#IF 0 +PSCN: + LD C,0 ; IO PORT NUMBER + LD B,0 ; LOOP COUNTER + CALL NEWLINE +PSCN1: + CALL NEWLINE + LD A,C + CALL PRTHEXBYTE + CALL PC_COLON + CALL PC_SPACE + CALL DELAY + LD A,C + LD (PSCNX),A +PSCNX .EQU $ + 1 + IN A,(0) + CALL PRTHEXBYTE + CALL PC_COMMA + PUSH BC + LD B,0 + IN A,(C) + POP BC + CALL PRTHEXBYTE + INC C + DJNZ PSCN1 +#ENDIF +; +; SETUP INTERRUPT VECTORS, AS APPROPRIATE +; +;#IF (INTMODE == 1) +; ; OVERLAY $0038 WITH JP INT_IM1 +; LD A,$C3 ; JP INSTRUCTION +; LD ($0038),A ; INSTALL IT +; LD HL,INT_IM1 ; DESTINATION ADDRESS +; LD ($0039),HL ; INSTALL IT +;#ENDIF +; +#IF (INTMODE == 2) + ; SETUP Z80 IVT AND INT MODE 2 + LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS + LD I,A ; ... AND PLACE IT IN I REGISTER + + #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + ; SETUP Z180 IVT + XOR A ; SETUP LO BYTE OF IVT ADDRESS + OUT0 (Z180_IL),A ; ... AND PLACE IN Z180 IL REGISTER + #ENDIF + + IM 2 ; SWITCH TO INT MODE 2 +#ENDIF + +#IF (PLATFORM == PLT_SBC) +; + #IF (HTIMENABLE) ; SIMH TIMER +; + #IF (INTMODE == 1) + LD HL,HB_TIMINT + CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST + #ENDIF +; + #IF (INTMODE == 2) + ;LD HL,INT_TIMER + ;LD (HBX_IVT),HL + #ENDIF +; + #ENDIF +; +#ENDIF +; +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) +; + #IF (INTMODE == 2) +; + ; MASK ALL EXTERNAL INTERRUPTS FOR NOW + ;XOR A ; INT0-2 DISABLED + LD A,$01 ; INT0 ENABLED, INT1-2 DISABLED + OUT0 (Z180_ITC),A ; WRITE TO INT/TRAP CONTROL REGISTER +; + ; SETUP Z180 TIMER0 INTERRUPT VECTOR IN IVT + LD HL,INT_TIMER + LD (HBX_IVT + IVT_TIM0),HL + + ; SETUP PERIODIC TIMER INTERRUPT ON TIMER 0 + LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ + LD B,0 + LD C,Z180_RLDR0L ; INITIALIZE TIMER 0 RELOAD REGISTER + OUT (C),L + INC C + OUT (C),H + LD C,Z180_TMDR0L ; INITIALIZE TIMER 0 DATA REGISTER + OUT (C),L + INC C + OUT (C),H + LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING + OUT0 (Z180_TCR),A +; + #ENDIF +; +#ENDIF +; + HB_EI ; INTERRUPTS SHOULD BE OK NOW +; +; DISPLAY PLATFORM INFORMATION +; + CALL NEWLINE2 + PRTX(STR_PLATFORM) + PRTS(" @ $") + LD HL,(CB_CPUKHZ) + CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA + PRTS("MHz$") +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + CALL PC_COMMA + PRTS(" IO=0x$") + LD A,Z180_BASE + CALL PRTHEXBYTE +#ENDIF +; +; DISPLAY CPU CONFIG +; + ;CALL PRTSTRD + ;.TEXT ", $" + CALL NEWLINE +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + LD A,Z180_MEMWAIT +#ELSE + LD A,0 +#ENDIF + CALL PRTDECB + CALL PRTSTRD + .TEXT " MEM W/S, $" +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + LD A,Z180_IOWAIT + 1 +#ELSE + LD A,1 +#ENDIF + CALL PRTDECB + CALL PRTSTRD + .TEXT " I/O W/S$" +#IF (INTMODE > 0) + CALL PRTSTRD + .TEXT ", INT MODE $" + LD A,INTMODE + CALL PRTDECB +#ENDIF +; +; DISPLAY MEMORY CONFIG +; + CALL NEWLINE + ;CALL PRTSTRD + ;.TEXT "MEMORY CONFIG: $" + LD HL,ROMSIZE + CALL PRTDEC + CALL PRTSTRD + .TEXT "KB ROM, $" + LD HL,RAMSIZE + CALL PRTDEC + CALL PRTSTRD + .TEXT "KB RAM$" +; +; PERFORM DEVICE INITIALIZATION +; + CALL NEWLINE + LD B,HB_INITTBLLEN + LD DE,HB_INITTBL +INITSYS1: + LD A,(DE) + LD L,A + INC DE + LD A,(DE) + LD H,A + INC DE + PUSH DE + PUSH BC + CALL JPHL + POP BC + POP DE + DJNZ INITSYS1 +; +; RECORD HEAP CURB AT THE CURRENT VALUE OF HEAP TOP. HEAP CURB +; MARKS THE POINT IN THE HEAP AFTER WHICH MEMORY IS RELEASED +; WHEN AN HBIOS RESET IS PEFORMED. +; + LD HL,(CB_HEAPTOP) + LD (HEAPCURB),HL +; +; NOW SWITCH TO CRT CONSOLE IF CONFIGURED +; +#IF CRTACT +; +; BIOS IS CONFIGURED TO AUTO ACTIVATE CRT DEVICE. FIRST, +; CHECK TO SEE IF WE HAVE A VALID CRT DEVICE TO USE. +; + LD A,(CB_CRTDEV) ; GET THE CRT DEVICE + INC A ; INCREMENT TO TEST FOR $FF + JR Z,INITSYS3 ; IF NO CRT DEVICE, BYPASS CONSOLE SWITCH +; +; IF PLATFORM HAS A CONFIG JUMPER, CHECK TO SEE IF IT IS JUMPERED. +; IF SO, BYPASS SWITCH TO CRT CONSOLE (FAILSAFE MODE) +; +#IF ((PLATFORM != PLT_N8) & (PLATFORM != PLT_MK4) & (PLATFORM != PLT_RC) & (PLATFORM != PLT_RC180) & (PLATFORM != PLT_EZZ80)) + IN A,(RTC) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER + BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE + JR Z,INITSYS3 ; Z=SHORTED, BYPASS CONSOLE SWITCH +#ENDIF +; + ; NOTIFY USER OF CONSOLE SWITCH ON BOOT CONSOLE + CALL NEWLINE2 + PRTX(STR_SWITCH) + CALL NEWLINE +; + ; SWITCH TO CRT CONSOLE + LD A,(CB_CRTDEV) ; GET CRT DISPLAY DEVICE + LD (CB_CONDEV),A ; SAVE IT AS ACTIVE CONSOLE DEVICE +; + ; DISPLAY HBIOS BANNER ON NEW CONSOLE + PRTX(STR_BANNER) +#ENDIF +; +INITSYS3: +; + CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE +; +; CHAIN TO OS LOADER +; +#IFDEF ROMBOOT + ; PERFORM BANK CALL TO OS IMAGES BANK IN ROM + LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK + LD HL,0 ; ENTER AT ADDRESS 0 + CALL HBX_BNKCALL ; GO THERE + HALT ; WE SHOULD NEVER COME BACK! +#ELSE + ; COPY OS IMAGE: BID_USR: --> BID_USR:0 + ;LD A,BID_USR + ;LD (HB_SRCBNK),A + ;LD (HB_DSTBNK),A + ;LD HL,HB_END + ;LD DE,0 + ;LD BC,$8000 + ;CALL HBX_BNKCPY + LD B,BF_SYSSETCPY ; HBIOS FUNC: SETUP BANK COPY + LD D,BID_USR ; D = DEST BANK = USER BANK + LD E,BID_USR ; E = SRC BANK = USER BANK + LD HL,$8000 ; HL = COPY LEN = ENTIRE BANK + RST 08 ; DO IT + LD B,BF_SYSBNKCPY ; HBIOS FUNC: PERFORM BANK COPY + LD HL,HB_END ; COPY FROM END OF OF HBIOS + LD DE,0 ; TO USER ADDRESS 0 + RST 08 ; DO IT +; + ; PERFORM BANK CALL TO USER BANK + LD A,BID_USR ; CHAIN TO OS IMAGES BANK + LD HL,0 ; ENTER AT ADDRESS 0 + CALL HBX_BNKCALL ; GO THERE + HALT ; WE SHOULD NEVER COME BACK! +; +#ENDIF +; + RET +; +;================================================================================================== +; TABLE OF INITIALIZATION ENTRY POINTS +;================================================================================================== +; +HB_INITTBL: +#IF (SPKENABLE) + .DW SPK_INIT ; AUDIBLE INDICATOR OF BOOT START +#ENDIF +#IF (AYENABLE) + .DW AY_INIT ; AUDIBLE INDICATOR OF BOOT START +#ENDIF +#IF (ASCIENABLE) + .DW ASCI_INIT +#ENDIF +#IF (UARTENABLE) + .DW UART_INIT +#ENDIF +#IF (SIOENABLE) + .DW SIO_INIT +#ENDIF +#IF (ACIAENABLE) + .DW ACIA_INIT +#ENDIF +#IF (SIMRTCENABLE) + .DW SIMRTC_INIT +#ENDIF +#IF (DSRTCENABLE) + .DW DSRTC_INIT +#ENDIF +#IF (VDUENABLE) + .DW VDU_INIT +#ENDIF +#IF (CVDUENABLE) + .DW CVDU_INIT +#ENDIF +#IF (VGAENABLE) + .DW VGA_INIT +#ENDIF +#IF (NECENABLE) + .DW NEC_INIT +#ENDIF +#IF (TMSENABLE) + .DW TMS_INIT +#ENDIF +#IF (DSKYENABLE) + .DW DSKY_INIT +#ENDIF +#IF (MDENABLE) + .DW MD_INIT +#ENDIF +#IF (FDENABLE) + .DW FD_INIT +#ENDIF +#IF (RFENABLE) + .DW RF_INIT +#ENDIF +#IF (IDEENABLE) + .DW IDE_INIT +#ENDIF +#IF (PPIDEENABLE) + .DW PPIDE_INIT +#ENDIF +#IF (SDENABLE) + .DW SD_INIT +#ENDIF +#IF (HDSKENABLE) + .DW HDSK_INIT +#ENDIF +#IF (PRPENABLE) + .DW PRP_INIT +#ENDIF +#IF (PPPENABLE) + .DW PPP_INIT +#ENDIF +#IF (PIO_4P | PIO_ZP) + .DW PIO_INIT +#ENDIF +; +HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2) +; +;================================================================================================== +; IDLE +;================================================================================================== +; +;__________________________________________________________________________________________________ +; +IDLE: + PUSH AF + PUSH BC + PUSH DE + PUSH HL + PUSH IY +#IF (FDENABLE) + CALL FD_IDLE +#ENDIF + POP IY + POP HL + POP DE + POP BC + POP AF + RET +; +;================================================================================================== +; BIOS FUNCTION DISPATCHER +;================================================================================================== +; +; MAIN BIOS FUNCTION +; B: FUNCTION +;__________________________________________________________________________________________________ +; +HB_DISPATCH: +; +#IF 0 ; *DEBUG* START +; + CALL HB_DISPCALL ; DO THE WORK +; + ; CHECK STACK INTEGRITY + PUSH AF + LD A,(HB_STACK - HB_STKSIZ + $08) + CP $FF + CALL NZ,PANIC + LD A,$FF + LD (HB_STACK - HB_STKSIZ + $08),A + POP AF + RET +HB_DISPCALL: +; +#ENDIF ; *DEBUG* END +; + LD A,B ; REQUESTED FUNCTION IS IN B + CP BF_CIO + $10 ; $00-$0F: CHARACTER I/O + JP C,CIO_DISPATCH + CP BF_DIO + $10 ; $10-$1F: DISK I/O + JP C,DIO_DISPATCH + CP BF_RTC + $10 ; $20-$2F: REAL TIME CLOCK (RTC) + JP C,RTC_DISPATCH + CP BF_EMU + $10 ; $30-$3F: EMULATION + CALL C,PANIC ; OBSOLETE! + CP BF_VDA + $10 ; $40-$4F: VIDEO DISPLAY ADAPTER + JP C,VDA_DISPATCH + CP BF_SYS ; SKIP TO BF_SYS VALUE AT $F0 + CALL C,PANIC ; PANIC IF LESS THAN BF_SYS + JP SYS_DISPATCH ; OTHERWISE SYS CALL + CALL PANIC ; THIS SHOULD NEVER BE REACHED + RET +; +;================================================================================================== +; CHARACTER I/O DEVICE FUNCTION DISPATCHER +;================================================================================================== +; +; ROUTE CALL TO SPECIFIED CHARACTER I/O DRIVER +; B: FUNCTION +; C: UNIT NUMBER +; +CIO_DISPATCH: + BIT 7,C ; CHECK FOR SPECIAL UNIT CODE + CALL NZ,CIO_SPECIAL ; IF SO, HANDLE IT + + PUSH IY ; SAVE INCOMING IY + + LD IY,CIO_TBL ; POINT IY TO START OF DIO TABLE + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE +; +; SPECIAL HANDLING FOR DEDICATED UNIT CODES +; +CIO_SPECIAL: + ; FOR NOW, ONLY SPECIAL CODE IS A CONSOLE REQUEST + ; SO JUST SWAP IN ACTIVE CONSOLE UNIT + LD A,(CB_CONDEV) ; GET ACTIVE CONSOLE + LD C,A ; OVERLAY UNIT CODE IN C + RET ; AND REJOIN MAIN DISPATCH FLOW +; +; ADD AN ENTRY TO THE CIO UNIT TABLE (SEE HB_ADDENT FOR DETAILS) +; +CIO_ADDENT: + LD HL,CIO_TBL ; POINT TO CIO TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE +; +; HBIOS CHARACTER DEVICE UNIT TABLE +; +; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. +; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT +; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS +; EACH ENTRY IS DEFINED AS: +; +; WORD DRIVER FUNCTION TABLE ADDRESS +; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) +; +CIO_FNCNT .EQU 7 ; NUMBER OF CIO FUNCS (FOR RANGE CHECK) +CIO_MAX .EQU 32 ; UP TO 32 UNITS +CIO_SIZ .EQU CIO_MAX * 4 ; EACH ENTRY IS 4 BYTES +; + .DB CIO_FNCNT ; CIO FUNCTION COUNT (FOR RANGE CHECK) + .DB CIO_MAX ; MAX ENTRY COUNT TABLE PREFIX +CIO_CNT .DB 0 ; ENTRY COUNT PREFIX +CIO_TBL .FILL CIO_SIZ,0 ; SPACE FOR ENTRIES +; +;================================================================================================== +; DISK I/O DEVICE FUNCTION DISPATCHER +;================================================================================================== +; +; ROUTE CALL TO SPECIFIED DISK I/O DRIVER +; B: FUNCTION +; C: UNIT NUMBER +; +DIO_DISPATCH: +; +#IF 0 ; *DEBUG* START +; + ; DUMP INCOMING CALL + CALL NEWLINE + PRTS("DIO>$") + CALL REGDMP ; DUMP REGS, NONE DESTROYED +; + ; DO THE ACTUAL DISPATCH PROCESSING + CALL DIO_DISPCALL +; + ; DUMP CALL RESULTS AND RETURN + CALL NEWLINE + PRTS("DIO<$") + CALL REGDMP ; DUMP REGS, NONE DESTROYED + RET +; +#ENDIF ; *DEBUG* END +; +DIO_DISPCALL: + PUSH IY ; SAVE INCOMING IY + + LD IY,DIO_TBL ; POINT IY TO START OF DIO TABLE + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE +; +; ADD AN ENTRY TO THE DIO UNIT TABLE +; +DIO_ADDENT: + LD HL,DIO_TBL ; POINT TO DIO TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE +; +; HBIOS DISK DEVICE UNIT TABLE +; +; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. +; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT +; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF DIO FUNCTION IDS +; EACH ENTRY IS DEFINED AS: +; +; WORD DRIVER FUNCTION TABLE ADDRESS +; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) +; +DIO_FNCNT .EQU 12 ; NUMBER OF DIO FUNCS (FOR RANGE CHECK) +DIO_MAX .EQU 16 ; UP TO 16 UNITS +DIO_SIZ .EQU DIO_MAX * 4 ; EACH ENTRY IS 4 BYTES +; + .DB DIO_FNCNT ; DIO FUNCTION COUNT (FOR RANGE CHECK) + .DB DIO_MAX ; MAX ENTRY COUNT TABLE PREFIX +DIO_CNT .DB 0 ; ENTRY COUNT PREFIX +DIO_TBL .FILL DIO_SIZ,0 ; SPACE FOR ENTRIES +; +;================================================================================================== +; REAL TIME CLOCK DEVICE DISPATCHER +;================================================================================================== +; +; ROUTE CALL TO REAL TIME CLOCK DRIVER +; B: FUNCTION +; +RTC_DISPATCH: +#IF (SIMRTCENABLE) + JP SIMRTC_DISPATCH +#ENDIF +#IF (DSRTCENABLE) + JP DSRTC_DISPATCH +#ENDIF + CALL PANIC +; +;================================================================================================== +; VIDEO DISPLAY ADAPTER DEVICE DISPATCHER +;================================================================================================== +; +; ROUTE CALL TO SPECIFIED VDA DEVICE DRIVER +; B: FUNCTION +; C: UNIT NUMBER +; +VDA_DISPATCH: + PUSH IY ; SAVE INCOMING IY + + LD IY,VDA_TBL ; POINT IY TO START OF DIO TABLE + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE +; +; ADD AN ENTRY TO THE VDA UNIT TABLE (SEE HB_ADDENT FOR DETAILS) +; +VDA_ADDENT: + LD HL,VDA_TBL ; POINT TO VDA TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE +; +; HBIOS VIDEO DEVICE UNIT TABLE +; +; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. +; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT +; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS +; EACH ENTRY IS DEFINED AS: +; +; WORD DRIVER FUNCTION TABLE ADDRESS +; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) +; +VDA_FNCNT .EQU 15 ; NUMBER OF VDA FUNCS (FOR RANGE CHECK) +VDA_MAX .EQU 16 ; UP TO 16 UNITS +VDA_SIZ .EQU VDA_MAX * 4 ; EACH ENTRY IS 4 BYTES +; + .DB VDA_FNCNT ; VDA FUNCTION COUNT (FOR RANGE CHECK) + .DB VDA_MAX ; MAX ENTRY COUNT TABLE PREFIX +VDA_CNT .DB 0 ; ENTRY COUNT PREFIX +VDA_TBL .FILL VDA_SIZ,0 ; SPACE FOR ENTRIES +; +;================================================================================================== +; SYSTEM FUNCTION DISPATCHER +;================================================================================================== +; +; B: FUNCTION +; +SYS_DISPATCH: + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION + JP Z,SYS_RESET ; $F0 + DEC A + JP Z,SYS_VER ; $F1 + DEC A + JP Z,SYS_SETBNK ; $F2 + DEC A + JP Z,SYS_GETBNK ; $F3 + DEC A + JP Z,SYS_SETCPY ; $F4 + DEC A + JP Z,SYS_BNKCPY ; $F5 + DEC A + JP Z,SYS_ALLOC ; $F6 + DEC A + JP Z,SYS_FREE ; $F7 + DEC A + JP Z,SYS_GET ; $F8 + DEC A + JP Z,SYS_SET ; $F9 + DEC A + JP Z,SYS_PEEK ; $FA + DEC A + JP Z,SYS_POKE ; $FB + DEC A + JP Z,SYS_INT ; $FC + CALL PANIC ; INVALID +; +; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS +; +SYS_RESET: + LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD + LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP + XOR A + RET +; +; GET THE CURRENT HBIOS VERSION +; ON INPUT, C=0 +; RETURNS VERSION IN DE AS BCD +; D: MAJOR VERION IN TOP 4 BITS, MINOR VERSION IN LOW 4 BITS +; E: UPDATE VERION IN TOP 4 BITS, PATCH VERSION IN LOW 4 BITS +; L: PLATFORM ID +; +SYS_VER: + LD DE,0 | (RMJ << 12) | (RMN << 8) | (RUP << 4) | RTP + LD L,PLATFORM + XOR A + RET +; +; SET ACTIVE MEMORY BANK AND RETURN PREVIOUSLY ACTIVE MEMORY BANK +; NOTE THAT IT GOES INTO EFFECT AS HBIOS FUNCTION IS EXITED +; HERE, WE JUST SET THE CURRENT BANK +; CALLER MUST EXTABLISH UPPER MEMORY STACK BEFORE INVOKING THIS FUNCTION! +; +SYS_SETBNK: + PUSH HL ; SAVE INCOMING HL + LD HL,HB_INVBNK ; POINT TO HBIOS INVOKE BANK ID ADDRESS + LD A,(HL) ; GET EXISTING BANK ID TO A + LD (HL),C ; UPDATE INVOKE BANK TO NEW BANK ID + LD C,A ; PUT PREVIOUS BANK ID IN C FOR RETURN + POP HL ; RESTORE ORIGINAL HL + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; GET ACTIVE MEMORY BANK +; +SYS_GETBNK: + LD A,(HB_INVBNK) ; GET THE ACTIVE MEMORY BANK + LD C,A ; MOVE TO C + XOR A ; SIGNAL SUCCESS + RET +; +; SET BANKS AND LENGTH FOR INTERBANK MEMORY COPY (BNKCPY) +; ENTRY: E=SOURCE BANK ID +; D=DEST BANK ID +; HL=COPY LENGTH (IN BYTES) +; +SYS_SETCPY: + LD A,E + LD (HB_SRCBNK),A ; RECORD THE SOURCE BANK + LD A,D + LD (HB_DSTBNK),A ; RECORD THE DESTINATION BANK + LD (HB_CPYLEN),HL ; RECORD THE COPY LENGTH + XOR A + RET +; +; PERFORM MEMORY COPY POTENTIALLY ACROSS BANKS +; ENTRY: HL=SOURCE ADDRESS +; DE=DESTINATION ADDRESS +; NOTE: SRC/DEST BANK & COPY LENGTH MUST BE SET VIA SETCPY +; +SYS_BNKCPY: + PUSH HL ; SAVE INCOMING HL + LD HL,(HB_CPYLEN) ; HL := COPY LEN (SAVED IN SETCPY) + EX (SP),HL ; RESTORE HL & SET (SP) TO COPY LEN + POP BC ; BC := COPY LEN +#IF (INTMODE == 1) + DI +#ENDIF + CALL HB_BNKCPY +#IF (INTMODE == 1) + EI +#ENDIF + XOR A + RET +; +; ALLOCATE HL BYTES OF MEMORY FROM HBIOS HEAP +; RETURNS POINTER TO ALLOCATED MEMORY IN HL +; ON SUCCESS RETURN A == 0, AND Z SET +; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED +; ALL OTHER REGISTERS PRESERVED +; +SYS_ALLOC: + JP HB_ALLOC +; +; FREE HEAP MEMORY BY SIMPLY RELEASING ALL +; MEMORY BEYOND POINTER IN HL. +; ON SUCCESS RETURN A == 0, AND Z SET +; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED +; ALL OTHER REGISTERS PRESERVED +; +SYS_FREE: + CALL PANIC ; NOT YET IMPLEMENTED + OR $FF + RET +; +; GET SYSTEM INFORMATION +; ITEM TO RETURN INDICATED IN C +; +SYS_GET: + LD A,C ; GET REQUESTED SUB-FUNCTION + CP BF_SYSGET_CIOCNT + JR Z,SYS_GETCIOCNT + CP BF_SYSGET_DIOCNT + JR Z,SYS_GETDIOCNT + CP BF_SYSGET_VDACNT + JR Z,SYS_GETVDACNT + CP BF_SYSGET_TIMER + JR Z,SYS_GETTIMER + CP BF_SYSGET_BOOTINFO + JR Z,SYS_GETBOOTINFO + CP BF_SYSGET_CPUINFO + JR Z,SYS_GETCPUINFO + CP BF_SYSGET_MEMINFO + JR Z,SYS_GETMEMINFO + CP BF_SYSGET_BNKINFO + JR Z,SYS_GETBNKINFO + OR $FF ; SIGNAL ERROR + RET +; +; GET TIMER +; RETURNS: +; DE:HL: TIMER VALUE (32 BIT) +; +SYS_GETTIMER: + LD HL,HB_TICKS + HB_DI + CALL LD32 + HB_EI + XOR A + RET +; +; GET BOOT INFORMATION +; RETURNS: +; L: BOOT BANK ID +; DE: BOOT DISK VOLUME (UNIT/SLICE) +; +SYS_GETBOOTINFO: + LD A,(CB_BOOTBID) + LD L,A + LD DE,(CB_BOOTVOL) + XOR A + RET +; +; GET CPU INFORMATION +; RETURNS: +; H: Z80 CPU VARIANT +; L: CPU SPEED IN MHZ +; DE: CPU SPEED IN KHZ +; +SYS_GETCPUINFO: + LD H,0 ; NOT YET DEFINED + LD A,(CB_CPUMHZ) + LD L,A + LD DE,(CB_CPUKHZ) + XOR A + RET +; +; GET MEMORY INFORMATION +; RETURNS: +; D: COUNT OF ROM BANKS +; E: COUNT OF RAM BANKS +; +SYS_GETMEMINFO: + LD D,ROMSIZE / 32 + LD E,RAMSIZE / 32 + XOR A + RET +; +; GET BANK CONFIGURATION INFORMATION +; RETURNS: +; D: HBIOS BANK ID +; E: USER BANK ID +; +SYS_GETBNKINFO: + LD A,(CB_BIDBIOS) + LD D,A + LD A,(CB_BIDUSR) + LD E,A + XOR A + RET +; +; GET SERIAL UNIT COUNT +; +SYS_GETCIOCNT: + LD A,(CIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) + LD E,A ; PUT IT IN E + XOR A ; SIGNALS SUCCESS + RET +; +; GET DISK UNIT COUNT +; +SYS_GETDIOCNT: + LD A,(DIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) + LD E,A ; PUT IT IN E + XOR A ; SIGNALS SUCCESS + RET +; +; GET VIDEO UNIT COUNT +; +SYS_GETVDACNT: + LD A,(VDA_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) + LD E,A ; PUT IT IN E + XOR A ; SIGNALS SUCCESS + RET +; +; SET SYSTEM PARAMETERS +; PARAMETER(S) TO SET INDICATED IN C +; +SYS_SET: + LD A,C ; GET REQUESTED SUB-FUNCTION + CP BF_SYSSET_TIMER + JR Z,SYS_SETTIMER + CP BF_SYSSET_BOOTINFO + JR Z,SYS_SETBOOTINFO + OR $FF ; SIGNAL ERROR + RET +; +; SET BOOT INFORMATION +; ON ENTRY: +; L: BOOT BANK ID +; DE: BOOT DISK VOLUME (UNIT/SLICE) +; +SYS_SETBOOTINFO: + LD A,L + LD (CB_BOOTBID),A + LD (CB_BOOTVOL),DE + XOR A + RET +; +; SET TIMER +; ON ENTRY: +; DE:HL: TIMER VALUE (32 BIT) +; +SYS_SETTIMER: + LD BC,HB_TICKS + HB_DI + CALL ST32 + HB_EI + XOR A + RET +; +; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK +; ENTRY: D=BANK ID, HL=ADDRESS +; RETURN: E=BYTE VALUE +; +SYS_PEEK: +#IF (INTMODE == 1) + DI +#ENDIF + CALL HBX_PEEK ; IMPLEMENTED IN PROXY +#IF (INTMODE == 1) + EI +#ENDIF + XOR A + RET +; +; WRITE A BYTE OF MEMORY TO SPECIFIED BANK +; ENTRY: D=BANK ID, HL=ADDRESS IN HBIOS BANK, E=BYTE VALUE +; +SYS_POKE: +#IF (INTMODE == 1) + DI +#ENDIF + CALL HBX_POKE ; IMPLEMENTED IN PROXY +#IF (INTMODE == 1) + EI +#ENDIF + XOR A + RET +; +; INTERRUPT MANAGEMENT FUNCTIONS +; SUBFUNCTION IN C +; +SYS_INT: + LD A,C ; GET REQUESTED SUB-FUNCTION + CP BF_SYSINT_INFO + JR Z,SYS_INTINFO + CP BF_SYSINT_GET + JR Z,SYS_INTGET + CP BF_SYSINT_SET + JR Z,SYS_INTSET + OR $FF ; SIGNAL ERROR + RET +; +; GET INTERRUPT SYSTEM INFORMATION +; RETURN D:=INTERRUPT MODE, E:=INT VEC TABLE SIZE +; +SYS_INTINFO: + LD D,INTMODE ; D := ACTIVE INTERRUPT MODE +#IF (INTMODE == 0) + LD E,0 ; 0 ENTRIES IF INTERRUPTS DISABLED +#ENDIF +#IF (INTMODE == 1) + LD A,(HB_IM1CNT) ; RETURN IM1 CALL LIST SIZE + LD E,A +#ENDIF +#IF (INTMODE == 2) + LD E,HBX_IVTCNT ; RETURN INT VEC TABLE SIZE +#ENDIF + XOR A ; INDICATE SUCCESS + RET ; AND DONE +; +; ROUTINE SHARED BY INT GET/SET. RETURNS ADDRESS OF VECTOR FOR SPECIFIED LIST / TABLE +; POSITION. ZF SET ON RETURN FOR SUCCESS, ELSE ERROR. +; +SYS_INTVECADR: +#IF (INTMODE == 0) + CALL PANIC ; INVALID FOR INT MODE 0 + OR $FF + RET +#ENDIF +#IF (INTMODE == 1) + LD A,(HB_IM1CNT) ; GET CURRENT ENTRY COUNT + INC A ; ALLOW FOR EXTRA ENTRY TO APPEND AT END + LD C,A ; SAVE IN C FOR COMPARE +#ENDIF +#IF (INTMODE == 2) + LD C,HBX_IVTCNT ; GET CURRENT ENTRY COUNT +#ENDIF + LD A,E ; INCOMING INDEX POSITION TO A + CP C ; COMPARE TO VECTOR COUNT + JR C,SYS_INTGET1 ; CONTINUE IF POSITION IN RANGE + CALL PANIC ; ELSE ERROR + OR $FF + RET +SYS_INTGET1: + OR A + RLA ; HL := (A * 2) FOR IM2 +#IF (INTMODE == 1) + RLA ; ... HL := (A * 4) + 1 FOR IM1 + INC A +#ENDIF + LD H,0 + LD L,A +#IF (INTMODE == 1) + LD DE,HB_IM1INT ; DE := START OF CALL LIST +#ENDIF +#IF (INTMODE == 2) + LD DE,HBX_IVT ; DE := START OF VECTOR TABLE +#ENDIF + ADD HL,DE ; HL := ADR OF VECTOR + XOR A ; INDICATE SUCCESS + RET +; +; RETURN THE INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE +; ENTRY: E=LIST/TABLE POSITION +; RETURN: HL=INTERRUPT VECTOR +; +SYS_INTGET: + CALL SYS_INTVECADR ; GET VECTOR ADDRESS + RET NZ ; BAIL OUT ON ERROR + LD A,(HL) ; DEREF HL TO GET VECTOR + INC HL + LD H,(HL) + LD L,A + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; SET AN INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE +; ENTRY: E=LIST/TABLE POSITION, HL=NEW INTERRUPT VECTOR +; RETURN: HL=PREVIOUS INTERRUPT VECTOR, DE=ADR OF INT ROUTING ENGINE FOR IM2 +; +SYS_INTSET: + PUSH HL ; SAVE NEW VECTOR + CALL SYS_INTVECADR ; GET VECTOR ADDRESS + JR Z,SYS_INTSET1 ; CONTINUE IF OK + POP HL ; FIX STACK + RET NZ ; BAIL OUT ON ERROR +SYS_INTSET1: + PUSH HL ; SAVE VECTOR ADDRESS + LD A,(HL) ; DEREF HL TO GET PREV VECTOR + INC HL + LD H,(HL) + LD L,A + EX (SP),HL ; (SP) := PREV VEC, HL := VEC ADR + POP DE ; DE := PREV VEC + POP BC ; BC := NEW VEC + LD (HL),C ; SAVE LSB + INC HL + LD (HL),B ; SAVE MSB + EX DE,HL ; HL := PREV VEC +#IF (INTMODE == 2) + LD DE,HBX_INT ; DE := IM2 INT ROUTING ENGINE +#ENDIF + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +;================================================================================================== +; GLOBAL HBIOS FUNCTIONS +;================================================================================================== +; +; COMMON ROUTINE THAT IS CALLED BY CHARACTER IO DRIVERS WHEN +; AN IDLE CONDITION IS DETECTED (WAIT FOR INPUT/OUTPUT) +; +CIO_IDLE: + PUSH AF ; PRESERVE AF + LD A,(IDLECOUNT) ; GET CURRENT IDLE COUNT + DEC A ; DECREMENT + LD (IDLECOUNT),A ; SAVE UPDATED VALUE + CALL Z,IDLE ; IF ZERO, DO IDLE PROCESSING + POP AF ; RECOVER AF + RET +; +#IF (INTMODE == 1) +; +; IM1 INTERRUPTS ARRIVE HERE AFTER BANK SWITCH TO HBIOS BANK +; LIST OF IM1 INT CALLS IS BUILT DYNAMICALLY BELOW +; SEE HB_ADDIM1 ROUTINE +; EACH ENTRY WILL LOOK LIKE: +; CALL XXXX ; CALL INT HANDLER +; RET NZ ; RETURN IF HANDLED +; +; NOTE THAT THE LIST IS INITIALLY FILLED WITH CALLS TO HB_BADINT. +; AS THE TABLE IS POPULATED, THE ADDRESS OF HB_BADINT IS OVERLAID +; WITH THE ADDRESS OF A REAL INTERRUPT HANDLER. +; +; THERE IS ROOM FOR 8 ENTRIES PLUS A FINAL CALL TO HB_BADINT. +; +HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER CALL LIST + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ + CALL HB_BADINT \ RET NZ +; +; ROUTINE BELOW IS USED TO ADD A NEW VECTOR TO THE IM1 +; CALL LIST ABOVE. ENTER WITH HL=VECTOR ADDRESS IN HBIOS +; +HB_ADDIM1: + EX DE,HL ; VECTOR ADDRESS TO DE + LD HL,(HB_IM1PTR) ; GET PTR FOR NEXT ENTRY + INC HL ; BUMP PTR TO ADDRESS FIELD OF CALL OPCODE + LD (HL),E ; ADD VECTOR ADDRESS + INC HL ; ... + LD (HL),D ; ... + INC HL ; BUMP PTR + INC HL ; BUMP PTR + LD (HB_IM1PTR),HL ; SAVE UPDATED POINTER + LD HL,HB_IM1CNT ; POINT TO ENTRY COUNT + INC (HL) ; INCREMENT + RET ; DONE +; +HB_IM1CNT .DB 0 ; NUMBER OF ENTRIES IN CALL LIST +HB_IM1MAX .DB 8 ; MAX ENTRIES IN CALL LIST +HB_IM1PTR .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY +; +#ENDIF +; +; TIMER INTERRUPT +; +HB_TIMINT: + ; INCREMENT TICK COUNTER (32 BIT) + LD HL,HB_TICKS ; POINT TO TICK COUNTER + INC (HL) + JR NZ,HB_TIMINT1 + INC HL + INC (HL) + JR NZ,HB_TIMINT1 + INC HL + INC (HL) + JR NZ,HB_TIMINT1 + INC HL + INC (HL) +; +HB_TIMINT1: +; +#IF 0 +; + LD HL,TEMPCNT + DEC (HL) + JR NZ,HB_TIMINT2 + LD (HL),250 +; + LD A,'*' + CALL COUT + JR HB_TIMINT2 +; +TEMPCNT .DB 250 +; +#ENDIF +; +HB_TIMINT2: +; +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + ; ACK/RESET Z180 TIMER INTERRUPT + IN0 A,(Z180_TCR) + IN0 A,(Z180_TMDR0L) +#ENDIF +; + OR $FF ; NZ SET TO INDICATE INT HANDLED + RET +; +; BAD INTERRUPT HANDLER +; +HB_BADINT: + +#IF 0 ; *DEBUG* + LD HL,HB_BADINTCNT + INC (HL) + LD A,(HL) + OUT (DIAGP),A + OR $FF + RET +HB_BADINTCNT .DB 0 +#ENDIF ; *DEBUG* + + CALL NEWLINE2 + PRTS("+++ BAD INT: $") + CALL _REGDMP + ;CALL CONTINUE + OR $FF ; SIGNAL INTERRUPT HANDLED + RET +; +; COMMON API FUNCTION DISPATCH CODE +; +; ON ENTRY C IS UNIT # (INDEX INTO XXX_TBL OF UNITS) +; AND IY POINTS TO START OF UNIT TABLE. +; USE UNIT # IN C TO LOOKUP XXX_TBL ENTRY. THE XXX_TBL +; ENTRY CONTAINS THE START OF THE DRIVER FUNCTION TABLE AND +; THE DEVICE SPECIFIC INSTANCE DATA (BLOB). SET IY TO BLOB ADDRESS +; AND CALL THE SPECIFIC FUNCTION REQUESTED IN THE DRIVER. +; +HB_DISPCALL: + ; CHECK INCOMING UNIT INDEX IN C FOR VAILIDITY + LD A,C ; A := INCOMING DISK UNIT INDEX + CP (IY-1) ; COMPARE TO COUNT + JR NC,HB_DISPERR ; HANDLE INVALID UNIT INDEX + + ; CHECK FUNCTION INDEX FOR VALIDITY + LD A,B ; A := INCOMING FUNCTION NUMBER + AND $0F ; LOW NIBBLE ONLY FOR FUNC INDEX + CP (IY-3) ; CHECK FN NUM AGAINST MAX + JR NC,HB_DISPERR ; HANDLE FN NUM OUT OF RANGE ERROR + + ; BUMP IY TO ACTUAL XXX_TBL ENTRY FOR INCOMING UNIT INDEX + LD B,0 ; MSB IS ALWAYS ZERO + RLC C ; MULTIPLY UNIT INDEX + RLC C ; ... BY 4 FOR TABLE ENTRY OFFSET + ADD IY,BC ; SET IY TO ENTRY ADDRESS + + ; DERIVE DRIVER FUNC ADR TO CALL + PUSH HL ; SAVE INCOMING HL + LD L,(IY+0) ; COPY DRIVER FUNC TABLE + LD H,(IY+1) ; ... START TO HL + RLCA ; CONV UNIT (STILL IN A) TO FN ADR OFFSET + CALL ADDHLA ; HL NOW HAS DRIVER FUNC TBL START ADR + LD A,(HL) ; DEREFERENCE HL + INC HL ; ... TO GET + LD H,(HL) ; ... ACTUAL + LD L,A ; ... TARGET FUNCTION ADDRESS + EX (SP),HL ; RESTORE HL, FUNC ADR ON STACK + + ; GET UNIT INSTANCE DATA BLOB ADDRESS TO IY + PUSH HL ; SAVE INCOMING HL + LD L,(IY+2) ; HL := DATA BLOB ADDRESS + LD H,(IY+3) ; ... + EX (SP),HL ; RESTORE HL, BLOB ADR ON TOS + POP IY ; IY := BLOB ADR + + RET ; JUMP TO DRIVER FUNC ADR ON TOS +; +HB_DISPERR: + CALL PANIC ; PANIC + OR $FF ; SIGNAL ERROR + RET ; AND RETURN VIA DISPEXIT +; +; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL +; BC: DRIVER FUNCTION TABLE +; DE: ADDRESS OF UNIT INSTANCE DATA +; RETURN +; A: UNIT NUMBER ASSIGNED +; +HB_ADDENT: + DEC HL ; POINT TO ENTRY COUNT + LD A,(HL) ; GET ENTRY COUNT + PUSH AF ; SAVE VALUE TO RETURN AS ENTRY NUM AT END + INC A ; INCREMENT TO ACCOUNT FOR NEW ENTRY + DEC HL ; POINT TO ENTRY MAX + CP (HL) ; COMPARE MAX TO CURRENT COUNT (COUNT - MAX) + CALL NC,PANIC ; OVERFLOW + INC HL ; POINT TO COUNT + LD (HL),A ; SAVE NEW COUNT + INC HL ; POINT TO START OF TABLE + DEC A ; CONVERT A FROM ENTRY COUNT TO ENTRY INDEX + RLCA ; MULTIPLY BY 4 + RLCA ; ... TO GET BYTE OFFSET OF ENTRY + CALL ADDHLA ; MAKE HL POINT TO ACTUAL ENTRY ADDRESS + PUSH BC ; GET TABLE ENTRY ADDRESS TO BC + EX (SP),HL ; ... AND DISPATCH ADDRESS TO HL + POP BC ; ... SO THAT DE:HL HAS 32 BIT ENTRY + CALL ST32 ; LD (BC),DE:HL STORES THE ENTRY + POP AF ; RETURN ENTRY INDEX (UNIT NUMBER ASSIGNED) + RET +; +; ALLOCATE HL BYTES OF MEMORY ON THE HEAP +; RETURNS POINTER TO ALLOCATED SPACE IN HL +; ON SUCCESS RETURN A == 0, AND Z SET +; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED +; ALL OTHER REGISTERS PRESERVED +; +; A 4 BYTE HEADER IS PLACED IN FRONT OF THE ALLOCATED MEMORY +; - DWORD: SIZE OF MEMROY ALLOCATED (DOES NOT INCLUDE 4 BYTE HEADER) +; - DWORD: ADDRESS WHERE ALLOC WAS CALLED (VALUE ON TOP OF STACK AT CALL) +; +HB_ALLOC: + ; SAVE ALLOC SIZE AND REFERENCE ADR FOR SUBSEQUENT HEADER CONSTRUCTION + LD (HB_TMPSZ),HL ; SAVE INCOMING SIZE REQUESTED + ; USE EX (SP),HL INSTEAD???? + POP HL ; GET RETURN ADDRESS + LD (HB_TMPREF),HL ; SAVE AS REFERENCE + ; USE EX (SP),HL INSTEAD???? + PUSH HL ; PUT IT BACK ON STACK + LD HL,(HB_TMPSZ) ; RECOVER INCOMING MEM SIZE PARM +; + ; CALC NEW HEAP TOP AND HANDLE OUT-OF-SPACE ERROR + PUSH DE ; SAVE INCOMING DE + LD DE,4 ; SIZE OF HEADER + ADD HL,DE ; ADD IT IN + JR C,HB_ALLOC1 ; ERROR ON OVERFLOW + LD DE,(CB_HEAPTOP) ; CURRENT HEAP TOP + ADD HL,DE ; ADD IT IN, HL := NEW HEAP TOP + JR C,HB_ALLOC1 ; ERROR ON OVERFLOW + BIT 7,H ; TEST PAST END OF BANK (>= 32K) + JR NZ,HB_ALLOC1 ; ERROR IF PAST END +; + ; SAVE NEW HEAP TOP + LD DE,(CB_HEAPTOP) ; GET ORIGINAL HEAP TOP + LD (CB_HEAPTOP),HL ; SAVE NEW HEAP TOP +; + ; SET HEADER VALUES + EX DE,HL ; HEADER ADR TO HL + LD DE,(HB_TMPSZ) ; GET THE ORIG SIZE REQUESTED + LD (HL),E ; SAVE SIZE (LSB) + INC HL ; BUMP HEADER POINTER + LD (HL),D ; SAVE SIZE (MSB) + INC HL ; BUMP HEADER POINTER + LD DE,(HB_TMPREF) ; GET THE REFERENCE ADR + LD (HL),E ; SAVE REF ADR (LSB) + INC HL ; BUMP HEADER POINTER + LD (HL),D ; SAVE REF ADR (MSB) + INC HL ; BUMP HEADER POINTER +; + ; RETURN SUCCESS, HL POINTS TO START OF ALLOCATED MEMORY (PAST HEADER) + POP DE ; RESTORE INCOMING DE + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +HB_ALLOC1: + ; ERROR RETURN + POP DE ; RESTORE INCOMING DE + OR $FF ; SIGNAL ERROR + RET ; AND RETURN +; +HB_TMPSZ .DW 0 +HB_TMPREF .DW 0 +; +;================================================================================================== +; DEVICE DRIVERS +;================================================================================================== +; +#IF (SIMRTCENABLE) +ORG_SIMRTC .EQU $ + #INCLUDE "simrtc.asm" +SIZ_SIMRTC .EQU $ - ORG_SIMRTC + .ECHO "SIMRTC occupies " + .ECHO SIZ_SIMRTC + .ECHO " bytes.\n" +#ENDIF +; +#IF (DSRTCENABLE) +ORG_DSRTC .EQU $ + #INCLUDE "dsrtc.asm" +SIZ_DSRTC .EQU $ - ORG_DSRTC + .ECHO "DSRTC occupies " + .ECHO SIZ_DSRTC + .ECHO " bytes.\n" +#ENDIF +; +#IF (ASCIENABLE) +ORG_ASCI .EQU $ + #INCLUDE "asci.asm" +SIZ_ASCI .EQU $ - ORG_ASCI + .ECHO "ASCI occupies " + .ECHO SIZ_ASCI + .ECHO " bytes.\n" +#ENDIF +; +#IF (UARTENABLE) +ORG_UART .EQU $ + #INCLUDE "uart.asm" +SIZ_UART .EQU $ - ORG_UART + .ECHO "UART occupies " + .ECHO SIZ_UART + .ECHO " bytes.\n" +#ENDIF +; +#IF (SIOENABLE) +ORG_SIO .EQU $ + #INCLUDE "sio.asm" +SIZ_SIO .EQU $ - ORG_SIO + .ECHO "SIO occupies " + .ECHO SIZ_SIO + .ECHO " bytes.\n" +#ENDIF +; +#IF (ACIAENABLE) +ORG_ACIA .EQU $ + #INCLUDE "acia.asm" +SIZ_ACIA .EQU $ - ORG_ACIA + .ECHO "ACIA occupies " + .ECHO SIZ_ACIA + .ECHO " bytes.\n" +#ENDIF +; +#IF (VGAENABLE) +ORG_VGA .EQU $ + #INCLUDE "vga.asm" +SIZ_VGA .EQU $ - ORG_VGA + .ECHO "VGA occupies " + .ECHO SIZ_VGA + .ECHO " bytes.\n" +#ENDIF +; +#IF (CVDUENABLE) +ORG_CVDU .EQU $ + #INCLUDE "cvdu.asm" +SIZ_CVDU .EQU $ - ORG_CVDU + .ECHO "CVDU occupies " + .ECHO SIZ_CVDU + .ECHO " bytes.\n" +#ENDIF +; +#IF (VDUENABLE) +ORG_VDU .EQU $ + #INCLUDE "vdu.asm" +SIZ_VDU .EQU $ - ORG_VDU + .ECHO "VDU occupies " + .ECHO SIZ_VDU + .ECHO " bytes.\n" +#ENDIF +; +#IF (TMSENABLE) +ORG_TMS .EQU $ + #INCLUDE "tms.asm" +SIZ_TMS .EQU $ - ORG_TMS + .ECHO "TMS occupies " + .ECHO SIZ_TMS + .ECHO " bytes.\n" +#ENDIF +; +#IF (NECENABLE) +ORG_NEC .EQU $ + ;#INCLUDE "nec.asm" +SIZ_NEC .EQU $ - ORG_NEC + .ECHO "NEC occupies " + .ECHO SIZ_NEC + .ECHO " bytes.\n" +#ENDIF +; +#IF (CVDUENABLE | VGAENABLE) +ORG_FONTHI .EQU $ + #INCLUDE "font_hi.asm" +SIZ_FONTHI .EQU $ - ORG_FONTHI + .ECHO "FONTHI occupies " + .ECHO SIZ_FONTHI + .ECHO " bytes.\n" +#ENDIF +; +#IF (TMSENABLE) +ORG_FONTTMS .EQU $ + #INCLUDE "font_tms.asm" +SIZ_FONTTMS .EQU $ - ORG_FONTTMS + .ECHO "FONTTMS occupies " + .ECHO SIZ_FONTTMS + .ECHO " bytes.\n" +#ENDIF +; +#IF (CVDUENABLE | VGAENABLE) +ORG_KBD .EQU $ + #INCLUDE "kbd.asm" +SIZ_KBD .EQU $ - ORG_KBD + .ECHO "KBD occupies " + .ECHO SIZ_KBD + .ECHO " bytes.\n" +#ENDIF +; +#IF (VDUENABLE | (TMSENABLE & (PLATFORM == PLT_N8))) +ORG_PPK .EQU $ + #INCLUDE "ppk.asm" +SIZ_PPK .EQU $ - ORG_PPK + .ECHO "PPK occupies " + .ECHO SIZ_PPK + .ECHO " bytes.\n" +#ENDIF +; +#IF (PRPENABLE) +ORG_PRP .EQU $ + #INCLUDE "prp.asm" +SIZ_PRP .EQU $ - ORG_PRP + .ECHO "PRP occupies " + .ECHO SIZ_PRP + .ECHO " bytes.\n" +#ENDIF +; +#IF (PPPENABLE) +ORG_PPP .EQU $ + #INCLUDE "ppp.asm" +SIZ_PPP .EQU $ - ORG_PPP + .ECHO "PPP occupies " + .ECHO SIZ_PPP + .ECHO " bytes.\n" +#ENDIF +; +#IF (MDENABLE) +ORG_MD .EQU $ + #INCLUDE "md.asm" +SIZ_MD .EQU $ - ORG_MD + .ECHO "MD occupies " + .ECHO SIZ_MD + .ECHO " bytes.\n" +#ENDIF + +#IF (FDENABLE) +ORG_FD .EQU $ + #INCLUDE "fd.asm" +SIZ_FD .EQU $ - ORG_FD + .ECHO "FD occupies " + .ECHO SIZ_FD + .ECHO " bytes.\n" +#ENDIF + +#IF (RFENABLE) +ORG_RF .EQU $ + #INCLUDE "rf.asm" +SIZ_RF .EQU $ - ORG_RF + .ECHO "RF occupies " + .ECHO SIZ_RF + .ECHO " bytes.\n" +#ENDIF + +#IF (IDEENABLE) +ORG_IDE .EQU $ + #INCLUDE "ide.asm" +SIZ_IDE .EQU $ - ORG_IDE + .ECHO "IDE occupies " + .ECHO SIZ_IDE + .ECHO " bytes.\n" +#ENDIF + +#IF (PPIDEENABLE) +ORG_PPIDE .EQU $ + #INCLUDE "ppide.asm" +SIZ_PPIDE .EQU $ - ORG_PPIDE + .ECHO "PPIDE occupies " + .ECHO SIZ_PPIDE + .ECHO " bytes.\n" +#ENDIF + +#IF (SDENABLE) +ORG_SD .EQU $ + #INCLUDE "sd.asm" +SIZ_SD .EQU $ - ORG_SD + .ECHO "SD occupies " + .ECHO SIZ_SD + .ECHO " bytes.\n" +#ENDIF + +#IF (HDSKENABLE) +ORG_HDSK .EQU $ + #INCLUDE "hdsk.asm" +SIZ_HDSK .EQU $ - ORG_HDSK + .ECHO "HDSK occupies " + .ECHO SIZ_HDSK + .ECHO " bytes.\n" +#ENDIF + +#IF (TERMENABLE) +ORG_TERM .EQU $ + #INCLUDE "term.asm" +SIZ_TERM .EQU $ - ORG_TERM + .ECHO "TERM occupies " + .ECHO SIZ_TERM + .ECHO " bytes.\n" +#ENDIF +; +#IF (SPKENABLE) +ORG_SPK .EQU $ + #INCLUDE "spk.asm" +SIZ_SPK .EQU $ - ORG_SPK + .ECHO "SPK occupies " + .ECHO SIZ_SPK + .ECHO " bytes.\n" +#ENDIF +; +#IF (AYENABLE) +ORG_AY .EQU $ + #INCLUDE "ay.asm" +SIZ_AY .EQU $ - ORG_AY + .ECHO "AY occupies " + .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" +#INCLUDE "time.asm" +#INCLUDE "bcd.asm" +#INCLUDE "decode.asm" +;#INCLUDE "xio.asm" +; +#IF (DSKYENABLE) +#DEFINE DSKY_KBD +#INCLUDE "dsky.asm" +#ENDIF +; +; DETECT CPU SPEED USING DS-1302 RTC +; +HB_CPUSPD: +; +#IF (DSRTCENABLE) +; + CALL DSRTC_TSTCLK ; IS CLOCK RUNNING? + JR Z,HB_CPUSPD1 ; YES, CONTINUE + ; MAKE SURE CLOCK IS RUNNING + LD HL,DSRTC_TIMDEF + CALL DSRTC_TIM2CLK + LD HL,DSRTC_BUF + CALL DSRTC_WRCLK + CALL DSRTC_TSTCLK ; NOW IS CLOCK RUNNING? + RET NZ +; +HB_CPUSPD1: +; LD B,8 +;HB_CPUSPDX: +; PUSH BC + + ; WAIT FOR AN INITIAL TICK TO ALIGN, THEN WAIT + ; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT + + CALL HB_RDSEC ; GET SECONDS + LD (HB_CURSEC),A ; AND INIT CURSEC + CALL HB_WAITSEC ; WAIT FOR SECONDS TICK + LD (HB_CURSEC),A ; SAVE NEW VALUE + CALL HB_WAITSEC ; WAIT FOR SECONDS TICK + +; PUSH DE +; POP BC +; CALL NEWLINE +; CALL PRTHEXWORD + +; POP BC +; DJNZ HB_CPUSPDX +; + LD A,H + OR L + RET Z ; FAILURE, USE DEFAULT CPU SPEED + +; + ; MOVE LOOP COUNT TO HL + PUSH DE + POP HL +; + ; TIMES 4 FOR CPU SPEED IN KHZ + RES 0,L ; GRANULARITY +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + SLA L + RL H +#ENDIF + SLA L + RL H + SLA L + RL H +; + LD (CB_CPUKHZ),HL + LD DE,1000 + CALL DIV16 + LD A,C + LD (CB_CPUMHZ),A +; + RET +; +HB_WAITSEC: + ; WAIT FOR SECONDS TICK + ; RETURN SECS VALUE IN A, LOOP COUNT IN DE + LD DE,0 ; INIT LOOP COUNTER +HB_WAITSEC1: +#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_EZZ80)) + ; LOOP TARGET IS 4000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4 + CALL DLY32 + CALL DLY8 + CALL DLY2 + JP $ + 3 ; 10 TSTATES + JP $ + 3 ; 10 TSTATES + JP $ + 3 ; 10 TSTATES + JP $ + 3 ; 10 TSTATES + ;LD A,R ; 9 TSTATES + INC BC ; 6 TSTATES + ;LD A,(BC) ; 7 TSTATES + ;NOP ; 4 TSTATES + NOP ; 4 TSTATES +#ENDIF + +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) + ; LOOP TARGET IS 8000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 8 + ;CALL DLY64 + CALL DLY32 + CALL DLY16 + CALL DLY8 + CALL DLY4 + CALL DLY2 + CALL DLY1 ; CALL (25TS) & RET (18TS) = 43TS + OR A ; 7 TSTATES + OR A ; 7 TSTATES + ;OR A ; 7 TSTATES + ;OR A ; 7 TSTATES + NOP ; 6 TSTATES + ;NOP ; 6 TSTATES + ;NOP ; 6 TSTATES + ;NOP ; 6 TSTATES + ;NOP ; 6 TSTATES +#ENDIF +; + PUSH DE + CALL HB_RDSEC ; GET SECONDS + POP DE + INC DE ; BUMP COUNTER + LD HL,HB_CURSEC ; POINT TO COMP VALUE + CP (HL) ; TEST FOR CHANGE + RET NZ ; DONE IF TICK OCCURRED + LD A,D ; CHECK HL + OR E ; ... FOR OVERFLOW + RET Z ; TIMEOUT, SOMETHING IS WRONG + JR HB_WAITSEC1 ; LOOP +; +HB_RDSEC: + ; READ SECONDS BYTE INTO A + LD C,$81 ; SECONDS REGISTER + CALL DSRTC_CMD ; SEND THE COMMAND + CALL DSRTC_GET ; READ THE REGISTER + CALL DSRTC_END ; FINISH IT + RET +; +#ELSE +; + RET ; NO RTC, ABORT +; +#ENDIF +; +; PRINT VALUE OF HL AS THOUSANDTHS, IE. 0.000 +; +PRTD3M: + PUSH BC + PUSH DE + PUSH HL + LD E,'0' + LD BC,-10000 + CALL PRTD3M1 + LD E,0 + LD BC,-1000 + CALL PRTD3M1 + CALL PC_PERIOD + LD BC,-100 + CALL PRTD3M1 + LD C,-10 + CALL PRTD3M1 + LD C,-1 + CALL PRTD3M1 + POP HL + POP DE + POP BC + RET +PRTD3M1: + LD A,'0' - 1 +PRTD3M2: + INC A + ADD HL,BC + JR C,PRTD3M2 + SBC HL,BC + CP E + JR Z,PRTD3M3 + LD E,0 + CALL COUT +PRTD3M3: + RET +; +;================================================================================================== +; DISPLAY SUMMARY OF ATTACHED UNITS/DEVICES +;================================================================================================== +; +PRTSUM: + CALL NEWLINE2 ; SKIP A LINE + LD DE,PS_STRHDR ; POINT TO HEADER + CALL WRITESTR ; PRINT IT +; + ; PRINT DISK DEVICES + LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET + LD C,BF_SYSGET_DIOCNT ; SUBFUNC: DISK UNIT COUNT + RST 08 ; E := DISK UNIT COUNT + LD B,E ; MOVE TO B FOR LOOP COUNT + LD A,E ; MOVE TO ACCUM + OR A ; SET FLAGS + JR Z,PRTSUM1A ; IF NONE, BYPASS + LD C,0 ; C WILL BE UNIT INDEX +PRTSUM1: + PUSH BC ; SAVE LOOP CONTROL + CALL PS_DISK ; PRINT DISK INFO + POP BC ; RESTORE LOOP CONTROL + INC C ; BUMP DISK UNIT INDEX + DJNZ PRTSUM1 ; LOOP THRU ALL DISK DEVICES +; +PRTSUM1A: + ; PRINT SERIAL DEVICES + LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET + LD C,BF_SYSGET_CIOCNT ; SUBFUNC: SERIAL UNIT COUNT + RST 08 ; E := SERIAL UNIT COUNT + LD B,E ; MOVE TO B FOR LOOP COUNT + LD A,E ; MOVE TO ACCUM + OR A ; SET FLAGS + JR Z,PRTSUM2A ; IF NONE, BYPASS + LD C,0 ; C WILL BE UNIT INDEX +PRTSUM2: + PUSH BC ; SAVE LOOP CONTROL + CALL PS_SERIAL ; PRINT SERIAL INFO + POP BC ; RESTORE LOOP CONTROL + INC C ; BUMP SERIAL UNIT INDEX + DJNZ PRTSUM2 ; LOOP THRU ALL SERIAL DEVICES +; +PRTSUM2A: + ; PRINT VIDEO DEVICES + LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET + LD C,BF_SYSGET_VDACNT ; SUBFUNC: VIDEO UNIT COUNT + RST 08 ; E := SERIAL UNIT COUNT + LD B,E ; MOVE TO B FOR LOOP COUNT + LD A,E ; MOVE TO ACCUM + OR A ; SET FLAGS + JR Z,PRTSUM3A ; IF NONE, BYPASS + LD C,0 ; C WILL BE UNIT INDEX +PRTSUM3: + PUSH BC ; SAVE LOOP CONTROL + CALL PS_VIDEO ; PRINT VIDEO INFO + POP BC ; RESTORE LOOP CONTROL + INC C ; BUMP VIDEO UNIT INDEX + DJNZ PRTSUM3 ; LOOP THRU ALL VIDEO DEVICES +; +PRTSUM3A: + RET ; DONE +; +; PRINT ONE LINE DISK UNIT/DEVICE INFO, DISK UNIT INDEX IN C +; +PS_DISK: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Disk $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_DDSTRREF ; POINT TO DISK DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT DISK DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP DE ; RECOVER ATTRIBUTES TO DE + PUSH DE ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTDT ; PRINT DISK TYPE + POP DE ; RESTORE ATTRIBUTES + POP BC ; RESTORE UNIT NUM + CALL PS_PRTDC ; PRINT DISK CAPACITY +; + CALL NEWLINE + RET +; +; PRINT DISK TYPE (DISK ATTRIBUTE IN E) +; +PS_PRTDT: + LD A,E ; ATTRIBUTES TO A + BIT 7,A ; FLOPPY BIT SET? + LD HL,PS_DTFLOP ; ASSUME FLOPPY + JR NZ,PS_PRTDT1 ; IF FLOPPY, JUMP AHEAD + RRCA ; SHIFT TYPE BITS + RRCA + RRCA + AND $07 ; AND ISOLATE THEM + RLCA ; X2 FOR WORD OFFSET IN STRING TABLE + LD HL,PS_DTSTRREF + 2 ; POINT TO STR REF TABLE (SKIP FLOPPY STRING) + CALL ADDHLA + LD A,(HL) + INC HL + LD H,(HL) + LD L,A +; +PS_PRTDT1: + CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED + LD A,18 ; 18 CHAR FIELD + SUB C + CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) + RET +; +; PRINT DISK CAPACITY (UNIT IN C, ATTRIBUTE IN E) +; +PS_PRTDC: +; + LD A,E ; ATTRIBUTE TO ACCUM + BIT 7,A ; TEST FOR FLOPPY + JR NZ,PS_PRTDC2 ; HANDLE FLOPPY + RRCA ; ISOLATE TYPE BITS + RRCA + RRCA + AND $07 + CP 4 ; ROM DISK? + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB + CP 5 ; RAM DISK? + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB +; + ; PRINT HARD DISK STORAGE SIZE IN MB + LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY + RST 08 ; DE:HL := BLOCKS + JP NZ,PS_PRTNUL ; MEDIA PROBLEM + RES 7,D ; CLEAR LBA BIT + LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB + CALL SRL32 ; RIGHT SHIFT + CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) + PRTS("MB$") ; PRINT SUFFIX + CALL PC_COMMA + PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA + RET ; DONE +; +PS_PRTDC1: + ; PRINT ROM/ROM DISK CAPACITY IN KB + LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY + RST 08 ; DE:HL := BLOCKS + JP NZ,PS_PRTNUL ; MEDIA PROBLEM + RES 7,D ; CLEAR LBA BIT + LD B,1 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB + CALL SRL32 ; RIGHT SHIFT + CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) + PRTS("KB$") ; PRINT SUFFIX + CALL PC_COMMA + PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA + RET ; DONE +; +PS_PRTDC2: + LD C,E ; ATTRIBUTE TO C FOR SAFE KEEPING + ; PRINT FLOPPY TYPE + LD A,C ; ATTRIBUTE TO ACCUM + RLCA ; ISOLATE FORM FACTOR BITS + RLCA + RLCA + AND $03 + LD DE,PS_FLP8 ; ASSUME 8" + CP 0 + JR Z,PS_PRTDC2A + LD DE,PS_FLP5 ; ASSUME 5.25" + CP 1 + JR Z,PS_PRTDC2A + LD DE,PS_FLP3 ; ASSUME 3.5" + CP 2 + JR Z,PS_PRTDC2A + LD DE,PS_FLPN ; ASSUME OTHER" +PS_PRTDC2A: + CALL WRITESTR + ; PRINT FLOPPY SIDES + LD A,C ; ATTRIBUTE TO ACCUM + LD DE,PS_FLPSS ; ASSUME SINGLE SIDED + BIT 4,A ; DS? + JR Z,PS_PRTDC2B + LD DE,PS_FLPDS ; DOUBLE SIDED +PS_PRTDC2B: + CALL WRITESTR + ; PRINT FLOPPY DENSITY + LD A,C ; ATTRIBUTE TO ACCUM + RRCA ; ISOLATE DENSITY BITS + RRCA + AND $03 + LD DE,PS_FLPSD ; SINGLE DENSITY + CP 0 + JR Z,PS_PRTDC2C + LD DE,PS_FLPDD ; DOUBLE DENSITY + CP 1 + JR Z,PS_PRTDC2C + LD DE,PS_FLPHD ; HIGH DENSITY + CP 2 + JR Z,PS_PRTDC2C + LD DE,PS_FLPED ; EXTENDED DENSITY + CP 3 + JR Z,PS_PRTDC2C +PS_PRTDC2C: + CALL WRITESTR + CALL PC_COMMA + PRTS("CHS$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA +; + RET ; DONE +; +; PRINT ONE LINE SERIAL UNIT/DEVICE INFO, SERIAL UNIT INDEX IN C +; +PS_SERIAL: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Char $" + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, C:=DEVICE ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_SDSTRREF ; POINT TO SERIAL DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT SERIAL DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP BC ; RECOVER ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTST ; PRINT SERIAL TYPE + POP BC ; RESTORE ATTRIBUTES + POP DE ; RESTORE UNIT NUM TO E + CALL PS_PRTSC ; PRINT SERIAL CONFIG +; + CALL NEWLINE + RET +; +; 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 + LD HL,PS_STTERM ; TYPE IS TERMINAL +; +PS_PRTST1: + CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED + LD A,18 ; 18 CHAR FIELD + SUB C + CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) + RET +; +; 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 + JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG +; + ; PRINT RS-232 CONFIG + LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG + LD C,E ; SET SERIAL UNIT NUM + RST 08 ; DE:HL := BAUD RATE + LD A,D ; TEST FOR $FF + AND E + INC A ; SET Z IF DE == $FF + JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED +; +PS_PRTSC0: + ; PRINT BAUD RATE + PUSH DE ; PRESERVE DE + LD A,D + AND $1F ; ISOLATE ENCODED BAUD RATE + LD L,A ; PUT IN L + LD H,0 ; H IS ALWAYS ZERO + LD DE,75 ; BAUD RATE DECODE CONSTANT + CALL DECODE ; DE:HL := BAUD RATE + LD BC,HB_BCDTMP ; POINT TO TEMP BCD BUF + CALL BIN2BCD ; CONVERT TO BCD + CALL PRTBCD ; AND PRINT IN DECIMAL + POP DE ; RESTORE DE +; + ; PRINT DATA BITS + PUSH DE ; PRESERVE DE + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + AND $03 ; ISOLATE DATA BITS VALUE + ADD A,'5' ; CONVERT TO CHARACTER + CALL COUT ; AND PRINT + POP DE ; RESTORE DE +; + ; PRINT PARITY + PUSH DE ; PRESERVE DE + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + RRCA ; SHIFT RELEVANT BITS + RRCA ; ... + RRCA ; ... + AND $07 ; AND ISOLATE DATA BITS VALUE + LD HL,PS_STPARMAP ; CHARACTER LOOKUP TABLE + CALL ADDHLA ; APPLY OFFSET + LD A,(HL) ; GET CHARACTER + CALL COUT ; AND PRINT + POP DE ; RESTORE DE +; + ; PRINT STOP BITS + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + RRCA ; SHIFT RELEVANT BITS + RRCA ; ... + AND $01 ; AND ISOLATE DATA BITS VALUE + ADD A,'1' ; MAKE IT A CHARACTER + CALL COUT ; AND PRINT +; + 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 + CP $FF ; NO ATTACHED VDA + JR Z,PS_PRTSC2 + PRTS("Video $") ; FORMATTING + AND $0F ; ISOLATE VIDEO UNIT NUM + CALL PRTDECB ; PRINT IT + CALL PC_COMMA +#IF (VDAEMU == EMUTYP_TTY) + PRTS("TTY$") +#ENDIF +#IF (VDAEMU == EMUTYP_ANSI) + PRTS("ANSI$") +#ENDIF + RET +; +PS_PRTSC2: + PRTS("PropTerm$") ; ASSUME PROPELLER + CALL PC_COMMA + PRTS("ANSI$") + RET +; +; PRINT ONE LINE VIDEO UNIT/DEVICE INFO, VIDEO UNIT INDEX IN C +; +PS_VIDEO: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Video $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_VDSTRREF ; POINT TO VIDEO DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT VIDEO DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP DE ; RECOVER ATTRIBUTES + PUSH DE ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTVT ; PRINT VIDEO TYPE + POP DE ; RESTORE ATTRIBUTES + POP BC ; RESTORE UNIT NUM + CALL PS_PRTVC ; PRINT VIDEO CONFIG +; + CALL NEWLINE + RET +; +; PRINT VIDEO TYPE (VIDEO ATTRIBUTE IN E) +; +PS_PRTVT: + LD HL,PS_VTCRT ; ASSUME CRT + CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED + LD A,18 ; 18 CHAR FIELD + SUB C + CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) + RET +; +; PRINT VIDEO CONFIG (UNIT IN C, ATTRIBUTE IN E) +; +PS_PRTVC: + PRTS("Text$") + CALL PC_COMMA + LD B,BF_VDAQRY ; FUNC: QUERY FOR VDA CONFIG + RST 08 ; D:=ROWS, E:=COLS + LD A,E + CALL PRTDECB + LD A,'x' + CALL COUT + LD A,D + CALL PRTDECB + RET +; +; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE +; +PS_PRTDEV: + LD A,D + RRCA ; TYPE IS IN UPPER NIBBLE, MOVE TO LOWER NIBBLE + RRCA + RRCA + RRCA + RLCA ; X2 FOR WORD OFFSET IN STRING TABLE + CALL ADDHLA + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED + LD A,E ; NUM + CALL PRTDECB ; PRINT NUM, ASSUME 1 CHAR + CALL PC_COLON ; PRINT COLON + LD A,12 - 2 ; 12 CHAR FIELD - 1 POS FOR UNIT NUM AND 1 POS FOR COLON + SUB C + CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) + RET +; +; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE +; +PS_PRTNUL: + LD HL,PS_STRNUL + ; FALL THRU TO PS_PRT +; +; +; +PS_PRT: + ; PRINT STRING AT (HL), $ TERM, RETURN CHARS PRINTED IN C + LD C,0 ; INIT CHAR COUNT +PS_PRT1: + LD A,(HL) ; GET CHAR + INC HL ; BUMP INDEX + CP '$' ; TERM? + RET Z ; IF SO, DONE + CALL COUT ; PRINT IT + INC C ; BUMP COUNTER + JR PS_PRT1 ; AND LOOP +; +; +; +PS_PAD: + ; PAD N SPACES SPECIFIED IN A + LD B,A + LD A,' ' +PS_PAD1: + CALL COUT + DJNZ PS_PAD1 + RET +; +; +; +PS_STRNUL .TEXT "--$" ; DISPLAY STRING FOR NUL VALUE +; +; DISK DEVICE STRINGS +; +PS_DDSTRREF: + .DW PS_DDMD, PS_DDFD, PS_DDRF, PS_DDIDE, PS_DDATAPI, PS_DDPPIDE + .DW PS_DDSD, PS_DDPRPSD, PS_DDPPPSD, PS_DDHDSK +; +PS_DDMD .TEXT "MD$" +PS_DDFD .TEXT "FD$" +PS_DDRF .TEXT "RF$" +PS_DDIDE .TEXT "IDE$" +PS_DDATAPI .TEXT "ATAPI$" +PS_DDPPIDE .TEXT "PPIDE$" +PS_DDSD .TEXT "SD$" +PS_DDPRPSD .TEXT "PRPSD$" +PS_DDPPPSD .TEXT "PPPSD$" +PS_DDHDSK .TEXT "HDSK$" +; +; DISK TYPE STRINGS +; +PS_DTSTRREF: + .DW PS_DTFLOP, PS_DTHARD, PS_DTCF, PS_DTSD + .DW PS_DTUSB, PS_DTROM, PS_DTRAM, PS_DTRF +; +PS_DTFLOP .TEXT "Floppy Disk$" +PS_DTHARD .TEXT "Hard Disk$" +PS_DTCF .TEXT "CompactFlash$" +PS_DTSD .TEXT "SD Card$" +PS_DTUSB .TEXT "USB Drive$" +PS_DTROM .TEXT "ROM Disk$" +PS_DTRAM .TEXT "RAM Disk$" +PS_DTRF .TEXT "RAM Floppy$" +PS_DTOTHER .TEXT "???$" +; +; FLOPPY ATTRIBUTE STRINGS +; +PS_FLP8 .TEXT "8\",$" +PS_FLP5 .TEXT "5.25\",$" +PS_FLP3 .TEXT "3.5\",$" +PS_FLPN .TEXT "???\",$" +; +PS_FLPSS .TEXT "SS/$" +PS_FLPDS .TEXT "DS/$" +; +PS_FLPSD .TEXT "SD$" +PS_FLPDD .TEXT "DD$" +PS_FLPHD .TEXT "HD$" +PS_FLPED .TEXT "ED$" +; +; SERIAL DEVICE STRINGS +; +PS_SDSTRREF: + .DW PS_SDUART, PS_SDASCI, PS_SDTERM, + .DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA, PS_SDPIO +; +PS_SDUART .TEXT "UART$" +PS_SDASCI .TEXT "ASCI$" +PS_SDTERM .TEXT "TERM$" +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" + +; +; SERIAL TYPE STRINGS +; +; +; VIDEO DEVICE STRINGS +; +PS_VDSTRREF: + .DW PS_VDVDU, PS_VDCVDU, PS_VDNEC, PS_VDTMS, PS_VDVGA +; +PS_VDVDU .TEXT "VDU$" +PS_VDCVDU .TEXT "CVDU$" +PS_VDNEC .TEXT "NEC$" +PS_VDTMS .TEXT "TMS$" +PS_VDVGA .TEXT "VGA$" +; +; VIDEO TYPE STRINGS +; +PS_VTCRT .TEXT "CRT$" +; +; VIDEO CONFIG STRINGS +; +; +; +; 0 1 2 3 4 5 6 7 +; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 +PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" + .TEXT "---------- ---------- ---------------- --------------------\r\n$" +; +;================================================================================================== +; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED) +;================================================================================================== +; +; OUTPUT CHARACTER FROM A +; +COUT: + ; SAVE ALL INCOMING REGISTERS + PUSH AF + PUSH BC + PUSH DE + PUSH HL +; + ; GET CURRENT CONSOLE UNIT + LD E,A ; TEMPORARILY STASH OUTPUT CHAR IN E + LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE + CP $FF ; TEST FOR $FF (HBIOS NOT READY) + JR Z,COUT1 ; IF NOT READY, USE XIO +; + ; USE HBIOS + LD C,A ; CONSOLE UNIT TO C + LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR + CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY + JR COUT2 ; CONTINUE +; +COUT1: + ;; USE XIO + ;LD A,E ; GET OUTPUT CHAR BACK TO ACCUM + ;CALL XIO_OUTC ; OUTPUT VIA XIO +; +COUT2: + ; RESTORE ALL REGISTERS + POP HL + POP DE + POP BC + POP AF + RET +; +; INPUT CHARACTER TO A +; +CIN: + ; SAVE INCOMING REGISTERS (AF IS OUTPUT) + PUSH BC + PUSH DE + PUSH HL +; + LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE + CP $FF ; TEST FOR $FF (HBIOS NOT READY) + JR Z,CIN1 ; IF NOT READY, USE XIO +; + ; USE HBIOS + LD C,A ; CONSOLE UNIT TO C + LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR + CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY + LD A,E ; RESULTANT CHAR TO A + JR CIN2 ; CONTINUE +; +CIN1: + ;; USE XIO + ;CALL XIO_INC ; GET CHAR +; +CIN2: +; + ; RESTORE REGISTERS (AF IS OUTPUT) + POP HL + POP DE + POP BC + RET +; +; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) +; +CST: + ; SAVE INCOMING REGISTERS (AF IS OUTPUT) + PUSH BC + PUSH DE + PUSH HL +; + LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE + CP $FF ; TEST FOR $FF (HBIOS NOT READY) + JR Z,CST1 ; IF NOT READY, USE XIO +; + ; USE HBIOS + LD C,A ; CONSOLE UNIT TO C + LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS + CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY + JR CST2 ; CONTINUE +; +CST1: + ;; USE XIO + ;CALL XIO_IST ; GET STATUS +; +CST2: + ; RESTORE REGISTERS (AF IS OUTPUT) + POP HL + POP DE + POP BC + RET +; +;================================================================================================== +; MISCELLANEOUS UTILITY FUNCTIONS +;================================================================================================== +; +; SET HL TO IY+A, A IS TRASHED +; +LDHLIYA: + PUSH IY ; COPY INSTANCE DATA PTR + POP HL ; ... TO HL + ;JP ADDHLA ; APPLY OFFSET TO HL AND RETURN + ADD A,L ; ADD OFFSET TO LSB + LD L,A ; ... PUT BACK IN L + RET NC ; DONE IF CF NOT SET + INC H ; IF CF SET, BUMP MSB + RET ; ... AND RETURN +; +; CONVERT AN HBIOS STANDARD HARD DISK CHS ADDRESS TO +; AN LBA ADDRESS. A STANDARD HBIOS HARD DISK IS ASSUMED +; TO HAVE 16 SECTORS PER TRACK AND 16 HEADS PER CYLINDER. +; +; INPUT: HL=TRACK, D=HEAD, E=SECTOR +; OUTPUT: DE:HL=32 BIT LBA ADDRESS (D:7 IS NOT SET IN THE RESULT) +; +HB_CHS2LBA: +; + LD A,D ; HEAD TO A + RLCA ; LEFT SHIFT TO HIGH NIBBLE + RLCA ; ... DEPENDS ON HIGH + RLCA ; ... NIBBLE BEING 0 SINCE + RLCA ; ... IT ROTATES INTO LOW NIBBLE + OR E ; COMBINE WITH SECTOR (HIGH NIBBLE MUST BE ZERO) + LD D,0 + LD E,H + LD H,L + LD L,A + XOR A + RET +; +;================================================================================================== +; HBIOS GLOBAL DATA +;================================================================================================== +; +IDLECOUNT .DB 0 +; +HEAPCURB .DW 0 ; MARK HEAP ADDRESS AFTER INITIALIZATION +; +HB_TICKS .FILL 4,0 ; 32 BIT TICK COUNTER +; +STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$" +STR_PLATFORM .DB PLATFORM_NAME, "$" +STR_SWITCH .DB "*** Activating CRT Console ***$" +STR_BADINT .DB "\r\n*** BAD INT ***\r\n$" +; +#IF (DSKYENABLE) +MSG_HBVER .DB $BE,$FF,$8A,$FB,$D7,$6D,$77,$B0 ; "HBIOS291" +#ENDIF +; +HB_CURSEC .DB 0 ; CURRENT SECOND (TEMP) +; +HB_BCDTMP .FILL 5,0 ; BCD NUMBER STORAGE (TEMP) +; +HB_WRKBUF .FILL 512,0 ; INTERNAL DISK BUFFER +; +HB_END .EQU $ +; +SLACK .EQU BNKTOP - $ + .ECHO "HBIOS space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" +; +#IFDEF ROMBOOT + .FILL SLACK +#ENDIF +; + .END diff --git a/pio.asm b/pio.asm new file mode 100644 index 00000000..9a04177d --- /dev/null +++ b/pio.asm @@ -0,0 +1,695 @@ +; 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 +; +; +; 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 (PIO_DEV),A ; CURRENT DEVICE NUMBER +PIO_PREINIT0: + PUSH BC ; SAVE LOOP CONTROL + LD A,C ; PHYSICAL UNIT TO A + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) + RLCA ; ... + RLCA ; ... TO GET OFFSET INTO CFG TABLE + LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + CALL ADDHLA ; HL := ENTRY ADDRESS + PUSH HL ; SAVE IT + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE + POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE + POP BC ; RESTORE LOOP CONTROL +; + LD A,(IY+1) ; GET THE PIO TYPE DETECTED + OR A ; SET FLAGS + JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND +; + PUSH BC ; SAVE LOOP CONTROL + PUSH AF + DEC A + LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS + JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D + DEC A + LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS + JR Z,TYPFND + DEC A + LD BC,PRT_FNTBL + JR NZ,TYPDUN +TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE +TYPDUN: POP AF + POP BC ; RESTORE LOOP CONTROL +; +PIO_PREINIT2: + INC C ; NEXT PHYSICAL UNIT + DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE +; +#IF (INTMODE == 2) + ; SETUP PIO INTERRUPT VECTOR IN IVT + LD HL,PIO0INT + LD (HBX_IVT + IVT_PIO0),HL +#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: + LD A,C ; SET THE UNIT NUMBER + LD (IY),A + + LD DE,-1 ; LEAVE CONFIG ALONE + JP PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN +; +PIO_INIT: + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + + LD A,C ; PHYSICAL UNIT TO A + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) + RLCA ; ... + RLCA ; ... TO GET OFFSET INTO CFG TABLE + LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + CALL ADDHLA ; HL := ENTRY ADDRESS + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + + LD A,(IY+1) ; GET PIO TYPE + OR A ; SET FLAGS + CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO + + PUSH DE + LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL + CALL PIO_INITDEV ; BASED ON DPW + POP DE + + POP BC ; RESTORE LOOP CONTROL + INC C ; NEXT UNIT + DJNZ PIO_INIT1 ; LOOP TILL DONE +; + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; EXAMPLE CODE +; +PIO_LPT: + IN A,($F6) ; get device status + AND $20 ; device ready? + JR Z,PIO_LPT ; no, busy wait + IN A,($F5) ; get transmit buffer register status ready? + AND $20 ; ready? + JR Z,PIO_LPT ; no, busy wait + LD A,C ; ready, char A for output through data port + OUT ($F0),A ; output char + RET + + + +; ------------------------------------ +; ZILOG PIO FUNCTION TABLE ROUTINES +;------------------------------------- + +PIO_IN: + LD C,(IY+3) + IN A,(C) + LD E,A + XOR A ; SIGNAL SUCCESS + RET + +; +PIO0INT: +PIO1INT: +PIO2INT: +PIO3INT: +PIO4INT: +PIO5INT: +PIO6INT: +PIO7INT: +PIO8INT: +PIO9INT: + OR $FF ; NZ SET TO INDICATE INT HANDLED + RET +; +; 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 + + LD C,(IY+3) ; GET PORT + LD A,(IY+4) ; GET MODE (B7B6) + + +PIO_IST: + RET +; +PIO_OST: + RET +; +; PIO_INITDEV - Configure device. +; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. +; Otherwise use the configuration information in DE to program those settings and save them in the device table +; +; SETUP PARAMETER WORD: +; +-------------------------------+ +-------+-----------+---+-------+ +; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | +; +-------------------------------+ --------------------+-----------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- +; +; +; MSB = BIT MAP USE IN MODE 3 +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; CHIP CHANNEL B5 B4 B3 001 Channel 1 +; 010 Channel 2 +; 100 Channel 3 +; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED +; = 1 IS ALLOCATED +; +; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 +; 01 IVT_PIO1 +; 10 IVT_PIO2 +; 11 IVT_PIO3 +PIO_INITDEV: + ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) + LD A,D ; TEST DE FOR + AND E ; ... VALUE OF -1 + INC A ; ... SO Z SET IF -1 + JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG +; + ; LOAD EXISTING CONFIG TO REINIT + 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 +; +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 +; +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: +PPI_DEVICE: + LD D,CIODEV_PIO ; D := DEVICE TYPE + LD E,(IY) ; E := PHYSICAL UNIT + LD C,$40 ; C := ATTRIBUTE + XOR A ; SIGNAL SUCCESS + RET + +; ------------------------------------ +; 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 + 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 + 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 +; + ; ALL DONE IF NO PIO WAS DETECTED + LD A,(IY+1) ; GET SIO 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 +; + XOR A + RET +; +; WORKING VARIABLES +; +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_PORT + +PIO_STR_NONE .DB "$" +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+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) +DEFPIO(PIO_ZPIO,PIOZBASE+4,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) +#ENDIF +#IF PIO_4P +DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO8FT,PIO9FT,INT_N,INT_N) +DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO10FT,PIO11FT,INT_N,INT_N) +#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 +; EACH PIO NEEDS A FUNCTION TABLE +; ECB-ZP : PIO0FT-PIO3FT +; ECB-4P : PIO4FT-PIO11FT + +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 +PIO2FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO2FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO3FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO3FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +#ENDIF +; +#IF PIO_4P +PIO4FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO4FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO5FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO5FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO6FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO6FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO7FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO7FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO8FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO8FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO9FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO9FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO10FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO10FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +PIO11FT .DW PIO_IN + .DW PIO_OUT + .DW PIO_IST + .DW PIO_OST + .DW PIO_INITDEV + .DW PIO_QUERY + .DW PIO_DEVICE +#IF (($ - PIO11FT) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" +#ENDIF +#ENDIF +; +; 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 From 8d3c7a185912314a3847519a6ffaed2416dcdd48 Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Tue, 9 Apr 2019 23:27:54 +0800 Subject: [PATCH 7/9] Delete hbios.asm --- hbios.asm | 3398 ----------------------------------------------------- 1 file changed, 3398 deletions(-) delete mode 100644 hbios.asm diff --git a/hbios.asm b/hbios.asm deleted file mode 100644 index 69f95dfb..00000000 --- a/hbios.asm +++ /dev/null @@ -1,3398 +0,0 @@ -; -;================================================================================================== -; HBIOS -;================================================================================================== -; -; THIS FILE CONTAINS THE HBIOS IMAGE THAT IS INTENDED TO RUN IN A DEDICATED RAM BANK. THE CODE IS -; CONSTRUCTED SUCH THAT IT CAN BE LAUNCHED IN A VARIETY OF MODES AND INSTALL ITSELF. A SMALL 512 -; BYTE PROXY IS PLACED AT THE TOP OF CPU MEMORY (FE00H-FFFFH). THIS PROXY CODE ALLOWS CODE -; RUNNING FROM ANY BANK TO INVOKE HBIOS FUNCTIONS. NORMALLY, ANY BANK THAT RUNS CODE WOULD SETUP -; THE RST 8 VECTOR TO POINT TO THE PROXY INVOKE ENTRY POINT AT FFF0H. CALLS VIA THE PROXY INVOKE -; ENTRY POINT TRANSPARENTLY SWAP IN THE HBIOS BANK, PERFORM THE REQUESTED FUNCTION, AND RETURN -; WITH THE ORIGINAL BANK ACTIVE. THE CODE USING HBIOS FUNCTIONS DOES NOT NEED TO BE AWARE OF -; THE BANK SWITCHING THAT OCCURS. -; -; THIS FILE CAN BE COMPILED TO BOOT IN ONE OF 3 MODES (ROM, APPLICATION, OR IMAGE) AS DESCRIBED -; BELOW. WHEN COMPILED, YOU MUST DEFINE EXACTLY ONE OF THE FOLLOWING MACROS: -; -; - ROMBOOT: BOOT FROM A ROM BANK -; -; WHEN ROMBOOT IS DEFINED, THE FILE IS ASSEMBLED TO BE IMBEDDED AT THE START OF A ROM -; ASSUMING THAT THE CPU WILL START EXECUTION AT ADDRESS 0. AFTER PERFORMING MINIMAL -; SYSTEM INITIALIZATION, THE IMAGE OF THE RUNNING ROM BANK IS COPIED TO A RAM BANK -; CREATING A SHADOW COPY IN RAM. EXECUTION IS THAN TRANSFERRED TO THE RAM SHADOW COPY. -; THIS IS ESSENTIAL BECAUSE THE HBIOS CODE DOES NOT SUPPORT RUNNING IN READ ONLY MEMORY -; (EXCEPT FOR THE INITIAL LAUNCHING CODE). IN THIS MODE, THE HBIOS INITIALIZATION WILL -; ALSO COPY THE OS IMAGES BANK IN ROM TO THE USER RAM BANK AND LAUNCH IT AFTER HBIOS -; IS INSTALLED. -; -; - APPBOOT: BOOT FROM A CP/M STYLE APPLICATION FILE -; -; WHEN APPBOOT IS DEFINED, THE FILE IS ASSEMBLED AS A CP/M APPLICATION ASSUMING -; THAT IT WILL BE LOADED AT 100H BY THE CP/M (OR COMPATIBLE) OS. NOTE THAT IN -; THIS CASE IT IS ASSUMED THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE -; HBIOS APPLICATION BINARY. THE APPENDED OS IMAGES ARE COPIED TO THE USER RAM -; BANK AND LAUNCHED AFTER HBIOS HAS INSTALLED ITSELF. -; -; - IMGBOOT: BOOT FROM AN IMAGE FILE THAT HAS BEEN PLACED IN THE USER BANK -; -; WHEN IMGBOOT IS DEFINED, THE FILE IS ASSEMBLED SUCH THAT IT CAN BE PRELOADED -; INTO THE RAM USER BANK BY AN EXTERNAL PROCESS THAT SUBSEQUENTLY LAUNCHES -; THE CODE AT ADDRESS 0. THE MOST COMMON EXAMPLE OF THIS IS THE UNA FSFAT -; TOOL WHICH CAN LOAD AN IMAGE FROM A DOS FAT FILESYSTEM PROVIDING A SIMPLE -; WAY TO LOAD A TEST COPY OF HBIOS. AS IS THE CASE WITH APPBOOT, IT IS ASSUMED -; THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE IMAGE AND IS LAUNCHED -; AFTER HBIOS IS INSTALLED. -; -; INCLUDE GENERIC STUFF -; -#INCLUDE "std.asm" -; -; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED. -; -MODCNT .EQU 0 -#IFDEF ROMBOOT -MODCNT .SET MODCNT + 1 -#ENDIF -#IFDEF APPBOOT -MODCNT .SET MODCNT + 1 -#ENDIF -#IFDEF IMGBOOT -MODCNT .SET MODCNT + 1 -#ENDIF -#IF (MODCNT != 1) - .ECHO "*** ERROR: PLEASE DEFINE ONE AND ONLY ONE OF ROMBOOT, APPBOOT, IMGBOOT!!!\n" - !!! ; FORCE AN ASSEMBLY ERROR -#ENDIF -; -; -; -#IF ((PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180)) -#DEFINE DIAGP $00 -#ENDIF -; -#IFDEF DIAGP -#DEFINE DIAG(N) PUSH AF - #DEFCONT \ LD A,N - #DEFCONT \ OUT (DIAGP),A - #DEFCONT \ POP AF -#ELSE -#DEFINE DIAG(N) \; -#ENDIF -; -; -; -#IF (INTMODE == 0) -; NO INTERRUPT HANDLING -#DEFINE HB_DI ; -#DEFINE HB_EI ; -#ENDIF -#IF ((INTMODE == 1) | (INTMODE == 2)) -; MODE 1 OR 2 INTERRUPT HANDLING -#DEFINE HB_DI DI -#DEFINE HB_EI EI -#ENDIF -#IF (INTMODE > 2) - .ECHO "*** ERROR: INVALID INTMODE SETTING!!!\n" - !!! ; FORCE AN ASSEMBLY ERROR -#ENDIF -; -; -; -#IFNDEF APPBOOT -; - .ORG 0 -; -;================================================================================================== -; NORMAL PAGE ZERO SETUP, RET/RETI/RETN AS APPROPRIATE, LEAVE INTERRUPTS DISABLED -;================================================================================================== -; - .FILL (000H - $),0FFH ; RST 0 - JP HB_START - .DW ROM_SIG - .FILL (008H - $),0FFH ; RST 8 - JP HB_INVOKE ; INVOKE HBIOS FUNCTION - .FILL (010H - $),0FFH ; RST 10 - RET - .FILL (018H - $),0FFH ; RST 18 - RET - .FILL (020H - $),0FFH ; RST 20 - RET - .FILL (028H - $),0FFH ; RST 28 - RET - .FILL (030H - $),0FFH ; RST 30 - RET - .FILL (038H - $),0FFH ; RST 38 / IM1 INT -#IF (INTMODE == 1) - JP INT_IM1 ; JP TO INTERRUPT HANDLER IN HI MEM -#ELSE - RETI ; RETURN W/ INTS DISABLED -#ENDIF - .FILL (066H - $),0FFH ; NMI - RETN -; - .FILL (070H - $),0FFH ; SIG STARTS AT $80 -; -ROM_SIG: - .DB $76, $B5 ; 2 SIGNATURE BYTES - .DB 1 ; STRUCTURE VERSION NUMBER - .DB 7 ; ROM SIZE (IN MULTIPLES OF 4KB, MINUS ONE) - .DW NAME ; POINTER TO HUMAN-READABLE ROM NAME - .DW AUTH ; POINTER TO AUTHOR INITIALS - .DW DESC ; POINTER TO LONGER DESCRIPTION OF ROM - .DB 0, 0, 0, 0, 0, 0 ; RESERVED FOR FUTURE USE; MUST BE ZERO -; -NAME .DB "ROMWBW v", BIOSVER, ", ", TIMESTAMP, 0 -AUTH .DB "WBW",0 -DESC .DB "ROMWBW v", BIOSVER, ", Copyright (C) 2015, Wayne Warthen, GNU GPL v3", 0 -; - .FILL ($100 - $),$FF ; PAD REMAINDER OF PAGE ZERO -; -#ENDIF -; -;================================================================================================== -; HBIOS CONFIGURATION BLOCK (HCB) -;================================================================================================== -; - .ORG HCB_LOC -HCB: - JP HB_START -; -CB_MARKER .DB 'W',~'W' ; MARKER -CB_VERSION .DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO - .DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO -; -CB_PLATFORM .DB PLATFORM -CB_CPUMHZ .DB CPUMHZ -CB_CPUKHZ .DW CPUKHZ -CB_RAMBANKS .DB RAMSIZE / 32 -CB_ROMBANKS .DB ROMSIZE / 32 -; -CB_BOOTVOL .DW 0 ; BOOT VOLUME IS UNIT/SLICE, SET BY LOADER -CB_BOOTBID .DB 0 ; BOOT BANK ID, SET BY LOADER -CB_SERDEV .DB 0 ; PRIMARY SERIAL UNIT IS UNIT #0 BY FIAT -CB_CRTDEV .DB $FF ; PRIMARY CRT UNIT, $FF UNTIL AFTER HBIOS INIT -CB_CONDEV .DB $FF ; CONSOLE UNIT, $FF UNTIL AFTER HBIOS INIT -; -; MEMORY MANAGEMENT VARIABLES START AT $20 -; - .FILL (HCB + $20 - $),0 -; -CB_HEAP .DW 0 -CB_HEAPTOP .DW 0 -; -; STANDARD BANK ID'S START AT $D8 -; - .FILL (HCB + $D8 - $),0 -; -CB_BIDCOM .DB BID_COM -CB_BIDUSR .DB BID_USR -CB_BIDBIOS .DB BID_BIOS -CB_BIDAUX .DB BID_AUX -CB_BIDRAMD0 .DB BID_RAMD0 -CB_BIDRAMDN .DB BID_RAMDN -CB_BIDROMD0 .DB BID_ROMD0 -CB_BIDROMDN .DB BID_ROMDN -; - .FILL (HCB + HCB_SIZ - $),0 ; PAD REMAINDER OF HCB -; -;================================================================================================== -; HBIOS UPPER MEMORY PROXY (RELOCATED TO RUN IN TOP 2 PAGES OF CPU RAM) -;================================================================================================== -; -; THE FOLLOWING CODE IS RELOCATED TO THE TOP OF MEMORY TO HANDLE INVOCATION DISPATCHING -; - .FILL (HBX_IMG - $) ; FILL TO START OF PROXY IMAGE START - .ORG HBX_LOC ; ADJUST FOR RELOCATION -; -; MEMORY LAYOUT: -; -; HBIOS PROXY CODE $FE00 (256 BYTES) -; INTERRUPT VECTORS $FF00 (32 BYTES, 16 ENTRIES) -; INTERRUPT HANDLER STUBS $FF20 (128 BYTES) -; HBIOS PROXY COPY BUFFER $FF80 (64 BYTES) -; HBIOS PROXY MGMT BLOCK $FFE0 (32 BYTES) -; -; DEFINITIONS -; -HBX_BUFSIZ .EQU $40 ; INTERBANK COPY BUFFER SIZE -; -; HBIOS IDENTIFICATION DATA BLOCK -; -HBX_IDENT: - .DB 'W',~'W' ; MARKER - .DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO - .DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO -; -;================================================================================================== -; HBIOS ENTRY FOR RST 08 PROCESSING -;================================================================================================== -; -HBX_INVOKE: - LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME - LD A,(HB_CURBNK) ; GET CURRENT BANK - LD (HB_INVBNK),A ; SAVE INVOCATION BANK - - LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH - LD A,BID_BIOS ; HBIOS BANK - CALL HBX_BNKSEL ; SELECT IT - LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK - - CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER - - LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH - PUSH AF ; SAVE AF (FUNCTION RETURN) - - LD A,(HB_INVBNK) ; LOAD ORIGINAL BANK - CALL HBX_BNKSEL ; SELECT IT - POP AF ; RESTORE AF - LD SP,0 ; RESTORE ORIGINAL STACK FRAME -HBX_INVSP .EQU $ - 2 - - RET ; RETURN TO CALLER -; -;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -;; BNKSEL - Switch Memory Bank to Bank in A. -;; Preserve all Registers including Flags. -;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -; -HBX_BNKSEL: - ; IF AN INTERRUPT OCCURS DURING THE BANK SWITCH CODE, - ; THE BANK WILL BE SET TO (CURBNK) AS THE INTERRUPT - ; RETURNS. SO, IT IS IMPORTANT THAT (HB_CURBNK) BE - ; SET AS THE FIRST STEP TO AVOID ISSUES IF AN INTERRUPT - ; OCCURS DURING PROCESSING. - LD (HB_CURBNK),A ; RECORD NEW CURRENT BANK -; -HBX_BNKSEL_INT: -; -#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) - #IF (INTMODE == 1) - ; THIS BIT OF ABSURDITY HANDLES A RARE (BUT FATAL) SITUATION - ; WHERE AN IM1 INTERRUPT OCCURS BETWEEN SETTING THE RAM AND - ; ROM SELECTORS. BRACKETING THE INSTRUCTIONS WITH DI/EI - ; IS CONTRAINDICATED BECAUSE THIS ROUTINE IS CALLED BY - ; OTHER ROUTINES THAT MUST CONTROL INT ENABLE AT A HIGHER - ; LEVEL. THE FOLLOWING TECHNIQUE ENSURES THAT YOU ALWAYS - ; SWITCH DIRECTLY FROM THE PREVIOUS BANK TO THE TARGET BANK - ; WITHOUT AN "ERRANT" BANK BEING ACTIVE BETWEEN THE TWO - ; BANK SELECTION I/O INSTRUCTIONS. THE TECHNIQUE IS ONLY - ; NEEDED WHEN USING INT MODE 1 BECAUSE THAT MODE REQUIRES - ; PAGE ONE TO HAVE A VALID INT HANDLER WHENEVER INTS ARE - ; ENABLED. - ;BIT 7,A ; [8] TEST RAM BIT - ;JR Z,HBX_ROM ; [12/7] IF NOT SET, JUST DO ROM - OR A ; [4] SET FLAGS - JP P,HBX_ROM ; [10] BIT 7 INDICATES RAM - #ENDIF - OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR -HBX_ROM: - OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR - RET ; DONE -#ENDIF -#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80)) - BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE - JR Z,HBX_ROM ; NOT SET, SELECT ROM PAGE - RES 7,A ; RAM PAGE REQUESTED: CLEAR ROM BIT - ADD A,16 ; ADD 16 x 32K - RAM STARTS FROM 512K -; -HBX_ROM: - RLCA ; TIMES 2 - GET 16K PAGE INSTEAD OF 32K - OUT (MPGSEL_0),A ; BANK_0: 0K - 16K - ;OUT (DIAGP),A ; *DEBUG* - INC A ; - OUT (MPGSEL_1),A ; BANK_1: 16K - 32K - RET ; DONE -#ENDIF -#IF (PLATFORM == PLT_N8) - BIT 7,A ; TEST BIT 7 FOR RAM VS. ROM - JR Z,HBX_ROM ; IF NOT SET, SELECT ROM PAGE -; -HBX_RAM: - RES 7,A ; CLEAR BIT 7 FROM ABOVE - RLCA ; SCALE SELECTOR TO - RLCA ; ... GO FROM Z180 4K PAGE SIZE - RLCA ; ... TO DESIRED 32K PAGE SIZE - OUT0 (Z180_BBR),A ; WRITE TO BANK BASE - LD A,N8_DEFACR | 80H ; SELECT RAM BY SETTING BIT 7 - OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER - RET ; DONE -; -HBX_ROM: - OUT0 (N8_RMAP),A ; BANK INDEX TO N8 RMAP REGISTER - XOR A ; ZERO ACCUM - OUT0 (Z180_BBR),A ; ZERO BANK BASE - LD A,N8_DEFACR ; SELECT ROM BY CLEARING BIT 7 - OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER - RET ; DONE -; -#ENDIF -#IF (PLATFORM == PLT_MK4) - RLCA ; RAM FLAG TO CARRY FLAG AND BIT 0 - JR NC,HBX_BNKSEL1 ; IF NC, WANT ROM PAGE, SKIP AHEAD - XOR %00100001 ; SET BIT FOR HI 512K, CLR BIT 0 -HBX_BNKSEL1: - RLCA ; CONTINUE SHIFTING TO SCALE SELECTOR - RLCA ; FOR Z180 4K PAGE -> DESIRED 32K PAGE - OUT0 (Z180_BBR),A ; WRITE TO BANK BASE - RET ; DONE -#ENDIF -; -;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -; Copy Data - Possibly between banks. This resembles CP/M 3, but -; usage of the HL and DE registers is reversed. -; Caller MUST ensure stack is already in high memory. -; Caller MUST preset HBX_SRCBNK and HBX_DSTBNK. -; Caller MUST disable ints if IM1 active -; Enter: -; HL = Source Address -; DE = Destination Address -; BC = Number of bytes to copy -; Exit : None -; Uses : AF,BC,DE,HL -; -;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -; -HBX_BNKCPY: - LD (HBX_BC_SP),SP ; PUT STACK - LD SP,HBX_TMPSTK ; ... IN HI MEM - - LD A,(HB_CURBNK) ; GET CURRENT BANK - PUSH AF ; AND SAVE TO RESTORE LATER - PUSH BC ; CUR LEN -> (SP) -; -HBX_BC_LOOP: - EX (SP),HL ; HL := CUR LEN, (SP) := CUR SRC - LD BC,HBX_BUFSIZ ; SET BC TO BOUNCE BUFFER SIZE - OR A ; CLEAR CARRY FLAG - SBC HL,BC ; CUR LEN := CUR LEN - BBUF SIZE - JR C,HBX_BC_LAST ; END GAME, LESS THAN BBUF BYTES LEFT - EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN - CALL HBX_BC_ITER ; DO A FULL BBUF SIZE CHUNK - JR HBX_BC_LOOP ; AND REPEAT TILL DONE -; -HBX_BC_LAST: - ; HL IS BETWEEN -(BBUF SIZE) AND -1, BC = BBUF SIZE - OR A ; CLEAR CARRY - ADC HL,BC ; HL := REM LEN (0 - 127) - EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN - POP BC ; BC := REM LEN - CALL NZ,HBX_BC_ITER ; DO FINAL CHUNK, IFF > 0 BYTES - POP AF ; RECOVER ORIGINAL BANK - CALL HBX_BNKSEL ; SWITCH - - LD SP,$FFFF ; RESTORE STACK -HBX_BC_SP .EQU $ - 2 ; ... TO ORIGINAL VALUE - RET -; -HBX_BC_ITER: - ; HL = SRC ADR, DE = DEST ADR, BC = LEN - PUSH BC ; SAVE COPY LEN - PUSH DE ; FINAL DEST ON STACK - LD DE,HBX_BUF ; SET DEST TO BUF - LD A,(HB_SRCBNK) ; GET SOURCE BANK - CALL HBX_BNKSEL ; SWITCH TO SOURCE BANK - LDIR ; HL -> BUF (DE), BC BYTES, HL UPDATED SRC ADR - POP DE ; DE := FINAL DEST - POP BC ; GET LEN BACK IN BC - PUSH HL ; SAVE UPDATED SRC ADR - LD HL,HBX_BUF ; SET SRC ADR TO BUF - LD A,(HB_DSTBNK) ; GET DEST BANK - CALL HBX_BNKSEL ; SWITCH TO DEST BANK - LDIR ; BUF (HL) -> DE, BC BYTES, DE UPDATED DEST ADR - POP HL ; RECOVER UPDATED SRC ADR - ; HL = UPDATED SRC, DE = UPDATED DEST, BC = 0 - RET -; -; CALL A ROUTINE IN ANOTHER BANK. -; CALLER MUST ENSURE STACK IS ALREADY IN HIGH MEMORY AND HAS ADEQUATE SPACE. -; IF IM1 INTERRUPTS ARE POSSIBLE, CALLER MUST EITHER DISABLE THEM PRIOR TO -; BNKCALL OR MAKE SURE THAT PAGE ZERO IN TARGTET BANK IS PREPARED FOR THEM. -; ON INPUT A=TARGET BANK, HL=TARGET ADDRESS -; -HBX_BNKCALL: - LD (HBX_TGTBNK),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW - LD (HBX_TGTADR),HL ; STUFF ADDRESS TO CALL INTO CODE BELOW - LD A,(HB_CURBNK) ; GET CURRENT BANK - PUSH AF ; SAVE FOR RETURN -HBX_TGTBNK .EQU $ + 1 - LD A,$FF ; LOAD BANK TO CALL ($FF OVERLAID AT ENTRY) - CALL HBX_BNKSEL ; ACTIVATE THE NEW BANK - -HBX_TGTADR .EQU $ + 1 - CALL $FFFF ; CALL ROUTINE ($FFFF IS OVERLAID ABOVE) - - EX (SP),HL ; SAVE HL AND GET BANK TO RESTORE IN HL - PUSH AF ; SAVE AF - LD A,H ; BANK TO RESTORE TO A - CALL HBX_BNKSEL ; RESTORE IT - POP AF ; RECOVER AF - POP HL ; RECOVER HL - RET -; -; PEEK & POKE ROUTINES -; ADDRESS IN HL, BANK IN D, VALUE IN/OUT IN E, A IS TRASHED -; CALLER MUST DISABLE INTS IF IM1 AND ACCESSING PAGE W/O IM1 INT VECTOR -; -HBX_PEEK: - LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME - LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM - LD A,(HB_CURBNK) - PUSH AF - LD A,D - CALL HBX_BNKSEL - LD E,(HL) - JR HBX_PPRET -; -HBX_POKE: - LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME - LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM - LD A,(HB_CURBNK) - PUSH AF - LD A,D - CALL HBX_BNKSEL - LD (HL),E -; -HBX_PPRET: - POP AF - CALL HBX_BNKSEL - LD SP,0 ; RESTORE ORIGINAL STACK FRAME -HBX_PPSP .EQU $ - 2 - RET -; -; SMALL TEMPORARY STACK FOR USE BY INVOKE, PEEK, AND POKE -; - .FILL 20,$CC ; 10 LEVEL STACK -HBX_TMPSTK .EQU $ -; -; PRIVATE STACK AT END OF HBIOS CODE -; OCCUPIES SPACE BEFORE IVT -; -HBX_STKSIZ .EQU $FF00 - $ - .ECHO "HBIOS PROXY STACK space: " - .ECHO HBX_STKSIZ - .ECHO " bytes.\n" - .FILL HBX_STKSIZ,$FF -HBX_STACK .EQU $ -; -#IF (INTMODE == 2) -; -; HBIOS INTERRUPT VECTOR TABLE (16 ENTRIES) -; -HBX_IVT: - .DW INT_BAD ; IVT_INT1 - .DW INT_BAD ; IVT_INT2 - .DW INT_BAD ; IVT_TIM0 - .DW INT_BAD ; IVT_TIM1 - .DW INT_BAD ; IVT_DMA0 - .DW INT_BAD ; IVT_DMA1 - .DW INT_BAD ; IVT_CSIO - .DW INT_BAD ; IVT_SER0 - .DW INT_BAD ; IVT_SER1 - .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 ; -; -HBX_IVTCNT .EQU ($ - HBX_IVT) / 2 -; -HBX_ITBL: - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT - .DW HB_BADINT -#ENDIF -; -; INTERRUPT HANDLER STUBS -; -; THE FOLLOWING INTERRUPT STUBS RECEIVE CONTROL FROM THE -; INTERRUPT, SETUP A HANDLER VECTOR IN HBIOS AND THEN -; BRANCH TO THE COMMON INTERRUPT DISPATCHER -; -; -INT_IM1: -#IF (INTMODE == 1) - PUSH HL ; SAVE HL - LD HL,HB_IM1INT ; HL := IM1 INT HANDLER IN BIOS BANK - JR HBX_INT ; TO TO ROUTING CODE -#ELSE - RETI ; UNEXPECTED INT, RET W/ INTS LEFT DISABLED -#ENDIF -; -#IF (INTMODE == 2) -; -INT_BAD: ; BAD INTERRUPT HANDLER - PUSH HL ; SAVE HL - LD HL,HB_BADINT ; HL := INT HANDLER IN BIOS BANK - JR HBX_INT ; GO TO ROUTING CODE -; -INT_TIMER: ; TIMER INTERRUPT HANDLER - PUSH HL ; SAVE HL - LD HL,HB_TIMINT ; HL := INT ADR IN BIOS - JR HBX_INT ; GO TO ROUTING CODE -; - #IF (SIOENABLE) -INT_SIO: ; SIO INTERRUPT HANDLER - PUSH HL ; SAVE HL - LD HL,SIO_INT ; HL := SIO INT HANDLER IN BIOS BANK - JR HBX_INT ; GO TO ROUTING CODE - #ENDIF -; -#IF (PIO_ZP) -INT_ZP0: ; PIO INTERRUPT HANDLER - PUSH HL ; SAVE HL - LD HL,PIO0INT ; HL := PIO INT HANDLER IN BIOS BANK - JR HBX_INT ; GO TO ROUTING CODE -INT_ZP1 - PUSH HL ; SAVE HL - LD HL,PIO1INT ; 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,PIO2INT ; HL := PIO INT HANDLER IN BIOS BANK - JR HBX_INT ; GO TO ROUTING CODE -INT_4P1: - PUSH HL ; SAVE HL - LD HL,PIO3INT ; HL := PIO INT HANDLER IN BIOS BANK - JR HBX_INT ; GO TO ROUTING CODE -#ENDIF -; -#ENDIF -; -#IF (INTMODE > 0) -; -; COMMON INTERRUPT DISPATCHING CODE -; SETUP AND CALL HANDLER IN BIOS BANK -; -HBX_INT: ; COMMON INTERRUPT ROUTING CODE -; - LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME - LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM - - ; SAVE STATE (HL SAVED PREVIOUSLY ON ORIGINAL STACK FRAME) - PUSH AF ; SAVE AF - PUSH BC ; SAVE BC - PUSH DE ; SAVE DE - PUSH IY ; SAVE IY - - LD A,BID_IMG0 ; HBIOS BANK - CALL HBX_BNKSEL_INT ; SELECT IT - - CALL JPHL ; CALL INTERRUPT ROUTINE - - LD A,(HB_CURBNK) ; GET PRE-INT BANK - CALL HBX_BNKSEL ; SELECT IT - - ; RESTORE STATE - POP IY ; RESTORE IY - POP DE ; RESTORE DE - POP BC ; RESTORE BC - POP AF ; RESTORE AF - - LD SP,$FFFF ; RESTORE ORIGINAL STACK FRAME -HBX_INT_SP .EQU $ - 2 - - POP HL ; RESTORE HL - - HB_EI ; ENABLE INTERRUPTS - RETI ; AND RETURN -; -#ENDIF -; -; FILL TO START OF BOUNCE BUFFER -; -HBX_INTFILL .EQU (HBX_XFC - HBX_BUFSIZ - $) - .ECHO "HBIOS INT space remaining: " - .ECHO HBX_INTFILL - .ECHO " bytes.\n" - .FILL HBX_INTFILL,$FF -; -; INTERBANK COPY BUFFER (64 BYTES) -; -HBX_BUF .FILL HBX_BUFSIZ,0 -; -; HBIOS PROXY MGMT BLOCK (TOP 32 BYTES) -; -#IFDEF ROMBOOT - .DB BID_BOOT ; CURRENTLY ACTIVE LOW MEMORY BANK ID -#ELSE - .DB BID_USR ; CURRENTLY ACTIVE LOW MEMORY BANK ID -#ENDIF - .DB 0 ; BANK ACTIVE AT TIME OF HBIOS CALL INVOCATION - .DW 0 ; BNKCPY SOURCE ADDRESS - .DB BID_USR ; BNKCPY SOURCE BANK ID - .DW 0 ; BNKCPY DESTINATION ADDRESS - .DB BID_USR ; BNKCPY DESTINATION BANK ID - .DW 0 ; BNKCPY LENGTH - .FILL 6,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE - JP HBX_INVOKE ; FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08) - JP HBX_BNKSEL ; FIXED ADR ENTRY FOR HBX_BNKSEL - JP HBX_BNKCPY ; FIXED ADR ENTRY FOR HBX_BNKCPY - JP HBX_BNKCALL ; FIXED ADR ENTRY FOR HBX_BNKCALL - .DW HBX_IDENT ; ADDRESS OF HBIOS PROXY START (DEPRECATED) - .DW HBX_IDENT ; ADDRESS OF HBIOS IDENT INFO DATA BLOCK -; - .FILL $MEMTOP - $ ; FILL TO END OF MEMORY (AS NEEDED) - .ORG HBX_IMG + HBX_SIZ ; RESET ORG -; -;================================================================================================== -; HBIOS CORE -;================================================================================================== -; -;================================================================================================== -; ENTRY VECTORS (JUMP TABLE) AND INTERNAL PROCESSING STACK -;================================================================================================== -; -HB_ENTRYTBL .EQU $ -; - JP HB_START ; HBIOS INITIALIZATION - JP HB_DISPATCH ; VECTOR TO DISPATCHER -; -HB_STKSIZ .EQU HB_ENTRYTBL + 256 - $ -; - .FILL HB_STKSIZ,$FF ; USE REMAINDER OF PAGE FOR HBIOS STACK -HB_STACK .EQU $ ; TOP OF HBIOS STACK - -; -;================================================================================================== -; SYSTEM INITIALIZATION -;================================================================================================== -; -HB_START: - DI ; NO INTERRUPTS - IM 1 ; INTERRUPT MODE 1 -; -#IFDEF DIAGP - LD A,%00000001 - OUT (DIAGP),A -#ENDIF -; - LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY -; -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - ; SET BASE FOR CPU IO REGISTERS - LD A,Z180_BASE - OUT0 (Z180_ICR),A - - DIAG(%00000010) - - ; DISABLE REFRESH - XOR A - OUT0 (Z180_RCR),A - - ; MASK OFF TIMER INTERRUPTS - XOR A - OUT0 (Z180_TCR),A - - ; SET DEFAULT CPU CLOCK MULTIPLIERS (XTAL / 2) - XOR A - OUT0 (Z180_CCR),A - OUT0 (Z180_CMR),A - - ; SET DEFAULT WAIT STATES - LD A,$F0 - OUT0 (Z180_DCNTL),A - -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) - ; MMU SETUP - LD A,$80 - OUT0 (Z180_CBAR),A ; SETUP FOR 32K/32K BANK CONFIG -;#IFDEF ROMBOOT -; XOR A -; OUT0 (Z180_BBR),A ; BANK BASE = 0 -;#ENDIF - LD A,(RAMSIZE + RAMBIAS - 64) >> 2 - OUT0 (Z180_CBR),A ; COMMON BASE = LAST (TOP) BANK -#ENDIF - -#IF (Z180_CLKDIV >= 1) - ; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED - LD A,$80 - OUT0 (Z180_CCR),A -#ENDIF - -#IF (Z180_CLKDIV >= 2) - ; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED - LD A,$80 - OUT0 (Z180_CMR),A -#ENDIF - -#ENDIF -; -#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80)) - ; SET PAGING REGISTERS -#IFDEF ROMBOOT - XOR A - OUT (MPGSEL_0),A - INC A - OUT (MPGSEL_1),A -#ENDIF - LD A,62 - OUT (MPGSEL_2),A - INC A - OUT (MPGSEL_3),A - ; ENABLE PAGING - LD A,1 - OUT (MPGENA),A -#ENDIF -; - DIAG(%00000011) -; -; INSTALL PROXY IN UPPER MEMORY -; - -;X1 .EQU $8000 -;X2 .EQU X1 + 2 -;X3 .EQU X2 + 2 -;X4 .EQU X3 + 2 - -; LD HL,(HBX_IMG) -; LD (X1),HL - -; LD HL,(HBX_IMG) -; LD (X2),HL - - LD HL,HBX_IMG - LD DE,HBX_LOC - LD BC,HBX_SIZ - LDIR - -; LD HL,(HBX_IMG) -; LD (X3),HL - -; LD HL,(HBX_LOC) -; LD (X4),HL - -; -; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION -; - LD A,(HB_RAMFLAG) - OR A - JR NZ,HB_START1 -; -; INSTALL HBIOS IN RAM BANK -; - LD A,(HB_CURBNK) - LD (HB_SRCBNK),A - LD A,BID_BIOS - LD (HB_DSTBNK),A - LD HL,0 - LD DE,0 - LD BC,$8000 - CALL HBX_BNKCPY -; -; TRANSITION TO HBIOS IN RAM BANK -; - LD A,BID_BIOS ; BIOS BANK ID - LD HL,HB_START1 ; EXECUTION RESUMES HERE - CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN - HALT ; WE SHOULD NOT COME BACK HERE! -; -HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION -; -; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK -; -HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK -; - DIAG(%00000111) -; - LD SP,HBX_LOC ; RESET STACK SINCE WE DO NOT RETURN - LD A,TRUE ; ACCUM := TRUE - LD (HB_RAMFLAG),A ; SET RAMFLAG -; -; IF APPBOOT, WE NEED TO FIX UP A FEW THINGS IN PAGE ZERO -; -#IFDEF APPBOOT - ; MAKE SURE RST 08 VECTOR IS RIGHT - LD A,$C3 - LD ($0008),A - LD HL,HB_INVOKE - LD ($0009),HL -; - ; MAKE SURE IM1 INT VECTOR IS RIGHT - #IF (INTMODE == 1) - ; JP INT_IM1 IF INTERRUPT MODE ACTIVE - LD A,$C3 - LD ($0038),A - LD HL,INT_IM1 - LD ($0039),HL - #ELSE - ; RETI ($ED, $4D) IF NON-INTERRUPT MODE - LD HL,($0038) - LD (HL),$ED - INC HL - LD (HL),$4D - #ENDIF -#ENDIF -; - DIAG(%00001111) -; -#IF (DSKYENABLE) - LD HL,MSG_HBVER - CALL DSKY_SHOWSEG -#ENDIF -; -; PERFORM DYNAMIC CPU SPEED DERIVATION -; - CALL HB_CPUSPD ; CPU SPEED DETECTION -; -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) -; - ; SET DESIRED WAIT STATES - LD A,0 + (Z180_MEMWAIT << 6) | (Z180_IOWAIT << 4) - OUT0 (Z180_DCNTL),A -; -#ENDIF -; - CALL DELAY_INIT ; INITIALIZE SPEED COMPENSATED DELAY FUNCTIONS -; - DIAG(%00011111) -; -; INITIALIZE HEAP STORAGE -; - ; INITIALIZE POINTERS - LD HL,HB_END ; HEAP FOLLOWS HBIOS CODE - LD (CB_HEAP),HL ; INIT HEAP BASE ADDRESS - LD (CB_HEAPTOP),HL ; INIT HEAP TOP ADDRESS - ; CLEAR HEAP - LD BC,BNKTOP - HB_END ; MAX SIZE OF HEAP - LD A,$FF ; FILL WITH $FF - CALL FILL ; DO IT -; - DIAG(%00111111) -; -; PRE-CONSOLE INITIALIZATION -; -#IF (ASCIENABLE) - CALL ASCI_PREINIT -#ENDIF -#IF (UARTENABLE) - CALL UART_PREINIT -#ENDIF -#IF (SIOENABLE) - CALL SIO_PREINIT -#ENDIF -#IF (ACIAENABLE) - CALL ACIA_PREINIT -#ENDIF -#IF (PIO_4P | PIO_ZP) - CALL PIO_PREINIT -#ENDIF -; - DIAG(%01111111) -; -; PRIOR TO THIS POINT, CONSOLE I/O WAS DIRECTED TO HARDWARE (XIO.ASM). -; NOW THAT HBIOS IS READY, SET THE CONSOLE UNIT TO ACTIVATE CONSOLE I/O -; VIA HBIOS. -; - XOR A ; INITIALLY, FIRST SERIAL UNIT IS CONSOLE - LD (CB_CONDEV),A ; SAVE IT, ACTIVATES CONSOLE ON HBIOS -; -; ANNOUNCE HBIOS -; - CALL NEWLINE2 - PRTX(STR_BANNER) -; - DIAG(%11111111) -; -; IO PORT SCAN -; -#IF 0 -PSCN: - LD C,0 ; IO PORT NUMBER - LD B,0 ; LOOP COUNTER - CALL NEWLINE -PSCN1: - CALL NEWLINE - LD A,C - CALL PRTHEXBYTE - CALL PC_COLON - CALL PC_SPACE - CALL DELAY - LD A,C - LD (PSCNX),A -PSCNX .EQU $ + 1 - IN A,(0) - CALL PRTHEXBYTE - CALL PC_COMMA - PUSH BC - LD B,0 - IN A,(C) - POP BC - CALL PRTHEXBYTE - INC C - DJNZ PSCN1 -#ENDIF -; -; SETUP INTERRUPT VECTORS, AS APPROPRIATE -; -;#IF (INTMODE == 1) -; ; OVERLAY $0038 WITH JP INT_IM1 -; LD A,$C3 ; JP INSTRUCTION -; LD ($0038),A ; INSTALL IT -; LD HL,INT_IM1 ; DESTINATION ADDRESS -; LD ($0039),HL ; INSTALL IT -;#ENDIF -; -#IF (INTMODE == 2) - ; SETUP Z80 IVT AND INT MODE 2 - LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS - LD I,A ; ... AND PLACE IT IN I REGISTER - - #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - ; SETUP Z180 IVT - XOR A ; SETUP LO BYTE OF IVT ADDRESS - OUT0 (Z180_IL),A ; ... AND PLACE IN Z180 IL REGISTER - #ENDIF - - IM 2 ; SWITCH TO INT MODE 2 -#ENDIF - -#IF (PLATFORM == PLT_SBC) -; - #IF (HTIMENABLE) ; SIMH TIMER -; - #IF (INTMODE == 1) - LD HL,HB_TIMINT - CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST - #ENDIF -; - #IF (INTMODE == 2) - ;LD HL,INT_TIMER - ;LD (HBX_IVT),HL - #ENDIF -; - #ENDIF -; -#ENDIF -; -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) -; - #IF (INTMODE == 2) -; - ; MASK ALL EXTERNAL INTERRUPTS FOR NOW - ;XOR A ; INT0-2 DISABLED - LD A,$01 ; INT0 ENABLED, INT1-2 DISABLED - OUT0 (Z180_ITC),A ; WRITE TO INT/TRAP CONTROL REGISTER -; - ; SETUP Z180 TIMER0 INTERRUPT VECTOR IN IVT - LD HL,INT_TIMER - LD (HBX_IVT + IVT_TIM0),HL - - ; SETUP PERIODIC TIMER INTERRUPT ON TIMER 0 - LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ - LD B,0 - LD C,Z180_RLDR0L ; INITIALIZE TIMER 0 RELOAD REGISTER - OUT (C),L - INC C - OUT (C),H - LD C,Z180_TMDR0L ; INITIALIZE TIMER 0 DATA REGISTER - OUT (C),L - INC C - OUT (C),H - LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING - OUT0 (Z180_TCR),A -; - #ENDIF -; -#ENDIF -; - HB_EI ; INTERRUPTS SHOULD BE OK NOW -; -; DISPLAY PLATFORM INFORMATION -; - CALL NEWLINE2 - PRTX(STR_PLATFORM) - PRTS(" @ $") - LD HL,(CB_CPUKHZ) - CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA - PRTS("MHz$") -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - CALL PC_COMMA - PRTS(" IO=0x$") - LD A,Z180_BASE - CALL PRTHEXBYTE -#ENDIF -; -; DISPLAY CPU CONFIG -; - ;CALL PRTSTRD - ;.TEXT ", $" - CALL NEWLINE -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - LD A,Z180_MEMWAIT -#ELSE - LD A,0 -#ENDIF - CALL PRTDECB - CALL PRTSTRD - .TEXT " MEM W/S, $" -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - LD A,Z180_IOWAIT + 1 -#ELSE - LD A,1 -#ENDIF - CALL PRTDECB - CALL PRTSTRD - .TEXT " I/O W/S$" -#IF (INTMODE > 0) - CALL PRTSTRD - .TEXT ", INT MODE $" - LD A,INTMODE - CALL PRTDECB -#ENDIF -; -; DISPLAY MEMORY CONFIG -; - CALL NEWLINE - ;CALL PRTSTRD - ;.TEXT "MEMORY CONFIG: $" - LD HL,ROMSIZE - CALL PRTDEC - CALL PRTSTRD - .TEXT "KB ROM, $" - LD HL,RAMSIZE - CALL PRTDEC - CALL PRTSTRD - .TEXT "KB RAM$" -; -; PERFORM DEVICE INITIALIZATION -; - CALL NEWLINE - LD B,HB_INITTBLLEN - LD DE,HB_INITTBL -INITSYS1: - LD A,(DE) - LD L,A - INC DE - LD A,(DE) - LD H,A - INC DE - PUSH DE - PUSH BC - CALL JPHL - POP BC - POP DE - DJNZ INITSYS1 -; -; RECORD HEAP CURB AT THE CURRENT VALUE OF HEAP TOP. HEAP CURB -; MARKS THE POINT IN THE HEAP AFTER WHICH MEMORY IS RELEASED -; WHEN AN HBIOS RESET IS PEFORMED. -; - LD HL,(CB_HEAPTOP) - LD (HEAPCURB),HL -; -; NOW SWITCH TO CRT CONSOLE IF CONFIGURED -; -#IF CRTACT -; -; BIOS IS CONFIGURED TO AUTO ACTIVATE CRT DEVICE. FIRST, -; CHECK TO SEE IF WE HAVE A VALID CRT DEVICE TO USE. -; - LD A,(CB_CRTDEV) ; GET THE CRT DEVICE - INC A ; INCREMENT TO TEST FOR $FF - JR Z,INITSYS3 ; IF NO CRT DEVICE, BYPASS CONSOLE SWITCH -; -; IF PLATFORM HAS A CONFIG JUMPER, CHECK TO SEE IF IT IS JUMPERED. -; IF SO, BYPASS SWITCH TO CRT CONSOLE (FAILSAFE MODE) -; -#IF ((PLATFORM != PLT_N8) & (PLATFORM != PLT_MK4) & (PLATFORM != PLT_RC) & (PLATFORM != PLT_RC180) & (PLATFORM != PLT_EZZ80)) - IN A,(RTC) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER - BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE - JR Z,INITSYS3 ; Z=SHORTED, BYPASS CONSOLE SWITCH -#ENDIF -; - ; NOTIFY USER OF CONSOLE SWITCH ON BOOT CONSOLE - CALL NEWLINE2 - PRTX(STR_SWITCH) - CALL NEWLINE -; - ; SWITCH TO CRT CONSOLE - LD A,(CB_CRTDEV) ; GET CRT DISPLAY DEVICE - LD (CB_CONDEV),A ; SAVE IT AS ACTIVE CONSOLE DEVICE -; - ; DISPLAY HBIOS BANNER ON NEW CONSOLE - PRTX(STR_BANNER) -#ENDIF -; -INITSYS3: -; - CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE -; -; CHAIN TO OS LOADER -; -#IFDEF ROMBOOT - ; PERFORM BANK CALL TO OS IMAGES BANK IN ROM - LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK - LD HL,0 ; ENTER AT ADDRESS 0 - CALL HBX_BNKCALL ; GO THERE - HALT ; WE SHOULD NEVER COME BACK! -#ELSE - ; COPY OS IMAGE: BID_USR: --> BID_USR:0 - ;LD A,BID_USR - ;LD (HB_SRCBNK),A - ;LD (HB_DSTBNK),A - ;LD HL,HB_END - ;LD DE,0 - ;LD BC,$8000 - ;CALL HBX_BNKCPY - LD B,BF_SYSSETCPY ; HBIOS FUNC: SETUP BANK COPY - LD D,BID_USR ; D = DEST BANK = USER BANK - LD E,BID_USR ; E = SRC BANK = USER BANK - LD HL,$8000 ; HL = COPY LEN = ENTIRE BANK - RST 08 ; DO IT - LD B,BF_SYSBNKCPY ; HBIOS FUNC: PERFORM BANK COPY - LD HL,HB_END ; COPY FROM END OF OF HBIOS - LD DE,0 ; TO USER ADDRESS 0 - RST 08 ; DO IT -; - ; PERFORM BANK CALL TO USER BANK - LD A,BID_USR ; CHAIN TO OS IMAGES BANK - LD HL,0 ; ENTER AT ADDRESS 0 - CALL HBX_BNKCALL ; GO THERE - HALT ; WE SHOULD NEVER COME BACK! -; -#ENDIF -; - RET -; -;================================================================================================== -; TABLE OF INITIALIZATION ENTRY POINTS -;================================================================================================== -; -HB_INITTBL: -#IF (SPKENABLE) - .DW SPK_INIT ; AUDIBLE INDICATOR OF BOOT START -#ENDIF -#IF (AYENABLE) - .DW AY_INIT ; AUDIBLE INDICATOR OF BOOT START -#ENDIF -#IF (ASCIENABLE) - .DW ASCI_INIT -#ENDIF -#IF (UARTENABLE) - .DW UART_INIT -#ENDIF -#IF (SIOENABLE) - .DW SIO_INIT -#ENDIF -#IF (ACIAENABLE) - .DW ACIA_INIT -#ENDIF -#IF (SIMRTCENABLE) - .DW SIMRTC_INIT -#ENDIF -#IF (DSRTCENABLE) - .DW DSRTC_INIT -#ENDIF -#IF (VDUENABLE) - .DW VDU_INIT -#ENDIF -#IF (CVDUENABLE) - .DW CVDU_INIT -#ENDIF -#IF (VGAENABLE) - .DW VGA_INIT -#ENDIF -#IF (NECENABLE) - .DW NEC_INIT -#ENDIF -#IF (TMSENABLE) - .DW TMS_INIT -#ENDIF -#IF (DSKYENABLE) - .DW DSKY_INIT -#ENDIF -#IF (MDENABLE) - .DW MD_INIT -#ENDIF -#IF (FDENABLE) - .DW FD_INIT -#ENDIF -#IF (RFENABLE) - .DW RF_INIT -#ENDIF -#IF (IDEENABLE) - .DW IDE_INIT -#ENDIF -#IF (PPIDEENABLE) - .DW PPIDE_INIT -#ENDIF -#IF (SDENABLE) - .DW SD_INIT -#ENDIF -#IF (HDSKENABLE) - .DW HDSK_INIT -#ENDIF -#IF (PRPENABLE) - .DW PRP_INIT -#ENDIF -#IF (PPPENABLE) - .DW PPP_INIT -#ENDIF -#IF (PIO_4P | PIO_ZP) - .DW PIO_INIT -#ENDIF -; -HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2) -; -;================================================================================================== -; IDLE -;================================================================================================== -; -;__________________________________________________________________________________________________ -; -IDLE: - PUSH AF - PUSH BC - PUSH DE - PUSH HL - PUSH IY -#IF (FDENABLE) - CALL FD_IDLE -#ENDIF - POP IY - POP HL - POP DE - POP BC - POP AF - RET -; -;================================================================================================== -; BIOS FUNCTION DISPATCHER -;================================================================================================== -; -; MAIN BIOS FUNCTION -; B: FUNCTION -;__________________________________________________________________________________________________ -; -HB_DISPATCH: -; -#IF 0 ; *DEBUG* START -; - CALL HB_DISPCALL ; DO THE WORK -; - ; CHECK STACK INTEGRITY - PUSH AF - LD A,(HB_STACK - HB_STKSIZ + $08) - CP $FF - CALL NZ,PANIC - LD A,$FF - LD (HB_STACK - HB_STKSIZ + $08),A - POP AF - RET -HB_DISPCALL: -; -#ENDIF ; *DEBUG* END -; - LD A,B ; REQUESTED FUNCTION IS IN B - CP BF_CIO + $10 ; $00-$0F: CHARACTER I/O - JP C,CIO_DISPATCH - CP BF_DIO + $10 ; $10-$1F: DISK I/O - JP C,DIO_DISPATCH - CP BF_RTC + $10 ; $20-$2F: REAL TIME CLOCK (RTC) - JP C,RTC_DISPATCH - CP BF_EMU + $10 ; $30-$3F: EMULATION - CALL C,PANIC ; OBSOLETE! - CP BF_VDA + $10 ; $40-$4F: VIDEO DISPLAY ADAPTER - JP C,VDA_DISPATCH - CP BF_SYS ; SKIP TO BF_SYS VALUE AT $F0 - CALL C,PANIC ; PANIC IF LESS THAN BF_SYS - JP SYS_DISPATCH ; OTHERWISE SYS CALL - CALL PANIC ; THIS SHOULD NEVER BE REACHED - RET -; -;================================================================================================== -; CHARACTER I/O DEVICE FUNCTION DISPATCHER -;================================================================================================== -; -; ROUTE CALL TO SPECIFIED CHARACTER I/O DRIVER -; B: FUNCTION -; C: UNIT NUMBER -; -CIO_DISPATCH: - BIT 7,C ; CHECK FOR SPECIAL UNIT CODE - CALL NZ,CIO_SPECIAL ; IF SO, HANDLE IT - - PUSH IY ; SAVE INCOMING IY - - LD IY,CIO_TBL ; POINT IY TO START OF DIO TABLE - CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE - - POP IY ; RESTORE IY - RET ; AND DONE -; -; SPECIAL HANDLING FOR DEDICATED UNIT CODES -; -CIO_SPECIAL: - ; FOR NOW, ONLY SPECIAL CODE IS A CONSOLE REQUEST - ; SO JUST SWAP IN ACTIVE CONSOLE UNIT - LD A,(CB_CONDEV) ; GET ACTIVE CONSOLE - LD C,A ; OVERLAY UNIT CODE IN C - RET ; AND REJOIN MAIN DISPATCH FLOW -; -; ADD AN ENTRY TO THE CIO UNIT TABLE (SEE HB_ADDENT FOR DETAILS) -; -CIO_ADDENT: - LD HL,CIO_TBL ; POINT TO CIO TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE -; -; HBIOS CHARACTER DEVICE UNIT TABLE -; -; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. -; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT -; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. -; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS -; EACH ENTRY IS DEFINED AS: -; -; WORD DRIVER FUNCTION TABLE ADDRESS -; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) -; -CIO_FNCNT .EQU 7 ; NUMBER OF CIO FUNCS (FOR RANGE CHECK) -CIO_MAX .EQU 32 ; UP TO 32 UNITS -CIO_SIZ .EQU CIO_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB CIO_FNCNT ; CIO FUNCTION COUNT (FOR RANGE CHECK) - .DB CIO_MAX ; MAX ENTRY COUNT TABLE PREFIX -CIO_CNT .DB 0 ; ENTRY COUNT PREFIX -CIO_TBL .FILL CIO_SIZ,0 ; SPACE FOR ENTRIES -; -;================================================================================================== -; DISK I/O DEVICE FUNCTION DISPATCHER -;================================================================================================== -; -; ROUTE CALL TO SPECIFIED DISK I/O DRIVER -; B: FUNCTION -; C: UNIT NUMBER -; -DIO_DISPATCH: -; -#IF 0 ; *DEBUG* START -; - ; DUMP INCOMING CALL - CALL NEWLINE - PRTS("DIO>$") - CALL REGDMP ; DUMP REGS, NONE DESTROYED -; - ; DO THE ACTUAL DISPATCH PROCESSING - CALL DIO_DISPCALL -; - ; DUMP CALL RESULTS AND RETURN - CALL NEWLINE - PRTS("DIO<$") - CALL REGDMP ; DUMP REGS, NONE DESTROYED - RET -; -#ENDIF ; *DEBUG* END -; -DIO_DISPCALL: - PUSH IY ; SAVE INCOMING IY - - LD IY,DIO_TBL ; POINT IY TO START OF DIO TABLE - CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE - - POP IY ; RESTORE IY - RET ; AND DONE -; -; ADD AN ENTRY TO THE DIO UNIT TABLE -; -DIO_ADDENT: - LD HL,DIO_TBL ; POINT TO DIO TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE -; -; HBIOS DISK DEVICE UNIT TABLE -; -; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. -; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT -; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. -; TABLE - 3 CONTAINS THE NUMBER OF DIO FUNCTION IDS -; EACH ENTRY IS DEFINED AS: -; -; WORD DRIVER FUNCTION TABLE ADDRESS -; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) -; -DIO_FNCNT .EQU 12 ; NUMBER OF DIO FUNCS (FOR RANGE CHECK) -DIO_MAX .EQU 16 ; UP TO 16 UNITS -DIO_SIZ .EQU DIO_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB DIO_FNCNT ; DIO FUNCTION COUNT (FOR RANGE CHECK) - .DB DIO_MAX ; MAX ENTRY COUNT TABLE PREFIX -DIO_CNT .DB 0 ; ENTRY COUNT PREFIX -DIO_TBL .FILL DIO_SIZ,0 ; SPACE FOR ENTRIES -; -;================================================================================================== -; REAL TIME CLOCK DEVICE DISPATCHER -;================================================================================================== -; -; ROUTE CALL TO REAL TIME CLOCK DRIVER -; B: FUNCTION -; -RTC_DISPATCH: -#IF (SIMRTCENABLE) - JP SIMRTC_DISPATCH -#ENDIF -#IF (DSRTCENABLE) - JP DSRTC_DISPATCH -#ENDIF - CALL PANIC -; -;================================================================================================== -; VIDEO DISPLAY ADAPTER DEVICE DISPATCHER -;================================================================================================== -; -; ROUTE CALL TO SPECIFIED VDA DEVICE DRIVER -; B: FUNCTION -; C: UNIT NUMBER -; -VDA_DISPATCH: - PUSH IY ; SAVE INCOMING IY - - LD IY,VDA_TBL ; POINT IY TO START OF DIO TABLE - CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE - - POP IY ; RESTORE IY - RET ; AND DONE -; -; ADD AN ENTRY TO THE VDA UNIT TABLE (SEE HB_ADDENT FOR DETAILS) -; -VDA_ADDENT: - LD HL,VDA_TBL ; POINT TO VDA TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE -; -; HBIOS VIDEO DEVICE UNIT TABLE -; -; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. -; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT -; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. -; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS -; EACH ENTRY IS DEFINED AS: -; -; WORD DRIVER FUNCTION TABLE ADDRESS -; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) -; -VDA_FNCNT .EQU 15 ; NUMBER OF VDA FUNCS (FOR RANGE CHECK) -VDA_MAX .EQU 16 ; UP TO 16 UNITS -VDA_SIZ .EQU VDA_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB VDA_FNCNT ; VDA FUNCTION COUNT (FOR RANGE CHECK) - .DB VDA_MAX ; MAX ENTRY COUNT TABLE PREFIX -VDA_CNT .DB 0 ; ENTRY COUNT PREFIX -VDA_TBL .FILL VDA_SIZ,0 ; SPACE FOR ENTRIES -; -;================================================================================================== -; SYSTEM FUNCTION DISPATCHER -;================================================================================================== -; -; B: FUNCTION -; -SYS_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JP Z,SYS_RESET ; $F0 - DEC A - JP Z,SYS_VER ; $F1 - DEC A - JP Z,SYS_SETBNK ; $F2 - DEC A - JP Z,SYS_GETBNK ; $F3 - DEC A - JP Z,SYS_SETCPY ; $F4 - DEC A - JP Z,SYS_BNKCPY ; $F5 - DEC A - JP Z,SYS_ALLOC ; $F6 - DEC A - JP Z,SYS_FREE ; $F7 - DEC A - JP Z,SYS_GET ; $F8 - DEC A - JP Z,SYS_SET ; $F9 - DEC A - JP Z,SYS_PEEK ; $FA - DEC A - JP Z,SYS_POKE ; $FB - DEC A - JP Z,SYS_INT ; $FC - CALL PANIC ; INVALID -; -; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS -; -SYS_RESET: - LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD - LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP - XOR A - RET -; -; GET THE CURRENT HBIOS VERSION -; ON INPUT, C=0 -; RETURNS VERSION IN DE AS BCD -; D: MAJOR VERION IN TOP 4 BITS, MINOR VERSION IN LOW 4 BITS -; E: UPDATE VERION IN TOP 4 BITS, PATCH VERSION IN LOW 4 BITS -; L: PLATFORM ID -; -SYS_VER: - LD DE,0 | (RMJ << 12) | (RMN << 8) | (RUP << 4) | RTP - LD L,PLATFORM - XOR A - RET -; -; SET ACTIVE MEMORY BANK AND RETURN PREVIOUSLY ACTIVE MEMORY BANK -; NOTE THAT IT GOES INTO EFFECT AS HBIOS FUNCTION IS EXITED -; HERE, WE JUST SET THE CURRENT BANK -; CALLER MUST EXTABLISH UPPER MEMORY STACK BEFORE INVOKING THIS FUNCTION! -; -SYS_SETBNK: - PUSH HL ; SAVE INCOMING HL - LD HL,HB_INVBNK ; POINT TO HBIOS INVOKE BANK ID ADDRESS - LD A,(HL) ; GET EXISTING BANK ID TO A - LD (HL),C ; UPDATE INVOKE BANK TO NEW BANK ID - LD C,A ; PUT PREVIOUS BANK ID IN C FOR RETURN - POP HL ; RESTORE ORIGINAL HL - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -; GET ACTIVE MEMORY BANK -; -SYS_GETBNK: - LD A,(HB_INVBNK) ; GET THE ACTIVE MEMORY BANK - LD C,A ; MOVE TO C - XOR A ; SIGNAL SUCCESS - RET -; -; SET BANKS AND LENGTH FOR INTERBANK MEMORY COPY (BNKCPY) -; ENTRY: E=SOURCE BANK ID -; D=DEST BANK ID -; HL=COPY LENGTH (IN BYTES) -; -SYS_SETCPY: - LD A,E - LD (HB_SRCBNK),A ; RECORD THE SOURCE BANK - LD A,D - LD (HB_DSTBNK),A ; RECORD THE DESTINATION BANK - LD (HB_CPYLEN),HL ; RECORD THE COPY LENGTH - XOR A - RET -; -; PERFORM MEMORY COPY POTENTIALLY ACROSS BANKS -; ENTRY: HL=SOURCE ADDRESS -; DE=DESTINATION ADDRESS -; NOTE: SRC/DEST BANK & COPY LENGTH MUST BE SET VIA SETCPY -; -SYS_BNKCPY: - PUSH HL ; SAVE INCOMING HL - LD HL,(HB_CPYLEN) ; HL := COPY LEN (SAVED IN SETCPY) - EX (SP),HL ; RESTORE HL & SET (SP) TO COPY LEN - POP BC ; BC := COPY LEN -#IF (INTMODE == 1) - DI -#ENDIF - CALL HB_BNKCPY -#IF (INTMODE == 1) - EI -#ENDIF - XOR A - RET -; -; ALLOCATE HL BYTES OF MEMORY FROM HBIOS HEAP -; RETURNS POINTER TO ALLOCATED MEMORY IN HL -; ON SUCCESS RETURN A == 0, AND Z SET -; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED -; ALL OTHER REGISTERS PRESERVED -; -SYS_ALLOC: - JP HB_ALLOC -; -; FREE HEAP MEMORY BY SIMPLY RELEASING ALL -; MEMORY BEYOND POINTER IN HL. -; ON SUCCESS RETURN A == 0, AND Z SET -; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED -; ALL OTHER REGISTERS PRESERVED -; -SYS_FREE: - CALL PANIC ; NOT YET IMPLEMENTED - OR $FF - RET -; -; GET SYSTEM INFORMATION -; ITEM TO RETURN INDICATED IN C -; -SYS_GET: - LD A,C ; GET REQUESTED SUB-FUNCTION - CP BF_SYSGET_CIOCNT - JR Z,SYS_GETCIOCNT - CP BF_SYSGET_DIOCNT - JR Z,SYS_GETDIOCNT - CP BF_SYSGET_VDACNT - JR Z,SYS_GETVDACNT - CP BF_SYSGET_TIMER - JR Z,SYS_GETTIMER - CP BF_SYSGET_BOOTINFO - JR Z,SYS_GETBOOTINFO - CP BF_SYSGET_CPUINFO - JR Z,SYS_GETCPUINFO - CP BF_SYSGET_MEMINFO - JR Z,SYS_GETMEMINFO - CP BF_SYSGET_BNKINFO - JR Z,SYS_GETBNKINFO - OR $FF ; SIGNAL ERROR - RET -; -; GET TIMER -; RETURNS: -; DE:HL: TIMER VALUE (32 BIT) -; -SYS_GETTIMER: - LD HL,HB_TICKS - HB_DI - CALL LD32 - HB_EI - XOR A - RET -; -; GET BOOT INFORMATION -; RETURNS: -; L: BOOT BANK ID -; DE: BOOT DISK VOLUME (UNIT/SLICE) -; -SYS_GETBOOTINFO: - LD A,(CB_BOOTBID) - LD L,A - LD DE,(CB_BOOTVOL) - XOR A - RET -; -; GET CPU INFORMATION -; RETURNS: -; H: Z80 CPU VARIANT -; L: CPU SPEED IN MHZ -; DE: CPU SPEED IN KHZ -; -SYS_GETCPUINFO: - LD H,0 ; NOT YET DEFINED - LD A,(CB_CPUMHZ) - LD L,A - LD DE,(CB_CPUKHZ) - XOR A - RET -; -; GET MEMORY INFORMATION -; RETURNS: -; D: COUNT OF ROM BANKS -; E: COUNT OF RAM BANKS -; -SYS_GETMEMINFO: - LD D,ROMSIZE / 32 - LD E,RAMSIZE / 32 - XOR A - RET -; -; GET BANK CONFIGURATION INFORMATION -; RETURNS: -; D: HBIOS BANK ID -; E: USER BANK ID -; -SYS_GETBNKINFO: - LD A,(CB_BIDBIOS) - LD D,A - LD A,(CB_BIDUSR) - LD E,A - XOR A - RET -; -; GET SERIAL UNIT COUNT -; -SYS_GETCIOCNT: - LD A,(CIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) - LD E,A ; PUT IT IN E - XOR A ; SIGNALS SUCCESS - RET -; -; GET DISK UNIT COUNT -; -SYS_GETDIOCNT: - LD A,(DIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) - LD E,A ; PUT IT IN E - XOR A ; SIGNALS SUCCESS - RET -; -; GET VIDEO UNIT COUNT -; -SYS_GETVDACNT: - LD A,(VDA_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST) - LD E,A ; PUT IT IN E - XOR A ; SIGNALS SUCCESS - RET -; -; SET SYSTEM PARAMETERS -; PARAMETER(S) TO SET INDICATED IN C -; -SYS_SET: - LD A,C ; GET REQUESTED SUB-FUNCTION - CP BF_SYSSET_TIMER - JR Z,SYS_SETTIMER - CP BF_SYSSET_BOOTINFO - JR Z,SYS_SETBOOTINFO - OR $FF ; SIGNAL ERROR - RET -; -; SET BOOT INFORMATION -; ON ENTRY: -; L: BOOT BANK ID -; DE: BOOT DISK VOLUME (UNIT/SLICE) -; -SYS_SETBOOTINFO: - LD A,L - LD (CB_BOOTBID),A - LD (CB_BOOTVOL),DE - XOR A - RET -; -; SET TIMER -; ON ENTRY: -; DE:HL: TIMER VALUE (32 BIT) -; -SYS_SETTIMER: - LD BC,HB_TICKS - HB_DI - CALL ST32 - HB_EI - XOR A - RET -; -; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK -; ENTRY: D=BANK ID, HL=ADDRESS -; RETURN: E=BYTE VALUE -; -SYS_PEEK: -#IF (INTMODE == 1) - DI -#ENDIF - CALL HBX_PEEK ; IMPLEMENTED IN PROXY -#IF (INTMODE == 1) - EI -#ENDIF - XOR A - RET -; -; WRITE A BYTE OF MEMORY TO SPECIFIED BANK -; ENTRY: D=BANK ID, HL=ADDRESS IN HBIOS BANK, E=BYTE VALUE -; -SYS_POKE: -#IF (INTMODE == 1) - DI -#ENDIF - CALL HBX_POKE ; IMPLEMENTED IN PROXY -#IF (INTMODE == 1) - EI -#ENDIF - XOR A - RET -; -; INTERRUPT MANAGEMENT FUNCTIONS -; SUBFUNCTION IN C -; -SYS_INT: - LD A,C ; GET REQUESTED SUB-FUNCTION - CP BF_SYSINT_INFO - JR Z,SYS_INTINFO - CP BF_SYSINT_GET - JR Z,SYS_INTGET - CP BF_SYSINT_SET - JR Z,SYS_INTSET - OR $FF ; SIGNAL ERROR - RET -; -; GET INTERRUPT SYSTEM INFORMATION -; RETURN D:=INTERRUPT MODE, E:=INT VEC TABLE SIZE -; -SYS_INTINFO: - LD D,INTMODE ; D := ACTIVE INTERRUPT MODE -#IF (INTMODE == 0) - LD E,0 ; 0 ENTRIES IF INTERRUPTS DISABLED -#ENDIF -#IF (INTMODE == 1) - LD A,(HB_IM1CNT) ; RETURN IM1 CALL LIST SIZE - LD E,A -#ENDIF -#IF (INTMODE == 2) - LD E,HBX_IVTCNT ; RETURN INT VEC TABLE SIZE -#ENDIF - XOR A ; INDICATE SUCCESS - RET ; AND DONE -; -; ROUTINE SHARED BY INT GET/SET. RETURNS ADDRESS OF VECTOR FOR SPECIFIED LIST / TABLE -; POSITION. ZF SET ON RETURN FOR SUCCESS, ELSE ERROR. -; -SYS_INTVECADR: -#IF (INTMODE == 0) - CALL PANIC ; INVALID FOR INT MODE 0 - OR $FF - RET -#ENDIF -#IF (INTMODE == 1) - LD A,(HB_IM1CNT) ; GET CURRENT ENTRY COUNT - INC A ; ALLOW FOR EXTRA ENTRY TO APPEND AT END - LD C,A ; SAVE IN C FOR COMPARE -#ENDIF -#IF (INTMODE == 2) - LD C,HBX_IVTCNT ; GET CURRENT ENTRY COUNT -#ENDIF - LD A,E ; INCOMING INDEX POSITION TO A - CP C ; COMPARE TO VECTOR COUNT - JR C,SYS_INTGET1 ; CONTINUE IF POSITION IN RANGE - CALL PANIC ; ELSE ERROR - OR $FF - RET -SYS_INTGET1: - OR A - RLA ; HL := (A * 2) FOR IM2 -#IF (INTMODE == 1) - RLA ; ... HL := (A * 4) + 1 FOR IM1 - INC A -#ENDIF - LD H,0 - LD L,A -#IF (INTMODE == 1) - LD DE,HB_IM1INT ; DE := START OF CALL LIST -#ENDIF -#IF (INTMODE == 2) - LD DE,HBX_IVT ; DE := START OF VECTOR TABLE -#ENDIF - ADD HL,DE ; HL := ADR OF VECTOR - XOR A ; INDICATE SUCCESS - RET -; -; RETURN THE INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE -; ENTRY: E=LIST/TABLE POSITION -; RETURN: HL=INTERRUPT VECTOR -; -SYS_INTGET: - CALL SYS_INTVECADR ; GET VECTOR ADDRESS - RET NZ ; BAIL OUT ON ERROR - LD A,(HL) ; DEREF HL TO GET VECTOR - INC HL - LD H,(HL) - LD L,A - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -; SET AN INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE -; ENTRY: E=LIST/TABLE POSITION, HL=NEW INTERRUPT VECTOR -; RETURN: HL=PREVIOUS INTERRUPT VECTOR, DE=ADR OF INT ROUTING ENGINE FOR IM2 -; -SYS_INTSET: - PUSH HL ; SAVE NEW VECTOR - CALL SYS_INTVECADR ; GET VECTOR ADDRESS - JR Z,SYS_INTSET1 ; CONTINUE IF OK - POP HL ; FIX STACK - RET NZ ; BAIL OUT ON ERROR -SYS_INTSET1: - PUSH HL ; SAVE VECTOR ADDRESS - LD A,(HL) ; DEREF HL TO GET PREV VECTOR - INC HL - LD H,(HL) - LD L,A - EX (SP),HL ; (SP) := PREV VEC, HL := VEC ADR - POP DE ; DE := PREV VEC - POP BC ; BC := NEW VEC - LD (HL),C ; SAVE LSB - INC HL - LD (HL),B ; SAVE MSB - EX DE,HL ; HL := PREV VEC -#IF (INTMODE == 2) - LD DE,HBX_INT ; DE := IM2 INT ROUTING ENGINE -#ENDIF - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -;================================================================================================== -; GLOBAL HBIOS FUNCTIONS -;================================================================================================== -; -; COMMON ROUTINE THAT IS CALLED BY CHARACTER IO DRIVERS WHEN -; AN IDLE CONDITION IS DETECTED (WAIT FOR INPUT/OUTPUT) -; -CIO_IDLE: - PUSH AF ; PRESERVE AF - LD A,(IDLECOUNT) ; GET CURRENT IDLE COUNT - DEC A ; DECREMENT - LD (IDLECOUNT),A ; SAVE UPDATED VALUE - CALL Z,IDLE ; IF ZERO, DO IDLE PROCESSING - POP AF ; RECOVER AF - RET -; -#IF (INTMODE == 1) -; -; IM1 INTERRUPTS ARRIVE HERE AFTER BANK SWITCH TO HBIOS BANK -; LIST OF IM1 INT CALLS IS BUILT DYNAMICALLY BELOW -; SEE HB_ADDIM1 ROUTINE -; EACH ENTRY WILL LOOK LIKE: -; CALL XXXX ; CALL INT HANDLER -; RET NZ ; RETURN IF HANDLED -; -; NOTE THAT THE LIST IS INITIALLY FILLED WITH CALLS TO HB_BADINT. -; AS THE TABLE IS POPULATED, THE ADDRESS OF HB_BADINT IS OVERLAID -; WITH THE ADDRESS OF A REAL INTERRUPT HANDLER. -; -; THERE IS ROOM FOR 8 ENTRIES PLUS A FINAL CALL TO HB_BADINT. -; -HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER CALL LIST - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ - CALL HB_BADINT \ RET NZ -; -; ROUTINE BELOW IS USED TO ADD A NEW VECTOR TO THE IM1 -; CALL LIST ABOVE. ENTER WITH HL=VECTOR ADDRESS IN HBIOS -; -HB_ADDIM1: - EX DE,HL ; VECTOR ADDRESS TO DE - LD HL,(HB_IM1PTR) ; GET PTR FOR NEXT ENTRY - INC HL ; BUMP PTR TO ADDRESS FIELD OF CALL OPCODE - LD (HL),E ; ADD VECTOR ADDRESS - INC HL ; ... - LD (HL),D ; ... - INC HL ; BUMP PTR - INC HL ; BUMP PTR - LD (HB_IM1PTR),HL ; SAVE UPDATED POINTER - LD HL,HB_IM1CNT ; POINT TO ENTRY COUNT - INC (HL) ; INCREMENT - RET ; DONE -; -HB_IM1CNT .DB 0 ; NUMBER OF ENTRIES IN CALL LIST -HB_IM1MAX .DB 8 ; MAX ENTRIES IN CALL LIST -HB_IM1PTR .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY -; -#ENDIF -; -; TIMER INTERRUPT -; -HB_TIMINT: - ; INCREMENT TICK COUNTER (32 BIT) - LD HL,HB_TICKS ; POINT TO TICK COUNTER - INC (HL) - JR NZ,HB_TIMINT1 - INC HL - INC (HL) - JR NZ,HB_TIMINT1 - INC HL - INC (HL) - JR NZ,HB_TIMINT1 - INC HL - INC (HL) -; -HB_TIMINT1: -; -#IF 0 -; - LD HL,TEMPCNT - DEC (HL) - JR NZ,HB_TIMINT2 - LD (HL),250 -; - LD A,'*' - CALL COUT - JR HB_TIMINT2 -; -TEMPCNT .DB 250 -; -#ENDIF -; -HB_TIMINT2: -; -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - ; ACK/RESET Z180 TIMER INTERRUPT - IN0 A,(Z180_TCR) - IN0 A,(Z180_TMDR0L) -#ENDIF -; - OR $FF ; NZ SET TO INDICATE INT HANDLED - RET -; -; BAD INTERRUPT HANDLER -; -HB_BADINT: - -#IF 0 ; *DEBUG* - LD HL,HB_BADINTCNT - INC (HL) - LD A,(HL) - OUT (DIAGP),A - OR $FF - RET -HB_BADINTCNT .DB 0 -#ENDIF ; *DEBUG* - - CALL NEWLINE2 - PRTS("+++ BAD INT: $") - CALL _REGDMP - ;CALL CONTINUE - OR $FF ; SIGNAL INTERRUPT HANDLED - RET -; -; COMMON API FUNCTION DISPATCH CODE -; -; ON ENTRY C IS UNIT # (INDEX INTO XXX_TBL OF UNITS) -; AND IY POINTS TO START OF UNIT TABLE. -; USE UNIT # IN C TO LOOKUP XXX_TBL ENTRY. THE XXX_TBL -; ENTRY CONTAINS THE START OF THE DRIVER FUNCTION TABLE AND -; THE DEVICE SPECIFIC INSTANCE DATA (BLOB). SET IY TO BLOB ADDRESS -; AND CALL THE SPECIFIC FUNCTION REQUESTED IN THE DRIVER. -; -HB_DISPCALL: - ; CHECK INCOMING UNIT INDEX IN C FOR VAILIDITY - LD A,C ; A := INCOMING DISK UNIT INDEX - CP (IY-1) ; COMPARE TO COUNT - JR NC,HB_DISPERR ; HANDLE INVALID UNIT INDEX - - ; CHECK FUNCTION INDEX FOR VALIDITY - LD A,B ; A := INCOMING FUNCTION NUMBER - AND $0F ; LOW NIBBLE ONLY FOR FUNC INDEX - CP (IY-3) ; CHECK FN NUM AGAINST MAX - JR NC,HB_DISPERR ; HANDLE FN NUM OUT OF RANGE ERROR - - ; BUMP IY TO ACTUAL XXX_TBL ENTRY FOR INCOMING UNIT INDEX - LD B,0 ; MSB IS ALWAYS ZERO - RLC C ; MULTIPLY UNIT INDEX - RLC C ; ... BY 4 FOR TABLE ENTRY OFFSET - ADD IY,BC ; SET IY TO ENTRY ADDRESS - - ; DERIVE DRIVER FUNC ADR TO CALL - PUSH HL ; SAVE INCOMING HL - LD L,(IY+0) ; COPY DRIVER FUNC TABLE - LD H,(IY+1) ; ... START TO HL - RLCA ; CONV UNIT (STILL IN A) TO FN ADR OFFSET - CALL ADDHLA ; HL NOW HAS DRIVER FUNC TBL START ADR - LD A,(HL) ; DEREFERENCE HL - INC HL ; ... TO GET - LD H,(HL) ; ... ACTUAL - LD L,A ; ... TARGET FUNCTION ADDRESS - EX (SP),HL ; RESTORE HL, FUNC ADR ON STACK - - ; GET UNIT INSTANCE DATA BLOB ADDRESS TO IY - PUSH HL ; SAVE INCOMING HL - LD L,(IY+2) ; HL := DATA BLOB ADDRESS - LD H,(IY+3) ; ... - EX (SP),HL ; RESTORE HL, BLOB ADR ON TOS - POP IY ; IY := BLOB ADR - - RET ; JUMP TO DRIVER FUNC ADR ON TOS -; -HB_DISPERR: - CALL PANIC ; PANIC - OR $FF ; SIGNAL ERROR - RET ; AND RETURN VIA DISPEXIT -; -; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL -; BC: DRIVER FUNCTION TABLE -; DE: ADDRESS OF UNIT INSTANCE DATA -; RETURN -; A: UNIT NUMBER ASSIGNED -; -HB_ADDENT: - DEC HL ; POINT TO ENTRY COUNT - LD A,(HL) ; GET ENTRY COUNT - PUSH AF ; SAVE VALUE TO RETURN AS ENTRY NUM AT END - INC A ; INCREMENT TO ACCOUNT FOR NEW ENTRY - DEC HL ; POINT TO ENTRY MAX - CP (HL) ; COMPARE MAX TO CURRENT COUNT (COUNT - MAX) - CALL NC,PANIC ; OVERFLOW - INC HL ; POINT TO COUNT - LD (HL),A ; SAVE NEW COUNT - INC HL ; POINT TO START OF TABLE - DEC A ; CONVERT A FROM ENTRY COUNT TO ENTRY INDEX - RLCA ; MULTIPLY BY 4 - RLCA ; ... TO GET BYTE OFFSET OF ENTRY - CALL ADDHLA ; MAKE HL POINT TO ACTUAL ENTRY ADDRESS - PUSH BC ; GET TABLE ENTRY ADDRESS TO BC - EX (SP),HL ; ... AND DISPATCH ADDRESS TO HL - POP BC ; ... SO THAT DE:HL HAS 32 BIT ENTRY - CALL ST32 ; LD (BC),DE:HL STORES THE ENTRY - POP AF ; RETURN ENTRY INDEX (UNIT NUMBER ASSIGNED) - RET -; -; ALLOCATE HL BYTES OF MEMORY ON THE HEAP -; RETURNS POINTER TO ALLOCATED SPACE IN HL -; ON SUCCESS RETURN A == 0, AND Z SET -; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED -; ALL OTHER REGISTERS PRESERVED -; -; A 4 BYTE HEADER IS PLACED IN FRONT OF THE ALLOCATED MEMORY -; - DWORD: SIZE OF MEMROY ALLOCATED (DOES NOT INCLUDE 4 BYTE HEADER) -; - DWORD: ADDRESS WHERE ALLOC WAS CALLED (VALUE ON TOP OF STACK AT CALL) -; -HB_ALLOC: - ; SAVE ALLOC SIZE AND REFERENCE ADR FOR SUBSEQUENT HEADER CONSTRUCTION - LD (HB_TMPSZ),HL ; SAVE INCOMING SIZE REQUESTED - ; USE EX (SP),HL INSTEAD???? - POP HL ; GET RETURN ADDRESS - LD (HB_TMPREF),HL ; SAVE AS REFERENCE - ; USE EX (SP),HL INSTEAD???? - PUSH HL ; PUT IT BACK ON STACK - LD HL,(HB_TMPSZ) ; RECOVER INCOMING MEM SIZE PARM -; - ; CALC NEW HEAP TOP AND HANDLE OUT-OF-SPACE ERROR - PUSH DE ; SAVE INCOMING DE - LD DE,4 ; SIZE OF HEADER - ADD HL,DE ; ADD IT IN - JR C,HB_ALLOC1 ; ERROR ON OVERFLOW - LD DE,(CB_HEAPTOP) ; CURRENT HEAP TOP - ADD HL,DE ; ADD IT IN, HL := NEW HEAP TOP - JR C,HB_ALLOC1 ; ERROR ON OVERFLOW - BIT 7,H ; TEST PAST END OF BANK (>= 32K) - JR NZ,HB_ALLOC1 ; ERROR IF PAST END -; - ; SAVE NEW HEAP TOP - LD DE,(CB_HEAPTOP) ; GET ORIGINAL HEAP TOP - LD (CB_HEAPTOP),HL ; SAVE NEW HEAP TOP -; - ; SET HEADER VALUES - EX DE,HL ; HEADER ADR TO HL - LD DE,(HB_TMPSZ) ; GET THE ORIG SIZE REQUESTED - LD (HL),E ; SAVE SIZE (LSB) - INC HL ; BUMP HEADER POINTER - LD (HL),D ; SAVE SIZE (MSB) - INC HL ; BUMP HEADER POINTER - LD DE,(HB_TMPREF) ; GET THE REFERENCE ADR - LD (HL),E ; SAVE REF ADR (LSB) - INC HL ; BUMP HEADER POINTER - LD (HL),D ; SAVE REF ADR (MSB) - INC HL ; BUMP HEADER POINTER -; - ; RETURN SUCCESS, HL POINTS TO START OF ALLOCATED MEMORY (PAST HEADER) - POP DE ; RESTORE INCOMING DE - XOR A ; SIGNAL SUCCESS - RET ; AND RETURN -; -HB_ALLOC1: - ; ERROR RETURN - POP DE ; RESTORE INCOMING DE - OR $FF ; SIGNAL ERROR - RET ; AND RETURN -; -HB_TMPSZ .DW 0 -HB_TMPREF .DW 0 -; -;================================================================================================== -; DEVICE DRIVERS -;================================================================================================== -; -#IF (SIMRTCENABLE) -ORG_SIMRTC .EQU $ - #INCLUDE "simrtc.asm" -SIZ_SIMRTC .EQU $ - ORG_SIMRTC - .ECHO "SIMRTC occupies " - .ECHO SIZ_SIMRTC - .ECHO " bytes.\n" -#ENDIF -; -#IF (DSRTCENABLE) -ORG_DSRTC .EQU $ - #INCLUDE "dsrtc.asm" -SIZ_DSRTC .EQU $ - ORG_DSRTC - .ECHO "DSRTC occupies " - .ECHO SIZ_DSRTC - .ECHO " bytes.\n" -#ENDIF -; -#IF (ASCIENABLE) -ORG_ASCI .EQU $ - #INCLUDE "asci.asm" -SIZ_ASCI .EQU $ - ORG_ASCI - .ECHO "ASCI occupies " - .ECHO SIZ_ASCI - .ECHO " bytes.\n" -#ENDIF -; -#IF (UARTENABLE) -ORG_UART .EQU $ - #INCLUDE "uart.asm" -SIZ_UART .EQU $ - ORG_UART - .ECHO "UART occupies " - .ECHO SIZ_UART - .ECHO " bytes.\n" -#ENDIF -; -#IF (SIOENABLE) -ORG_SIO .EQU $ - #INCLUDE "sio.asm" -SIZ_SIO .EQU $ - ORG_SIO - .ECHO "SIO occupies " - .ECHO SIZ_SIO - .ECHO " bytes.\n" -#ENDIF -; -#IF (ACIAENABLE) -ORG_ACIA .EQU $ - #INCLUDE "acia.asm" -SIZ_ACIA .EQU $ - ORG_ACIA - .ECHO "ACIA occupies " - .ECHO SIZ_ACIA - .ECHO " bytes.\n" -#ENDIF -; -#IF (VGAENABLE) -ORG_VGA .EQU $ - #INCLUDE "vga.asm" -SIZ_VGA .EQU $ - ORG_VGA - .ECHO "VGA occupies " - .ECHO SIZ_VGA - .ECHO " bytes.\n" -#ENDIF -; -#IF (CVDUENABLE) -ORG_CVDU .EQU $ - #INCLUDE "cvdu.asm" -SIZ_CVDU .EQU $ - ORG_CVDU - .ECHO "CVDU occupies " - .ECHO SIZ_CVDU - .ECHO " bytes.\n" -#ENDIF -; -#IF (VDUENABLE) -ORG_VDU .EQU $ - #INCLUDE "vdu.asm" -SIZ_VDU .EQU $ - ORG_VDU - .ECHO "VDU occupies " - .ECHO SIZ_VDU - .ECHO " bytes.\n" -#ENDIF -; -#IF (TMSENABLE) -ORG_TMS .EQU $ - #INCLUDE "tms.asm" -SIZ_TMS .EQU $ - ORG_TMS - .ECHO "TMS occupies " - .ECHO SIZ_TMS - .ECHO " bytes.\n" -#ENDIF -; -#IF (NECENABLE) -ORG_NEC .EQU $ - ;#INCLUDE "nec.asm" -SIZ_NEC .EQU $ - ORG_NEC - .ECHO "NEC occupies " - .ECHO SIZ_NEC - .ECHO " bytes.\n" -#ENDIF -; -#IF (CVDUENABLE | VGAENABLE) -ORG_FONTHI .EQU $ - #INCLUDE "font_hi.asm" -SIZ_FONTHI .EQU $ - ORG_FONTHI - .ECHO "FONTHI occupies " - .ECHO SIZ_FONTHI - .ECHO " bytes.\n" -#ENDIF -; -#IF (TMSENABLE) -ORG_FONTTMS .EQU $ - #INCLUDE "font_tms.asm" -SIZ_FONTTMS .EQU $ - ORG_FONTTMS - .ECHO "FONTTMS occupies " - .ECHO SIZ_FONTTMS - .ECHO " bytes.\n" -#ENDIF -; -#IF (CVDUENABLE | VGAENABLE) -ORG_KBD .EQU $ - #INCLUDE "kbd.asm" -SIZ_KBD .EQU $ - ORG_KBD - .ECHO "KBD occupies " - .ECHO SIZ_KBD - .ECHO " bytes.\n" -#ENDIF -; -#IF (VDUENABLE | (TMSENABLE & (PLATFORM == PLT_N8))) -ORG_PPK .EQU $ - #INCLUDE "ppk.asm" -SIZ_PPK .EQU $ - ORG_PPK - .ECHO "PPK occupies " - .ECHO SIZ_PPK - .ECHO " bytes.\n" -#ENDIF -; -#IF (PRPENABLE) -ORG_PRP .EQU $ - #INCLUDE "prp.asm" -SIZ_PRP .EQU $ - ORG_PRP - .ECHO "PRP occupies " - .ECHO SIZ_PRP - .ECHO " bytes.\n" -#ENDIF -; -#IF (PPPENABLE) -ORG_PPP .EQU $ - #INCLUDE "ppp.asm" -SIZ_PPP .EQU $ - ORG_PPP - .ECHO "PPP occupies " - .ECHO SIZ_PPP - .ECHO " bytes.\n" -#ENDIF -; -#IF (MDENABLE) -ORG_MD .EQU $ - #INCLUDE "md.asm" -SIZ_MD .EQU $ - ORG_MD - .ECHO "MD occupies " - .ECHO SIZ_MD - .ECHO " bytes.\n" -#ENDIF - -#IF (FDENABLE) -ORG_FD .EQU $ - #INCLUDE "fd.asm" -SIZ_FD .EQU $ - ORG_FD - .ECHO "FD occupies " - .ECHO SIZ_FD - .ECHO " bytes.\n" -#ENDIF - -#IF (RFENABLE) -ORG_RF .EQU $ - #INCLUDE "rf.asm" -SIZ_RF .EQU $ - ORG_RF - .ECHO "RF occupies " - .ECHO SIZ_RF - .ECHO " bytes.\n" -#ENDIF - -#IF (IDEENABLE) -ORG_IDE .EQU $ - #INCLUDE "ide.asm" -SIZ_IDE .EQU $ - ORG_IDE - .ECHO "IDE occupies " - .ECHO SIZ_IDE - .ECHO " bytes.\n" -#ENDIF - -#IF (PPIDEENABLE) -ORG_PPIDE .EQU $ - #INCLUDE "ppide.asm" -SIZ_PPIDE .EQU $ - ORG_PPIDE - .ECHO "PPIDE occupies " - .ECHO SIZ_PPIDE - .ECHO " bytes.\n" -#ENDIF - -#IF (SDENABLE) -ORG_SD .EQU $ - #INCLUDE "sd.asm" -SIZ_SD .EQU $ - ORG_SD - .ECHO "SD occupies " - .ECHO SIZ_SD - .ECHO " bytes.\n" -#ENDIF - -#IF (HDSKENABLE) -ORG_HDSK .EQU $ - #INCLUDE "hdsk.asm" -SIZ_HDSK .EQU $ - ORG_HDSK - .ECHO "HDSK occupies " - .ECHO SIZ_HDSK - .ECHO " bytes.\n" -#ENDIF - -#IF (TERMENABLE) -ORG_TERM .EQU $ - #INCLUDE "term.asm" -SIZ_TERM .EQU $ - ORG_TERM - .ECHO "TERM occupies " - .ECHO SIZ_TERM - .ECHO " bytes.\n" -#ENDIF -; -#IF (SPKENABLE) -ORG_SPK .EQU $ - #INCLUDE "spk.asm" -SIZ_SPK .EQU $ - ORG_SPK - .ECHO "SPK occupies " - .ECHO SIZ_SPK - .ECHO " bytes.\n" -#ENDIF -; -#IF (AYENABLE) -ORG_AY .EQU $ - #INCLUDE "ay.asm" -SIZ_AY .EQU $ - ORG_AY - .ECHO "AY occupies " - .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" -#INCLUDE "time.asm" -#INCLUDE "bcd.asm" -#INCLUDE "decode.asm" -;#INCLUDE "xio.asm" -; -#IF (DSKYENABLE) -#DEFINE DSKY_KBD -#INCLUDE "dsky.asm" -#ENDIF -; -; DETECT CPU SPEED USING DS-1302 RTC -; -HB_CPUSPD: -; -#IF (DSRTCENABLE) -; - CALL DSRTC_TSTCLK ; IS CLOCK RUNNING? - JR Z,HB_CPUSPD1 ; YES, CONTINUE - ; MAKE SURE CLOCK IS RUNNING - LD HL,DSRTC_TIMDEF - CALL DSRTC_TIM2CLK - LD HL,DSRTC_BUF - CALL DSRTC_WRCLK - CALL DSRTC_TSTCLK ; NOW IS CLOCK RUNNING? - RET NZ -; -HB_CPUSPD1: -; LD B,8 -;HB_CPUSPDX: -; PUSH BC - - ; WAIT FOR AN INITIAL TICK TO ALIGN, THEN WAIT - ; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT - - CALL HB_RDSEC ; GET SECONDS - LD (HB_CURSEC),A ; AND INIT CURSEC - CALL HB_WAITSEC ; WAIT FOR SECONDS TICK - LD (HB_CURSEC),A ; SAVE NEW VALUE - CALL HB_WAITSEC ; WAIT FOR SECONDS TICK - -; PUSH DE -; POP BC -; CALL NEWLINE -; CALL PRTHEXWORD - -; POP BC -; DJNZ HB_CPUSPDX -; - LD A,H - OR L - RET Z ; FAILURE, USE DEFAULT CPU SPEED - -; - ; MOVE LOOP COUNT TO HL - PUSH DE - POP HL -; - ; TIMES 4 FOR CPU SPEED IN KHZ - RES 0,L ; GRANULARITY -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - SLA L - RL H -#ENDIF - SLA L - RL H - SLA L - RL H -; - LD (CB_CPUKHZ),HL - LD DE,1000 - CALL DIV16 - LD A,C - LD (CB_CPUMHZ),A -; - RET -; -HB_WAITSEC: - ; WAIT FOR SECONDS TICK - ; RETURN SECS VALUE IN A, LOOP COUNT IN DE - LD DE,0 ; INIT LOOP COUNTER -HB_WAITSEC1: -#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_EZZ80)) - ; LOOP TARGET IS 4000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4 - CALL DLY32 - CALL DLY8 - CALL DLY2 - JP $ + 3 ; 10 TSTATES - JP $ + 3 ; 10 TSTATES - JP $ + 3 ; 10 TSTATES - JP $ + 3 ; 10 TSTATES - ;LD A,R ; 9 TSTATES - INC BC ; 6 TSTATES - ;LD A,(BC) ; 7 TSTATES - ;NOP ; 4 TSTATES - NOP ; 4 TSTATES -#ENDIF - -#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180)) - ; LOOP TARGET IS 8000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 8 - ;CALL DLY64 - CALL DLY32 - CALL DLY16 - CALL DLY8 - CALL DLY4 - CALL DLY2 - CALL DLY1 ; CALL (25TS) & RET (18TS) = 43TS - OR A ; 7 TSTATES - OR A ; 7 TSTATES - ;OR A ; 7 TSTATES - ;OR A ; 7 TSTATES - NOP ; 6 TSTATES - ;NOP ; 6 TSTATES - ;NOP ; 6 TSTATES - ;NOP ; 6 TSTATES - ;NOP ; 6 TSTATES -#ENDIF -; - PUSH DE - CALL HB_RDSEC ; GET SECONDS - POP DE - INC DE ; BUMP COUNTER - LD HL,HB_CURSEC ; POINT TO COMP VALUE - CP (HL) ; TEST FOR CHANGE - RET NZ ; DONE IF TICK OCCURRED - LD A,D ; CHECK HL - OR E ; ... FOR OVERFLOW - RET Z ; TIMEOUT, SOMETHING IS WRONG - JR HB_WAITSEC1 ; LOOP -; -HB_RDSEC: - ; READ SECONDS BYTE INTO A - LD C,$81 ; SECONDS REGISTER - CALL DSRTC_CMD ; SEND THE COMMAND - CALL DSRTC_GET ; READ THE REGISTER - CALL DSRTC_END ; FINISH IT - RET -; -#ELSE -; - RET ; NO RTC, ABORT -; -#ENDIF -; -; PRINT VALUE OF HL AS THOUSANDTHS, IE. 0.000 -; -PRTD3M: - PUSH BC - PUSH DE - PUSH HL - LD E,'0' - LD BC,-10000 - CALL PRTD3M1 - LD E,0 - LD BC,-1000 - CALL PRTD3M1 - CALL PC_PERIOD - LD BC,-100 - CALL PRTD3M1 - LD C,-10 - CALL PRTD3M1 - LD C,-1 - CALL PRTD3M1 - POP HL - POP DE - POP BC - RET -PRTD3M1: - LD A,'0' - 1 -PRTD3M2: - INC A - ADD HL,BC - JR C,PRTD3M2 - SBC HL,BC - CP E - JR Z,PRTD3M3 - LD E,0 - CALL COUT -PRTD3M3: - RET -; -;================================================================================================== -; DISPLAY SUMMARY OF ATTACHED UNITS/DEVICES -;================================================================================================== -; -PRTSUM: - CALL NEWLINE2 ; SKIP A LINE - LD DE,PS_STRHDR ; POINT TO HEADER - CALL WRITESTR ; PRINT IT -; - ; PRINT DISK DEVICES - LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET - LD C,BF_SYSGET_DIOCNT ; SUBFUNC: DISK UNIT COUNT - RST 08 ; E := DISK UNIT COUNT - LD B,E ; MOVE TO B FOR LOOP COUNT - LD A,E ; MOVE TO ACCUM - OR A ; SET FLAGS - JR Z,PRTSUM1A ; IF NONE, BYPASS - LD C,0 ; C WILL BE UNIT INDEX -PRTSUM1: - PUSH BC ; SAVE LOOP CONTROL - CALL PS_DISK ; PRINT DISK INFO - POP BC ; RESTORE LOOP CONTROL - INC C ; BUMP DISK UNIT INDEX - DJNZ PRTSUM1 ; LOOP THRU ALL DISK DEVICES -; -PRTSUM1A: - ; PRINT SERIAL DEVICES - LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET - LD C,BF_SYSGET_CIOCNT ; SUBFUNC: SERIAL UNIT COUNT - RST 08 ; E := SERIAL UNIT COUNT - LD B,E ; MOVE TO B FOR LOOP COUNT - LD A,E ; MOVE TO ACCUM - OR A ; SET FLAGS - JR Z,PRTSUM2A ; IF NONE, BYPASS - LD C,0 ; C WILL BE UNIT INDEX -PRTSUM2: - PUSH BC ; SAVE LOOP CONTROL - CALL PS_SERIAL ; PRINT SERIAL INFO - POP BC ; RESTORE LOOP CONTROL - INC C ; BUMP SERIAL UNIT INDEX - DJNZ PRTSUM2 ; LOOP THRU ALL SERIAL DEVICES -; -PRTSUM2A: - ; PRINT VIDEO DEVICES - LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET - LD C,BF_SYSGET_VDACNT ; SUBFUNC: VIDEO UNIT COUNT - RST 08 ; E := SERIAL UNIT COUNT - LD B,E ; MOVE TO B FOR LOOP COUNT - LD A,E ; MOVE TO ACCUM - OR A ; SET FLAGS - JR Z,PRTSUM3A ; IF NONE, BYPASS - LD C,0 ; C WILL BE UNIT INDEX -PRTSUM3: - PUSH BC ; SAVE LOOP CONTROL - CALL PS_VIDEO ; PRINT VIDEO INFO - POP BC ; RESTORE LOOP CONTROL - INC C ; BUMP VIDEO UNIT INDEX - DJNZ PRTSUM3 ; LOOP THRU ALL VIDEO DEVICES -; -PRTSUM3A: - RET ; DONE -; -; PRINT ONE LINE DISK UNIT/DEVICE INFO, DISK UNIT INDEX IN C -; -PS_DISK: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Disk $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_DDSTRREF ; POINT TO DISK DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT DISK DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP DE ; RECOVER ATTRIBUTES TO DE - PUSH DE ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTDT ; PRINT DISK TYPE - POP DE ; RESTORE ATTRIBUTES - POP BC ; RESTORE UNIT NUM - CALL PS_PRTDC ; PRINT DISK CAPACITY -; - CALL NEWLINE - RET -; -; PRINT DISK TYPE (DISK ATTRIBUTE IN E) -; -PS_PRTDT: - LD A,E ; ATTRIBUTES TO A - BIT 7,A ; FLOPPY BIT SET? - LD HL,PS_DTFLOP ; ASSUME FLOPPY - JR NZ,PS_PRTDT1 ; IF FLOPPY, JUMP AHEAD - RRCA ; SHIFT TYPE BITS - RRCA - RRCA - AND $07 ; AND ISOLATE THEM - RLCA ; X2 FOR WORD OFFSET IN STRING TABLE - LD HL,PS_DTSTRREF + 2 ; POINT TO STR REF TABLE (SKIP FLOPPY STRING) - CALL ADDHLA - LD A,(HL) - INC HL - LD H,(HL) - LD L,A -; -PS_PRTDT1: - CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED - LD A,18 ; 18 CHAR FIELD - SUB C - CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) - RET -; -; PRINT DISK CAPACITY (UNIT IN C, ATTRIBUTE IN E) -; -PS_PRTDC: -; - LD A,E ; ATTRIBUTE TO ACCUM - BIT 7,A ; TEST FOR FLOPPY - JR NZ,PS_PRTDC2 ; HANDLE FLOPPY - RRCA ; ISOLATE TYPE BITS - RRCA - RRCA - AND $07 - CP 4 ; ROM DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB - CP 5 ; RAM DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB -; - ; PRINT HARD DISK STORAGE SIZE IN MB - LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY - RST 08 ; DE:HL := BLOCKS - JP NZ,PS_PRTNUL ; MEDIA PROBLEM - RES 7,D ; CLEAR LBA BIT - LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB - CALL SRL32 ; RIGHT SHIFT - CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) - PRTS("MB$") ; PRINT SUFFIX - CALL PC_COMMA - PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA - RET ; DONE -; -PS_PRTDC1: - ; PRINT ROM/ROM DISK CAPACITY IN KB - LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY - RST 08 ; DE:HL := BLOCKS - JP NZ,PS_PRTNUL ; MEDIA PROBLEM - RES 7,D ; CLEAR LBA BIT - LD B,1 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB - CALL SRL32 ; RIGHT SHIFT - CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) - PRTS("KB$") ; PRINT SUFFIX - CALL PC_COMMA - PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA - RET ; DONE -; -PS_PRTDC2: - LD C,E ; ATTRIBUTE TO C FOR SAFE KEEPING - ; PRINT FLOPPY TYPE - LD A,C ; ATTRIBUTE TO ACCUM - RLCA ; ISOLATE FORM FACTOR BITS - RLCA - RLCA - AND $03 - LD DE,PS_FLP8 ; ASSUME 8" - CP 0 - JR Z,PS_PRTDC2A - LD DE,PS_FLP5 ; ASSUME 5.25" - CP 1 - JR Z,PS_PRTDC2A - LD DE,PS_FLP3 ; ASSUME 3.5" - CP 2 - JR Z,PS_PRTDC2A - LD DE,PS_FLPN ; ASSUME OTHER" -PS_PRTDC2A: - CALL WRITESTR - ; PRINT FLOPPY SIDES - LD A,C ; ATTRIBUTE TO ACCUM - LD DE,PS_FLPSS ; ASSUME SINGLE SIDED - BIT 4,A ; DS? - JR Z,PS_PRTDC2B - LD DE,PS_FLPDS ; DOUBLE SIDED -PS_PRTDC2B: - CALL WRITESTR - ; PRINT FLOPPY DENSITY - LD A,C ; ATTRIBUTE TO ACCUM - RRCA ; ISOLATE DENSITY BITS - RRCA - AND $03 - LD DE,PS_FLPSD ; SINGLE DENSITY - CP 0 - JR Z,PS_PRTDC2C - LD DE,PS_FLPDD ; DOUBLE DENSITY - CP 1 - JR Z,PS_PRTDC2C - LD DE,PS_FLPHD ; HIGH DENSITY - CP 2 - JR Z,PS_PRTDC2C - LD DE,PS_FLPED ; EXTENDED DENSITY - CP 3 - JR Z,PS_PRTDC2C -PS_PRTDC2C: - CALL WRITESTR - CALL PC_COMMA - PRTS("CHS$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA -; - RET ; DONE -; -; PRINT ONE LINE SERIAL UNIT/DEVICE INFO, SERIAL UNIT INDEX IN C -; -PS_SERIAL: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Char $" - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, C:=DEVICE ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_SDSTRREF ; POINT TO SERIAL DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT SERIAL DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP BC ; RECOVER ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTST ; PRINT SERIAL TYPE - POP BC ; RESTORE ATTRIBUTES - POP DE ; RESTORE UNIT NUM TO E - CALL PS_PRTSC ; PRINT SERIAL CONFIG -; - CALL NEWLINE - RET -; -; 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 - LD HL,PS_STTERM ; TYPE IS TERMINAL -; -PS_PRTST1: - CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED - LD A,18 ; 18 CHAR FIELD - SUB C - CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) - RET -; -; 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 - JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG -; - ; PRINT RS-232 CONFIG - LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG - LD C,E ; SET SERIAL UNIT NUM - RST 08 ; DE:HL := BAUD RATE - LD A,D ; TEST FOR $FF - AND E - INC A ; SET Z IF DE == $FF - JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED -; -PS_PRTSC0: - ; PRINT BAUD RATE - PUSH DE ; PRESERVE DE - LD A,D - AND $1F ; ISOLATE ENCODED BAUD RATE - LD L,A ; PUT IN L - LD H,0 ; H IS ALWAYS ZERO - LD DE,75 ; BAUD RATE DECODE CONSTANT - CALL DECODE ; DE:HL := BAUD RATE - LD BC,HB_BCDTMP ; POINT TO TEMP BCD BUF - CALL BIN2BCD ; CONVERT TO BCD - CALL PRTBCD ; AND PRINT IN DECIMAL - POP DE ; RESTORE DE -; - ; PRINT DATA BITS - PUSH DE ; PRESERVE DE - CALL PC_COMMA ; FORMATTING - LD A,E ; GET CONFIG BYTE - AND $03 ; ISOLATE DATA BITS VALUE - ADD A,'5' ; CONVERT TO CHARACTER - CALL COUT ; AND PRINT - POP DE ; RESTORE DE -; - ; PRINT PARITY - PUSH DE ; PRESERVE DE - CALL PC_COMMA ; FORMATTING - LD A,E ; GET CONFIG BYTE - RRCA ; SHIFT RELEVANT BITS - RRCA ; ... - RRCA ; ... - AND $07 ; AND ISOLATE DATA BITS VALUE - LD HL,PS_STPARMAP ; CHARACTER LOOKUP TABLE - CALL ADDHLA ; APPLY OFFSET - LD A,(HL) ; GET CHARACTER - CALL COUT ; AND PRINT - POP DE ; RESTORE DE -; - ; PRINT STOP BITS - CALL PC_COMMA ; FORMATTING - LD A,E ; GET CONFIG BYTE - RRCA ; SHIFT RELEVANT BITS - RRCA ; ... - AND $01 ; AND ISOLATE DATA BITS VALUE - ADD A,'1' ; MAKE IT A CHARACTER - CALL COUT ; AND PRINT -; - 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 - CP $FF ; NO ATTACHED VDA - JR Z,PS_PRTSC2 - PRTS("Video $") ; FORMATTING - AND $0F ; ISOLATE VIDEO UNIT NUM - CALL PRTDECB ; PRINT IT - CALL PC_COMMA -#IF (VDAEMU == EMUTYP_TTY) - PRTS("TTY$") -#ENDIF -#IF (VDAEMU == EMUTYP_ANSI) - PRTS("ANSI$") -#ENDIF - RET -; -PS_PRTSC2: - PRTS("PropTerm$") ; ASSUME PROPELLER - CALL PC_COMMA - PRTS("ANSI$") - RET -; -; PRINT ONE LINE VIDEO UNIT/DEVICE INFO, VIDEO UNIT INDEX IN C -; -PS_VIDEO: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Video $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_VDSTRREF ; POINT TO VIDEO DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT VIDEO DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP DE ; RECOVER ATTRIBUTES - PUSH DE ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTVT ; PRINT VIDEO TYPE - POP DE ; RESTORE ATTRIBUTES - POP BC ; RESTORE UNIT NUM - CALL PS_PRTVC ; PRINT VIDEO CONFIG -; - CALL NEWLINE - RET -; -; PRINT VIDEO TYPE (VIDEO ATTRIBUTE IN E) -; -PS_PRTVT: - LD HL,PS_VTCRT ; ASSUME CRT - CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED - LD A,18 ; 18 CHAR FIELD - SUB C - CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) - RET -; -; PRINT VIDEO CONFIG (UNIT IN C, ATTRIBUTE IN E) -; -PS_PRTVC: - PRTS("Text$") - CALL PC_COMMA - LD B,BF_VDAQRY ; FUNC: QUERY FOR VDA CONFIG - RST 08 ; D:=ROWS, E:=COLS - LD A,E - CALL PRTDECB - LD A,'x' - CALL COUT - LD A,D - CALL PRTDECB - RET -; -; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE -; -PS_PRTDEV: - LD A,D - RRCA ; TYPE IS IN UPPER NIBBLE, MOVE TO LOWER NIBBLE - RRCA - RRCA - RRCA - RLCA ; X2 FOR WORD OFFSET IN STRING TABLE - CALL ADDHLA - LD A,(HL) - INC HL - LD H,(HL) - LD L,A - CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED - LD A,E ; NUM - CALL PRTDECB ; PRINT NUM, ASSUME 1 CHAR - CALL PC_COLON ; PRINT COLON - LD A,12 - 2 ; 12 CHAR FIELD - 1 POS FOR UNIT NUM AND 1 POS FOR COLON - SUB C - CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) - RET -; -; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE -; -PS_PRTNUL: - LD HL,PS_STRNUL - ; FALL THRU TO PS_PRT -; -; -; -PS_PRT: - ; PRINT STRING AT (HL), $ TERM, RETURN CHARS PRINTED IN C - LD C,0 ; INIT CHAR COUNT -PS_PRT1: - LD A,(HL) ; GET CHAR - INC HL ; BUMP INDEX - CP '$' ; TERM? - RET Z ; IF SO, DONE - CALL COUT ; PRINT IT - INC C ; BUMP COUNTER - JR PS_PRT1 ; AND LOOP -; -; -; -PS_PAD: - ; PAD N SPACES SPECIFIED IN A - LD B,A - LD A,' ' -PS_PAD1: - CALL COUT - DJNZ PS_PAD1 - RET -; -; -; -PS_STRNUL .TEXT "--$" ; DISPLAY STRING FOR NUL VALUE -; -; DISK DEVICE STRINGS -; -PS_DDSTRREF: - .DW PS_DDMD, PS_DDFD, PS_DDRF, PS_DDIDE, PS_DDATAPI, PS_DDPPIDE - .DW PS_DDSD, PS_DDPRPSD, PS_DDPPPSD, PS_DDHDSK -; -PS_DDMD .TEXT "MD$" -PS_DDFD .TEXT "FD$" -PS_DDRF .TEXT "RF$" -PS_DDIDE .TEXT "IDE$" -PS_DDATAPI .TEXT "ATAPI$" -PS_DDPPIDE .TEXT "PPIDE$" -PS_DDSD .TEXT "SD$" -PS_DDPRPSD .TEXT "PRPSD$" -PS_DDPPPSD .TEXT "PPPSD$" -PS_DDHDSK .TEXT "HDSK$" -; -; DISK TYPE STRINGS -; -PS_DTSTRREF: - .DW PS_DTFLOP, PS_DTHARD, PS_DTCF, PS_DTSD - .DW PS_DTUSB, PS_DTROM, PS_DTRAM, PS_DTRF -; -PS_DTFLOP .TEXT "Floppy Disk$" -PS_DTHARD .TEXT "Hard Disk$" -PS_DTCF .TEXT "CompactFlash$" -PS_DTSD .TEXT "SD Card$" -PS_DTUSB .TEXT "USB Drive$" -PS_DTROM .TEXT "ROM Disk$" -PS_DTRAM .TEXT "RAM Disk$" -PS_DTRF .TEXT "RAM Floppy$" -PS_DTOTHER .TEXT "???$" -; -; FLOPPY ATTRIBUTE STRINGS -; -PS_FLP8 .TEXT "8\",$" -PS_FLP5 .TEXT "5.25\",$" -PS_FLP3 .TEXT "3.5\",$" -PS_FLPN .TEXT "???\",$" -; -PS_FLPSS .TEXT "SS/$" -PS_FLPDS .TEXT "DS/$" -; -PS_FLPSD .TEXT "SD$" -PS_FLPDD .TEXT "DD$" -PS_FLPHD .TEXT "HD$" -PS_FLPED .TEXT "ED$" -; -; SERIAL DEVICE STRINGS -; -PS_SDSTRREF: - .DW PS_SDUART, PS_SDASCI, PS_SDTERM, - .DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA, PS_SDPIO -; -PS_SDUART .TEXT "UART$" -PS_SDASCI .TEXT "ASCI$" -PS_SDTERM .TEXT "TERM$" -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" - -; -; SERIAL TYPE STRINGS -; -; -; VIDEO DEVICE STRINGS -; -PS_VDSTRREF: - .DW PS_VDVDU, PS_VDCVDU, PS_VDNEC, PS_VDTMS, PS_VDVGA -; -PS_VDVDU .TEXT "VDU$" -PS_VDCVDU .TEXT "CVDU$" -PS_VDNEC .TEXT "NEC$" -PS_VDTMS .TEXT "TMS$" -PS_VDVGA .TEXT "VGA$" -; -; VIDEO TYPE STRINGS -; -PS_VTCRT .TEXT "CRT$" -; -; VIDEO CONFIG STRINGS -; -; -; -; 0 1 2 3 4 5 6 7 -; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 -PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" - .TEXT "---------- ---------- ---------------- --------------------\r\n$" -; -;================================================================================================== -; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED) -;================================================================================================== -; -; OUTPUT CHARACTER FROM A -; -COUT: - ; SAVE ALL INCOMING REGISTERS - PUSH AF - PUSH BC - PUSH DE - PUSH HL -; - ; GET CURRENT CONSOLE UNIT - LD E,A ; TEMPORARILY STASH OUTPUT CHAR IN E - LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE - CP $FF ; TEST FOR $FF (HBIOS NOT READY) - JR Z,COUT1 ; IF NOT READY, USE XIO -; - ; USE HBIOS - LD C,A ; CONSOLE UNIT TO C - LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR - CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY - JR COUT2 ; CONTINUE -; -COUT1: - ;; USE XIO - ;LD A,E ; GET OUTPUT CHAR BACK TO ACCUM - ;CALL XIO_OUTC ; OUTPUT VIA XIO -; -COUT2: - ; RESTORE ALL REGISTERS - POP HL - POP DE - POP BC - POP AF - RET -; -; INPUT CHARACTER TO A -; -CIN: - ; SAVE INCOMING REGISTERS (AF IS OUTPUT) - PUSH BC - PUSH DE - PUSH HL -; - LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE - CP $FF ; TEST FOR $FF (HBIOS NOT READY) - JR Z,CIN1 ; IF NOT READY, USE XIO -; - ; USE HBIOS - LD C,A ; CONSOLE UNIT TO C - LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR - CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY - LD A,E ; RESULTANT CHAR TO A - JR CIN2 ; CONTINUE -; -CIN1: - ;; USE XIO - ;CALL XIO_INC ; GET CHAR -; -CIN2: -; - ; RESTORE REGISTERS (AF IS OUTPUT) - POP HL - POP DE - POP BC - RET -; -; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) -; -CST: - ; SAVE INCOMING REGISTERS (AF IS OUTPUT) - PUSH BC - PUSH DE - PUSH HL -; - LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE - CP $FF ; TEST FOR $FF (HBIOS NOT READY) - JR Z,CST1 ; IF NOT READY, USE XIO -; - ; USE HBIOS - LD C,A ; CONSOLE UNIT TO C - LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS - CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY - JR CST2 ; CONTINUE -; -CST1: - ;; USE XIO - ;CALL XIO_IST ; GET STATUS -; -CST2: - ; RESTORE REGISTERS (AF IS OUTPUT) - POP HL - POP DE - POP BC - RET -; -;================================================================================================== -; MISCELLANEOUS UTILITY FUNCTIONS -;================================================================================================== -; -; SET HL TO IY+A, A IS TRASHED -; -LDHLIYA: - PUSH IY ; COPY INSTANCE DATA PTR - POP HL ; ... TO HL - ;JP ADDHLA ; APPLY OFFSET TO HL AND RETURN - ADD A,L ; ADD OFFSET TO LSB - LD L,A ; ... PUT BACK IN L - RET NC ; DONE IF CF NOT SET - INC H ; IF CF SET, BUMP MSB - RET ; ... AND RETURN -; -; CONVERT AN HBIOS STANDARD HARD DISK CHS ADDRESS TO -; AN LBA ADDRESS. A STANDARD HBIOS HARD DISK IS ASSUMED -; TO HAVE 16 SECTORS PER TRACK AND 16 HEADS PER CYLINDER. -; -; INPUT: HL=TRACK, D=HEAD, E=SECTOR -; OUTPUT: DE:HL=32 BIT LBA ADDRESS (D:7 IS NOT SET IN THE RESULT) -; -HB_CHS2LBA: -; - LD A,D ; HEAD TO A - RLCA ; LEFT SHIFT TO HIGH NIBBLE - RLCA ; ... DEPENDS ON HIGH - RLCA ; ... NIBBLE BEING 0 SINCE - RLCA ; ... IT ROTATES INTO LOW NIBBLE - OR E ; COMBINE WITH SECTOR (HIGH NIBBLE MUST BE ZERO) - LD D,0 - LD E,H - LD H,L - LD L,A - XOR A - RET -; -;================================================================================================== -; HBIOS GLOBAL DATA -;================================================================================================== -; -IDLECOUNT .DB 0 -; -HEAPCURB .DW 0 ; MARK HEAP ADDRESS AFTER INITIALIZATION -; -HB_TICKS .FILL 4,0 ; 32 BIT TICK COUNTER -; -STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$" -STR_PLATFORM .DB PLATFORM_NAME, "$" -STR_SWITCH .DB "*** Activating CRT Console ***$" -STR_BADINT .DB "\r\n*** BAD INT ***\r\n$" -; -#IF (DSKYENABLE) -MSG_HBVER .DB $BE,$FF,$8A,$FB,$D7,$6D,$77,$B0 ; "HBIOS291" -#ENDIF -; -HB_CURSEC .DB 0 ; CURRENT SECOND (TEMP) -; -HB_BCDTMP .FILL 5,0 ; BCD NUMBER STORAGE (TEMP) -; -HB_WRKBUF .FILL 512,0 ; INTERNAL DISK BUFFER -; -HB_END .EQU $ -; -SLACK .EQU BNKTOP - $ - .ECHO "HBIOS space remaining: " - .ECHO SLACK - .ECHO " bytes.\n" -; -#IFDEF ROMBOOT - .FILL SLACK -#ENDIF -; - .END From 21acf463ba7f67cd75a778f97199cba91002860d Mon Sep 17 00:00:00 2001 From: b1ackmai1er <39449559+b1ackmai1er@users.noreply.github.com> Date: Tue, 9 Apr 2019 23:28:06 +0800 Subject: [PATCH 8/9] Delete pio.asm --- pio.asm | 695 -------------------------------------------------------- 1 file changed, 695 deletions(-) delete mode 100644 pio.asm diff --git a/pio.asm b/pio.asm deleted file mode 100644 index 9a04177d..00000000 --- a/pio.asm +++ /dev/null @@ -1,695 +0,0 @@ -; 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 -; -; -; 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 (PIO_DEV),A ; CURRENT DEVICE NUMBER -PIO_PREINIT0: - PUSH BC ; SAVE LOOP CONTROL - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS - PUSH HL ; SAVE IT - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - CALL PIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE - POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE - POP BC ; RESTORE LOOP CONTROL -; - LD A,(IY+1) ; GET THE PIO TYPE DETECTED - OR A ; SET FLAGS - JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND -; - PUSH BC ; SAVE LOOP CONTROL - PUSH AF - DEC A - LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D - DEC A - LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND - DEC A - LD BC,PRT_FNTBL - JR NZ,TYPDUN -TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE -TYPDUN: POP AF - POP BC ; RESTORE LOOP CONTROL -; -PIO_PREINIT2: - INC C ; NEXT PHYSICAL UNIT - DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE -; -#IF (INTMODE == 2) - ; SETUP PIO INTERRUPT VECTOR IN IVT - LD HL,PIO0INT - LD (HBX_IVT + IVT_PIO0),HL -#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: - LD A,C ; SET THE UNIT NUMBER - LD (IY),A - - LD DE,-1 ; LEAVE CONFIG ALONE - JP PIO_INITDEV ; IMPLEMENT IT AND RETURN -; XOR A ; SIGNAL SUCCESS -; RET ; AND RETURN -; -PIO_INIT: - LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS - LD C,0 ; INDEX INTO PIO CONFIG TABLE -PIO_INIT1: - PUSH BC ; SAVE LOOP CONTROL - - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) - RLCA ; ... - RLCA ; ... TO GET OFFSET INTO CFG TABLE - LD HL,PIO_CFG ; POINT TO START OF CFG TABLE - CALL ADDHLA ; HL := ENTRY ADDRESS - PUSH HL ; COPY CFG DATA PTR - POP IY ; ... TO IY - - LD A,(IY+1) ; GET PIO TYPE - OR A ; SET FLAGS - CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO - - PUSH DE - LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL - CALL PIO_INITDEV ; BASED ON DPW - POP DE - - POP BC ; RESTORE LOOP CONTROL - INC C ; NEXT UNIT - DJNZ PIO_INIT1 ; LOOP TILL DONE -; - XOR A ; SIGNAL SUCCESS - RET ; DONE -; -; EXAMPLE CODE -; -PIO_LPT: - IN A,($F6) ; get device status - AND $20 ; device ready? - JR Z,PIO_LPT ; no, busy wait - IN A,($F5) ; get transmit buffer register status ready? - AND $20 ; ready? - JR Z,PIO_LPT ; no, busy wait - LD A,C ; ready, char A for output through data port - OUT ($F0),A ; output char - RET - - - -; ------------------------------------ -; ZILOG PIO FUNCTION TABLE ROUTINES -;------------------------------------- - -PIO_IN: - LD C,(IY+3) - IN A,(C) - LD E,A - XOR A ; SIGNAL SUCCESS - RET - -; -PIO0INT: -PIO1INT: -PIO2INT: -PIO3INT: -PIO4INT: -PIO5INT: -PIO6INT: -PIO7INT: -PIO8INT: -PIO9INT: - OR $FF ; NZ SET TO INDICATE INT HANDLED - RET -; -; 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 - - LD C,(IY+3) ; GET PORT - LD A,(IY+4) ; GET MODE (B7B6) - - -PIO_IST: - RET -; -PIO_OST: - RET -; -; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. -; Otherwise use the configuration information in DE to program those settings and save them in the device table -; -; SETUP PARAMETER WORD: -; +-------------------------------+ +-------+-----------+---+-------+ -; | BIT CONTROL | | MODE | C2 C1 C0 | A | INT | -; +-------------------------------+ --------------------+-----------+ -; F E D C B A 9 8 7 6 5 4 3 2 1 0 -; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- -; -; -; MSB = BIT MAP USE IN MODE 3 -; MODE B7 B6 = 00 Mode 0 Output -; 01 Mode 1 Input -; 10 Mode 2 Bidir -; 11 Mode 3 Bit Mode -; CHIP CHANNEL B5 B4 B3 001 Channel 1 -; 010 Channel 2 -; 100 Channel 3 -; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED -; = 1 IS ALLOCATED -; -; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 -; 01 IVT_PIO1 -; 10 IVT_PIO2 -; 11 IVT_PIO3 -PIO_INITDEV: - ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) - LD A,D ; TEST DE FOR - AND E ; ... VALUE OF -1 - INC A ; ... SO Z SET IF -1 - JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG -; - ; LOAD EXISTING CONFIG TO REINIT - 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 -; -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 -; -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: -PPI_DEVICE: - LD D,CIODEV_PIO ; D := DEVICE TYPE - LD E,(IY) ; E := PHYSICAL UNIT - LD C,$40 ; C := ATTRIBUTE - XOR A ; SIGNAL SUCCESS - RET - -; ------------------------------------ -; 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 - 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 - 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 -; - ; ALL DONE IF NO PIO WAS DETECTED - LD A,(IY+1) ; GET SIO 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 -; - XOR A - RET -; -; WORKING VARIABLES -; -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_PORT - -PIO_STR_NONE .DB "$" -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+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) -DEFPIO(PIO_ZPIO,PIOZBASE+4,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) -#ENDIF -#IF PIO_4P -DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO8FT,PIO9FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO10FT,PIO11FT,INT_N,INT_N) -#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 -; EACH PIO NEEDS A FUNCTION TABLE -; ECB-ZP : PIO0FT-PIO3FT -; ECB-4P : PIO4FT-PIO11FT - -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 -PIO2FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO2FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO3FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO3FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF -; -#IF PIO_4P -PIO4FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO4FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO5FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO5FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO6FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO6FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO7FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO7FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO8FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO8FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO9FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO9FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO10FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO10FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO11FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO11FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF -; -; 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