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.
 
 
 
 
 
 

320 lines
7.9 KiB

;
;==================================================================================================
; CENTRONICS INTERFACE DRIVER
;==================================================================================================
;
; CENTRONICS-STYLE PARALLEL PRINTER DRIVER. ASSUMES MBC PRINT BOARD
; AS HARDWARE.
;
; IMPLEMENTED AS A ROMWBW CHARACTER DEVICE. CURRENTLY HANDLES OUPUT
; ONLY.
;
; PORT 0 (INPUT/OUTPUT):
;
; D7 D6 D5 D4 D3 D2 D1 D0
; +-------+-------+-------+-------+-------+-------+-------+-------+
; | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 |
; +-------+-------+-------+-------+-------+-------+-------+-------+
;
; PORT 1 (INPUT):
;
; D7 D6 D5 D4 D3 D2 D1 D0
; +-------+-------+-------+-------+-------+-------+-------+-------+
; | BUSY | ACK | POUT | SEL | ERR | 0 | 0 | 0 |
; +-------+-------+-------+-------+-------+-------+-------+-------+
;
; PORT 2 (INPUT/OUTPUT):
;
; D7 D6 D5 D4 D3 D2 D1 D0
; +-------+-------+-------+-------+-------+-------+-------+-------+
; | STAT1 | STAT0 | ENBL | PINT | SEL | RES | LF | STB |
; +-------+-------+-------+-------+-------+-------+-------+-------+
;
CEN_NONE .EQU 0
CEN_MBC .EQU 1
;
; PRE-CONSOLE INITIALIZATION - DETECT AND INIT HARDWARE
;
CEN_PREINIT:
;
; SETUP THE DISPATCH TABLE ENTRIES
; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN
; DISABLED.
;
LD B,CEN_CFGCNT ; LOOP CONTROL
XOR A ; ZERO TO ACCUM
LD (CEN_DEV),A ; CURRENT DEVICE NUMBER
LD IY,CEN_CFG ; POINT TO START OF CFG TABLE
CEN_PREINIT0:
PUSH BC ; SAVE LOOP CONTROL
CALL CEN_INITUNIT ; HAND OFF TO UNIT INIT CODE
POP BC ; RESTORE LOOP CONTROL
;
LD A,(IY+1) ; GET THE CEN TYPE DETECTED
OR A ; SET FLAGS
JR Z,CEN_PREINIT2 ; SKIP IT IF NOTHING FOUND
;
PUSH BC ; SAVE LOOP CONTROL
PUSH IY ; CFG ENTRY ADDRESS
POP DE ; ... TO DE
LD BC,CEN_FNTBL ; BC := FUNCTION TABLE ADDRESS
CALL NZ,CIO_ADDENT ; ADD ENTRY IF CEN FOUND, BC:DE
POP BC ; RESTORE LOOP CONTROL
;
CEN_PREINIT2:
LD DE,CEN_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,DE ; BUMP IY TO NEXT ENTRY
DJNZ CEN_PREINIT0 ; LOOP UNTIL DONE
;
CEN_PREINIT3:
XOR A ; SIGNAL SUCCESS
RET ; AND RETURN
;
; CEN INITIALIZATION ROUTINE
;
CEN_INITUNIT:
CALL CEN_DETECT ; DETERMINE CEN TYPE
LD (IY+1),A ; SAVE IN CONFIG TABLE
OR A ; SET FLAGS
RET Z ; ABORT IF NOTHING THERE
;
; UPDATE WORKING CEN DEVICE NUM
LD HL,CEN_DEV ; POINT TO CURRENT DEVICE NUM
LD A,(HL) ; PUT IN ACCUM
INC (HL) ; INCREMENT IT (FOR NEXT LOOP)
LD (IY),A ; UPDATE UNIT NUM
;
; SET DEFAULT CONFIG
LD DE,-1 ; LEAVE CONFIG ALONE
; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL
; THE INITDEV ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS!
JP CEN_INITDEVX ; IMPLEMENT IT AND RETURN
;
;
;
CEN_INIT:
LD B,CEN_CFGCNT ; COUNT OF POSSIBLE CEN UNITS
LD IY,CEN_CFG ; POINT TO START OF CFG TABLE
CEN_INIT1:
PUSH BC ; SAVE LOOP CONTROL
LD A,(IY+1) ; GET CEN TYPE
OR A ; SET FLAGS
CALL NZ,CEN_PRTCFG ; PRINT IF NOT ZERO
POP BC ; RESTORE LOOP CONTROL
LD DE,CEN_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,DE ; BUMP IY TO NEXT ENTRY
DJNZ CEN_INIT1 ; LOOP TILL DONE
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; DRIVER FUNCTION TABLE
;
CEN_FNTBL:
.DW CEN_IN
.DW CEN_OUT
.DW CEN_IST
.DW CEN_OST
.DW CEN_INITDEV
.DW CEN_QUERY
.DW CEN_DEVICE
#IF (($ - CEN_FNTBL) != (CIO_FNCNT * 2))
.ECHO "*** INVALID CEN FUNCTION TABLE ***\n"
!!! ; FORCE AN ASSEMBLY ERROR
#ENDIF
;
; BYTE INTPUT
;
CEN_IN:
; INPUT NOT SUPPORTED - RETURN NULL BYTE
LD E,0 ; NULL BYTE
XOR A ; SIGNAL SUCCESS
RET
;
; BYTE OUTPUT
;
CEN_OUT:
CALL CEN_OST ; READY TO SEND?
JR Z,CEN_OUT ; LOOP IF NOT
; *** ADD CODE TO OUTPUT BYTE ***
LD A,(IY+3)
LD C,A ; PORT 0 (DATA)
OUT (C),E ; OUTPUT DATA TO PORT
call DELAY ; ignore anything back after a reset
ld A,%00001101 ; select & strobe, LEDS OFF
INC C ; PUT CONTROL PORT IN C
INC C
OUT (C),A ; OUTPUT DATA TO PORT
call DELAY ; ignore anything back after a reset
ld A,%00001100 ; select, LEDS OFF
OUT (C),A ; OUTPUT DATA TO PORT
XOR A ; SIGNAL SUCCESS
RET
;
; INPUT STATUS
;
CEN_IST:
; INPUT NOT SUPPORTED - RETURN NOT READY
XOR A ; ZERO BYTES AVAILABLE
RET ; DONE
;
; OUTPUT STATUS
;
CEN_OST:
LD A,(IY+3)
LD C,A ; PORT 0 (DATA)
INC C ; SELECT STATUS PORT
IN A,(C) ; GET STATUS INFO
AND %10000000 ; ONLY INTERESTED IN BUSY FLAG
RET ; DONE
;
; INITIALIZE DEVICE
;
CEN_INITDEV:
HB_DI ; AVOID CONFLICTS
CALL CEN_INITDEVX ; DO THE REAL WORK
HB_EI ; INTS BACK ON
RET ; DONE
;
; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY
; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS!
;
CEN_INITDEVX:
LD A,(IY+3)
LD C,A ; PORT 0 (DATA)
XOR A ; CLEAR ACCUM
OUT (C),A ; SEND IT
INC C ; BUMP TO
INC C ; ... PORT 2
LD A,%00001000 ; SELECT AND ASSERT RESET, LEDS OFF
OUT (C),A ; SEND IT
CALL LDELAY ; HALF SECOND DELAY
LD A,%00001100 ; SELECT AND DEASSERT RESET, LEDS OFF
OUT (C),A ; SEND IT
XOR A ; SIGNAL SUCCESS
RET ; RETURN
;
;
;
CEN_QUERY:
LD E,(IY+4) ; FIRST CONFIG BYTE TO E
LD D,(IY+5) ; SECOND CONFIG BYTE TO D
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
;
;
CEN_DEVICE:
LD D,CIODEV_CEN ; D := DEVICE TYPE
LD E,(IY) ; E := PHYSICAL UNIT
LD C,$40 ; C := DEVICE TYPE, 0x40 IS PIO
LD H,(IY+1) ; H := MODE
LD L,(IY+3) ; L := BASE I/O ADDRESS
XOR A ; SIGNAL SUCCESS
RET
;
; CEN DETECTION ROUTINE
;
CEN_DETECT:
LD A,(IY+3) ; BASE PORT ADDRESS
ADD A,2 ; USE PORT 2 FOR DETECT
LD C,A ; PUT IN C FOR I/O
CALL CEN_DETECT2 ; CHECK IT
JR Z,CEN_DETECT1 ; FOUND IT, RECORD IT
LD A,CEN_NONE ; NOTHING FOUND
RET ; DONE
;
CEN_DETECT1:
; CEN FOUND, RECORD IT
LD A,CEN_MBC ; RETURN CHIP TYPE
RET ; DONE
;
CEN_DETECT2:
; LOOK FOR CEN AT PORT ADDRESS IN C
XOR A ; DEFAULT VALUE
OUT (C),A ; SEND IT
IN A,(C) ; READ IT
AND %11000000 ; ISOLATE STATUS BITS
CP %00000000 ; CORRECT VALUE?
RET NZ ; IF NOT, RETURN
LD A,%11000000 ; STATUS BITS ON (LEDS OFF)
OUT (C),A ; SEND IT
IN A,(C) ; READ IT
AND %11000000 ; ISOLATE STATUS BITS
CP %11000000 ; CORRECT VALUE?
RET ; RETURN (ZF SET CORRECTLY)
;
;
;
CEN_PRTCFG:
; ANNOUNCE PORT
CALL NEWLINE ; FORMATTING
PRTS("CEN$") ; 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 CEN TYPE
CALL PC_SPACE ; FORMATTING
LD A,(IY+1) ; GET CEN TYPE BYTE
RLCA ; MAKE IT A WORD OFFSET
LD HL,CEN_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 CEN WAS DETECTED
LD A,(IY+1) ; GET CEN TYPE BYTE
OR A ; SET FLAGS
RET Z ; IF ZERO, NOT PRESENT
;
; *** ADD MORE DEVICE INFO??? ***
;
XOR A
RET
;
;
;
CEN_TYPE_MAP:
.DW CEN_STR_NONE
.DW CEN_STR_MBC
;
CEN_STR_NONE .DB "<NOT PRESENT>$"
CEN_STR_MBC .DB "MBC$"
;
; WORKING VARIABLES
;
CEN_DEV .DB 0 ; DEVICE NUM USED DURING INIT
;
; CEN DEVICE CONFIGURATION TABLE
;
CEN_CFG:
;
CEN0_CFG:
; CEN MODULE A CONFIG
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; CEN TYPE (SET DURING INIT)
.DB 0 ; MODULE ID
.DB CEN0BASE ; BASE PORT
.DW 0 ; LINE CONFIGURATION
;
CEN_CFGSIZ .EQU $ - CEN_CFG ; SIZE OF ONE CFG TABLE ENTRY
;
#IF (CENCNT >= 2)
;
CEN1_CFG:
; CEN MODULE B CONFIG
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; CEN TYPE (SET DURING INIT)
.DB 1 ; MODULE ID
.DB CEN1BASE ; BASE PORT
.DW 0 ; LINE CONFIGURATION
;
#ENDIF
;
CEN_CFGCNT .EQU ($ - CEN_CFG) / CEN_CFGSIZ