From 248097630810ccc342cd0f00343eb18827accfc7 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 14 Jul 2019 20:38:51 +0800 Subject: [PATCH] Update pio.asm Major restructure --- Source/HBIOS/pio.asm | 1200 ++++++++++++++++++++++++++---------------- 1 file changed, 742 insertions(+), 458 deletions(-) diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index e9327111..841c04ad 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -3,46 +3,58 @@ ; ; HBIOS initializes driver by: ; -; 1) Performing Pre-initialization +; 1) Calling Pre-initialization ; -; This involves setting up all the data structures decribing the devices. +; This involves setting up all the data structures describing the devices. ; If possible, do a hardware test to verify it is available for adding to available devices. ; -; 2) Performing individual device/unit initialization. +; 2) Calling device initialization. ; ; Hardware initialization. ; Configure to initial state or to a new state. +; ; Implementation limitations: ; ; The fully functionality of the Z80 PIO can only be realized by using Z80 interrupt mode 2. ; Registers cannot be interrogated for interrupts status and the originating interrupt ; device cannot be determine. ; -; Full implementation of IM2 functionality in an ECB-ZP and ECB-4P board would require the -; allocation of an interrupt handler for each chip channel. Thus, 10 interrupt handler +; Full implementation of IM2 functionality for an ECB-ZP and ECB-4P board would require the +; allocation of an interrupt handler for each chip channel. Thus, 12 interrupt handlers ; would be required to support this configuration. As the HBIOS only has an allocation of ; 16, a full implmentation is impractical. ; -; The compromise solution is for the driver to allow IM2 only on the first PIO on each board. -; So, a ECB-4PIO would be fully interrupt drived in all modes but a ECB-ZP would only allow -; PIO 0 to be interrupt drived and PIO 1,2,3 would be limited to Bit mode or blind read and -; writed to the input/output ports. +; The compromise solution is to allow 4 interrupts for the PIO driver.; All remaining PIO's +; are limited to Bit mode or blind read and writed to the input/output ports. ; ; Zilog PIO reset state: ; -; Both port mask registers are reset to inhibit All port data bits. -; Port data bus lines are set to a high-impedance state and the Ready "handshake" -; Mode 1 is automatically selected. -; The vector address registers are not reset. -; Both port interrupt enable flip-flops are reset. -; Both port output registers are reset. -; -; Program a channel -; -; LD C,PIOBC ; C -> PIO Channel B control -; LD B,5 ; 5 bytes to send -; LD HL,PT ; HL -> Initialization data -; OTIR ; send bytes +; Both port mask registers are reset to inhibit All port data bits. +; Port data bus lines are set to a high-impedance state and the Ready "handshake" +; Mode 1 (output) is automatically selected. +; The vector address registers are not reset. +; Both port interrupt enable flip-flops are reset. +; Both port output registers are reset. +; +; Register addressing for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +; +; PIO ----ZP---- ----4P---- +; 0 DATA 0 90h DATA 0 B8h +; 0 DATA 1 91h DATA 1 B9h +; 0 CMD 0 92h CMD 0 BAh +; 0 CMD 1 93h CMD 1 BBh +; 1 DATA 0 94h DATA 0 BCh +; 1 DATA 1 95h DATA 1 BDh +; 1 CMD 0 96h CMD 0 BEh +; 1 CMD 1 97h CMD 1 BFh +; 2 DATA 0 C0h +; 2 DATA 1 C1h +; 2 CMD 0 C2h +; 2 CMD 1 C3h +; 3 DATA 0 C4h +; 3 DATA 1 C5h +; 3 CMD 0 C6h +; 3 CMD 1 C7h ; PIODEBUG .EQU 1 ; @@ -58,307 +70,613 @@ PIO_ZPIO .EQU 1 PIO_8255 .EQU 2 PIO_PORT .EQU 3 -;INT_POOL .EQU HBX_IVT+IVT_PIO0 +; SET MAXIMUM NUMBER OF INTERRUPTS AVAILABLE FOR ALL +; ENSURE INTERRUPTS ARE NOT TURNED ON IF IM2 IS NOT SET. INT_ALLOC .DB 0 INT_N .EQU 00000000B #IF (INTMODE == 2) -INT_Y .EQU INT_N +INT_Y .EQU 00000100B INT_ALLOW .EQU 4 #ELSE -INT_Y .EQU 00000100B +INT_Y .EQU INT_N INT_ALLOW .EQU 0 #ENDIF - -INT_0 .EQU 00000000B -INT_1 .EQU 00000001B -INT_2 .EQU 00000010B -INT_3 .EQU 00000011B ; +INT0 .EQU 00000000B +INT1 .EQU 00000001B +INT2 .EQU 00000010B +INT3 .EQU 00000011B ; ; SETUP THE DISPATCH TABLE ENTRIES ; -; WE CANT PRINT ANYTHING TO HBIOS CONSOLE AT THIS POINT ; PIO_CNT HOLDS THE NUMBER OF DEVICED CALCULATED FROM THE NUMBER OF DEFPIO MACROS ; PIO_CNT SHOULD INCREASE BY 2 FOR EVERY PIO CHIP ADDED. ; +; PIO_PREINIT WILL READ THROUGH ALL PIOCFG TABLES AND CONFIGURE EACH TABLE. +; IT WITH THEN CALL PIO_INITUNIT TO INITIALIZE EACH DEVICE TO ITS DEFAULT STATE +; +; EXPECTS NOTHING ON ENTRY +; PIO_PREINIT: + CALL NEWLINE ;D LD B,PIO_CNT ; LOOP CONTROL LD C,0 ; PHYSICAL UNIT INDEX XOR A ; ZERO TO ACCUM - LD (PIO_DEV),A ; CURRENT DEVICE NUMBER +; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER + LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED PIO_PREINIT0: PUSH BC ; SAVE LOOP CONTROL - LD A,C ; PHYSICAL UNIT TO A - RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES) + LD A,C ; INITIALIZE THE UNIT + + PUSH AF ;D + LD A,'u' ;D + CALL COUT ;D + POP AF ;D + CALL PRTHEXBYTE ;D UNIT + CALL PC_SPACE ;D + + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) RLCA ; ... RLCA ; ... TO GET OFFSET INTO CFG TABLE + RLCA +; RLCA LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + PUSH AF + CALL ADDHLA ; HL := ENTRY ADDRESS + POP AF CALL ADDHLA ; HL := ENTRY ADDRESS PUSH HL ; SAVE IT - 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 (HL),C + + PUSH AF ;D + LD A,'c' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + PUSH HL ;D + POP BC ;D + CALL PRTHEXWORD ;D CONFIG TABLE + CALL PC_SPACE ;D + POP BC ;D + LD A,(IY+1) ; GET THE PIO TYPE DETECTED - OR A ; SET FLAGS - JR Z,PIO_PREINIT2 ; SKIP IT IF NOTHING FOUND -; - PUSH BC ; SAVE LOOP CONTROL - PUSH AF - DEC A - LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:D - DEC A - LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS - JR Z,TYPFND - DEC A - LD BC,PRT_FNTBL - JR NZ,TYPDUN -TYPFND: CALL CIO_ADDENT ; ADD ENTRY IF PIO FOUND, BC:DE -TYPDUN: POP AF - POP BC ; RESTORE LOOP CONTROL -; -PIO_PREINIT2: - INC C ; NEXT PHYSICAL UNIT - DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE -; -#IF (INTMODE == 2) - ; SETUP PIO INTERRUPT VECTOR IN IVT - LD HL,PIO0INT -; LD (HBX_IVT + IVT_PIO0),HL - LD (HB_IVT09 + 1),HL ; WW: IVT INDEX 9 FOR PIO0 -#ENDIF -PIO_PREINIT3: - 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 + CP PIO_PORT ; SET FLAGS - 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 + PUSH AF ;D + LD A,'t' ;D + CALL COUT ;D + POP AF ;D + CALL PRTHEXBYTE ;D TYPE + CALL PC_SPACE ;D - 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 +; JR Z,BADINIT +; PUSH BC ; SAVE LOOP CONTROL +; LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; SKIP IT IF NOTHING FOUND +; LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS +; DEC A +; JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:DE +; LD BC,PRT_FNTBL +; DEC A +; JR Z,TYPFND +; POP BC +; JR BADINIT + PUSH HL + LD DE,-1 ; INITIALIZE THIS DEVICE WITH + CALL PIO_INITDEV ; DEFAULT VALUES + POP HL -; ------------------------------------ -; ZILOG PIO FUNCTION TABLE ROUTINES -;------------------------------------- +; JR NZ,SKPINIT + + ; AT THIS POINT WE KNOW WE + ; HAVE A VALID DEVICE SO ADD IT -PIO_IN: - LD C,(IY+3) - IN A,(C) - LD E,A - XOR A ; SIGNAL SUCCESS - RET + LD A,8 ; CALCULATE THE FUNCTION TABLE + CALL ADDHLA ; POSITION WHICH FOLLOWS THE + PUSH HL ; CONFIGURATION TABLE OF EACH + POP BC ; DEVICE -; -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 +TYPFND: PUSH AF ;D + LD A,'f' ;D + CALL COUT ;D + POP AF ;D + PUSH BC ;D + CALL PRTHEXWORD ;D FUNCTION TABLE + POP BC ;D + CALL NEWLINE ;D - LD C,(IY+3) ; GET PORT - LD A,(IY+4) ; GET MODE (B7B6) + PUSH IY ; ADD ENTRY IF PIO FOUND, BC:DE + POP DE ; BC: DRIVER FUNCTION TABLE + CALL CIO_ADDENT ; DE: ADDRESS OF UNIT INSTANCE DATA +BADINIT:POP BC ; RESTORE LOOP CONTROL -PIO_IST: - RET -; -PIO_OST: - RET + INC C ; NEXT PHYSICAL UNIT +SKPINIT:DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE + + PUSH AF ;D + PRTS("INTS=$") ;D + LD A,(INT_ALLOC) ;D + CALL PRTHEXBYTE ;D + POP AF ;D + PUSH DE ;D + LD DE,CIO_TBL-3 ;D + CALL DUMP_BUFFER ;D + POP DE ;D + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + +; PIO_INITDEV - INITIALIZE DEVICE ; -; 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 +; IF DE = FFFF THEN THE SETUP PARAMETER WORD WILL BE READ FROM THE DEVICE CONFIGURATION +; TABLE POINTED TO BY IY AND THE PIO PORT WILL BE PROGRAMMED BASED ON THAT CONFIGURATION. ; -; 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 +; OTHERWISE THE PIO PORT WILL BE PROGRAMMED BY THE SETUP PARAMETER WORD IN DE AND THIS +; WILL BE SAVED IN THE DEVICE CONFIGURATION TABLE POINTED TO BY IY. +; +; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT + PIO_INITDEV: ; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR AND E ; ... VALUE OF -1 INC A ; ... SO Z SET IF -1 JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG -; - ; LOAD EXISTING CONFIG TO REINIT +PIO_INITDEV0: + ; LOAD EXISTING CONFIG (DCW) TO REINIT LD E,(IY+4) ; LOW BYTE LD D,(IY+5) ; HIGH BYTE ; -PIO_INITDEV1: - ; WHICH DEVICE TYPE? +PIO_INITDEV1: ; WHICH DEVICE TYPE? LD A,(IY+1) CP PIO_ZPIO - JR Z,SET_PIO + JR Z,SETPIO0 CP PIO_8255 - JR Z,SET_8255 + JP Z,SET_8255 CP PIO_PORT - JR Z,SET_PORT -PIO_BAD:OR $FF ; UNKNOWN DEVICE + JP Z,SET_PORT +BAD_SET:OR $FF ; UNKNOWN DEVICE RET -SET_PORT: - ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT - LD C,(IY+3) - OUT (C),A - XOR A +SETPIO0:LD A,E ; GET MODE + AND 11000000B ; BITS (B7B6) + CP 10000000B ; IS IT BIDIR? + JR NZ,SETPIO1 + LD A,(IY+2) ; GET CHANNEL + OR A + JR NZ,BAD_SET ; CAN'T DO ON CH1 + + ; VALIDATE INTERRUPT REQUEST + ; GRANT INTERRUPT IF THERE IS A FREE INTERRUPT + ; GRANT INTERRUPT IF AN INTERRUPT IS ALREADY ALLOCATED TO THIS UNIT + +SETPIO1:PUSH AF ;D + LD A,'[' ;D + CALL COUT ;D + LD A,(IY) ;D + CALL PRTHEXBYTE ;D + LD A,']' ;D + CALL COUT ;D + POP AF ;D + + BIT 2,E ; SKIP IF WE ARE NOT REQUESTING + JP Z,SETPIO2 ; AN INTERRUPT + + PRTS("[INTREQ]$") ;D + +; LD A,(IY+4) ; GET CURRENT INTERRUPT SETTING +; BIT 2,A ; SKIP IF IT IS ALREADY +; JP NZ,SETPIO2 ; ALLOCATED TO THIS UNIT + + LD A,(INT_ALLOC) ; WE NEED TO ALLOCATE AN + CP INT_ALLOW ; INTERRUPT. DO WE HAVE + JR NC,BAD_SET ; ONE FREE? + + PRTS("[ALLOCINT]$") ;D + + ; WHICH INTERRUPT IS FREE ? + ; SCAN THROUGH THE CFG TABLES + ; AND FIND A FREE ONE + + PUSH AF ; NESTED LOOP + LD DE,32 ; OUTSIDE LOOP IS INTERRUPT + LD B,INT_ALLOW ; INSIDE LOOP IS DEVICE +SETPIOP: LD C,B + DEC C + PUSH BC + LD B,PIO_CNT + LD HL,PIO_CFG+4 +SETPIOX: LD A,(HL) + BIT 2,A ; JUMP TO NEXT DEVICE + JR Z,SETPIOY ; IF NO INTERRUPT ON + AND 00000011B ; THIS DEVICE + + CP C ; IF WE MATCH AN INTERRUPT HERE THEN IT IS NOT FREE. + JR NZ,SETPIOY ; SO EXIT INSIDE LOOP AND TRY NEXT INTERRUPT + + XOR A ; WE MATCH INT 0 - IF WE ARE CHECKING FOR IT THEN + OR C ; WE REGARD IS AS FREE. + JR NZ,SETPIOZ + +SETPIOY: ADD HL,DE + DJNZ SETPIOX + + JR SETPIOQ ; WE GET HERE IF THE CURRENT INTERRUPT + ; WAS NOT MATCHED SO IT IS FREE +SETPIOZ: POP BC + DJNZ SETPIOP + POP AF + + PRTS("[NONEFREE]$") RET + +SETPIOQ:PUSH AF ; AVAILABLE INTERRUPT IS IN C + PRTS("[FREE]=$") + LD A,C + CALL PRTHEXBYTE + POP AF + + POP AF + POP AF + +SETPIOR: + LD HL,INT_ALLOC ; INCREASE THE COUNT + INC (HL) ; OF USED INTERRUPTS + LD A,(HL) + +; LD A,(IY) ; IS THIS UNIT +; INC A ; UNITIALIZED? +; JR Z,SETPIO6 + + LD A,(IY+4) ; IT IS UNITIALIZED SO + OR C ; SAVE THE ALLOCATES + LD (IY+4),A ; INTERRUPT +; +; +; FOR THIS DEVICE AND INTERRUPT, UPDATE THE CONFIG TABLE FOR THIS DEVICE. +; PIO_IN, PIO_OUT, PIO_IST, PIO_OST ENTRIES NEED TO BE REDIRECTED. +; INTERRUPT VECTOR NEEDS TO BE UPDATED ; -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 A,(IY+0) + LD HL,0 + ; SETUP SIO INTERRUPT VECTOR IN IVT + LD HL,HB_IVT09+1 + + CALL SPK_BEEP + + +SETPIO6:RET + + ; EXIT WITH FREE INTERRUPT IN C + + LD A,C + LD (INT_ALLOC),A + +; CALL SPK_BEEP + + LD A,E + AND 11000000B + OR 00000100B + OR C + LD E,A + LD (IY+5),A +; + ; TODO: DEALLOCATE AN INTERRUPT +; +; LD A,(INT_ALLOC) +; DEC A +; LD (INT_ALLOC),A +; +SETPIO2: + +; DE CONTAINS THE MODE IF INTERRUPT ROUTINE SKIPPED + + PRTS("[NOINTREQ]$") ;D + +; LD A,(IY+4) + LD A,E ; GET MODE AND CREATE COMMAND + AND 11000000B ; $B0 + OR 00001111B ; $0F + LD C,(IY+3) ; GET DATA PORT INC C ; POINT TO CMD - INC C ; PORT - LD A,(IY+4) ; GET MODE (B7B6) - AND 11010000B ; KEEP MODE & CHANNEL - CP 10010000B ; SET CH1 & BIDIR - JR Z,PIO_BAD ; CAN'T DO ON CH1 - AND 11000000B ; $B0 - OR 00001111B ; $0F + INC C ; PORT OUT (C),A ; SET MODE CP (M_BitCtrl | $0F) ; IF MODE 3 - JR NZ,SET_NM3 - LD A,(IY+5) ; SET I/O + JR NZ,SETPIO3 + LD A,(IY+5) ; SET I/O DIRECTION OUT (C),A ; FOR MODE 3 -SET_NM3:; INTERUPT HANDLING - LD A,(IY+4) ; CHECK IF INTERRUPT - BIT 2,A ; REQUEST BIT SET - JR Z,NOINT1 - - LD A,(INT_ALLOC) ; DO WE HAVE AN - CP INT_ALLOW+1 ; INTERRUPT FREE? - JR NC,BADSET - - INC A ; ONE INTERRUPT - LD (INT_ALLOC),A ; USED - ; THE TRICKY BIT - SETUP THE RIGHT INTERRUPT VECTOR +SETPIO3:; INTERUPT HANDLING -NOINT1: LD A,00000111B ; $07 - OUT (C),A ; NO INTERRUPTS - DEC C - DEC C - LD A,$FF ; DEFAULT VALUE + JP SETPIO4 + + ; SETUP THE INTERRUPT VECTOR + + LD A,E + AND 00000011B +; DEC A ; INDEX INTO THE + ADD A,A ; THE VECTOR TABLE + ADD A,A ; + LD C,A + LD B,0 + LD HL,HB_IVT07+1 + ADD HL,BC ; GET THE ADDRESS OF + PUSH DE + LD D,(HL) ; THAT INTERRUPT + INC HL ; HANDLER + LD E,(HL) + LD HL,HBX_IVT+IVT_PIO0 ; POPULATE THE + LD A,L ; GET LOW BYTE OF IVT ADDRESS + ADD HL,BC ; INTERRUPT TABLE + LD (HL),D ; WITH THE INTERRUPT + INC HL ; HANDLER ADDRESS FOR + LD (HL),E ; THIS UNIT + POP DE + LD HL,INT_ALLOC + LD C,(HL) + LD B,0 + LD HL,PRTTAB-1 ; SAVE THE DATA + ADD HL,BC ; PORT FOR EACH INTERRUPT + LD C,(IY+3) + LD (HL),C + + INC C ; POINT TO CMD PORT + INC C + DI ; SET THE VECTOR ADDRESS OUT (C),A + +; LD A,10000011B ; ENABLE INTERRUPTS ON + OUT (C),A ; THIS UNIT + EI +; JR GUD_SET +; +SETPIO4:LD A,00000111B ; $07 + OUT (C),A ; NO INTERRUPTS +; +; SUCCESSFULL SO SAVE DEVICE CONFIGURATION WORD (DCW) +; +GUD_SET:LD (IY+4),E ; LOW BYTE + LD (IY+5),D ; HIGH BYTE +; +; UPDATE THE DEVICE TABLE WITH THE ADDRESSES FOR THE CORRECT ROUTINE. +; + LD HL,INTMATRIX ; POINT TO EITHER THE INTERRUPT + LD HL,POLMATRIX ; MATRIX OR THE POLLED MATRIX + PUSH HL + + PUSH IY ; CALCULATE THE DESTINATION + POP HL ; ADDRESS IN THE PIO_CFG TABLE + LD BC,8 ; FOR THE FOUR ADDESSES TO BE + ADD HL,BC ; COPIED TO + + +; LD B,0 ; 00000000 CALCULATE THE SOURCE ADDRESS + LD C,E ; XX?????? FROM THE MATRIX. EACH ENTRY + SRL C ; 0XX????? IN THE MATRIX IS 8 BYTES SO + SRL C ; 00XX???? SOURCE = MATRIX BASE + (8 * MODE) + SRL C ; 000XX??? + POP DE ; LOAD THE MATRIX BASE +; LD DE,POLMATRIX + EX DE,HL + ADD HL,BC ; HL = SOURCE + + LD C,8 ; COPY 8 BYTES + LDIR + +; PUSH IY +; POP DE +; CALL DUMP_BUFFER + XOR A RET -BADSET: LD A,$FF - RET -SET_8255: - RET +PRTTAB: .DB 0 + .DB 0 + .DB 0 + .DB 0 +; +;----------------------------------------------------------------------------- +; +; INPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +#DEFINE PIOMIVT(PIOIN,PIOIST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN WITH ERROR IF THERE IS \ +#DEFCONT ; ALREADY A CHARACTER IN BUFFER \ +#DEFCONT ;\ +#DEFCONT ; OTHERWISE CHANGE THE STATUS TO \ +#DEFCONT ; SHOW THERE IS ONE CHARACTER IN \ +#DEFCONT ; THE BUFFER AND READ IT IN AND \ +#DEFCONT ; AND STORE IT.RETURN GOOD STATUS.\ +#DEFCONT ;\ +#DEFCONT \ LD A,(_CIST) +#DEFCONT \ OR A +#DEFCONT \ JR NZ,_OVFL +#DEFCONT \ LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ LD A,1 +#DEFCONT \ LD (_CIST),A +#DEFCONT \ IN A,(C) +#DEFCONT \ LD (_CICH),A +#DEFCONT \ OR $FF +#DEFCONT \ RET +#DEFCONT \_OVFL:XOR A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT ;\ +#DEFCONT \PIOIN:CALL PIOIST +#DEFCONT \ JR Z,PIOIN +#DEFCONT \ LD A,(_CICH) +#DEFCONT \ LD E,A +#DEFCONT \ XOR A +#DEFCONT \ LD (_CIST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; If THERE A CHARACTER \ +#DEFCONT ; AVAILABLE? RETURN NUMBER \ +#DEFCONT ; IN A - 0 OR 1 \ +#DEFCONT ;\ +#DEFCONT \PIOIST:LD A,(_CIST) +#DEFCONT \ AND 00000001B +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; CIST : 01 = CHARACTER READY ELSE NOT READY \ +#DEFCONT ; CISH : CHARACTER STORED BY INTERRUPT \ +#DEFCONT ;\ +#DEFCONT \_CIST .DB 00 +#DEFCONT \_CICH .DB 00 +; +PIOIVT0:.MODULE PIOIVT0 +PIOMIVT(PIO0IN,PI0_IST,PRTTAB+0) +PIOIVT1:.MODULE PIOIVT1 +PIOMIVT(PIO1IN,PI1_IST,PRTTAB+1) +PIOIVT2:.MODULE PIOIVT2 +PIOMIVT(PIO2IN,PI2_IST,PRTTAB+2) +PIOIVT3:.MODULE PIOIVT3 +PIOMIVT(PIO3IN,PI3_IST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; OUTPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS +; +; AN INTERRUPT IS GENERATED WHEN THE RECEIVING DEVICE CAN ACCEPT A CHARACTER +; +#DEFINE PIOMOVT(PIOOUT,PIOOST,PIOPRT) \ +#DEFCONT ;\ +#DEFCONT ; RETURN IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTER (COST = 00) \ +#DEFCONT ;\ +#DEFCONT ; IF ZERO CHARACTERS READY +#DEFCONT ; (COST = 01) CHANGE STATUS TO \ +#DEFCONT ; WAITING FOR CHARACTER (COST 00) \ +#DEFCONT ;\ +#DEFCONT ; IF A CHARACTER IS READY THEN \ +#DEFCONT ; OUTPUT AND CHANGE STATUS TO \ +#DEFCONT ; ZERO CHARACTERS READY \ +#DEFCONT ;\ +#DEFCONT \ LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ RET M +#DEFCONT \ JR Z,_WFC +#DEFCONT \ LD A,(_COCH) +#DEFCONT \ LD E,A +#DEFCONT \_ONOW:LD A,(PIOPRT) +#DEFCONT \ LD C,A +#DEFCONT \ OUT (C),E +#DEFCONT \ LD A,1 +#DEFCONT \_WFC: LD (_COST),A +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; WAIT FOR SPACE FOR THE CHARACTER\ +#DEFCONT ; IF WE ARE WAITING FOR A \ +#DEFCONT ; CHARACTRE THEN OUTPUT IT NOW \ +#DEFCONT ; OTHERWISE STORE IT UNTIL THE \ +#DEFCONT ; INTERRUPT CALLS FOR IT \ +#DEFCONT ;\ +#DEFCONT \PIOOUT:LD A,(_COST) +#DEFCONT \ CP 2 +#DEFCONT \ JR C,_ONOW +#DEFCONT \ LD A,E +#DEFCONT \ LD (_COCH),A +#DEFCONT \ LD A,2 +#DEFCONT \ LD (_COST),A +#DEFCONT \ JR PIOOUT +#DEFCONT ;\ +#DEFCONT ; RETURN WITH NUMBER OF \ +#DEFCONT ; CHARACTERS AVAILABLE 0 or 1 \ +#DEFCONT ;\ +#DEFCONT \PIOOST:LD A,(_COST) +#DEFCONT \ DEC A +#DEFCONT \ DEC A +#DEFCONT \ RET Z +#DEFCONT \ LD A,1 +#DEFCONT \ RET +#DEFCONT ;\ +#DEFCONT ; COST : 00 WAITING FOR CHARACTER\ +#DEFCONT ; 01 ZERO CHARACTERS READY\ +#DEFCONT ; 02 ONE CHARACTER READY \ +#DEFCONT ; COCH : CHARACTER TO OUTPUT \ +#DEFCONT ;\ +#DEFCONT \_COST .DB 01 +#DEFCONT \_COCH .DB 00 +; +PIOOVT0:.MODULE PIOOVT0 +PIOMOVT(PIO0OUT,PI0_OST,PRTTAB+0) +PIOOVT1:.MODULE PIOOVT1 +PIOMOVT(PIO1OUT,PI1_OST,PRTTAB+1) +PIOOVT2:.MODULE PIOOVT2 +PIOMOVT(PIO2OUT,PI2_OST,PRTTAB+2) +PIOOVT3:.MODULE PIOOVT3 +PIOMOVT(PIO3OUT,PI3_OST,PRTTAB+3) +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT OUTPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS RETURN ERROR, CHARACTER RETURNED IS UNDEFINED. +; OUTPUT WILL ALWAYS RETURN SUCCESS +; INPUT-STATUS WILL ALWAYS RETURN 0 CHARACTERS IN BUFFER. +; OUTPUT-STATUS WILL ALWAYS RETURN 1 CHARACTER SPACE IN BUFFER. -SET_BYE: - XOR A ; SIGNAL SUCCESS +PIOSHO_IN: + LD A,1 RET -; -PIO_ZP0: -PIO_ZP1: -PIO_4P0: -PIO_4P1: -PIO_4P2: -PIO_4P3: -PIO_4P4: -PIO_4P5: -PIO_4P6: -PIO_4P7:OR $FF ; NZ SET TO INDICATE INT HANDLED +; +PIOSHO_OUT: + LD C,(IY+3) + OUT (C),E + XOR A + RET +; +PIOSHO_IST: XOR A + RET +; +PIOSH_OST: + LD A,1 + RET +; +;----------------------------------------------------------------------------- +; +; NON INTERRUPT INPUT ROUTINE - SHARED +; +; INPUT WILL ALWAYS A CHARACTER AND SUCCESS. +; OUTPUT WILL ALWAYS RETURN FAILURE +; INPUT STATUS WILL ALWAYS RETURN 1 CHARACTER IN BUFFER. +;OUTPUT-STATUS WILL ALWAYS RETURN 0 CHARACTER SPACE IN BUFFER. +; +PIOSHI_IN: + LD C,(IY+3) + IN A,(C) + LD E,A + XOR A RET ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD -; WE GET AND RETURN THE CONFIGURATION WORD IN DE +PIOSHI_OUT: + LD A,1 + RET +; +PIOSH_IST: + LD A,1 + RET +; +PIOSHI_OST: + XOR A + RET +; +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE ; PIO_QUERY: PPI_QUERY: @@ -367,17 +685,37 @@ PPI_QUERY: XOR A ; SIGNAL SUCCESS RET ; -; ON ENTRY IY POINTS TO THE DEVICE RECORD -; FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE -; INDICATES PARALLEL PORT IF 1 SO WE SET IT. -; +;----------------------------------------------------------------------------- +; +; ON ENTRY IY POINTS TO THE DEVICE RECORD. FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE +; INDICATES PARALLEL PORT IF 1 SO WE SET IT. COMMON TO ALL PORTS +; PIO_DEVICE: PPI_DEVICE: LD D,CIODEV_PIO ; D := DEVICE TYPE LD E,(IY) ; E := PHYSICAL UNIT LD C,$40 ; C := ATTRIBUTE XOR A ; SIGNAL SUCCESS + RET +; +INTMATRIX: + .DW PIO0IN, PIO0OUT, PI0_IST, PI0_OST + .DW PIO1IN, PIO1OUT, PI1_IST, PI1_OST + .DW PIO2IN, PIO2OUT, PI2_IST, PI2_OST + .DW PIO3IN, PIO3OUT, PI3_IST, PI3_OST +POLMATRIX: + .DW PIOSHO_IN, PIOSHO_OUT, PIOSHO_IST, PIOSH_OST ; OUTPUT + .DW PIOSHI_IN, PIOSHI_OUT, PIOSH_IST, PIOSHI_OST ; INPUT + .DW 0,0,0,0 ; BIDIR + .DW 0,0,0,0 ; BIT MODE + +SET_8255: RET +; +SET_BYE: + XOR A ; SIGNAL SUCCESS + RET + ; ------------------------------------ ; i8255 FUNCTION TABLE ROUTINES @@ -438,7 +776,14 @@ PIO_PRTCFG: LD D,(IY+5) ; ... WORD TO DE CALL PS_PRTPC0 ; PRINT CONFIG ; - XOR A + LD A,(IY+4) ; PRINT + BIT 2,A ; ALLOCATED + JR Z,NOINT ; INTERRUPT + PRTS("/i$") + LD A,(IY+4) + AND 00000011B + CALL PRTDECB +NOINT: XOR A RET ; ; WORKING VARIABLES @@ -460,237 +805,176 @@ PIO_STR_PORT .DB "IO Port$" ; ; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS ; -#DEFINE DEFPIO(MPIO_TYPE,MPIO_BASE,MPIO_CH0,MPIO_CH1,MPIO_CH0X,MPIO_CH1X,MPIO_FT0,MPIO_FT1,MPIO_IN0,MPIO_IN1) \ +; 32 BYTE DATA STRUCTURE FOR EACH PORT +; +; .DB 0 ; IY+0 CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) +; .DB 0 ; IY+1 PIO TYPE (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+2 PIO CHANNEL (SET AT ASSEMBLY, FIXED) +; .DB PIOBASE+2 ; IY+3 BASE DATA PORT (SET AT ASSEMBLY, FIXED) +; .DB 0 ; IY+4 SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) +; .DB 0 ; IY+5 SPW - MODE, INTERRUPT (SET AT ASSEMBLY, SET WITH INIT) +; .DW 0 ; IY+6/7 FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) +; .DW PIO_IN ; IY+8 ADDR FOR DEVICE INPUT (SET WITH INIT) +; .DW PIO_OUT ; IY+10 ADDR FOR DEVICE OUTPUT (SET WITH INIT) +; .DW PIO_IST ; IY+12 ADDR FOR DEVICE INPUT STATUS (SET WITH INIT) +; .DW PIO_OST ; IY+14 ADDR FOR DEVICE OUTPUT STATUS (SET WITH INIT) +; .DW PIO_INITDEV ; IY+16 ADDR FOR INITIALIZE DEVICE ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_QUERY ; IY+18 ADDR FOR QUERY DEVICE RECORD ROUTINE (SET AT ASSEMBLY, FIXED) +; .DW PIO_DEVICE ; IY+20 ADDR FOR DEVICE TYPE ROUTINE (SET AT ASSEMBLY, FIXED) +; .FILL 10 + +; SETUP PARAMETER WORD: +; +; +-------------------------------+ +-------+-----------+---+-------+ +; | BIT CONTROL | | MODE | | A | INT | +; +-------------------------------+ --------------------+-----------+ +; F E D C B A 9 8 7 6 5 4 3 2 1 0 +; -- MSB (D REGISTER) -- -- LSB (E REGISTER) -- +; +; +; MSB = BIT CONTROL MAP USE IN MODE 3 +; +; MODE B7 B6 = 00 Mode 0 Output +; 01 Mode 1 Input +; 10 Mode 2 Bidir +; 11 Mode 3 Bit Mode +; +; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED +; = 1 IS ALLOCATED +; +; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0 +; 01 IVT_PIO1 +; 10 IVT_PIO2 +; 11 IVT_PIO3 +; +#DEFINE DEFPIO(MPIOBASE,MPIOCH0,MPIOCH1,MPIOCH0X,MPIOCH1X,MPIOIN0,MPIOIN1) \ #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB PIO_ZPIO #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_BASE -#DEFCONT \ .DB (MPIO_CH0 | 00001000B | MPIO_IN0) -#DEFCONT \ .DB MPIO_CH0X -#DEFCONT \ .DW MPIO_FT0 +#DEFCONT \ .DB MPIOBASE +#DEFCONT \ .DB (MPIOCH0|MPIOIN0) +#DEFCONT \ .DB MPIOCH0X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 10 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPIO_TYPE +#DEFCONT \ .DB PIO_ZPIO #DEFCONT \ .DB 1 -#DEFCONT \ .DB MPIO_BASE+1 -#DEFCONT \ .DB (MPIO_CH1 | 00010000B | MPIO_IN1) -#DEFCONT \ .DB MPIO_CH1X -#DEFCONT \ .DW MPIO_FT1 +#DEFCONT \ .DB MPIOBASE+1 +#DEFCONT \ .DB (MPIOCH1|MPIOIN1) +#DEFCONT \ .DB MPIOCH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE +#DEFCONT \ .FILL 10 ; ; i8255 PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. THREE PORTS ; -#DEFINE DEFPPI(MPPI_TYPE,MPPI_BASE,MPPI_CH1,MPPI_CH2,MPPI_CH3,MPPI_CH1X,MPPI_CH2X,MPPI_CH3X) \ +#DEFINE DEFPPI(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \ #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_BASE+0 -#DEFCONT \ .DB (MPPI_CH1 | 00001000B) -#DEFCONT \ .DB MPPI_CH1X -#DEFCONT \ .DW +#DEFCONT \ .DB MPPIBASE +#DEFCONT \ .DB (MPPICH1|00001000B) +#DEFCONT \ .DB MPPICH1X +#DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 10 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 1 -#DEFCONT \ .DB MPPI_BASE+2 -#DEFCONT \ .DB (MPPI_CH2 | 00010000B) -#DEFCONT \ .DB MPPI_CH2X +#DEFCONT \ .DB MPPIBASE+2 +#DEFCONT \ .DB (MPPICH2|00010000B) +#DEFCONT \ .DB MPPICH2X #DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 10 #DEFCONT \ .DB 0 -#DEFCONT \ .DB MPPI_TYPE +#DEFCONT \ .DB PIO_8255 #DEFCONT \ .DB 2 -#DEFCONT \ .DB MPPI_BASE+4 -#DEFCONT \ .DB (MPPI_CH3 | 00100000B) -#DEFCONT \ .DB MPPI_CH3X +#DEFCONT \ .DB MPPIBASE+4 +#DEFCONT \ .DB (MPPICH3|00100000B) +#DEFCONT \ .DB MPPICH3X #DEFCONT \ .DW 0 +#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE +#DEFCONT \ .FILL 10 ; ; HERE WE ACTUALLY DEFINE THE HARDWARE THAT THE HBIOS CAN ACCESS ; THE INIT ROUTINES READ AND SET THE INITIAL MODES FROM THIS INFO ; PIO_CFG: - -#IF PIO_ZP -DEFPIO(PIO_ZPIO,PIOZBASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO0FT,PIO1FT,INT_Y,INT_N) -DEFPIO(PIO_ZPIO,PIOZBASE+4,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO2FT,PIO3FT,INT_Y,INT_N) -#ENDIF +; #IF PIO_4P -DEFPIO(PIO_ZPIO,PIO4BASE+0,M_Output,M_BitCtrl,M_BitAllOut,M_BitAllOut,PIO4FT,PIO5FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+4,M_Output,M_Input,M_BitAllOut,M_BitAllOut,PIO6FT,PIO7FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,PIO8FT,PIO9FT,INT_N,INT_N) -DEFPIO(PIO_ZPIO,PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,PIO10FT,PIO11FT,INT_N,INT_N) +DEFPIO(PIO4BASE+0,M_Output,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+4,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,INT_N,INT_N) +#ENDIF +#IF PIO_ZP +DEFPIO(PIOZBASE+0,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N) +DEFPIO(PIOZBASE+4,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N) #ENDIF ; PPI_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC)) #IF PPI_SBC -DEFPPI(PIO_8255,PPIBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) +DEFPPI(PPIBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut) #ENDIF ; -; ; PIO CHANNEL A -; .DB 0 ; CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED) -; .DB 0 ; PIO TYPE (SET AT ASSEMBLY, FIXED) -; .DB 0 ; FREE -; .DB PIOBASE+2 ; BASE DATA PORT (DATA PORT) (SET AT ASSEMBLY, FIXED) -; .DB 0 ; SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT) - .DB 0 ; SPW - MODE, CHANNEL (SET AT ASSEMBLY, SET WITH INIT, CHANNEL FIXED) -; .DW 0 ; FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT) - -PIO_CNT .EQU ($ - PIO_CFG) / 8 +PIO_CNT .EQU ($ - PIO_CFG) / 32 ; - -; DRIVER FUNCTION TABLE FOR Z80 PIO's -; EACH PIO NEEDS A FUNCTION TABLE -; ECB-ZP : PIO0FT-PIO3FT -; ECB-4P : PIO4FT-PIO11FT - -PIO_FNTBL: +;------------------------------------------------------------------- +; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON. +; C IS THE UNIT NUMBER +;------------------------------------------------------------------- ; -#IF PIO_ZP -PIO0FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO0FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO1FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO1FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO2FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO2FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO3FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO3FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF +;PIO_INITUNIT: +; LD A,C ; SET THE UNIT NUMBER +; LD (IY),A ; -#IF PIO_4P -PIO4FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO4FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO5FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO5FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO6FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO6FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO7FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO7FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO8FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO8FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO9FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO9FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO10FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO10FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -PIO11FT .DW PIO_IN - .DW PIO_OUT - .DW PIO_IST - .DW PIO_OST - .DW PIO_INITDEV - .DW PIO_QUERY - .DW PIO_DEVICE -#IF (($ - PIO11FT) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PIO FUNCTION TABLE ***\n" -#ENDIF -#ENDIF +; LD DE,-1 ; LEAVE CONFIG ALONE +; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN +; XOR A ; SIGNAL SUCCESS +; RET ; AND RETURN ; -; DRIVER FUNCTION TABLE FOR i8255's -; -PPI_FNTBL: - .DW PPI_IN - .DW PPI_OUT - .DW PPI_IST - .DW PPI_OST - .DW PPI_INITDEV - .DW PPI_QUERY - .DW PPI_DEVICE -#IF (($ - PPI_FNTBL) != (CIO_FNCNT * 2)) - .ECHO "*** INVALID PPI FUNCTION TABLE ***\n" -#ENDIF +PIO_INIT: +; CALL SPK_BEEP + LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS + LD C,0 ; INDEX INTO PIO CONFIG TABLE +PIO_INIT1: + PUSH BC ; SAVE LOOP CONTROL + + LD A,C ; PHYSICAL UNIT TO A + RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES) + RLCA ; ... + RLCA ; ... TO GET OFFSET INTO CFG TABLE + RLCA +; RLCA + LD HL,PIO_CFG ; POINT TO START OF CFG TABLE + PUSH AF + CALL ADDHLA ; HL := ENTRY ADDRESS + POP AF + CALL ADDHLA ; HL := ENTRY ADDRESS + PUSH HL ; COPY CFG DATA PTR + POP IY ; ... TO IY + + 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 ; -; 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 + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +SET_PORT: + ; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT + LD C,(IY+3) + OUT (C),A + XOR A + RET