DOS 3.30 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2192 lines
40 KiB

4 years ago
  1. ; SCCSID = @(#)print_r.asm 4.7 85/09/13
  2. INCLUDE pridefs.inc
  3. BREAK <Resident Portion>
  4. ;
  5. ; MSDOS V3.00 PRINT
  6. ;
  7. ; Resident Portion
  8. ;
  9. Code Segment public para
  10. extrn TransRet:WORD,TransSize:WORD
  11. Code EndS
  12. BREAK <Resident Data>
  13. CodeR Segment public para
  14. extrn ERRMES:BYTE, ERRMEST:BYTE, BELMES:BYTE, ErrMesT2:BYTE
  15. extrn CanMes:BYTE, CanFilNAm:BYTE, AllCan:BYTE, ERR0:BYTE
  16. extrn ERR1:BYTE, ERR2:BYTE, ERR3:BYTE, ERR4:BYTE, ERR5:BYTE
  17. extrn ERR6:BYTE, ERR7:BYTE, ERR8:BYTE, ERR9:BYTE, ERR10:BYTE
  18. extrn ERR11:BYTE, ERR12:BYTE, FATMES:BYTE, BADDRVM:BYTE,
  19. extrn BADMES:BYTE, badmeslen:WORD, GOODMES:BYTE, goodmeslen:WORD
  20. if hardint
  21. public SliceCnt, BusyTick, MaxTick, TimeSlice
  22. endif
  23. public EndRes, BlkSiz, QueueLen, PChar
  24. public ListName, FileQueue, EndQueue, Buffer
  25. public EndPtr, NxtChr, MoveTrans
  26. assume CS:CodeR
  27. public PRNR001S,PRNR001E
  28. PRNR001S:
  29. db "*** Microsoft/V310 ***"
  30. DB (362 - 80h) + 310 DUP (?) ; (362 - 80h) is IBM's New
  31. ; recommended Stack Size -
  32. ; Old recommended Stack Size
  33. ; == New stack growth
  34. ISTACK LABEL WORD ;Stack starts here and grows down the
  35. ;Resident data
  36. ;
  37. ; Due to flagrant bogosity by file servers, BUSY is *ALWAYS* relevant.
  38. ;
  39. BUSY DB 0 ;Internal ME flag
  40. IF HARDINT
  41. ;
  42. ; WARNING!!! The *&^%(*&^ 286 chip hangs if you access a word that will wrap
  43. ; at the segment boundary. Make the initial INDOS point somewhere reasonable.
  44. ;
  45. INDOS DD TimeSlice ;DOS buisy flag
  46. NEXTINT DD ? ;Chain for int
  47. NEXT_REBOOT DD ? ;Chain for ROM bootstrap
  48. fFake db 0 ; TRUE => do not diddle I/O ports
  49. SOFINT DB 0 ;Internal ME flag
  50. TICKCNT DB 0 ;Tick counter
  51. TICKSUB DB 0 ;Tick miss counter
  52. SLICECNT DB 8 ;Time slice counter, init to same val
  53. ; as TIMESLICE
  54. TIMESLICE DB 8 ;The PRINT scheduling time slice. PRINT
  55. ; lets this many "ticks" go by before
  56. ; using a time slice to pump out characters.
  57. ; Setting this to 3 for instance means PRINT
  58. ; Will skip 3 slices, then take the fourth.
  59. ; Thus using up 1/4 of the CPU. Setting it
  60. ; to one gives PRINT 1/2 of the CPU.
  61. ; The above examples assume MAXTICK is
  62. ; 1. The actual PRINT CPU percentage is
  63. ; (MAXTICK/(1+TIMESLICE))*100
  64. MAXTICK DB 2 ;The PRINT in timeslice. PRINT will pump
  65. ; out characters for this many clock ticks
  66. ; and then exit. The selection of a value
  67. ; for this is dependent on the timer rate.
  68. BUSYTICK DB 1 ;If PRINT sits in a wait loop waiting for
  69. ; output device to come ready for this
  70. ; many ticks, it gives up its time slice.
  71. ; Setting it greater than or equal to
  72. ; MAXTICK causes it to be ignored.
  73. ;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK
  74. ; ticks go by without getting a character out.
  75. ENDIF
  76. QueueLen db DefQueueLen ; Actual length of print queue
  77. even
  78. EndQueue dw ? ; pointer to end of print queue
  79. QueueTail dw offset CodeR:FileQueue ; pointer to next free entry
  80. ; in the print queue
  81. buffer dw ? ; pointer to data buffer
  82. I24_ERR DW ? ;Save location for INT 24H error code
  83. Ctrlc DB ? ; saved ^C trapping state
  84. SPNEXT DD ? ;Chain location for INT 28
  85. COMNEXT DD ? ;Chain location for INT 2F
  86. SSsave DW ? ;Stack save area for INT 24
  87. SPsave DW ?
  88. HERRINT DD ? ;Place to save Hard error interrupt
  89. LISTDEV DD ? ;Pointer to Device
  90. COLPOS DB 0 ;Column position for TAB processing
  91. CURRFIL DB 0
  92. NXTCHR DW ?
  93. CURRHAND DW -1
  94. PrinterNum DW -1 ; index for printer
  95. QueueLock db 0 ; queue lock, 0=unlocked
  96. PChar db ? ; path character
  97. AmbCan db ? ; = 1 ambigous cancel
  98. CanFlg db ? ; = 1 Current was already canceled
  99. ACanOcrd db ? ; = 1 a file was found during an
  100. ; ambigous cancel
  101. ;--- Warnning: this is a FCB!!
  102. ACBuf db ?
  103. ACName db 8 dup(?)
  104. ACExt db 3 dup(?)
  105. db 4 dup(?) ; how big is an unopened fcb???
  106. CONTXTFLAG DB 0 ;0 means his context, NZ means me
  107. HISPDB DW ?
  108. PABORT DB 0 ;Abort flag
  109. BLKSIZ DW 512 ;Size of the PRINT I/O block in bytes
  110. ENDPTR DW ?
  111. COMDISP LABEL WORD ; Communications dispatch table
  112. DW OFFSET CodeR:INST_REQ
  113. DW OFFSET CodeR:ADDFIL
  114. DW OFFSET CodeR:CANFIL
  115. DW offset CodeR:CanAll
  116. DW OFFSET CodeR:QSTAT
  117. DW offset CodeR:EndStat
  118. DW offset CodeR:QSTATDEV
  119. ;Resident messages
  120. MESBAS DW OFFSET CodeR:ERR0
  121. DW OFFSET CodeR:ERR1
  122. DW OFFSET CodeR:ERR2
  123. DW OFFSET CodeR:ERR3
  124. DW OFFSET CodeR:ERR4
  125. DW OFFSET CodeR:ERR5
  126. DW OFFSET CodeR:ERR6
  127. DW OFFSET CodeR:ERR7
  128. DW OFFSET CodeR:ERR8
  129. DW OFFSET CodeR:ERR9
  130. DW OFFSET CodeR:ERR10
  131. DW OFFSET CodeR:ERR11
  132. DW OFFSET CodeR:ERR12
  133. ENDRES DW ? ; filled in at initialization time
  134. PRNR001E:
  135. CodeR EndS
  136. BREAK <Resident Code>
  137. CodeR Segment public para
  138. Break <Server critical section routines>
  139. TestSetServer:
  140. IF IBM
  141. CLC
  142. PUSH AX
  143. MOV AX,8700h ; Can I run?
  144. INT 2Ah
  145. POP AX
  146. ENDIF
  147. ret
  148. LeaveServer:
  149. IF IBM
  150. PUSH AX
  151. MOV AX,8701h
  152. INT 2Ah
  153. POP AX
  154. ENDIF
  155. ret
  156. ;Interrupt routines
  157. ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:NOTHING
  158. ;
  159. ; PRINT is stimulated by a hardware interrupt.
  160. ;
  161. ;
  162. ; The Server may also stimulate us during timer ticks (if we handled the
  163. ; ticks ourselves, it would be disasterous. Therefore, we have a substitute
  164. ; entry here that simulates the timer stuff but does NOT muck with the ports.
  165. ;
  166. IF HARDINT
  167. FakeINT1C:
  168. MOV fFake,-1
  169. JMP SHORT InnerHardInt
  170. HDSPINT: ;Hardware interrupt entry point
  171. mov fFake,0
  172. InnerHardInt:
  173. CALL TestSetServer
  174. JNC TickTime
  175. jmp ChainInt
  176. TickTime:
  177. INC [TICKCNT] ;Tick
  178. INC [TICKSUB] ;Tick
  179. CMP [SLICECNT],0
  180. JZ TIMENOW
  181. DEC [SLICECNT] ;Count down
  182. JMP SHORT HardIntDone ;Not time yet
  183. TIMENOW:
  184. CMP BUSY,0 ;See if interrupting ourself
  185. JNZ HardIntDone
  186. IF IBM
  187. push ax ; check for nested interrupts
  188. mov al,00001011b ; select ISR in 8259
  189. out 20H,al
  190. JMP x
  191. x:
  192. in al,20H ; get ISR register
  193. and al,0FEH ; mask timer int
  194. pop ax
  195. jnz HardIntDone ; there was another int in service...
  196. ENDIF
  197. PUSH DS
  198. PUSH SI
  199. LDS SI,[INDOS] ;Check for making DOS calls
  200. ;
  201. ; WARNING!!! Due to INT 24 clearing the INDOS flag, we must test both INDOS
  202. ; and ERRORMODE at once! These must be contiguous in MSDATA.
  203. ;
  204. CMP WORD PTR [SI-1],0
  205. POP SI
  206. POP DS
  207. JNZ HardIntDone ;DOS is Busy
  208. INC [BUSY] ;Exclude furthur interrupts
  209. MOV [TICKCNT],0 ;Reset tick counter
  210. MOV [TICKSUB],0 ;Reset tick counter
  211. STI ;Keep things rolling
  212. IF AINT
  213. TEST fFake,-1
  214. JNZ NoAck
  215. PUSH AX
  216. MOV AL,EOI ;Acknowledge interrupt
  217. OUT AKPORT,AL
  218. POP AX
  219. NoAck:
  220. ENDIF
  221. CALL DOINT
  222. CLI
  223. PUSH AX
  224. MOV AL,[TIMESLICE]
  225. MOV [SLICECNT],AL ;Either soft or hard int resets time slice
  226. POP AX
  227. DEC Busy ;Done, let others in
  228. HardIntDone:
  229. Call LeaveServer
  230. CHAININT:
  231. TEST fFake,-1
  232. JNZ DoIRET
  233. JMP [NEXTINT] ;Chain to next clock routine
  234. DoIRET:
  235. IRET
  236. ENDIF
  237. ;
  238. ; PRINT is stimulated by a spooler idle interrupt
  239. ;
  240. SPINT: ;INT 28H entry point
  241. CALL TestSetServer
  242. JC NxtSp
  243. IF HARDINT
  244. CMP [BUSY],0
  245. JNZ SpIntDone
  246. INC [BUSY] ;Exclude hardware interrupt
  247. INC [SOFINT] ;Indicate a software int in progress
  248. ENDIF
  249. STI ;Hardware interrupts ok on INT 28H entry
  250. CALL DOINT
  251. IF HARDINT
  252. CLI
  253. MOV [SOFINT],0 ;Indicate INT done
  254. PUSH AX
  255. MOV AL,[TIMESLICE]
  256. MOV [SLICECNT],AL ;Either soft or hard int resets time slice
  257. POP AX
  258. DEC Busy
  259. ENDIF
  260. SpIntDone:
  261. call LeaveServer
  262. NXTSP: JMP [SPNEXT] ;Chain to next INT 28
  263. ;
  264. ; Since we may be entering at arbitrary times, we need to get/set the extended
  265. ; error as we may end up blowing it away. We do not do this on spooler ints.
  266. ;
  267. public PRNR002S, PRNR002E
  268. PRNR002S:
  269. SaveState DPL <> ; empty DPL
  270. PRNR002E:
  271. public enterprint
  272. EnterPRINT:
  273. IF HardInt
  274. TEST SofInt,-1
  275. JNZ EnterDone
  276. ENDIF
  277. MOV AH,GetExtendedError
  278. CALL DO_21
  279. MOV SaveState.DPL_AX,AX
  280. MOV SaveState.DPL_BX,BX
  281. MOV SaveState.DPL_CX,CX
  282. MOV SaveState.DPL_DX,DX
  283. MOV SaveState.DPL_SI,SI
  284. MOV SaveState.DPL_DI,DI
  285. MOV SaveState.DPL_DS,DS
  286. MOV SaveState.DPL_ES,ES
  287. EnterDone:
  288. RET
  289. public leaveprint
  290. LeavePRINT:
  291. IF HardInt
  292. TEST SofInt,-1
  293. JNZ LeaveDone
  294. ENDIF
  295. MOV AX,(ServerCall SHL 8) + 10
  296. PUSH CS
  297. POP DS
  298. MOV DX,OFFSET CodeR:SaveState
  299. CALL Do_21
  300. LeaveDone:
  301. RET
  302. public doint
  303. DOINT:
  304. ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:NOTHING
  305. CMP [CURRFIL],0
  306. JNZ GOAHEAD
  307. SPRET:
  308. ret ;Nothing to do
  309. GOAHEAD:
  310. cmp [QueueLock],1
  311. je spret ; queue locked, do nothing...
  312. PUSH AX ;Need a working register
  313. MOV [SSsave],SS
  314. MOV [SPsave],SP
  315. MOV AX,CS
  316. CLI
  317. ;Go to internal stack to prevent INT 24 overflowing system stack
  318. MOV SS,AX
  319. MOV SP,OFFSET CodeR:ISTACK
  320. STI
  321. PUSH ES
  322. PUSH DS
  323. PUSH BP
  324. PUSH BX
  325. PUSH CX
  326. PUSH DX
  327. PUSH SI
  328. PUSH DI
  329. PUSH CS
  330. POP DS
  331. ASSUME DS:CodeR
  332. Call EnterPRINT
  333. MOV BX,[NXTCHR]
  334. CMP BX,[ENDPTR]
  335. JB PLOOP
  336. JMP READBUFF ;Buffer empty
  337. DONEJMPJP:
  338. POPF
  339. DONEJMPJ:
  340. JMP DONEJMP
  341. FILEOFJ:
  342. ASSUME DS:CodeR
  343. JMP FILEOF
  344. PLOOP:
  345. IF HARDINT
  346. MOV BX,[NXTCHR]
  347. CMP BX,[ENDPTR]
  348. JAE DONEJMPJ ;Buffer has become empty
  349. CMP [SOFINT],0
  350. JNZ STATCHK
  351. PUSH AX
  352. MOV AL,[MAXTICK]
  353. CMP [TICKCNT],AL ;Check our time slice
  354. POP AX
  355. JAE DONEJMPJ
  356. STATCHK:
  357. ENDIF
  358. CALL PSTAT
  359. PUSHF
  360. CMP [CURRFIL],0
  361. JZ DONEJMPJP ;File got cancelled by error
  362. POPF
  363. IF HARDINT
  364. JZ DOCHAR ;Printer ready
  365. CMP [SOFINT],0
  366. ENDIF
  367. JNZ DONEJMP ;If soft int give up
  368. IF HARDINT
  369. PUSH AX
  370. MOV AL,[BUSYTICK]
  371. CMP [TICKSUB],AL ;Check our busy timeout
  372. POP AX
  373. JAE DONEJMP
  374. JMP PLOOP
  375. ENDIF
  376. DOCHAR:
  377. MOV AL,BYTE PTR [BX]
  378. CMP AL,1AH ;^Z?
  379. JZ FILEOFJ ;CPM EOF
  380. CMP AL,0DH ;CR?
  381. JNZ NOTCR
  382. MOV [COLPOS],0
  383. NOTCR:
  384. CMP AL,9 ;TAB?
  385. JNZ NOTABDO
  386. MOV CL,[COLPOS] ;expand tab to # spaces
  387. OR CL,0F8H
  388. NEG CL
  389. XOR CH,CH
  390. JCXZ TABDONE ;CX contains # spaces to print
  391. TABLP:
  392. MOV AL," "
  393. INC [COLPOS]
  394. PUSH CX
  395. CALL POUT
  396. POP CX
  397. DEC CX ;G
  398. JZ TABDONE ;G We're done - get next char
  399. JMP PLOOP ;G Keep processing tab
  400. ;G LOOP TABLP
  401. ;G JMP TABDONE
  402. NOTABDO:
  403. CMP AL,8 ;Back space?
  404. JNZ NOTBACK
  405. DEC [COLPOS]
  406. NOTBACK:
  407. CMP AL,20H ;Non Printing char?
  408. JB NOCHAR
  409. INC [COLPOS] ;Printing char
  410. NOCHAR:
  411. CALL POUT ;Print it
  412. TABDONE:
  413. INC [NXTCHR] ;Next char
  414. IF HARDINT
  415. MOV [TICKSUB],0 ;Got a character out, Reset counter
  416. CMP [SOFINT],0 ;Soft int does one char at a time
  417. JNZ DONEJMP
  418. JMP PLOOP
  419. ENDIF
  420. DONEJMP:
  421. CALL CONTEXT_BACK
  422. Call LeavePRINT
  423. POP DI
  424. POP SI
  425. POP DX
  426. POP CX
  427. POP BX
  428. POP BP
  429. POP DS
  430. POP ES
  431. ASSUME DS:NOTHING,ES:NOTHING
  432. CLI
  433. MOV SS,[SSsave] ;Restore Entry Stack
  434. MOV SP,[SPsave]
  435. STI
  436. POP AX
  437. RET
  438. CONTEXT_BACK:
  439. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  440. CMP [CONTXTFLAG],0
  441. JZ CONTOK
  442. SaveReg <AX,BX>
  443. MOV BX,[HISPDB]
  444. MOV AH,SET_CURRENT_PDB
  445. call do_21
  446. RestoreReg <BX,AX>
  447. MOV [CONTXTFLAG],0
  448. CONTOK:
  449. RET
  450. CONTEXT_SWITCH:
  451. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  452. CMP [CONTXTFLAG],0
  453. JNZ RET45
  454. SaveReg <BX,AX>
  455. MOV AH,GET_CURRENT_PDB
  456. call do_21
  457. MOV [HISPDB],BX
  458. MOV BX,CS
  459. sub bx,10h ; The 2.5 print is an exe program
  460. MOV AH,SET_CURRENT_PDB
  461. call do_21
  462. RestoreReg <AX,BX>
  463. MOV [CONTXTFLAG],1
  464. RET45: RET
  465. ;--- Refill the print buffer ---
  466. READBUFF:
  467. ASSUME DS:CodeR,ES:NOTHING,SS:NOTHING
  468. call Set24 ; switch Int24 vector
  469. MOV [PABORT],0 ;No abort
  470. MOV BX,[CURRHAND]
  471. MOV CX,[BLKSIZ]
  472. MOV DX,[BUFFER]
  473. MOV AH,READ
  474. call My21
  475. PUSHF
  476. call Res24 ; reset Int 24 vector
  477. CMP [PABORT],0
  478. JZ NOHERR
  479. POP AX ;Flags from read
  480. jmp FilClose ;Barf on this file, got INT 24
  481. NOHERR:
  482. POPF
  483. JC FILEOF
  484. CMP AX,0
  485. JZ FILEOF ;Read EOF?
  486. MOV BX,[BUFFER] ;Buffer full
  487. MOV DI,BX
  488. ADD DI,AX
  489. MOV [NXTCHR],BX
  490. MOV CX,[BLKSIZ]
  491. SUB CX,AX
  492. JCXZ DONEJ ; Buffer is completely full
  493. PUSH CS
  494. POP ES
  495. MOV AL,1AH
  496. cld
  497. REP STOSB ; ^Z pad the buffer
  498. DONEJ:
  499. JMP DONEJMP
  500. FILEOF:
  501. MOV AL,0CH ;Form feed
  502. CALL POUT
  503. ;--- Close file
  504. ; note: we came here from an i24 then PAbort is already = 1
  505. FilClose:
  506. call Set24
  507. mov pAbort,-1
  508. MOV BX,[CURRHAND]
  509. MOV AH,CLOSE
  510. call My21
  511. call Res24
  512. MOV [CURRFIL],0 ; No file
  513. MOV [CURRHAND],-1 ; Invalid handle
  514. MOV AX,[ENDPTR]
  515. MOV [NXTCHR],AX ; Buffer empty
  516. ;--- Send close on output device
  517. call Close_Dev
  518. ;--- compact the print queue
  519. CompQAgn:
  520. call CompQ
  521. ;--- Check if there are any more files to print
  522. mov si,offset CodeR:FileQueue
  523. cmp byte ptr [si],0 ; no more left if name starts with nul
  524. je NoFilesLeft
  525. call Set24
  526. MOV [PABORT],0 ;No abort
  527. mov dx,si ; DS:DX points to file name
  528. mov ax,(open shl 8)
  529. call My21 ; try opening new file
  530. pushf
  531. call Res24
  532. cmp [PAbort],0
  533. je NoI24a
  534. popf
  535. jmp short CompQAgn ; try next file
  536. NoI24a:
  537. popf
  538. jnc GotNewFile
  539. call PrtOpErr
  540. jmp short CompQAgn
  541. GotNewFile: ; buffer was already marked as empty
  542. mov [CurrHand],ax
  543. mov [CurrFil],1
  544. ;--- Send Open on output device
  545. call Open_Dev
  546. NoFilesLeft:
  547. JMP DONEJMP
  548. ;--- Print open error ---
  549. ; preserves DS
  550. PrtOpErr:
  551. assume ds:CodeR,es:Nothing
  552. ; This stuff constitutes a "file" so it is bracketed by an open/close
  553. ; on the output device.
  554. ;--- Send Open on output device
  555. call Open_Dev
  556. push cs
  557. pop es
  558. assume es:CodeR
  559. mov si,offset CodeR:ErrMes
  560. call ListMes
  561. mov si,offset CodeR:ErrMesT2
  562. call ListMes
  563. mov si,offset CodeR:FileQueue
  564. call ListMes2
  565. mov si,offset CodeR:BelMes
  566. call ListMes
  567. ;--- Send close on output device
  568. call Close_Dev
  569. ret
  570. ;--- Compact File Queue ---
  571. ; modifies: AX,CX,SI,DI,ES
  572. CompQ:
  573. assume ds:CodeR,es:nothing,ss:nothing
  574. push cs
  575. pop es
  576. assume es:CodeR
  577. mov di,offset CodeR:FileQueue ; ES:DI points to top of queue
  578. mov si,(offset CodeR:FileQueue + MaxFileLen) ; DS:SI points to next entry
  579. mov cx,[EndQueue]
  580. sub cx,si ; length in bytes of the queue
  581. cld
  582. rep movsb ; compact the queue
  583. mov ax,[QueueTail] ; normalize tail pointer as we
  584. sub ax,MaxFileLen ; know have a new "next empty slot"
  585. mov [QueueTail],ax
  586. mov si,ax
  587. mov byte ptr [si],0 ; nul first byte of last entry
  588. ret
  589. BREAK <Resident Code: DSKERR>
  590. ;--- Set Local Int 24 vector ---
  591. ; modifies: AX,DX
  592. Set24:
  593. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  594. push es
  595. push bx
  596. push dx
  597. MOV AL,24H
  598. MOV AH,GET_INTERRUPT_VECTOR
  599. call do_21
  600. MOV WORD PTR [HERRINT+2],ES ; Save current vector
  601. MOV WORD PTR [HERRINT],BX
  602. MOV DX,OFFSET CodeR:DSKERR
  603. MOV AL,24H
  604. MOV AH,SET_INTERRUPT_VECTOR ; Install our own
  605. call do_21 ; Spooler must catch its errors
  606. pop dx
  607. pop bx
  608. pop es
  609. ret
  610. ;--- Reset Old Int 24 vector ---
  611. ; modifies: none
  612. Res24:
  613. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  614. push ds
  615. PUSH AX
  616. push dx
  617. LDS DX,[HERRINT]
  618. ASSUME DS:NOTHING
  619. MOV AL,24H
  620. MOV AH,SET_INTERRUPT_VECTOR
  621. call do_21 ;Restore Error INT
  622. pop dx
  623. POP AX
  624. pop ds
  625. ret
  626. ;--- INT 24 handler ---
  627. DSKERR:
  628. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  629. CMP [PABORT],0
  630. JNZ IGNRET
  631. STI
  632. PUSH BX
  633. PUSH CX
  634. PUSH DX
  635. PUSH DI
  636. PUSH SI
  637. PUSH BP
  638. PUSH ES
  639. PUSH DS
  640. PUSH CS
  641. POP DS
  642. PUSH CS
  643. POP ES
  644. ASSUME DS:CodeR,ES:CodeR
  645. ADD [BADDRVM],AL ;Set correct drive letter
  646. MOV SI,OFFSET CodeR:ERRMES
  647. CALL LISTMES
  648. TEST AH,080H
  649. JNZ FATERR
  650. AND DI,0FFH
  651. CMP DI,12
  652. JBE HAVCOD
  653. MOV DI,12
  654. HAVCOD:
  655. MOV [I24_ERR],DI
  656. SHL DI,1
  657. MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message
  658. MOV SI,DI
  659. CALL LISTMES ; Print error type
  660. MOV SI,OFFSET CodeR:ERRMEST
  661. CALL LISTMES
  662. mov si,offset CodeR:FileQueue ; print filename
  663. call ListMes2 ; print name
  664. mov si,offset CodeR:BelMes
  665. call ListMes
  666. SETABORT:
  667. INC [PABORT] ;Indicate abort
  668. POP DS
  669. POP ES
  670. POP BP
  671. POP SI
  672. POP DI
  673. POP DX
  674. POP CX
  675. POP BX
  676. IGNRET:
  677. XOR AL,AL ;Ignore
  678. IRET
  679. FATERR:
  680. MOV [I24_ERR],0FFH
  681. MOV SI,OFFSET CodeR:FATMES
  682. CALL LISTMES
  683. JMP SHORT SETABORT
  684. BREAK <Resident Code: SPCOMINT>
  685. ;--- Communications interrupt ---
  686. SPCOMINT proc far
  687. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  688. CMP AH,1
  689. JBE MINE
  690. JMP [COMNEXT]
  691. MINE:
  692. CMP AL,0F8H
  693. JAE RESERVED_RET
  694. IF HardInt
  695. CMP AX,0080h
  696. JNZ CheckPSP
  697. JMP FakeINT1C
  698. ENDIF
  699. CheckPSP:
  700. OR AH,AH
  701. JNE PSPDO
  702. MOV AL,1 ; Tell PSPRINT to go away (AH = 1)
  703. RESERVED_RET:
  704. IRET
  705. PSPDO:
  706. OR AL,AL
  707. JNE PSPDISP
  708. INST_REQ:
  709. MOV AL,0FFH
  710. IRET
  711. PSPDISP:
  712. CMP [BUSY],0
  713. JZ SETCBUSY
  714. ErrBusy:
  715. MOV AX,error_busy
  716. setcret:
  717. push bp
  718. mov bp,sp
  719. or word ptr [bp+6],f_Carry
  720. pop bp
  721. iret
  722. SETCBUSY:
  723. XOR AH,AH
  724. CMP AX,6 ; check function within valid range
  725. Jbe GoForIt
  726. mov ax,error_invalid_function
  727. jmp setcret
  728. GoForIt:
  729. INC [BUSY] ;Exclude
  730. STI ;Turn ints back on
  731. PUSH DI ;G
  732. PUSH ES
  733. PUSH DS
  734. PUSH CS
  735. POP DS
  736. ASSUME DS:CodeR
  737. mov [QueueLock],0 ; unlock the print queue
  738. SHL AX,1 ;Turn into word index
  739. mov di,ax
  740. call ComDisp[DI]
  741. assume ds:nothing
  742. jc ErrRet
  743. ASSUME DS:CodeR,ES:NOTHING
  744. push ds
  745. push cs
  746. pop ds
  747. ASSUME DS:CodeR,ES:NOTHING
  748. CALL PSTAT ; Tweek error counter
  749. pop ds
  750. assume ds:nothing
  751. ErrRet:
  752. pushf
  753. call Context_Back
  754. popf
  755. CLI
  756. DEC BUSY ; leaves carry alone!
  757. POP DS
  758. ASSUME DS:NOTHING
  759. POP ES
  760. POP DI ;G
  761. jc setcret
  762. push bp
  763. mov bp,sp
  764. and word ptr [bp+6],NOT f_Carry
  765. pop bp
  766. iret
  767. SpComInt Endp
  768. BREAK <Get queue status>
  769. ;--- Return pointer to file queue ---
  770. QSTAT:
  771. ASSUME DS:CodeR,ES:NOTHING
  772. mov [QueueLock],1 ; lock the print queue
  773. CALL PSTAT ; Tweek error counter
  774. push bp
  775. mov bp,sp ; 0 2 4
  776. MOV [bp+ 2 + 2],cs ; <BP> <RET> <DS>
  777. POP BP
  778. mov si,offset CodeR:FileQueue
  779. mov dx,[ErrCnt] ; return error count
  780. clc
  781. ret
  782. ;--- Return pointer to device driver if active ---
  783. QSTATDEV:
  784. ASSUME DS:CodeR,ES:NOTHING
  785. xor ax,ax ;g assume not busy
  786. mov [QueueLock],1 ;g lock the print queue
  787. CALL PSTAT ;g Tweek error counter
  788. cmp byte ptr FileQueue,0 ;g is there anything in the queue?
  789. clc ;g
  790. jz qstatdev_end ;g no - just exit
  791. mov ax,error_queue_full ;g yes - set error queue full
  792. mov si,word ptr [listdev+2] ;g get segment of list device
  793. push bp ;g
  794. mov bp,sp ;g 0 2 4
  795. MOV [bp+2+2],si ;g <BP><RET><DS> seg of device to DS
  796. pop bp ;g
  797. mov si,word ptr [listdev] ;g offset of device to SI
  798. stc ;g
  799. qstatdev_end: ;g
  800. mov [QueueLock],0 ;g unlock the print queue
  801. ret ;g
  802. BREAK <Resident Code: EndStat>
  803. ;--- Unlock the print queue ---
  804. EndStat:
  805. assume ds:CodeR,es:nothing
  806. mov [QueueLock],0
  807. clc
  808. ret
  809. BREAK <Cancel all available files in the queue>
  810. ;
  811. ; Note that we need to spin until the background is free
  812. ;
  813. CanAll:
  814. assume ds:CodeR,es:nothing
  815. cmp [CurrFil],0 ; are we currently printing?
  816. jnz DoCanAll ; yes, go and cancel
  817. ret ; carry is clear
  818. DoCanAll:
  819. ;--- Cancel active file
  820. mov bx,[CurrHand] ; close the current file
  821. call Set24
  822. mov [PAbort],1 ; no Int24's
  823. mov ah,Close
  824. call My21
  825. call Res24
  826. mov [CurrFil],0 ; no files to print
  827. mov [CurrHand],-1 ; invalidate handle
  828. mov ax,[EndPtr] ; buffer empty
  829. mov [NxtChr],ax
  830. ;--- Cancel rest of files
  831. mov si,offset CodeR:FileQueue
  832. mov [QueueTail],si ; next free entry is the first
  833. mov byte ptr [si],0 ; nul first byte of firts entry
  834. mov si,offset CodeR:AllCan
  835. call ListMes ; print cancelation message
  836. mov si,offset CodeR:BelMes
  837. call ListMes ; ring!!
  838. ;--- Send close on output device
  839. call Close_Dev
  840. clc
  841. ret
  842. BREAK <Cancel a file in progress>
  843. CANFIL:
  844. ASSUME DS:CodeR,ES:NOTHING
  845. CMP [CURRFIL],0
  846. JNZ DOCAN
  847. ret ; carry is clear
  848. DOCAN:
  849. ;--- find which file to cancel
  850. push bp
  851. mov bp,sp ; 0 2 4
  852. MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
  853. POP BP
  854. assume ds:nothing
  855. push cs
  856. pop es
  857. assume es:CodeR
  858. mov CS:[CanFlg],0 ; reset message flag
  859. mov CS:[ACanOcrd],0 ; no cancelation has ocured yet
  860. mov bx,offset CodeR:FileQueue ; ES:BX points to 1st entry in queue
  861. call AmbChk
  862. AnotherTry:
  863. mov di,bx ; ES:DI points to 1st entry in queue
  864. mov si,dx ; DS:SI points to filename to cancel
  865. MatchLoop:
  866. lodsb
  867. cmp al,byte ptr es:[di] ; names in queue are all in upper case
  868. je CharMatch
  869. call UpConv ; did not match, try upper case
  870. cmp al,byte ptr es:[di]
  871. jne AnotherName ; a mismatch, try another name
  872. CharMatch:
  873. cmp es:byte ptr es:[di],0 ; was this the terminating nul?
  874. je NameFound ; yes we got our file...
  875. inc di
  876. jmp MatchLoop
  877. AnotherName:
  878. cmp CS:[AmbCan],1 ; ambigous file name specified?
  879. jne AnName ; if not then no more work to do
  880. cmp al,"?"
  881. jne AnName
  882. cmp byte ptr es:[di],"."
  883. je FindPeriod
  884. cmp byte ptr es:[di],0 ; if nul then file names match
  885. jne CharMatch ; only if only ?'s are left...
  886. FindNul:
  887. lodsb
  888. cmp al,"?"
  889. je FindNul
  890. cmp al,"."
  891. je FindNul
  892. or al,al
  893. jne AnName ; found something else, no match
  894. jmp short NameFound
  895. FindPeriod: ; ambigous files always have 8 chars
  896. lodsb ; in name so we can not look for the
  897. or al,al ; period twice (smart uh?)
  898. je AnName ; no period found, files do not match
  899. cmp al,"."
  900. jne FindPeriod
  901. jmp short CharMatch
  902. AnName:
  903. add bx,MaxFileLen
  904. cmp byte ptr es:[bx],0 ; end of queue?
  905. jne AnotherTry ; no, continue...
  906. cmp CS:[ACanOcrd],1 ; yes, was there a file found?
  907. jne sk2
  908. push cs
  909. pop ds
  910. assume ds:CodeR ; StartAnFil likes it this way...
  911. jmp StartAnFil ; restart printing
  912. sk2:
  913. assume ds:nothing
  914. mov ax,error_file_not_found
  915. stc
  916. ret
  917. ;--- Name found, check if current file
  918. NameFound:
  919. push cs
  920. pop ds
  921. assume ds:CodeR
  922. mov [ACanOcrd],1 ; remember we found a file
  923. cmp bx,offset CodeR:FileQueue ; is the file being printed?
  924. jne NotCurrent ; no, just compact the queue
  925. cmp [CanFlg],0
  926. jne NotCurrent ; only cance current once
  927. ;--- Cancel current file
  928. mov [CanFlg],1 ; remeber we already canceled current
  929. push bx
  930. mov bx,[CurrHand] ; close the current file
  931. call Set24
  932. mov [PAbort],1 ; no Int24's
  933. mov ah,Close
  934. call My21
  935. call Res24
  936. mov [CurrFil],0 ; no files to print
  937. mov [CurrHand],-1 ; invalidate handle
  938. mov ax,[EndPtr] ; buffer empty
  939. mov [NxtChr],ax
  940. pop bx
  941. ;--- print cancelation message
  942. push bx
  943. mov si,offset CodeR:CanMes
  944. call ListMes ; print cancelation message
  945. mov si,bx ; points to filename
  946. call ListMes2 ; print filename
  947. mov si,offset CodeR:CanFilNam
  948. call ListMes
  949. mov si,offset CodeR:BelMes
  950. call ListMes ; ring!!
  951. pop bx
  952. ;--- Send close on output device
  953. call Close_Dev
  954. NotCurrent:
  955. mov di,bx ; DI points to entry to cancel
  956. mov si,bx
  957. add si,MaxFileLen ; SI points to next entry
  958. cmp si,[QueueTail] ; is the entry being canceled the last?
  959. jne DoCompact ; no, do compaction
  960. mov byte ptr [di],0 ; yes, just nul the first byte
  961. jmp short CompactDone
  962. DoCompact:
  963. mov cx,[EndQueue] ; CX points to the end of the queue
  964. sub cx,si ; length of the remainning of the queue
  965. cld
  966. rep movsb ; compact the queue
  967. CompactDone:
  968. mov ax,[QueueTail] ; remember new end of queue
  969. sub ax,MaxFileLen
  970. mov [QueueTail],ax
  971. mov si,ax
  972. mov byte ptr [si],0 ; nul first byte of last entry
  973. cmp byte ptr [bx],0 ; is there another file to consider?
  974. je StartAnFil
  975. push bp
  976. mov bp,sp ; 0 2 4
  977. MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
  978. POP BP
  979. assume ds:nothing
  980. jmp AnotherTry ; yes do it again...
  981. ;--- Start new file...
  982. StartAnFil:
  983. assume ds:CodeR
  984. cmp [CurrHand],-1 ; was the canceled name the current?
  985. jne NoneLeft ; no, just quit
  986. StartAnFil2:
  987. mov si,offset CodeR:FileQueue ; points to new current file
  988. cmp byte ptr[si],0 ; is there one there?
  989. je NoneLeft ; no, we canceled current and are none left
  990. call Set24
  991. mov [PAbort],0
  992. mov dx,si
  993. mov ax,(open shl 8)
  994. call My21
  995. pushf
  996. call Res24
  997. cmp [PAbort],0
  998. je NoI24b
  999. popf
  1000. call CompQ ; compact file queue
  1001. jmp short StartAnFil2
  1002. NoI24b:
  1003. popf
  1004. jnc GoodNewCurr
  1005. call PrtOpErr ; print open error
  1006. call CompQ ; compact file queue
  1007. jmp short StartAnFil2
  1008. GoodNewCurr:
  1009. mov [CurrHand],ax ; save handle
  1010. mov [CurrFil],1 ; signal active (buffer is already empty)
  1011. ;--- Send Open on output device
  1012. call Open_Dev
  1013. NoneLeft:
  1014. clc
  1015. ret
  1016. ;--- Upper case conversion ---
  1017. UpConv:
  1018. CMP AL,'a'
  1019. JB NOCONV
  1020. CMP AL,'z'
  1021. JA NOCONV
  1022. SUB AL,20H
  1023. NOCONV:
  1024. RET
  1025. ;--- Ambigous file name check ---
  1026. ; entry: ds:dx points to filename
  1027. ; preserves ds:dx and es
  1028. ;
  1029. assume ds:nothing,es:CodeR
  1030. AmbChk:
  1031. mov CS:[AmbCan],0 ; assume not ambigous
  1032. mov si,dx
  1033. cld
  1034. AmbLoop:
  1035. lodsb
  1036. or al,al ; the nul?
  1037. jne AmbLoop
  1038. dec si ; points to nul
  1039. std ; scan backwards
  1040. ScanBack:
  1041. lodsb
  1042. cmp al,"*"
  1043. jne NotAStar
  1044. mov CS:[AmbCan],1
  1045. NotAStar:
  1046. cmp al,"?"
  1047. jne NotAQues
  1048. mov CS:[AmbCan],1
  1049. NotAQues:
  1050. cmp al,CS:[PChar]
  1051. jne ScanBack
  1052. cld ; be safe
  1053. cmp CS:[AmbCan],1 ; an ambigous cancel?
  1054. je AmbCanFnd ; no, just proceed
  1055. ret
  1056. ;--- transform * to ?'s
  1057. AmbCanFnd:
  1058. inc si
  1059. inc si ; points to actual name (past path char)
  1060. mov di,offset CodeR:ACBuf
  1061. push di
  1062. mov cx,12
  1063. mov al,20h
  1064. cld
  1065. rep stosb ; fill fcb with blanks
  1066. pop di
  1067. push si
  1068. mov ax,(Parse_file_descriptor shl 8) and 0FF00h
  1069. call My21
  1070. pop si
  1071. ;--- Copy name to expanded name
  1072. push ds
  1073. pop es
  1074. assume ds:nothing
  1075. push cs
  1076. pop ds
  1077. assume ds:CodeR
  1078. push es
  1079. mov di,si
  1080. mov si,offset CodeR:ACName
  1081. mov cx,8
  1082. ACMovNam:
  1083. lodsb ; move name
  1084. cmp al,20h
  1085. je ACMovDn1
  1086. stosb
  1087. loop ACMovNam
  1088. ACMovDn1:
  1089. mov si,offset CodeR:ACExt
  1090. cmp byte ptr [si],20h ; if extension starts with blank
  1091. je ACMovDn2 ; then do not put period
  1092. mov al,"."
  1093. stosb
  1094. mov cx,3
  1095. ACMovExt:
  1096. lodsb ; move name
  1097. cmp al,20h
  1098. je ACMovDn2
  1099. stosb
  1100. loop ACMovExt
  1101. ACMovDn2:
  1102. mov byte ptr es:[di],0 ; nul terminate
  1103. pop ds
  1104. assume ds:nothing
  1105. push cs
  1106. pop es
  1107. assume es:CodeR
  1108. ret
  1109. BREAK <Add a file to the queue>
  1110. ADDFIL:
  1111. ASSUME DS:CodeR,ES:NOTHING
  1112. ;--- Check that queue is not full
  1113. mov di,[QueueTail] ; load pointer to next empty entry
  1114. cmp di,[EndQueue] ; queue full?
  1115. jb OkToQueue ; no, place in queue...
  1116. mov ax,error_queue_full
  1117. stc
  1118. ret
  1119. ;--- Copy name to empty slot in queue
  1120. OkToQueue:
  1121. ;
  1122. ; Retrieve old DS
  1123. ;
  1124. push bp
  1125. mov bp,sp ; 0 2 4
  1126. MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
  1127. POP BP
  1128. assume ds:nothing
  1129. push cs
  1130. pop es ; ES:DI points to empty slot
  1131. assume es:CodeR
  1132. mov si,dx ; DS:SI points to submit packet
  1133. cmp byte ptr ds:[si],0
  1134. jnz IncorrectLevel
  1135. lds si,dword ptr ds:[si+1] ; DS:SI points to filename
  1136. mov cx,MaxFileLen ; maximum length of file name
  1137. CopyLop:
  1138. lodsb
  1139. call UpConv ; convert to upper case
  1140. stosb
  1141. or al,al ; nul?
  1142. je CopyDone ; yes, done with move...
  1143. loop CopyLop
  1144. push cs
  1145. pop ds
  1146. assume ds:CodeR
  1147. mov ax,error_name_too_long ; if normal exit from the loop then
  1148. stc
  1149. ret
  1150. IncorrectLevel:
  1151. mov ax,error_invalid_function
  1152. stc
  1153. ret
  1154. assume ds:nothing,es:nothing ; es:nothing = not true but lets
  1155. CopyDone: ; avoid possible problems...
  1156. push cs
  1157. pop ds
  1158. assume ds:CodeR
  1159. ;--- advance queue pointer
  1160. mov si,[QueueTail] ; pointer to slot just used
  1161. push si ; save for test open later
  1162. add si,MaxFileLen
  1163. mov [QueueTail],si ; store for next round
  1164. mov byte ptr [si],0 ; nul next entry (maybe the EndQueue)
  1165. ;--- Check that file exists
  1166. call Set24
  1167. mov [PAbort],0
  1168. pop dx ; get pointer to filename
  1169. MOV AX,(OPEN SHL 8)
  1170. call My21
  1171. pushf
  1172. PUSH DX
  1173. call Res24
  1174. POP DX
  1175. popf
  1176. JNC GOTFIL
  1177. ;
  1178. ; See if brain damaged user entered an invalid drive
  1179. ;
  1180. PUSH AX
  1181. MOV SI,DX
  1182. CMP BYTE PTR CS:[SI+1],':'
  1183. JZ GotDrive
  1184. POP AX
  1185. JMP SHORT i24bf
  1186. GotDrive:
  1187. MOV AH,Get_default_drive ; get current
  1188. CALL My21
  1189. PUSH AX
  1190. MOV DL,CS:[SI] ; get drive letter to test
  1191. OR DL,20h
  1192. SUB DL,'a'
  1193. MOV AH,Set_Default_Drive ; set it
  1194. CALL My21
  1195. MOV AH,Get_default_drive ; get it back
  1196. CALL My21
  1197. CMP AL,DL ; same?
  1198. JNZ BadDrive ; no, bad drive
  1199. POP DX ; get original back
  1200. MOV AH,Set_Default_Drive ; set original
  1201. CALL My21
  1202. POP AX
  1203. MOV DX,SI
  1204. JMP SHORT i24bf
  1205. BadDrive:
  1206. POP DX ; get original back
  1207. MOV AH,Set_Default_Drive ; set original
  1208. CALL My21
  1209. POP AX
  1210. MOV AX,error_invalid_drive
  1211. MOV DX,SI
  1212. I24BF:
  1213. mov si,[QueueTail] ; take bad name out of queue
  1214. sub si,MaxFileLen ; SI points to the slot with bad name
  1215. mov [QueueTail],si
  1216. mov byte ptr [si],0 ; nul the first byte
  1217. stc
  1218. ret
  1219. ;--- Check if print currently busy
  1220. GotFil:
  1221. CMP [CURRFIL],0 ; currently printing?
  1222. JZ OKAFIL ; no, start new print
  1223. mov bx,ax ; busy, close handle
  1224. call Set24
  1225. mov [PAbort],1 ; no Int24's
  1226. mov ah,Close
  1227. call My21
  1228. call Res24
  1229. clc
  1230. ret
  1231. ;--- Save file data
  1232. OKAFIL:
  1233. MOV [CURRHAND],AX ; Valid handle
  1234. MOV AX,[ENDPTR]
  1235. MOV [NXTCHR],AX ; Buffer empty
  1236. MOV [CURRFIL],1
  1237. ;--- Send Open on output device
  1238. call Open_Dev
  1239. clc
  1240. ret
  1241. BREAK <Fake int 21H>
  1242. ;
  1243. ; perform a system call as myself
  1244. ;
  1245. My21:
  1246. call Context_switch
  1247. call Do_21
  1248. ret
  1249. Public do_21
  1250. DO_21:
  1251. ASSUME DS:NOTHING,ES:NOTHING
  1252. IF IBM
  1253. CMP BYTE PTR CS:[INT15FLAG],0
  1254. JZ REAL_21
  1255. PUSH DS
  1256. PUSH BX
  1257. LDS BX,CS:[INT15PTR]
  1258. INC BYTE PTR [BX]
  1259. POP BX
  1260. POP DS
  1261. CALL OffSave
  1262. INT 21H
  1263. Call OnSave
  1264. PUSH DS
  1265. PUSH BX
  1266. PUSHF ; Flags from system call
  1267. LDS BX,CS:[INT15PTR]
  1268. DEC BYTE PTR [BX]
  1269. POPF
  1270. POP BX
  1271. POP DS
  1272. RET
  1273. ENDIF
  1274. REAL_21:
  1275. Call OffSave
  1276. INT 21H
  1277. CALL OnSave
  1278. RET
  1279. OffSave:
  1280. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1281. PUSH AX
  1282. PUSH DX
  1283. MOV AX,Set_CTRL_C_Trapping SHL 8 + 2
  1284. XOR DL,DL
  1285. INT 21h
  1286. MOV CtrlC,DL
  1287. POP DX
  1288. POP AX
  1289. ret
  1290. OnSave:
  1291. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1292. PUSH AX
  1293. PUSH DX
  1294. MOV AX,Set_CTRL_C_Trapping SHL 8 + 2
  1295. MOV DL,CtrlC
  1296. INT 21h
  1297. POP DX
  1298. POP AX
  1299. ret
  1300. BREAK <Priter Support>
  1301. ListMes2:
  1302. ASSUME DS:CodeR,ES:NOTHING
  1303. LODSB
  1304. cmp al,0
  1305. jz LMesDone
  1306. CALL LOUT
  1307. JMP short LISTMES2
  1308. LISTMES:
  1309. ASSUME DS:CodeR,ES:NOTHING
  1310. LODSB
  1311. CMP AL,"$"
  1312. JZ LMESDONE
  1313. CALL LOUT
  1314. JMP short LISTMES
  1315. LMESDONE:
  1316. RET
  1317. LOUT:
  1318. PUSH BX
  1319. LWAIT:
  1320. CALL PSTAT
  1321. JZ PREADY
  1322. CMP [ERRCNT],ERRCNT2
  1323. JA POPRET ;Don't get stuck
  1324. JMP SHORT LWAIT
  1325. PREADY:
  1326. CALL POUT
  1327. POPRET:
  1328. POP BX
  1329. RET
  1330. ;Stuff for BIOS interface
  1331. IOBUSY EQU 0200H
  1332. IOERROR EQU 8000H
  1333. public PRNR003S, PRNR003E
  1334. PRNR003S:
  1335. BYTEBUF DB ?
  1336. CALLAD DD ?
  1337. IOCALL DB 22
  1338. DB 0
  1339. IOREQ DB ?
  1340. IOSTAT DW 0
  1341. DB 8 DUP(?)
  1342. DB 0
  1343. DW OFFSET CodeR:BYTEBUF
  1344. INTSEG DW ?
  1345. IOCNT DW 1
  1346. DW 0
  1347. PRNR003E:
  1348. ; Following two routines perform device open and close on output device.
  1349. ; NO REGISTERS (including flags) are modified. No errors generated.
  1350. public open_dev
  1351. Open_Dev:
  1352. ASSUME DS:NOTHING,ES:NOTHING
  1353. ;
  1354. ; We are now going to use the printer... We must lock down the printer so
  1355. ; that the network does not intersperse output on us...
  1356. ; We must also signal the REDIRector for stream open.
  1357. ; We must ask DOS to set the Printer Flag to busy
  1358. ;
  1359. PUSH BX
  1360. PUSHF
  1361. PUSH AX
  1362. PUSH DX
  1363. MOV DX,PrinterNum
  1364. CMP DX,-1
  1365. JZ NoORop
  1366. MOV AX,0203h ; redirector lock
  1367. INT 2FH
  1368. MOV AX,0201H ; Redirector OPEN
  1369. INT 2FH
  1370. NoORop:
  1371. mov ax,(SET_PRINTER_FLAG SHL 8) + 01
  1372. int 21H
  1373. POP DX
  1374. POP AX
  1375. MOV BL,DEVOPN ; Device OPEN
  1376. CALL OP_CL_OP
  1377. POPF
  1378. POP BX
  1379. RET
  1380. OP_CL_OP:
  1381. PUSH DS
  1382. PUSH SI
  1383. LDS SI,[LISTDEV]
  1384. ASSUME DS:NOTHING
  1385. TEST [SI.SDEVATT],DEVOPCL
  1386. JZ NO_OP_CL
  1387. PUSH CS
  1388. POP DS
  1389. ASSUME DS:CodeR
  1390. MOV [IOCALL],DOPCLHL
  1391. CALL DOCALL
  1392. NO_OP_CL:
  1393. POP SI
  1394. POP DS
  1395. ASSUME DS:NOTHING
  1396. Ret
  1397. public close_dev
  1398. Close_Dev:
  1399. ASSUME DS:NOTHING,ES:NOTHING
  1400. ;
  1401. ; At this point, we release the ownership of the printer...
  1402. ; and do a redirector CLOSE.
  1403. ; Also tell DOS to reset the Printer Flag
  1404. ;
  1405. PUSH BX
  1406. PUSHF
  1407. MOV BL,DEVCLS
  1408. CALL OP_CL_OP ; Device CLOSE
  1409. PUSH AX
  1410. PUSH DX
  1411. MOV DX,PrinterNum
  1412. CMP DX,-1
  1413. JZ NoCRop
  1414. MOV AX,0202H ; redirector CLOSE
  1415. INT 2FH
  1416. MOV AX,0204h ; redirector clear
  1417. INT 2FH
  1418. NoCRop:
  1419. MOV AX,(SET_PRINTER_FLAG SHL 8) +00
  1420. INT 21H
  1421. POP DX
  1422. POP AX
  1423. POPF
  1424. POP BX
  1425. RET
  1426. PSTAT:
  1427. ASSUME DS:CodeR
  1428. PUSH BX
  1429. INC [ERRCNT]
  1430. MOV BL,DEVOST
  1431. MOV [IOCALL],DSTATHL
  1432. CALL DOCALL
  1433. TEST [IOSTAT],IOERROR
  1434. JZ NOSTATERR
  1435. OR [IOSTAT],IOBUSY ;If error, show buisy
  1436. NOSTATERR:
  1437. TEST [IOSTAT],IOBUSY
  1438. JNZ RET13P ;Shows buisy
  1439. MOV [ERRCNT],0
  1440. RET13P:
  1441. POP BX
  1442. RET
  1443. POUT:
  1444. ASSUME DS:CodeR
  1445. MOV [BYTEBUF],AL
  1446. MOV BL,DEVWRT
  1447. MOV [IOCALL],DRDWRHL
  1448. DOCALL:
  1449. PUSH ES
  1450. MOV [IOREQ],BL
  1451. MOV BX,CS
  1452. MOV ES,BX
  1453. MOV [IOSTAT],0
  1454. MOV [IOCNT],1
  1455. PUSH DS
  1456. PUSH SI
  1457. PUSH AX
  1458. call Context_Switch
  1459. MOV BX,OFFSET CodeR:IOCALL
  1460. LDS SI,[LISTDEV]
  1461. ASSUME DS:NOTHING
  1462. MOV AX,[SI+SDEVSTRAT]
  1463. MOV WORD PTR [CALLAD],AX
  1464. CALL [CALLAD]
  1465. MOV AX,[SI+SDEVINT]
  1466. MOV WORD PTR [CALLAD],AX
  1467. CALL [CALLAD]
  1468. POP AX
  1469. POP SI
  1470. POP DS
  1471. ASSUME DS:CodeR
  1472. POP ES
  1473. RET
  1474. IF IBM
  1475. Public PRNR004S, PRNR004E
  1476. PRNR004S:
  1477. REAL_INT_13 DD ?
  1478. INT_13_RETADDR DW OFFSET CodeR:INT_13_BACK
  1479. PRNR004E:
  1480. INT_13 PROC FAR
  1481. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1482. PUSHF
  1483. INC [BUSY] ;Exclude if dumb program call ROM
  1484. PUSH CS
  1485. PUSH [INT_13_RETADDR]
  1486. PUSH WORD PTR [REAL_INT_13+2]
  1487. PUSH WORD PTR [REAL_INT_13]
  1488. RET
  1489. INT_13 ENDP
  1490. INT_13_BACK PROC FAR
  1491. PUSHF
  1492. DEC [BUSY]
  1493. POPF
  1494. RET 2 ;Chuck saved flags
  1495. INT_13_BACK ENDP
  1496. ENDIF
  1497. IF IBM
  1498. Public PRNR005S, PRNR005E
  1499. PRNR005S:
  1500. REAL_INT_15 DD ?
  1501. INT15FLAG DB 0 ; Init to off
  1502. INT15PTR DD ?
  1503. PRNR005E:
  1504. INT_15 PROC FAR
  1505. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1506. CMP AH,20H
  1507. JNZ REAL_15 ; Not my function
  1508. CMP AL,1
  1509. JA REAL_15 ; I only know 0 and 1
  1510. JE FUNC1
  1511. INC [INT15FLAG] ; Turn ON
  1512. MOV WORD PTR [INT15PTR],BX ; Save counter loc
  1513. MOV WORD PTR [INT15PTR+2],ES
  1514. IRET
  1515. FUNC1:
  1516. MOV [INT15FLAG],0 ; Turn OFF
  1517. IRET
  1518. REAL_15:
  1519. JMP [REAL_INT_15]
  1520. INT_15 ENDP
  1521. Public PRNR006S, PRNR006E
  1522. PRNR006S:
  1523. FLAG17_14 DB 0 ; Flags state of AUX/PRN redir
  1524. REAL_INT_5 DD ?
  1525. REAL_INT_17 DD ?
  1526. INT_17_NUM DW 0
  1527. PRNR006E:
  1528. INT_17:
  1529. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1530. CMP [FLAG17_14],1
  1531. JNZ DO_INT_17 ;The PRN device is not used
  1532. CMP [CURRFIL],0
  1533. JZ DO_INT_17 ;Nothing pending, so OK
  1534. CMP DX,[INT_17_NUM]
  1535. JNZ DO_INT_17 ;Not my unit
  1536. CMP [BUSY],0
  1537. JNZ DO_INT_17 ;You are me
  1538. STI
  1539. MOV AH,0A1H ;You are bad, get time out
  1540. IRET
  1541. DO_INT_17:
  1542. JMP [REAL_INT_17] ;Do a 17
  1543. Public PRNR007S, PRNR007E
  1544. PRNR007S:
  1545. REAL_INT_14 DD ?
  1546. INT_14_NUM DW 0
  1547. PRNR007E:
  1548. INT_14:
  1549. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1550. CMP [FLAG17_14],2
  1551. JNZ DO_INT_14 ;The AUX device is not used
  1552. CMP [CURRFIL],0
  1553. JZ DO_INT_14 ;Nothing pending, so OK
  1554. CMP DX,[INT_14_NUM]
  1555. JNZ DO_INT_14 ;Not my unit
  1556. CMP [BUSY],0
  1557. JNZ DO_INT_14 ;You are me
  1558. STI
  1559. OR AH,AH
  1560. JZ SET14_AX
  1561. CMP AH,2
  1562. JBE SET14_AH
  1563. SET14_AX:
  1564. MOV AL,0
  1565. SET14_AH:
  1566. MOV AH,80H ;Time out
  1567. IRET
  1568. DO_INT_14:
  1569. JMP [REAL_INT_14] ;Do a 14
  1570. INT_5:
  1571. ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
  1572. CMP [FLAG17_14],1
  1573. JNZ DO_INT_5 ;The PRN device is not used
  1574. CMP [CURRFIL],0
  1575. JZ DO_INT_5 ;Nothing pending, so OK
  1576. CMP [INT_17_NUM],0
  1577. JNZ DO_INT_5 ;Only care about unit 0
  1578. IRET ;Pretend it worked
  1579. DO_INT_5:
  1580. JMP [REAL_INT_5] ;Do a 5
  1581. ENDIF
  1582. Public PRNR008S, PRNR008E
  1583. PRNR008S:
  1584. ERRCNT DW 0
  1585. IF IBM
  1586. ;Reserved names for parallel card
  1587. INT_17_HITLIST LABEL BYTE
  1588. DB 8,"PRN ",0
  1589. DB 8,"LPT1 ",0
  1590. DB 8,"LPT2 ",1
  1591. DB 8,"LPT3 ",2
  1592. DB 0
  1593. ;Reserved names for Async adaptor
  1594. INT_14_HITLIST LABEL BYTE
  1595. DB 8,"AUX ",0
  1596. DB 8,"COM1 ",0
  1597. DB 8,"COM2 ",1
  1598. ;--------------------------------------------------------------bug330a09
  1599. DB 8,"COM3 ",2
  1600. DB 8,"COM4 ",3
  1601. ;--------------------------------------------------------------bug330a09
  1602. DB 0
  1603. ENDIF
  1604. LISTNAME DB "PRN " ;Device name
  1605. PRNR008E:
  1606. SETDEV:
  1607. ASSUME CS:CodeR,DS:CodeR,ES:NOTHING,SS:NOTHING
  1608. ; LISTNAME has the 8 char device name IN UPPER CASE
  1609. ; CARRY set if bad device
  1610. ; DS preserved, others destroyed.
  1611. MOV AH,GET_IN_VARS
  1612. call My21
  1613. PUSH ES
  1614. POP DS
  1615. LEA SI,ES:[BX.SYSI_DEV]
  1616. ASSUME DS:NOTHING
  1617. PUSH CS
  1618. POP ES
  1619. ASSUME ES:CodeR
  1620. MOV DI,OFFSET CodeR:LISTNAME
  1621. LOOKDEV:
  1622. TEST [SI.SDEVATT],DEVTYP
  1623. JZ NEXTDEV ; Skip Block devs
  1624. PUSH SI
  1625. PUSH DI
  1626. ADD SI,SDEVNAME ; Point at name
  1627. MOV CX,8
  1628. REPE CMPSB
  1629. POP DI
  1630. POP SI
  1631. JE GOTDEV
  1632. NEXTDEV:
  1633. LDS SI,[SI.SDEVNEXT]
  1634. CMP SI,-1
  1635. JNZ LOOKDEV
  1636. PUSH CS
  1637. POP DS
  1638. STC
  1639. RET
  1640. GOTDEV:
  1641. MOV WORD PTR CS:[CALLAD+2],DS ;Get I/O routines
  1642. MOV WORD PTR CS:[LISTDEV+2],DS ;Get I/O routines
  1643. MOV WORD PTR CS:[LISTDEV],SI
  1644. PUSH CS
  1645. POP DS
  1646. ASSUME DS:CodeR
  1647. IF IBM
  1648. MOV PrinterNum,-1 ; Assume not an INT 17 device
  1649. PUSH CS
  1650. POP ES
  1651. ASSUME ES:CodeR
  1652. MOV BP,OFFSET CodeR:LISTNAME
  1653. MOV SI,BP
  1654. MOV DI,OFFSET CodeR:INT_17_HITLIST
  1655. CHKHIT:
  1656. MOV SI,BP
  1657. MOV CL,[DI]
  1658. INC DI
  1659. JCXZ NOTONHITLIST
  1660. REPE CMPSB
  1661. LAHF
  1662. ADD DI,CX ;Bump to next position without affecting flags
  1663. MOV BL,[DI] ;Get device number
  1664. INC DI
  1665. SAHF
  1666. JNZ CHKHIT
  1667. XOR BH,BH
  1668. MOV [INT_17_NUM],BX
  1669. MOV PrinterNum,BX ; Set this as well to the INT 17 device
  1670. MOV [FLAG17_14],1
  1671. JMP SHORT ALLSET
  1672. NOTONHITLIST:
  1673. MOV DI,OFFSET CodeR:INT_14_HITLIST
  1674. CHKHIT2:
  1675. MOV SI,BP
  1676. MOV CL,[DI]
  1677. INC DI
  1678. JCXZ NOTONHITLIST2
  1679. REPE CMPSB
  1680. LAHF
  1681. ADD DI,CX ;Bump to next position without affecting flags
  1682. MOV BL,[DI] ;Get device number
  1683. INC DI
  1684. SAHF
  1685. JNZ CHKHIT2
  1686. XOR BH,BH
  1687. MOV [INT_14_NUM],BX
  1688. MOV [FLAG17_14],2
  1689. JMP SHORT ALLSET
  1690. NOTONHITLIST2:
  1691. MOV [FLAG17_14],0
  1692. ALLSET:
  1693. ENDIF
  1694. CLC
  1695. RET
  1696. IF HARDINT
  1697. BREAK <Bootstrap Cleanup Code>
  1698. ReBtINT:
  1699. ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:Nothing
  1700. CLI
  1701. push cs
  1702. pop ds
  1703. IntWhileBusy:
  1704. INT ComInt
  1705. JNC NotBusy
  1706. JMP IntWhileBusy
  1707. ret
  1708. NotBusy:
  1709. INC [BUSY] ; Exclude hardware interrupts
  1710. INC [SOFINT] ; Exclude software interrupts
  1711. call CanAll ; Purge the Queue
  1712. LDS DX,CodeR:COMNEXT
  1713. mov ax,(set_interrupt_vector shl 8) or comint
  1714. INT 21H ;Set int 2f vector
  1715. LDS DX,CodeR:NEXTINT
  1716. mov ax,(set_interrupt_vector shl 8) or intloc
  1717. INT 21H ;Set hardware interrupt
  1718. mov ax,(set_interrupt_vector shl 8) or 15h
  1719. lds dx,CodeR:Real_Int_15 ; Reset the wait on event on ATs
  1720. int 21h
  1721. mov ax,(set_interrupt_vector shl 8) or 17h
  1722. LDS DX,CodeR:Real_Int_17
  1723. INT 21H ;Set printer interrupt
  1724. mov ax,(set_interrupt_vector shl 8) or 5h
  1725. LDS DX,CodeR:Real_Int_5
  1726. INT 21H ;Set print screen interrupt
  1727. mov ax,(set_interrupt_vector shl 8) or 14h
  1728. LDS DX,CodeR:Real_Int_14
  1729. INT 21H ;Set printer interrupt
  1730. mov ax,(set_interrupt_vector shl 8) or 24h
  1731. LDS DX,CodeR:HERRINT
  1732. INT 21H ;Set printer interrupt
  1733. LDS DX,CodeR:NEXT_REBOOT
  1734. mov ax,(set_interrupt_vector shl 8) or reboot
  1735. INT 21H ;Set bootstrap interrupt
  1736. STI
  1737. INT 19H
  1738. ENDIF ; HARDINT
  1739. ;----- File name Queue and data buffer goes here
  1740. Public PRNR009S
  1741. PRNR009S:
  1742. FileQueue Label byte
  1743. db 0 ; the file queue starts empty
  1744. BREAK <Initialization Code>
  1745. BADSPOOL:
  1746. ASSUME CS:CodeR,DS:CodeR,ES:NOTHING,SS:Nothing
  1747. MOV DX,OFFSET CODER:BADMES
  1748. mov cx,badmeslen
  1749. mov bx,stdout
  1750. mov ah,write
  1751. INT 21H
  1752. ;*********************************************************************
  1753. MOV AX,(SET_PRINTER_FLAG SHL 8) ; Set flag to Idle
  1754. int 21H
  1755. ;*********************************************************************
  1756. MOV AX,(EXIT SHL 8) OR 0FFH
  1757. INT 21H
  1758. ;--- move transient out of the way
  1759. ContTrans dd ? ; transient continuation address after move
  1760. MoveTrans label far
  1761. ASSUME CS:CodeR,DS:CodeR,ES:CodeR,SS:Nothing
  1762. cli
  1763. CLD
  1764. MOV [INTSEG],CS
  1765. CALL SETDEV
  1766. ASSUME ES:NOTHING
  1767. JC BADSPOOL
  1768. MOV DX,OFFSET CodeR:SPINT
  1769. MOV AL,SOFTINT
  1770. MOV AH,GET_INTERRUPT_VECTOR
  1771. INT 21H ;Get soft vector
  1772. MOV WORD PTR [SPNEXT+2],ES
  1773. MOV WORD PTR [SPNEXT],BX
  1774. MOV AL,SOFTINT
  1775. MOV AH,SET_INTERRUPT_VECTOR
  1776. INT 21H ;Set soft vector
  1777. MOV DX,OFFSET CodeR:SPCOMINT
  1778. MOV AL,ComInt
  1779. MOV AH,GET_INTERRUPT_VECTOR
  1780. INT 21H ;Get communication vector
  1781. MOV WORD PTR [COMNEXT+2],ES
  1782. MOV WORD PTR [COMNEXT],BX
  1783. MOV AL,ComInt
  1784. MOV AH,SET_INTERRUPT_VECTOR ;Set communication vector
  1785. INT 21H
  1786. IF IBM
  1787. MOV AL,13H
  1788. MOV AH,GET_INTERRUPT_VECTOR
  1789. INT 21H
  1790. MOV WORD PTR [REAL_INT_13+2],ES
  1791. MOV WORD PTR [REAL_INT_13],BX
  1792. MOV DX,OFFSET CodeR:INT_13
  1793. MOV AL,13H
  1794. MOV AH,SET_INTERRUPT_VECTOR
  1795. INT 21H ;Set diskI/O interrupt
  1796. MOV AL,15H
  1797. MOV AH,GET_INTERRUPT_VECTOR
  1798. INT 21H
  1799. MOV WORD PTR [REAL_INT_15+2],ES
  1800. MOV WORD PTR [REAL_INT_15],BX
  1801. MOV DX,OFFSET CodeR:INT_15
  1802. MOV AL,15H
  1803. MOV AH,SET_INTERRUPT_VECTOR
  1804. INT 21H ;Set INT 15 vector
  1805. MOV AL,17H
  1806. MOV AH,GET_INTERRUPT_VECTOR
  1807. INT 21H
  1808. MOV WORD PTR [REAL_INT_17+2],ES
  1809. MOV WORD PTR [REAL_INT_17],BX
  1810. MOV DX,OFFSET CodeR:INT_17
  1811. MOV AL,17H
  1812. MOV AH,SET_INTERRUPT_VECTOR
  1813. INT 21H ;Set printer interrupt
  1814. MOV AL,14H
  1815. MOV AH,GET_INTERRUPT_VECTOR
  1816. INT 21H
  1817. MOV WORD PTR [REAL_INT_14+2],ES
  1818. MOV WORD PTR [REAL_INT_14],BX
  1819. MOV DX,OFFSET CodeR:INT_14
  1820. MOV AL,14H
  1821. MOV AH,SET_INTERRUPT_VECTOR
  1822. INT 21H ;Set RS232 port interrupt
  1823. MOV AL,5H
  1824. MOV AH,GET_INTERRUPT_VECTOR
  1825. INT 21H
  1826. MOV WORD PTR [REAL_INT_5+2],ES
  1827. MOV WORD PTR [REAL_INT_5],BX
  1828. MOV DX,OFFSET CodeR:INT_5
  1829. MOV AL,5H
  1830. MOV AH,SET_INTERRUPT_VECTOR
  1831. INT 21H ;Set print screen interrupt
  1832. ENDIF
  1833. IF HARDINT
  1834. MOV AH,GET_INDOS_FLAG
  1835. INT 21H
  1836. ASSUME ES:NOTHING
  1837. MOV WORD PTR [INDOS+2],ES ;Get indos flag location
  1838. MOV WORD PTR [INDOS],BX
  1839. MOV AL,INTLOC
  1840. MOV AH,GET_INTERRUPT_VECTOR
  1841. INT 21H
  1842. MOV WORD PTR [NEXTINT+2],ES
  1843. MOV WORD PTR [NEXTINT],BX
  1844. MOV AL,REBOOT ; We also need to chain
  1845. MOV AH,GET_INTERRUPT_VECTOR ; Into the INT 19 sequence
  1846. INT 21H ; To properly "unhook"
  1847. MOV WORD PTR [NEXT_REBOOT+2],ES ; ourselves from the TimerTick
  1848. MOV WORD PTR [NEXT_REBOOT],BX ; sequence
  1849. IF IBM
  1850. MOV AX,0B800H
  1851. INT 2FH
  1852. CMP AL,0
  1853. JE SET_HDSPINT ; No NETWORK, set hardware int
  1854. TEST BX,0000000011000100B
  1855. JNZ NO_HDSPINT ; DO NOT set HDSPINT if RCV|MSG|SRV
  1856. ENDIF
  1857. SET_HDSPINT:
  1858. MOV DX,OFFSET CodeR:HDSPINT
  1859. MOV AL,INTLOC
  1860. MOV AH,SET_INTERRUPT_VECTOR
  1861. INT 21H ;Set hardware interrupt
  1862. MOV DX,OFFSET CodeR:ReBtINT
  1863. MOV AL,REBOOT
  1864. MOV AH,SET_INTERRUPT_VECTOR
  1865. INT 21H ;Set bootstrap interrupt
  1866. NO_HDSPINT:
  1867. ENDIF
  1868. MOV DX,OFFSET CODER:GOODMES
  1869. mov cx,goodmeslen
  1870. mov bx,stdout
  1871. mov ah,write
  1872. int 21h
  1873. ;--- Move transient
  1874. ; Note: do not use stack, it may get trashed in move!
  1875. public RealMove
  1876. RealMove:
  1877. mov ax,offset dg:TransRet
  1878. mov word ptr [ContTrans],ax ; store return offset
  1879. mov ax,CodeR
  1880. add ax,[endres] ; get start of moved transient, actually
  1881. ; this is 100 bytes more than need be
  1882. ; because of lack of pdb, but who cares?
  1883. mov word ptr [ContTrans+2],ax ; return segment
  1884. mov es,ax ; new location for dg group
  1885. assume es:nothing
  1886. mov ax,dg
  1887. mov ds,ax
  1888. assume ds:nothing
  1889. mov cx,offset dg:TransSize
  1890. mov si,cx ; start from the bottom and move up
  1891. mov di,cx
  1892. std
  1893. rep movsb ; move all code, data and stack
  1894. cld ; restore to expected setting...
  1895. ;--- normalize transient segment regs
  1896. mov ax,es
  1897. mov ds,ax
  1898. sub ax,dg ; displacement
  1899. mov dx,ss
  1900. add dx,ax ; displace stack segemnt
  1901. mov ss,dx
  1902. assume ds:nothing,es:nothing,ss:nothing
  1903. jmp ContTrans ; back to the transient...
  1904. PRNR009E:
  1905. CodeR EndS
  1906. End