; ;================================================================================================== ; 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 "$" 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