summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/MODE/RESCODE.ASM
blob: ff557723bd634cf61bac368fb7b7bb24f4e6c66f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
	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 <CS:request EQ COM_status> 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 <CH EQ E> THEN										      ;AN001;
	      MOV  AX,time_out+framing_error+parity_error+overrun_error     ;indicate the port is on fire     ;AN001;
	   .ELSEIF <CH EQ R> 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 <DI EQ 0> 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 <retry_requested EQ true> AND      ;AN000;
;     .IF <device_type EQ COMX> 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 <device_type EQ LPTX> AND	     ;AN000;
;     .IF <retry_requested EQ true> OR	     ;AN000;
;     .IF <reroute_requested EQ true> 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