2 ; ^C status routines for MSDOS
7 CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
31 i_need ConC_spSave
,WORD
39 i_need CurrentPDB
,WORD
43 SUBTTL Checks for ^C
in CON I
/O
45 ASSUME
DS:NOTHING
,ES:NOTHING
47 procedure DSKSTATCHK
,NEAR ; Check for ^C if only one level in
48 CMP BYTE PTR [INDOS
],1
61 MOV BYTE PTR [DSKSTCOM
],DEVRDND
62 MOV BYTE PTR [DSKSTCALL
],DRDNDHL
64 MOV BX,OFFSET DOSGROUP
:DSKSTCALL
69 JNZ ZRET
; No characters available
70 MOV AL,BYTE PTR [DSKCHRET
]
74 MOV BYTE PTR [DSKSTCOM
],DEVRD
75 MOV BYTE PTR [DSKSTCALL
],DRDWRHL
76 MOV BYTE PTR [DSKCHRET
],CL
80 invoke DEVIOCALL2
; Eat the ^C
112 procedure SPOOLINT
,NEAR
114 CMP BYTE PTR [IDLEINT
],0
116 CMP BYTE PTR [ERRORMODE
],0
117 JNZ POPFRET
;No spool ints in error mode
124 procedure STATCHK
,NEAR
126 invoke DSKSTATCHK
; Allows ^C to be detected under
139 invoke IOFUNC
; Eat Cntrl-S
170 procedure CNTCHAND
,NEAR
172 ; "^C" and CR/LF is printed. Then the user registers are restored and
173 ; the user CTRL-C handler is executed. At this point the top of the stack
174 ; has 1) the interrupt return address should the user CTRL-C handler wish
175 ; to allow processing to continue; 2) the original interrupt return address
176 ; to the code that performed the function call in the first place. If
177 ; the user CTRL-C handler wishes to continue, it must leave all registers
178 ; unchanged and RET (not IRET) with carry CLEAR. If carry is SET then
179 ; an terminate system call is simulated.
180 MOV AL,3 ; Display "^C"
186 CMP BYTE PTR [CONSWAP
],0
190 CLI ; Prepare to play with stack
192 MOV SS,[user_SS
] ; User stack now restored
194 invoke restore_world
; User registers now restored
196 MOV BYTE PTR [INDOS
],0 ; Go to known state
197 MOV BYTE PTR [ERRORMODE
],0
198 MOV [ConC_spsave
],SP ; save his SP
199 INT int_ctrl_c
; Execute user Ctrl-C handler
200 MOV [user_SS
],AX ; save the AX
201 PUSHF ; and the flags (maybe new call)
204 JNZ ctrlc_try_new
; new syscall maybe?
206 MOV AX,[user_SS
] ; no...
207 transfer COMMAND
; Repeat command otherwise
210 SUB [ConC_spsave
],2 ; Are there flags on the stack?
212 JZ ctrlc_new
; yes, new system call
215 MOV AX,(EXIT
SHL 8) + 0
216 MOV BYTE PTR [DidCTRLC
],0FFh
218 transfer COMMAND
; give up by faking $EXIT
224 JNC ctrlc_repeat
; repeat operation
225 JMP ctrlc_abort
; indicate ^ced
229 SUBTTL DIVISION OVERFLOW INTERRUPT
231 ; Default handler for division overflow trap
233 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
234 MOV SI,OFFSET DOSGROUP
:DIVMES
236 JMP ctrlc_abort
; Use Ctrl-C abort on divide overflow
240 ; RealDivOv: perform actual divide overflow stuff.
242 ; Outputs: message to BCON
244 procedure RealDivOv
,NEAR ; Do divide overflow and clock process
246 PUSH CS ; get ES addressability
249 PUSH CS ; get DS addressability
253 MOV BYTE PTR [DskStCom
],DevWrt
254 MOV BYTE PTR [DskStCall
],DRdWrHL
259 MOV BX,OFFSET DOSGROUP
:DskStCall
260 MOV WORD PTR [DskChRet
+1],SI ; transfer address (need an EQU)
264 MOV WORD PTR [DskChRet
+1],OFFSET DOSGROUP
:DevIOBuf
269 SUBTTL CHARHRD
,HARDERR
,ERROR
-- HANDLE DISK ERRORS
AND RETURN TO USER
271 procedure CHARHARD
,NEAR
272 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
274 ; Character device error handler
275 ; Same function as HARDERR
277 MOV WORD PTR [EXITHOLD
+2],ES
278 MOV WORD PTR [EXITHOLD
],BP
281 MOV BP,DS ;Device pointer is BP:SI
287 procedure HardErr
,NEAR
288 ASSUME
DS:NOTHING
,ES:NOTHING
290 ; Hard disk error handler. Entry conditions:
291 ; DS:BX = Original disk transfer address
292 ; DX = Original logical sector number
293 ; CX = Number of sectors to go (first one gave the error)
294 ; AX = Hardware error code
295 ; DI = Original sector transfer count
296 ; ES:BP = Base of drive parameters
297 ; [READOP] = 0 for read, 1 for write
299 XCHG AX,DI ; Error code in DI, count in AX
300 AND DI,STECODE
; And off status bits
301 CMP DI,WRECODE
; Write Protect Error?
304 MOV AL,ES:[BP.dpb_drive
]
305 MOV BYTE PTR [WPERR
],AL ; Flag drive with WP error
308 SUB AX,CX ; Number of sectors successfully transferred
309 ADD DX,AX ; First sector number to retry
311 MUL ES:[BP.dpb_sector_size
] ; Number of bytes transferred
313 ADD BX,AX ; First address for retry
314 XOR AH,AH ; Flag disk section in error
315 CMP DX,ES:[BP.dpb_first_FAT
] ; In reserved area?
317 INC AH ; Flag for FAT
318 CMP DX,ES:[BP.dpb_dir_sector
] ; In FAT?
321 CMP DX,ES:[BP.dpb_first_sector
] ; In directory?
323 INC AH ; Must be in data area
325 SHL AH,1 ; Make room for read/write bit
326 OR AH,BYTE PTR [READOP
]
328 MOV AL,ES:[BP.dpb_drive
] ; Get drive number
330 MOV WORD PTR [EXITHOLD
+2],ES
331 MOV WORD PTR [EXITHOLD
],BP ; The only things we preserve
332 LES SI,ES:[BP.dpb_driver_addr
]
333 MOV BP,ES ; BP:SI points to the device involved
335 CMP BYTE PTR [ERRORMODE
],0
336 JNZ SETIGN
; No INT 24s if already INT 24
341 CLI ; Prepare to play with stack
342 INC BYTE PTR [ERRORMODE
] ; Flag INT 24 in progress
343 DEC BYTE PTR [INDOS
] ; INT 24 handler might not return
346 MOV SP,ES:[user_SP
] ; User stack pointer restored
347 INT int_fatal_abort
; Fatal error interrupt vector, must preserve ES
348 MOV ES:[user_SP
],SP ; restore our stack
354 INC BYTE PTR [INDOS
] ; Back in the DOS
355 MOV BYTE PTR [ERRORMODE
],0 ; Back from INT 24
362 MOV BYTE PTR [WPERR
],-1 ;Forget about WP error
366 XOR AL,AL ;Flag ignore
373 CMP BYTE PTR [CONSWAP
],0
377 MOV BYTE PTR [exit_Type
],Exit_hard_error
382 ; reset_environment checks the DS value against the CurrentPDB. If they
383 ; are different, then an old-style return is performed. If they are
384 ; the same, then we release jfns and restore to parent. We still use
385 ; the PDB at DS:0 as the source of the terminate addresses.
389 entry reset_environment
390 ASSUME
DS:NOTHING
,ES:NOTHING
391 PUSH DS ; save PDB of process
394 invoke $Get_interrupt_vector
; and who to go to
395 MOV WORD PTR [EXITHOLD
+2],ES ; save return address
396 MOV WORD PTR [EXITHOLD
],BX
398 MOV BX,[CurrentPDB
] ; get current process
400 MOV AX,DS:[PDB_Parent_PID
] ; get parent to return to
403 ; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
404 ; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
408 JZ reset_return
; parentPDB = CurrentPDB
410 JNZ reset_return
; CurrentPDB <> ThisPDB
411 PUSH AX ; save parent
412 CMP BYTE PTR [exit_type
],Exit_keep_process
413 JZ reset_to_parent
; keeping this process
415 invoke arena_free_process
417 ; reset environment at [CurrentPDB]; close those handles
424 invoke $CLOSE
; close it, ignore return
426 LOOP reset_free_jfn
; and do 'em all
429 POP [CurrentPDB
] ; set up process as parent
431 reset_return: ; come here for normal return
436 invoke FLUSHBUF
; make sure that everything is clean
439 MOV BYTE PTR [INDOS
],0 ;Go to known state
440 MOV BYTE PTR [WPERR
],-1 ;Forget about WP error
442 ; Snake into multitasking... Get stack from CurrentPDB person
446 MOV SS,WORD PTR DS:[PDB_user_stack
+2]
447 MOV SP,WORD PTR DS:[PDB_user_stack
]
452 POP AX ; suck off CS:IP of interrupt...
457 PUSH WORD PTR [EXITHOLD
+2]
458 PUSH WORD PTR [EXITHOLD
]
460 IRET ; Long return back to user terminate address