mirror of https://github.com/AR1972/DOS3.3
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.
2189 lines
40 KiB
2189 lines
40 KiB
; SCCSID = @(#)print_r.asm 4.7 85/09/13
|
|
INCLUDE pridefs.inc
|
|
|
|
|
|
BREAK <Resident Portion>
|
|
|
|
;
|
|
; MSDOS V3.00 PRINT
|
|
;
|
|
; Resident Portion
|
|
;
|
|
|
|
Code Segment public para
|
|
extrn TransRet:WORD,TransSize:WORD
|
|
Code EndS
|
|
|
|
|
|
|
|
BREAK <Resident Data>
|
|
|
|
CodeR Segment public para
|
|
|
|
extrn ERRMES:BYTE, ERRMEST:BYTE, BELMES:BYTE, ErrMesT2:BYTE
|
|
extrn CanMes:BYTE, CanFilNAm:BYTE, AllCan:BYTE, ERR0:BYTE
|
|
extrn ERR1:BYTE, ERR2:BYTE, ERR3:BYTE, ERR4:BYTE, ERR5:BYTE
|
|
extrn ERR6:BYTE, ERR7:BYTE, ERR8:BYTE, ERR9:BYTE, ERR10:BYTE
|
|
extrn ERR11:BYTE, ERR12:BYTE, FATMES:BYTE, BADDRVM:BYTE,
|
|
extrn BADMES:BYTE, badmeslen:WORD, GOODMES:BYTE, goodmeslen:WORD
|
|
|
|
if hardint
|
|
public SliceCnt, BusyTick, MaxTick, TimeSlice
|
|
endif
|
|
|
|
public EndRes, BlkSiz, QueueLen, PChar
|
|
public ListName, FileQueue, EndQueue, Buffer
|
|
public EndPtr, NxtChr, MoveTrans
|
|
|
|
assume CS:CodeR
|
|
|
|
public PRNR001S,PRNR001E
|
|
PRNR001S:
|
|
db "*** Microsoft/V310 ***"
|
|
|
|
DB (362 - 80h) + 310 DUP (?) ; (362 - 80h) is IBM's New
|
|
; recommended Stack Size -
|
|
; Old recommended Stack Size
|
|
; == New stack growth
|
|
ISTACK LABEL WORD ;Stack starts here and grows down the
|
|
|
|
;Resident data
|
|
|
|
;
|
|
; Due to flagrant bogosity by file servers, BUSY is *ALWAYS* relevant.
|
|
;
|
|
BUSY DB 0 ;Internal ME flag
|
|
|
|
IF HARDINT
|
|
;
|
|
; WARNING!!! The *&^%(*&^ 286 chip hangs if you access a word that will wrap
|
|
; at the segment boundary. Make the initial INDOS point somewhere reasonable.
|
|
;
|
|
INDOS DD TimeSlice ;DOS buisy flag
|
|
NEXTINT DD ? ;Chain for int
|
|
NEXT_REBOOT DD ? ;Chain for ROM bootstrap
|
|
|
|
fFake db 0 ; TRUE => do not diddle I/O ports
|
|
SOFINT DB 0 ;Internal ME flag
|
|
TICKCNT DB 0 ;Tick counter
|
|
TICKSUB DB 0 ;Tick miss counter
|
|
SLICECNT DB 8 ;Time slice counter, init to same val
|
|
; as TIMESLICE
|
|
|
|
TIMESLICE DB 8 ;The PRINT scheduling time slice. PRINT
|
|
; lets this many "ticks" go by before
|
|
; using a time slice to pump out characters.
|
|
; Setting this to 3 for instance means PRINT
|
|
; Will skip 3 slices, then take the fourth.
|
|
; Thus using up 1/4 of the CPU. Setting it
|
|
; to one gives PRINT 1/2 of the CPU.
|
|
; The above examples assume MAXTICK is
|
|
; 1. The actual PRINT CPU percentage is
|
|
; (MAXTICK/(1+TIMESLICE))*100
|
|
|
|
MAXTICK DB 2 ;The PRINT in timeslice. PRINT will pump
|
|
; out characters for this many clock ticks
|
|
; and then exit. The selection of a value
|
|
; for this is dependent on the timer rate.
|
|
|
|
BUSYTICK DB 1 ;If PRINT sits in a wait loop waiting for
|
|
; output device to come ready for this
|
|
; many ticks, it gives up its time slice.
|
|
; Setting it greater than or equal to
|
|
; MAXTICK causes it to be ignored.
|
|
|
|
;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK
|
|
; ticks go by without getting a character out.
|
|
ENDIF
|
|
|
|
QueueLen db DefQueueLen ; Actual length of print queue
|
|
even
|
|
EndQueue dw ? ; pointer to end of print queue
|
|
QueueTail dw offset CodeR:FileQueue ; pointer to next free entry
|
|
; in the print queue
|
|
buffer dw ? ; pointer to data buffer
|
|
|
|
I24_ERR DW ? ;Save location for INT 24H error code
|
|
Ctrlc DB ? ; saved ^C trapping state
|
|
SPNEXT DD ? ;Chain location for INT 28
|
|
COMNEXT DD ? ;Chain location for INT 2F
|
|
SSsave DW ? ;Stack save area for INT 24
|
|
SPsave DW ?
|
|
HERRINT DD ? ;Place to save Hard error interrupt
|
|
LISTDEV DD ? ;Pointer to Device
|
|
COLPOS DB 0 ;Column position for TAB processing
|
|
CURRFIL DB 0
|
|
NXTCHR DW ?
|
|
CURRHAND DW -1
|
|
PrinterNum DW -1 ; index for printer
|
|
QueueLock db 0 ; queue lock, 0=unlocked
|
|
|
|
|
|
PChar db ? ; path character
|
|
AmbCan db ? ; = 1 ambigous cancel
|
|
CanFlg db ? ; = 1 Current was already canceled
|
|
ACanOcrd db ? ; = 1 a file was found during an
|
|
; ambigous cancel
|
|
|
|
;--- Warnning: this is a FCB!!
|
|
ACBuf db ?
|
|
ACName db 8 dup(?)
|
|
ACExt db 3 dup(?)
|
|
db 4 dup(?) ; how big is an unopened fcb???
|
|
|
|
|
|
CONTXTFLAG DB 0 ;0 means his context, NZ means me
|
|
HISPDB DW ?
|
|
PABORT DB 0 ;Abort flag
|
|
BLKSIZ DW 512 ;Size of the PRINT I/O block in bytes
|
|
ENDPTR DW ?
|
|
|
|
COMDISP LABEL WORD ; Communications dispatch table
|
|
DW OFFSET CodeR:INST_REQ
|
|
DW OFFSET CodeR:ADDFIL
|
|
DW OFFSET CodeR:CANFIL
|
|
DW offset CodeR:CanAll
|
|
DW OFFSET CodeR:QSTAT
|
|
DW offset CodeR:EndStat
|
|
DW offset CodeR:QSTATDEV
|
|
|
|
;Resident messages
|
|
|
|
MESBAS DW OFFSET CodeR:ERR0
|
|
DW OFFSET CodeR:ERR1
|
|
DW OFFSET CodeR:ERR2
|
|
DW OFFSET CodeR:ERR3
|
|
DW OFFSET CodeR:ERR4
|
|
DW OFFSET CodeR:ERR5
|
|
DW OFFSET CodeR:ERR6
|
|
DW OFFSET CodeR:ERR7
|
|
DW OFFSET CodeR:ERR8
|
|
DW OFFSET CodeR:ERR9
|
|
DW OFFSET CodeR:ERR10
|
|
DW OFFSET CodeR:ERR11
|
|
DW OFFSET CodeR:ERR12
|
|
ENDRES DW ? ; filled in at initialization time
|
|
PRNR001E:
|
|
|
|
CodeR EndS
|
|
|
|
|
|
|
|
BREAK <Resident Code>
|
|
|
|
CodeR Segment public para
|
|
|
|
Break <Server critical section routines>
|
|
|
|
TestSetServer:
|
|
IF IBM
|
|
CLC
|
|
PUSH AX
|
|
MOV AX,8700h ; Can I run?
|
|
INT 2Ah
|
|
POP AX
|
|
ENDIF
|
|
ret
|
|
|
|
LeaveServer:
|
|
IF IBM
|
|
PUSH AX
|
|
MOV AX,8701h
|
|
INT 2Ah
|
|
POP AX
|
|
ENDIF
|
|
ret
|
|
|
|
;Interrupt routines
|
|
ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
;
|
|
; PRINT is stimulated by a hardware interrupt.
|
|
;
|
|
;
|
|
; The Server may also stimulate us during timer ticks (if we handled the
|
|
; ticks ourselves, it would be disasterous. Therefore, we have a substitute
|
|
; entry here that simulates the timer stuff but does NOT muck with the ports.
|
|
;
|
|
IF HARDINT
|
|
FakeINT1C:
|
|
MOV fFake,-1
|
|
JMP SHORT InnerHardInt
|
|
|
|
HDSPINT: ;Hardware interrupt entry point
|
|
mov fFake,0
|
|
InnerHardInt:
|
|
CALL TestSetServer
|
|
JNC TickTime
|
|
jmp ChainInt
|
|
TickTime:
|
|
INC [TICKCNT] ;Tick
|
|
INC [TICKSUB] ;Tick
|
|
CMP [SLICECNT],0
|
|
JZ TIMENOW
|
|
DEC [SLICECNT] ;Count down
|
|
JMP SHORT HardIntDone ;Not time yet
|
|
TIMENOW:
|
|
CMP BUSY,0 ;See if interrupting ourself
|
|
JNZ HardIntDone
|
|
|
|
IF IBM
|
|
push ax ; check for nested interrupts
|
|
mov al,00001011b ; select ISR in 8259
|
|
out 20H,al
|
|
JMP x
|
|
x:
|
|
in al,20H ; get ISR register
|
|
and al,0FEH ; mask timer int
|
|
pop ax
|
|
jnz HardIntDone ; there was another int in service...
|
|
ENDIF
|
|
|
|
PUSH DS
|
|
PUSH SI
|
|
LDS SI,[INDOS] ;Check for making DOS calls
|
|
;
|
|
; WARNING!!! Due to INT 24 clearing the INDOS flag, we must test both INDOS
|
|
; and ERRORMODE at once! These must be contiguous in MSDATA.
|
|
;
|
|
CMP WORD PTR [SI-1],0
|
|
POP SI
|
|
POP DS
|
|
JNZ HardIntDone ;DOS is Busy
|
|
INC [BUSY] ;Exclude furthur interrupts
|
|
MOV [TICKCNT],0 ;Reset tick counter
|
|
MOV [TICKSUB],0 ;Reset tick counter
|
|
STI ;Keep things rolling
|
|
|
|
IF AINT
|
|
TEST fFake,-1
|
|
JNZ NoAck
|
|
PUSH AX
|
|
MOV AL,EOI ;Acknowledge interrupt
|
|
OUT AKPORT,AL
|
|
POP AX
|
|
NoAck:
|
|
ENDIF
|
|
|
|
CALL DOINT
|
|
CLI
|
|
PUSH AX
|
|
MOV AL,[TIMESLICE]
|
|
MOV [SLICECNT],AL ;Either soft or hard int resets time slice
|
|
POP AX
|
|
DEC Busy ;Done, let others in
|
|
HardIntDone:
|
|
Call LeaveServer
|
|
CHAININT:
|
|
TEST fFake,-1
|
|
JNZ DoIRET
|
|
JMP [NEXTINT] ;Chain to next clock routine
|
|
DoIRET:
|
|
IRET
|
|
ENDIF
|
|
|
|
|
|
;
|
|
; PRINT is stimulated by a spooler idle interrupt
|
|
;
|
|
SPINT: ;INT 28H entry point
|
|
CALL TestSetServer
|
|
JC NxtSp
|
|
|
|
IF HARDINT
|
|
CMP [BUSY],0
|
|
JNZ SpIntDone
|
|
INC [BUSY] ;Exclude hardware interrupt
|
|
INC [SOFINT] ;Indicate a software int in progress
|
|
ENDIF
|
|
|
|
STI ;Hardware interrupts ok on INT 28H entry
|
|
CALL DOINT
|
|
|
|
IF HARDINT
|
|
CLI
|
|
MOV [SOFINT],0 ;Indicate INT done
|
|
PUSH AX
|
|
MOV AL,[TIMESLICE]
|
|
MOV [SLICECNT],AL ;Either soft or hard int resets time slice
|
|
POP AX
|
|
DEC Busy
|
|
ENDIF
|
|
SpIntDone:
|
|
call LeaveServer
|
|
|
|
NXTSP: JMP [SPNEXT] ;Chain to next INT 28
|
|
|
|
;
|
|
; Since we may be entering at arbitrary times, we need to get/set the extended
|
|
; error as we may end up blowing it away. We do not do this on spooler ints.
|
|
;
|
|
|
|
public PRNR002S, PRNR002E
|
|
PRNR002S:
|
|
|
|
SaveState DPL <> ; empty DPL
|
|
|
|
PRNR002E:
|
|
|
|
public enterprint
|
|
EnterPRINT:
|
|
IF HardInt
|
|
TEST SofInt,-1
|
|
JNZ EnterDone
|
|
ENDIF
|
|
MOV AH,GetExtendedError
|
|
CALL DO_21
|
|
MOV SaveState.DPL_AX,AX
|
|
MOV SaveState.DPL_BX,BX
|
|
MOV SaveState.DPL_CX,CX
|
|
MOV SaveState.DPL_DX,DX
|
|
MOV SaveState.DPL_SI,SI
|
|
MOV SaveState.DPL_DI,DI
|
|
MOV SaveState.DPL_DS,DS
|
|
MOV SaveState.DPL_ES,ES
|
|
EnterDone:
|
|
RET
|
|
|
|
public leaveprint
|
|
LeavePRINT:
|
|
IF HardInt
|
|
TEST SofInt,-1
|
|
JNZ LeaveDone
|
|
ENDIF
|
|
MOV AX,(ServerCall SHL 8) + 10
|
|
PUSH CS
|
|
POP DS
|
|
MOV DX,OFFSET CodeR:SaveState
|
|
CALL Do_21
|
|
LeaveDone:
|
|
RET
|
|
|
|
public doint
|
|
DOINT:
|
|
ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [CURRFIL],0
|
|
JNZ GOAHEAD
|
|
SPRET:
|
|
ret ;Nothing to do
|
|
|
|
GOAHEAD:
|
|
cmp [QueueLock],1
|
|
je spret ; queue locked, do nothing...
|
|
PUSH AX ;Need a working register
|
|
MOV [SSsave],SS
|
|
MOV [SPsave],SP
|
|
MOV AX,CS
|
|
CLI
|
|
;Go to internal stack to prevent INT 24 overflowing system stack
|
|
MOV SS,AX
|
|
MOV SP,OFFSET CodeR:ISTACK
|
|
STI
|
|
PUSH ES
|
|
PUSH DS
|
|
PUSH BP
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH SI
|
|
PUSH DI
|
|
PUSH CS
|
|
POP DS
|
|
ASSUME DS:CodeR
|
|
|
|
Call EnterPRINT
|
|
|
|
MOV BX,[NXTCHR]
|
|
CMP BX,[ENDPTR]
|
|
JB PLOOP
|
|
JMP READBUFF ;Buffer empty
|
|
|
|
DONEJMPJP:
|
|
POPF
|
|
DONEJMPJ:
|
|
JMP DONEJMP
|
|
|
|
FILEOFJ:
|
|
ASSUME DS:CodeR
|
|
JMP FILEOF
|
|
|
|
PLOOP:
|
|
IF HARDINT
|
|
MOV BX,[NXTCHR]
|
|
CMP BX,[ENDPTR]
|
|
JAE DONEJMPJ ;Buffer has become empty
|
|
CMP [SOFINT],0
|
|
JNZ STATCHK
|
|
PUSH AX
|
|
MOV AL,[MAXTICK]
|
|
CMP [TICKCNT],AL ;Check our time slice
|
|
POP AX
|
|
JAE DONEJMPJ
|
|
STATCHK:
|
|
ENDIF
|
|
|
|
CALL PSTAT
|
|
PUSHF
|
|
CMP [CURRFIL],0
|
|
JZ DONEJMPJP ;File got cancelled by error
|
|
POPF
|
|
|
|
IF HARDINT
|
|
JZ DOCHAR ;Printer ready
|
|
CMP [SOFINT],0
|
|
ENDIF
|
|
|
|
JNZ DONEJMP ;If soft int give up
|
|
|
|
IF HARDINT
|
|
PUSH AX
|
|
MOV AL,[BUSYTICK]
|
|
CMP [TICKSUB],AL ;Check our busy timeout
|
|
POP AX
|
|
JAE DONEJMP
|
|
JMP PLOOP
|
|
ENDIF
|
|
|
|
DOCHAR:
|
|
MOV AL,BYTE PTR [BX]
|
|
CMP AL,1AH ;^Z?
|
|
JZ FILEOFJ ;CPM EOF
|
|
CMP AL,0DH ;CR?
|
|
JNZ NOTCR
|
|
MOV [COLPOS],0
|
|
NOTCR:
|
|
CMP AL,9 ;TAB?
|
|
JNZ NOTABDO
|
|
MOV CL,[COLPOS] ;expand tab to # spaces
|
|
OR CL,0F8H
|
|
NEG CL
|
|
XOR CH,CH
|
|
JCXZ TABDONE ;CX contains # spaces to print
|
|
TABLP:
|
|
MOV AL," "
|
|
INC [COLPOS]
|
|
PUSH CX
|
|
CALL POUT
|
|
POP CX
|
|
DEC CX ;G
|
|
JZ TABDONE ;G We're done - get next char
|
|
JMP PLOOP ;G Keep processing tab
|
|
|
|
;G LOOP TABLP
|
|
;G JMP TABDONE
|
|
|
|
NOTABDO:
|
|
CMP AL,8 ;Back space?
|
|
JNZ NOTBACK
|
|
DEC [COLPOS]
|
|
NOTBACK:
|
|
CMP AL,20H ;Non Printing char?
|
|
JB NOCHAR
|
|
INC [COLPOS] ;Printing char
|
|
NOCHAR:
|
|
CALL POUT ;Print it
|
|
TABDONE:
|
|
INC [NXTCHR] ;Next char
|
|
|
|
IF HARDINT
|
|
MOV [TICKSUB],0 ;Got a character out, Reset counter
|
|
CMP [SOFINT],0 ;Soft int does one char at a time
|
|
JNZ DONEJMP
|
|
JMP PLOOP
|
|
ENDIF
|
|
|
|
DONEJMP:
|
|
CALL CONTEXT_BACK
|
|
Call LeavePRINT
|
|
|
|
POP DI
|
|
POP SI
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP BP
|
|
POP DS
|
|
POP ES
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
CLI
|
|
MOV SS,[SSsave] ;Restore Entry Stack
|
|
MOV SP,[SPsave]
|
|
STI
|
|
POP AX
|
|
RET
|
|
|
|
CONTEXT_BACK:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [CONTXTFLAG],0
|
|
JZ CONTOK
|
|
SaveReg <AX,BX>
|
|
MOV BX,[HISPDB]
|
|
MOV AH,SET_CURRENT_PDB
|
|
call do_21
|
|
RestoreReg <BX,AX>
|
|
MOV [CONTXTFLAG],0
|
|
CONTOK:
|
|
RET
|
|
|
|
CONTEXT_SWITCH:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [CONTXTFLAG],0
|
|
JNZ RET45
|
|
SaveReg <BX,AX>
|
|
MOV AH,GET_CURRENT_PDB
|
|
call do_21
|
|
MOV [HISPDB],BX
|
|
MOV BX,CS
|
|
sub bx,10h ; The 2.5 print is an exe program
|
|
MOV AH,SET_CURRENT_PDB
|
|
call do_21
|
|
RestoreReg <AX,BX>
|
|
MOV [CONTXTFLAG],1
|
|
RET45: RET
|
|
|
|
|
|
;--- Refill the print buffer ---
|
|
READBUFF:
|
|
ASSUME DS:CodeR,ES:NOTHING,SS:NOTHING
|
|
|
|
call Set24 ; switch Int24 vector
|
|
MOV [PABORT],0 ;No abort
|
|
MOV BX,[CURRHAND]
|
|
MOV CX,[BLKSIZ]
|
|
MOV DX,[BUFFER]
|
|
MOV AH,READ
|
|
call My21
|
|
PUSHF
|
|
call Res24 ; reset Int 24 vector
|
|
CMP [PABORT],0
|
|
JZ NOHERR
|
|
POP AX ;Flags from read
|
|
jmp FilClose ;Barf on this file, got INT 24
|
|
|
|
|
|
NOHERR:
|
|
POPF
|
|
JC FILEOF
|
|
CMP AX,0
|
|
JZ FILEOF ;Read EOF?
|
|
MOV BX,[BUFFER] ;Buffer full
|
|
MOV DI,BX
|
|
ADD DI,AX
|
|
MOV [NXTCHR],BX
|
|
MOV CX,[BLKSIZ]
|
|
SUB CX,AX
|
|
JCXZ DONEJ ; Buffer is completely full
|
|
PUSH CS
|
|
POP ES
|
|
MOV AL,1AH
|
|
cld
|
|
REP STOSB ; ^Z pad the buffer
|
|
DONEJ:
|
|
JMP DONEJMP
|
|
|
|
FILEOF:
|
|
MOV AL,0CH ;Form feed
|
|
CALL POUT
|
|
|
|
;--- Close file
|
|
; note: we came here from an i24 then PAbort is already = 1
|
|
FilClose:
|
|
call Set24
|
|
mov pAbort,-1
|
|
MOV BX,[CURRHAND]
|
|
MOV AH,CLOSE
|
|
call My21
|
|
call Res24
|
|
MOV [CURRFIL],0 ; No file
|
|
MOV [CURRHAND],-1 ; Invalid handle
|
|
MOV AX,[ENDPTR]
|
|
MOV [NXTCHR],AX ; Buffer empty
|
|
|
|
;--- Send close on output device
|
|
call Close_Dev
|
|
|
|
;--- compact the print queue
|
|
CompQAgn:
|
|
call CompQ
|
|
|
|
;--- Check if there are any more files to print
|
|
mov si,offset CodeR:FileQueue
|
|
cmp byte ptr [si],0 ; no more left if name starts with nul
|
|
je NoFilesLeft
|
|
call Set24
|
|
MOV [PABORT],0 ;No abort
|
|
mov dx,si ; DS:DX points to file name
|
|
mov ax,(open shl 8)
|
|
call My21 ; try opening new file
|
|
pushf
|
|
call Res24
|
|
cmp [PAbort],0
|
|
je NoI24a
|
|
popf
|
|
jmp short CompQAgn ; try next file
|
|
|
|
NoI24a:
|
|
popf
|
|
jnc GotNewFile
|
|
call PrtOpErr
|
|
jmp short CompQAgn
|
|
|
|
GotNewFile: ; buffer was already marked as empty
|
|
mov [CurrHand],ax
|
|
mov [CurrFil],1
|
|
|
|
;--- Send Open on output device
|
|
call Open_Dev
|
|
|
|
NoFilesLeft:
|
|
JMP DONEJMP
|
|
|
|
|
|
;--- Print open error ---
|
|
; preserves DS
|
|
|
|
PrtOpErr:
|
|
assume ds:CodeR,es:Nothing
|
|
|
|
; This stuff constitutes a "file" so it is bracketed by an open/close
|
|
; on the output device.
|
|
|
|
;--- Send Open on output device
|
|
call Open_Dev
|
|
|
|
push cs
|
|
pop es
|
|
assume es:CodeR
|
|
mov si,offset CodeR:ErrMes
|
|
call ListMes
|
|
mov si,offset CodeR:ErrMesT2
|
|
call ListMes
|
|
mov si,offset CodeR:FileQueue
|
|
call ListMes2
|
|
mov si,offset CodeR:BelMes
|
|
call ListMes
|
|
|
|
;--- Send close on output device
|
|
call Close_Dev
|
|
|
|
ret
|
|
|
|
|
|
;--- Compact File Queue ---
|
|
; modifies: AX,CX,SI,DI,ES
|
|
|
|
CompQ:
|
|
assume ds:CodeR,es:nothing,ss:nothing
|
|
push cs
|
|
pop es
|
|
assume es:CodeR
|
|
mov di,offset CodeR:FileQueue ; ES:DI points to top of queue
|
|
mov si,(offset CodeR:FileQueue + MaxFileLen) ; DS:SI points to next entry
|
|
mov cx,[EndQueue]
|
|
sub cx,si ; length in bytes of the queue
|
|
cld
|
|
rep movsb ; compact the queue
|
|
mov ax,[QueueTail] ; normalize tail pointer as we
|
|
sub ax,MaxFileLen ; know have a new "next empty slot"
|
|
mov [QueueTail],ax
|
|
mov si,ax
|
|
mov byte ptr [si],0 ; nul first byte of last entry
|
|
ret
|
|
|
|
|
|
BREAK <Resident Code: DSKERR>
|
|
|
|
;--- Set Local Int 24 vector ---
|
|
; modifies: AX,DX
|
|
|
|
Set24:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
push es
|
|
push bx
|
|
push dx
|
|
MOV AL,24H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
call do_21
|
|
MOV WORD PTR [HERRINT+2],ES ; Save current vector
|
|
MOV WORD PTR [HERRINT],BX
|
|
MOV DX,OFFSET CodeR:DSKERR
|
|
MOV AL,24H
|
|
MOV AH,SET_INTERRUPT_VECTOR ; Install our own
|
|
call do_21 ; Spooler must catch its errors
|
|
pop dx
|
|
pop bx
|
|
pop es
|
|
ret
|
|
|
|
|
|
;--- Reset Old Int 24 vector ---
|
|
; modifies: none
|
|
|
|
Res24:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
push ds
|
|
PUSH AX
|
|
push dx
|
|
LDS DX,[HERRINT]
|
|
ASSUME DS:NOTHING
|
|
MOV AL,24H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
call do_21 ;Restore Error INT
|
|
pop dx
|
|
POP AX
|
|
pop ds
|
|
ret
|
|
|
|
|
|
;--- INT 24 handler ---
|
|
DSKERR:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [PABORT],0
|
|
JNZ IGNRET
|
|
STI
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH DI
|
|
PUSH SI
|
|
PUSH BP
|
|
PUSH ES
|
|
PUSH DS
|
|
PUSH CS
|
|
POP DS
|
|
PUSH CS
|
|
POP ES
|
|
ASSUME DS:CodeR,ES:CodeR
|
|
ADD [BADDRVM],AL ;Set correct drive letter
|
|
MOV SI,OFFSET CodeR:ERRMES
|
|
CALL LISTMES
|
|
TEST AH,080H
|
|
JNZ FATERR
|
|
AND DI,0FFH
|
|
CMP DI,12
|
|
JBE HAVCOD
|
|
MOV DI,12
|
|
HAVCOD:
|
|
MOV [I24_ERR],DI
|
|
SHL DI,1
|
|
MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message
|
|
MOV SI,DI
|
|
CALL LISTMES ; Print error type
|
|
MOV SI,OFFSET CodeR:ERRMEST
|
|
CALL LISTMES
|
|
mov si,offset CodeR:FileQueue ; print filename
|
|
call ListMes2 ; print name
|
|
mov si,offset CodeR:BelMes
|
|
call ListMes
|
|
SETABORT:
|
|
INC [PABORT] ;Indicate abort
|
|
POP DS
|
|
POP ES
|
|
POP BP
|
|
POP SI
|
|
POP DI
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
IGNRET:
|
|
XOR AL,AL ;Ignore
|
|
IRET
|
|
|
|
FATERR:
|
|
MOV [I24_ERR],0FFH
|
|
MOV SI,OFFSET CodeR:FATMES
|
|
CALL LISTMES
|
|
JMP SHORT SETABORT
|
|
|
|
|
|
BREAK <Resident Code: SPCOMINT>
|
|
|
|
;--- Communications interrupt ---
|
|
SPCOMINT proc far
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP AH,1
|
|
JBE MINE
|
|
JMP [COMNEXT]
|
|
|
|
MINE:
|
|
CMP AL,0F8H
|
|
JAE RESERVED_RET
|
|
IF HardInt
|
|
CMP AX,0080h
|
|
JNZ CheckPSP
|
|
JMP FakeINT1C
|
|
ENDIF
|
|
CheckPSP:
|
|
OR AH,AH
|
|
JNE PSPDO
|
|
MOV AL,1 ; Tell PSPRINT to go away (AH = 1)
|
|
RESERVED_RET:
|
|
IRET
|
|
|
|
PSPDO:
|
|
OR AL,AL
|
|
JNE PSPDISP
|
|
INST_REQ:
|
|
MOV AL,0FFH
|
|
IRET
|
|
|
|
PSPDISP:
|
|
CMP [BUSY],0
|
|
JZ SETCBUSY
|
|
ErrBusy:
|
|
MOV AX,error_busy
|
|
setcret:
|
|
push bp
|
|
mov bp,sp
|
|
or word ptr [bp+6],f_Carry
|
|
pop bp
|
|
iret
|
|
|
|
SETCBUSY:
|
|
XOR AH,AH
|
|
CMP AX,6 ; check function within valid range
|
|
Jbe GoForIt
|
|
mov ax,error_invalid_function
|
|
jmp setcret
|
|
GoForIt:
|
|
INC [BUSY] ;Exclude
|
|
STI ;Turn ints back on
|
|
PUSH DI ;G
|
|
PUSH ES
|
|
PUSH DS
|
|
PUSH CS
|
|
POP DS
|
|
ASSUME DS:CodeR
|
|
mov [QueueLock],0 ; unlock the print queue
|
|
SHL AX,1 ;Turn into word index
|
|
mov di,ax
|
|
call ComDisp[DI]
|
|
assume ds:nothing
|
|
jc ErrRet
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
CALL PSTAT ; Tweek error counter
|
|
pop ds
|
|
assume ds:nothing
|
|
ErrRet:
|
|
pushf
|
|
call Context_Back
|
|
popf
|
|
CLI
|
|
DEC BUSY ; leaves carry alone!
|
|
POP DS
|
|
ASSUME DS:NOTHING
|
|
POP ES
|
|
POP DI ;G
|
|
jc setcret
|
|
push bp
|
|
mov bp,sp
|
|
and word ptr [bp+6],NOT f_Carry
|
|
pop bp
|
|
iret
|
|
SpComInt Endp
|
|
|
|
BREAK <Get queue status>
|
|
|
|
;--- Return pointer to file queue ---
|
|
QSTAT:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
|
|
mov [QueueLock],1 ; lock the print queue
|
|
CALL PSTAT ; Tweek error counter
|
|
push bp
|
|
mov bp,sp ; 0 2 4
|
|
MOV [bp+ 2 + 2],cs ; <BP> <RET> <DS>
|
|
POP BP
|
|
mov si,offset CodeR:FileQueue
|
|
mov dx,[ErrCnt] ; return error count
|
|
clc
|
|
ret
|
|
|
|
;--- Return pointer to device driver if active ---
|
|
QSTATDEV:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
|
|
xor ax,ax ;g assume not busy
|
|
mov [QueueLock],1 ;g lock the print queue
|
|
CALL PSTAT ;g Tweek error counter
|
|
cmp byte ptr FileQueue,0 ;g is there anything in the queue?
|
|
clc ;g
|
|
jz qstatdev_end ;g no - just exit
|
|
mov ax,error_queue_full ;g yes - set error queue full
|
|
mov si,word ptr [listdev+2] ;g get segment of list device
|
|
push bp ;g
|
|
mov bp,sp ;g 0 2 4
|
|
MOV [bp+2+2],si ;g <BP><RET><DS> seg of device to DS
|
|
pop bp ;g
|
|
mov si,word ptr [listdev] ;g offset of device to SI
|
|
stc ;g
|
|
|
|
qstatdev_end: ;g
|
|
mov [QueueLock],0 ;g unlock the print queue
|
|
ret ;g
|
|
|
|
BREAK <Resident Code: EndStat>
|
|
|
|
;--- Unlock the print queue ---
|
|
EndStat:
|
|
assume ds:CodeR,es:nothing
|
|
mov [QueueLock],0
|
|
clc
|
|
ret
|
|
|
|
BREAK <Cancel all available files in the queue>
|
|
|
|
;
|
|
; Note that we need to spin until the background is free
|
|
;
|
|
CanAll:
|
|
assume ds:CodeR,es:nothing
|
|
|
|
cmp [CurrFil],0 ; are we currently printing?
|
|
jnz DoCanAll ; yes, go and cancel
|
|
ret ; carry is clear
|
|
|
|
DoCanAll:
|
|
|
|
;--- Cancel active file
|
|
mov bx,[CurrHand] ; close the current file
|
|
call Set24
|
|
mov [PAbort],1 ; no Int24's
|
|
mov ah,Close
|
|
call My21
|
|
call Res24
|
|
mov [CurrFil],0 ; no files to print
|
|
mov [CurrHand],-1 ; invalidate handle
|
|
mov ax,[EndPtr] ; buffer empty
|
|
mov [NxtChr],ax
|
|
|
|
;--- Cancel rest of files
|
|
mov si,offset CodeR:FileQueue
|
|
mov [QueueTail],si ; next free entry is the first
|
|
mov byte ptr [si],0 ; nul first byte of firts entry
|
|
mov si,offset CodeR:AllCan
|
|
call ListMes ; print cancelation message
|
|
mov si,offset CodeR:BelMes
|
|
call ListMes ; ring!!
|
|
|
|
;--- Send close on output device
|
|
call Close_Dev
|
|
clc
|
|
ret
|
|
|
|
BREAK <Cancel a file in progress>
|
|
|
|
CANFIL:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
|
|
CMP [CURRFIL],0
|
|
JNZ DOCAN
|
|
ret ; carry is clear
|
|
|
|
DOCAN:
|
|
|
|
;--- find which file to cancel
|
|
push bp
|
|
mov bp,sp ; 0 2 4
|
|
MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
|
|
POP BP
|
|
|
|
assume ds:nothing
|
|
push cs
|
|
pop es
|
|
assume es:CodeR
|
|
mov CS:[CanFlg],0 ; reset message flag
|
|
mov CS:[ACanOcrd],0 ; no cancelation has ocured yet
|
|
mov bx,offset CodeR:FileQueue ; ES:BX points to 1st entry in queue
|
|
call AmbChk
|
|
|
|
AnotherTry:
|
|
mov di,bx ; ES:DI points to 1st entry in queue
|
|
mov si,dx ; DS:SI points to filename to cancel
|
|
MatchLoop:
|
|
lodsb
|
|
cmp al,byte ptr es:[di] ; names in queue are all in upper case
|
|
je CharMatch
|
|
call UpConv ; did not match, try upper case
|
|
cmp al,byte ptr es:[di]
|
|
jne AnotherName ; a mismatch, try another name
|
|
CharMatch:
|
|
cmp es:byte ptr es:[di],0 ; was this the terminating nul?
|
|
je NameFound ; yes we got our file...
|
|
inc di
|
|
jmp MatchLoop
|
|
|
|
AnotherName:
|
|
cmp CS:[AmbCan],1 ; ambigous file name specified?
|
|
jne AnName ; if not then no more work to do
|
|
cmp al,"?"
|
|
jne AnName
|
|
cmp byte ptr es:[di],"."
|
|
je FindPeriod
|
|
cmp byte ptr es:[di],0 ; if nul then file names match
|
|
jne CharMatch ; only if only ?'s are left...
|
|
FindNul:
|
|
lodsb
|
|
cmp al,"?"
|
|
je FindNul
|
|
cmp al,"."
|
|
je FindNul
|
|
or al,al
|
|
jne AnName ; found something else, no match
|
|
jmp short NameFound
|
|
|
|
FindPeriod: ; ambigous files always have 8 chars
|
|
lodsb ; in name so we can not look for the
|
|
or al,al ; period twice (smart uh?)
|
|
je AnName ; no period found, files do not match
|
|
cmp al,"."
|
|
jne FindPeriod
|
|
jmp short CharMatch
|
|
|
|
AnName:
|
|
add bx,MaxFileLen
|
|
cmp byte ptr es:[bx],0 ; end of queue?
|
|
jne AnotherTry ; no, continue...
|
|
cmp CS:[ACanOcrd],1 ; yes, was there a file found?
|
|
jne sk2
|
|
push cs
|
|
pop ds
|
|
assume ds:CodeR ; StartAnFil likes it this way...
|
|
jmp StartAnFil ; restart printing
|
|
|
|
sk2:
|
|
assume ds:nothing
|
|
|
|
mov ax,error_file_not_found
|
|
stc
|
|
ret
|
|
|
|
|
|
;--- Name found, check if current file
|
|
NameFound:
|
|
push cs
|
|
pop ds
|
|
assume ds:CodeR
|
|
mov [ACanOcrd],1 ; remember we found a file
|
|
cmp bx,offset CodeR:FileQueue ; is the file being printed?
|
|
jne NotCurrent ; no, just compact the queue
|
|
cmp [CanFlg],0
|
|
jne NotCurrent ; only cance current once
|
|
|
|
;--- Cancel current file
|
|
mov [CanFlg],1 ; remeber we already canceled current
|
|
push bx
|
|
mov bx,[CurrHand] ; close the current file
|
|
call Set24
|
|
mov [PAbort],1 ; no Int24's
|
|
mov ah,Close
|
|
call My21
|
|
call Res24
|
|
mov [CurrFil],0 ; no files to print
|
|
mov [CurrHand],-1 ; invalidate handle
|
|
mov ax,[EndPtr] ; buffer empty
|
|
mov [NxtChr],ax
|
|
pop bx
|
|
|
|
;--- print cancelation message
|
|
push bx
|
|
mov si,offset CodeR:CanMes
|
|
call ListMes ; print cancelation message
|
|
mov si,bx ; points to filename
|
|
call ListMes2 ; print filename
|
|
mov si,offset CodeR:CanFilNam
|
|
call ListMes
|
|
mov si,offset CodeR:BelMes
|
|
call ListMes ; ring!!
|
|
pop bx
|
|
|
|
;--- Send close on output device
|
|
call Close_Dev
|
|
|
|
NotCurrent:
|
|
mov di,bx ; DI points to entry to cancel
|
|
mov si,bx
|
|
add si,MaxFileLen ; SI points to next entry
|
|
cmp si,[QueueTail] ; is the entry being canceled the last?
|
|
jne DoCompact ; no, do compaction
|
|
mov byte ptr [di],0 ; yes, just nul the first byte
|
|
jmp short CompactDone
|
|
DoCompact:
|
|
mov cx,[EndQueue] ; CX points to the end of the queue
|
|
sub cx,si ; length of the remainning of the queue
|
|
cld
|
|
rep movsb ; compact the queue
|
|
CompactDone:
|
|
mov ax,[QueueTail] ; remember new end of queue
|
|
sub ax,MaxFileLen
|
|
mov [QueueTail],ax
|
|
mov si,ax
|
|
mov byte ptr [si],0 ; nul first byte of last entry
|
|
|
|
cmp byte ptr [bx],0 ; is there another file to consider?
|
|
je StartAnFil
|
|
push bp
|
|
mov bp,sp ; 0 2 4
|
|
MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
|
|
POP BP
|
|
assume ds:nothing
|
|
jmp AnotherTry ; yes do it again...
|
|
|
|
|
|
;--- Start new file...
|
|
StartAnFil:
|
|
assume ds:CodeR
|
|
cmp [CurrHand],-1 ; was the canceled name the current?
|
|
jne NoneLeft ; no, just quit
|
|
StartAnFil2:
|
|
mov si,offset CodeR:FileQueue ; points to new current file
|
|
cmp byte ptr[si],0 ; is there one there?
|
|
je NoneLeft ; no, we canceled current and are none left
|
|
call Set24
|
|
mov [PAbort],0
|
|
mov dx,si
|
|
mov ax,(open shl 8)
|
|
call My21
|
|
pushf
|
|
call Res24
|
|
cmp [PAbort],0
|
|
je NoI24b
|
|
popf
|
|
call CompQ ; compact file queue
|
|
jmp short StartAnFil2
|
|
|
|
NoI24b:
|
|
popf
|
|
jnc GoodNewCurr
|
|
call PrtOpErr ; print open error
|
|
call CompQ ; compact file queue
|
|
jmp short StartAnFil2
|
|
|
|
GoodNewCurr:
|
|
mov [CurrHand],ax ; save handle
|
|
mov [CurrFil],1 ; signal active (buffer is already empty)
|
|
|
|
;--- Send Open on output device
|
|
call Open_Dev
|
|
NoneLeft:
|
|
clc
|
|
ret
|
|
|
|
;--- Upper case conversion ---
|
|
UpConv:
|
|
CMP AL,'a'
|
|
JB NOCONV
|
|
CMP AL,'z'
|
|
JA NOCONV
|
|
SUB AL,20H
|
|
NOCONV:
|
|
RET
|
|
|
|
|
|
;--- Ambigous file name check ---
|
|
; entry: ds:dx points to filename
|
|
; preserves ds:dx and es
|
|
;
|
|
assume ds:nothing,es:CodeR
|
|
AmbChk:
|
|
mov CS:[AmbCan],0 ; assume not ambigous
|
|
mov si,dx
|
|
cld
|
|
AmbLoop:
|
|
lodsb
|
|
or al,al ; the nul?
|
|
jne AmbLoop
|
|
dec si ; points to nul
|
|
std ; scan backwards
|
|
ScanBack:
|
|
lodsb
|
|
cmp al,"*"
|
|
jne NotAStar
|
|
mov CS:[AmbCan],1
|
|
NotAStar:
|
|
cmp al,"?"
|
|
jne NotAQues
|
|
mov CS:[AmbCan],1
|
|
NotAQues:
|
|
cmp al,CS:[PChar]
|
|
jne ScanBack
|
|
cld ; be safe
|
|
cmp CS:[AmbCan],1 ; an ambigous cancel?
|
|
je AmbCanFnd ; no, just proceed
|
|
ret
|
|
|
|
;--- transform * to ?'s
|
|
AmbCanFnd:
|
|
inc si
|
|
inc si ; points to actual name (past path char)
|
|
mov di,offset CodeR:ACBuf
|
|
push di
|
|
mov cx,12
|
|
mov al,20h
|
|
cld
|
|
rep stosb ; fill fcb with blanks
|
|
pop di
|
|
push si
|
|
mov ax,(Parse_file_descriptor shl 8) and 0FF00h
|
|
call My21
|
|
pop si
|
|
|
|
;--- Copy name to expanded name
|
|
push ds
|
|
pop es
|
|
assume ds:nothing
|
|
push cs
|
|
pop ds
|
|
assume ds:CodeR
|
|
push es
|
|
mov di,si
|
|
mov si,offset CodeR:ACName
|
|
mov cx,8
|
|
ACMovNam:
|
|
lodsb ; move name
|
|
cmp al,20h
|
|
je ACMovDn1
|
|
stosb
|
|
loop ACMovNam
|
|
|
|
ACMovDn1:
|
|
mov si,offset CodeR:ACExt
|
|
cmp byte ptr [si],20h ; if extension starts with blank
|
|
je ACMovDn2 ; then do not put period
|
|
mov al,"."
|
|
stosb
|
|
mov cx,3
|
|
|
|
ACMovExt:
|
|
lodsb ; move name
|
|
cmp al,20h
|
|
je ACMovDn2
|
|
stosb
|
|
loop ACMovExt
|
|
|
|
ACMovDn2:
|
|
mov byte ptr es:[di],0 ; nul terminate
|
|
pop ds
|
|
assume ds:nothing
|
|
push cs
|
|
pop es
|
|
assume es:CodeR
|
|
ret
|
|
|
|
|
|
|
|
BREAK <Add a file to the queue>
|
|
|
|
ADDFIL:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
|
|
;--- Check that queue is not full
|
|
mov di,[QueueTail] ; load pointer to next empty entry
|
|
cmp di,[EndQueue] ; queue full?
|
|
jb OkToQueue ; no, place in queue...
|
|
mov ax,error_queue_full
|
|
stc
|
|
ret
|
|
|
|
;--- Copy name to empty slot in queue
|
|
OkToQueue:
|
|
;
|
|
; Retrieve old DS
|
|
;
|
|
push bp
|
|
mov bp,sp ; 0 2 4
|
|
MOV ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
|
|
POP BP
|
|
|
|
assume ds:nothing
|
|
push cs
|
|
pop es ; ES:DI points to empty slot
|
|
assume es:CodeR
|
|
mov si,dx ; DS:SI points to submit packet
|
|
cmp byte ptr ds:[si],0
|
|
jnz IncorrectLevel
|
|
lds si,dword ptr ds:[si+1] ; DS:SI points to filename
|
|
mov cx,MaxFileLen ; maximum length of file name
|
|
CopyLop:
|
|
lodsb
|
|
call UpConv ; convert to upper case
|
|
stosb
|
|
or al,al ; nul?
|
|
je CopyDone ; yes, done with move...
|
|
loop CopyLop
|
|
push cs
|
|
pop ds
|
|
assume ds:CodeR
|
|
mov ax,error_name_too_long ; if normal exit from the loop then
|
|
stc
|
|
ret
|
|
|
|
IncorrectLevel:
|
|
mov ax,error_invalid_function
|
|
stc
|
|
ret
|
|
|
|
assume ds:nothing,es:nothing ; es:nothing = not true but lets
|
|
CopyDone: ; avoid possible problems...
|
|
push cs
|
|
pop ds
|
|
assume ds:CodeR
|
|
|
|
;--- advance queue pointer
|
|
mov si,[QueueTail] ; pointer to slot just used
|
|
push si ; save for test open later
|
|
add si,MaxFileLen
|
|
mov [QueueTail],si ; store for next round
|
|
mov byte ptr [si],0 ; nul next entry (maybe the EndQueue)
|
|
|
|
;--- Check that file exists
|
|
call Set24
|
|
mov [PAbort],0
|
|
pop dx ; get pointer to filename
|
|
MOV AX,(OPEN SHL 8)
|
|
call My21
|
|
pushf
|
|
PUSH DX
|
|
call Res24
|
|
POP DX
|
|
popf
|
|
JNC GOTFIL
|
|
;
|
|
; See if brain damaged user entered an invalid drive
|
|
;
|
|
PUSH AX
|
|
MOV SI,DX
|
|
CMP BYTE PTR CS:[SI+1],':'
|
|
JZ GotDrive
|
|
POP AX
|
|
JMP SHORT i24bf
|
|
GotDrive:
|
|
MOV AH,Get_default_drive ; get current
|
|
CALL My21
|
|
PUSH AX
|
|
MOV DL,CS:[SI] ; get drive letter to test
|
|
OR DL,20h
|
|
SUB DL,'a'
|
|
MOV AH,Set_Default_Drive ; set it
|
|
CALL My21
|
|
MOV AH,Get_default_drive ; get it back
|
|
CALL My21
|
|
CMP AL,DL ; same?
|
|
JNZ BadDrive ; no, bad drive
|
|
POP DX ; get original back
|
|
MOV AH,Set_Default_Drive ; set original
|
|
CALL My21
|
|
POP AX
|
|
MOV DX,SI
|
|
JMP SHORT i24bf
|
|
BadDrive:
|
|
POP DX ; get original back
|
|
MOV AH,Set_Default_Drive ; set original
|
|
CALL My21
|
|
POP AX
|
|
MOV AX,error_invalid_drive
|
|
MOV DX,SI
|
|
I24BF:
|
|
mov si,[QueueTail] ; take bad name out of queue
|
|
sub si,MaxFileLen ; SI points to the slot with bad name
|
|
mov [QueueTail],si
|
|
mov byte ptr [si],0 ; nul the first byte
|
|
stc
|
|
ret
|
|
|
|
|
|
;--- Check if print currently busy
|
|
GotFil:
|
|
CMP [CURRFIL],0 ; currently printing?
|
|
JZ OKAFIL ; no, start new print
|
|
mov bx,ax ; busy, close handle
|
|
call Set24
|
|
mov [PAbort],1 ; no Int24's
|
|
mov ah,Close
|
|
call My21
|
|
call Res24
|
|
clc
|
|
ret
|
|
|
|
;--- Save file data
|
|
OKAFIL:
|
|
MOV [CURRHAND],AX ; Valid handle
|
|
MOV AX,[ENDPTR]
|
|
MOV [NXTCHR],AX ; Buffer empty
|
|
MOV [CURRFIL],1
|
|
|
|
;--- Send Open on output device
|
|
call Open_Dev
|
|
clc
|
|
ret
|
|
|
|
BREAK <Fake int 21H>
|
|
|
|
;
|
|
; perform a system call as myself
|
|
;
|
|
My21:
|
|
call Context_switch
|
|
call Do_21
|
|
ret
|
|
|
|
Public do_21
|
|
DO_21:
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
IF IBM
|
|
CMP BYTE PTR CS:[INT15FLAG],0
|
|
JZ REAL_21
|
|
PUSH DS
|
|
PUSH BX
|
|
LDS BX,CS:[INT15PTR]
|
|
INC BYTE PTR [BX]
|
|
POP BX
|
|
POP DS
|
|
CALL OffSave
|
|
INT 21H
|
|
Call OnSave
|
|
PUSH DS
|
|
PUSH BX
|
|
PUSHF ; Flags from system call
|
|
LDS BX,CS:[INT15PTR]
|
|
DEC BYTE PTR [BX]
|
|
POPF
|
|
POP BX
|
|
POP DS
|
|
RET
|
|
ENDIF
|
|
|
|
REAL_21:
|
|
Call OffSave
|
|
INT 21H
|
|
CALL OnSave
|
|
RET
|
|
|
|
OffSave:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
PUSH AX
|
|
PUSH DX
|
|
MOV AX,Set_CTRL_C_Trapping SHL 8 + 2
|
|
XOR DL,DL
|
|
INT 21h
|
|
MOV CtrlC,DL
|
|
POP DX
|
|
POP AX
|
|
ret
|
|
|
|
OnSave:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
PUSH AX
|
|
PUSH DX
|
|
MOV AX,Set_CTRL_C_Trapping SHL 8 + 2
|
|
MOV DL,CtrlC
|
|
INT 21h
|
|
POP DX
|
|
POP AX
|
|
ret
|
|
|
|
BREAK <Priter Support>
|
|
|
|
ListMes2:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
LODSB
|
|
cmp al,0
|
|
jz LMesDone
|
|
CALL LOUT
|
|
JMP short LISTMES2
|
|
|
|
|
|
LISTMES:
|
|
ASSUME DS:CodeR,ES:NOTHING
|
|
LODSB
|
|
CMP AL,"$"
|
|
JZ LMESDONE
|
|
CALL LOUT
|
|
JMP short LISTMES
|
|
|
|
LMESDONE:
|
|
RET
|
|
|
|
LOUT:
|
|
PUSH BX
|
|
LWAIT:
|
|
CALL PSTAT
|
|
JZ PREADY
|
|
CMP [ERRCNT],ERRCNT2
|
|
JA POPRET ;Don't get stuck
|
|
JMP SHORT LWAIT
|
|
PREADY:
|
|
CALL POUT
|
|
POPRET:
|
|
POP BX
|
|
RET
|
|
|
|
;Stuff for BIOS interface
|
|
IOBUSY EQU 0200H
|
|
IOERROR EQU 8000H
|
|
|
|
public PRNR003S, PRNR003E
|
|
PRNR003S:
|
|
|
|
BYTEBUF DB ?
|
|
|
|
CALLAD DD ?
|
|
|
|
IOCALL DB 22
|
|
DB 0
|
|
IOREQ DB ?
|
|
IOSTAT DW 0
|
|
DB 8 DUP(?)
|
|
DB 0
|
|
DW OFFSET CodeR:BYTEBUF
|
|
INTSEG DW ?
|
|
IOCNT DW 1
|
|
DW 0
|
|
|
|
PRNR003E:
|
|
|
|
; Following two routines perform device open and close on output device.
|
|
; NO REGISTERS (including flags) are modified. No errors generated.
|
|
|
|
public open_dev
|
|
Open_Dev:
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
;
|
|
; We are now going to use the printer... We must lock down the printer so
|
|
; that the network does not intersperse output on us...
|
|
; We must also signal the REDIRector for stream open.
|
|
; We must ask DOS to set the Printer Flag to busy
|
|
;
|
|
PUSH BX
|
|
PUSHF
|
|
PUSH AX
|
|
PUSH DX
|
|
MOV DX,PrinterNum
|
|
CMP DX,-1
|
|
JZ NoORop
|
|
MOV AX,0203h ; redirector lock
|
|
INT 2FH
|
|
MOV AX,0201H ; Redirector OPEN
|
|
INT 2FH
|
|
NoORop:
|
|
mov ax,(SET_PRINTER_FLAG SHL 8) + 01
|
|
int 21H
|
|
POP DX
|
|
POP AX
|
|
MOV BL,DEVOPN ; Device OPEN
|
|
CALL OP_CL_OP
|
|
POPF
|
|
POP BX
|
|
RET
|
|
|
|
OP_CL_OP:
|
|
PUSH DS
|
|
PUSH SI
|
|
LDS SI,[LISTDEV]
|
|
ASSUME DS:NOTHING
|
|
TEST [SI.SDEVATT],DEVOPCL
|
|
JZ NO_OP_CL
|
|
PUSH CS
|
|
POP DS
|
|
ASSUME DS:CodeR
|
|
MOV [IOCALL],DOPCLHL
|
|
CALL DOCALL
|
|
NO_OP_CL:
|
|
POP SI
|
|
POP DS
|
|
ASSUME DS:NOTHING
|
|
Ret
|
|
|
|
|
|
public close_dev
|
|
Close_Dev:
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
;
|
|
; At this point, we release the ownership of the printer...
|
|
; and do a redirector CLOSE.
|
|
; Also tell DOS to reset the Printer Flag
|
|
;
|
|
PUSH BX
|
|
PUSHF
|
|
MOV BL,DEVCLS
|
|
CALL OP_CL_OP ; Device CLOSE
|
|
PUSH AX
|
|
PUSH DX
|
|
MOV DX,PrinterNum
|
|
CMP DX,-1
|
|
JZ NoCRop
|
|
MOV AX,0202H ; redirector CLOSE
|
|
INT 2FH
|
|
MOV AX,0204h ; redirector clear
|
|
INT 2FH
|
|
NoCRop:
|
|
MOV AX,(SET_PRINTER_FLAG SHL 8) +00
|
|
INT 21H
|
|
POP DX
|
|
POP AX
|
|
POPF
|
|
POP BX
|
|
RET
|
|
|
|
PSTAT:
|
|
ASSUME DS:CodeR
|
|
PUSH BX
|
|
INC [ERRCNT]
|
|
MOV BL,DEVOST
|
|
MOV [IOCALL],DSTATHL
|
|
CALL DOCALL
|
|
TEST [IOSTAT],IOERROR
|
|
JZ NOSTATERR
|
|
OR [IOSTAT],IOBUSY ;If error, show buisy
|
|
NOSTATERR:
|
|
TEST [IOSTAT],IOBUSY
|
|
JNZ RET13P ;Shows buisy
|
|
MOV [ERRCNT],0
|
|
RET13P:
|
|
POP BX
|
|
RET
|
|
|
|
POUT:
|
|
ASSUME DS:CodeR
|
|
MOV [BYTEBUF],AL
|
|
MOV BL,DEVWRT
|
|
MOV [IOCALL],DRDWRHL
|
|
DOCALL:
|
|
PUSH ES
|
|
MOV [IOREQ],BL
|
|
MOV BX,CS
|
|
MOV ES,BX
|
|
MOV [IOSTAT],0
|
|
MOV [IOCNT],1
|
|
PUSH DS
|
|
PUSH SI
|
|
PUSH AX
|
|
call Context_Switch
|
|
MOV BX,OFFSET CodeR:IOCALL
|
|
LDS SI,[LISTDEV]
|
|
ASSUME DS:NOTHING
|
|
MOV AX,[SI+SDEVSTRAT]
|
|
MOV WORD PTR [CALLAD],AX
|
|
CALL [CALLAD]
|
|
MOV AX,[SI+SDEVINT]
|
|
MOV WORD PTR [CALLAD],AX
|
|
CALL [CALLAD]
|
|
POP AX
|
|
POP SI
|
|
POP DS
|
|
ASSUME DS:CodeR
|
|
POP ES
|
|
RET
|
|
|
|
IF IBM
|
|
Public PRNR004S, PRNR004E
|
|
PRNR004S:
|
|
|
|
REAL_INT_13 DD ?
|
|
INT_13_RETADDR DW OFFSET CodeR:INT_13_BACK
|
|
|
|
PRNR004E:
|
|
|
|
INT_13 PROC FAR
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
PUSHF
|
|
INC [BUSY] ;Exclude if dumb program call ROM
|
|
PUSH CS
|
|
PUSH [INT_13_RETADDR]
|
|
PUSH WORD PTR [REAL_INT_13+2]
|
|
PUSH WORD PTR [REAL_INT_13]
|
|
RET
|
|
INT_13 ENDP
|
|
|
|
INT_13_BACK PROC FAR
|
|
PUSHF
|
|
DEC [BUSY]
|
|
POPF
|
|
RET 2 ;Chuck saved flags
|
|
INT_13_BACK ENDP
|
|
ENDIF
|
|
|
|
|
|
IF IBM
|
|
|
|
Public PRNR005S, PRNR005E
|
|
PRNR005S:
|
|
|
|
REAL_INT_15 DD ?
|
|
INT15FLAG DB 0 ; Init to off
|
|
INT15PTR DD ?
|
|
|
|
PRNR005E:
|
|
|
|
INT_15 PROC FAR
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP AH,20H
|
|
JNZ REAL_15 ; Not my function
|
|
CMP AL,1
|
|
JA REAL_15 ; I only know 0 and 1
|
|
JE FUNC1
|
|
INC [INT15FLAG] ; Turn ON
|
|
MOV WORD PTR [INT15PTR],BX ; Save counter loc
|
|
MOV WORD PTR [INT15PTR+2],ES
|
|
IRET
|
|
|
|
FUNC1:
|
|
MOV [INT15FLAG],0 ; Turn OFF
|
|
IRET
|
|
|
|
REAL_15:
|
|
JMP [REAL_INT_15]
|
|
|
|
INT_15 ENDP
|
|
|
|
|
|
Public PRNR006S, PRNR006E
|
|
PRNR006S:
|
|
|
|
FLAG17_14 DB 0 ; Flags state of AUX/PRN redir
|
|
REAL_INT_5 DD ?
|
|
REAL_INT_17 DD ?
|
|
INT_17_NUM DW 0
|
|
|
|
PRNR006E:
|
|
|
|
INT_17:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [FLAG17_14],1
|
|
JNZ DO_INT_17 ;The PRN device is not used
|
|
CMP [CURRFIL],0
|
|
JZ DO_INT_17 ;Nothing pending, so OK
|
|
CMP DX,[INT_17_NUM]
|
|
JNZ DO_INT_17 ;Not my unit
|
|
CMP [BUSY],0
|
|
JNZ DO_INT_17 ;You are me
|
|
STI
|
|
MOV AH,0A1H ;You are bad, get time out
|
|
IRET
|
|
|
|
DO_INT_17:
|
|
JMP [REAL_INT_17] ;Do a 17
|
|
|
|
Public PRNR007S, PRNR007E
|
|
PRNR007S:
|
|
REAL_INT_14 DD ?
|
|
INT_14_NUM DW 0
|
|
|
|
PRNR007E:
|
|
|
|
INT_14:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [FLAG17_14],2
|
|
JNZ DO_INT_14 ;The AUX device is not used
|
|
CMP [CURRFIL],0
|
|
JZ DO_INT_14 ;Nothing pending, so OK
|
|
CMP DX,[INT_14_NUM]
|
|
JNZ DO_INT_14 ;Not my unit
|
|
CMP [BUSY],0
|
|
JNZ DO_INT_14 ;You are me
|
|
STI
|
|
OR AH,AH
|
|
JZ SET14_AX
|
|
CMP AH,2
|
|
JBE SET14_AH
|
|
SET14_AX:
|
|
MOV AL,0
|
|
SET14_AH:
|
|
MOV AH,80H ;Time out
|
|
IRET
|
|
|
|
DO_INT_14:
|
|
JMP [REAL_INT_14] ;Do a 14
|
|
|
|
INT_5:
|
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|
CMP [FLAG17_14],1
|
|
JNZ DO_INT_5 ;The PRN device is not used
|
|
CMP [CURRFIL],0
|
|
JZ DO_INT_5 ;Nothing pending, so OK
|
|
CMP [INT_17_NUM],0
|
|
JNZ DO_INT_5 ;Only care about unit 0
|
|
IRET ;Pretend it worked
|
|
|
|
DO_INT_5:
|
|
JMP [REAL_INT_5] ;Do a 5
|
|
ENDIF
|
|
|
|
Public PRNR008S, PRNR008E
|
|
PRNR008S:
|
|
|
|
ERRCNT DW 0
|
|
|
|
IF IBM
|
|
;Reserved names for parallel card
|
|
INT_17_HITLIST LABEL BYTE
|
|
DB 8,"PRN ",0
|
|
DB 8,"LPT1 ",0
|
|
DB 8,"LPT2 ",1
|
|
DB 8,"LPT3 ",2
|
|
DB 0
|
|
;Reserved names for Async adaptor
|
|
INT_14_HITLIST LABEL BYTE
|
|
DB 8,"AUX ",0
|
|
DB 8,"COM1 ",0
|
|
DB 8,"COM2 ",1
|
|
DB 0
|
|
ENDIF
|
|
|
|
LISTNAME DB "PRN " ;Device name
|
|
|
|
PRNR008E:
|
|
|
|
SETDEV:
|
|
ASSUME CS:CodeR,DS:CodeR,ES:NOTHING,SS:NOTHING
|
|
; LISTNAME has the 8 char device name IN UPPER CASE
|
|
; CARRY set if bad device
|
|
; DS preserved, others destroyed.
|
|
|
|
MOV AH,GET_IN_VARS
|
|
call My21
|
|
PUSH ES
|
|
POP DS
|
|
LEA SI,ES:[BX.SYSI_DEV]
|
|
ASSUME DS:NOTHING
|
|
PUSH CS
|
|
POP ES
|
|
ASSUME ES:CodeR
|
|
MOV DI,OFFSET CodeR:LISTNAME
|
|
LOOKDEV:
|
|
TEST [SI.SDEVATT],DEVTYP
|
|
JZ NEXTDEV ; Skip Block devs
|
|
PUSH SI
|
|
PUSH DI
|
|
ADD SI,SDEVNAME ; Point at name
|
|
MOV CX,8
|
|
REPE CMPSB
|
|
POP DI
|
|
POP SI
|
|
JE GOTDEV
|
|
NEXTDEV:
|
|
LDS SI,[SI.SDEVNEXT]
|
|
CMP SI,-1
|
|
JNZ LOOKDEV
|
|
PUSH CS
|
|
POP DS
|
|
STC
|
|
RET
|
|
|
|
GOTDEV:
|
|
MOV WORD PTR CS:[CALLAD+2],DS ;Get I/O routines
|
|
MOV WORD PTR CS:[LISTDEV+2],DS ;Get I/O routines
|
|
MOV WORD PTR CS:[LISTDEV],SI
|
|
PUSH CS
|
|
POP DS
|
|
ASSUME DS:CodeR
|
|
|
|
IF IBM
|
|
MOV PrinterNum,-1 ; Assume not an INT 17 device
|
|
PUSH CS
|
|
POP ES
|
|
ASSUME ES:CodeR
|
|
MOV BP,OFFSET CodeR:LISTNAME
|
|
MOV SI,BP
|
|
MOV DI,OFFSET CodeR:INT_17_HITLIST
|
|
CHKHIT:
|
|
MOV SI,BP
|
|
MOV CL,[DI]
|
|
INC DI
|
|
JCXZ NOTONHITLIST
|
|
REPE CMPSB
|
|
LAHF
|
|
ADD DI,CX ;Bump to next position without affecting flags
|
|
MOV BL,[DI] ;Get device number
|
|
INC DI
|
|
SAHF
|
|
JNZ CHKHIT
|
|
XOR BH,BH
|
|
MOV [INT_17_NUM],BX
|
|
MOV PrinterNum,BX ; Set this as well to the INT 17 device
|
|
MOV [FLAG17_14],1
|
|
JMP SHORT ALLSET
|
|
|
|
NOTONHITLIST:
|
|
MOV DI,OFFSET CodeR:INT_14_HITLIST
|
|
CHKHIT2:
|
|
MOV SI,BP
|
|
MOV CL,[DI]
|
|
INC DI
|
|
JCXZ NOTONHITLIST2
|
|
REPE CMPSB
|
|
LAHF
|
|
ADD DI,CX ;Bump to next position without affecting flags
|
|
MOV BL,[DI] ;Get device number
|
|
INC DI
|
|
SAHF
|
|
JNZ CHKHIT2
|
|
XOR BH,BH
|
|
MOV [INT_14_NUM],BX
|
|
MOV [FLAG17_14],2
|
|
JMP SHORT ALLSET
|
|
|
|
NOTONHITLIST2:
|
|
MOV [FLAG17_14],0
|
|
ALLSET:
|
|
ENDIF
|
|
CLC
|
|
RET
|
|
|
|
|
|
IF HARDINT
|
|
|
|
BREAK <Bootstrap Cleanup Code>
|
|
|
|
ReBtINT:
|
|
ASSUME CS:CodeR,DS:NOTHING,ES:NOTHING,SS:Nothing
|
|
|
|
CLI
|
|
push cs
|
|
pop ds
|
|
|
|
IntWhileBusy:
|
|
INT ComInt
|
|
JNC NotBusy
|
|
JMP IntWhileBusy
|
|
ret
|
|
NotBusy:
|
|
|
|
INC [BUSY] ; Exclude hardware interrupts
|
|
INC [SOFINT] ; Exclude software interrupts
|
|
|
|
call CanAll ; Purge the Queue
|
|
|
|
LDS DX,CodeR:COMNEXT
|
|
mov ax,(set_interrupt_vector shl 8) or comint
|
|
INT 21H ;Set int 2f vector
|
|
|
|
LDS DX,CodeR:NEXTINT
|
|
mov ax,(set_interrupt_vector shl 8) or intloc
|
|
INT 21H ;Set hardware interrupt
|
|
|
|
mov ax,(set_interrupt_vector shl 8) or 15h
|
|
lds dx,CodeR:Real_Int_15 ; Reset the wait on event on ATs
|
|
int 21h
|
|
|
|
mov ax,(set_interrupt_vector shl 8) or 17h
|
|
LDS DX,CodeR:Real_Int_17
|
|
INT 21H ;Set printer interrupt
|
|
|
|
mov ax,(set_interrupt_vector shl 8) or 5h
|
|
LDS DX,CodeR:Real_Int_5
|
|
INT 21H ;Set print screen interrupt
|
|
|
|
mov ax,(set_interrupt_vector shl 8) or 14h
|
|
LDS DX,CodeR:Real_Int_14
|
|
INT 21H ;Set printer interrupt
|
|
|
|
mov ax,(set_interrupt_vector shl 8) or 24h
|
|
LDS DX,CodeR:HERRINT
|
|
INT 21H ;Set printer interrupt
|
|
|
|
LDS DX,CodeR:NEXT_REBOOT
|
|
mov ax,(set_interrupt_vector shl 8) or reboot
|
|
INT 21H ;Set bootstrap interrupt
|
|
|
|
STI
|
|
INT 19H
|
|
|
|
ENDIF ; HARDINT
|
|
|
|
|
|
|
|
|
|
;----- File name Queue and data buffer goes here
|
|
Public PRNR009S
|
|
PRNR009S:
|
|
FileQueue Label byte
|
|
db 0 ; the file queue starts empty
|
|
|
|
|
|
BREAK <Initialization Code>
|
|
|
|
BADSPOOL:
|
|
ASSUME CS:CodeR,DS:CodeR,ES:NOTHING,SS:Nothing
|
|
MOV DX,OFFSET CODER:BADMES
|
|
mov cx,badmeslen
|
|
mov bx,stdout
|
|
mov ah,write
|
|
INT 21H
|
|
;*********************************************************************
|
|
MOV AX,(SET_PRINTER_FLAG SHL 8) ; Set flag to Idle
|
|
int 21H
|
|
;*********************************************************************
|
|
MOV AX,(EXIT SHL 8) OR 0FFH
|
|
INT 21H
|
|
|
|
;--- move transient out of the way
|
|
ContTrans dd ? ; transient continuation address after move
|
|
|
|
MoveTrans label far
|
|
ASSUME CS:CodeR,DS:CodeR,ES:CodeR,SS:Nothing
|
|
cli
|
|
CLD
|
|
MOV [INTSEG],CS
|
|
CALL SETDEV
|
|
ASSUME ES:NOTHING
|
|
JC BADSPOOL
|
|
MOV DX,OFFSET CodeR:SPINT
|
|
MOV AL,SOFTINT
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H ;Get soft vector
|
|
MOV WORD PTR [SPNEXT+2],ES
|
|
MOV WORD PTR [SPNEXT],BX
|
|
MOV AL,SOFTINT
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set soft vector
|
|
MOV DX,OFFSET CodeR:SPCOMINT
|
|
MOV AL,ComInt
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H ;Get communication vector
|
|
MOV WORD PTR [COMNEXT+2],ES
|
|
MOV WORD PTR [COMNEXT],BX
|
|
MOV AL,ComInt
|
|
MOV AH,SET_INTERRUPT_VECTOR ;Set communication vector
|
|
INT 21H
|
|
|
|
IF IBM
|
|
MOV AL,13H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [REAL_INT_13+2],ES
|
|
MOV WORD PTR [REAL_INT_13],BX
|
|
MOV DX,OFFSET CodeR:INT_13
|
|
MOV AL,13H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set diskI/O interrupt
|
|
|
|
MOV AL,15H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [REAL_INT_15+2],ES
|
|
MOV WORD PTR [REAL_INT_15],BX
|
|
MOV DX,OFFSET CodeR:INT_15
|
|
MOV AL,15H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set INT 15 vector
|
|
|
|
MOV AL,17H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [REAL_INT_17+2],ES
|
|
MOV WORD PTR [REAL_INT_17],BX
|
|
MOV DX,OFFSET CodeR:INT_17
|
|
MOV AL,17H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set printer interrupt
|
|
MOV AL,14H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [REAL_INT_14+2],ES
|
|
MOV WORD PTR [REAL_INT_14],BX
|
|
MOV DX,OFFSET CodeR:INT_14
|
|
MOV AL,14H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set RS232 port interrupt
|
|
MOV AL,5H
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [REAL_INT_5+2],ES
|
|
MOV WORD PTR [REAL_INT_5],BX
|
|
MOV DX,OFFSET CodeR:INT_5
|
|
MOV AL,5H
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set print screen interrupt
|
|
ENDIF
|
|
|
|
IF HARDINT
|
|
MOV AH,GET_INDOS_FLAG
|
|
INT 21H
|
|
ASSUME ES:NOTHING
|
|
MOV WORD PTR [INDOS+2],ES ;Get indos flag location
|
|
MOV WORD PTR [INDOS],BX
|
|
MOV AL,INTLOC
|
|
MOV AH,GET_INTERRUPT_VECTOR
|
|
INT 21H
|
|
MOV WORD PTR [NEXTINT+2],ES
|
|
MOV WORD PTR [NEXTINT],BX
|
|
|
|
MOV AL,REBOOT ; We also need to chain
|
|
MOV AH,GET_INTERRUPT_VECTOR ; Into the INT 19 sequence
|
|
INT 21H ; To properly "unhook"
|
|
MOV WORD PTR [NEXT_REBOOT+2],ES ; ourselves from the TimerTick
|
|
MOV WORD PTR [NEXT_REBOOT],BX ; sequence
|
|
|
|
IF IBM
|
|
MOV AX,0B800H
|
|
INT 2FH
|
|
CMP AL,0
|
|
JE SET_HDSPINT ; No NETWORK, set hardware int
|
|
TEST BX,0000000011000100B
|
|
JNZ NO_HDSPINT ; DO NOT set HDSPINT if RCV|MSG|SRV
|
|
ENDIF
|
|
|
|
SET_HDSPINT:
|
|
MOV DX,OFFSET CodeR:HDSPINT
|
|
MOV AL,INTLOC
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set hardware interrupt
|
|
|
|
MOV DX,OFFSET CodeR:ReBtINT
|
|
MOV AL,REBOOT
|
|
MOV AH,SET_INTERRUPT_VECTOR
|
|
INT 21H ;Set bootstrap interrupt
|
|
|
|
NO_HDSPINT:
|
|
ENDIF
|
|
MOV DX,OFFSET CODER:GOODMES
|
|
mov cx,goodmeslen
|
|
mov bx,stdout
|
|
mov ah,write
|
|
int 21h
|
|
|
|
;--- Move transient
|
|
; Note: do not use stack, it may get trashed in move!
|
|
public RealMove
|
|
RealMove:
|
|
|
|
mov ax,offset dg:TransRet
|
|
mov word ptr [ContTrans],ax ; store return offset
|
|
mov ax,CodeR
|
|
add ax,[endres] ; get start of moved transient, actually
|
|
; this is 100 bytes more than need be
|
|
; because of lack of pdb, but who cares?
|
|
mov word ptr [ContTrans+2],ax ; return segment
|
|
mov es,ax ; new location for dg group
|
|
assume es:nothing
|
|
mov ax,dg
|
|
mov ds,ax
|
|
assume ds:nothing
|
|
mov cx,offset dg:TransSize
|
|
mov si,cx ; start from the bottom and move up
|
|
mov di,cx
|
|
std
|
|
rep movsb ; move all code, data and stack
|
|
cld ; restore to expected setting...
|
|
|
|
;--- normalize transient segment regs
|
|
mov ax,es
|
|
mov ds,ax
|
|
sub ax,dg ; displacement
|
|
mov dx,ss
|
|
add dx,ax ; displace stack segemnt
|
|
mov ss,dx
|
|
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
jmp ContTrans ; back to the transient...
|
|
|
|
PRNR009E:
|
|
|
|
CodeR EndS
|
|
|
|
End
|
|
|