]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/DOS/MS_CODE.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / MS_CODE.ASM
1 ; SCCSID = @(#)mscode.asm 1.2 85/07/23
2 ;
3 ; MSCODE.ASM -- MSDOS code
4 ;
5
6 .xlist
7 .xcref
8 include dossym.inc
9 include devsym.inc
10 include dosseg.asm
11 include ifssym.inc
12 include fastopen.inc
13 include fastxxxx.inc
14 .cref
15 .list
16
17 AsmVars <Kanji, Debug>
18
19 CODE SEGMENT BYTE PUBLIC 'CODE'
20
21 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
22
23 I_need InDos,BYTE ; TRUE => we are in dos, no interrupt
24 I_need OpenBuf,128 ; temp name buffer
25 I_need ExtErr,WORD ; extended error code
26 I_need User_SS,WORD ; stack segment from user
27 I_need User_SP,WORD ; stack pointer from user
28 I_need DskStack,BYTE ; stack segment inside DOS
29 I_need ThisCDS,DWORD ; Currently referenced CDS pointer
30 I_need ThisDPB,DWORD ; Currently referenced DPB pointer
31 I_need Err_Table_21 ; allowed return map table for errors
32 I_need FailErr,BYTE ; TRUE => system call is being failed
33 I_need ExtErr_Action,BYTE ; recommended action
34 I_need ExtErr_Class,BYTE ; error classification
35 I_need ExtErr_Locus,BYTE ; error location
36 I_need I21_Map_E_Tab,BYTE ; mapping extended error table
37 I_need User_In_AX,WORD ; initial input user AX
38 I_need FOO,WORD ; return address for dos 2f dispatch
39 I_need DTAB,WORD ; dos 2f dispatch table
40 I_need HIGH_SECTOR,WORD ; >32mb
41 I_need IFS_DRIVER_ERR,WORD ; >32mb
42 I_need FastOpenFlg,BYTE ;
43 I_need FastSeekFlg,BYTE ;
44 I_need CURSC_DRIVE,BYTE ;
45
46 BREAK <NullDev -- Driver for null device>
47
48 procedure SNULDEV,FAR
49 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
50 OR ES:[BX.REQSTAT],STDON ; Set done bit
51 entry INULDEV
52 RET ; MUST NOT BE A RETURN!
53 EndProc SNULDEV
54
55 BREAK <AbsDRD, AbsDWRT -- INT int_disk_read, int_disk_write handlers>
56
57
58 TABLE SEGMENT
59 Public MSC001S,MSC001E
60 MSC001S label byte
61 IF IBM
62 ; Codes returned by BIOS
63 ERRIN:
64 DB 2 ; NO RESPONSE
65 DB 6 ; SEEK FAILURE
66 DB 12 ; GENERAL ERROR
67 DB 4 ; BAD CRC
68 DB 8 ; SECTOR NOT FOUND
69 DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK
70 ERROUT:
71 ; DISK ERRORS RETURNED FROM INT 25 and 26
72 DB 80H ; NO RESPONSE
73 DB 40H ; Seek failure
74 DB 2 ; Address Mark not found
75 DB 10H ; BAD CRC
76 DB 4 ; SECTOR NOT FOUND
77 DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK
78
79 NUMERR EQU $-ERROUT
80 ENDIF
81 MSC001E label byte
82
83 TABLE ENDS
84
85 ; AbsSetup - setup for abs disk functions
86
87 Procedure AbsSetup,NEAR
88 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
89 INC INDOS
90 STI
91 CLD
92 PUSH DS
93 Context DS
94 CALL GETBP
95 JC errdriv ;PM. error drive ;AN000;
96 MOV ES:[BP.dpb_free_cnt],-1 ; do not trust user at all.
97 errdriv:
98 POP DS
99 ASSUME DS:NOTHING
100 retc
101
102 MOV [HIGH_SECTOR],0 ;>32mb from API ;AN000;
103 CALL RW32_CONVERT ;>32mb convert 32bit format to 16bit ;AN000;
104 retc
105
106 invoke SET_RQ_SC_PARMS ;LB. set up SC parms ;AN000;
107 PUSH DS
108 PUSH SI
109 PUSH AX
110 Context DS
111 MOV SI,OFFSET DOSGROUP:OPENBUF
112 MOV [SI],AL
113 ADD BYTE PTR [SI],"A"
114 MOV WORD PTR [SI+1],003AH ; ":",0
115 MOV AX,0300H
116 CLC
117 INT int_IBM ; Will set carry if shared
118 POP AX
119 POP SI
120 POP DS
121 ASSUME DS:NOTHING
122 retnc
123 MOV ExtErr,error_not_supported
124 return
125 EndProc AbsSetup
126
127 ; Interrupt 25 handler. Performs absolute disk read.
128 ; Inputs: AL - 0-based drive number
129 ; DS:BX point to destination buffer
130 ; CX number of logical sectors to read
131 ; DX starting logical sector number (0-based)
132 ; Outputs: Original flags still on stack
133 ; Carry set
134 ; AH error from BIOS
135 ; AL same as low byte of DI from INT 24
136
137 procedure ABSDRD,FAR
138 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
139
140 CLI
141 MOV [user_SS],SS
142 MOV [user_SP],SP
143 PUSH CS
144 POP SS
145 ASSUME SS:DOSGROUP
146 MOV SP,OFFSET DOSGROUP:DSKSTACK
147 invoke Save_World ;>32mb save all regs ;AN000;
148 PUSH ES
149 CALL AbsSetup
150 JC ILEAVE
151 if not ibmcopyright
152 ; Here is a gross temporary fix to get around a serious design flaw in
153 ; the secondary cache. The secondary cache does not check for media
154 ; changed (it should). Hence, you can change disks, do an absolute
155 ; read, and get data from the previous disk. To get around this,
156 ; we just won't use the secondary cache for absolute disk reads.
157 ; -mw 8/5/88
158 EnterCrit critDisk
159 MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
160 LeaveCrit critDisk
161 endif
162 invoke DSKREAD
163 TLEAVE:
164 JZ ILEAVE
165
166 IF IBM
167 ; Translate the error code to ancient 1.1 codes
168 PUSH ES
169 PUSH CS
170 POP ES
171 XOR AH,AH ; Nul error code
172 MOV CX,NUMERR ; Number of possible error conditions
173 MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions
174 REPNE SCASB
175 JNZ LEAVECODE ; Not found
176 MOV AH,ES:[DI+NUMERR-1] ; Get translation
177 LEAVECODE:
178 POP ES
179 ENDIF
180 MOV [IFS_DRIVER_ERR],AX ;>32mb save error
181 STC
182 ILEAVE:
183 POP ES
184 invoke Restore_World ;>32mb ;AN000;
185 CLI
186 DEC INDOS
187 MOV SS,[user_SS]
188 ASSUME SS:NOTHING
189 MOV SP,[user_SP]
190 MOV AX,[IFS_DRIVER_ERR] ;>32mb restore error ;AN000;
191 STI
192 RET ; This must not be a RETURN!
193 EndProc ABSDRD
194
195 ; Interrupt 26 handler. Performs absolute disk write.
196 ; Inputs: AL - 0-based drive number
197 ; DS:BX point to source buffer
198 ; CX number of logical sectors to write
199 ; DX starting logical sector number (0-based)
200 ; Outputs: Original flags still on stack
201 ; Carry set
202 ; AH error from BIOS
203 ; AL same as low byte of DI from INT 24
204
205 procedure ABSDWRT,FAR
206 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
207
208 CLI
209 MOV [user_SS],SS
210 MOV [user_SP],SP
211 PUSH CS
212 POP SS
213 ASSUME SS:DOSGROUP
214 MOV SP,OFFSET DOSGROUP:DSKSTACK
215 invoke Save_World ;>32mb save all regs ;AN000;
216
217 PUSH ES
218 CALL AbsSetup
219 JC ILEAVE
220
221 EnterCrit critDisk
222 MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
223 CALL Fastxxx_Purge ; purge fatopen ;AN000;
224 LeaveCrit critDisk
225
226 invoke DSKWRITE
227 JMP TLEAVE
228 EndProc ABSDWRT
229
230 ; Inputs:
231 ; AL = Logical unit number (A = 0)
232 ; Function:
233 ; Find Drive Parameter Block
234 ; Outputs:
235 ; ES:BP points to DPB
236 ; [THISDPB] = ES:BP
237 ; Carry set if unit number bad or unit is a NET device.
238 ; Later case sets extended error error_I24_not_supported
239 ; No other registers altered
240
241 Procedure GETBP,NEAR
242 DOSAssume CS,<DS>,"GetBP"
243 ASSUME ES:NOTHING
244
245 PUSH AX
246 ADD AL,1 ; No increment; need carry flag
247 JC SkipGet
248 invoke GetThisDrv
249 JNC SkipGet ;PM. good drive ;AN000;
250 XOR AH,AH ;DCR. ax= error code ;AN000;
251 CMP AX,error_not_dos_disk ;DCR. is unknown media ? ;AN000;
252 JZ SkipGet ;DCR. yes, let it go ;AN000;
253 STC ;DCR. ;AN000;
254 MOV ExtErr,AX ;PM. invalid drive or Non DOS drive ;AN000;
255 MOV [IFS_DRIVER_ERR],0201H ;PM. other errors/unknown unit ;AN000;
256 SkipGet:
257 POP AX
258 retc
259 LES BP,[THISCDS]
260 TEST ES:[BP.curdir_flags],curdir_isnet ; Clears carry
261 JZ GETBP_CDS
262 LES BP,ES:[BP.curdir_ifs_hdr] ;IFS. if remote file ;AN000;
263 TEST ES:[BP.ifs_attribute],IFSREMOTE ;IFS. ;AN000;
264 LES BP,[THISCDS]
265 JZ GETBP_CDS ;IFS. then error ;AN000;
266 MOV ExtErr,error_not_supported
267 STC
268 return
269
270 GETBP_CDS:
271 LES BP,ES:[BP.curdir_devptr]
272
273 entry GOTDPB
274 DOSAssume CS,<DS>,"GotDPB"
275 ; Load THISDPB from ES:BP
276
277 MOV WORD PTR [THISDPB],BP
278 MOV WORD PTR [THISDPB+2],ES
279 return
280 EndProc GetBP
281
282 BREAK <SYS_RET_OK SYS_RET_ERR CAL_LK ETAB_LK set system call returns>
283
284 ASSUME SS:DOSGROUP
285
286 ;
287 ; These are the general system call exit mechanisms. All internal system
288 ; calls will transfer (jump) to one of these at the end. Their sole purpose
289 ; is to set the user's flags and set his AX register for return.
290 ;
291
292 procedure SYS_RETURN,NEAR
293 ASSUME DS:NOTHING,ES:NOTHING
294 entry SYS_RET_OK
295 invoke FETCHI_CHECK ; TAG checking for FETCHI
296 invoke get_user_stack
297 AND [SI.user_F],NOT f_Carry ; turn off user's carry flag
298 JMP SHORT DO_RET ; carry is now clear
299
300 entry SYS_RET_ERR
301 XOR AH,AH ; hack to allow for smaller error rets
302 invoke ETAB_LK ; Make sure code is OK, EXTERR gets set
303 CALL ErrorMap
304 entry From_GetSet
305 invoke get_user_stack
306 OR [SI.user_F],f_Carry ; signal carry to user
307 STC ; also, signal internal error
308 DO_RET:
309 MOV [SI.user_AX],AX ; Really only sets AH
310 return
311
312 entry FCB_RET_OK
313 entry CPMFunc
314 XOR AL,AL
315 return
316
317 entry FCB_RET_ERR
318 XOR AH,AH
319 mov exterr,AX
320 CALL ErrorMap
321 MOV AL,-1
322 return
323
324 entry errorMap
325 PUSH SI
326 MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
327 CMP [FAILERR],0 ; Check for SPECIAL case.
328 JZ EXTENDED_NORMAL ; All is OK.
329 MOV [EXTERR],error_FAIL_I24 ; Ooops, this is the REAL reason
330 MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
331 EXTENDED_NORMAL:
332 invoke CAL_LK ; Set CLASS,ACTION,LOCUS for EXTERR
333 POP SI
334 return
335
336 EndProc SYS_RETURN
337
338 ; Inputs:
339 ; SI is OFFSET in DOSGROUP of CLASS,ACTION,LOCUS Table to use
340 ; (DS NEED not be DOSGROUP)
341 ; [EXTERR] is set with error
342 ; Function:
343 ; Look up and set CLASS ACTION and LOCUS values for GetExtendedError
344 ; Outputs:
345 ; [EXTERR_CLASS] set
346 ; [EXTERR_ACTION] set
347 ; [EXTERR_LOCUS] set (EXCEPT on certain errors as determined by table)
348 ; Destroys SI, FLAGS
349
350 procedure CAL_LK,NEAR
351 ASSUME DS:NOTHING,ES:NOTHING
352
353 PUSH DS
354 PUSH AX
355 PUSH BX
356 Context DS ; DS:SI -> Table
357 MOV BX,[EXTERR] ; Get error in BL
358 TABLK1:
359 LODSB
360 CMP AL,0FFH
361 JZ GOT_VALS ; End of table
362 CMP AL,BL
363 JZ GOT_VALS ; Got entry
364 ADD SI,3 ; Next table entry
365 JMP TABLK1
366
367 GOT_VALS:
368 LODSW ; AL is CLASS, AH is ACTION
369 CMP AH,0FFH
370 JZ NO_SET_ACT
371 MOV [EXTERR_ACTION],AH ; Set ACTION
372 NO_SET_ACT:
373 CMP AL,0FFH
374 JZ NO_SET_CLS
375 MOV [EXTERR_CLASS],AL ; Set CLASS
376 NO_SET_CLS:
377 LODSB ; Get LOCUS
378 CMP AL,0FFH
379 JZ NO_SET_LOC
380 MOV [EXTERR_LOCUS],AL
381 NO_SET_LOC:
382 POP BX
383 POP AX
384 POP DS
385 return
386 EndProc CAL_LK
387
388 ; Inputs:
389 ; AX is error code
390 ; [USER_IN_AX] has AH value of system call involved
391 ; Function:
392 ; Make sure error code is appropriate to this call.
393 ; Outputs:
394 ; AX MAY be mapped error code
395 ; [EXTERR] = Input AX
396 ; Destroys ONLY AX and FLAGS
397
398 procedure ETAB_LK,NEAR
399 ASSUME DS:NOTHING,ES:NOTHING
400
401 PUSH DS
402 PUSH SI
403 PUSH CX
404 PUSH BX
405 Context DS
406 MOV [EXTERR],AX ; Set EXTERR with "real" error
407 MOV SI,OFFSET DOSGROUP:I21_MAP_E_TAB
408 MOV BH,AL ; Real code to BH
409 MOV BL,BYTE PTR [USER_IN_AX + 1] ; Sys call to BL
410 TABLK2:
411 LODSW
412 CMP AL,0FFH ; End of table?
413 JZ NOT_IN_TABLE ; Yes
414 CMP AL,BL ; Found call?
415 JZ GOT_CALL ; Yes
416 XCHG AH,AL ; Count to AL
417 XOR AH,AH ; Make word for add
418 ADD SI,AX ; Next table entry
419 JMP TABLK2
420
421 NOT_IN_TABLE:
422 MOV AL,BH ; Restore original code
423 JMP SHORT NO_MAP
424
425 GOT_CALL:
426 MOV CL,AH
427 XOR CH,CH ; Count of valid err codes to CX
428 CHECK_CODE:
429 LODSB
430 CMP AL,BH ; Code OK?
431 JZ NO_MAP ; Yes
432 LOOP CHECK_CODE
433 NO_MAP:
434 XOR AH,AH ; AX is now valid code
435 POP BX
436 POP CX
437 POP SI
438 POP DS
439 return
440
441 EndProc ETAB_LK
442
443 BREAK <DOS 2F Handler and default NET 2F handler>
444
445 IF installed
446
447 ;
448 ; SetBad sets up info for bad functions
449 ;
450 Procedure SetBad,NEAR
451 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
452 MOV AX,error_invalid_function ; ALL NET REQUESTS get inv func
453 MOV ExtErr_LOCUS,errLoc_UNK
454 STC
455 ret
456 EndProc SetBad
457 ;
458 ; BadCall is the initial routine for bad function calls
459 ;
460 procedure BadCall,FAR
461 call SetBad
462 ret
463 EndProc BadCall
464 ;
465 ; OKCall always sets carry to off.
466 ;
467 Procedure OKCall,FAR
468 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
469 CLC
470 ret
471 EndProc OKCall
472
473 ; INT 2F handler works as follows:
474 ; PUSH AX
475 ; MOV AX,multiplex:function
476 ; INT 2F
477 ; POP ...
478 ; The handler itself needs to make the AX available for the various routines.
479
480 PUBLIC Int2F
481 INT2F PROC FAR
482
483 INT2FNT:
484 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
485 STI
486 CMP AH,multNET
487 JNZ INT2FSHR
488 TestInstall:
489 OR AL,AL
490 JZ Leave2F
491 BadFunc:
492 CALL SetBad
493 entry Leave2F
494 RET 2 ; long return + clear flags off stack
495
496 INT2FSHR:
497 CMP AH,multSHARE ; is this a share request
498 JZ TestInstall ; yes, check for installation
499
500 INT2FNLS:
501 CMP AH,NLSFUNC ; is this a DOS 3.3 NLSFUNC request
502 JZ TestInstall ; yes check for installation
503
504 INT2FDOS:
505 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
506 CMP AH,multDOS
507 JZ DispatchDOS
508 IRET ; This assume that we are at the head
509 ; of the list
510 INT2F ENDP
511
512 DispatchDOS:
513 PUSH FOO ; push return address
514 PUSH DTab ; push table address
515 PUSH AX ; push index
516 PUSH BP
517 MOV BP,SP
518 ; stack looks like:
519 ; 0 BP
520 ; 2 DISPATCH
521 ; 4 TABLE
522 ; 6 RETURN
523 ; 8 LONG-RETURN
524 ; c FLAGS
525 ; e AX
526
527 MOV AX,[BP+0Eh] ; get AX value
528 POP BP
529 Invoke TableDispatch
530 JMP BadFunc ; return indicates invalid function
531
532 Procedure INT2F_etcetera,NEAR
533 entry DosGetGroup
534 PUSH CS
535 POP DS
536 return
537
538 entry DOSInstall
539 MOV AL,0FFh
540 return
541 EndProc INT2F_etcetera
542
543 ENDIF
544 ;Input: same as ABSDRD and ABSDWRT
545 ; ES:BP -> DPB
546 ;Functions: convert 32bit absolute RW input parms to 16bit input parms
547 ;Output: carry set when CX=-1 and drive is less then 32mb
548 ; carry clear, parms ok
549 ;
550 Procedure RW32_CONVERT,NEAR
551 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
552 CMP CX,-1 ;>32mb new format ? ;AN000;
553 JZ new32format ;>32mb yes ;AN000;
554 PUSH AX ;>32mb save ax ;AN000;
555 PUSH DX ;>32mb save dx ;AN000;
556 MOV AX,ES:[BP.dpb_max_cluster] ;>32mb get max cluster # ;AN000;
557 MOV DL,ES:[BP.dpb_cluster_mask] ;>32mb ;AN000;
558 CMP DL,0FEH ;>32mb removable ? ;AN000;
559 JZ letold ;>32mb yes ;AN000;
560 INC DL ;>32mb ;AN000;
561 XOR DH,DH ;>32mb dx = sector/cluster ;AN000;
562 MUL DX ;>32mb dx:ax= max sector # ;AN000;
563 OR DX,DX ;>32mb > 32mb ? ;AN000;
564 letold:
565 POP DX ;>32mb retore dx ;AN000;
566 POP AX ;>32mb restore ax ;AN000;
567 JZ old_style ;>32mb no ;AN000;
568 MOV [IFS_DRIVER_ERR],0207H ;>32mb error ;AN000;
569 STC ;>32mb ;AN000;
570 return ;>32mb ;AN000;
571 new32format:
572 MOV DX,WORD PTR [BX.SECTOR_RBA+2];>32mb ;AN000;
573 MOV [HIGH_SECTOR],DX ;>32mb ;AN000;
574 MOV DX,WORD PTR [BX.SECTOR_RBA] ;>32mb ;AN000;
575 MOV CX,[BX.ABS_RW_COUNT] ;>32mb ;AN000;
576 LDS BX,[BX.BUFFER_ADDR] ;>32mb ;AN000;
577 old_style: ;>32mb ;AN000;
578 CLC ;>32mb ;AN000;
579 return ;>32mb ;AN000;
580 EndProc RW32_CONVERT
581
582
583 ;Input: None
584 ;Functions: Purge Fastopen/seek Cache Buffers
585 ;Output: None
586 ;
587 ;
588 Procedure Fastxxx_Purge,NEAR
589 ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
590 PUSH AX ; save regs. ;AN000;
591 PUSH SI ;AN000;
592 PUSH DX ;AN000;
593 TEST FastSeekflg,Fast_yes ; fastseek installed ? ;AN000;
594 JZ topen ; no ;AN000;
595 MOV AH,FastSeek_ID ; set fastseek id ;AN000;
596 JMP SHORT dofast ; ;AN000;
597 topen:
598 TEST FastOpenflg,Fast_yes ; fastopen installed ? ;AN000;
599 JZ nofast ; no ;AN000;
600 MOV AH,FastOpen_ID ; set fastseek installed ;AN000;
601 dofast:
602 MOV AL,FONC_purge ; purge ;AN000;
603 MOV DL,ES:[BP.dpb_drive] ; set up drive number ;AN000;
604 invoke Fast_Dispatch ; call fastopen/seek ;AN000;
605 nofast:
606 POP DX ;AN000;
607 POP SI ; restore regs ;AN000;
608 POP AX ; ;AN000;
609
610 return ; exit ;AN000;
611 EndProc Fastxxx_Purge
612
613 CODE ENDS
614 \1a