PAGE ,132 ; TITLE CODE TO BE MADE RESIDENT BY MODE .XLIST INCLUDE STRUC.INC .LIST ;.SALL ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P R O L O G ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;AN000; ;Ί Ί ;AN000; ;AN000; ; AC000 - P2852: Infinite retry check at beginning of INT 14 handler was using ; wrong bit pattern. ; AC001 - P5148: retry_flag was addressing the wrong segment ;Ί Ί ;AN000; ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P R O L O G ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ;AN000; ;AN000; ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ M A C R O S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί DISPLAY MACRO MSG MOV DX,OFFSET MSG CALL PRINTF ENDM GET_INT_VECT MACRO INT_NO ;Input: "INT_NO" - the interrupt to be gotten PUSH AX MOV AL,INT_NO ; MOV AH,35H ;FUNCTION CALL "GET VECTOR" INT 21H ;Output: ES:BX = the address in the vector POP AX ENDM SET MACRO REG,VALUE ;SET REG TO VALUE. DON'T SPECIFY AX FOR REG PUSH AX MOV AX,VALUE MOV REG,AX POP AX ENDM SET_INT_VECT MACRO INT_NO ;Input: "INT_NO" - the interrupt to be set PUSH AX ; DS:DX = CS:IP value to set the interrupt to MOV AL,INT_NO ;Output: the vector "INT_NO" contains DS:DX MOV AH,25H ;function call "SET VECTOR" INT 21H POP AX ENDM store_vector MACRO dword_holder ;Input: "dword_holder" - where to store it ; ES:BX - the address (vector) to be stored MOV WORD PTR dword_holder,BX ;Output: "dword_holder"=the value passed in ES:BX MOV WORD PTR dword_holder[2],ES ENDM ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ M A C R O S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ E Q U A T E S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί ADJUSTMENT EQU (entpt - move_destination) ;# of bytes the resident code is moved adjustment_in_paragraphs EQU (adjustment / 10H) ;# paragraphs the code moved COM_status EQU 03 ;BIOS input for com status request ;AN001; E EQU 1 ;value of "res_com_retry_type" for E retry requested ;AN001; false EQU 0 framing_error EQU 0000100000000000B ;bit returned in AX from com status ;AN001; holding_empty EQU 0010000000000000B ;bit returned in AX from com status ;AN001; INT14 EQU 014H INT17 EQU 017H LPT_status EQU 02 ;value of AH for printer status checks ;AN000; not_busy EQU 80H ;just the not busy bit on overrun_error EQU 0000001000000000B ;bit returned in AX from com status ;AN001; parity_error EQU 0000010000000000B ;bit returned in AX from com status ;AN001; P14_model_byte EQU 0F9H ;P14's have a F9 at F000:FFFE R EQU 3 ;value of "res_com_retry_type" for R retry requested ;AN001; shift_empty EQU 0100000000000000B ;bit returned in AX from com status ;AN001; time_out EQU 1000000000000000B ;time out bit returned in AX from com status ;AN001; TO_SCREEN EQU 9 ;REQUEST OUTPUT TO SCREEN TRUE EQU 0FFH USER_ABORT EQU 00H ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ E Q U A T E S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ S T R U C T U R E S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ S T R U C T U R E S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ROM SEGMENT AT 0F000H ORG 0E739H RS232 LABEL FAR ORG 0EFD2H PRINTER_IO LABEL FAR ;NOTE: THE VALUES REPRESENTED BY THIS SEGMENT ARE NOT NECESSARILY ; THE ONES USED BY THE SUBSEQUENT PROCEDURES. THESE HERE MERELY ; SERVE AS SAMPLES. THE ACTUAL VALUES IN THE INSTRUCTIONS: ; JMP RS232 ; JMP PRINTER_IO ; WILL BE MOVED INTO THESE INSTRUCTIONS FROM THE VECTOR TABLE USING ; THE THEN CURRENT VALUES OF INT 14H FOR RS232 AND OF INT 17H FOR ; THE PRINTER_IO JUMP TARGETS. THIS IS TO ALLOW FOR SOME USER ; TO HAVE INTERCEPTED THESE VECTORS AND DIRECTED THEIR REQUESTS TO ; HIMSELF INSTEAD OF TO THE ROM. ORG 0FFFEH ;model_byte LABEL BYTE ROM ENDS VECT SEGMENT AT 0 ORG 50H VECT14H LABEL DWORD ;RS232 CALL ORG 5CH VECT17H LABEL DWORD ;PRINTER I/O CALL ORG 471H BREAK_FLAG LABEL BYTE ;BREAK FLAG BREAK_BIT EQU 80H ;ON=BREAK ORG 530H RESSEG LABEL DWORD ;VECTOR OF MODETO, INIT TO ZERO VECT ENDS ;**************************************************************** PRINTF_CODE SEGMENT PUBLIC ASSUME CS:PRINTF_CODE,DS:PRINTF_CODE ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ E X T R N S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί EXTRN device_type:BYTE ;see parse.asm EXTRN COMX:ABS ;see parse.asm EXTRN LPTX:ABS ;see parse.asm EXTRN MAIN:NEAR EXTRN MOVED_MSG:WORD ;CR,LF,"Resident portion of MODE loaded",CR,LF,"$" EXTRN busy_status:ABS ;value of lpt1_retry_type[BX] when user wants actual status, see modeprin EXTRN PRINTF:NEAR ;interface to message retriever, see display.asm EXTRN reroute_requested:BYTE ;see parse.asm EXTRN retry_requested:BYTE ;see parse.asm ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ E X T R N S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P U B L I C S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί PUBLIC first_char_in_command_line ;location of the command line parameters PUBLIC FIXUP PUBLIC lpt1_retry_type ;filled in and used to get at other two lpt retry masks in modeprin PUBLIC rescode_length ;REFERENCED IN MAIN PROCEDURE PUBLIC MODETO PUBLIC move_destination ;location of the resident code after it has been moved PUBLIC NEW_PTSFLAG ;RESIDENT THE FLAG WILL BE ACCESSABLE TO PUBLIC NEW_SCRNTABL ;MODESCRN NEEDS TO KNOW WHERE IT WENT PUBLIC OFFPTS ;USED IN MODEECHO TO ADDRESS MODEPTS PUBLIC OFFRETRY PUBLIC ptsflag1 ;make available to display_printer_reroute_status PUBLIC P14_model_byte PUBLIC res_com_retry_type ;PUBLIC res_lpt_retry_type PUBLIC resflag2 ;make available to display_printer_reroute_status PUBLIC RES_MODEFLAG ; RESIDENT THE FLAG WILL BE ACCESSABLE PUBLIC RESSEG ;SCRNTABL NEEDS TO FOLLOW THIS VECTOR TO ADDRESS VIDEO PARMS PUBLIC SCRNTABL PUBLIC submodel_byte ;holder for machine's secondary model byte PUBLIC VECTOR14 PUBLIC VECTOR17 ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P U B L I C S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ORG 2CH environ_seg DW ? ;segment address of the environment, used as the block of memory to free so ;AN000; ;environment is not part of resident code. ORG 60H ;first usable byte of PSP. If you change this check the ;calculation of paragraphs in 'main' move_destination LABEL WORD ;where the resident will be moved to ; THIS STRUCTURE DEFINES THE PROGRAM SEGMENT PREFIX AREA ; POINTED TO BY THE ES REGISTER. THIS MUST BE DEFINED HERE, IT REPLACES THE ; 'ORG 100' ORG 80H command_line_length DB ? ;not used, just place holder to allign next field first_char_in_command_line LABEL BYTE ;location of the command line parameters ;command_line DB 7FH DUP(?) ;PARM AREA ORG 100H ENTPT: JMP MAIN ;ENTRY POINT, START AT THE MAIN PROCEDURE SUBTTL SERIAL RETRY PAGE ;THIS PROC WILL BE POINTED TO BY INT VECTOR 14H MODETO PROC NEAR PUSH CX MOV CL,DL ;CL=DL=0,1,2 or 3 SHL CL,1 ;CL= 0, 2, 4 or 6 for COM 1,2,3 or 4 respectively ;AC000; XOR CH,CH ;CH=0 ready for ANDing in the mask ;AC000; OR CH,00000011B ;CH=00000011, mask for any type of retry, to be shifted into proper position ;AC000; SHL CH,CL ;CH=00000011, 00001100, 00110000 or 11000000 for COM 1,2,3 or 4 respectively AND CH,BYTE PTR CS:res_modeflag ;see if any bit is on for this COM port ;AC001; MOV CS:retry_type,CX ;AC001; save for check after call to old INT 14 ;AN001; POP CX JNZ pushax VECTOR14 LABEL WORD ;THE NEXT JMP INSTRUCTION HAS 5 BYTES, ; THE LAST 4 ARE THE CONTENTS OF INT 14H, ; WHICH NORMALLY POINTS TO THE ROM RS232 ; HANDLER. THE CODE GENERATED HERE BY THE ; ASSEMBLER IS REPLACED BY THE ACTUAL ; CONTENTS OF INT 14H. TOROM: JMP RS232 ;NO RETRY, GO DIRECTLY TO ROM ENTRY IRET from there PUSHAX: MOV CS:request,AH ;save request type PUSH AX ;SAVE ENTRY PARAMETERS FOR LATER RETRY PUSH DS ;SAVE REGS PUSH AX ;SAVE REGS SUB AX,AX ;POINT TO MOV DS,AX ; PAGE ZERO AND DS:BREAK_FLAG,0FFH-BREAK_BIT ;RESET BREAK FLAG POP AX ;RESTORE POP DS ; REGS PUSHF ;SAVE FLAGS TO SIMULATE INT INSTRUCTION VEC EQU (VECTOR14 +1) ;OFFSET TO IMMEDIATE FIELD OF PREVIOUSLY SET ; FAR JMP INSTRUCTION, FILLED WITH THE ; ORIGINAL CONTENTS OF THE INTERRUPT VECTOR CALL DWORD PTR CS:VEC ;CALL PREVIOUS RS232 HANDLER .IF THEN ;IF a status request THEN ;AN001; PUSH CX ;need CX for shift count in CL ;AN001; MOV CX,CS:retry_type ;AC001; get back retry type for this port ;AN001; SHR CH,CL ;put back in first two bits for retry type check below ;AN001; .IF THEN ;AN001; MOV AX,time_out+framing_error+parity_error+overrun_error ;indicate the port is on fire ;AN001; .ELSEIF THEN ;AN001; MOV AX,shift_empty+holding_empty+clear_to_send+data_set_ready ;indicate the port is ready ;AN001; .ENDIF ;otherwise assume B retry and pass actual status ;AN001; POP CX ;restore reg ;AN001; .ELSE ;continue as if a send request ;AN001; PUSH AX ;SAVE REGS PUSH DS ; REGS SUB AX,AX ;POINT TO MOV DS,AX ; PAGE ZERO TEST DS:BREAK_FLAG,BREAK_BIT ;TEST BREAK FLAG POP DS ;RESTORE POP AX ; REGS JZ TESTER ;BRANCH IF NO BREAK OR AH,80H ;SIMULATE TIMEOUT ERROR ON BREAK .ENDIF ;ENDIF status request ;AN001; FLUSH: INC SP ;FLUSH THE INC SP ; STACK IRET ;RETURN ; TESTER: TEST AH,80H ;TEST IF A REAL TIMEOUT JZ FLUSH ;IF NOT, RETURN POP AX ;RETRIEVE ORIGINAL ENTRY PARAMETERS JMP PUSHAX ;DO RETRY ;********************************************************************** RES_MODEFLAG EQU $ ;WHEN THIS CODE IS RESIDENT THE FLAG WILL BE ; ACCESSABLE BY MODECOM AS AN OFFSET FROM ADDRESS ; POINTED TO BY VECT14H AND RESSEG res_com_retry_type equ $ DB 0 ;AN665;no retry of any type active for any port ; ; bits comx 00=>no retry for any port ; ---- ---- 01=>E for COM1, no retry for 2, 3 and 4 ; 0-1 com1 02=>B for COM1, no retry for 2, 3 and 4 ; 2-3 com2 03=>R for COM1, no retry for 2, 3 and 4 ; 4-5 com3 04=>E for COM2, no retry for 1, 3 and 4 ; 6-7 com4 05=>E for COM2, E for COM1, none for 3 and 4 ; 06=>E for COM2, B for COM1, none for 3 and 4 ; bit 07=>E for COM2, R for COM1, none for 3 and 4 ; pair 08=>B for COM2, none for 1, 3 and 4 ; value active 09=>B for COM2, E for COM1, none for 3 and 4 ; ----- ------ 0A=>B for COM2, B for COM1, none for 3 and 4 ; 0 unknown 0B=>B for COM2, R for COM1, none for 3 and 4 ; 1 E 0C=>R for COM2, no retry for 1, 3 and 4 ; 2 B 0D=>R for COM2, E for COM1, none for 3 and 4 ; 3 R 0E=>R for COM2, B for COM1, none for 3 and 4 ; 0F=>R for COM2, R for COM1, none for 3 and 4 ; 10=>E for COM3, none for 1, 2 and 4 ; etc. MODETO ENDP ;************************************************************** SUBTTL DETERMINE PARALLEL TO SERIAL, OR PARALLEL TIMEOUT PAGE ;THIS PROC MAY BE POINTED TO BY INT VECTOR 17H MODEPTS PROC NEAR OFFPTS EQU MODEPTS - MODETO TEST DL,1 ;DETERMINE IF REDIRECTION APPLIES ; NOTE: THIS IMMEDIATE FIELD IS Revised BY MODE ; ;THIS NEXT JUMP INSTRUCTION IS Revised BY MODEECHO TO REFLECT WHICH ;LPTN IS TO BE REDIRECTED TO WHICH COMM. JNZ CK ;THIS JNZ IS Revised BY MODE ; ORG $-2 JZ CK ;IT MAY BE CHANGED TO THIS ; ORG $-2 JMP SHORT NOREDIRECT ; OR THIS... ; NOREDIRECT: OFFRETRY EQU $ ;disp into resident code of retry flgs ;THIS NEXT SECTION WILL TEST FOR THE OPTIONAL RETRY ON PARALLEL TIMEOUT. TEST DL,1 ;TEST TO SEE IF PARALLEL RETRY IS ACTIVE ;THIS NEXT JUMP INSTRUCTION IS Revised BY MODEPRIN TO REFLECT WHICH ;LPT1n DEFICE IS TO BE RETRIED. IT WILL APPEAR IN SEVERAL FORMS: JNZ PAR_RETRY ;THIS INSTRUCTION MAY BE Revised ; ORG $-2 JZ PAR_RETRY ; ORG $-2 JMP SHORT ASIS ; VECTOR17 LABEL WORD ASIS: JMP PRINTER_IO ;NO REDIRECTION, GO DIRECTLY TO PREVIOUS INT 17H ;************************************************************** SUBTTL RETRY PARALLEL ON TIMEOUT. PAGE PAR_RETRY: RT: MOV CS:request,AH ;save the function requested for check after return from call to INT 17 ;AN000; PUSH AX ;SAVE ENTRY PARAMETERS FOR LATER USE PUSH DS ;SAVE CALLER'S REGS PUSH AX ;SAVE REGS ; SUB AX,AX ;POINT TO PAGE ZERO MOV DS,AX ; USING THE DATA SEG REG ; AND DS:BREAK_FLAG,0FFH-BREAK_BIT ;RESET BREAK FLAG ; POP AX ;RESTORE CALLER'S REGS POP DS ;RESTORE REGS PUSHF ;SAVE FLAGS TO SIMULATE INT INSTRUCTION PVEC EQU VECTOR17+1 ;OFFSET TO IMMEDIATE FIELD OF PREVIOUSLY SET ; FAR JUMP INSTRUCTION, FILLED WITH THE ; ORIGINAL CONTENTS OF THE INT 17H VECTOR. CALL DWORD PTR CS:PVEC ;CALL PREVIOUS PARALLEL PORT HANDLER CMP CS:request,LPT_status ;AN000; JNE init_or_write ;AN000; TEST AH,not_busy ;see if the printer was busy (not busy bit off) ;AN000; JNZ pflush ;IF busy dork the status byte ;AN000; PUSH BX ;AN000; MOV BX,DX ;BX=zero based printer number ;AN000; CMP BYTE PTR CS:lpt1_retry_type[BX],busy_status ;IF status should be changed THEN ;AN000; JZ dont_modify ;busy setting means user wants actual status ;AN000; MOV AH,BYTE PTR CS:lpt1_retry_type[BX] ;change to status set by prior retry setting request for this LPT ;AN000; dont_modify: ;AN000; POP BX ;AN000; JMP pflush ;return to caller ;AN000; init_or_write: ;AN000; PUSH AX ;SAVE RETURN CODE IN AH PUSH DS ;SAVE DATA SEGMENT REG ; SUB AX,AX ;POINT TO MOV DS,AX ; SEGMENT AT ZERO ; TEST DS:BREAK_FLAG,BREAK_BIT ;TEST BREAK FLAG BIT POP DS ;RESTORE SEG REG POP AX ;RESTORE RETURN CODE TO AH JZ PTEST ;BRANCH IF NO BREAK REQUESTED ; OR AH,USER_ABORT ;SIMULATE TIMEOUT PFLUSH: INC SP ;FLUSH THE INC SP ; STACK IRET ;RETURN TO CALLER ; PTEST: TEST AH,01H ;TEST IF A REAL PARALLEL TIMEOUT JZ PFLUSH ;IF NOT, RETURN POP AX ;RETRIEVE ORIGINAL ENTRY PARAMETERS JMP RT ;DO RETRY ;************************************************************** SUBTTL REDIRECT PARALLEL I/O TO SERIAL PAGE CK: FIXUP EQU CK - NOREDIRECT CMP AH,1 ;CHECK FOR 'INITIALIZE' CODE ; AH=0, PRINT THE CHAR IN AL ; AH=1, INITIALIZE ; AH=2, READ STATUS JNZ PTCHR ;IT IS PRINT CHARACTER OR READ STATUS ; SINCE IT IS 'INITIALIZE' MOV AH,80H ;PASS BACK 'NOT BUSY' RETURN CODE FROM ; AH=1, (INITIALIZE) IRET ; PTCHR: ; IT IS PRINT CHARACTER OR READ STATUS PUSH BX ;SAVE THE PUSH AX ; REGS PUSH DX ;SAVE MORE REGS MOV BX,OFFSET RESFLAG2 ;POINT AT PARALLEL TO SERIAL ; CORRESPONDENCE TABLE IN RESIDENT CODE ADD BX,DX ;INDEX USING PRINTER SELECTION (0,1,OR 2) MOV DL,CS:[BX] ;GET CORRESPONDING SERIAL PORT SELECT CMP AH,0 ;CHECK FOR 'PRINT CHAR' CODE JZ SENDCHAR ; YES, PRINT CHAR ; NO, MUST BE READ STATUS MOV AH,3 ;SET TO INT 14 'READ STAT' ENTRY PT INT 14H ;GO RS232 AND READ STATUS INTO AX ; ; AH HAS LINE STATUS: ; IF TRANSFER HOLDING REG EMPTY, AND ; IF TRANSMIT SHIFT REGISTER READY, THEN SERIAL PORT ; NOT BUSY CLEAR_TO_SEND EQU 10H DATA_SET_READY EQU 20H ;DATA SET READY LINE HIGH AND AL,CLEAR_TO_SEND+DATA_SET_READY ;SEE IF PRINTER HAS A CHANCE ; $IF Z ;DSR and CTS low, so probably off or out of paper JNZ $$IF1 MOV AH,29H ;PAR 'BUSY' 'OUT OF PAPER' 'I/O ERROR' 'TIME OUT' ; $ELSE JMP SHORT $$EN1 $$IF1: CMP AL,CLEAR_TO_SEND+DATA_SET_READY ; $IF E ;IF clear to send and dsta set ready THEN JNE $$IF3 MOV AH,90H ;'NOT BUSY' 'SELECTED' ; $ELSE ;ELSE clear to send high OR data set ready high JMP SHORT $$EN3 $$IF3: MOV AH,10H ;SET TO PARALLEL 'BUSY' 'SELECTED' ; $ENDIF $$EN3: ; $ENDIF $$EN1: POP DX ;RESTORE REG JMP SHORT POPPER ;RESTORE REGS AND EXIT ; SENDCHAR: MOV AH,1 ;SET TO INT 14 'SEND CHAR' ENTRY PT INT 14H ;GO RS232 SEND CHAR ; POP DX ;RESTORE REG TEST AH,80H ;TEST IF TIMEOUT RS232 ERROR MOV AH,90H ;SET UP NORMAL RETURN AS IF FROM PRINTER ; THAT IS: PARALLEL 'NOT BUSY' 'SELECTED' JZ POPPER ;IF NO ERROR MOV AH,09H ;RESET AH TO PARALLEL TIMEOUT ERROR CODE ; RET CODE='BUSY', 'I/O ERROR', 'TIMEOUT' ; THE USUAL RETURN FROM A WRITE DATA ; TO A PARALLEL PRINTER THAT IS OFFLINE POPPER: POP BX ;RETRIEVE ORIGINAL AX MOV AL,BL ;RESTORE ORIGINAL AL VALUE LEAVING NEW AH POP BX ;RESTORE BX IRET ;RETURN ;********************************************************************** PAGE PTSFLAG1 DB 0 ;FLAG FOR MODE COMMAND: NEW_PTSFLAG EQU PTSFLAG1 - MODETO ;WHEN THIS CODE IS ; RESIDENT THE FLAG WILL BE ACCESSABLE TO ; MODEECHO AS AN OFFSET FROM ADDRESS ; POINTED TO BY VECT14H AND RESSEG ; 0=NO INTERCEPT ; 1=INTERCEPT LPT1 ; 2=INTERCEPT LPT2 ; 3=INTERCEPT LPT1 AND LPT2 ; 4=INTERCEPT LPT3 ; 5=INTERCEPT LPT1 AND LPT3 ; 6=INTERCEPT LPT2 AND LPT3 ; 7=INTERCEPT LPT1, LPT2, AND LPT3 RESFLAG2 EQU $ ;WHERE PTSFLAG2 IS IN THE RESIDENT CODE PTSFLAG2 DB 0 ;FLAG FOR MODE COMMAND: ; LPT1 CORRESPONDENCE VALUE: ; 0=COM1 ; 1=COM2 ; 2=COM3 ; 3=COM4 ;RESFLAG2 EQU (PTSFLAG2 - MODETO)+BASE ;WHERE PTSFLAG2 ; IS IN THE RESIDENT CODE PTSFLAG3 DB 0 ;FLAG FOR MODE COMMAND: ; LPT2 CORRESPONDENCE VALUE: ; 0=COM1 ; 1=COM2 ; 2=COM3 ; 3=COM4 PTSFLAG4 DB 0 ;FLAG FORMODE COMMAND: ; LPT3 CORRESPONDENCE VALUE: ; 0=COM1 ; 1=COM2 ; 2=COM3 ; 3=COM4 lpt1_retry_type DB 0 ;holder of mask for status return byte ;AN000; lpt2_retry_type DB 0 ;can be one of no_retry_flag, error_status, ;AN000; lpt3_retry_type DB 0 ;busy_status or ready_status, see MODEPRIN ;AN000; PUBLIC lpt1_retry_type ;THE FOLLOWING AREA IS USED BY MODESCRN TO STORE THE VIDEO PARMS THAT ;ALLOW FOR THE SHIFTING RIGHT OR LEFT OF THE SCREEN IMAGE. SCRNTABL DB 16 DUP("PARM") ;64 BYTES OF SPACE NEW_SCRNTABL EQU SCRNTABL - MODETO ;OFFSET INTO RESIDENT ; CODE OF THE 64 BYTE SCREEN TABLE request DB 0 ;holder for INT 14 or INT 17 request passed in AH retry_type DW 0 ;holder for INT 14 retry type and shift count MODEPTS ENDP rescode_length equ (($ - entpt) / 16) + 1 ;length of resident code in paragraphs MOVELEN EQU $ - entpt ;length of resident code in bytes ;******************************************************************************* SUBTTL LOAD THE RESIDENT PORTION OF MODE PAGE MODELOAD PROC NEAR PUBLIC MODELOAD ; GET THE CONTENTS OF INT VECTOR 14H ; TO SEE IF THE RESIDENT CODE IS ; ALREADY LOADED ; SET UP REGS TO MOVE IT INTO PLACE PUSH DS ;SAVE SEG REG PUSH ES ;SAVE SEG REG PUSH DI PUSH SI ;SAVE FOR CALLING PROCEDURE PUSH DX ;SAVE FOR CALLING PROCEDURE PUSH AX ;SAVE FOR CALLING PROCEDURE PUSH BX MOV AX,0 ;GET THE PARAGRAPH NUMBER OF DESTINATION MOV ES,AX ; TO THE EXTRA SEGMENT BASE LES DI,ES:RESSEG ;GET POINTER TO RETRY CODE ; IF THE CODE IS NOT ALREADY MOVED, .IF THEN NEAR ;AC000;IF nothing at 50:30 THEN code is not loaded ; ; SINCE CODE HAS NOT YET BEEN MOVED, ; PATCH PROPER ADDRESSES INTO IT ; .IF AND ;AN000; ; .IF THEN ;AN000; ; ; XOR AX,AX ; MOV ES,AX ;BACK TO THE VECTOR AT ZERO ; MOV AX,WORD PTR ES:VECT14H ;GET THE VECTOR OF INT 14H ; MOV VECTOR14+1,AX ; INTO CODE TO BE MOVED ; ; MOV AX,WORD PTR ES:VECT14H[2] ;MOVE REST OF VECTOR ; MOV VECTOR14+3,AX ; ; .ENDIF ;AN000; ; ; .IF AND ;AN000; ; .IF OR ;AN000; ; .IF THEN ;AN000; ; ; MOV AX,WORD PTR ES:VECT17H ;GET VECTOR OF INT 17H ; MOV VECTOR17+1,AX ; INTO CODE TO BE MOVED ; ; MOV AX,WORD PTR ES:VECT17H[2] ;MOVE REST OF VECTOR ; MOV VECTOR17+3,AX ; ; .ENDIF ;AN000; PUSH ES ;SAVE POINTER TO VECTOR ZERO ;Get and save previous interrupt handlers get_int_vect 14H ;get vector of INT 17H, ES:BX=vector MOV VECTOR14+1,BX ;put offset INTO CODE TO BE MOVED MOV VECTOR14+3,ES ;save segment get_int_vect 17H ;get vector of INT 17H, ES:BX=vector MOV VECTOR17+1,BX ;put offset INTO CODE TO BE MOVED MOV VECTOR17+3,ES ;save segment MOV SI,OFFSET entpt ;WILL BE MOVED FROM HERE MOV DI,OFFSET move_destination ;WILL BE MOVED TO HERE MOV CX,MOVELEN ;NUMBER OF BYTES TO BE MOVED PUSH CS ;GET SEGMENT OF PROGRAM HEADER POP ES ; INTO ES, THE DESTINATION SEGMENT CLD ;INCREMENT SI AND DI AFTER EACH BYTE IS MOVED REP MOVSB ;MOVE CX BYTES FROM DS:SI TO ES:DI POP ES ;Put a pointer to the resident code 50:30 (0:530) CLI ;DISABLE UNTIL VECTOR SET MOV ES:WORD PTR resseg,OFFSET modeto ;offset of "modeto" in res code pointer MOV AX,CS SUB AX,adjustment_in_paragraphs ;adjust res CS by amount the code moved MOV ES:WORD PTR resseg[2],AX ;store segment of res code in pointer STI ;allow some interrupts ;Set interrupts 14 and 17 to point to their respective handlers. AX has correct segment. MOV DS,AX ;DS=resident code segment MOV DX,OFFSET modeto ;DS:DX=> INT14 handler "modeto" set_int_vect INT14 MOV DX,OFFSET modepts ;DS:DX=> INT17 handler "modepts" set_int_vect INT17 MOV ES,CS:environ_seg ;ES=segment of the block to be returned MOV AH,49H ;49 is the Free Allocated Memory function call INT 21H ;free the environment MOV BYTE PTR CS:1,27H ;SET EXIT TO REMAIN RESIDENT by dorking opcode in the PSP ; PUSH CS POP DS ;"PRINTF" requires that DS be the segment containing the messages DISPLAY MOVED_MSG ;"Resident portion of MODE loaded" MOV BYTE PTR CS:LOADED_YET,1 ;SET FLAG TO INDICATE ABOVE MSG ; HAS BEEN DISPLAYED ; MODESCRN MAY NEED TO REPEAT MESSAGE MOV stay_resident,true .ENDIF ;AC000;END IS CODE ALREADY LOADED? TEST POP BX POP AX ;RESTORE FOR CALLING PROCEDURE POP DX ;RESTORE FOR CALLING PROCEDURE POP SI ;RESTORE FOR CALLING PROCEDURE POP DI POP ES ;RESTORE SEG REG POP DS ;RESTORE SEG REG RET MODELOAD ENDP ;************************************************************ SUBTTL COMMON PARMAMETER LIST AND WORKAREA PAGE ; THE FOLLOWING AREA IS USED TO STORE PARSED PARAMETER LIST, AND WORK STORAGE ; USED BY OTHER MODULES ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ N O N R E S I D E N T D A T A ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί CTRL_ST DB 5 DUP(24) ;PRINTER CONFIGURATION CONTROL STRING PARM1 DB 10 DUP(0) PARM2 DB -1 ;-1 INDICATES TO SERVER THAT THIS PARM IS UNCHANGED PARM3 DB 0 MODE DB 0 FLAG DB 0 INDEX DW 00 ;REDIRECTED PRINTER NETWORK REDIRECTION LIST INDEX IS_LOCAL DB TRUE ;INITIALIZE for MODEPRIN LOADED_YET DB false LOCAL_NAME DB 16 DUP(0) ;HOLDING AREA FOR GET ASSIGN LIST ENTRY CALL USE machine_type DB 0FFH ;holder for the machine type NOERROR DB TRUE ;INDICATE NO ERROR MESSAGES HAVE BEEN ISSUED YET NEW_VIDEO_PARMS_OFFSET DW 090H ;OFFSET OF INIT TABLE FOR SCREEN SHIFTING NEW_VIDEO_PARMS_SEGMENT DW 040H ;SEGMENT OF INIT TABLE FOR SCREEN SHIFTING REMOTE_DEV DB 50 DUP(0) ;HOLDING AREA FOR GET ASSIGN LIST ENTRY CALL USE stay_resident DB false ;boolean indicating should stay resident when terminate submodel_byte DB 0FFH ;secondary model byte ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ N O N R E S I D E N T D A T A ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ ;ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P U B L I C S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» ;Ί Ί PUBLIC PARM1,PARM2,PARM3,MODE,FLAG,CTRL_ST,INDEX,LOCAL_NAME,REMOTE_DEV ;AC000; PUBLIC IS_LOCAL PUBLIC LOADED_YET PUBLIC machine_type ;holder for machine type, found in "main" PUBLIC NOERROR PUBLIC NEW_VIDEO_PARMS_OFFSET PUBLIC NEW_VIDEO_PARMS_SEGMENT PUBLIC stay_resident ;Ί Ί ;ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ P U B L I C S ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ PRINTF_CODE ENDS END ENTPT