mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
999 lines
25 KiB
999 lines
25 KiB
; PIO driver sets up the parallel port as a subtype of Serial/Char device.
|
|
;
|
|
;
|
|
; HBIOS initializes driver by:
|
|
;
|
|
; 1) Calling Pre-initialization
|
|
;
|
|
; This involves setting up all the data structures describing the devices.
|
|
; If possible, do a hardware test to verify it is available for adding to available devices.
|
|
;
|
|
; 2) Calling device initialization.
|
|
;
|
|
; Hardware initialization.
|
|
; Configure to initial state or to a new state.
|
|
;
|
|
; Implementation limitations:
|
|
;
|
|
; The fully functionality of the Z80 PIO can only be realized by using Z80 interrupt mode 2.
|
|
; Registers cannot be interrogated for interrupts status and the originating interrupt
|
|
; device cannot be determine.
|
|
;
|
|
; Full implementation of IM2 functionality for an ECB-ZP and ECB-4P board would require the
|
|
; allocation of an interrupt handler for each chip channel. Thus, 12 interrupt handlers
|
|
; would be required to support this configuration. As the HBIOS only has an allocation of
|
|
; 16, a full implmentation is impractical.
|
|
;
|
|
; The compromise solution is to allow 4 interrupts for the PIO driver. All remaining PIO's
|
|
; are limited to Bit mode or blind read and write to the input/output ports.
|
|
;
|
|
; Zilog PIO reset state:
|
|
;
|
|
; Both port mask registers are reset to inhibit All port data bits.
|
|
; Port data bus lines are set to a high-impedance state and the Ready "handshake"
|
|
; Mode 1 (output) is automatically selected.
|
|
; The vector address registers are not reset.
|
|
; Both port interrupt enable flip-flops are reset.
|
|
; Both port output registers are reset.
|
|
;
|
|
; Register addressing for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively.
|
|
;
|
|
; PIO ----ZP---- ----4P----
|
|
; 0 DATA 0 90h DATA 0 B8h
|
|
; 0 DATA 1 91h DATA 1 B9h
|
|
; 0 CMD 0 92h CMD 0 BAh
|
|
; 0 CMD 1 93h CMD 1 BBh
|
|
; 1 DATA 0 94h DATA 0 BCh
|
|
; 1 DATA 1 95h DATA 1 BDh
|
|
; 1 CMD 0 96h CMD 0 BEh
|
|
; 1 CMD 1 97h CMD 1 BFh
|
|
; 2 DATA 0 C0h
|
|
; 2 DATA 1 C1h
|
|
; 2 CMD 0 C2h
|
|
; 2 CMD 1 C3h
|
|
; 3 DATA 0 C4h
|
|
; 3 DATA 1 C5h
|
|
; 3 CMD 0 C6h
|
|
; 3 CMD 1 C7h
|
|
;
|
|
PIODEBUG .EQU 1
|
|
;
|
|
M_Output .EQU $00 << 6
|
|
M_Input .EQU $01 << 6
|
|
M_Bidir .EQU $02 << 6
|
|
M_BitCtrl .EQU $03 << 6
|
|
M_BitAllIn .EQU $FF
|
|
M_BitAllOut .EQU $00
|
|
;
|
|
PIO_NONE .EQU 0
|
|
PIO_ZPIO .EQU 1
|
|
PIO_8255 .EQU 2
|
|
PIO_PORT .EQU 3
|
|
|
|
; SET MAXIMUM NUMBER OF INTERRUPTS AVAILABLE FOR ALL
|
|
; ENSURE INTERRUPTS ARE NOT TURNED ON IF IM2 IS NOT SET.
|
|
|
|
INT_ALLOC .DB 0
|
|
INT_N .EQU 00000000B
|
|
#IF (INTMODE == 2)
|
|
INT_Y .EQU 00000100B
|
|
INT_ALLOW .EQU 4
|
|
#ELSE
|
|
INT_Y .EQU INT_N
|
|
INT_ALLOW .EQU 0
|
|
#ENDIF
|
|
;
|
|
INT0 .EQU 00000000B
|
|
INT1 .EQU 00000001B
|
|
INT2 .EQU 00000010B
|
|
INT3 .EQU 00000011B
|
|
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
;
|
|
; PIO_CNT HOLDS THE NUMBER OF DEVICED CALCULATED FROM THE NUMBER OF DEFPIO MACROS
|
|
; PIO_CNT SHOULD INCREASE BY 2 FOR EVERY PIO CHIP ADDED.
|
|
;
|
|
; PIO_PREINIT WILL READ THROUGH ALL PIOCFG TABLES AND CONFIGURE EACH TABLE.
|
|
; IT WITH THEN CALL PIO_INITUNIT TO INITIALIZE EACH DEVICE TO ITS DEFAULT STATE
|
|
;
|
|
; EXPECTS NOTHING ON ENTRY
|
|
;
|
|
PIO_PREINIT:
|
|
CALL NEWLINE ;D
|
|
LD B,PIO_CNT ; LOOP CONTROL
|
|
LD C,0 ; PHYSICAL UNIT INDEX
|
|
XOR A ; ZERO TO ACCUM
|
|
; LD (PIO_DEV),A ; CURRENT DEVICE NUMBER
|
|
LD (INT_ALLOC),A ; START WITH NO INTERRUPTS ALLOCATED
|
|
PIO_PREINIT0:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
; LD A,C ; INITIALIZE THE UNIT
|
|
|
|
; PUSH AF ;D
|
|
; LD A,'u' ;D
|
|
; CALL COUT ;D
|
|
; POP AF ;D
|
|
; CALL PRTHEXBYTE ;D UNIT
|
|
; CALL PC_SPACE ;D
|
|
|
|
; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES)
|
|
; RLCA ; ...
|
|
; RLCA ; ... TO GET OFFSET INTO CFG TABLE
|
|
; RLCA
|
|
;; RLCA
|
|
; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE
|
|
; PUSH AF
|
|
; CALL ADDHLA ; HL := ENTRY ADDRESS
|
|
; POP AF
|
|
; CALL ADDHLA ; HL := ENTRY ADDRESS
|
|
; PUSH HL ; SAVE IT
|
|
; POP IY ; ... TO IY
|
|
|
|
CALL IDXCFG
|
|
|
|
LD (HL),C
|
|
|
|
PUSH AF ;D
|
|
LD A,'c' ;D
|
|
CALL COUT ;D
|
|
POP AF ;D
|
|
PUSH BC ;D
|
|
PUSH HL ;D
|
|
POP BC ;D
|
|
CALL PRTHEXWORD ;D CONFIG TABLE
|
|
CALL PC_SPACE ;D
|
|
POP BC ;D
|
|
|
|
LD A,(IY+1) ; GET THE PIO TYPE DETECTED
|
|
CP PIO_PORT ; SET FLAGS
|
|
|
|
PUSH AF ;D
|
|
LD A,'t' ;D
|
|
CALL COUT ;D
|
|
POP AF ;D
|
|
CALL PRTHEXBYTE ;D TYPE
|
|
CALL PC_SPACE ;D
|
|
|
|
; JR Z,BADINIT
|
|
|
|
; PUSH BC ; SAVE LOOP CONTROL
|
|
; LD BC,PIO_FNTBL ; BC := FUNCTION TABLE ADDRESS
|
|
; DEC A
|
|
; JR Z,TYPFND ; SKIP IT IF NOTHING FOUND
|
|
; LD BC,PPI_FNTBL ; BC := FUNCTION TABLE ADDRESS
|
|
; DEC A
|
|
; JR Z,TYPFND ; ADD ENTRY IF PIO FOUND, BC:DE
|
|
; LD BC,PRT_FNTBL
|
|
; DEC A
|
|
; JR Z,TYPFND
|
|
; POP BC
|
|
; JR BADINIT
|
|
|
|
PUSH HL
|
|
LD DE,-1 ; INITIALIZE THIS DEVICE WITH
|
|
CALL PIO_INITDEV ; DEFAULT VALUES
|
|
POP HL
|
|
|
|
; JR NZ,SKPINIT
|
|
|
|
; AT THIS POINT WE KNOW WE
|
|
; HAVE A VALID DEVICE SO ADD IT
|
|
|
|
LD A,8 ; CALCULATE THE FUNCTION TABLE
|
|
CALL ADDHLA ; POSITION WHICH FOLLOWS THE
|
|
PUSH HL ; CONFIGURATION TABLE OF EACH
|
|
POP BC ; DEVICE
|
|
|
|
TYPFND: PUSH AF ;D
|
|
LD A,'f' ;D
|
|
CALL COUT ;D
|
|
POP AF ;D
|
|
PUSH BC ;D
|
|
CALL PRTHEXWORD ;D FUNCTION TABLE
|
|
POP BC ;D
|
|
CALL NEWLINE ;D
|
|
|
|
PUSH IY ; ADD ENTRY IF PIO FOUND, BC:DE
|
|
POP DE ; BC: DRIVER FUNCTION TABLE
|
|
CALL CIO_ADDENT ; DE: ADDRESS OF UNIT INSTANCE DATA
|
|
|
|
BADINIT:POP BC ; RESTORE LOOP CONTROL
|
|
|
|
INC C ; NEXT PHYSICAL UNIT
|
|
SKPINIT:DJNZ PIO_PREINIT0 ; LOOP UNTIL DONE
|
|
|
|
PUSH AF ;D
|
|
PRTS("INTS=$") ;D
|
|
LD A,(INT_ALLOC) ;D
|
|
CALL PRTHEXBYTE ;D
|
|
POP AF ;D
|
|
PUSH DE ;D
|
|
LD DE,CIO_TBL-3 ;D
|
|
CALL DUMP_BUFFER ;D
|
|
POP DE ;D
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
; INDEX INTO THE CONFIG TABLE
|
|
; ON ENTRY C = UNIT NUMBER
|
|
; ON EXIT IY = CONFIG DATA POINTER
|
|
; ON EXIT DE = CONFIG TABLE START
|
|
;
|
|
; EACH CONFIG TABLE IS 24 BYTES LONG
|
|
;
|
|
CFG_SIZ .EQU 24
|
|
;
|
|
IDXCFG: LD A,C
|
|
RLCA ; X 2
|
|
RLCA ; X 4
|
|
RLCA ; X 8
|
|
LD H,0
|
|
LD L,A ; HL = X 8
|
|
PUSH HL
|
|
ADD HL,HL ; HL = X 16
|
|
POP DE
|
|
ADD HL,DE ; HL = X 24
|
|
LD DE,PIO_CFG
|
|
ADD HL,DE
|
|
PUSH HL ; COPY CFG DATA PTR
|
|
POP IY ; ... TO IY
|
|
RET
|
|
|
|
; PIO_INITDEV - INITIALIZE DEVICE
|
|
;
|
|
; IF DE = FFFF THEN THE SETUP PARAMETER WORD WILL BE READ FROM THE DEVICE CONFIGURATION
|
|
; TABLE POINTED TO BY IY AND THE PIO PORT WILL BE PROGRAMMED BASED ON THAT CONFIGURATION.
|
|
;
|
|
; OTHERWISE THE PIO PORT WILL BE PROGRAMMED BY THE SETUP PARAMETER WORD IN DE AND THIS
|
|
; WILL BE SAVED IN THE DEVICE CONFIGURATION TABLE POINTED TO BY IY.
|
|
;
|
|
; ALL OTHER CONFIGURATION OF THE DEVICE CONFIGURATION TABLE IS DONE UPSTEAM BY PIO_PREINIT
|
|
|
|
PIO_INITDEV:
|
|
; TEST FOR -1 (FFFF) WHICH MEANS USE CURRENT CONFIG (JUST REINIT)
|
|
LD A,D ; TEST DE FOR
|
|
AND E ; ... VALUE OF -1
|
|
INC A ; ... SO Z SET IF -1
|
|
JR NZ,PIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG
|
|
PIO_INITDEV0:
|
|
; LOAD EXISTING CONFIG (DCW) TO REINIT
|
|
LD E,(IY+4) ; LOW BYTE
|
|
LD D,(IY+5) ; HIGH BYTE
|
|
;
|
|
PIO_INITDEV1: ; WHICH DEVICE TYPE?
|
|
LD A,(IY+1)
|
|
CP PIO_ZPIO
|
|
JR Z,SETPIO0
|
|
CP PIO_8255
|
|
JP Z,SET_8255
|
|
CP PIO_PORT
|
|
JP Z,SET_PORT
|
|
BAD_SET:OR $FF ; UNKNOWN DEVICE
|
|
RET
|
|
|
|
SETPIO0:LD A,E ; GET MODE
|
|
AND 11000000B ; BITS (B7B6)
|
|
CP 10000000B ; IS IT BIDIR?
|
|
JR NZ,SETPIO1
|
|
LD A,(IY+2) ; GET CHANNEL
|
|
OR A
|
|
JR NZ,BAD_SET ; CAN'T DO ON CH1
|
|
|
|
; VALIDATE INTERRUPT REQUEST
|
|
; GRANT INTERRUPT IF THERE IS A FREE INTERRUPT
|
|
; GRANT INTERRUPT IF AN INTERRUPT IS ALREADY ALLOCATED TO THIS UNIT
|
|
|
|
SETPIO1:PUSH AF ;D
|
|
LD A,'[' ;D
|
|
CALL COUT ;D
|
|
LD A,(IY) ;D
|
|
CALL PRTHEXBYTE ;D
|
|
LD A,']' ;D
|
|
CALL COUT ;D
|
|
POP AF ;D
|
|
|
|
BIT 2,E ; SKIP IF WE ARE NOT REQUESTING
|
|
JP Z,SETPIO2 ; AN INTERRUPT
|
|
|
|
PRTS("[INTREQ]$") ;D
|
|
|
|
; LD A,(IY+4) ; GET CURRENT INTERRUPT SETTING
|
|
; BIT 2,A ; SKIP IF IT IS ALREADY
|
|
; JP NZ,SETPIO2 ; ALLOCATED TO THIS UNIT
|
|
|
|
LD A,(INT_ALLOC) ; WE NEED TO ALLOCATE AN
|
|
CP INT_ALLOW ; INTERRUPT. DO WE HAVE
|
|
JR NC,BAD_SET ; ONE FREE?
|
|
|
|
PRTS("[ALLOCINT]$") ;D
|
|
|
|
; WHICH INTERRUPT IS FREE ?
|
|
; SCAN THROUGH THE CFG TABLES
|
|
; AND FIND A FREE ONE
|
|
|
|
PUSH AF ; NESTED LOOP
|
|
LD DE,CFG_SIZ ; OUTSIDE LOOP IS INTERRUPT
|
|
LD B,INT_ALLOW ; INSIDE LOOP IS DEVICE
|
|
SETPIOP: LD C,B
|
|
DEC C
|
|
PUSH BC
|
|
LD B,PIO_CNT
|
|
LD HL,PIO_CFG+4
|
|
SETPIOX: LD A,(HL)
|
|
BIT 2,A ; JUMP TO NEXT DEVICE
|
|
JR Z,SETPIOY ; IF NO INTERRUPT ON
|
|
AND 00000011B ; THIS DEVICE
|
|
|
|
CP C ; IF WE MATCH AN INTERRUPT HERE THEN IT IS NOT FREE.
|
|
JR NZ,SETPIOY ; SO EXIT INSIDE LOOP AND TRY NEXT INTERRUPT
|
|
|
|
XOR A ; WE MATCH INT 0 - IF WE ARE CHECKING FOR IT THEN
|
|
OR C ; WE REGARD IS AS FREE.
|
|
JR NZ,SETPIOZ
|
|
|
|
SETPIOY: ADD HL,DE
|
|
DJNZ SETPIOX
|
|
|
|
JR SETPIOQ ; WE GET HERE IF THE CURRENT INTERRUPT
|
|
; WAS NOT MATCHED SO IT IS FREE
|
|
SETPIOZ: POP BC
|
|
DJNZ SETPIOP
|
|
POP AF
|
|
|
|
PRTS("[NONEFREE]$")
|
|
RET
|
|
|
|
SETPIOQ:PUSH AF ; AVAILABLE INTERRUPT IS IN C
|
|
PRTS("[FREE]=$")
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
POP AF
|
|
|
|
POP AF
|
|
POP AF
|
|
|
|
SETPIOR:LD HL,INT_ALLOC ; INCREASE THE COUNT
|
|
INC (HL) ; OF USED INTERRUPTS
|
|
LD A,(HL)
|
|
|
|
; LD A,(IY) ; IS THIS UNIT
|
|
; INC A ; UNITIALIZED?
|
|
; JR Z,SETPIO6
|
|
|
|
LD A,(IY+4) ; IT IS UNITIALIZED SO
|
|
OR C ; SAVE THE ALLOCATES
|
|
LD (IY+4),A ; INTERRUPT
|
|
;
|
|
; FOR THIS DEVICE AND INTERRUPT, UPDATE THE CONFIG TABLE FOR THIS DEVICE.
|
|
; PIO_IN, PIO_OUT, PIO_IST, PIO_OST ENTRIES NEED TO BE REDIRECTED.
|
|
; INTERRUPT VECTOR NEEDS TO BE UPDATED
|
|
;
|
|
LD A,(IY+0)
|
|
LD HL,0
|
|
; SETUP PIO INTERRUPT VECTOR IN IVT
|
|
LD HL,HBX_IV09+1
|
|
|
|
; CALL SPK_BEEP
|
|
;
|
|
SETPIO6:RET
|
|
|
|
; EXIT WITH FREE INTERRUPT IN C
|
|
|
|
LD A,C
|
|
LD (INT_ALLOC),A
|
|
|
|
LD A,E
|
|
AND 11000000B
|
|
OR 00000100B
|
|
OR C
|
|
LD E,A
|
|
LD (IY+5),A
|
|
;
|
|
; TODO: DEALLOCATE AN INTERRUPT
|
|
;
|
|
; LD A,(INT_ALLOC)
|
|
; DEC A
|
|
; LD (INT_ALLOC),A
|
|
;
|
|
SETPIO2:
|
|
|
|
; DE CONTAINS THE MODE IF INTERRUPT ROUTINE SKIPPED
|
|
|
|
PRTS("[NOINTREQ]$") ;D
|
|
|
|
; LD A,(IY+4)
|
|
LD A,E ; GET MODE AND CREATE COMMAND
|
|
AND 11000000B ; $B0
|
|
OR 00001111B ; $0F
|
|
|
|
LD C,(IY+3) ; GET DATA PORT
|
|
INC C ; POINT TO CMD
|
|
INC C ; PORT
|
|
OUT (C),A ; SET MODE
|
|
CP (M_BitCtrl | $0F) ; IF MODE 3
|
|
JR NZ,SETPIO3
|
|
LD A,(IY+5) ; SET I/O DIRECTION
|
|
OUT (C),A ; FOR MODE 3
|
|
|
|
SETPIO3:; INTERUPT HANDLING
|
|
|
|
JP SETPIO4
|
|
|
|
; SETUP THE INTERRUPT VECTOR
|
|
|
|
LD A,E
|
|
AND 00000011B
|
|
; DEC A ; INDEX INTO THE
|
|
ADD A,A ; THE VECTOR TABLE
|
|
ADD A,A ;
|
|
LD C,A
|
|
LD B,0
|
|
LD HL,HBX_IV09+1
|
|
ADD HL,BC ; GET THE ADDRESS OF
|
|
PUSH DE
|
|
LD D,(HL) ; THAT INTERRUPT
|
|
INC HL ; HANDLER
|
|
LD E,(HL)
|
|
LD HL,0 ;HBX_IVT+IVT_PIO0 ; POPULATE THE
|
|
LD A,L ; GET LOW BYTE OF IVT ADDRESS
|
|
ADD HL,BC ; INTERRUPT TABLE
|
|
LD (HL),D ; WITH THE INTERRUPT
|
|
INC HL ; HANDLER ADDRESS FOR
|
|
LD (HL),E ; THIS UNIT
|
|
POP DE
|
|
LD HL,INT_ALLOC
|
|
LD C,(HL)
|
|
LD B,0
|
|
LD HL,PRTTAB-1 ; SAVE THE DATA
|
|
ADD HL,BC ; PORT FOR EACH INTERRUPT
|
|
LD C,(IY+3)
|
|
LD (HL),C
|
|
|
|
INC C ; POINT TO CMD PORT
|
|
INC C
|
|
DI ; SET THE VECTOR ADDRESS
|
|
OUT (C),A
|
|
|
|
; LD A,10000011B ; ENABLE INTERRUPTS ON
|
|
OUT (C),A ; THIS UNIT
|
|
EI
|
|
; JR GUD_SET
|
|
;
|
|
SETPIO4:LD A,00000111B ; $07
|
|
OUT (C),A ; NO INTERRUPTS
|
|
;
|
|
; SUCCESSFULL SO SAVE DEVICE CONFIGURATION WORD (DCW)
|
|
;
|
|
GUD_SET:LD (IY+4),E ; LOW BYTE
|
|
LD (IY+5),D ; HIGH BYTE
|
|
;
|
|
; UPDATE THE DEVICE TABLE WITH THE ADDRESSES FOR THE CORRECT ROUTINE.
|
|
;
|
|
LD A,E
|
|
AND 00000111B
|
|
LD HL,INTMATRIX ; POINT TO EITHER THE INTERRUPT
|
|
JR NZ, USEIM
|
|
LD HL,POLMATRIX ; MATRIX OR THE POLLED MATRIX
|
|
USEIM: PUSH HL
|
|
|
|
PUSH IY ; CALCULATE THE DESTINATION
|
|
POP HL ; ADDRESS IN THE PIO_CFG TABLE
|
|
LD BC,8 ; FOR THE FOUR ADDESSES TO BE
|
|
ADD HL,BC ; COPIED TO
|
|
|
|
; LD B,0 ; 00000000 CALCULATE THE SOURCE ADDRESS
|
|
LD C,E ; XX?????? FROM THE MATRIX. EACH ENTRY
|
|
SRL C ; 0XX????? IN THE MATRIX IS 8 BYTES SO
|
|
SRL C ; 00XX???? SOURCE = MATRIX BASE + (8 * MODE)
|
|
SRL C ; 000XX???
|
|
POP DE ; LOAD THE MATRIX BASE
|
|
; LD DE,POLMATRIX
|
|
EX DE,HL
|
|
ADD HL,BC ; HL = SOURCE
|
|
|
|
LD C,8 ; COPY 8 BYTES
|
|
LDIR
|
|
|
|
; PUSH IY
|
|
; POP DE
|
|
; CALL DUMP_BUFFER
|
|
|
|
XOR A
|
|
RET
|
|
|
|
PRTTAB: .DB 0
|
|
.DB 0
|
|
.DB 0
|
|
.DB 0
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; INPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS
|
|
;
|
|
#DEFINE PIOMIVT(PIOIN,PIOIST,PIOPRT) \
|
|
#DEFCONT ;\
|
|
#DEFCONT ; RETURN WITH ERROR IF THERE IS \
|
|
#DEFCONT ; ALREADY A CHARACTER IN BUFFER \
|
|
#DEFCONT ;\
|
|
#DEFCONT ; OTHERWISE CHANGE THE STATUS TO \
|
|
#DEFCONT ; SHOW THERE IS ONE CHARACTER IN \
|
|
#DEFCONT ; THE BUFFER AND READ IT IN AND \
|
|
#DEFCONT ; AND STORE IT.RETURN GOOD STATUS.\
|
|
#DEFCONT ;\
|
|
#DEFCONT \ LD A,(_CIST)
|
|
#DEFCONT \ OR A
|
|
#DEFCONT \ JR NZ,_OVFL
|
|
#DEFCONT \ LD A,(PIOPRT)
|
|
#DEFCONT \ LD C,A
|
|
#DEFCONT \ LD A,1
|
|
#DEFCONT \ LD (_CIST),A
|
|
#DEFCONT \ IN A,(C)
|
|
#DEFCONT \ LD (_CICH),A
|
|
#DEFCONT \ OR $FF
|
|
#DEFCONT \ RET
|
|
#DEFCONT \_OVFL:XOR A
|
|
#DEFCONT \ RET
|
|
#DEFCONT ;\
|
|
#DEFCONT ;\
|
|
#DEFCONT ;\
|
|
#DEFCONT ;\
|
|
#DEFCONT ;\
|
|
#DEFCONT ;\
|
|
#DEFCONT \PIOIN:CALL PIOIST
|
|
#DEFCONT \ JR Z,PIOIN
|
|
#DEFCONT \ LD A,(_CICH)
|
|
#DEFCONT \ LD E,A
|
|
#DEFCONT \ XOR A
|
|
#DEFCONT \ LD (_CIST),A
|
|
#DEFCONT \ RET
|
|
#DEFCONT ;\
|
|
#DEFCONT ; If THERE A CHARACTER \
|
|
#DEFCONT ; AVAILABLE? RETURN NUMBER \
|
|
#DEFCONT ; IN A - 0 OR 1 \
|
|
#DEFCONT ;\
|
|
#DEFCONT \PIOIST:LD A,(_CIST)
|
|
#DEFCONT \ AND 00000001B
|
|
#DEFCONT \ RET
|
|
#DEFCONT ;\
|
|
#DEFCONT ; CIST : 01 = CHARACTER READY ELSE NOT READY \
|
|
#DEFCONT ; CISH : CHARACTER STORED BY INTERRUPT \
|
|
#DEFCONT ;\
|
|
#DEFCONT \_CIST .DB 00
|
|
#DEFCONT \_CICH .DB 00
|
|
;
|
|
PIOIVT0:.MODULE PIOIVT0
|
|
PIOMIVT(PIO0IN,PI0_IST,PRTTAB+0)
|
|
PIOIVT1:.MODULE PIOIVT1
|
|
PIOMIVT(PIO1IN,PI1_IST,PRTTAB+1)
|
|
PIOIVT2:.MODULE PIOIVT2
|
|
PIOMIVT(PIO2IN,PI2_IST,PRTTAB+2)
|
|
PIOIVT3:.MODULE PIOIVT3
|
|
PIOMIVT(PIO3IN,PI3_IST,PRTTAB+3)
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; OUTPUT INTERRUPT VECTOR MACRO AND DEFINITION FOR FOUR PORTS
|
|
;
|
|
; AN INTERRUPT IS GENERATED WHEN THE RECEIVING DEVICE CAN ACCEPT A CHARACTER
|
|
;
|
|
#DEFINE PIOMOVT(PIOOUT,PIOOST,PIOPRT) \
|
|
#DEFCONT ;\
|
|
#DEFCONT ; RETURN IF WE ARE WAITING FOR A \
|
|
#DEFCONT ; CHARACTER (COST = 00) \
|
|
#DEFCONT ;\
|
|
#DEFCONT ; IF ZERO CHARACTERS READY
|
|
#DEFCONT ; (COST = 01) CHANGE STATUS TO \
|
|
#DEFCONT ; WAITING FOR CHARACTER (COST 00) \
|
|
#DEFCONT ;\
|
|
#DEFCONT ; IF A CHARACTER IS READY THEN \
|
|
#DEFCONT ; OUTPUT AND CHANGE STATUS TO \
|
|
#DEFCONT ; ZERO CHARACTERS READY \
|
|
#DEFCONT ;\
|
|
#DEFCONT \ LD A,(_COST)
|
|
#DEFCONT \ DEC A
|
|
#DEFCONT \ RET M
|
|
#DEFCONT \ JR Z,_WFC
|
|
#DEFCONT \ LD A,(_COCH)
|
|
#DEFCONT \ LD E,A
|
|
#DEFCONT \_ONOW:LD A,(PIOPRT)
|
|
#DEFCONT \ LD C,A
|
|
#DEFCONT \ OUT (C),E
|
|
#DEFCONT \ LD A,1
|
|
#DEFCONT \_WFC: LD (_COST),A
|
|
#DEFCONT \ RET
|
|
#DEFCONT ;\
|
|
#DEFCONT ; WAIT FOR SPACE FOR THE CHARACTER\
|
|
#DEFCONT ; IF WE ARE WAITING FOR A \
|
|
#DEFCONT ; CHARACTRE THEN OUTPUT IT NOW \
|
|
#DEFCONT ; OTHERWISE STORE IT UNTIL THE \
|
|
#DEFCONT ; INTERRUPT CALLS FOR IT \
|
|
#DEFCONT ;\
|
|
#DEFCONT \PIOOUT:LD A,(_COST)
|
|
#DEFCONT \ CP 2
|
|
#DEFCONT \ JR C,_ONOW
|
|
#DEFCONT \ LD A,E
|
|
#DEFCONT \ LD (_COCH),A
|
|
#DEFCONT \ LD A,2
|
|
#DEFCONT \ LD (_COST),A
|
|
#DEFCONT \ JR PIOOUT
|
|
#DEFCONT ;\
|
|
#DEFCONT ; RETURN WITH NUMBER OF \
|
|
#DEFCONT ; CHARACTERS AVAILABLE 0 or 1 \
|
|
#DEFCONT ;\
|
|
#DEFCONT \PIOOST:LD A,(_COST)
|
|
#DEFCONT \ DEC A
|
|
#DEFCONT \ DEC A
|
|
#DEFCONT \ RET Z
|
|
#DEFCONT \ LD A,1
|
|
#DEFCONT \ RET
|
|
#DEFCONT ;\
|
|
#DEFCONT ; COST : 00 WAITING FOR CHARACTER\
|
|
#DEFCONT ; 01 ZERO CHARACTERS READY\
|
|
#DEFCONT ; 02 ONE CHARACTER READY \
|
|
#DEFCONT ; COCH : CHARACTER TO OUTPUT \
|
|
#DEFCONT ;\
|
|
#DEFCONT \_COST .DB 01
|
|
#DEFCONT \_COCH .DB 00
|
|
;
|
|
PIOOVT0:.MODULE PIOOVT0
|
|
PIOMOVT(PIO0OUT,PI0_OST,PRTTAB+0)
|
|
PIOOVT1:.MODULE PIOOVT1
|
|
PIOMOVT(PIO1OUT,PI1_OST,PRTTAB+1)
|
|
PIOOVT2:.MODULE PIOOVT2
|
|
PIOMOVT(PIO2OUT,PI2_OST,PRTTAB+2)
|
|
PIOOVT3:.MODULE PIOOVT3
|
|
PIOMOVT(PIO3OUT,PI3_OST,PRTTAB+3)
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; NON INTERRUPT OUTPUT ROUTINE - SHARED
|
|
;
|
|
; INPUT WILL ALWAYS RETURN ERROR, CHARACTER RETURNED IS UNDEFINED.
|
|
; OUTPUT WILL ALWAYS RETURN SUCCESS
|
|
; INPUT-STATUS WILL ALWAYS RETURN 0 CHARACTERS IN BUFFER.
|
|
; OUTPUT-STATUS WILL ALWAYS RETURN 1 CHARACTER SPACE IN BUFFER.
|
|
|
|
PIOSHO_IN:
|
|
LD A,1
|
|
RET
|
|
;
|
|
PIOSHO_OUT:
|
|
LD C,(IY+3)
|
|
OUT (C),E
|
|
XOR A
|
|
RET
|
|
;
|
|
PIOSHO_IST: XOR A
|
|
RET
|
|
;
|
|
PIOSH_OST:
|
|
LD A,1
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; NON INTERRUPT INPUT ROUTINE - SHARED
|
|
;
|
|
; INPUT WILL ALWAYS A CHARACTER AND SUCCESS.
|
|
; OUTPUT WILL ALWAYS RETURN FAILURE
|
|
; INPUT STATUS WILL ALWAYS RETURN 1 CHARACTER IN BUFFER.
|
|
;OUTPUT-STATUS WILL ALWAYS RETURN 0 CHARACTER SPACE IN BUFFER.
|
|
;
|
|
PIOSHI_IN:
|
|
LD C,(IY+3)
|
|
IN A,(C)
|
|
LD E,A
|
|
XOR A
|
|
RET
|
|
;
|
|
PIOSHI_OUT:
|
|
LD A,1
|
|
RET
|
|
;
|
|
PIOSH_IST:
|
|
LD A,1
|
|
RET
|
|
;
|
|
PIOSHI_OST:
|
|
XOR A
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; ON ENTRY IY POINTS TO THE DEVICE RECORD. GET AND RETURN THE CONFIGURATION WORD IN DE
|
|
;
|
|
PIO_QUERY:
|
|
PPI_QUERY:
|
|
LD E,(IY+4) ; FIRST CONFIG BYTE TO E
|
|
LD D,(IY+5) ; SECOND CONFIG BYTE TO D
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
; ON ENTRY IY POINTS TO THE DEVICE RECORD. FOR CHARACTER DEVICES BIT 6 OF ATTRIBUTE
|
|
; INDICATES PARALLEL PORT IF 1 SO WE SET IT. COMMON TO ALL PORTS
|
|
;
|
|
PIO_DEVICE:
|
|
PPI_DEVICE:
|
|
LD D,CIODEV_PIO ; D := DEVICE TYPE
|
|
LD E,(IY) ; E := PHYSICAL UNIT
|
|
LD C,$40 ; C := ATTRIBUTE
|
|
LD H,0 ; H := 0, DRIVER HAS NO MODES
|
|
LD L,(IY+3) ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
INTMATRIX:
|
|
.DW PIO0IN, PIO0OUT, PI0_IST, PI0_OST
|
|
.DW PIO1IN, PIO1OUT, PI1_IST, PI1_OST
|
|
.DW PIO2IN, PIO2OUT, PI2_IST, PI2_OST
|
|
.DW PIO3IN, PIO3OUT, PI3_IST, PI3_OST
|
|
POLMATRIX:
|
|
.DW PIOSHO_IN, PIOSHO_OUT, PIOSHO_IST, PIOSH_OST ; OUTPUT
|
|
.DW PIOSHI_IN, PIOSHI_OUT, PIOSH_IST, PIOSHI_OST ; INPUT
|
|
.DW 0,0,0,0 ; BIDIR
|
|
.DW 0,0,0,0 ; BIT MODE
|
|
|
|
SET_8255:
|
|
RET
|
|
;
|
|
SET_BYE:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; ------------------------------------
|
|
; i8255 FUNCTION TABLE ROUTINES
|
|
;-------------------------------------
|
|
|
|
PPI_IN:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
PPI_OUT:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
PPI_IST:
|
|
RET
|
|
;
|
|
PPI_OST:
|
|
RET
|
|
;
|
|
; PIO_INITDEV - Configure device.
|
|
; If DE = FFFF then extract the 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
|
|
LD DE,PIO_TYPE_STR ; POINT HL TO TYPE MAP TABLE
|
|
CALL PRTIDXDEA
|
|
|
|
; ALL DONE IF NO PIO WAS DETECTED
|
|
LD A,(IY+1) ; GET PIO TYPE BYTE
|
|
OR A ; SET FLAGS
|
|
RET Z ; IF ZERO, NOT PRESENT
|
|
;
|
|
PRTS(" MODE=$") ; FORMATTING
|
|
LD E,(IY+4) ; LOAD CONFIG
|
|
LD D,(IY+5) ; ... WORD TO DE
|
|
CALL PS_PRTPC0 ; PRINT CONFIG
|
|
;
|
|
LD A,(IY+4) ; PRINT
|
|
BIT 2,A ; ALLOCATED
|
|
JR Z,NOINT ; INTERRUPT
|
|
PRTS("/i$")
|
|
LD A,(IY+4)
|
|
AND 00000011B
|
|
CALL PRTDECB
|
|
NOINT: XOR A
|
|
RET
|
|
;
|
|
; WORKING VARIABLES
|
|
;
|
|
PIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT
|
|
;
|
|
; DESCRIPTION OF DIFFERENT PORT TYPES
|
|
;
|
|
PIO_TYPE_STR:
|
|
.TEXT "<NOT PRESENT>$" ; IDX 0
|
|
.TEXT "Zilog PIO$" ; IDX 1
|
|
.TEXT "i8255 PPI$" ; IDX 2
|
|
.TEXT "IO Port$" ; IDX 3
|
|
;
|
|
; Z80 PIO PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. TWO PORTS
|
|
;
|
|
; 32 BYTE DATA STRUCTURE FOR EACH PORT
|
|
;
|
|
; .DB 0 ; IY+0 CIO DEVICE NUMBER (SET DURING PRE-INIT, THEN FIXED)
|
|
; .DB 0 ; IY+1 PIO TYPE (SET AT ASSEMBLY, FIXED)
|
|
; .DB 0 ; IY+2 PIO CHANNEL (SET AT ASSEMBLY, FIXED)
|
|
; .DB PIOBASE+2 ; IY+3 BASE DATA PORT (SET AT ASSEMBLY, FIXED)
|
|
; .DB 0 ; IY+4 SPW - MODE 3 I/O DIRECTION BYTE (SET AT ASSEMBLE, SET WITH INIT)
|
|
; .DB 0 ; IY+5 SPW - MODE, INTERRUPT (SET AT ASSEMBLY, SET WITH INIT)
|
|
; .DW 0 ; IY+6/7 FUNCTION TABLE (SET AT ASSEMBLY, SET DURING PRE-INIT AND AT INIT)
|
|
; .DW PIO_IN ; IY+8 ADDR FOR DEVICE INPUT (SET WITH INIT)
|
|
; .DW PIO_OUT ; IY+10 ADDR FOR DEVICE OUTPUT (SET WITH INIT)
|
|
; .DW PIO_IST ; IY+12 ADDR FOR DEVICE INPUT STATUS (SET WITH INIT)
|
|
; .DW PIO_OST ; IY+14 ADDR FOR DEVICE OUTPUT STATUS (SET WITH INIT)
|
|
; .DW PIO_INITDEV ; IY+16 ADDR FOR INITIALIZE DEVICE ROUTINE (SET AT ASSEMBLY, FIXED)
|
|
; .DW PIO_QUERY ; IY+18 ADDR FOR QUERY DEVICE RECORD ROUTINE (SET AT ASSEMBLY, FIXED)
|
|
; .DW PIO_DEVICE ; IY+20 ADDR FOR DEVICE TYPE ROUTINE (SET AT ASSEMBLY, FIXED)
|
|
; .FILL 10
|
|
;
|
|
; SETUP PARAMETER WORD:
|
|
;
|
|
; +-------------------------------+ +-------+-----------+---+-------+
|
|
; | BIT CONTROL | | MODE | | A | INT |
|
|
; +-------------------------------+ --------------------+-----------+
|
|
; F E D C B A 9 8 7 6 5 4 3 2 1 0
|
|
; -- MSB (D REGISTER) -- -- LSB (E REGISTER) --
|
|
;
|
|
;
|
|
; MSB = BIT CONTROL MAP USE IN MODE 3
|
|
;
|
|
; MODE B7 B6 = 00 Mode 0 Output
|
|
; 01 Mode 1 Input
|
|
; 10 Mode 2 Bidir
|
|
; 11 Mode 3 Bit Mode
|
|
;
|
|
; INTERRUPT ALLOCATED B2 = 0 NOT ALLOCATED
|
|
; = 1 IS ALLOCATED
|
|
;
|
|
; WHICH IVT IS ALLOCATES B1 B0 00 IVT_PIO0
|
|
; 01 IVT_PIO1
|
|
; 10 IVT_PIO2
|
|
; 11 IVT_PIO3
|
|
;
|
|
#DEFINE DEFPIO(MPIOBASE,MPIOCH0,MPIOCH1,MPIOCH0X,MPIOCH1X,MPIOIN0,MPIOIN1) \
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB PIO_ZPIO
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB MPIOBASE
|
|
#DEFCONT \ .DB (MPIOCH0|MPIOIN0)
|
|
#DEFCONT \ .DB MPIOCH0X
|
|
#DEFCONT \ .DW 0
|
|
#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE
|
|
#DEFCONT \ .FILL 2
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB PIO_ZPIO
|
|
#DEFCONT \ .DB 1
|
|
#DEFCONT \ .DB MPIOBASE+1
|
|
#DEFCONT \ .DB (MPIOCH1|MPIOIN1)
|
|
#DEFCONT \ .DB MPIOCH1X
|
|
#DEFCONT \ .DW 0
|
|
#DEFCONT \ .DW 0,0,0,0, PIO_INITDEV,PIO_QUERY,PIO_DEVICE
|
|
#DEFCONT \ .FILL 2
|
|
;
|
|
; i8255 PORT TABLE - EACH ENTRY IS FOR 1 CHIP I.E. THREE PORTS
|
|
;
|
|
#DEFINE DEFPPI(MPPIBASE,MPPICH1,MPPICH2,MPPICH3,MPPICH1X,MPPICH2X,MPPICH3X) \
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB PIO_8255
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB MPPIBASE
|
|
#DEFCONT \ .DB (MPPICH1|00001000B)
|
|
#DEFCONT \ .DB MPPICH1X
|
|
#DEFCONT \ .DW 0
|
|
#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE
|
|
#DEFCONT \ .FILL 2
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB PIO_8255
|
|
#DEFCONT \ .DB 1
|
|
#DEFCONT \ .DB MPPIBASE+2
|
|
#DEFCONT \ .DB (MPPICH2|00010000B)
|
|
#DEFCONT \ .DB MPPICH2X
|
|
#DEFCONT \ .DW 0
|
|
#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE
|
|
#DEFCONT \ .FILL 2
|
|
#DEFCONT \ .DB 0
|
|
#DEFCONT \ .DB PIO_8255
|
|
#DEFCONT \ .DB 2
|
|
#DEFCONT \ .DB MPPIBASE+4
|
|
#DEFCONT \ .DB (MPPICH3|00100000B)
|
|
#DEFCONT \ .DB MPPICH3X
|
|
#DEFCONT \ .DW 0
|
|
#DEFCONT \ .DW PPI_IN,PPI_OUT,PPI_IST,PPI_OST,PPI_INITDEV,PPI_QUERY,PPI_DEVICE
|
|
#DEFCONT \ .FILL 2
|
|
;
|
|
; HERE WE ACTUALLY DEFINE THE HARDWARE THAT THE HBIOS CAN ACCESS
|
|
; THE INIT ROUTINES READ AND SET THE INITIAL MODES FROM THIS INFO
|
|
;
|
|
PIO_CFG:
|
|
;
|
|
#IF PIO_4P
|
|
DEFPIO(PIO4BASE+0,M_Output,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N)
|
|
DEFPIO(PIO4BASE+4,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N)
|
|
DEFPIO(PIO4BASE+8,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N)
|
|
DEFPIO(PIO4BASE+12,M_Output,M_Output,M_BitAllOut,M_Output,INT_N,INT_N)
|
|
#ENDIF
|
|
#IF PIO_ZP
|
|
DEFPIO(PIOZBASE+0,M_Input,M_Input,M_BitAllOut,M_BitAllOut,INT_N,INT_N)
|
|
DEFPIO(PIOZBASE+4,M_Output,M_Output,M_BitAllOut,M_BitAllOut,INT_N,INT_N)
|
|
#ENDIF
|
|
; PPI_SBC & (PLATFORM == PLT_SBC) & (PPIDEMODE != PPIDEMODE_SBC))
|
|
|
|
#IF PPI_SBC
|
|
DEFPPI(PPIBASE,M_Output,M_Output,M_Output,M_BitAllOut,M_BitAllOut,M_BitAllOut)
|
|
#ENDIF
|
|
;
|
|
PIO_CNT .EQU ($ - PIO_CFG) / CFG_SIZ
|
|
;
|
|
;-------------------------------------------------------------------
|
|
; WHEN WE GET HERE IY POINTS TO THE PIO_CFG TABLE WE ARE WORKING ON.
|
|
; C IS THE UNIT NUMBER
|
|
;-------------------------------------------------------------------
|
|
;
|
|
;PIO_INITUNIT:
|
|
; LD A,C ; SET THE UNIT NUMBER
|
|
; LD (IY),A
|
|
;
|
|
; LD DE,-1 ; LEAVE CONFIG ALONE
|
|
; CALL PIO_INITDEV ; IMPLEMENT IT AND RETURN
|
|
; XOR A ; SIGNAL SUCCESS
|
|
; RET ; AND RETURN
|
|
;
|
|
PIO_INIT:
|
|
; CALL SPK_BEEP
|
|
LD B,PIO_CNT ; COUNT OF POSSIBLE PIO UNITS
|
|
LD C,0 ; INDEX INTO PIO CONFIG TABLE
|
|
PIO_INIT1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
|
|
; LD A,C ; PHYSICAL UNIT TO A
|
|
; RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (32 BYTES)
|
|
; RLCA ; ...
|
|
; RLCA ; ... TO GET OFFSET INTO CFG TABLE
|
|
; RLCA
|
|
;; RLCA
|
|
; LD HL,PIO_CFG ; POINT TO START OF CFG TABLE
|
|
; PUSH AF
|
|
; CALL ADDHLA ; HL := ENTRY ADDRESS
|
|
; POP AF
|
|
; CALL ADDHLA ; HL := ENTRY ADDRESS
|
|
; PUSH HL ; COPY CFG DATA PTR
|
|
; POP IY ; ... TO IY
|
|
; POP IY ; ... TO IY
|
|
|
|
CALL IDXCFG
|
|
|
|
LD A,(IY+1) ; GET PIO TYPE
|
|
OR A ; SET FLAGS
|
|
CALL NZ,PIO_PRTCFG ; PRINT IF NOT ZERO
|
|
|
|
; PUSH DE
|
|
; LD DE,$FFFF ; INITIALIZE DEVICE/CHANNEL
|
|
; CALL PIO_INITDEV ; BASED ON DPW
|
|
; POP DE
|
|
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; NEXT UNIT
|
|
DJNZ PIO_INIT1 ; LOOP TILL DONE
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
SET_PORT:
|
|
; DEVICE TYPE IS I/O PORT SO JUST WRITE $00 TO IT
|
|
LD C,(IY+3)
|
|
OUT (C),A
|
|
XOR A
|
|
RET
|
|
|