PAGE ,132 TITLE ADI INT DRIVER FOR THE HEWLETT PACKARD THINKJET ; THIS PROGRAM IS A MEMORY RESIDENT UTILITY THAT ; PROVIDES AN ADI DRIVER INTERRUPT PROCESSOR FOR ; AUTOCAD VERSION 2.5 OR HIGHER TO ALLOW PLOTTING ; ON A HEWLETT PACKARD THINKJET PRINTER. ; ; SWITCH 5 MUST BE DOWN! (HEWLETT PACKARD MODE) ; ; BY PATRICK SWAYNE, HUG SOFTWARE ENGINEER 29-SEP-88 ; REMOVABLE VERSION 01-MAR-90 TRUE EQU 0FFFFH ;DEFINE TRUE FALSE EQU NOT TRUE ;AND FALSE TEST EQU FALSE ;ASSEMBLE TEST VERSION IF TRUE ADIINT EQU 7BH ;ADI INTERRUPT USED PORT EQU 0 ;PRINTER PORT TO USE (LPT1) TIMEOUT EQU 78H ;ADDRESS OF LPT TIMEOUT JMPF MACRO DB 0EAH ;DEFINE FAR JUMP ENDM CODE SEGMENT ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE ; DEFINE SOME MEMORY LOCATIONS ORG 1 PSPSEG LABEL WORD ;PROGRAM SEGMENT PREFIX SEGMENT ADDR. ORG 3 MCBSIZE LABEL WORD ;MEMORY CONTROL BLOCK SIZE ORG 2CH ENVSEG LABEL WORD ;ENVIRONMENT SEGMENT ORG 5DH FCBARG LABEL BYTE ;FCB ARGUMENT ORG 100H START: JMP SETUP ;SET UP PROGRAM EVEN SIG DB 'ADITJET 1.1' ; DATA AREA ADIVEC DW 0,0 ;OLD ADI INT VECTOR UNFLG DB 0 ;UNLOAD FLAG OTIMOUT DB 0 ;OLD TIMEOUT ENDFLG DB 0 ;END FLAG ; PRINTER CONTROL STRINGS GRCODE DB 1BH,'*r1280S' ;PRINT GRAPHICS COMMAND DB 1BH,'*rA',0 BEGLIN DB 1BH,'*b' ;BEGIN LINE COMMAND LSIZE DB '000W',0 ENDJOB DB 1BH,'*rB',0 ;END OF JOB STRING ; ADI INTERRUPT PROCESSOR ADIPROC:PUSH DX ;WE'LL USE THIS PUSH SI CLD STI CMP AX,8001H ;START PLOT? JZ STPLOT ;YES CMP CS:ENDFLG,1 ;THIS PLOT ENDED? JNZ DOPLOT ;NO, CAN DO PLOT POP SI POP DX XOR AX,AX IRET DOPLOT: CMP AX,8002H ;END PLOT? JB DATALIN ;NO, MUST BE DATA LINE MOV CS:ENDFLG,1 ;MARK END PUSH DS MOV AX,40H MOV DS,AX ;POINT TO BIOS RAM MOV AL,CS:OTIMOUT ;GET OLD TIMEOUT MOV SI,OFFSET TIMEOUT+PORT ;POINT TO CURRENT TIMEOUT MOV [SI],AL ;RESTORE OLD TIMEOUT POP DS MOV SI,OFFSET ENDJOB CALL PRTSTR ;ELSE, INDICATE END OF JOB JC PRNBAD JMP SHORT PRNOK STPLOT: MOV CS:ENDFLG,0 ;CLEAR END FLAG PUSH DS MOV AX,40H MOV DS,AX ;POINT TO BIOS RAM MOV SI,OFFSET TIMEOUT+PORT ;POINT TO TIMEOUT FOR CURRENT PORT MOV AL,[SI] ;GET OLD TIMEOUT MOV CS:OTIMOUT,AL ;SAVE IT MOV BYTE PTR [SI],0FFH ;SET TIMEOUT TO MAX POP DS MOV AH,2 MOV DX,PORT INT 17H ;TEST PRINTER PORT AND AH,90H CMP AH,90H ;IS PRINTER READY? JNZ PRNBAD ;NO MOV SI,OFFSET GRCODE CALL PRTSTR ;ELSE, SET UP PRINTER JC PRNBAD ;SOMETHING WENT WRONG MOV BX,0 ;INDICATE MONOCHROME PRNOK: MOV AX,1 ;RETURN INIT OK POP SI POP DX IRET PRNBAD: XOR AX,AX ;RETURN INIT NO GOOD POP SI POP DX IRET ; A DATA LINE HAS BEEN SENT. SEND THE COUNT AND THEN ; THE DATA TO THE PRINTER DATALIN:CMP AX,160 ;TEST LINE SIZE JBE DATAL1 ;OK MOV AX,160 ;ELSE, TRUNCATE DATAL1: PUSH AX ;SAVE COUNT MOV DL,100 DIV DL ;GET HUNDREDS ADD AL,'0' MOV CS:LSIZE,AL ;STORE HUNDREDS MOV AL,AH ;REMAINDER TO AL AAM ;CONVERT TO BCD XCHG AL,AH ;FIX ORDER ADD AX,'00' ;CONVERT TO ASCII MOV WORD PTR CS:LSIZE+1,AX ;SAVE COUNT MOV SI,OFFSET BEGLIN CALL PRTSTR ;SEND COUNT TO PRINTER POP AX ;RESTORE ORIGINAL COUNT JC PRNBAD ;BAD PRINTER OR AX,AX JZ PRNOK ;EMPTY LINE MOV DS,CX ;DATA SEGMENT TO DS MOV SI,BX ;DATA OFFSET TO SI MOV CX,AX ;COUNT TO CX MOV DX,PORT ;GET PRINTER PORT LINLP: LODSB ;GET A CHARACTER XOR AH,AH INT 17H ;PRINT THE CHARACTER TEST AH,1 ;TEST PRINTER JNZ PRNBAD ;BAD PRINTER LOOP LINLP ;LOOP UNTIL DONE JMP PRNOK ; PRINT A STRING OF TEXT PRTSTR: MOV DX,PORT ;GET PRINTER PORT PRTSTL: LODS CS:BEGLIN ;GET A CHARACTER OR AL,AL ;DONE? JZ PRTSTX ;YES XOR AH,AH ;AH = 0, AL = CHAR INT 17H ;SEND CHAR TO INIT PRINTER TEST AH,1 ;PRINTER OK? JZ PRTSTL ;YES, GO ON STC ;ELSE, FLAG ERROR PRTSTX: RET IF NOT TEST ; INT 28H PROCESSOR. USED FOR UN-INSTALLING ADITJET. INT28: CMP CS:UNFLG,1 ;UN-INSTALL ADITJET? JZ UNINS ;YES JMPF INT28V DW 0,0 ;ELSE, EXIT UNINS: PUSH CS POP DS ;POINT TO THIS SEGMENT XOR AX,AX MOV ES,AX ;AND TO INT. SEGMENT MOV SI,OFFSET ADIVEC ;POINT TO ADI INT VECTOR MOV DI,ADIINT*4 ;WHERE IT GOES CLD CLI MOVSW ;RESTORE VECTOR MOVSW MOV SI,OFFSET INT28V ;POINT TO INT 28 VECTOR MOV DI,28H*4 ;WHERE IT GOES MOVSW ;RESTORE VECTOR MOVSW PUSH CS POP ES ;PUT ES HERE MOV AH,49H INT 21H ;RELEASE THIS PROGRAM'S MEMORY MOV ES,ENVSEG ;POINT TO ENVIRONMENT SEGMENT MOV AH,49H INT 21H ;RELEASE ENVIRONMENT SEGMENT STI ;ENABLE INTERRUPTS INT 20H ;EXIT ENDIF ENDRES: ;END OF RESIDENT CODE ; INSTALL THIS DRIVER IN MEMORY SETUP: MOV DX,OFFSET SIGNON MOV AH,9 INT 21H ;PRINT SIGN-ON CLD MOV AH,52H INT 21H ;GET MEMORY CONTROL BLOCK ADDR. MOV AX,ES:[BX-2] ;GET FIRST MCB SEGMENT MOV DS,AX ;POINT TO IT FNDLP: MOV AX,PSPSEG ;GET PSP SEGMENT MOV DX,CS CMP AX,DX ;IN THIS SEGMENT? JAE CHKFND ;IF SO, CHECK IF ADITJET FOUND MOV ES,AX ;ELSE, PSP SEGMENT TO ES MOV SI,OFFSET SIG MOV DI,SI PUSH DS ;SAVE MCB SEGMENT PUSH CS POP DS ;PUT DS HERE MOV CX,6 ;6 WORDS IN SIGNATURE REPZ CMPSW ;IS ADITJET HERE? JZ GOTCC ;WE FOUND ADITJET MOV LSTSEG,ES ;SAVE PSP SEGMENT FNDNXT: POP DS ;RESTORE MCB SEGMENT MOV AX,MCBSIZE ;GET MCB SIZE INC AX ;CORRECT IT MOV BX,DS ADD AX,BX ;CALCULATE NEXT MCB SEGMENT MOV DS,AX ;POINT TO IT JMP FNDLP ;TRY AGAIN GOTCC: MOV FNDSEG,ES ;SAVE SEGMENT WHERE FOUND MOV BYTE PTR FNDFLG,1 ;MARK PROGRAM FOUND JMP FNDNXT CHKFND: PUSH CS POP DS ;FIX DS CMP BYTE PTR FNDFLG,1 ;WAS ADITJET FOUND? JNZ NOTFND ;NO MOV ES,FNDSEG ;GET SEGMENT WHERE FOUND CMP FCBARG,'U' ;UNINSTALL? JZ DOUNIN MOV DX,OFFSET ALMSG MOV AH,9 INT 21H ;SAY "ADITJET ALREADY IN" INT 20H DOUNIN: MOV BX,FNDSEG ;GET SEGMENT WHERE FOUND CMP BX,LSTSEG ;COMPARE WITH LAST PSP FOUND JNC UNLOK ;OK TO UNLOAD MOV DX,OFFSET NOUNMSG MOV AH,9 INT 21H ;ELSE, SAY "CAN'T UNLOAD" INT 20H UNLOK: MOV DX,OFFSET UNMSG MOV AH,9 INT 21H ;PRINT UNLOAD MESSAGE MOV ES:UNFLG,1 ;FLAG UNLOAD DESIRED INT 20H ;AND EXIT NOTFND: CMP FCBARG,'U' ;UNINSTALL? JNZ DOINS ;NO MOV DX,OFFSET NINMSG MOV AH,9 INT 21H ;ELSE, SAY "ALREADY UNLOADED" INT 20H ;AND EXIT DOINS: PUSH CS POP ES ;FIX ES PUSH DS ;SAVE DS XOR AX,AX MOV DS,AX ;DS AT 0 MOV SI,OFFSET ADIINT*4 ;POINT TO ADI INTERRUPT MOV DI,OFFSET ADIVEC ;PUT OLD VECTOR HERE PUSH SI CLI ;TURN OFF INTERRUPTS CLD MOVSW ;MOVE VECTOR MOVSW POP SI MOV WORD PTR [SI],OFFSET ADIPROC ;PUT IN MY VECTOR MOV 2[SI],CS ;AND THIS SEGMENT IF NOT TEST MOV SI,OFFSET 28H*4 ;POINT TO INT 28 VECTOR MOV DI,OFFSET INT28V PUSH SI MOVSW ;COPY INT 28 VECTOR MOVSW POP SI MOV WORD PTR [SI],OFFSET INT28 ;SET NEW ONE MOV 2[SI],CS ENDIF STI POP DS IF NOT TEST MOV DX,OFFSET INMSG MOV AH,9 INT 21H ;SAY "ADITJET INSTALLED" MOV DX,OFFSET ENDRES ;POINT TO END OF RES. CODE INT 27H ;EXIT, LEAVE PROGRAM HERE ELSE MOV AX,8001H INT 7BH ;INITIALIZE PRINTER OR AL,AL ;TEST PRINTER JNZ GOON ;GO ON WITH TEST MOV DX,OFFSET SAYBAD MOV AH,9 INT 21H INT 20H GOON: MOV AX,160 ;GET A BYTE COUNT MOV BX,OFFSET GDATA ;POINT TO GRAPHIC DATA TSTLOOP:MOV CX,DS ;USE THIS DS PUSH AX ;SAVE COUNT PUSH BX ;AND POINTER INT 7BH ;CALL DRIVER POP BX POP AX DEC AX ;MAKE NEXT LINE SHORTER JNZ TSTLOOP MOV AX,8002H INT 7BH ;SIGNAL END XOR AX,AX MOV ES,AX ;AND TO INT. SEGMENT MOV SI,OFFSET ADIVEC ;POINT TO ADI INT VECTOR MOV DI,ADIINT*4 ;WHERE IT GOES CLD MOVSW ;RESTORE VECTOR MOVSW INT 20H SAYBAD DB 13,10,'Printer reported bad.$' GDATA DB 160 DUP (0FFH) ENDIF LSTSEG DW 0 ;LAST PSP SEGMENT (SHOULD BE < PSPSEG) FNDSEG DW 0 ;SEGMENT WHERE FOUND FNDFLG DB 0 ;PROGRAM FOUND FLAG SIGNON DB 13,10,'ADI Driver for HP ThinkJet printer, v 1.1',13,10 DB 'By Patrick Swayne, HUG Software Engineer',13,10 DB "Copyright (C) 1990 by Heath/Zenith Users' Group",13,10,10,'$' INMSG DB 'ADITJET is now installed.',13,10 DB 'To uninstall, type ADITJET U.',13,10,'$' ALMSG DB 'ADITJET is already installed.',13,10,'$' UNMSG DB 'ADITJET is now uninstalled.',13,10,'$' NOUNMSG DB "ADITJET is not the last TSR. Can't uninstall.",13,10,'$' NINMSG DB "ADITJET is already not installed.",13,10,'$' CODE ENDS END START