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
|
PAGE ,132 ;
TITLE MSLPT - BIOS
%OUT ...MSLPT.ASM
;==============================================================================
;REVISION HISTORY:
;AN000 - New for DOS Version 4.00 - J.K.
;AC000 - Changed for DOS Version 4.00 - J.K.
;AN00x - PTM number for DOS Version 4.00 - J.K.
;==============================================================================
;AN001 - P156 KBMLPT device driver's retry logic. 8/18/87 J.K.
;==============================================================================
itest=0
INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT
INCLUDE MSEQU.INC
INCLUDE MSMACRO.INC
INCLUDE DEVSYM.INC
INCLUDE IOCTL.INC
EXTRN BUS$EXIT:NEAR ;MSBIO1
EXTRN ERR$CNT:NEAR ;MSBIO1
EXTRN CMDERR:NEAR ;MSBIO1
EXTRN GETDX:NEAR ;MSBIO1
EXTRN EXIT:NEAR ;MSBIO1
EXTRN ERR$EXIT:NEAR ;MSBIO1
;DATA
EXTRN PTRSAV:DWORD ;MSBIO1
EXTRN TIMDEV:WORD ;MSCLOCK
EXTRN LPT2DEV:WORD ;MSBIO2
EXTRN WAIT_COUNT:WORD ;MSDATA
EXTRN PRINTDEV:BYTE ;MSDATA
; IBM ROM STATUS BITS (I DON'T TRUST THEM, NEITHER SHOULD YOU)
NOTBUSYSTATUS = 10000000B ; NOT BUSY
ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?)
NOPAPERSTATUS = 00100000B ; NO MORE PAPER
SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED
IOERRSTATUS = 00001000B ; SOME KINDA ERROR
RESERVED = 00000110B ; NOPS
TIMEOUTSTATUS = 00000001B ; TIME OUT.
; WARNING!!! THE IBM ROM DOES NOT RETURN JUST ONE BIT. IT RETURNS A
; WHOLE SLEW OF BITS, ONLY ONE OF WHICH IS CORRECT.
;----------------------------------------------------------
;J.K. AN001; PRN$WRIT will retry only if error code is TIMEOUT.
; WRITE TO PRINTER DEVICE
; CX HAS COUNT OF BYTES
; ES:DI POINT TO DESTINATION
; AUXNUM HAS PRINTER NUMBER
PUBLIC PRN$WRIT
PRN$WRIT PROC NEAR
ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY
jcxz Prn$Done ;No char to output
Prn$Loop:
mov bx, 2 ;Initialize retry count
Prn$Out:
;SB34LPT000****************************************************************
;SB Print the character at ES:[DI]
;SB Call the function PrnOP to do this
;SB The character to be printed goes in AL and the function code
;SB for 'Output character' goes in AH
;SB Check for error in printing.
;SB If there is no error go to print the next character.
;SB If there is an error indicated see if it is due to TIMEOUT. If the
;SB error is not TIMEOUT then we can do nothing about it. Just go to
;SB print the next character. If it is due to timeout we can execute
;SB the code to retry the print which follows this piece of code
;SB LOCS: 6
mov al,es:[di] ; assume AX disposible since enter
xor ah,ah ; via int 21h
call PrnOp ; print to printer
jz Prn$Con ; no error - continue
test ah,TIMEOUTSTATUS
jz Prn$Con ; NOT time out - continue
;SB34LPT000****************************************************************
dec bx ;Retry until count is exhausted.
jnz Prn$Out ;Retry it.
jmp short Pmessg ;Return with error.
;
; next character
;
Prn$Con:
inc di ;point to next char and continue
loop Prn$Loop
Prn$Done:
jmp Exit
Pmessg:
jmp Err$Cnt
PRN$WRIT endp
; JCXZ EXVEC3 ; NO CHARS TO OUTPUT..
;PRN$LOOP:
; MOV BX,2 ; INITIALIZE RETRY FLAG
;PRN$OUT:
; MOV AL,ES:[DI] ; GET CHAR INTO AL
; INC DI ; POINT TO NEXT CHAR
; XOR AH,AH ; AH=0 => OUTPUT CHAR IN DL
; CALL PRNOP ; TO INDICATE PRINT CHAR IN AL
; JNZ PRRETRY
; LOOP PRN$LOOP
;EXVEC3:
; JMP EXIT
;PRRETRY:
; DEC DI ; UNDO THE INC ABOVE...
; DEC BX
; JNZ PRN$OUT
;PMESSG:
; JMP ERR$CNT ;RETURN WITH THE ERROR
;PRN$WRIT ENDP
;--------------------------------------------------------
; PRINTER STATUS ROUTINE
PUBLIC PRN$STAT
PRN$STAT PROC NEAR
ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY
CALL PRNSTAT ;DEVICE IN DX
JNZ PMESSG ; OTHER ERRORS WERE FOUND
;J.K. The next three lines are commented out, since it is a dead code.
; MOV AL,9 ; AGAIN, ASSUME OUT OF PAPER...
; TEST AH,NOPAPERSTATUS
; JNZ PMESSG
TEST AH,NOTBUSYSTATUS
jnz Prn$Done ;No error. Exit
JMP BUS$EXIT
PRN$STAT ENDP
; TAKE THE APPROPRIATE PRINTER AND DO THE OPERATION. TRIAGE THE STATUS
; RETURNED IN AH INTO SOME MEANINGFUL ERROR.
PRNSTAT PROC NEAR
;SB33037**********************************************************************
mov AH, 2 ; set command for get status ;SB ;3.30*
PRNOP: ;SB ;3.30*
call GETDX ; determine which printer ;SB ;3.30*
int 17h ; call ROM-BIOS printer routine ;SB;3.30*
;SB33037**********************************************************************
; EXAMINE THE STATUS BITS TO SEE IF AN ERROR OCCURRED. UNFORTUNATELY, SEVERAL
; OF THE BITS ARE SET SO WE HAVE TO PICK AND CHOOSE. WE MUST BE EXTREMELY
; CAREFUL ABOUT BREAKING BASIC.
TEST AH,IOERRSTATUS ; I/O ERROR?
JZ CHECKNOTREADY ; NO, TRY NOT READY
; AT THIS POINT, WE KNOW WE HAVE AN ERROR. THE CONVERSE IS NOT TRUE.
MOV AL,9 ; FIRST, ASSUME OUT OF PAPER
TEST AH,NOPAPERSTATUS ; OUT OF PAPER SET?
JNZ RET1 ; YES, ERROR IS SET
INC AL ; INDICATE I/O ERROR
RET1:
; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
RET ; RETURN WITH ERROR
; THE BITS SAID NO ERROR. UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK
; HERE.
CHECKNOTREADY:
MOV AL,2 ; ASSUME NOT-READY
TEST AH,TIMEOUTSTATUS ; IS TIME-OUT SET?
; IF NZ THEN ERROR, ELSE OK???
PRNOP2:
RET
PRNSTAT ENDP
; OUTPUT UNTIL BUSY. THIS ENTRY POINT IS USED EXCLUSIVELY BY THE PRINT
; SPOOLERS. UNDER NO CURCUMSTANCES SHOULD THE DEVICE DRIVER BLOCK WAITING FOR
; THE DEVICE TO BECOME READY.
; INPUTS: CX HAS COUNT OF BYTES TO OUTPUT.
; ES:DI POINTS TO SOURCE BUFFER
; OUTPUTS: SET THE NUMBER OF BYTES TRANSFERRED APPROPRIATELY
PUBLIC PRN$TILBUSY
PRN$TILBUSY PROC NEAR
ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY
PUSH DS
PUSH ES
POP DS ; NOW ES AND DS BOTH POINT TO SOURCE BUFFER
ASSUME DS:NOTHING
MOV SI,DI ; EVERYTHING IS SET FOR LODSB
PRN$TILBLOOP:
PUSH CX
PUSH BX
XOR BX,BX
MOV BL,CS:[PRINTDEV]
SHL BX,1
MOV CX,CS:WAIT_COUNT[BX] ; WAIT COUNT TIMES TO COME READY
POP BX
PRN$GETSTAT:
CALL PRNSTAT ; GET STATUS
JNZ PRN$BPERR ; ERROR
TEST AH,10000000B ; READY YET?
LOOPZ PRN$GETSTAT ; NO, GO FOR MORE
POP CX ; GET ORIGINAL COUNT
JZ PRN$BERR ; STILL NOT READY => DONE
LODSB
XOR AH,AH
CALL PRNOP
JNZ PRN$BERR ; ERROR
LOOP PRN$TILBLOOP ; GO FOR MORE
PRN$B:
POP DS
LDS BX,CS:[PTRSAV]
ASSUME DS:NOTHING
SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S
JMP EXIT
PRN$TILBUSY ENDP
PRN$BPERR PROC NEAR
ASSUME DS:CODE
POP CX
PRN$BERR:
POP DS
LDS BX,CS:[PTRSAV]
ASSUME DS:NOTHING
SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S
JMP ERR$EXIT
PRN$BPERR ENDP
;
; MANIPULATES THE VALUE IN WAIT_COUNT DEPENDING ON THE VALUE PASSED IN THE
; GENERIC IOCTL PACKET.
; IT EITHER SETS OR RETURNS THE CURRENT VALUE FOR THE RETRY COUNT FOR THE
; DEVICE.
;
PUBLIC PRN$GENIOCTL
PRN$GENIOCTL PROC NEAR
ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY
LES DI,[PTRSAV]
CMP ES:[DI].MAJORFUNCTION,IOC_PC
JE PRNFUNC_OK
PRNFUNCERR:
JMP CMDERR
PRNFUNC_OK:
MOV AL,ES:[DI].MINORFUNCTION
LES DI,ES:[DI].GENERICIOCTL_PACKET
XOR BX,BX
MOV BL,[PRINTDEV] ; GET INDEX INTO RETRY COUNTS
SHL BX,1
MOV CX,WAIT_COUNT[BX] ; PULL OUT RETRY COUNT FOR DEVICE
CMP AL,GET_RETRY_COUNT
JZ PRNGETCOUNT
CMP AL,SET_RETRY_COUNT
JNZ PRNFUNCERR
MOV CX,ES:[DI].RC_COUNT
PRNGETCOUNT:
MOV WAIT_COUNT[BX],CX ; PLACE "NEW" RETRY COUNT
MOV ES:[DI].RC_COUNT,CX ; RETURN CURRENT RETRY COUNT
JMP EXIT
PRN$GENIOCTL ENDP
CODE ENDS
END
|