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

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / MISC.ASM
1 ; SCCSID = @(#)misc.asm 1.1 85/04/10
2 TITLE MISC - Miscellanious routines for MS-DOS
3 NAME MISC
4 ;
5 ; Miscellaneous system calls most of which are CAVEAT
6 ;
7 ; $SLEAZEFUNC
8 ; $SLEAZEFUNCDL
9 ; $GET_INDOS_FLAG
10 ; $GET_IN_VARS
11 ; $GET_DEFAULT_DPB
12 ; $GET_DPB
13 ; $DISK_RESET
14 ; $SETDPB
15 ; $Dup_PDB
16 ; $CREATE_PROCESS_DATA_BLOCK
17 ; SETMEM
18 ; FETCHI_CHECK
19 ; $GSetMediaID
20 ;
21 ; Revision history:
22 ;
23 ; Created: ARR 30 March 1983
24 ;
25 ; A000 version 4.00 Jan. 1988
26 ; A001 D490 -- Change IOCTL subfunctions from 63h, 43h to 66h , 46h
27
28 .xlist
29 ;
30 ; get the appropriate segment definitions
31 ;
32 include dosseg.asm
33
34 CODE SEGMENT BYTE PUBLIC 'CODE'
35 ASSUME SS:DOSGROUP,CS:DOSGROUP
36
37 .xcref
38 INCLUDE DOSSYM.INC
39 INCLUDE DEVSYM.INC
40 .cref
41 .list
42
43 ENTRYPOINTSEG EQU 0CH
44 MAXDIF EQU 0FFFH
45 SAVEXIT EQU 10
46
47 i_need LASTBUFFER,DWORD
48 i_need BuffHead,DWORD
49 i_need INDOS,BYTE
50 i_need SYSINITVAR,BYTE
51 i_need CurrentPDB,WORD
52 i_need CreatePDB,BYTE
53 i_need FATBYTE,BYTE
54 i_need THISCDS,DWORD
55 i_need THISSFT,DWORD
56 i_need FETCHI_TAG,WORD ; for TAG CHECK
57 i_need BUF_HASH_COUNT,WORD ;AN000; number of Hash Entries
58 i_need HIGH_SECTOR,WORD ;AN000; high word of sector #
59 i_need DOS34_FLAG,WORD ;AN000;
60 if debug
61 I_need BugLev,WORD
62 I_need BugTyp,WORD
63 include bugtyp.asm
64 endif
65
66 BREAK <SleazeFunc -- get a pointer to media byte>
67
68 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
69 ; C A V E A T P R O G R A M M E R ;
70 ; ;
71 ; Inputs:
72 ; None
73 ; Function:
74 ; Return Stuff sort of like old get fat call
75 ; Outputs:
76 ; DS:BX = Points to FAT ID byte (IBM only)
77 ; GOD help anyone who tries to do ANYTHING except
78 ; READ this ONE byte.
79 ; DX = Total Number of allocation units on disk
80 ; CX = Sector size
81 ; AL = Sectors per allocation unit
82 ; = -1 if bad drive specified
83
84 procedure $SLEAZEFUNC,NEAR
85 ASSUME DS:NOTHING,ES:NOTHING
86
87 MOV DL,0
88
89 entry $SLEAZEFUNCDL
90 ;Same as above except drive passed in DL (0=default, 1=A, 2=B, ...)
91
92 context DS
93 MOV AL,DL
94 invoke GETTHISDRV ; Get CDS structure
95 SET_AL_RET:
96 ; MOV AL,error_invalid_drive ; Assume error ;AC000;
97 JC BADSLDRIVE
98 invoke DISK_INFO
99 JC SET_AL_RET ; User FAILed to I 24
100 MOV [FATBYTE],AH
101 ; NOTE THAT A FIXED MEMORY CELL IS USED --> THIS CALL IS NOT
102 ; RE-ENTRANT. USERS BETTER GET THE ID BYTE BEFORE THEY MAKE THE
103 ; CALL AGAIN
104 MOV DI,OFFSET DOSGROUP:FATBYTE
105 XOR AH,AH ; AL has sectors/cluster
106 invoke get_user_stack
107 ASSUME DS:NOTHING
108 MOV [SI.user_CX],CX
109 MOV [SI.user_DX],BX
110 MOV [SI.user_BX],DI
111 MOV [SI.user_DS],CS ; stash correct pointer
112 return
113 BADSLDRIVE:
114 transfer FCB_Ret_ERR
115 EndProc $SLEAZEFUNC
116 ; ;
117 ; C A V E A T P R O G R A M M E R ;
118 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
119
120 BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
121 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
122 ; C A V E A T P R O G R A M M E R ;
123 ; ;
124 ; Inputs:
125 ; None
126 ; Function:
127 ; Returns location of DOS status for interrupt routines
128 ; Returns:
129 ; Flag location in ES:BX
130
131 procedure $GET_INDOS_FLAG,NEAR
132 ASSUME DS:NOTHING,ES:NOTHING
133
134 invoke get_user_stack
135 MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
136 MOV [SI.user_ES],SS
137 return
138 EndProc $GET_INDOS_FLAG
139 ; ;
140 ; C A V E A T P R O G R A M M E R ;
141 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
142
143 BREAK <$Get_IN_VARS -- Return a pointer to DOS variables>
144 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
145 ; C A V E A T P R O G R A M M E R ;
146 ; ;
147 ; Return a pointer to interesting DOS variables This call is version
148 ; dependent and is subject to change without notice in future versions.
149 ; Use at risk.
150 procedure $GET_IN_VARS,NEAR
151 invoke get_user_stack
152 MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
153 MOV [SI.user_ES],SS
154 return
155 EndProc $GET_IN_VARS
156 ; ;
157 ; C A V E A T P R O G R A M M E R ;
158 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
159
160
161 BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
162 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
163 ; C A V E A T P R O G R A M M E R ;
164 ; ;
165 ; Inputs:
166 ; None
167 ; Function:
168 ; Return pointer to drive parameter table for default drive
169 ; Returns:
170 ; DS:BX points to the DPB
171 ; AL = 0 If OK, = -1 if bad drive (call 50 only)
172
173 procedure $GET_DEFAULT_DPB,NEAR
174 ASSUME DS:NOTHING,ES:NOTHING
175
176 MOV DL,0
177
178 entry $GET_DPB
179 ; Same as above only drive passed in DL (0=default, 1=A, 2=B, ...)
180
181 context DS
182 MOV AL,DL
183 invoke GETTHISDRV ; Get CDS structure
184 JC ISNODRV ; no valid drive
185 LES DI,[THISCDS] ; check for net CDS
186 TEST ES:[DI.curdir_flags],curdir_isnet
187 JNZ ISNODRV ; No DPB to point at on NET stuff
188 EnterCrit CritDisk
189 invoke FATRead_CDS ; Force Media Check and return DPB
190 LeaveCrit CritDisk
191 JC ISNODRV ; User FAILed to I 24, only error we
192 ; have.
193 invoke get_user_stack
194 ASSUME DS:NOTHING
195 MOV [SI.user_BX],BP
196 MOV [SI.user_DS],ES
197 XOR AL,AL
198 return
199
200 ISNODRV:
201 MOV AL,-1
202 return
203 EndProc $GET_Default_dpb
204 ; ;
205 ; C A V E A T P R O G R A M M E R ;
206 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
207
208
209 BREAK <$Disk_Reset -- Flush out all dirty buffers>
210
211 procedure $DISK_RESET,NEAR
212 ASSUME DS:NOTHING,ES:NOTHING
213
214 ; Inputs:
215 ; None
216 ; Function:
217 ; Flush and invalidate all buffers
218 ; Returns:
219 ; Nothing
220
221 MOV AL,-1
222 entry $DISK_RESET2
223 context DS
224 EnterCrit critDisk
225 OR [DOS34_FLAG],FROM_DISK_RESET ;AN000;
226 invoke FLUSHBUF
227 AND [DOS34_FLAG],NO_FROM_DISK_RESET ;AN000;
228 ;
229 ; We will "ignore" any errors on the flush, and go ahead and invalidate. This
230 ; call doesn't return any errors and it is supposed to FORCE a known state, so
231 ; let's do it.
232 ;
233 ; Invalidate 'last-buffer' used
234 ;
235 MOV BX,-1
236 MOV WORD PTR [LASTBUFFER+2],BX
237 MOV WORD PTR [LASTBUFFER],BX
238 ;
239 ; TEST [DOS34_FLAG],IFS_DRIVE_RESET ;AN000;;IFS. from ifs call back ?
240 ; JZ FreeDone ;AN000;;IFS. no
241 ; AND [DOS34_FLAG],NO_IFS_DRIVE_RESET ;AN000;;IFS. clear the flag
242 ; LeaveCrit critDisk ;AN000;;IFS.
243 ; return ;AN000;;IFS. return
244 FreeDone:
245 LeaveCrit critDisk
246 MOV AX,-1
247 CallInstall NetFlushBuf,multNET,32
248 return
249 EndProc $DISK_RESET
250
251 BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
252 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
253 ; C A V E A T P R O G R A M M E R ;
254 ; ;
255 procedure $SETDPB,NEAR
256 ASSUME DS:NOTHING,ES:NOTHING
257
258 ; Inputs:
259 ; ES:BP Points to DPB
260 ; DS:SI Points to BPB
261 ; Function:
262 ; Build a correct DPB from the BPB
263 ; Outputs:
264 ; ES:BP and DS preserved all others destroyed
265
266 MOV DI,BP
267 ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
268 LODSW
269 STOSW ; dpb_sector_size
270 CMP BYTE PTR [SI.BPFTCNT-2],0 ; FAT file system drive ;AN000;
271 JNZ yesfat ; yes ;AN000;
272 MOV BYTE PTR ES:[DI.dpb_FAT_count-4],0
273 JMP setend ; NO ;AN000;
274 yesfat:
275 MOV DX,AX
276 LODSB
277 DEC AL
278 STOSB ; dpb_cluster_mask
279 INC AL
280 XOR AH,AH
281 LOG2LOOP:
282 TEST AL,1
283 JNZ SAVLOG
284 INC AH
285 SHR AL,1
286 JMP SHORT LOG2LOOP
287 SAVLOG:
288 MOV AL,AH
289 STOSB ; dpb_cluster_shift
290 MOV BL,AL
291 MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
292 LODSB
293 STOSB ; dpb_FAT_count Number of FATs
294 ; OR AL,AL ; NONFAT ? ;AN000;
295 ; JZ setend ; yes, don't do anything ;AN000;
296 MOV BH,AL
297 LODSW
298 STOSW ; dpb_root_entries Number of directory entries
299 MOV CL,5
300 SHR DX,CL ; Directory entries per sector
301 DEC AX
302 ADD AX,DX ; Cause Round Up
303 MOV CX,DX
304 XOR DX,DX
305 DIV CX
306 MOV CX,AX ; Number of directory sectors
307 INC DI
308 INC DI ; Skip dpb_first_sector
309 MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
310 LODSB
311 MOV ES:[BP.dpb_media],AL ; Media byte
312 LODSW ; Number of sectors in a FAT
313 STOSW ;AC000;;>32mb dpb_FAT_size
314 MOV DL,BH ;AN000;;>32mb
315 XOR DH,DH ;AN000;;>32mb
316 MUL DX ;AC000;;>32mb Space occupied by all FATs
317 ADD AX,ES:[BP.dpb_first_FAT]
318 STOSW ; dpb_dir_sector
319 ADD AX,CX ; Add number of directory sectors
320 MOV ES:[BP.dpb_first_sector],AX
321
322 MOV CL,BL ;F.C. >32mb ;AN000;
323 CMP WORD PTR ES:[BP.DSKSIZ],0 ;F.C. >32mb ;AN000;
324 JNZ normal_dpb ;F.C. >32mb ;AN000;
325 XOR CH,CH ;F.C. >32mb ;AN000;
326 MOV BX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack] ;AN000;
327 MOV DX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack+2] ;AN000;
328 SUB BX,AX ;AN000;;F.C. >32mb
329 SBB DX,0 ;AN000;;F.C. >32mb
330 OR CX,CX ;AN000;;F.C. >32mb
331 JZ norot ;AN000;;F.C. >32mb
332 rott: ;AN000;;F.C. >32mb
333 CLC ;AN000;;F.C. >32mb
334 RCR DX,1 ;AN000;;F.C. >32mb
335 RCR BX,1 ;AN000;;F.C. >32mb
336 LOOP rott ;AN000;;F.C. >32mb
337 norot: ;AN000;
338 MOV AX,BX ;AN000;;F.C. >32mb
339 JMP setend ;AN000;;F.C. >32mb
340 normal_dpb:
341 SUB AX,ES:[BP.DSKSIZ]
342 NEG AX ; Sectors in data area
343 ;; MOV CL,BL ; dpb_cluster_shift
344 SHR AX,CL ; Div by sectors/cluster
345 setend:
346 INC AX
347 MOV ES:[BP.dpb_max_cluster],AX
348 MOV ES:[BP.dpb_next_free],0 ; Init so first ALLOC starts at
349 ; begining of FAT
350 MOV ES:[BP.dpb_free_cnt],-1 ; current count is invalid.
351 return
352 EndProc $SETDPB
353 ; ;
354 ; C A V E A T P R O G R A M M E R ;
355 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
356
357 BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
358 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
359 ; C A V E A T P R O G R A M M E R ;
360 ; ;
361 ;
362 ; Inputs: DX is new segment address of process
363 ; SI is end of new allocation block
364 ;
365 procedure $Dup_PDB,NEAR
366 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
367 MOV CreatePDB,0FFH ; indicate a new process
368 MOV DS,CurrentPDB
369 PUSH SI
370 JMP SHORT CreateCopy
371 EndProc $Dup_PDB
372
373 procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
374 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
375
376 ; Inputs:
377 ; DX = Segment number of new base
378 ; Function:
379 ; Set up program base and copy term and ^C from int area
380 ; Returns:
381 ; None
382 ; Called at DOS init
383
384 CALL get_user_stack
385 MOV DS,[SI.user_CS]
386 PUSH DS:[PDB_Block_len]
387 CreateCopy:
388 MOV ES,DX
389 XOR SI,SI ; copy all 80h bytes
390 MOV DI,SI
391 MOV CX,80H
392 REP MOVSW
393 ; DOS 3.3 7/9/86
394
395 MOV CX,FilPerProc ; copy handles in case of
396 MOV DI,PDB_JFN_Table ; Set Handle Count has been issued
397 PUSH DS
398 LDS SI,DS:[PDB_JFN_Pointer]
399 REP MOVSB
400 POP DS
401
402 ; DOS 3.3 7/9/86
403 TEST CreatePDB,0FFh ; Shall we create a process?
404 JZ Create_PDB_cont ; nope, old style call
405 ;
406 ; Here we set up for a new process...
407 ;
408
409 PUSH CS ; Called at DOSINIT time, NO SS
410 POP DS
411 DOSAssume CS,<DS>,"MISC/Create_Copy"
412 XOR BX,BX ; dup all jfns
413 MOV CX,FilPerProc ; only 20 of them
414
415 Create_dup_jfn:
416 PUSH ES ; save new PDB
417 invoke SFFromHandle ; get sf pointer
418 MOV AL,-1 ; unassigned JFN
419 JC CreateStash ; file was not really open
420 TEST ES:[DI].sf_flags,sf_no_inherit
421 JNZ CreateStash ; if no-inherit bit is set, skip dup.
422 ;
423 ; We do not inherit network file handles.
424 ;
425 MOV AH,BYTE PTR ES:[DI].sf_mode
426 AND AH,sharing_mask
427 CMP AH,sharing_net_fcb
428 jz CreateStash
429 ;
430 ; The handle we have found is duplicatable (and inheritable). Perform
431 ; duplication operation.
432 ;
433 MOV WORD PTR [THISSFT],DI
434 MOV WORD PTR [THISSFT+2],ES
435 invoke DOS_DUP ; signal duplication
436 ;
437 ; get the old sfn for copy
438 ;
439 invoke pJFNFromHandle ; ES:DI is jfn
440 MOV AL,ES:[DI] ; get sfn
441 ;
442 ; Take AL (old sfn or -1) and stash it into the new position
443 ;
444 CreateStash:
445 POP ES
446 MOV ES:[BX].PDB_JFN_Table,AL; copy into new place!
447 INC BX ; next jfn...
448 LOOP create_dup_jfn
449
450 MOV BX,CurrentPDB ; get current process
451 MOV ES:[PDB_Parent_PID],BX ; stash in child
452 MOV [CurrentPDB],ES
453 ASSUME DS:NOTHING
454 MOV DS,BX
455 ;
456 ; end of new process create
457 ;
458 Create_PDB_cont:
459 MOV BYTE PTR [CreatePDB],0h ; reset flag
460 POP AX
461
462 entry SETMEM
463 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
464
465 ; Inputs:
466 ; AX = Size of memory in paragraphs
467 ; DX = Segment
468 ; Function:
469 ; Completely prepares a program base at the
470 ; specified segment.
471 ; Called at DOS init
472 ; Outputs:
473 ; DS = DX
474 ; ES = DX
475 ; [0] has INT int_abort
476 ; [2] = First unavailable segment
477 ; [5] to [9] form a long call to the entry point
478 ; [10] to [13] have exit address (from int_terminate)
479 ; [14] to [17] have ctrl-C exit address (from int_ctrl_c)
480 ; [18] to [21] have fatal error address (from int_fatal_abort)
481 ; DX,BP unchanged. All other registers destroyed.
482
483 XOR CX,CX
484 MOV DS,CX
485 MOV ES,DX
486 MOV SI,addr_int_terminate
487 MOV DI,SAVEXIT
488 MOV CX,6
489 REP MOVSW
490 MOV ES:[2],AX
491 SUB AX,DX
492 CMP AX,MAXDIF
493 JBE HAVDIF
494 MOV AX,MAXDIF
495 HAVDIF:
496 SUB AX,10H ; Allow for 100h byte "stack"
497 MOV BX,ENTRYPOINTSEG ; in .COM files
498 SUB BX,AX
499 MOV CL,4
500 SHL AX,CL
501 MOV DS,DX
502 MOV WORD PTR DS:[PDB_CPM_Call+1],AX
503 MOV WORD PTR DS:[PDB_CPM_Call+3],BX
504 MOV DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT
505 MOV BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL
506 MOV WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT
507 MOV BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET
508 MOV WORD PTR DS:[PDB_JFN_Pointer],PDB_JFN_Table
509 MOV WORD PTR DS:[PDB_JFN_Pointer+2],DS
510 MOV WORD PTR DS:[PDB_JFN_Length],FilPerProc
511 ;
512 ; The server runs several PDB's without creating them VIA EXEC. We need to
513 ; enumerate all PDB's at CPS time in order to find all references to a
514 ; particular SFT. We perform this by requiring that the server link together
515 ; for us all sub-PDB's that he creates. The requirement for us, now, is to
516 ; initialize this pointer.
517 ;
518 MOV word ptr DS:[PDB_Next_PDB],-1
519 MOV word ptr DS:[PDB_Next_PDB+2],-1
520 return
521
522 EndProc $CREATE_PROCESS_DATA_BLOCK
523
524 ; ;
525 ; C A V E A T P R O G R A M M E R ;
526 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
527 procedure FETCHI_CHECK,NEAR
528 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
529 PUSHF
530 CMP CS:[FETCHI_TAG],22642
531 JZ TAG_OK
532 invoke DOSINIT ; go to hell
533 TAG_OK:
534 POPF
535 return
536 EndProc FETCHI_CHECK
537
538 BREAK <$GSetMediaID -- get set media ID>
539 ; Inputs:
540 ; BL= drive number as defined in IOCTL
541 ; AL= 0 get media ID
542 ; 1 set media ID
543 ; DS:DX= buffer containing information
544 ; DW 0 info level (set on input)
545 ; DD ? serial #
546 ; DB 11 dup(?) volume id
547 ; DB 8 dup(?) file system type
548 ; Function:
549 ; Get or set media ID
550 ; Returns:
551 ; carry clear, DS:DX is filled
552 ; carry set, error
553
554 procedure $GSetMediaID,NEAR ;AN000;
555 ASSUME DS:NOTHING,ES:NOTHING ;AN000;
556
557 MOV CX,0866H ;AN000;MS.; assume get for IOCTL
558 CMP AL,0 ;AN001;MS.; get ?
559 JZ doioctl ;AN000;MS.; yes
560 CMP AL,1 ;AN000;MS.; set ?
561 JNZ errorfunc ;AN000;MS.; no
562 MOV CX,0846H ;AN001;MS.;
563 doioctl: ;AN000;
564 MOV AL,0DH ;AN000;MS.; generic IOCTL
565 invoke $IOCTL ;AN000;MS.; let IOCTL take care of it
566 return ;AN000;MS.;
567 errorfunc: ;AN000;
568 error error_invalid_function;AN000;MS. ; invalid function
569 EndProc $GSetMediaID ;AN000;
570
571 CODE ENDS
572 END