diff options
Diffstat (limited to 'v2.0/source/CTRLC.ASM')
| -rw-r--r-- | v2.0/source/CTRLC.ASM | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/v2.0/source/CTRLC.ASM b/v2.0/source/CTRLC.ASM new file mode 100644 index 0000000..054903d --- /dev/null +++ b/v2.0/source/CTRLC.ASM | |||
| @@ -0,0 +1,468 @@ | |||
| 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 | ||