4 ;==============================================================================
6 ;==============================================================================
7 Is_drive_head EQU
00000001b ;AN000;
8 Is_delete EQU
00000010b ;AN000;
9 Is_insert EQU
00000100b ;AN000;
10 Not_drive_head EQU
11111110b ;AN000;
11 Not_delete EQU
11111101b ;AN000;
12 Not_insert EQU
11111011b
14 EMS_SAVE_STATE EQU 4FH
;AN000;
15 EMS_RESTORE_STATE EQU 4FH
;AN000;
16 EMS_INT EQU 67H
;AN000;
17 DOS_PAGE1 EQU
0FEH ;AN000;
20 ;==============================================================================
22 ;==============================================================================
25 debug
=0 ; an equate only for DOSMAC.inc ;AN000;
26 INCLUDE DOSMAC
.inc ;AN000;
29 INCLUDE dirent
.inc ;AN000;
30 INCLUDE fastsegs
.inc ; this cannot include in Fastopen.inc
31 INCLUDE fastopen
.inc ; this include file also contains DOS equates ;AN000;
34 ;==============================================================================
38 EXTRN FK_OPEN
:FAR ;AN000;
39 EXTRN FK_CLOSE
:FAR ;AN000;
40 EXTRN FK_INSERT
:FAR ;AN000;
41 EXTRN FK_DELETE
:FAR ;AN000;
42 EXTRN FK_LOOKUP
:FAR ;AN000;
43 EXTRN FK_TRUNCATE
:FAR ;AN000;
44 EXTRN FK_PURGE
:FAR ;AN000;
47 ;============================================================================
49 CSEG_MAIN
SEGMENT PARA
PUBLIC 'code'
50 ASSUME
cs:cseg_main
, ds:nothing
,es:nothing
,ss:nothing
51 ;============================================================================
56 PUBLIC SAVE_EMS_PAGE_STATE
57 PUBLIC EMS_PAGE_NUMBER
60 PUBLIC RESTORE_PAGE_STATE
61 PUBLIC EMS_SAVE_HANDLE1
63 PUBLIC Main_name_cache_seg
;AN000;
64 PUBLIC Main_Num_Of_drives
;AN000;
65 PUBLIC Main_Ext_Count
;AN000;
66 PUBLIC Main_extent_drive_Buff
;AN000;
67 PUBLIC Main_ext_cache_size
;AN000;
68 PUBLIC Main_name_cache_Buff
;AN000;
69 PUBLIC Main_EMS_FLAG
;AN000;
70 PUBLIC Main_Res_Segs
;AN000;
71 PUBLIC Main_EMS_PAGE_SIZE
;AN000;
72 PUBLIC Main_EMS_PAGE_SEG
;AN000;
73 PUBLIC Main_Total_Ext_Count
;AN000;
74 PUBLIC Main_Total_Name_Count
;AN000;
75 PUBLIC Main_Name_Drive_Buff
;AN000;
76 PUBLIC Main_ParamBuff
;AN000;
78 PUBLIC FOPEN_Insert
;AN000;
79 PUBLIC FOPEN_Update
;AN000;
80 PUBLIC FOPEN_Delete
;AN000;
81 PUBLIC FOPEN_Lookup
;AN000;
82 PUBLIC FOPEN_PURGE
;AN000;
84 PUBLIC FSEEK_Open
;AN000;
85 PUBLIC FSEEK_Close
;AN000;
86 PUBLIC FSEEK_Insert
;AN000;
87 PUBLIC FSEEK_Delete
;AN000;
88 PUBLIC FSEEK_Lookup
;AN000;
89 PUBLIC FSEEK_Truncate
;AN000;
90 PUBLIC FSEEK_Purge
;AN000;
92 PUBLIC VECTOR_LookUp
;AN000;
93 PUBLIC VECTOR_Delete
;AN000;
96 ; Following data variables are accessed by all other segments
98 Purge_Flag
DW 0 ; =1 if last call is PURGE function
99 Prev_drv_id
DB -1 ; previous request drive id
100 Main_name_cache_seg
DW Cseg_Init
; default to Init1 seg ;AN000;
101 Main_Num_Of_drives
DW 0 ; number of drives ;AN000;
102 Main_Ext_Count
DW 0 ; total name extent entries ;AN000;
103 Main_extent_drive_Buff
DW 0 ; addrs to extent drive ;AN000;
104 Main_name_cache_Buff
DW 0 ; address of Name cache buffer ;AN000;
105 Main_ext_cache_size
DW 0 ; extent cache size
106 Main_EMS_FLAG
DW 0 ; EMI flag 1= if EMI is enabled ;AN000;
107 Main_Res_Segs
DW 0 ; number of segs to be stay resident ;AN000;
108 Main_Total_Ext_Count
DW 0 ; Total extent count entries ;AN000;
109 Main_Total_Name_Count
DW 0 ; Total name count entries ;AN000;
110 Main_Name_Drive_Buff
DW 0 ; EMS data page segment ID ;AN000;
111 Main_ParamBuff
DW 50 dup (0) ; Drive ID/extent count buffer ;AN000;
113 ; The following structure is for saving and restoring EMS page state
114 EMS_PAGE_MAP
LABEL WORD
115 Main_EMS_SEG_COUNT
DW 1 ; EMS segment count
116 Main_EMS_PAGE_SEG
DW 0 ; EMS page segment ID ;AN000;
119 Main_EMS_PAGE_SIZE
DW 0 ; EMS page size ;AN000;
120 EMS_PAGE_ARRAY
DW 30 dup (0) ; EMS state save array
122 ; The following data values are used by MAIN segment
123 EMS_SAVE_LOG_PAGE1
DW ?
;HOLDS PREVIOUS PAGE1 ;AN000;
124 EMS_SAVE_HANDLE1
DW ?
;HOLDS PREVIOUS handle1 ;AN000;
127 ;----------------------------------------------------------HKN 8/26/88
129 EMS_PAGE_NUMBER
DW ?
; holds the ems
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 ;-----------------------------------------------------------------------------
140 FOPEN_Insert
DD Insert
;AN000;
141 FOPEN_Update
DD Update
;AN000;
142 FOPEN_Delete
DD delete
;AN000;
143 FOPEN_Lookup
DD lookup
;AN000;
144 FOPEN_Purge
DD FP_purge
;AN000;
146 FSEEK_Open
DD Fk_Open
;AN000;
147 FSEEK_Close
DD Fk_Close
;AN000;
148 FSEEK_Insert
DD Fk_Insert
;AN000;
149 FSEEK_Delete
DD Fk_Delete
;AN000;
150 FSEEK_Lookup
DD Fk_Lookup
;AN000;
151 FSEEK_Truncate
DD Fk_Truncate
;AN000;
152 FSEEK_Purge
DD Fk_Purge
;AN000;
154 VECTOR_LookUp
DD LookUp
; jump vector to LookUp used by Insert call
155 VECTOR_Delete
DD Fk_Delete
; jump vector to Delete used by Free_buffer routine
161 ;==============================================================================
163 MAIN 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;
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
183 ;-----------------------------------------------------------------------------
184 ; SAVE EMS PAGE STATE
185 ;-----------------------------------------------------------------------------
186 PUSH AX ; save registers
195 MOV AX, SEG EMS_PAGE_MAP
; get segid
197 LEA SI,EMS_PAGE_MAP
; DS:SI-->page map struc
198 MOV AX, SEG EMS_PAGE_ARRAY
; get segid
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;
215 JNE SAVE_FAILED
; no, error
221 ;------------------------------------------------------------HKN 8/26/88--
222 ; Before dispatching off the fastopen functions we must do the
224 ; 1. save the map for this page
225 ; 2. map this page to log. page 0 with the fastopen handle in
242 call far ptr save_ems_page_state
256 POP AX ; restore registers
258 JMP DISPATCH_FUNCS
; yes, dispatch functions
276 POP AX ; restore registers
278 POP BX ; no, restore DOS registers ;AN000;
286 JMP ERROR_RET
; error return
289 ;-----------------------------------------------------------------------------
290 ; FASTOPEN/FASTSEEK DISPATCHER
291 ;-----------------------------------------------------------------------------
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;
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 ;-----------------------------------------------------------------------------
305 cmp cs:Prev_drv_id
, dl ; current id same as previous valid
306 je Dispatch_Fseek
; yes - dont check drive ID
309 push bx ;DS=addressability to Cseg_Main ;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;
314 Get_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;
321 Drive_Not_Found: ; drive id not found
322 pop cx ; restore registers ;AN000;
325 jmp Error_Exit
; return
327 Drive_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;
333 ;-----------------------------------------------------------------------------
334 ; FASTSEEK FUNCTION DISPATCHER
335 ;-----------------------------------------------------------------------------
339 inc cs:call_cnt
;AN000;
340 ; cmp cs:call_cnt,0efffH ; for debugging
341 ; jne fsk_cont ; for debugging
345 push cs ; set addressability
346 pop ds ; CS = DS = Cseg_Main segment
348 cmp al,FONC_Purge
; PURGE call ?? ;AN000;
349 je chk_05
; yes - continue ;AN000;
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;
357 cmp al,FSK_Close
; CLOSE ?? ;AN000;
359 CALL FSEEK_CLOSE
; process close function ;AN000;
362 cmp al,FSK_Lookup
; LOOKUP ?? ;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;
371 cmp al,FSK_Insert
; INSERT ?? ;AN000;
373 CALL FSEEK_INSERT
; Process insert ;AN000;
376 cmp al,FSK_DELETE
; DELETE ?? ;AN000;
378 CALL FSEEK_DELETE
; process delete ;AN000;
379 jmp short exit
;AN000;
381 cmp al,FSK_Trunc
; TRUNCATE ?? ;AN000;
383 CALL FSEEK_TRUNCATE
; process truncate ;AN000;
384 jmp short exit
;AN000;
387 cmp cs:Purge_Flag
, 1 ; previous call is purge ?? ;AN000;
388 jne Purge_buffs
; no - purge the buffers
390 jmp short exit
;AN000;
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;
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;
405 jmp short exit
;AN000;
408 ; NOTE: Carry Flag state from Function calls must be correctly returned
409 ; to the DOS, especially from Fastseek Lookup function
412 ;-----------------------------------------------------------------------------
413 ; FASTOPEN FUNCTION DISPATCHER
414 ;-----------------------------------------------------------------------------
415 DISPATCH_FOPEN: ; dispatch FOPEN functions
417 mov cs:Purge_Flag
, 0 ; reset purge flag
418 cmp al, FONC_update
;AN000;
420 CALL CS:Fopen_Update
; UPDATE ;AN000;
421 jmp short exit
;AN000;
424 cmp al, FONC_insert
;AN000;
426 CALL CS:Fopen_Insert
; INSERT ;AN000;
427 jmp short exit
;AN000;
429 cmp al, FONC_look_up
;AN000;
431 CALL CS:Fopen_lookup
; LOOKUP ;AN000;
432 jmp short exit
;AN000;
434 cmp al, FONC_delete
;AN000;
435 jne Error_Exit
;AN000;
436 CALL CS:Fopen_delete
; DELETE ;AN000;
437 jmp short exit
;AN000;
441 ;-----------------------------------------------------------------------------
442 ; EXIT TO DOS FROM FUNCTIONS
443 ;-----------------------------------------------------------------------------
445 ERROR_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
450 cmp al,FSK_Lookup
;AN000;
452 mov di,1 ; set error flag - invalid drive id ;AN000;
454 jmp short Exit_1
;AN000;
458 jmp short Exit_1
;AN000;
461 ; Normal Exit from Fastopen Functions except Fastseek Lookup function
463 CALL RESTORE_PAGE_STATE
; restore EMS page state ;AN000;;AN000;
464 pop bx ; restore BX ;AN000;
465 pop di ; restore DI ;AN000;
468 ; Exit from FastSeek Lookup function. Dont restore BX and DI
470 pop bp ; restore remaining DOS registers
471 pop es ; except BX and DI since they contain ;AN000;
472 pop ds ; return values. ;AN000;
482 ;---------------------------------------------------------------------------
483 ; Procedure name : save_ems_page_state
486 ; Saves the state of the page whose physical segment value is
487 ; specified in Main_EMS_PAGE_SEG.
488 ;---------------------------------------------------------------------------
490 SAVE_EMS_PAGE_STATE PROC
FAR
492 PUSH AX ; save registers
502 MOV AX, SEG EMS_PAGE_MAP
; get segid
504 LEA SI,EMS_PAGE_MAP
; DS:SI-->page map struc
505 MOV AX, SEG EMS_PAGE_ARRAY
; get segid
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;
531 SAVE_EMS_PAGE_STATE ENDP
536 ;-----------------------------------------------------------------------------
537 ; PROCERDURE: RESTORE_PAGE_STATE
539 ; Function: Restore state of EMS page
542 ; Output: Page is restored
544 ;-----------------------------------------------------------------------------
546 RESTORE_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
553 PUSH AX ; save function code
554 PUSH CX ; save caller registers ;AN000;
563 MOV AX, SEG EMS_PAGE_ARRAY
565 LEA SI,EMS_PAGE_ARRAY
; DS:SI-->Page array
566 MOV AH,EMS_RESTORE_STATE
;
568 INT EMS_INT
; restre page state ;AN000;
569 CMP AH,0 ; restore OK ??
570 JE REST_POP_REGS
; yes
574 POP BX ; RESTORE REGISTERS ;AN000;
582 POP AX ; restore function code
588 RESTORE_PAGE_STATE ENDP
593 ;---------------------------------------------------------HKN 8/26/88-------
594 ; procedure name : map_page
595 ; Inputs : ems_page_number = physical page frame
597 ; ems_save_handle1 = emm_handle.
598 ; Output : CY - error
599 ; NC - page is mapped to logical page 0
600 ;----------------------------------------------------------------------------
608 mov ax, cs:ems_page_number
; contains the page number obtained
609 ; during fastopen intialization.
611 mov dx, cs:ems_save_handle1
; contains the emm handle that was
612 ; obtained during fast init.
617 jmp short map_page_done
634 CSEG_MAIN ENDS
; End of the first portion of the
635 ; Cseg_Main segment. Remaining
636 ; portion is in Fastinit.asm
638 ;-----------------------------------------------------------------------------
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
653 ;*****************************************************************************
654 CSEG_OPEN
SEGMENT PARA
PUBLIC 'code'
655 ASSUME
cs:cseg_open
,ds:nothing
,es:nothing
,ss:nothing
656 ;*****************************************************************************
658 PUBLIC Open_name_cache_seg
;AN000;
659 PUBLIC Open_name_Drive_Buff
;AN000;
660 PUBLIC End_Open
;AN000;
661 PUBLIC Chk_Flag
;AN000;
663 ;---- FastOpen Functions Local Variables --------------
665 Current_Node
DW ?
;address of current node entry buffer ;AN000;
666 Current_Sibling
DW ?
;address of current sibling node entry buffer ;AN000;
667 Current_Drive
DW ?
;address of current drive header ;AN000;
668 Matching_Node
DW -1 ;flag ;AN000;
669 From_Delete
DW 0 ;= 1 if call is from DELETE function ;AN000;
670 Old_SI
DW 0 ;SI save area ;AN000;
672 Level
DB 0 ;depth level of the path ;AN000;
673 Dir_Info_Buffer
DD ?
;Dir_Info buffer inside DOS ;AN000;
674 Extended_Info_Buffer
DD ?
;Extended Info buffer inside DOS ;AN000;
675 New_FEI_clusnum
DW 0 ;AN000;
676 Packed_Name
DB 11 dup (0) ;Space for packed dir name ;AN000;
682 Chk_Flag dw 0 ; flag used by the analyser
683 func_cod db 0 ; function code for analyser
685 ;Following data area is filled during initialization
686 Open_name_cache_seg
DW Cseg_Init
; address of name cache buffer
687 Open_name_Drive_Buff
DW 0 ; address of first drive buffer
693 ;==============================================================================
694 ; Pathname Tree Search
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
711 ;==============================================================================
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
722 ; If the whole path is found,
724 ; ES:DI--> DIR_INFO buffer is filled with directory info
725 ; ES:CX--> EXT_INFO buffer is filled with extended info
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
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
737 ;==============================================================================
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
746 jmp short Look_save_regs
;save registers
749 CALL PACK_DIR_NAME
;on return drive letter => DL,
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
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.
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
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
775 CALL PACK_DIR_NAME
;get the next dir name from the path
776 jc Lookup_Done
;yes, found the whole path.
778 test cs:Flag
, Is_drive_head
;dir name = drive header ?
781 push ds ;yes-drive header
782 mov ds,cs:Open_Name_Cache_Seg
784 mov BP, DS:[BP.DCH_Child_ptr
] ;BP-->first child node under drive hdr
790 mov BP, ES:[BP.nChild_ptr
] ;BP--> child of current node
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.
799 CALL CMPARE
;look for path in current node
800 je Lookup_Found
;Yes, found a match. Next level for
801 ;possible remianing path
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
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
813 mov cs:Matching_Node
,BP ;Used by Unfold_Name_Record
815 CALL PRE_LRU_STACK
;set the TEMP_LRU_Stack
816 jmp Lookup_Path
;continue to the next dir
820 pop cx ;restore Extended_Info buffer
821 pop di ;restore Dir_Info buffer
822 pop es ;the segment for the above buffers
825 je Lookup_ERR
;error occured in Pack_Dir_Name.
827 jmp short Lookup_Done1
829 Lookup_ERR: ;error exit
833 test cs:Flag
, is_delete
;called by delete?
835 jc Lookup_Exit
;If it was an error, don't change the carry flag
837 CALL UNFOLD_NAME_RECORD
;unfold the current node's record
839 jmp short Lookup_Return
;return to DOS.
841 Lookup_Error: ;error exit
845 Lookup_Return: ;return to Delete routine.
846 CALL Check_It
;check tree structure
855 ;==============================================================================
858 ;INPUT: DS:DI -> Dir_Info in DOS
859 ; ES:BX -> Fastopen_Extended_Info in DOS
860 ; Current_Node, Current_Sibling, Current_Drive, Flag
862 ;OUTPUT: Information inserted into Name_cache_tree.
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.
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
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.)
890 ;==============================================================================
893 mov cs:func_cod
,al ; save function code
894 inc cs:Level
;increment directory level
898 mov bp, cs:Current_Drive
;BP-->address of current drive header
900 mov ds,cs:Open_Name_Cache_Seg
;DS=name cache segment
902 ASSUME
ds:Cseg_Init
;AN000;
903 cmp ax, ds:[bp.DCH_Num_Entries
] ;Level > (Num_Entries - 1) ?
906 jbe Insert_it
;no- insert it
907 jmp short Insert_return
;yes return
910 or cs:Flag
, is_insert
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.
916 CALL MAKE_NAME_RECORD
;Fill the above name record entry.
917 ;ES was changed to Name_Cache_Seg.
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
926 I_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
932 I_Child_first: ;this is the first child in this drive.
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
939 mov bx, cs:Current_Drive
;change bx to Current_Drive
940 and cs:Flag
, Not_drive_head
;reset the flag
944 mov es:[bp.nBackward_ptr
],bx ;set the backward ptr of the inserted node.
946 CALL PRE_LRU_STACK
;save this inserted record temporarily.
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
953 and cs:Flag
, not_insert
;set not insert flag
956 CALL Check_It
;check tree structure
966 ;==============================================================================
969 ;INPUT: DS:SI -> path
970 ; ES:BP -> drive_cache_header (for Look_Up operation)
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.
976 ;==============================================================================
980 mov cs:func_cod
,al ; save function code
981 CALL PACK_DIR_NAME
;drive letter => DL, ;AN000;
983 CALL FIND_DRIVE_CACHE_HEADER
;find drive header address
984 ;on return ES:BP-->drive header
985 jc d_err_exit
;error exit
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
992 mov ds,ax ;DS=Main segment ID
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
998 mov cs:From_Delete
, 0 ;reset from delete flag
1001 jc D_err_Exit
;indirectly in the same segment
1003 cmp byte ptr ds:[si], 0 ;found the whole path?
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.
1012 cmp es:[bp.nChild_ptr
], -1 ;No children?
1014 CALL REMOVEFROMTREE
;remove the node while maintaing the
1015 ;integrity of the tree.
1017 mov es:[bp.nCmpct_Dir_Info
], ' ' ;mark that this entry is free!!!
1020 CALL REMOVEFROMLRUCHAIN
;Remove BP from the LRU,MRU chain
1022 mov si, cs:Current_Drive
;Now let the deleted node to be the
1024 mov ds,cs:Open_Name_Cache_Seg
1025 ASSUME
ds:Cseg_Init
;AN000;
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
1034 jmp short D_Exit
;exit
1036 D_err_Exit: ;error exit
1041 and cs:Flag
, not_delete
;reset the flag
1042 CALL Check_It
;check tree structure
1051 ;==============================================================================
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, ...).
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.
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.
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)
1076 ;OUT: if found, then data is updated
1077 ; else CY and AX = -1.
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
1088 ;==============================================================================
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-
1102 U_ERROR: ;no - error exit
1104 jmp short Update_Exit
1106 Update_Delete: ; same as delete
1107 CALL FIND_CLUSTER_NUMBER
; find name entry using first cluster
1109 jmp Delete_Node
; if found, delete entry
1111 Update_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
1117 mov cx, es:[di.dir_first
]
1118 push es ;save Dir_Info pointer ES:DI
1120 CALL FIND_CLUSTER_NUMBER
1121 pop si ;restore Dir_Info pointer in DS:SI
1123 jc U_ERROR
;error-if not found
1125 push bp ;found the entry
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
1135 Update_Extended_clusnum: ;update extended info field
1136 mov cs:New_FEI_clusnum
,bp
1137 CALL FIND_CLUSTER_NUMBER
;Find entry based first cluster number
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
1145 CALL Check_It
;check tree structure
1155 ;==============================================================================
1156 ;Subroutine: FP_PURGE Rest Name Cache Buffers
1158 ;INPUT: Main_Name_Drive_Buff - Offset to Name cache buffer
1159 ; Main_Name_Cache_Seg - Name cache seg id
1162 ;OUT: Buffer is purged
1164 ;==============================================================================
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
1174 ; Search for the name drive header corresponds to the drive letter
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
1181 Purge_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
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
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
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
1208 pop ax ; AX = last name record address
1211 dec cx ;update record count
1212 jcxz purge_exit
;exit if last name record is done
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
1227 ;----------------------------------------------------------------------------
1228 ; FASTOPEN SUPPORT ROUTINES
1229 ;----------------------------------------------------------------------------
1231 ; PROCEDURE: Find_Drive_Cache_Header
1233 ; Function: Validate drive ID and find address of drive cache header
1235 ;IN: DL - drive letter
1236 ; Drive_Header_Start ;label
1239 ;OUT: If CY = 0 Drive Header found
1240 ; ES:BP -> Drive_Cache_Header,
1242 ; If CY = 1 Drive Header not found
1244 ;----------------------------------------------------------------------------
1246 FIND_DRIVE_CACHE_HEADER PROC
NEAR
1248 mov bp, cs:Open_name_drive_buff
1250 mov ds,cs:Open_Name_Cache_Seg
;AN000;
1251 ASSUME
ds:Cseg_Init
;DS:BP-->first drive header ;AN000;
1254 cmp byte ptr ds:[bp.DCH_Drive_Letter
], dl ; drive letter match
1255 jne fdch_chk_end
; no - check next header
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
1268 FDCH_Exit: ;ES:BP-->header if found
1270 ASSUME
ds:nothing
;return
1273 FIND_DRIVE_CACHE_HEADER endp
1278 ;----------------------------------------------------------------------
1279 ; PROCEDURE: GET_FREE_NODE
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
1286 ; IN: Current_Drive, Current_Node
1288 ; OUT: AX = offset of the free node in Name_Cache_Seg
1289 ; Other registers saved.
1290 ;----------------------------------------------------------------------
1292 GET_FREE_NODE PROC
NEAR
1294 push es ;save registers
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
1304 mov ds,cs:Open_Name_Cache_Seg
1306 mov ax, ds:[si.DCH_LRU_ROOT
] ;get the LRU node
1310 cmp ax, cs:current_Node
;LRU node=Current Node ??
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
1317 mov ds,cs:Open_Name_Cache_Seg
;DS=Name cache segment
1319 mov ds:[si.DCH_LRU_ROOT
],di ;connect previous node to
1323 cmp byte ptr es:[bp.nCmpct_Dir_Info
],' ';an empty node?
1324 je GFN_OK
;then no problem.
1326 CALL RemoveFromTree
;otherwise, it should be removed
1348 ;----------------------------------------------------------------------
1349 ; PROCEDURE: PRE_LRU_STACK
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;
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;
1364 ; else if Depth >= 3 then Temp = Top;
1366 ; Top.LRU_ptr = Temp;
1367 ; Temp.MRU_ptr = Top;
1371 ;IN: Depth, Top, Bottom, Temp,
1372 ; Requested target node (BP)
1373 ; ES = Name_Cache_Seg
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 ;----------------------------------------------------------------------
1382 PRE_LRU_STACK PROC
NEAR
1384 test cs:Flag
, is_delete
;invoked by Delete routine
1386 test cs:Flag
, is_insert
;called by Insert routine
1389 CALL RemoveFromLRUChain
;remove BP from the chain.
1397 mov cs:Bottom
, bp ;bottom = bp
1398 mov es:[bp.nLRU_ptr
], -1
1404 mov cs:Top
, bp ;Top = bp
1405 mov di, cs:bottom
;di = bottom
1408 mov es:[bp.nLRU_ptr
],di ;Top.LRU_ptr = bottom
1409 mov es:[di.nMRU_ptr
],bp ;Bottom.MRU_ptr = top
1413 mov di, cs:Top
;di = Top
1414 mov cs:Temp
, di ;Temp = di
1415 mov cs:Top
, bp ;Top = bp
1419 mov es:[bp.nMRU_ptr
],-1
1432 ;----------------------------------------------------------------------
1435 ;INPUT: Depth, Top, Bottom, Current_Drive, ES = Name_Cache_Seg
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;
1451 ;----------------------------------------------------------------------
1455 cmp cs:Depth
, 0 ;nothing in the stack?
1461 mov si, cs:Current_Drive
;cs:si -> Drive_Cache_Header
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
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
1476 SL_Other: ;Depth >= 2
1478 mov es:[di.nLRU_ptr
],bx
1479 mov es:[bx.nMRU_ptr
],di
1481 mov ds:[si.DCH_MRU_ROOT
],bx
1486 mov cs:Depth
, 0 ;reset the Depth
1500 ;----------------------------------------------------------------------
1501 ; Procedure RemoveFromLRUChain
1503 ;IN: Target node (BP) to be removed
1505 ; ES - Name_Cache_Seg
1507 ;OUT: Target node removed from the LRU,MRU chain. LRU,MRU chain
1510 ;----------------------------------------------------------------------
1512 RemoveFromLRUChain PROC
near
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?
1523 cmp di, -1 ;Is target the last node of LRU chain?
1525 mov es:[bx.nLRU_ptr
],di ;Preceding.LRU_ptr->following node
1526 mov es:[di.nMRU_ptr
],bx ;Following.MRU_ptr->preceding node
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
1536 mov es:[di.nMRU_ptr
], -1 ;Following node's MRU_ptr
1541 mov ds,cs:Open_Name_Cache_Seg
1543 mov ds:[si.DCH_MRU_ROOT
],bx ;MRU_ROOT-> preceding node
1544 mov es:[bx.nLRU_ptr
], -1 ;Preceding node's LRU_ptr
1554 RemoveFromLRUChain endp
1559 ;----------------------------------------------------------------------
1560 ; Proceure RemoveFromTree
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
1567 ;OUT: The node will be freed from the tree.
1568 ; The neighbor's Child_ptr, Sibling_ptr, Backward_ptr are adjusted
1570 ; The freed node's child_ptr, sibling_ptr, backward_ptr are reset to -1.
1571 ;----------------------------------------------------------------------
1573 REMOVEFROMTREE PROC
NEAR
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
1590 mov ds,cs:Open_Name_Cache_Seg
;AN000;
1591 ASSUME
ds:Cseg_Init
;AN000;
1592 mov ds:[bx.DCH_Child_ptr
],dx
1598 mov es:[bx.nChild_ptr
],dx
1600 RFT_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
1605 xchg dx,bx ;now, dx=preceding node, bx=following node
1606 cmp bx,-1 ;end of sibling?
1608 mov es:[bx.nBackward_ptr
],dx;modify backward_ptr of the sibling node
1621 ;----------------------------------------------------------------------
1627 ;OUT: ZERO flag set when compare O.K.
1629 ;----------------------------------------------------------------------
1638 mov si, offset
cs:Packed_Name
;ds:si -> Packed_Name
1640 add di,nCmpct_Dir_Info
;es:di -> bp.nCmpact_Dir_Info
1651 ;----------------------------------------------------------------------
1652 ; Procedure: MAKE_NAME_RECORD
1654 ;IN: DS:DI -> Dir_Info, ES:BX -> Extended_Info
1655 ; AX = offset of the Name_Record entry in Name_Cache_Seg.
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 ;----------------------------------------------------------------------
1662 MAKE_NAME_RECORD PROC
NEAR
1667 push es ;save Extended_Info seg in DOS
1669 pop si ;DS:SI -> Dir_Info
1670 mov di, cs:Open_Name_Cache_Seg
;AN000;
1672 ASSUME
es:Cseg_Init
;AN000;
1673 mov di, ax ;ES:DI -> Name_Record
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.
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
1695 MAKE_NAME_RECORD ENDP
1701 ;----------------------------------------------------------------------
1702 ; Procedure Unfold_Name_Record
1704 ;IN: Matching_Node, ES:DI -> Dir_Info buffer, ES:CX -> Extended_Info buffer
1706 ;OUT: if no matching node is found, then just return
1707 ; else Dir_Info, Extended_Info buffer are filled.
1708 ;----------------------------------------------------------------------
1710 Unfold_Name_Record PROC
near
1712 cmp cs:Matching_Node
, -1
1713 je UNR_Exit
;just exit
1717 push cx ;save extended_info addr
1719 mov si, cs:Open_Name_Cache_Seg
;AN000;
1721 ASSUME
ds:Cseg_Init
;AN000;
1722 mov si, cs:Matching_Node
1723 add si, nCmpct_Dir_Info
;DS:SI -> Cmpct_Dir_Info
1725 mov cx, ODI_head_leng
;Dir_Info header length
1726 REP MOVSB ;Cmpct_Dir_Info.CDI_file_name -> ODI_head
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
1733 pop di ;ES:DI -> Extended_info
1734 push di ;save di again for cx.
1735 mov cx, size Fastopen_Extended_Info
1738 pop cx ;restore extended_info addr
1746 Unfold_Name_Record endp
1752 ;----------------------------------------------------------------------
1753 ; PROCEDURE: PACK DIR_NAME
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 ;----------------------------------------------------------------------
1767 PACK_DIR_NAME PROC
NEAR
1769 cmp byte ptr ds:[si], 0 ;end of path ??
1770 jne PDN_Drive
;no-check for drive letter
1772 jmp short PDN_Exit
;yes-exit
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
1779 inc si ;set SI -> '\' after ':'
1780 jmp short PDN_Exit
;then exit
1783 cmp byte ptr ds:[si], '\' ;delimeter?
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.
1792 PDN_Path: ;pack path name
1799 mov di, offset cs:Packed_Name ;ES:DI-->pack buffer
1802 STOSB ;blank out the Packed_Name
1808 mov di, offset cs:Packed_Name
1811 LODSB ;DS:SI => AL, SI++
1819 jmp short PDN_GetName
1822 mov di, offset
cs:Packed_Name
+8
1836 dec si ;set SI back to the delimeter or 0.
1850 ;----------------------------------------------------------------------
1851 ; PROCEDURE: FIND_CLUSTER_NUMBER
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.
1858 ;OUT: ES = Name_Cache_Seg
1860 ; if not found, carry bit.
1861 ; ES, BP register changed.
1862 ;----------------------------------------------------------------------
1864 FIND_CLUSTER_NUMBER PROC NEAR
1869 add dl, 'A
' ;convert to a drive letter
1871 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1872 jc FCN_exit ;exit if not found
1874 mov dx, cx ;save the key in DX ;AN000;
1875 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1879 CALL SET_LRU ;clean up the LRU stack
1881 mov cs:Current_Drive,bp ;set Current_Drive (You should not set
1882 ;Current_Drive before SET_LRU at any time!!!
1884 mov ds,cs:Open_Name_Cache_Seg
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
1892 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1893 je FCN_not_found ;then no reason to continue search.
1895 cmp dx, es:[bp.nCmpct_Dir_Info.CDI_cluster] ;matching starting cluster # ?
1896 je FCN_exit ;found it!!!
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...
1912 FIND_CLUSTER_NUMBER ENDP
1917 ;----------------------------------------------------------------------
1918 ; PROCEDURE: FIND_DIR_SECTOR (PTR 3718 3/10/88)
1920 ; Search Name_Record using directory sector and directory position
1921 ; for the name entry.
1923 ;IN: DL = driver # (0 = A, 1 = B,...)
1924 ; DI = Dirctory sector Low value
1925 ; CX = Dirctory sector high value
1926 ; DH = Dirctory position
1928 ;OUT: ES = Name_Cache_Seg
1930 ; if not found, carry bit.
1931 ; ES, BP register changed.
1932 ;----------------------------------------------------------------------
1934 FIND_DIR_SECTOR PROC NEAR
1939 add dl, 'A
' ;convert to a drive letter
1941 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1942 jc FDIR_exit ; error if not found
1944 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1948 CALL SET_LRU ;clean up the LRU stack
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!!!
1954 mov ds,cs:Open_Name_Cache_Seg
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
1962 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1963 je FDIR_NOT_FOUND ;then no reason to continue search.
1965 cmp di, word ptr es:[bp.nExtended_Info.FEI_dirsec] ;matching directory sector hi?
1966 jne FDIR_Next ;check next entry
1968 cmp ax, word ptr es:[bp.nExtended_Info.FEI_dirsec+2] ;matching directory sector low ?
1969 jne FDIR_Next ;check next entry
1971 cmp dh, es:[bp.nExtended_Info.FEI_dirpos] ;matching directory postion ?
1972 je FDIR_Exit ;check next entry
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...
1980 FDIR_Not_found: ; no found
1989 FIND_DIR_SECTOR ENDP
1995 ;--------------------------------------------------------------------------
1996 ; Procedure: CHECK_IT Call Fastopen Tree Analyser to check the
1997 ; consistency of the Directory/File Tree strucutre.
1998 ;--------------------------------------------------------------------------
2001 pushf ; save all registers
2010 cmp cs:Chk_flag,0 ;Fastopen analyser enabled ??
2011 je Check_Exit ;no - exit
2013 mov ax,cs:Open_Name_Cache_Seg ;yes-set multiplex function call
2015 mov ah,091h ;load Multiplex ID
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
2023 pop es ;restore all registers
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;