summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM')
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM2052
1 files changed, 2052 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM
new file mode 100644
index 0000000..5594abd
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM
@@ -0,0 +1,2052 @@
1 Page 84,132 ;
2Title FASTOPEN
3;Date: May 13,1988
4;==============================================================================
5; EQUATES
6;==============================================================================
7Is_drive_head EQU 00000001b ;AN000;
8Is_delete EQU 00000010b ;AN000;
9Is_insert EQU 00000100b ;AN000;
10Not_drive_head EQU 11111110b ;AN000;
11Not_delete EQU 11111101b ;AN000;
12Not_insert EQU 11111011b
13
14EMS_SAVE_STATE EQU 4FH ;AN000;
15EMS_RESTORE_STATE EQU 4FH ;AN000;
16EMS_INT EQU 67H ;AN000;
17DOS_PAGE1 EQU 0FEH ;AN000;
18
19
20;==============================================================================
21; INCLUDE FILES
22;==============================================================================
23.xcref
24.xlist
25debug=0 ; an equate only for DOSMAC.inc ;AN000;
26INCLUDE DOSMAC.inc ;AN000;
27.list
28.cref
29INCLUDE dirent.inc ;AN000;
30INCLUDE fastsegs.inc ; this cannot include in Fastopen.inc
31INCLUDE fastopen.inc ; this include file also contains DOS equates ;AN000;
32include version.inc
33
34;==============================================================================
35
36
37
38EXTRN FK_OPEN:FAR ;AN000;
39EXTRN FK_CLOSE:FAR ;AN000;
40EXTRN FK_INSERT:FAR ;AN000;
41EXTRN FK_DELETE:FAR ;AN000;
42EXTRN FK_LOOKUP:FAR ;AN000;
43EXTRN FK_TRUNCATE:FAR ;AN000;
44EXTRN FK_PURGE:FAR ;AN000;
45
46
47;============================================================================
48
49CSEG_MAIN SEGMENT PARA PUBLIC 'code'
50 ASSUME cs:cseg_main, ds:nothing,es:nothing,ss:nothing
51;============================================================================
52
53PUBLIC MAIN ;AN000;
54
55IF BUFFERFLAG
56PUBLIC SAVE_EMS_PAGE_STATE
57PUBLIC EMS_PAGE_NUMBER
58ENDIF
59
60PUBLIC RESTORE_PAGE_STATE
61PUBLIC EMS_SAVE_HANDLE1
62
63PUBLIC Main_name_cache_seg ;AN000;
64PUBLIC Main_Num_Of_drives ;AN000;
65PUBLIC Main_Ext_Count ;AN000;
66PUBLIC Main_extent_drive_Buff ;AN000;
67PUBLIC Main_ext_cache_size ;AN000;
68PUBLIC Main_name_cache_Buff ;AN000;
69PUBLIC Main_EMS_FLAG ;AN000;
70PUBLIC Main_Res_Segs ;AN000;
71PUBLIC Main_EMS_PAGE_SIZE ;AN000;
72PUBLIC Main_EMS_PAGE_SEG ;AN000;
73PUBLIC Main_Total_Ext_Count ;AN000;
74PUBLIC Main_Total_Name_Count ;AN000;
75PUBLIC Main_Name_Drive_Buff ;AN000;
76PUBLIC Main_ParamBuff ;AN000;
77
78PUBLIC FOPEN_Insert ;AN000;
79PUBLIC FOPEN_Update ;AN000;
80PUBLIC FOPEN_Delete ;AN000;
81PUBLIC FOPEN_Lookup ;AN000;
82PUBLIC FOPEN_PURGE ;AN000;
83
84PUBLIC FSEEK_Open ;AN000;
85PUBLIC FSEEK_Close ;AN000;
86PUBLIC FSEEK_Insert ;AN000;
87PUBLIC FSEEK_Delete ;AN000;
88PUBLIC FSEEK_Lookup ;AN000;
89PUBLIC FSEEK_Truncate ;AN000;
90PUBLIC FSEEK_Purge ;AN000;
91
92PUBLIC VECTOR_LookUp ;AN000;
93PUBLIC VECTOR_Delete ;AN000;
94
95
96; Following data variables are accessed by all other segments
97call_cnt DW 0 ;AN000;
98Purge_Flag DW 0 ; =1 if last call is PURGE function
99Prev_drv_id DB -1 ; previous request drive id
100Main_name_cache_seg DW Cseg_Init ; default to Init1 seg ;AN000;
101Main_Num_Of_drives DW 0 ; number of drives ;AN000;
102Main_Ext_Count DW 0 ; total name extent entries ;AN000;
103Main_extent_drive_Buff DW 0 ; addrs to extent drive ;AN000;
104Main_name_cache_Buff DW 0 ; address of Name cache buffer ;AN000;
105Main_ext_cache_size DW 0 ; extent cache size
106Main_EMS_FLAG DW 0 ; EMI flag 1= if EMI is enabled ;AN000;
107Main_Res_Segs DW 0 ; number of segs to be stay resident ;AN000;
108Main_Total_Ext_Count DW 0 ; Total extent count entries ;AN000;
109Main_Total_Name_Count DW 0 ; Total name count entries ;AN000;
110Main_Name_Drive_Buff DW 0 ; EMS data page segment ID ;AN000;
111Main_ParamBuff DW 50 dup (0) ; Drive ID/extent count buffer ;AN000;
112
113; The following structure is for saving and restoring EMS page state
114EMS_PAGE_MAP LABEL WORD
115Main_EMS_SEG_COUNT DW 1 ; EMS segment count
116Main_EMS_PAGE_SEG DW 0 ; EMS page segment ID ;AN000;
117
118
119Main_EMS_PAGE_SIZE DW 0 ; EMS page size ;AN000;
120EMS_PAGE_ARRAY DW 30 dup (0) ; EMS state save array
121
122; The following data values are used by MAIN segment
123EMS_SAVE_LOG_PAGE1 DW ? ;HOLDS PREVIOUS PAGE1 ;AN000;
124EMS_SAVE_HANDLE1 DW ? ;HOLDS PREVIOUS handle1 ;AN000;
125
126IF BUFFERFLAG
127;----------------------------------------------------------HKN 8/26/88
128
129EMS_PAGE_NUMBER DW ? ; holds the ems
130 ; physical page no.
131
132ENDIF
133;
134;-----------------------------------------------------------------------------
135; Fastopen/Fastseek function jump vectors
136; Inititally the jump vectors have default offset and segment values.
137; If the modules are relocated, the offset and the segID in the jump vectors
138; may be changed to the new segID of the new location.
139;-----------------------------------------------------------------------------
140FOPEN_Insert DD Insert ;AN000;
141FOPEN_Update DD Update ;AN000;
142FOPEN_Delete DD delete ;AN000;
143FOPEN_Lookup DD lookup ;AN000;
144FOPEN_Purge DD FP_purge ;AN000;
145
146FSEEK_Open DD Fk_Open ;AN000;
147FSEEK_Close DD Fk_Close ;AN000;
148FSEEK_Insert DD Fk_Insert ;AN000;
149FSEEK_Delete DD Fk_Delete ;AN000;
150FSEEK_Lookup DD Fk_Lookup ;AN000;
151FSEEK_Truncate DD Fk_Truncate ;AN000;
152FSEEK_Purge DD Fk_Purge ;AN000;
153
154VECTOR_LookUp DD LookUp ; jump vector to LookUp used by Insert call
155VECTOR_Delete DD Fk_Delete ; jump vector to Delete used by Free_buffer routine
156
157
158
159
160
161;==============================================================================
162
163MAIN PROC FAR ; FAR procedure for FAR call from DOS
164 push cx ; save DOS registers ;AN000;
165 push dx ; makesure to restore the necessary ;AN000;
166 push ds ; ones on return ;AN000;
167 push es ;AN000;
168 push bp ;AN000;
169 push di ;AN000;
170 push bx ;AN000;
171
172;-----------------------------------------------------------------------------
173; The cache buffers are maintained in a seperate segement whose segment ID is
174; in Name_Cache_Seg. The ES will be used as the seg register during the access
175; of data in the cache buffers, while DS will be used to access the Fastopen
176; resident and non-resident data area.
177;-----------------------------------------------------------------------------
178 cmp cs:Main_EMS_flag,1 ; EMS enabled ?? ;AN000;
179 jne dispatch_funcs ; no - dispatch functions ;AN000;
180 ; yes - save EMS page state
181IF NOT BUFFERFLAG
182
183;-----------------------------------------------------------------------------
184; SAVE EMS PAGE STATE
185;-----------------------------------------------------------------------------
186 PUSH AX ; save registers
187 PUSH CX
188 PUSH DX ;AN000;
189 PUSH DS ;AN000;
190 PUSH ES ;AN000;
191 PUSH BP ;AN000;
192 PUSH SI ;AN000;
193 PUSH DI ;AN000;
194 PUSH BX ;AN000;
195 MOV AX, SEG EMS_PAGE_MAP ; get segid
196 MOV DS,AX
197 LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc
198 MOV AX, SEG EMS_PAGE_ARRAY ; get segid
199 MOV ES,AX
200 LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY
201 MOV AH,EMS_SAVE_STATE ;
202 MOV AL,0 ; subfunction code
203 INT EMS_INT ; save page state ;AN000;
204
205 POP BX ;AN000;
206 POP DI ;AN000;
207 POP SI ;AN000;
208 POP BP ;AN000;
209 POP ES ;AN000;
210 POP DS ;AN000;
211 POP DX ;AN000;
212 POP CX ;AN000;
213
214 CMP AH,0 ; save ok??
215 JNE SAVE_FAILED ; no, error
216 POP AX ; clear stack
217
218ELSE
219
220
221;------------------------------------------------------------HKN 8/26/88--
222; Before dispatching off the fastopen functions we must do the
223; following:
224; 1. save the map for this page
225; 2. map this page to log. page 0 with the fastopen handle in
226; ems_save_handle1.
227; 3. dispatch
228;
229
230; int 3
231
232 push ax
233 push cx
234 push dx
235 push ds
236 push es
237 push bp
238 push si
239 push di
240 push bx
241
242 call far ptr save_ems_page_state
243 jc ems_failed
244
245 call map_page
246 jc ems_failed
247
248 pop bx
249 pop di
250 pop si
251 pop bp
252 pop es
253 pop ds
254 pop dx
255 pop cx
256 POP AX ; restore registers
257
258 JMP DISPATCH_FUNCS ; yes, dispatch functions
259
260EMS_FAILED:
261 pop bx
262 pop di
263 pop si
264 pop bp
265 pop es
266 pop ds
267 pop dx
268 pop cx
269
270ENDIF
271
272IF NOT BUFFERFLAG
273SAVE_FAILED:
274ENDIF
275
276 POP AX ; restore registers
277
278 POP BX ; no, restore DOS registers ;AN000;
279 POP DI ;AN000;
280 POP BP ;AN000;
281 POP ES ;AN000;
282 POP DS ;AN000;
283 POP DX ;AN000;
284 POP CX ;AN000;
285 STC
286 JMP ERROR_RET ; error return
287
288
289;-----------------------------------------------------------------------------
290; FASTOPEN/FASTSEEK DISPATCHER
291;-----------------------------------------------------------------------------
292DISPATCH_FUNCS:
293 cmp al,5 ; buffer purge ??
294 je Check_Drive_id ; yes - check drive id
295 cmp al,11 ; Fastopen function call ?? ;AN000;
296 jge Check_drive_id ; no - dispatch Fastseek functions
297 jmp Dispatch_fopen ; yes - dispatch Fastopen functions ;AN000;
298
299
300;-----------------------------------------------------------------------------
301; Check to see the Drive ID in DL is the valid. If not error and return DI=1
302; if Fastseek LookUp function. Makesure to preserve AL, DS, SI and DI
303;-----------------------------------------------------------------------------
304CHECK_DRIVE_ID:
305 cmp cs:Prev_drv_id, dl ; current id same as previous valid
306 je Dispatch_Fseek ; yes - dont check drive ID
307
308 push si ;AN000;
309 push bx ;DS=addressability to Cseg_Main ;AN000;
310 push cx ;AN000;
311 lea si,cs:Main_ParamBuff ; DS:SI-->drive ID buffer ;AN000;
312 mov cx,cs:Main_Num_Of_Drives ; number of drives ;AN000;
313
314Get_Drive_Id: ;AN000;
315 mov bx,cs:[si] ;AN000;
316 cmp bl,dl ; drive ID match ?? ;AN000;
317 je drive_found ; yes, drive ID found ;AN000;
318 add si,4 ; (2/11) no, move pointer to next ID ;AN000;
319 LOOP get_drive_id ; check next drive id ;AN000;
320
321Drive_Not_Found: ; drive id not found
322 pop cx ; restore registers ;AN000;
323 pop bx ;AN000;
324 pop si ;AN000;
325 jmp Error_Exit ; return
326
327Drive_Found: ; drive ID found
328 mov cs:Prev_drv_id,dl ; save drive id as prev drive id
329 pop cx ; restore registers ;AN000;
330 pop bx ; and do the specified function ;AN000;
331 pop si ;AN000;
332
333;-----------------------------------------------------------------------------
334; FASTSEEK FUNCTION DISPATCHER
335;-----------------------------------------------------------------------------
336DISPATCH_FSEEK:
337 cmp al,010H
338 jle Fsk_Cont
339 inc cs:call_cnt ;AN000;
340; cmp cs:call_cnt,0efffH ; for debugging
341; jne fsk_cont ; for debugging
342
343
344Fsk_Cont:
345 push cs ; set addressability
346 pop ds ; CS = DS = Cseg_Main segment
347 ASSUME ds:Cseg_Main
348 cmp al,FONC_Purge ; PURGE call ?? ;AN000;
349 je chk_05 ; yes - continue ;AN000;
350
351 mov cs:Purge_Flag, 0 ; reset purge flag
352 cmp al,FSK_Open ; OPEN call ;AN000;
353 jne chk_12 ; jump if not ;AN000;
354 CALL FSEEK_OPEN ;AN000;
355 jmp exit ;AN000;
356Chk_12:
357 cmp al,FSK_Close ; CLOSE ?? ;AN000;
358 jne chk_14 ;AN000;
359 CALL FSEEK_CLOSE ; process close function ;AN000;
360 jmp exit ;AN000;
361Chk_14:
362 cmp al,FSK_Lookup ; LOOKUP ?? ;AN000;
363 jne chk_15 ;AN000;
364 CALL FSEEK_LOOKUP ; process lookup ;AN000;
365 CALL RESTORE_PAGE_STATE ; restore EMS page ;AN000;
366 pop dx ; dont restore original BX and DI ;AN000;
367 pop dx ; from DOS since BX and DI contins return values ;AN000;
368 jmp exit_1 ; exit
369
370Chk_15:
371 cmp al,FSK_Insert ; INSERT ?? ;AN000;
372 jne chk_13 ;AN000;
373 CALL FSEEK_INSERT ; Process insert ;AN000;
374 jmp exit ;AN000;
375Chk_13:
376 cmp al,FSK_DELETE ; DELETE ?? ;AN000;
377 jne chk_16 ;AN000;
378 CALL FSEEK_DELETE ; process delete ;AN000;
379 jmp short exit ;AN000;
380Chk_16:
381 cmp al,FSK_Trunc ; TRUNCATE ?? ;AN000;
382 jne Chk_05 ;
383 CALL FSEEK_TRUNCATE ; process truncate ;AN000;
384 jmp short exit ;AN000;
385
386Chk_05:
387 cmp cs:Purge_Flag, 1 ; previous call is purge ?? ;AN000;
388 jne Purge_buffs ; no - purge the buffers
389 clc ; yes - exit
390 jmp short exit ;AN000;
391
392Purge_Buffs:
393 mov cs:Purge_Flag,1 ; set purge flag
394 cmp CS:Main_Total_Ext_Count,0 ; reset fseek buffs??
395 je reset_fopen ; no - reset fopen
396 CALL FSEEK_PURGE ; reset extent cache ;AN000;
397
398Reset_Fopen:
399 cmp CS:Main_Total_Name_Count,0 ; reset fopen buffs??
400 je Reset_Exit ; no - reset f
401 CALL CS:FOPEN_PURGE ; reset extent cache ;AN000;
402
403Reset_Exit:
404 clc
405 jmp short exit ;AN000;
406
407
408; NOTE: Carry Flag state from Function calls must be correctly returned
409; to the DOS, especially from Fastseek Lookup function
410
411
412;-----------------------------------------------------------------------------
413; FASTOPEN FUNCTION DISPATCHER
414;-----------------------------------------------------------------------------
415DISPATCH_FOPEN: ; dispatch FOPEN functions
416 cld ;AN000;
417 mov cs:Purge_Flag, 0 ; reset purge flag
418 cmp al, FONC_update ;AN000;
419 jne Chk_02 ;AN000;
420 CALL CS:Fopen_Update ; UPDATE ;AN000;
421 jmp short exit ;AN000;
422
423Chk_02:
424 cmp al, FONC_insert ;AN000;
425 jne Chk_01 ;AN000;
426 CALL CS:Fopen_Insert ; INSERT ;AN000;
427 jmp short exit ;AN000;
428Chk_01:
429 cmp al, FONC_look_up ;AN000;
430 jne chk_03 ;AN000;
431 CALL CS:Fopen_lookup ; LOOKUP ;AN000;
432 jmp short exit ;AN000;
433Chk_03:
434 cmp al, FONC_delete ;AN000;
435 jne Error_Exit ;AN000;
436 CALL CS:Fopen_delete ; DELETE ;AN000;
437 jmp short exit ;AN000;
438
439
440
441;-----------------------------------------------------------------------------
442; EXIT TO DOS FROM FUNCTIONS
443;-----------------------------------------------------------------------------
444
445ERROR_EXIT: ; EXIT from invalid drive id search loop
446 CALL RESTORE_PAGE_STATE ; restore frame buff status ;AN000;
447 ; on return AX should have function code
448 pop bx ; restore first two regs of DOS
449 pop di ;AN000;
450 cmp al,FSK_Lookup ;AN000;
451 jne exit_2 ;AN000;
452 mov di,1 ; set error flag - invalid drive id ;AN000;
453 stc ;AN000;
454 jmp short Exit_1 ;AN000;
455
456EXIT_2:
457 clc ;AN000;
458 jmp short Exit_1 ;AN000;
459
460
461; Normal Exit from Fastopen Functions except Fastseek Lookup function
462EXIT:
463 CALL RESTORE_PAGE_STATE ; restore EMS page state ;AN000;;AN000;
464 pop bx ; restore BX ;AN000;
465 pop di ; restore DI ;AN000;
466
467
468; Exit from FastSeek Lookup function. Dont restore BX and DI
469EXIT_1:
470 pop bp ; restore remaining DOS registers
471 pop es ; except BX and DI since they contain ;AN000;
472 pop ds ; return values. ;AN000;
473 pop dx ;AN000;
474 pop cx ;AN000;
475
476ERROR_RET:
477 ret ;AN000;
478
479MAIN ENDP
480
481IF BUFFERFLAG
482;---------------------------------------------------------------------------
483; Procedure name : save_ems_page_state
484;
485; Description:
486; Saves the state of the page whose physical segment value is
487; specified in Main_EMS_PAGE_SEG.
488;---------------------------------------------------------------------------
489
490SAVE_EMS_PAGE_STATE PROC FAR
491
492 PUSH AX ; save registers
493 PUSH CX
494 PUSH DX ;AN000;
495 PUSH DS ;AN000;
496 PUSH ES ;AN000;
497 PUSH BP ;AN000;
498 PUSH SI ;AN000;
499 PUSH DI ;AN000;
500 PUSH BX ;AN000;
501
502 MOV AX, SEG EMS_PAGE_MAP ; get segid
503 MOV DS,AX
504 LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc
505 MOV AX, SEG EMS_PAGE_ARRAY ; get segid
506 MOV ES,AX
507 LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY
508 MOV AH,EMS_SAVE_STATE ;
509 MOV AL,0 ; subfunction code
510 INT EMS_INT ; save page state ;AN000;
511
512 POP BX ;AN000;
513 POP DI ;AN000;
514 POP SI ;AN000;
515 POP BP ;AN000;
516 POP ES ;AN000;
517 POP DS ;AN000;
518 POP DX ;AN000;
519 POP CX ;AN000;
520
521 CMP AH,0 ; save ok??
522 JE SAVE_OK ;
523 STC
524 JMP SHORT DONE
525SAVE_OK:
526 CLC
527DONE:
528 POP AX
529 RET
530
531SAVE_EMS_PAGE_STATE ENDP
532
533ENDIF
534
535
536;-----------------------------------------------------------------------------
537; PROCERDURE: RESTORE_PAGE_STATE
538;
539; Function: Restore state of EMS page
540;
541; Input: None
542; Output: Page is restored
543;
544;-----------------------------------------------------------------------------
545
546RESTORE_PAGE_STATE PROC NEAR ;RESTORE EMS PAGE STATE
547 PUSHF ;save flag ;AN000;
548 CMP CS:MAIN_EMS_FLAG, 0 ;EMS enabled ?? ;AN000;
549 JNE REST_PUSH_REGS ;yes, restore registers
550 JMP SHORT RESTORE_EXIT ;no, exit ;AN000;
551 ;yes, restore page registers
552REST_PUSH_REGS:
553 PUSH AX ; save function code
554 PUSH CX ; save caller registers ;AN000;
555 PUSH DX ;AN000;
556 PUSH DS ;AN000;
557 PUSH ES ;AN000;
558 PUSH BP ;AN000;
559 PUSH SI ;AN000;
560 PUSH DI ;AN000;
561 PUSH BX ;AN000;
562
563 MOV AX, SEG EMS_PAGE_ARRAY
564 MOV DS,AX
565 LEA SI,EMS_PAGE_ARRAY ; DS:SI-->Page array
566 MOV AH,EMS_RESTORE_STATE ;
567 MOV AL,1 ;
568 INT EMS_INT ; restre page state ;AN000;
569 CMP AH,0 ; restore OK ??
570 JE REST_POP_REGS ; yes
571 STC ; set carry
572
573REST_POP_REGS:
574 POP BX ; RESTORE REGISTERS ;AN000;
575 POP DI ;AN000;
576 POP SI ;AN000;
577 POP BP ;AN000;
578 POP ES ;AN000;
579 POP DS ;AN000;
580 POP DX ;AN000;
581 POP CX ;AN000;
582 POP AX ; restore function code
583
584RESTORE_EXIT:
585 POPF
586 RET ;AN000;
587
588RESTORE_PAGE_STATE ENDP
589
590
591IF BUFFERFLAG
592
593;---------------------------------------------------------HKN 8/26/88-------
594; procedure name : map_page
595; Inputs : ems_page_number = physical page frame
596; number.
597; ems_save_handle1 = emm_handle.
598; Output : CY - error
599; NC - page is mapped to logical page 0
600;----------------------------------------------------------------------------
601map_page proc near
602
603 push ax
604 push bx
605 push dx
606
607 xor bx, bx
608 mov ax, cs:ems_page_number ; contains the page number obtained
609 ; during fastopen intialization.
610 mov ah, 44h
611 mov dx, cs:ems_save_handle1 ; contains the emm handle that was
612 ; obtained during fast init.
613 int ems_int
614 or ah, ah
615 jnz err_map_page
616 clc
617 jmp short map_page_done
618
619err_map_page:
620 stc
621
622map_page_done:
623 pop dx
624 pop bx
625 pop ax
626 ret
627
628map_page endp
629
630ENDIF
631
632
633 ; NOTE:
634CSEG_MAIN ENDS ; End of the first portion of the
635 ; Cseg_Main segment. Remaining
636 ; portion is in Fastinit.asm
637
638;-----------------------------------------------------------------------------
639
640
641
642
643
644;==============================================================================
645; All Fastopen functions are kept in a seperate segment. These are accessed
646; by a FAR indirect call from the MAIN routine.
647; ADDRESSABILTY: CS is used for accessing local data in Cseg_Open segment
648; DS is used for accessing data in the drive cache buffer
649; in the Cseg_Init segment
650; ES is used for accessing data in the name cache buffer
651; in the Cseg_Init segment
652;
653;*****************************************************************************
654CSEG_OPEN SEGMENT PARA PUBLIC 'code'
655 ASSUME cs:cseg_open,ds:nothing,es:nothing,ss:nothing
656;*****************************************************************************
657
658PUBLIC Open_name_cache_seg ;AN000;
659PUBLIC Open_name_Drive_Buff ;AN000;
660PUBLIC End_Open ;AN000;
661PUBLIC Chk_Flag ;AN000;
662
663;---- FastOpen Functions Local Variables --------------
664
665Current_Node DW ? ;address of current node entry buffer ;AN000;
666Current_Sibling DW ? ;address of current sibling node entry buffer ;AN000;
667Current_Drive DW ? ;address of current drive header ;AN000;
668Matching_Node DW -1 ;flag ;AN000;
669From_Delete DW 0 ;= 1 if call is from DELETE function ;AN000;
670Old_SI DW 0 ;SI save area ;AN000;
671Flag DB 0 ;AN000;
672Level DB 0 ;depth level of the path ;AN000;
673Dir_Info_Buffer DD ? ;Dir_Info buffer inside DOS ;AN000;
674Extended_Info_Buffer DD ? ;Extended Info buffer inside DOS ;AN000;
675New_FEI_clusnum DW 0 ;AN000;
676Packed_Name DB 11 dup (0) ;Space for packed dir name ;AN000;
677Top DW 0 ;AN000;
678Temp DW 0 ;AN000;
679Bottom DW 0 ;AN000;
680Depth DB 0 ;AN000;
681
682Chk_Flag dw 0 ; flag used by the analyser
683func_cod db 0 ; function code for analyser
684
685;Following data area is filled during initialization
686Open_name_cache_seg DW Cseg_Init ; address of name cache buffer
687Open_name_Drive_Buff DW 0 ; address of first drive buffer
688
689
690
691
692;
693;==============================================================================
694; Pathname Tree Search
695;
696; Element of each path name is represented by a node in the tree. First
697; node is connected to the the Drive header through first child pointer
698; (DCH_Child_Ptr). The first node may have one or more nodes underneath.
699; The first one is called the Child of this node and the others are the siblings
700; of the child node. Previous node is connected to the first node through
701; the child pointer (nChild_Ptr) and the siblings are connected through the
702; sibling pointer (nSibling_Ptr). Each node is connected to the previous
703; node through a backward pointer (nBackward_Ptr). For example, to go to the
704; previous node from any of the siblings. It is necessary to go to the
705; child through previous siblings (if any) and then to the previous from the
706; child. All this backward movement is using nBackward_Ptr.
707; Similarly to go to a child or sibling, nChild_ptr or nSibling_Ptr should be
708; used. The strucure of drive header and the node are defined in Fastopen.inc
709;
710
711;==============================================================================
712;Subroutine: LOOKUP
713;
714;INPUT:
715; DS:SI -> path (drive letter D: will be validated by Find_Drive_Cache_hdr)
716; ES:DI -> DIR_INFO buffer to be returned inside DOS
717; ES:CX -> FASTOPEN_Extended_Info buffer inside DOS
718; ES:BP -> Drive_Cache_Heade
719;
720;
721;OUTPUT:
722; If the whole path is found,
723; DS:SI--> 0
724; ES:DI--> DIR_INFO buffer is filled with directory info
725; ES:CX--> EXT_INFO buffer is filled with extended info
726;
727; If partially found the path,
728; DS:SI--> '\' after the matching directory name
729; ES:DI--> DIR_INFO buffer is filled with directory info
730; ES:CX--> EXT_INFO buffer is filled with extended info
731;
732; If the Name_cache tree is empty, i.e.,no root directory name,
733; DS:SI--> '\' after ':'
734; ES:DI--> DIR_INFO buffer is undetermined
735; ES:CX--> EXT_INFO buffer is undetermined
736;
737;==============================================================================
738
739LOOKUP PROC FAR
740
741 mov cs:func_cod,al ; save function code
742 cmp From_Delete, 0 ;call from DELETE function ??
743 je Look_Pack_Dir ;no, dont restore DS
744 mov DS,bx ;yes, restore DS
745 ASSUME DS:Cseg_Init
746 jmp short Look_save_regs ;save registers
747
748Look_Pack_Dir:
749 CALL PACK_DIR_NAME ;on return drive letter => DL,
750
751 CALL FIND_DRIVE_CACHE_HEADER ;find drive header address
752 ;on return ES:BP-->drive header
753 jnc look_save_regs ;drive buffer found
754 jmp lookup_error ;drive buffer not found
755
756Look_Save_Regs:
757 push es
758 push di
759 push cx
760 mov ax, cs:Open_Name_Cache_Seg ;AN000;
761 mov es, ax ;ES = Name_Cache_Seg ;AN000;
762 ASSUME es:Cseg_Init ;AN000;
763 CALL SET_LRU ;set the Real LRU, if any.
764
765 or cs:Flag,Is_drive_head ;level of the tree. Drive header
766 mov cs:Matching_Node, -1 ;Nothing found yet.
767 mov cs:Current_Drive, BP ;drive header
768 mov cs:Level, 0 ;path level is 0
769
770Lookup_Path:
771 mov cs:Current_Node, BP ;save current node address
772 mov cs:Current_Sibling,0fffeh ;set no sibligs yet.
773 mov cs:Old_SI, si ;save current path address
774
775 CALL PACK_DIR_NAME ;get the next dir name from the path
776 jc Lookup_Done ;yes, found the whole path.
777
778 test cs:Flag, Is_drive_head ;dir name = drive header ?
779 jz Lp_Path1 ;no-
780
781 push ds ;yes-drive header
782 mov ds,cs:Open_Name_Cache_Seg
783 ASSUME ds:Cseg_Init
784 mov BP, DS:[BP.DCH_Child_ptr] ;BP-->first child node under drive hdr
785 pop ds
786 ASSUME ds:nothing
787 jmp short Lp_Path2
788
789Lp_Path1:
790 mov BP, ES:[BP.nChild_ptr] ;BP--> child of current node
791
792Lp_Path2:
793 cmp BP, -1 ;no child?
794 je Lookup_Done ;Not found or partially found
795 mov cs:Current_Node, BP ;current_node = found node
796 and cs:Flag, Not_drive_head ;reset the flag.
797
798Lp_Cmpare:
799 CALL CMPARE ;look for path in current node
800 je Lookup_Found ;Yes, found a match. Next level for
801 ;possible remianing path
802
803 mov BP, ES:[BP.nSibling_ptr] ;not found. Any siblings?
804 mov cs:Current_Sibling,BP
805 cmp BP, -1 ;any more sibling?
806 je Lookup_Done ;no - done
807
808 mov cs:Current_Node, BP ;yes- make the found sibling as a current
809 jmp short Lp_Cmpare ;node and search path in this node
810
811Lookup_Found:
812 inc cs:Level
813 mov cs:Matching_Node,BP ;Used by Unfold_Name_Record
814
815 CALL PRE_LRU_STACK ;set the TEMP_LRU_Stack
816 jmp Lookup_Path ;continue to the next dir
817
818Lookup_Done:
819 mov si, cs:Old_SI
820 pop cx ;restore Extended_Info buffer
821 pop di ;restore Dir_Info buffer
822 pop es ;the segment for the above buffers
823
824 cmp ax, -1
825 je Lookup_ERR ;error occured in Pack_Dir_Name.
826 clc ;clear carry.
827 jmp short Lookup_Done1
828
829Lookup_ERR: ;error exit
830 stc
831
832Lookup_Done1:
833 test cs:Flag, is_delete ;called by delete?
834 jnz Lookup_Return
835 jc Lookup_Exit ;If it was an error, don't change the carry flag
836
837 CALL UNFOLD_NAME_RECORD ;unfold the current node's record
838Lookup_Exit:
839 jmp short Lookup_Return ;return to DOS.
840
841Lookup_Error: ;error exit
842 stc
843 mov ax,-1
844
845Lookup_Return: ;return to Delete routine.
846 CALL Check_It ;check tree structure
847 ret
848
849LOOKUP ENDP
850
851
852
853
854
855;==============================================================================
856;SUBROUTINE: INSERT
857;
858;INPUT: DS:DI -> Dir_Info in DOS
859; ES:BX -> Fastopen_Extended_Info in DOS
860; Current_Node, Current_Sibling, Current_Drive, Flag
861;
862;OUTPUT: Information inserted into Name_cache_tree.
863;
864; Any Sequential Insert operation should be preceded by a Look_up
865; operation. For ex., if the DOS wants to insert C:\DIR1\DIR2\File1
866; and suppose there is no matching name cache record for DIR1 in the tree.
867; Firstly DOS will try to look up C:\DIR1\DIR2\File1. FASTOPEN will
868; return to DOS with DS:SI points to "\" after the drive letter.
869; Then, DOS will simply ask an insert operation with DS:DI, ES:BX
870; points to the information on "DIR1". FASTOPEN will insert DIR1
871; onto the tree. After that DOS will ask another insert
872; operation for DIR2. FASTOPEN will insert DIR2. Finally DOS will
873; ask to insert File1.
874;
875; Suppose when DOS try to look up C:\DIR1\DIR2\File2 at this moment.
876; FASTOPEN will return to DOS with DS:SI points to "\" after DIR2 (since
877; DIR2 information is already in the name cache tree). Then DOS will ask
878; to insert File2.
879;
880; Any Insert operation of subdirectory name which is deeper than (Number_
881; of_Entries - 1) will not be inserted but will just return.
882; Also, for the safety reason, if the would be freed node (=LRU node) is
883; the same as the Current_Node, there will be no insertion. (This is a simple
884; safety valve. A more smart logic can look for the next **legitimately
885; available** LRU node to use, or sometimes, simply replace the contents of the
886; entry if adequate. But this will increase the complexity greatly, and I
887; think the current logic is still practical enough to use despite of the
888; possible small window of performance degradation in a very special cases. J.K.)
889;
890;==============================================================================
891
892INSERT PROC FAR
893 mov cs:func_cod,al ; save function code
894 inc cs:Level ;increment directory level
895 xor ax,ax
896 mov al, cs:Level
897 inc al
898 mov bp, cs:Current_Drive ;BP-->address of current drive header
899 push ds
900 mov ds,cs:Open_Name_Cache_Seg ;DS=name cache segment
901
902 ASSUME ds:Cseg_Init ;AN000;
903 cmp ax, ds:[bp.DCH_Num_Entries] ;Level > (Num_Entries - 1) ?
904 pop ds
905 ASSUME ds:nothing
906 jbe Insert_it ;no- insert it
907 jmp short Insert_return ;yes return
908
909Insert_it:
910 or cs:Flag, is_insert
911
912 CALL GET_FREE_NODE ;AX = offset value of the available
913 ;name_record in Name_Cache_Seg.
914 jc I_Exit ;Current node = would-be freed node.
915
916 CALL MAKE_NAME_RECORD ;Fill the above name record entry.
917 ;ES was changed to Name_Cache_Seg.
918
919 mov bp, cs:Current_Node ;set BP to current_node
920 mov bx, bp ;save it into bx
921 cmp cs:Current_Sibling,0fffeh ;current node sibling node ??
922 je I_Child ;no-child of preceding node
923 mov es:[bp.nSibling_ptr], ax ;yes-make new node sibling of
924 jmp short I_Done ;current node
925
926I_Child: ;set nChild_ptr
927 test cs:Flag,Is_drive_head ;drive level?
928 jnz I_Child_first ;Yes, must be the first child
929 mov es:[bp.nChild_ptr], ax ;no-make ndew node child of
930 jmp short I_Done ;current node
931
932I_Child_first: ;this is the first child in this drive.
933 push ds
934 mov ds,cs:Open_Name_Cache_Seg ;AN000;
935 ASSUME ds:Cseg_Init ;AN000;
936 mov ds:[bp.DCH_Child_ptr],ax ;make new node 1st child current drive
937 pop ds
938 ASSUME ds:nothing
939 mov bx, cs:Current_Drive ;change bx to Current_Drive
940 and cs:Flag, Not_drive_head ;reset the flag
941
942I_Done:
943 mov bp, ax
944 mov es:[bp.nBackward_ptr],bx ;set the backward ptr of the inserted node.
945
946 CALL PRE_LRU_STACK ;save this inserted record temporarily.
947
948 mov cs:Current_Node,bp ;make new node current node
949 ;any subsequent insert operation
950 mov cs:Current_Sibling,0fffeh ;should be installed as a child
951
952I_Exit:
953 and cs:Flag, not_insert ;set not insert flag
954
955Insert_return:
956 CALL Check_It ;check tree structure
957 ret ;return
958
959INSERT ENDP
960
961
962
963
964
965
966;==============================================================================
967;Subroutine: DELETE
968;
969;INPUT: DS:SI -> path
970; ES:BP -> drive_cache_header (for Look_Up operation)
971;
972;OUTPUT: if found, then remove the matching Name_Record will be removed from
973; the tree and from the LRU chain. The freed entry will be placed
974; on top of the LRU chain.
975;
976;==============================================================================
977
978DELETE PROC FAR
979
980 mov cs:func_cod,al ; save function code
981 CALL PACK_DIR_NAME ;drive letter => DL, ;AN000;
982
983 CALL FIND_DRIVE_CACHE_HEADER ;find drive header address
984 ;on return ES:BP-->drive header
985 jc d_err_exit ;error exit
986
987 or cs:Flag, is_delete ;set the flag for Look_up.
988 push ds ;save DS in BX since it is going to be
989 pop bx ;changed for jumping to other segment
990 push ds
991 mov ax,cseg_Main
992 mov ds,ax ;DS=Main segment ID
993 assume ds:Cseg_Main
994 mov cs:From_Delete, 1 ;set flag indicate that the call
995 ;is from DELETE function
996 CALL VECTOR_LOOKUP ;FAR call to Lookup function
997
998 mov cs:From_Delete, 0 ;reset from delete flag
999 pop ds
1000 ASSUME ds:nothing
1001 jc D_err_Exit ;indirectly in the same segment
1002
1003 cmp byte ptr ds:[si], 0 ;found the whole path?
1004 jne D_err_Exit ;No.
1005
1006;At this point, Current_Node = BP.
1007 mov bx, cs:Open_Name_Cache_Seg
1008 mov es, bx ;set ES to name_cache_seg.
1009 ASSUME es:Cseg_Init
1010
1011Delete_Node:
1012 cmp es:[bp.nChild_ptr], -1 ;No children?
1013 jne D_err_Exit
1014 CALL REMOVEFROMTREE ;remove the node while maintaing the
1015 ;integrity of the tree.
1016
1017 mov es:[bp.nCmpct_Dir_Info], ' ' ;mark that this entry is free!!!
1018
1019D_LRU_MRU:
1020 CALL REMOVEFROMLRUCHAIN ;Remove BP from the LRU,MRU chain
1021
1022 mov si, cs:Current_Drive ;Now let the deleted node to be the
1023 push ds ; LRU node
1024 mov ds,cs:Open_Name_Cache_Seg
1025 ASSUME ds:Cseg_Init ;AN000;
1026
1027 mov bx, ds:[si.DCH_LRU_ROOT] ;es:bx -> first node
1028 mov es:[bp.nLRU_ptr],bx ;Target.nLRU_ptr -> first node
1029 mov es:[bx.nMRU_ptr],bp ;First_node.nMRU_ptr -> target
1030 mov ds:[si.DCH_LRU_ROOT],bp ;LRU_ROOT -> target
1031 mov es:[bp.nMRU_ptr],-1
1032 pop ds
1033 ASSUME ds:nothing
1034 jmp short D_Exit ;exit
1035
1036D_err_Exit: ;error exit
1037 stc
1038 mov ax, -1
1039
1040D_Exit:
1041 and cs:Flag, not_delete ;reset the flag
1042 CALL Check_It ;check tree structure
1043 ret ;return
1044
1045DELETE ENDP
1046
1047
1048
1049
1050
1051;==============================================================================
1052;Subroutine: UPDATE
1053;
1054;INPUT: If AH = 0, then update Dir_Entry area.
1055; ES:DI -> Dir_entry ("dir_first" is the key to search).
1056; DL = Logical Drive number (0 = A, 1 = B, ...).
1057;
1058; If AH = 1, then update "Fastopen_extended_info.FEI_clusnum".
1059; DL = Logical Drive number (0 = A, 1 = B, ...)
1060; CX = The value of "dir_first" to search.
1061; BP = new value of FEI_clusnum in the extended_info area.
1062;
1063; If AH = 2, then delete the entry. Same effect as Delete function
1064; except this time the keys used to delete are;
1065; DL = logical drive number
1066; CX = the value of "dir_first" to search.
1067;
1068; If AH = 3, then delete the entry. Same effect as Delete function
1069; except this time the keys used to delete are;
1070; DL = logical drive number
1071; DH = directory position
1072; DI = directory sector (low value)
1073; CX = directory sector (high value)
1074;
1075;
1076;OUT: if found, then data is updated
1077; else CY and AX = -1.
1078;
1079; This routine use "starting cluster number" and "drive letter"
1080; as a key to find the name record. Usually the reason is DOS
1081; does not have any "full path" information about the file when
1082; it has to call this routine to update the information.
1083; It follows the MRU chain until it finds the name record or
1084; until it reaches the free name record (identified by the
1085; Directory name starting with ' '), or until the end of
1086; the MRU chain.
1087;
1088;==============================================================================
1089
1090UPDATE PROC FAR
1091
1092 mov cs:func_cod,al ; save function code
1093 cmp ah, 0 ;update directory entry ?
1094 je Update_Dir_Entry ;yes-
1095 cmp ah, 1 ;update extended info ?
1096 je Update_Extended_clusnum ;yes-
1097 cmp ah, 2 ;delete based on first clus num ?
1098 je Update_Delete ;yes-
1099 cmp ah, 3 ;delete based directory sector ?
1100 je Update_Delete1 ;yes-
1101
1102U_ERROR: ;no - error exit
1103 stc
1104 jmp short Update_Exit
1105
1106Update_Delete: ; same as delete
1107 CALL FIND_CLUSTER_NUMBER ; find name entry using first cluster
1108 jc U_ERROR
1109 jmp Delete_Node ; if found, delete entry
1110
1111Update_Delete1: ; same as delete (PTR P3718 3/10/88)
1112 CALL FIND_DIR_SECTOR ; find name entry using directory
1113 jc U_ERROR ; sector and directory position
1114 jmp Delete_Node ; if found, delete node
1115
1116Update_Dir_Entry:
1117 mov cx, es:[di.dir_first]
1118 push es ;save Dir_Info pointer ES:DI
1119 push di
1120 CALL FIND_CLUSTER_NUMBER
1121 pop si ;restore Dir_Info pointer in DS:SI
1122 pop ds
1123 jc U_ERROR ;error-if not found
1124
1125 push bp ;found the entry
1126 pop di
1127 add di, nCmpct_Dir_Info ;ES:DI->Name_Record.nCmpct_Dir_Info
1128 mov cx, ODI_head_leng
1129 REP MOVSB ;update Cmpct_dir_info head section
1130 add si, ODI_skip_leng
1131 mov cx, ODI_tail_leng
1132 REP MOVSB ;update tail section
1133 jmp short Update_Exit ;exit
1134
1135Update_Extended_clusnum: ;update extended info field
1136 mov cs:New_FEI_clusnum,bp
1137 CALL FIND_CLUSTER_NUMBER ;Find entry based first cluster number
1138 jc U_ERROR
1139
1140 add bp, nExtended_Info ;es:bp -> Name_record.nExtended_Info
1141 mov bx, cs:New_FEI_clusnum
1142 mov es:[bp.FEI_clusnum],bx
1143
1144Update_Exit:
1145 CALL Check_It ;check tree structure
1146 ret ;return
1147
1148UPDATE ENDP
1149
1150
1151
1152
1153
1154
1155;==============================================================================
1156;Subroutine: FP_PURGE Rest Name Cache Buffers
1157;
1158;INPUT: Main_Name_Drive_Buff - Offset to Name cache buffer
1159; Main_Name_Cache_Seg - Name cache seg id
1160; DL = Drive ID
1161;
1162;OUT: Buffer is purged
1163;
1164;==============================================================================
1165
1166FP_PURGE PROC FAR
1167
1168 mov si,Open_Name_Drive_Buff ; SI-->first Name drive cache buff
1169 mov es,Open_Name_Cache_Seg ; ES = name cache seg ID
1170 mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer
1171 inc dl ; DL=drive number
1172 add dl,040H ; convert drive num to drive letter
1173
1174; Search for the name drive header corresponds to the drive letter
1175Purge_Drv_Loop:
1176 cmp es:[si].DCH_Drive_Letter,dl ; drive letter match ??
1177 je Purge_drive_cache ; yes - set drive cache
1178 add si, size Drive_Cache_Header ; no - get address of next drive cache
1179 jmp purge_drv_loop ; try next name drive header
1180
1181Purge_Drive_Cache: ; SI-->drive header
1182 mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer
1183 mov cx,es:[si].DCH_num_entries ; get number of name records
1184 mov ax,bx ; save last name record address
1185 mov es:[bx].nMRU_ptr, -1 ; make first MRU -1
1186 jmp short set_start
1187
1188Set_Up_Names:
1189 mov es:[bx].nMRU_ptr,ax ;save last name record as MRU entry
1190 add ax, size Name_Record ;AX = last name record = current name record
1191
1192Set_Start:
1193 mov es:[bx].nChild_ptr, -1 ;no children or siblings
1194 mov es:[bx].nsibling_ptr, -1 ;right now
1195 mov es:[bx].nBackward_ptr, -1
1196
1197 push di
1198 push ax
1199 mov ax, ' ' ;AX = ' '
1200 mov di, bx ;DI-->current name record
1201 add di, nCmpct_Dir_Info ;blank out the Dir name area
1202 stosb ;in the name record
1203 stosw
1204 stosw
1205 stosw
1206 stosw
1207 stosw
1208 pop ax ; AX = last name record address
1209 pop di
1210
1211 dec cx ;update record count
1212 jcxz purge_exit ;exit if last name record is done
1213 mov dx,bx
1214 add dx, size Name_Record ;DX-->next name record
1215 mov es:[bx].nLRU_ptr,dx ;set LRU pointer - next name record
1216 add bx, size Name_Record
1217 jmp set_up_names ;set next name record
1218
1219Purge_exit:
1220 clc
1221 ret
1222
1223FP_PURGE ENDP
1224
1225
1226
1227;----------------------------------------------------------------------------
1228; FASTOPEN SUPPORT ROUTINES
1229;----------------------------------------------------------------------------
1230;
1231; PROCEDURE: Find_Drive_Cache_Header
1232;
1233; Function: Validate drive ID and find address of drive cache header
1234;
1235;IN: DL - drive letter
1236; Drive_Header_Start ;label
1237; Flag.
1238;
1239;OUT: If CY = 0 Drive Header found
1240; ES:BP -> Drive_Cache_Header,
1241;
1242; If CY = 1 Drive Header not found
1243;
1244;----------------------------------------------------------------------------
1245
1246FIND_DRIVE_CACHE_HEADER PROC NEAR
1247
1248 mov bp, cs:Open_name_drive_buff
1249 push ds
1250 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1251 ASSUME ds:Cseg_Init ;DS:BP-->first drive header ;AN000;
1252
1253FDCH_while:
1254 cmp byte ptr ds:[bp.DCH_Drive_Letter], dl ; drive letter match
1255 jne fdch_chk_end ; no - check next header
1256 clc ; yes - exit
1257 jmp short FDCH_Exit
1258
1259FDCH_Chk_End:
1260 cmp byte ptr ds:[bp.DCH_Sibling_ptr], -1 ; is this last header ?
1261 je FDCH_Not_Found ; yes - header not found
1262 add bp, size Drive_Cache_Header ; no - get next header
1263 jmp short FDCH_while ; look for match
1264
1265FDCH_Not_Found:
1266 stc ;not found
1267
1268FDCH_Exit: ;ES:BP-->header if found
1269 pop ds
1270 ASSUME ds:nothing ;return
1271 ret
1272
1273FIND_DRIVE_CACHE_HEADER endp
1274
1275
1276
1277
1278;----------------------------------------------------------------------
1279; PROCEDURE: GET_FREE_NODE
1280;
1281; called by Insert. The LRU node pointed DCH_LRU_ROOT is returned in AX
1282; and DCH_LRU_ROOT points to the following node in LRU chain.
1283; If the node is not an empty node, then it will be removed from the
1284; tree.
1285;
1286; IN: Current_Drive, Current_Node
1287;
1288; OUT: AX = offset of the free node in Name_Cache_Seg
1289; Other registers saved.
1290;----------------------------------------------------------------------
1291
1292GET_FREE_NODE PROC NEAR
1293
1294 push es ;save registers
1295 push di
1296 push si
1297 push bp
1298
1299 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1300 mov es, ax ;ES=Name cache segment ;AN000;
1301 ASSUME es:Cseg_Init ;AN000;
1302 mov si, cs:Current_Drive ;SI-->drive_cache_header
1303 push ds
1304 mov ds,cs:Open_Name_Cache_Seg
1305 ASSUME ds:Cseg_Init
1306 mov ax, ds:[si.DCH_LRU_ROOT] ;get the LRU node
1307 pop ds
1308 ASSUME ds:nothing
1309
1310 cmp ax, cs:current_Node ;LRU node=Current Node ??
1311 je GFN_skip ;yes-
1312
1313 mov bp, ax ;BP=Current node
1314 mov di, es:[bp.nLRU_ptr] ;DI= current LRU node's following node
1315 mov es:[di.nMRU_ptr],-1 ;set that node's MRU ptr
1316 push ds
1317 mov ds,cs:Open_Name_Cache_Seg ;DS=Name cache segment
1318 ASSUME ds:Cseg_Init
1319 mov ds:[si.DCH_LRU_ROOT],di ;connect previous node to
1320 pop ds ;next node
1321 ASSUME ds:nothing
1322
1323 cmp byte ptr es:[bp.nCmpct_Dir_Info],' ';an empty node?
1324 je GFN_OK ;then no problem.
1325
1326 CALL RemoveFromTree ;otherwise, it should be removed
1327 ;from the tree.
1328GFN_OK:
1329 clc
1330 jmp short GFN_ret
1331
1332GFN_Skip:
1333 stc
1334
1335GFN_ret:
1336 pop bp
1337 pop si
1338 pop di
1339 pop es
1340 ret ;return
1341
1342GET_FREE_NODE endp
1343
1344
1345
1346
1347;
1348;----------------------------------------------------------------------
1349; PROCEDURE: PRE_LRU_STACK
1350;
1351; When called by Look_up, Insert routine, the requested target node (BP)
1352; will be temporarily removed from LRU,MRU chain (until SET_LRU routine
1353; call), and will be pushed into a logical stack. Actually, this routine
1354; will not use a stack, but try to get the effect of the use of stack
1355; to keep the history of target nodes in "REVERSE" LRU order as follows;
1356; { inc Depth;
1357; if Depth == 1 then Bottom = BP;
1358; Bottom.LRU_ptr = -1;
1359; Bottom.MRU_ptr = -1;
1360; else if Depth == 2 then Top = BP;
1361; Top.LRU_ptr = Bottom;
1362; Bottom.MRU_ptr = Top;
1363; Top.MRU_ptr = -1;
1364; else if Depth >= 3 then Temp = Top;
1365; Top = BP;
1366; Top.LRU_ptr = Temp;
1367; Temp.MRU_ptr = Top;
1368; Top.MRU_ptr = -1;
1369; }
1370;
1371;IN: Depth, Top, Bottom, Temp,
1372; Requested target node (BP)
1373; ES = Name_Cache_Seg
1374;
1375;OUT: Target node removed from LRU,MRU chain.
1376; Target node's history saved in reverse LRU order.
1377; If called by "Delete" routine, then will just exit.
1378; If called by "Insert" routine, then will not attempt
1379; to remove the target node.
1380;----------------------------------------------------------------------
1381
1382PRE_LRU_STACK PROC NEAR
1383
1384 test cs:Flag, is_delete ;invoked by Delete routine
1385 jnz PLS_Exit
1386 test cs:Flag, is_insert ;called by Insert routine
1387 jnz PLS_Push
1388
1389 CALL RemoveFromLRUChain ;remove BP from the chain.
1390
1391PLS_Push:
1392 push di
1393
1394 inc cs:Depth
1395 cmp cs:Depth, 1
1396 jne PLS_Top
1397 mov cs:Bottom, bp ;bottom = bp
1398 mov es:[bp.nLRU_ptr], -1
1399 jmp short PLS_Done
1400
1401PLS_Top:
1402 cmp cs:Depth, 2
1403 jne PLS_Temp
1404 mov cs:Top, bp ;Top = bp
1405 mov di, cs:bottom ;di = bottom
1406
1407PLS_com:
1408 mov es:[bp.nLRU_ptr],di ;Top.LRU_ptr = bottom
1409 mov es:[di.nMRU_ptr],bp ;Bottom.MRU_ptr = top
1410 jmp short PLS_Done
1411
1412PLS_Temp:
1413 mov di, cs:Top ;di = Top
1414 mov cs:Temp, di ;Temp = di
1415 mov cs:Top, bp ;Top = bp
1416 jmp short PLS_com
1417
1418PLS_Done:
1419 mov es:[bp.nMRU_ptr],-1
1420 pop di
1421
1422PLS_Exit:
1423 ret
1424
1425PRE_LRU_STACK endp
1426;
1427
1428
1429
1430
1431
1432;----------------------------------------------------------------------
1433;PROCEDURE: SET_LRU
1434;
1435;INPUT: Depth, Top, Bottom, Current_Drive, ES = Name_Cache_Seg
1436;
1437;OUT: If Depth == 0 then exit
1438; Pre_LRU_Stack procedure already maintained a reverse order LRU
1439; mini chain. Set_LRU will just put the top after the last node
1440; of the current LRU chain;
1441; { Get the last node of LRU chain.
1442; if Depth == 0 then exit;
1443; if Depth == 1 then Last_Node.LRU_ptr = Bottom;
1444; Bottom.MRU_ptr = Last_Node;
1445; MRU_ROOT = Bottom;
1446; if Depth >= 2 then Last_Node.LRU_ptr = Top;
1447; Top.MRU_ptr = Last_Node;
1448; MRU_ROOT = Bottom;
1449; Depth = 0;
1450; }
1451;----------------------------------------------------------------------
1452
1453SET_LRU PROC NEAR
1454
1455 cmp cs:Depth, 0 ;nothing in the stack?
1456 je SL_Exit
1457
1458 push si
1459 push di
1460 push bx
1461 mov si, cs:Current_Drive ;cs:si -> Drive_Cache_Header
1462 push ds
1463 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1464 ASSUME ds:Cseg_Init ;AN000;
1465 mov di, ds:[si.DCH_MRU_ROOT] ;es:di -> Last node in LRU chain
1466
1467 cmp cs:Depth, 1
1468 jne SL_Other
1469
1470 mov bx, cs:Bottom
1471 mov es:[di.nLRU_ptr],bx ;Last_Node.LRU_ptr = Bottom
1472 mov es:[bx.nMRU_ptr],di ;Bottom.MRU_ptr = Last_Node
1473 mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT = Bottom
1474 jmp short SL_Done
1475
1476SL_Other: ;Depth >= 2
1477 mov bx, cs:Top
1478 mov es:[di.nLRU_ptr],bx
1479 mov es:[bx.nMRU_ptr],di
1480 mov bx, cs:Bottom
1481 mov ds:[si.DCH_MRU_ROOT],bx
1482
1483SL_Done:
1484 pop ds
1485 ASSUME ds:nothing
1486 mov cs:Depth, 0 ;reset the Depth
1487 pop bx
1488 pop di
1489 pop si
1490
1491SL_Exit:
1492 ret
1493
1494Set_LRU endp
1495
1496
1497
1498
1499
1500;----------------------------------------------------------------------
1501; Procedure RemoveFromLRUChain
1502;
1503;IN: Target node (BP) to be removed
1504; Current_drive
1505; ES - Name_Cache_Seg
1506;
1507;OUT: Target node removed from the LRU,MRU chain. LRU,MRU chain
1508; updated.
1509;
1510;----------------------------------------------------------------------
1511
1512RemoveFromLRUChain PROC near
1513
1514 push bx
1515 push di
1516 push si
1517
1518 mov si, cs:Current_drive ;cs:si-> Drive_cache_header
1519 mov bx, es:[bp.nMRU_ptr] ;es:bx-> Preceding node
1520 mov di, es:[bp.nLRU_ptr] ;es:di-> Following node
1521 cmp bx, -1 ;Is target the first node?
1522 je RFLC_first_node
1523 cmp di, -1 ;Is target the last node of LRU chain?
1524 je RFLC_last_node
1525 mov es:[bx.nLRU_ptr],di ;Preceding.LRU_ptr->following node
1526 mov es:[di.nMRU_ptr],bx ;Following.MRU_ptr->preceding node
1527 jmp short RFLC_done
1528
1529RFLC_first_node:
1530 push ds
1531 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1532 ASSUME ds:Cseg_Init ;AN000;
1533 mov ds:[si.DCH_LRU_ROOT],di ;LRU_ROOT-> following node
1534 pop ds
1535 ASSUME ds:nothing
1536 mov es:[di.nMRU_ptr], -1 ;Following node's MRU_ptr
1537 jmp short RFLC_done
1538
1539RFLC_last_node:
1540 push ds
1541 mov ds,cs:Open_Name_Cache_Seg
1542 ASSUME ds:Cseg_Init
1543 mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT-> preceding node
1544 mov es:[bx.nLRU_ptr], -1 ;Preceding node's LRU_ptr
1545 pop ds
1546 ASSUME ds:nothing
1547
1548RFLC_done:
1549 pop si
1550 pop di
1551 pop bx
1552 ret
1553
1554RemoveFromLRUChain endp
1555;
1556
1557
1558
1559;----------------------------------------------------------------------
1560; Proceure RemoveFromTree
1561;
1562;IN: BP - offset of node to be removed from the tree
1563; This node shoud not be a subdirectory that is not empty!!!
1564; ES - Name_Cache_Seg
1565; Current_Drive
1566;
1567;OUT: The node will be freed from the tree.
1568; The neighbor's Child_ptr, Sibling_ptr, Backward_ptr are adjusted
1569; accordingly.
1570; The freed node's child_ptr, sibling_ptr, backward_ptr are reset to -1.
1571;----------------------------------------------------------------------
1572
1573REMOVEFROMTREE PROC NEAR
1574
1575 push bx
1576 push dx
1577
1578 mov bx, es:[bp.nBackward_ptr] ;get the preceding node
1579 mov dx, es:[bp.nSibling_ptr] ;get the sibling node
1580 cmp bx, cs:Current_Drive
1581 je RFT_First_Child ;bp is the first child
1582 cmp es:[bx.nChild_ptr],bp
1583 je RFT_Child ;bp is the child of the preceding node
1584 mov es:[bx.nSibling_ptr],dx ;bp is the Sibling of the preceding node
1585 ;Update the preceding node's Sibling ptr
1586 jmp short RFT_Reset
1587
1588RFT_First_Child:
1589 push ds
1590 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1591 ASSUME ds:Cseg_Init ;AN000;
1592 mov ds:[bx.DCH_Child_ptr],dx
1593 pop ds
1594 ASSUME ds:nothing
1595 jmp short RFT_Reset
1596
1597RFT_Child:
1598 mov es:[bx.nChild_ptr],dx
1599
1600RFT_Reset: ;reset the deleted node's tree pointers
1601 mov es:[bp.nChild_ptr],-1
1602 mov es:[bp.nSibling_ptr],-1
1603 mov es:[bp.nBackward_ptr],-1
1604
1605 xchg dx,bx ;now, dx=preceding node, bx=following node
1606 cmp bx,-1 ;end of sibling?
1607 je RFT_ret
1608 mov es:[bx.nBackward_ptr],dx;modify backward_ptr of the sibling node
1609
1610RFT_ret:
1611 pop dx
1612 pop bx
1613 ret ;return
1614
1615REMOVEFROMTREE endp
1616;
1617
1618
1619
1620
1621;----------------------------------------------------------------------
1622; Procedure CMPARE
1623;
1624;IN: Packed name
1625; BP = target node
1626;
1627;OUT: ZERO flag set when compare O.K.
1628; DI destroyed.
1629;----------------------------------------------------------------------
1630
1631CMPARE PROC near
1632
1633 push ds
1634 push si
1635 mov cx, 11
1636 push cs
1637 pop ds
1638 mov si, offset cs:Packed_Name ;ds:si -> Packed_Name
1639 mov di,bp
1640 add di,nCmpct_Dir_Info ;es:di -> bp.nCmpact_Dir_Info
1641 REPE CMPSB
1642 pop si
1643 pop ds
1644 ret
1645CMPARE endp
1646
1647
1648
1649
1650;
1651;----------------------------------------------------------------------
1652; Procedure: MAKE_NAME_RECORD
1653;
1654;IN: DS:DI -> Dir_Info, ES:BX -> Extended_Info
1655; AX = offset of the Name_Record entry in Name_Cache_Seg.
1656;
1657;OUT: Name_Record in Name_Cache_Seg filled.
1658; nLRU_ptr, nChild_ptr, nSibling_ptr and nMRU_ptr are set to -1 for now.
1659; ES, SI, DI destroyed. ES will be Name_Cache_Seg.
1660;----------------------------------------------------------------------
1661
1662MAKE_NAME_RECORD PROC NEAR
1663
1664 push ds ;save DS
1665 push ax
1666
1667 push es ;save Extended_Info seg in DOS
1668 push di
1669 pop si ;DS:SI -> Dir_Info
1670 mov di, cs:Open_Name_Cache_Seg ;AN000;
1671 mov es, di ;AN000;
1672 ASSUME es:Cseg_Init ;AN000;
1673 mov di, ax ;ES:DI -> Name_Record
1674 mov ax, -1
1675 mov es:[di.nLRU_ptr],ax ;initialize pointers
1676 mov es:[di.nChild_ptr],ax
1677 mov es:[di.nSibling_ptr],ax
1678 mov es:[di.nMRU_ptr],ax
1679 add di, nCmpct_Dir_Info ;ES:DI -> Name_Record.nCmpct_Dir_Info
1680 mov cx, ODI_head_leng ;currently 10.
1681 rep movsb ;Move header part
1682 add si, ODI_skip_leng ;DS:SI -> tail part of Dir_Info
1683 mov cx, ODI_tail_leng
1684 REP MOVSB ;move tail part.
1685
1686 pop ds ;restore Extended_Info seg in DS!!!
1687 mov si, bx ;DS:SI -> Extended_Info
1688 mov cx, size Fastopen_Extended_Info
1689 rep movsb ;Move Extended_Info
1690 pop ax
1691 pop ds ;Restore DS
1692
1693 ret ;return
1694
1695MAKE_NAME_RECORD ENDP
1696;
1697
1698
1699
1700
1701;----------------------------------------------------------------------
1702; Procedure Unfold_Name_Record
1703;
1704;IN: Matching_Node, ES:DI -> Dir_Info buffer, ES:CX -> Extended_Info buffer
1705;
1706;OUT: if no matching node is found, then just return
1707; else Dir_Info, Extended_Info buffer are filled.
1708;----------------------------------------------------------------------
1709
1710Unfold_Name_Record PROC near
1711
1712 cmp cs:Matching_Node, -1
1713 je UNR_Exit ;just exit
1714 push ds
1715 push si
1716 push di
1717 push cx ;save extended_info addr
1718
1719 mov si, cs:Open_Name_Cache_Seg ;AN000;
1720 mov ds, si ;AN000;
1721 ASSUME ds:Cseg_Init ;AN000;
1722 mov si, cs:Matching_Node
1723 add si, nCmpct_Dir_Info ;DS:SI -> Cmpct_Dir_Info
1724
1725 mov cx, ODI_head_leng ;Dir_Info header length
1726 REP MOVSB ;Cmpct_Dir_Info.CDI_file_name -> ODI_head
1727
1728 add di, ODI_skip_leng ;length of Skiped part of Dir_Info
1729 mov cx, ODI_tail_leng ;Dir_Info tail length
1730 REP movsb ;Cmpct_Dir_Info.CDI_Time -> ODI_tail
1731 ;At this moment, SI -> nExtended_Info
1732
1733 pop di ;ES:DI -> Extended_info
1734 push di ;save di again for cx.
1735 mov cx, size Fastopen_Extended_Info
1736 REP movsb
1737
1738 pop cx ;restore extended_info addr
1739 pop di
1740 pop si
1741 pop ds
1742 ASSUME ds:nothing
1743UNR_Exit:
1744 ret ;return
1745
1746Unfold_Name_Record endp
1747;
1748
1749
1750
1751
1752;----------------------------------------------------------------------
1753; PROCEDURE: PACK DIR_NAME
1754;
1755; Parse the name off of DS:SI into Packed_Name. If called first time and
1756; DS:[SI+1] = ':' then it is ASSUMEd to be a drive letter and it will be
1757; returned in DL and SI will points to '\' after ':'. If it was a directory
1758; name then Packed_Name will be set and SI points to '\' or 0 after the
1759; parsed directory name or filename. This routine will check DS:[SI] when
1760; called to see if it points to '\' or 0. If it points to '\' then
1761; it is ASSUMEd that the user want to skip the delimiter. If it was 0,
1762; then this routine will set carry. So, with a given drive,path string,
1763; the user is going to keep calling this routine until it returns
1764; with carry set that tells the end.
1765;----------------------------------------------------------------------
1766
1767PACK_DIR_NAME PROC NEAR
1768
1769 cmp byte ptr ds:[si], 0 ;end of path ??
1770 jne PDN_Drive ;no-check for drive letter
1771 stc
1772 jmp short PDN_Exit ;yes-exit
1773
1774PDN_Drive:
1775 cmp byte ptr ds:[si+1], ':' ;drive letter terminater?
1776 jnz PDN_chk_skip ;no -
1777 mov dl, byte ptr ds:[si] ;yes-set DL to the drive letter
1778 inc si
1779 inc si ;set SI -> '\' after ':'
1780 jmp short PDN_Exit ;then exit
1781
1782PDN_chk_skip:
1783 cmp byte ptr ds:[si], '\' ;delimeter?
1784 jne PDN_Path ;no-
1785 inc si ;yes-skip delimiter
1786 cmp byte ptr ds:[si], 0 ;end of path ??
1787 jne PDN_Path ;no-pack path name
1788 stc ;yes-In fact, the input from DOS was
1789 mov ax, -1 ;D:\,0. FASTOPEN will treate
1790 jmp short PDN_Exit ;this as an error.
1791
1792PDN_Path: ;pack path name
1793 push es
1794 push di
1795 push ax
1796
1797 push cs
1798 pop es
1799 mov di, offset cs:Packed_Name ;ES:DI-->pack buffer
1800
1801 mov ax,' '
1802 STOSB ;blank out the Packed_Name
1803 STOSW
1804 STOSW
1805 STOSW
1806 STOSW
1807 STOSW
1808 mov di, offset cs:Packed_Name
1809
1810PDN_GetName:
1811 LODSB ;DS:SI => AL, SI++
1812 cmp al,'.'
1813 jz PDN_SetExt
1814 or al,al
1815 jz PDN_GetDone
1816 cmp al,'\'
1817 jz PDN_GetDone
1818 STOSB
1819 jmp short PDN_GetName
1820
1821PDN_SetExt:
1822 mov di, offset cs:Packed_Name+8
1823
1824PDN_GetExt:
1825 LODSB
1826 or al,al
1827 jz PDN_GetDone
1828 cmp al,'\'
1829 jz PDN_GetDone
1830
1831PDN_StoExt:
1832 STOSB
1833 jmp PDN_GetExt
1834
1835PDN_GetDone:
1836 dec si ;set SI back to the delimeter or 0.
1837 pop ax
1838 pop di
1839 pop es
1840
1841PDN_Exit:
1842 ret
1843
1844PACK_DIR_NAME endp
1845
1846
1847
1848
1849
1850;----------------------------------------------------------------------
1851; PROCEDURE: FIND_CLUSTER_NUMBER
1852;
1853;IN: DL = driver # (0 = A, 1 = B,...)
1854; CX = The value of Dir_First in Name_Record to search.
1855; Search Name_Record entries to find the matching starting cluster number.
1856; The search uses MRU chain for efficiency.
1857;
1858;OUT: ES = Name_Cache_Seg
1859; BP = Name_Record
1860; if not found, carry bit.
1861; ES, BP register changed.
1862;----------------------------------------------------------------------
1863
1864FIND_CLUSTER_NUMBER PROC NEAR
1865
1866 push ax
1867 push cx
1868 push dx
1869 add dl, 'A' ;convert to a drive letter
1870
1871 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1872 jc FCN_exit ;exit if not found
1873
1874 mov dx, cx ;save the key in DX ;AN000;
1875 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1876 mov es, ax ;AN000;
1877 ASSUME es:Cseg_Init
1878
1879 CALL SET_LRU ;clean up the LRU stack
1880
1881 mov cs:Current_Drive,bp ;set Current_Drive (You should not set
1882 ;Current_Drive before SET_LRU at any time!!!
1883 push ds
1884 mov ds,cs:Open_Name_Cache_Seg
1885 ASSUME ds:Cseg_Init
1886 mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try
1887 mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing
1888 pop ds
1889 ASSUME ds:nothing
1890
1891FCN_while:
1892 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1893 je FCN_not_found ;then no reason to continue search.
1894
1895 cmp dx, es:[bp.nCmpct_Dir_Info.CDI_cluster] ;matching starting cluster # ?
1896 je FCN_exit ;found it!!!
1897
1898 mov bp, es:[bp.nMRU_ptr] ;next MRU entry address
1899 cmp bp, -1 ;It was the end of MRU chain?
1900 je FCN_not_found ;not found. End of search
1901 LOOP FCN_while ;else compare cluster and contine...
1902
1903FCN_Not_found:
1904 stc
1905
1906FCN_exit:
1907 pop dx
1908 pop cx
1909 pop ax
1910 ret
1911
1912FIND_CLUSTER_NUMBER ENDP
1913
1914
1915
1916
1917;----------------------------------------------------------------------
1918; PROCEDURE: FIND_DIR_SECTOR (PTR 3718 3/10/88)
1919;
1920; Search Name_Record using directory sector and directory position
1921; for the name entry.
1922;
1923;IN: DL = driver # (0 = A, 1 = B,...)
1924; DI = Dirctory sector Low value
1925; CX = Dirctory sector high value
1926; DH = Dirctory position
1927;
1928;OUT: ES = Name_Cache_Seg
1929; BP = Name_Record
1930; if not found, carry bit.
1931; ES, BP register changed.
1932;----------------------------------------------------------------------
1933
1934FIND_DIR_SECTOR PROC NEAR
1935
1936 push ax
1937 push cx
1938 push dx
1939 add dl, 'A' ;convert to a drive letter
1940
1941 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1942 jc FDIR_exit ; error if not found
1943
1944 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1945 mov es, ax ;AN000;
1946 ASSUME es:Cseg_Init
1947
1948 CALL SET_LRU ;clean up the LRU stack
1949
1950 mov ax,cx ; save directory sector high value
1951 mov cs:Current_Drive,bp ;set Current_Drive (You should not set
1952 ;Current_Drive before SET_LRU at any time!!!
1953 push ds
1954 mov ds,cs:Open_Name_Cache_Seg
1955 ASSUME ds:Cseg_Init
1956 mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try
1957 mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing
1958 pop ds
1959 ASSUME ds:nothing
1960
1961FDIR_while:
1962 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1963 je FDIR_NOT_FOUND ;then no reason to continue search.
1964
1965 cmp di, word ptr es:[bp.nExtended_Info.FEI_dirsec] ;matching directory sector hi?
1966 jne FDIR_Next ;check next entry
1967
1968 cmp ax, word ptr es:[bp.nExtended_Info.FEI_dirsec+2] ;matching directory sector low ?
1969 jne FDIR_Next ;check next entry
1970
1971 cmp dh, es:[bp.nExtended_Info.FEI_dirpos] ;matching directory postion ?
1972 je FDIR_Exit ;check next entry
1973
1974FDIR_Next:
1975 mov bp, es:[bp.nMRU_ptr] ;next MRU entry address
1976 cmp bp, -1 ;It was the end of MRU chain?
1977 je FDIR_not_found ;not found. End of search
1978 loop FDIR_while ;else compare cluster and contine...
1979
1980FDIR_Not_found: ; no found
1981 stc
1982
1983FDIR_exit:
1984 pop dx
1985 pop cx
1986 pop ax
1987 ret
1988
1989FIND_DIR_SECTOR ENDP
1990
1991
1992
1993
1994
1995;--------------------------------------------------------------------------
1996; Procedure: CHECK_IT Call Fastopen Tree Analyser to check the
1997; consistency of the Directory/File Tree strucutre.
1998;--------------------------------------------------------------------------
1999CHECK_IT PROC NEAR
2000
2001 pushf ; save all registers
2002 push ax
2003 push bx
2004 push cx
2005 push dx
2006 push si
2007 push di
2008 push ds
2009 push es
2010 cmp cs:Chk_flag,0 ;Fastopen analyser enabled ??
2011 je Check_Exit ;no - exit
2012
2013 mov ax,cs:Open_Name_Cache_Seg ;yes-set multiplex function call
2014 mov es,ax
2015 mov ah,091h ;load Multiplex ID
2016 xor al,al
2017 xor cx,cx
2018 mov cl,cs:func_cod ;CL=Fastopen Function code
2019 mov di,cs:Current_Drive ;ES:DI-->current drive header
2020 INT 2FH ;call the analyser
2021
2022Check_Exit:
2023 pop es ;restore all registers
2024 pop ds
2025 pop di
2026 pop si
2027 pop dx
2028 pop cx
2029 pop bx
2030 pop ax
2031 popf ;return
2032 ret
2033
2034CHECK_IT ENDP
2035
2036
2037
2038
2039
2040; Calculate the size of the CSEG_OPEN Module in bytes
2041 IF ($-Cseg_Open) MOD 16 ;AN000;
2042 ORG ($-Cseg_Open)+16-(($-Cseg_Open) MOD 16) ;AN000;
2043 ENDIF ;AN000;
2044
2045END_OPEN label word
2046
2047
2048
2049
2050CSEG_OPEN ends
2051 end
2052 \ No newline at end of file