summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/MISC.ASM
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--v4.0/src/DOS/MISC.ASM572
1 files changed, 572 insertions, 0 deletions
diff --git a/v4.0/src/DOS/MISC.ASM b/v4.0/src/DOS/MISC.ASM
new file mode 100644
index 0000000..e169f32
--- /dev/null
+++ b/v4.0/src/DOS/MISC.ASM
@@ -0,0 +1,572 @@
1; SCCSID = @(#)misc.asm 1.1 85/04/10
2TITLE MISC - Miscellanious routines for MS-DOS
3NAME 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;
32include dosseg.asm
33
34CODE SEGMENT BYTE PUBLIC 'CODE'
35 ASSUME SS:DOSGROUP,CS:DOSGROUP
36
37.xcref
38INCLUDE DOSSYM.INC
39INCLUDE DEVSYM.INC
40.cref
41.list
42
43ENTRYPOINTSEG EQU 0CH
44MAXDIF EQU 0FFFH
45SAVEXIT 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;
60if debug
61 I_need BugLev,WORD
62 I_need BugTyp,WORD
63include bugtyp.asm
64endif
65
66BREAK <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
85ASSUME DS:NOTHING,ES:NOTHING
86
87 MOV DL,0
88
89entry $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
95SET_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
107ASSUME 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
113BADSLDRIVE:
114 transfer FCB_Ret_ERR
115EndProc $SLEAZEFUNC
116; ;
117; C A V E A T P R O G R A M M E R ;
118;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
119
120BREAK <$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
132ASSUME 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
138EndProc $GET_INDOS_FLAG
139; ;
140; C A V E A T P R O G R A M M E R ;
141;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
142
143BREAK <$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
155EndProc $GET_IN_VARS
156; ;
157; C A V E A T P R O G R A M M E R ;
158;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
159
160
161BREAK <$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
174ASSUME 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
194ASSUME DS:NOTHING
195 MOV [SI.user_BX],BP
196 MOV [SI.user_DS],ES
197 XOR AL,AL
198 return
199
200ISNODRV:
201 MOV AL,-1
202 return
203EndProc $GET_Default_dpb
204; ;
205; C A V E A T P R O G R A M M E R ;
206;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
207
208
209BREAK <$Disk_Reset -- Flush out all dirty buffers>
210
211 procedure $DISK_RESET,NEAR
212ASSUME 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
244FreeDone:
245 LeaveCrit critDisk
246 MOV AX,-1
247 CallInstall NetFlushBuf,multNET,32
248 return
249EndProc $DISK_RESET
250
251BREAK <$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
256ASSUME 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;
274yesfat:
275 MOV DX,AX
276 LODSB
277 DEC AL
278 STOSB ; dpb_cluster_mask
279 INC AL
280 XOR AH,AH
281LOG2LOOP:
282 TEST AL,1
283 JNZ SAVLOG
284 INC AH
285 SHR AL,1
286 JMP SHORT LOG2LOOP
287SAVLOG:
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
332rott: ;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
337norot: ;AN000;
338 MOV AX,BX ;AN000;;F.C. >32mb
339 JMP setend ;AN000;;F.C. >32mb
340normal_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
345setend:
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
352EndProc $SETDPB
353; ;
354; C A V E A T P R O G R A M M E R ;
355;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
356
357BREAK <$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
366ASSUME 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
371EndProc $Dup_PDB
372
373 procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
374ASSUME 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]
387CreateCopy:
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
415Create_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;
444CreateStash:
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;
458Create_PDB_cont:
459 MOV BYTE PTR [CreatePDB],0h ; reset flag
460 POP AX
461
462 entry SETMEM
463ASSUME 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
495HAVDIF:
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
522EndProc $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
528ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
529 PUSHF
530 CMP CS:[FETCHI_TAG],22642
531 JZ TAG_OK
532 invoke DOSINIT ; go to hell
533TAG_OK:
534 POPF
535 return
536EndProc FETCHI_CHECK
537
538BREAK <$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;
555ASSUME 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.;
563doioctl: ;AN000;
564 MOV AL,0DH ;AN000;MS.; generic IOCTL
565 invoke $IOCTL ;AN000;MS.; let IOCTL take care of it
566 return ;AN000;MS.;
567errorfunc: ;AN000;
568 error error_invalid_function;AN000;MS. ; invalid function
569EndProc $GSetMediaID ;AN000;
570
571CODE ENDS
572END