]> wirehaze git hosting - MS-DOS.git/blob - v2.0/source/CTRLC.ASM

wirehaze git hosting

Merge pull request #151 from jamespack/spelling-fix
[MS-DOS.git] / v2.0 / source / CTRLC.ASM
1 ;
2 ; ^C status routines for MSDOS
3 ;
4
5 INCLUDE DOSSEG.ASM
6
7 CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10 .xlist
11 .xcref
12 INCLUDE DOSSYM.ASM
13 INCLUDE DEVSYM.ASM
14 .cref
15 .list
16
17 i_need DevIOBuf,BYTE
18 i_need DidCTRLC,BYTE
19 i_need INDOS,BYTE
20 i_need DSKSTCOM,BYTE
21 i_need DSKSTCALL,BYTE
22 i_need DSKSTST,WORD
23 i_need BCON,DWORD
24 i_need DSKCHRET,BYTE
25 i_need DSKSTCNT,WORD
26 i_need IDLEINT,BYTE
27 i_need CONSWAP,BYTE
28 i_need user_SS,WORD
29 i_need user_SP,WORD
30 i_need ERRORMODE,BYTE
31 i_need ConC_spSave,WORD
32 i_need Exit_type,BYTE
33 i_need PFLAG,BYTE
34 i_need ExitHold,DWORD
35 i_need WPErr,BYTE
36 i_need ReadOp,BYTE
37 i_need CONTSTK,WORD
38 i_need Exit_Code,WORD
39 i_need CurrentPDB,WORD
40 i_need DIVMES,BYTE
41 i_need DivMesLen,BYTE
42
43 SUBTTL Checks for ^C in CON I/O
44 PAGE
45 ASSUME DS:NOTHING,ES:NOTHING
46
47 procedure DSKSTATCHK,NEAR ; Check for ^C if only one level in
48 CMP BYTE PTR [INDOS],1
49 retnz ; Do NOTHING
50 PUSH CX
51 PUSH ES
52 PUSH BX
53 PUSH DS
54 PUSH SI
55 PUSH CS
56 POP ES
57 PUSH CS
58 POP DS
59 ASSUME DS:DOSGROUP
60 XOR CX,CX
61 MOV BYTE PTR [DSKSTCOM],DEVRDND
62 MOV BYTE PTR [DSKSTCALL],DRDNDHL
63 MOV [DSKSTST],CX
64 MOV BX,OFFSET DOSGROUP:DSKSTCALL
65 LDS SI,[BCON]
66 ASSUME DS:NOTHING
67 invoke DEVIOCALL2
68 TEST [DSKSTST],STBUI
69 JNZ ZRET ; No characters available
70 MOV AL,BYTE PTR [DSKCHRET]
71 DSK1:
72 CMP AL,"C"-"@"
73 JNZ RET36
74 MOV BYTE PTR [DSKSTCOM],DEVRD
75 MOV BYTE PTR [DSKSTCALL],DRDWRHL
76 MOV BYTE PTR [DSKCHRET],CL
77 MOV [DSKSTST],CX
78 INC CX
79 MOV [DSKSTCNT],CX
80 invoke DEVIOCALL2 ; Eat the ^C
81 POP SI
82 POP DS
83 POP BX ; Clean stack
84 POP ES
85 POP CX
86 JMP SHORT CNTCHAND
87
88 ZRET:
89 XOR AL,AL ; Set zero
90 RET36:
91 POP SI
92 POP DS
93 POP BX
94 POP ES
95 POP CX
96 return
97
98 NOSTOP:
99 CMP AL,"P"-"@"
100 JZ INCHK
101
102 IF NOT TOGLPRN
103 CMP AL,"N"-"@"
104 JZ INCHK
105 ENDIF
106
107 CMP AL,"C"-"@"
108 JZ INCHK
109 return
110 DSKSTATCHK ENDP
111
112 procedure SPOOLINT,NEAR
113 PUSHF
114 CMP BYTE PTR [IDLEINT],0
115 JZ POPFRET
116 CMP BYTE PTR [ERRORMODE],0
117 JNZ POPFRET ;No spool ints in error mode
118 INT int_spooler
119 POPFRET:
120 POPF
121 RET18: return
122 SPOOLINT ENDP
123
124 procedure STATCHK,NEAR
125
126 invoke DSKSTATCHK ; Allows ^C to be detected under
127 ; input redirection
128 PUSH BX
129 XOR BX,BX
130 invoke GET_IO_FCB
131 POP BX
132 JC RET18
133 MOV AH,1
134 invoke IOFUNC
135 JZ SPOOLINT
136 CMP AL,'S'-'@'
137 JNZ NOSTOP
138 XOR AH,AH
139 invoke IOFUNC ; Eat Cntrl-S
140 JMP SHORT PAUSOSTRT
141 PRINTOFF:
142 PRINTON:
143 NOT BYTE PTR [PFLAG]
144 return
145
146 PAUSOLP:
147 CALL SPOOLINT
148 PAUSOSTRT:
149 MOV AH,1
150 invoke IOFUNC
151 JZ PAUSOLP
152 INCHK:
153 PUSH BX
154 XOR BX,BX
155 invoke GET_IO_FCB
156 POP BX
157 JC RET18
158 XOR AH,AH
159 invoke IOFUNC
160 CMP AL,'P'-'@'
161 JZ PRINTON
162 IF NOT TOGLPRN
163 CMP AL,'N'-'@'
164 JZ PRINTOFF
165 ENDIF
166 CMP AL,'C'-'@'
167 retnz
168 STATCHK ENDP
169
170 procedure CNTCHAND,NEAR
171 ; Ctrl-C handler.
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"
181 invoke BUFOUT
182 invoke CRLF
183 PUSH SS
184 POP DS
185 ASSUME DS:DOSGROUP
186 CMP BYTE PTR [CONSWAP],0
187 JZ NOSWAP
188 invoke SWAPBACK
189 NOSWAP:
190 CLI ; Prepare to play with stack
191 MOV SP,[user_SP]
192 MOV SS,[user_SS] ; User stack now restored
193 ASSUME SS:NOTHING
194 invoke restore_world ; User registers now restored
195 ASSUME DS:NOTHING
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)
202 POP AX
203 CMP SP,[ConC_spsave]
204 JNZ ctrlc_try_new ; new syscall maybe?
205 ctrlc_repeat:
206 MOV AX,[user_SS] ; no...
207 transfer COMMAND ; Repeat command otherwise
208
209 ctrlc_try_new:
210 SUB [ConC_spsave],2 ; Are there flags on the stack?
211 CMP SP,[ConC_spsave]
212 JZ ctrlc_new ; yes, new system call
213
214 ctrlc_abort:
215 MOV AX,(EXIT SHL 8) + 0
216 MOV BYTE PTR [DidCTRLC],0FFh
217
218 transfer COMMAND ; give up by faking $EXIT
219
220 ctrlc_new:
221 PUSH AX
222 POPF
223 POP [user_SS]
224 JNC ctrlc_repeat ; repeat operation
225 JMP ctrlc_abort ; indicate ^ced
226
227 CNTCHAND ENDP
228
229 SUBTTL DIVISION OVERFLOW INTERRUPT
230 PAGE
231 ; Default handler for division overflow trap
232 procedure DIVOV,NEAR
233 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
234 MOV SI,OFFSET DOSGROUP:DIVMES
235 CALL RealDivOv
236 JMP ctrlc_abort ; Use Ctrl-C abort on divide overflow
237 DIVOV ENDP
238
239 ;
240 ; RealDivOv: perform actual divide overflow stuff.
241 ; Inputs: none
242 ; Outputs: message to BCON
243 ;
244 procedure RealDivOv,NEAR ; Do divide overflow and clock process
245
246 PUSH CS ; get ES addressability
247 POP ES
248
249 PUSH CS ; get DS addressability
250 POP DS
251 ASSUME DS:DOSGROUP
252
253 MOV BYTE PTR [DskStCom],DevWrt
254 MOV BYTE PTR [DskStCall],DRdWrHL
255 MOV [DskSTST],0
256 MOV BL,[DivMesLen]
257 XOR BH,BH
258 MOV [DskStCnt],BX
259 MOV BX,OFFSET DOSGROUP:DskStCall
260 MOV WORD PTR [DskChRet+1],SI ; transfer address (need an EQU)
261 LDS SI,[BCON]
262 ASSUME DS:NOTHING
263 invoke DEVIOCALL2
264 MOV WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf
265 MOV [DskStCnt],1
266 return
267 RealDivOv ENDP
268
269 SUBTTL CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER
270 PAGE
271 procedure CHARHARD,NEAR
272 ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
273
274 ; Character device error handler
275 ; Same function as HARDERR
276
277 MOV WORD PTR [EXITHOLD+2],ES
278 MOV WORD PTR [EXITHOLD],BP
279 PUSH SI
280 AND DI,STECODE
281 MOV BP,DS ;Device pointer is BP:SI
282 CALL FATALC
283 POP SI
284 return
285 CHARHARD ENDP
286
287 procedure HardErr,NEAR
288 ASSUME DS:NOTHING,ES:NOTHING
289
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
298 ;
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?
302 JNZ NOSETWRPERR
303 PUSH AX
304 MOV AL,ES:[BP.dpb_drive]
305 MOV BYTE PTR [WPERR],AL ; Flag drive with WP error
306 POP AX
307 NOSETWRPERR:
308 SUB AX,CX ; Number of sectors successfully transferred
309 ADD DX,AX ; First sector number to retry
310 PUSH DX
311 MUL ES:[BP.dpb_sector_size] ; Number of bytes transferred
312 POP DX
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?
316 JB ERRINT
317 INC AH ; Flag for FAT
318 CMP DX,ES:[BP.dpb_dir_sector] ; In FAT?
319 JB ERRINT
320 INC AH
321 CMP DX,ES:[BP.dpb_first_sector] ; In directory?
322 JB ERRINT
323 INC AH ; Must be in data area
324 ERRINT:
325 SHL AH,1 ; Make room for read/write bit
326 OR AH,BYTE PTR [READOP]
327 entry FATAL
328 MOV AL,ES:[BP.dpb_drive] ; Get drive number
329 entry FATAL1
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
334 FATALC:
335 CMP BYTE PTR [ERRORMODE],0
336 JNZ SETIGN ; No INT 24s if already INT 24
337 MOV [CONTSTK],SP
338 PUSH SS
339 POP ES
340 ASSUME ES:DOSGROUP
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
344 MOV SS,[user_SS]
345 ASSUME SS:NOTHING
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
349 MOV ES:[user_SS],SS
350 MOV SP,ES
351 MOV SS,SP
352 ASSUME SS:DOSGROUP
353 MOV SP,[CONTSTK]
354 INC BYTE PTR [INDOS] ; Back in the DOS
355 MOV BYTE PTR [ERRORMODE],0 ; Back from INT 24
356 STI
357 IGNRET:
358 LES BP,[EXITHOLD]
359 ASSUME ES:NOTHING
360 CMP AL,2
361 JZ error_abort
362 MOV BYTE PTR [WPERR],-1 ;Forget about WP error
363 return
364
365 SETIGN:
366 XOR AL,AL ;Flag ignore
367 JMP SHORT IGNRET
368
369 error_abort:
370 PUSH SS
371 POP DS
372 ASSUME DS:DOSGROUP
373 CMP BYTE PTR [CONSWAP],0
374 JZ NOSWAP2
375 invoke SWAPBACK
376 NOSWAP2:
377 MOV BYTE PTR [exit_Type],Exit_hard_error
378 MOV DS,[CurrentPDB]
379 ASSUME DS:NOTHING
380
381 ;
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.
386 ;
387 ; output: none.
388 ;
389 entry reset_environment
390 ASSUME DS:NOTHING,ES:NOTHING
391 PUSH DS ; save PDB of process
392
393 MOV AL,int_Terminate
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
397
398 MOV BX,[CurrentPDB] ; get current process
399 MOV DS,BX ;
400 MOV AX,DS:[PDB_Parent_PID] ; get parent to return to
401 POP CX
402 ;
403 ; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
404 ; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
405 ; Exit_keep_process
406 ;
407 CMP AX,BX
408 JZ reset_return ; parentPDB = CurrentPDB
409 CMP BX,CX
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
414
415 invoke arena_free_process
416
417 ; reset environment at [CurrentPDB]; close those handles
418 MOV CX,FilPerProc
419
420 reset_free_jfn:
421 MOV BX,CX
422 PUSH CX
423 DEC BX ; get jfn
424 invoke $CLOSE ; close it, ignore return
425 POP CX
426 LOOP reset_free_jfn ; and do 'em all
427
428 reset_to_parent:
429 POP [CurrentPDB] ; set up process as parent
430
431 reset_return: ; come here for normal return
432 PUSH CS
433 POP DS
434 ASSUME DS:DOSGROUP
435 MOV AL,-1
436 invoke FLUSHBUF ; make sure that everything is clean
437
438 CLI
439 MOV BYTE PTR [INDOS],0 ;Go to known state
440 MOV BYTE PTR [WPERR],-1 ;Forget about WP error
441 ;
442 ; Snake into multitasking... Get stack from CurrentPDB person
443 ;
444 MOV DS,[CurrentPDB]
445 ASSUME DS:NOTHING
446 MOV SS,WORD PTR DS:[PDB_user_stack+2]
447 MOV SP,WORD PTR DS:[PDB_user_stack]
448
449 ASSUME SS:NOTHING
450 invoke restore_world
451 ASSUME ES:NOTHING
452 POP AX ; suck off CS:IP of interrupt...
453 POP AX
454 POP AX
455 MOV AX,0F202h ; STI
456 PUSH AX
457 PUSH WORD PTR [EXITHOLD+2]
458 PUSH WORD PTR [EXITHOLD]
459 STI
460 IRET ; Long return back to user terminate address
461 HardErr ENDP
462
463 ASSUME SS:DOSGROUP
464
465 do_ext
466
467 CODE ENDS
468 END