Page 84,132 ; Title FASTOPEN ;--------------- INCLUDE FILES ----------------- .xcref .xlist debug=0 ;this is an equate only for DOSMAC.inc INCLUDE DOSMAC.inc .list .cref INCLUDE dirent.inc INCLUDE fastsegs.inc ; Cannot declare this in DOS includes INCLUDE fastopen.inc ; This include file also contains DOS equates CSEG_MAIN SEGMENT PARA PUBLIC 'CODE' ; Cseg_Seek segment EXTRN VECTOR_DELETE:dword ; jump vector inside Cseg_Seek to make ; a FAR call to FSeek Delete function within ; the segment CSEG_MAIN ENDS ;***************************************************************************** ; ALL FastSeek functions are kept in a seperate segment. They are accessed ; by a FAR indirect call from the MAIN routine. ; ADDRESSABILTY: DS is for accessing local data in Cseg_Seek segment ; ES is for accessing data in the extent cache buffer ; in the Cseg_Init segment ; On entry, only DS is set, ES is set to Cache segment later ;***************************************************************************** CSEG_SEEK SEGMENT PARA PUBLIC 'code' assume cs:cseg_seek,ds:nothing,es:nothing,ss:nothing PUBLIC Seek_name_cache_seg ;AN000; PUBLIC Seek_Num_Of_drives PUBLIC Seek_extent_drive_Buff ;AN000; PUBLIC Seek_Total_Ext_Count ;AN000; PUBLIC Seek_Total_Name_Count ;AN000; PUBLIC Seek_Name_Drive_Buff ;AN000; PUBLIC Seek_Name_Cache_Buff ;AN000; PUBLIC End_Seek PUBLIC Check_Flag ;AN000; PUBLIC Fk_Open PUBLIC Fk_Close ;AN000; PUBLIC Fk_Insert ;AN000; PUBLIC Fk_Delete PUBLIC Fk_Lookup ;AN000; PUBLIC Fk_Truncate PUBLIC Fk_Purge ;;---------- FASTSEEK LOCAL VARIABLES --------------------- First_Phys_ClusNum dw 0 ; first phys clus num of file (file id) ;AN000; Logical_ClusNum dw 0 ; logical cluster num to be searched ;AN000; Physical_ClusNum dw 0 ; physical clus num of above logical clus num ;AN000; Extent_buff_Ptr dw 0 ; starting offset of extent cache ;AN000; drv_id db -1 ; drive id of last fastseek function func_cod db 0 ; function code Cur_Hdr_Ptr dw 0 ; address of current header ;AN000; Cur_Extn_Ptr dw 0 ; address of current extent ;AN000; New_Extn_Ptr dw 0 ; address of area where new extent will be created New_Hdr_Ptr dw 0 ; address of area where new header will be created ;AN000; Prev_Hdr_Ptr dw 0 ; address of previous header ;AN000; Prev_Extn_Ptr dw 0 ; address of previous extent ;AN000; Prev_MRU_Extn_Ptr dw 0 ; address of previous MRU extent ;AN000; LRU_Prev_Hdr dw 0 ; address of previous hdr to the LRU header ;AN000; LRU_Prev_Extent dw 0 ; address of previous extent to LRU extent ;AN000; LRU_Extent dw 0 ; address of LRU extent ;AN000; LRU_Hdr dw 0 ; address of LRU header ;AN000; Drive_Hdr_Ptr dw 0 ; address of drive header of current drive ;AN000; From_FreeBuff dw 0 ; 1 = if call from Free_Buff routine ;AN000; Hdr_Flag dw 0 ; 1 = current header is the only ; remaining header in Queue Extn_Flag dw 0 ; 1 = current extent is the only ;AN000;;AN000; ; remaining extent under this header Fully_Flag dw 0 ; 1= cluster fully found in extent ;AN000;;AN000; ; 0= cluster partially found Find_Flag dw 0 ; # = specifies the relative location of the new cluster ;AN000; Open_Queue_Flag dw 0 ; 1 = if open queue is empty ;AN000; Free_Flag dw 0 ; Free area Type: 0 - continuous ;AN000; ; 1 - non-continuous Queue_Type dw 0 ; Queue Type: 0 - Open Queue ;AN000; ; 1 - Close Queue phys_num dw 0 ; ** for queue analyser logic_num dw 0 ; ** for queue analyser ; Following data area is initialized during initialization Check_Flag dw 0 Seek_name_cache_seg dw Cseg_Init ; Seg ID of Ccahe buffer Seek_Num_Of_drives dw 0 ; number of drives ;AN000; Seek_Total_Name_Count dw 0 ; total name count Seek_Total_Ext_Count dw 0 ; total extent count Seek_Name_Drive_Buff dw 0 ; starting address of name drive buffers ;AN000; Seek_Name_Cache_Buff dw 0 ; starting address of name cahe buffers ;AN000; Seek_extent_drive_Buff dw 0 ; starting address of extent ;AN000; ; cache in the cache buffer ;------------------------------------------------------------------------------- ;------------------------------------------------------------------------------- ; PROCEDURE: FK_OPEN ; ; FUNCTION: Create and initialize a file header using the starting ; Physical Cluster number (file id) of the file. ; ; If the file header already exist in the OPEN Queue, then increase ; the file reference count by one and make the header ; MRU header. ; ; If header is not found in the OPEN Queue, then check to ; see if it exists in the CLOSE Queue. If found in the ; CLOSE Queue, move the header and the extents to the top of ; OPEN Queue and make the header MRU header. ; ; If the header is not found in both Queues, create a new ; header at the top of the OPEN Queue and initialize with the ; given first physical cluster number. ; ; If not enough space for new header in OPEN Queue, find the ; LRU header and Last Exetent in the CLOSED Queue. Delete this ; extent and use the space for the new header. If none in ; CLOSE Queue, find the LRU header and the LRU extent in the ; OPEN Queue. Delete this extent and use this space. ; ; ; INPUT: CX = First Physical Cluster Number of the file ; DL = Drive ID ; ; ; OUTPUT: Created a new file header. If header already exist, then the file ; reference count is incremented by one. ; ; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;------------------------------------------------------------------------------- FK_OPEN PROC FAR push cs ; establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov First_Phys_Clusnum,cx ; save physical cluster number ;AN000; mov func_cod,al ;------------------------------------------------------------------------------- ; Search for Drive header in the cache buffer using Drive ID in DL ;------------------------------------------------------------------------------- CALL FIND_DRIVE_HEADER ; get drive buffer Header ;AN000; ; DI-->drive header jnc open_Search_Header ; header found - check for file header ;AN000; jmp open_exit ; drive header not found - exit ;AN000; ;------------------------------------------------------------------------------ ; Check if both OPEN and CLOSE Queues are empty. If empty, create a new ; file header at the top of OPEN Queue. If there are headers, search OPEN ; queue. If found, increment file count by one. If not found, check if ; the file header exists in CLOSE Queue. If found, move header to the ; top of the OPEN Queue. ;------------------------------------------------------------------------------ Open_Search_Header: inc es:[di].Extent_Count ; increment sequence count ( DEBUG) mov ax,es:[di].Buff_Size ; total buffer size equal ;AN000; cmp es:[di].Free_Size,ax ; to current free area ;AN000; jne Search_Open_List ; yes, check OPEN and CLOSE Queues ;AN000; ; for header jmp Open_Make_Hdr ; no, make new header ;AN000; ;------------------------------------------------------------------------------ ; Search for header in the OPEN Queues. If found, increment file reference ; count by one. ;------------------------------------------------------------------------------ Search_Open_List: mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; mov si,es:[di].MRU_Hdr_Ptr ;AN000; cmp si, -1 ; Any header in OPEN Queue ?? ;AN000; je Open_Chk_Close_list ; none, check CLOSE Queue ;AN000; CALL FIND_FILE_HEADER ; search header in OPEN Queue ;AN000; jc Open_chk_CLOSE_list ; if not found check in CLOSE Queue ;AN000; ;------------------------------------------------------------------------------ ; Found in the OPEN Queue. Now, increment the file reference count by one ; and also make the header MRU header. If header found is LRU header then ; make previous header LRU header. If header is not LRU header, connect ; previous header to next header. If the header is the first header in the ; Queue, dont make it to MRU header since it is already at the top of Queue. ;------------------------------------------------------------------------------ ; DI-->Header found inc es:[di].FH_refer_Count ; increment file reference count ;AN000; cmp Hdr_Flag, 1 ; current header Single header ?? ;AN000; jne Open_Chk_Last_Hdr ; No, Check for last header ;AN000; clc ; make sure caary is clear jmp Open_Exit ; yes, exit ;AN000; Open_Chk_Last_Hdr: cmp Hdr_Flag, 3 ; current header LRU header ?? ;AN000; jne Open_Join_Gap ; no, close the gap ;AN000; Mark_Previous_Hdr: ; yes - mark previous hdr mov si, Prev_Hdr_Ptr ;AN000; mov es:[si].FH_Next_Hdr_Ptr,-1 ; yes, Mark previous Hdr LRU hdr ;AN000; ; Make current Hdr MRU header. No need to close the gap CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000; clc ; make sure caary is clear jmp Open_Exit ; then EXIT ;AN000; ;----------------------------------------------------------------------------- ; Comes here if current header is first of many headers or in between a previous ; and next header. Make current header MRU header and close the gap. ;----------------------------------------------------------------------------- Open_Join_Gap: ; DI-->Current header cmp Hdr_Flag, 2 ; current Header First Hdr in Queue ?? ;AN000; jne Open_Make_MRU_Hdr ; no, jump ;AN000; clc ; MAKE SURE caary is clear jmp Open_Exit ; yes, no need to make MRU hdr, or ;AN000; ; or close the gap Open_Make_MRU_Hdr: ; header is between 1st and last headers CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000; clc ; make sure caary is clear jmp Open_exit ; then EXIT ;AN000; ;------------------------------------------------------------------------------ ; Look for a header in the CLOSE Queue. If found, move file header and ; and extents (if any) to top of OPEN Queue. If not found in the CLOSE ; queue, create a new header at the top of OPEN queue. ;------------------------------------------------------------------------------ Open_Chk_Close_List: mov di,drive_Hdr_Ptr ; DI-->current drive header ;AN000; cmp es:[di].CLOSE_Ptr,-1 ; anything in CLOSE Queue ?? ;AN000; jne open_search_hdr ; if any, search CLOSE Queue ;AN000; jmp open_make_hdr ; if none, make a new header ;AN000; ;------------------------------------------------------------------------------ ; CLOSE Queue is not empty, next search for header in the CLOSE Queue using ; starting physical cluster number of the file. ;------------------------------------------------------------------------------ Open_Search_Hdr: ; mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000; ; in the CLOSE Queue ;AN000; mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; CALL FIND_FILE_HEADER ; find file header in CLOSE Queue ;AN000; ; DI-->header found jnc open_chk_only_hdr ; if found, check only header ;AN000; jmp short open_make_hdr ; if not, make a new header ;AN000; ;------------------------------------------------------------------------------ ; Found header in the CLOSE Queue. Check if the header found is the single HDR ; in the CLOSE Queue, If single header, then, mark the CLOSE Queue as empty ; before copy the this header to the OPEN Queue. ;------------------------------------------------------------------------------ Open_Chk_only_Hdr: ; cmp Hdr_flag, 1 ; Only Header in the CLOSE Queue?? ;AN000; jne Open_chk_Last_header ; if not check header is LRU header ;AN000; mov di,Drive_Hdr_Ptr ; only header in the CLOSE Queue ;AN000; mov es:[di].Close_Ptr,-1 ; mark CLOSE Queue as empty ;AN000; jmp short Open_Move_Hdr ; then move header to OPEN Queue ;AN000; ;------------------------------------------------------------------------------ ; Current header is not the only header in the CLOSE Queue. Now check if the ; current header is the LRU header in CLOSE Queue. If true, mark previous ; header as LRU header before moving it from from CLOSE Queue to OPEN queue. ;------------------------------------------------------------------------------ Open_Chk_Last_Header: ; cmp Hdr_Flag, 3 ; Current header last header ?? ;AN000; jne Open_Close_gap ; no, close the gap before move it ;AN000; ; to OPEN Queue mov si, Prev_Hdr_Ptr ;AN000; mov es:[si].Fh_Next_Hdr_Ptr,-1 ; yes, mark the previous hdr as last ;AN000; jmp short open_move_Hdr ; header then move to the top of ;AN000; ; OPEN Queue ;------------------------------------------------------------------------------ ; Close the gap in the CLOSE Queue. ;------------------------------------------------------------------------------ Open_Close_Gap: mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000; CALL JOIN_PREV_TO_NEXT ; join previous header to next header ;AN000; ;------------------------------------------------------------------------------ ; Now move the current header from CLOSE Queue to top of OPEN Queue ;------------------------------------------------------------------------------ Open_Move_Hdr: mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; mov di,drive_Hdr_Ptr ; DI-->drive header ;AN000; ;------------------------------------------------------------------------------ ;Update the file refernce count to 1 before move header to OPEN Queue ;------------------------------------------------------------------------------ mov es:[si].FH_Refer_Count, 1 ; set refernce count = 1 ;AN000; mov ax,es:[di].MRU_Hdr_Ptr ; address of current MRU header ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; connect new header to the ;AN000; ; current MRU header mov es:[di].MRU_Hdr_Ptr,si ; make the header MRU header ;AN000; clc ;AN000; jmp short open_exit ; then exit. ;AN000; ;------------------------------------------------------------------------------ ; If header is not found in both OPEN and CLOSE Queues, then make a new ; header in the next available free area and initialize the new header and ; make it MRU header (mov it to the top of the OPEN Queue). ; If no free space to create a new header, get space from CLOSE Queue. ; If none in CLOSE Queue, then get space from from OPEN Queue. See the ; Procedure (Find_Free_Buffer ) ;------------------------------------------------------------------------------ Open_Make_Hdr: CALL MAKE_NEW_HEADER ; create new header ;AN000; clc ;AN000; Open_exit: CALL Check_it ret ; return ;AN000; Fk_Open endp ;-------------------------------------------------------------------------- ; PROCEDURE: FK_CLOSE ; ; FUNCTION: Search for the header on OPEN Queue. If the header is found, ; decrement the file reference count by one. If the resultant ; count is zero, then move the header and the extents under it ; to the CLOSE Queue. If not, make the header MRU header in the ; OPEN Queue. ; ; INPUT: DL = Drive Number ; CX = First Physical Cluster Number of the file ; ; OUTPUT: Moved the file header and the extents to the close Queue ; ; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header ; ; REVISION HISTORY: New (5/87) ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;--------------------------------------------------------------------------- FK_CLOSE PROC FAR ;AN000; ; Search for Drive header in the Cache buffer using Drive ID in DL push cs ; establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov First_Phys_Clusnum, CX ; save phys cluster number ;AN000; mov func_cod,al CALL FIND_DRIVE_HEADER ; search for drive header ; DI-->Current drive buffer jnc Close_search_hdr ; found, search for file header ;AN000; clc ; MAKE SURE carry is clear jmp Close_Exit ; not found, error ;AN000; ;-------------------------------------------------------------------------- ; Search for file header in the OPEN Queue using given physical cluster number ;-------------------------------------------------------------------------- Close_Search_Hdr: inc es:[di].Extent_Count ; increment sequence coutn (DEBUG) mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN Queue ;AN000; mov cx,First_Phys_Clusnum ; CX = First phys clus num ;AN000; CALL FIND_FILE_HEADER ; find the header in OPEN Queue ; DI-->header found ;AN000; jnc Close_Chk_Last_Hdr ; jump if header found ;AN000; clc ; clear carry ;AN000; jmp short close_exit ; headr not found - exit ;AN000; ;-------------------------------------------------------------------------- ; Check if the header found is the only header in the OPEN Queue. If true ; go and decrement file reference count by one. ;-------------------------------------------------------------------------- Close_Chk_Last_Hdr: cmp Hdr_Flag, 1 ; Only header in the Queue ?? ;AN000; je Dec_Ref_Count ; yes - decrement count, if count =0 ;AN000; ; then move to the top of CLOSE Queue cmp Hdr_Flag, 3 ; no - Last Header in the CLOSE Queue?? ;AN000; jne Close_Join_Hdr ; no, close gap ;AN000; mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; jmp short Dec_Ref_Count ; decrement count and move to ;AN000; ; CLOSE Queue ;-------------------------------------------------------------------------- ; Connect previous header to next header to close the gap in OPEN Queue ;-------------------------------------------------------------------------- Close_Join_Hdr: mov si,Cur_Hdr_Ptr ; SI-->Current header dec es:[si].FH_Refer_Count ; decrement fiel refernce count cmp es:[si].FH_Refer_Count,0 ; count = 0 ?? jne Close_Make_MRU ; no - make current header MRU header mov Queue_Type, 0 ; else set flag to indicate OPEN Queue ;AN000; CALL JOIN_PREV_TO_NEXT ; close gap before move to CLOSE queue ;AN000; jmp short move_to_Close_List ; move header to CLOSE queue ;-------------------------------------------------------------------------- ; Decrement the reference count by one. If count = 0, then move the header to ; the top of CLOSE Queue. Else, dont move to CLOSE queue, since the file has ; have multiple open before. In this case make the header MRU header in the ; OPEN queue. ;-------------------------------------------------------------------------- Dec_Ref_Count: mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; dec es:[si].FH_Refer_Count ; decrement refernece count ;AN000; cmp es:[si].FH_Refer_Count,0 ; reference count = 0 ?? ;AN000; je Move_to_Close_List ; yes, move header to CLOSE Queue ;AN000; ;-------------------------------------------------------------------------- ; Else, move current Header to top of OPEN Queue. Move to the top of the queue ; only if the header is not the first header in the queue. ;-------------------------------------------------------------------------- Close_Make_MRU: cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000; je Dont_Move_To_Top ; yes, dont move to top ;AN000; CALL MAKE_MRU_HEADER ; move header to top of queue ;AN000; Dont_Move_To_Top: clc ;AN000; jmp short Close_Exit ; exit ;AN000; ;-------------------------------------------------------------------------- ; Move header to the top of the CLOSE Queue. If the header is the only header ; header in the OPEN Queue, mark OPEN Queue empty. ;-------------------------------------------------------------------------- Move_To_Close_List: mov si,Cur_Hdr_Ptr ; SI-->Cur_Hdr_Ptr ;AN000; cmp hdr_flag,1 ; single header in the Queue ?? ;AN000; jne Join_To_Close_List ; no, move header to CLOSE queue ;AN000; mov di,Drive_Hdr_Ptr ;AN000; mov es:[di].MRU_Hdr_Ptr, -1 ; else mark OPEN Queue empty ;AN000; Join_To_Close_List: mov di,Drive_Hdr_Ptr ; DI-->current drive header ;AN000; mov ax,es:[di].Close_Ptr ; connect current header to the ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; previous first hdr in CLOSE queue ;AN000; mov es:[di].Close_Ptr,si ; make the current header first ; header in the CLOSE queue clc ;AN000; Close_Exit: CALL Check_it ret ; return ;AN000; FK_CLOSE ENDP ;------------------------------------------------------------------------ ; ; PROCEDURE: FK_DELETE ; ; FUNCTION: Delete a specific header and extents under the header ; and release the buffers to the FREE pool ; ; Search OPEN Queue for file header. If found, delete header and ; extents and release the buffer to FREE area. If not found in OPEN ; queue, search CLOSE Queue. If found, delete header and extents ; under the header and release the area to FREE area. ; ; INPUT: CX = First Physical Cluster Number of the file ; DL = drive id ; ; OUTPUT: The file header and the extents are deleted ; ; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header ; ; REVISION HISTORY: New (5/87) ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;------------------------------------------------------------------------- FK_DELETE PROC FAR push cs ; establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; mov func_cod,al ;-------------------------------------------------------------------------- ; If the delete call is from Free_Buff, then go straight to file header ; search. Else usual delete request from DOS ;-------------------------------------------------------------------------- cmp From_FreeBuff,1 ; call from Free_Buff routine ?? je Del_Search_Close_List ; yes - find file header in CLOSE queue ;-------------------------------------------------------------------------- ; Search for Drive Cache buffer using Drive ID in DL ;-------------------------------------------------------------------------- CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; jnc Delete_search_hdr ; found, search for file header ;AN000; jmp Delete_Exit ; not found, error ;AN000; ;-------------------------------------------------------------------------- ; Search for a header in the OPEN Queue using given physical cluster number ;-------------------------------------------------------------------------- Delete_Search_Hdr: inc es:[di].Extent_Count ; ;***; mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; ; in the OPEN queue ;AN000; cmp si, -1 ; any header in OPEN Queue ?? ;AN000; je Del_search_Close_list ; none, search CLOSE queue ;AN000; mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000; jnc Del_Open_Last_Hdr ; if found, jump ;AN000; ;-------------------------------------------------------------------------- ; Not found in OPEN queue. Search in CLOSE queue ;-------------------------------------------------------------------------- Del_Search_Close_List: mov di,Drive_Hdr_Ptr ;AN000; mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000; ; in the CLOSE queue cmp si, -1 ; anything in CLOSE Queue ?? ;AN000; jne Del_scan_close_list ; yes, jump ;AN000; clc ; none, header not found ;AN000; jmp delete_exit ; exit ;AN000; Del_Scan_Close_List: mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; CALL FIND_FILE_HEADER ; find the header in CLOSE queue ;AN000; ;AN000; jnc Del_Close_last_hdr ; if found, chk if this header ;AN000; ; is the last header in CLOSE queue clc ; else, set header not found ;AN000; jmp delete_exit ; and then exit ;AN000; ;------------------------------------------------------------------------- ; Header found in CLOSE queue. Check header found is the only single ; header left in the queue. ;------------------------------------------------------------------------- Del_Close_Last_Hdr: cmp Hdr_Flag, 1 ; Single Header in CLOSE Queue ?? ;AN000; jne Del_Chk_LRU_Hdr ; no, check for LRU header ;AN000; ;-------------------------------------------------------------------------- ; Yes, single header in the queue, make CLOSE_PTR empty before delete the ; header from the queue. ;-------------------------------------------------------------------------- mov di,Drive_Hdr_Ptr ;AN000; mov es:[di].Close_Ptr, -1 ; mark CLOSE_Ptr as empty ;AN000; jmp short delete_Free_Buff ; release the deleted header ;AN000; Del_Chk_LRU_Hdr: cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000; jne Del_Join_Hdr ; no, close gap ;AN000; mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; jmp short delete_Free_Buff ; release the deleted header ;AN000; ;-------------------------------------------------------------------------- ; Connect previous header to next header to close the gap in CLOSE Queue ;-------------------------------------------------------------------------- Del_Join_Hdr: mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000; CALL JOIN_PREV_TO_NEXT ; close gap ;AN000; ;AN000; jmp short Delete_Free_Buff ; release header to FREE area ;AN000; ;------------------------------------------------------------------------- ; Header found in OPEN queue. Check header found is the only single ; header left in the queue. ;------------------------------------------------------------------------- Del_Open_Last_Hdr: cmp Hdr_Flag, 1 ; Single Header in OPEN Queue?? ;AN000; jne Del_Chk_Opn_LRU_Hdr ; no, check for LRU header ;AN000; ;-------------------------------------------------------------------------- ; Yes, single header in the queue, mark OPEN Queue empty before delete ;-------------------------------------------------------------------------- ; the header from the queue. mov di,Drive_Hdr_Ptr ;AN000; mov es:[di].MRU_Hdr_Ptr, -1 ; mark OPEN Queue as empty ;AN000; jmp short delete_Free_Buff ; release the delete header ;AN000; Del_Chk_OPN_LRU_Hdr: cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000; jne Del_Opn_Join_Hdr ; no, close gap ;AN000; mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; jmp short Delete_Free_Buff ; release header to FREE area ;AN000; ;-------------------------------------------------------------------------- ; Connect previous header to next header to close the gap in OPEN queue ;-------------------------------------------------------------------------- Del_Opn_Join_Hdr: mov Queue_Type, 0 ; set flag to indicate OPEN Queue ;AN000; CALL JOIN_PREV_TO_NEXT ; close gap ;AN000; ;AN000; ;---------------------------------------------------------------------------- ; Header and extends found. Mark the beginning of this free area with "-2". ; Connect this header to the FREE area. Mark all extnts under this header ; and chain them together through the 4th word. Connect the last extent to ; the OLD free area. This process will effectively release the header to the ; FREE area. Finally update the FREE area size in the Drive header. ; ; NOTE: The deleted buffers have size same as the size of a header or extent. ; Each buffers first location contains a marker (-2) to indicate that ; the buffer is a discontinuous buffer. Each discontinuos buffer is ; connected to the next discontinuous buffer through the 4TH word. ;--------------------------------------------------------------------------- Delete_Free_buff: mov di,Drive_Hdr_Ptr ; SI-->drive header ;AN000; mov si,Cur_Hdr_Ptr ; DI-->current header ;AN000; ;------------------------------------------------------------------------- ; Put (-2) in the beginning of the released area to indicate that this is ; a discontinuous free area. Each Free area is 8 bytes which is same size ; as an extent or header. ;------------------------------------------------------------------------- mov ax,-2 ;AN000; mov es:[si], ax ;AN000; cmp es:[si].FH_Next_Extn_Ptr, -1 ; any extents under this header ?? ;AN000; jne del_look_extent ; yes, jump ;AN000; ;------------------------------------------------------------------------- ; There is no extents under this header. Connect relased header to the ; Free area and update Free area size in drive header before exit. ;------------------------------------------------------------------------- mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000; mov ax,es:[di].Free_Ptr ; connect current header ;AN000; mov es:[si].FH_Next_Hdr_Ptr, ax ; to the Free AREA ;AN000; mov es:[di].Free_Ptr,si ;AN000; mov cx, SIZE File_Header ; start with file header size ;AN000; mov di,Drive_Hdr_Ptr ;AN000; add es:[di].Free_Size,cx ; update free area size ;AN000; clc ; make sure caary is clear jmp short Delete_Exit ; Then exit ;AN000; ;------------------------------------------------------------------------- ; Yes, one or more extents under this header. Connect the header to the ; the first extent through 4th word (FH_Next_Hdr_Ptr). Subsequent free ; extents are connected through the 4th word (EH_Next_Extn_Ptr). Next calculate ; the size of the header and possible extendta and update the free area ; size in the drive header. ;------------------------------------------------------------------------- Del_Look_Extent: mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; mov ax, -2 ; mark header as discontinuous ;AN000; mov es:[si],ax ; free area (12/28) ;AN000; mov cx, SIZE File_Header ; start with file header size ;AN000; mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under this hdr ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; connect this header to first extnt ;AN000; ; through the 4th word ;AN000; mov si,ax ; SI-->First extent ;AN000; mov ax, -2 ; mark first extent as discontinous ;AN000; mov es:[si],ax ; free area ;AN000; Delete_Loop: add cx, SIZE Extent_Header ; add size of extent ;AN000; cmp es:[si].EH_Next_Extn_Ptr, -1 ; current extent last extent ? ;AN000; je Del_Update_Free_Size ; yes - jump (12/28) ;AN000; mov ax,es:[si].EH_Next_Extn_Ptr ; get pointer to next extent ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; connect curr ext to next extent ;AN000; mov si,ax ; SI-->next extent ;AN000; mov ax, -2 ; mark subsequent extents as ;AN000; mov es:[si],ax ; discontinuous free areas ;AN000; jmp Delete_Loop ; adding the size until last extent ;AN000; Del_Update_Free_Size: mov di,Drive_Hdr_Ptr ;AN000; add es:[di].Free_Size,cx ; update free area in drive header ;AN000; ;AN000; ; At this point SI-->Last extent mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; connect last extent under this ;AN000; ; header to the Free area mov ax,Cur_Hdr_Ptr ; AX-->Current header ;AN000; mov es:[di].Free_Ptr,ax ; connect header being deleted to ;AN000; ; the free pool ;AN000; Delete_Exit: clc cmp check_flag,0 jne open_chk_Que clc ret Open_Chk_Que: CALL Check_it ret ; exit ;AN000; FK_DELETE ENDP ;-------------------------------------------------------------------------- ; PROCEDURE: FK_INSERT ; ; FUNCTION: Search for a specific extent using the starting physical ; cluster number and the given logical cluster number. ; Insert the given physical cluster number in the extent ; indexed by the given logical cluster number. If extent is ; not found, create a new extent. If free space is not ; available, take free space free CLOSE or OPEN Queue. ; ; INPUT DL = drive number ; CX = First Physical Cluster Number of the file ; BX = Logical Cluster Number ; DI = Physical Cluster Number ; ; OUTPUT: Physical cluster number is inserted. If extent is not found, ; a new file is created ; ; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_LRU_Header ; ; REVISION HISTORY: New (5/87) ; ;------------------------------------------------------------------------ FK_INSERT PROC FAR push cs ; Establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov first_phys_clusNum,cx ; save cluster numbers ;AN000; mov Logical_ClusNum,bx ;AN000; mov Physical_ClusNum,di ;AN000; mov func_cod,al ; Search for Drive Cache buffer using Drive ID in DL CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; jnc Insert_Search_Hdr ; found, search for file header ;AN000; jmp Insert_Exit ; not found, error ;AN000; ;-------------------------------------------------------------------------- ; If there are no free buffers and there is only a single header in the ; OPEN queue then there is no headers in the CLOSE queue, then the new ; clusters wont be insterted. This is because, file header should not consume ; its own extent if no free space is available. ;-------------------------------------------------------------------------- Insert_Search_Hdr: inc es:[di].Extent_Count ; increment sequence count (DEBUGGING) mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN queue ;AN000; cmp es:[si].FH_Next_Hdr_Ptr, -1 ; only one header in OPEN queue?? je insert_chk_buff ; yes - check free buffer jmp short insert_Inc_count ; no - go and insert clusters Insert_Chk_Buff: cmp es:[di].Free_Size, 0 ; any free buffers ?? jne Insert_Inc_Count ; yes - go insert clusters cmp es:[di].Close_Ptr, -1 ; any headers in close queue?? (1/7/88 ;AN000; jne Insert_Inc_Count ; yes - go insert clusters clc ; no - dont insert clusters jmp Insert_Exit ; exit insert_Inc_Count: mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the OPEN queue ;AN000; mov cx,first_phys_clusnum ; CX = physical cluster number ;AN000; CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000; ; DI-->Header jc Insert_Make_Hdr ; header not found, make new header ;AN000; jmp Insert_Find_extent ; header is found, now go and ;AN000; ; search for the extent ;-------------------------------------------------------------------------- ; If header not found, create a new header in the free area and connect it ; to the top of the OPEN queue. Mark the new header with no extents. Insert ; the first logical and physical cluster number into the header. At this ; point CX=First Physical Cluster number. ;-------------------------------------------------------------------------- Insert_Make_Hdr: CALL MAKE_NEW_HEADER ; make a new header at the top ;AN000; ; top of the queue ;-------------------------------------------------------------------------- ; Now the header is created, next create an extent and put both logical and ; physical cluster number in the extent. The new extent should be ; created at the bottom end of the current queue, except if AX =3, ; then the new extent will be created between current and previous extent. ; Use Find_Free_Buffer to check the free space. ;-------------------------------------------------------------------------- CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; jnc ins_save_addrs1 ; found, jump ;AN000; jmp Insert_Exit ; if free area found is its own ;AN000; ; header, exit Ins_Save_Addrs1: mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Extn_Ptr,ax ; save new extent address ;AN000; CALL UPDATE_FREE_AREA ; update Free area ;AN000; mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; mov ax,New_Extn_Ptr ; beginning of new extent ;AN000; mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; mov es:[si].FH_Next_Extn_Ptr,ax ; connect current header to adj CHAIN ;AN000; mov es:[si].FH_MRU_EXTN_Ptr,ax ; connect current header to LRU chain ;AN000; mov si,New_Extn_Ptr ; SI-->New extent mov bx,Logical_ClusNum ;AN000; mov es:[si].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000; mov cx,Physical_ClusNum ;AN000; mov es:[si].EH_Phys_Clus_Num,cx ; insert physical clus num ;AN000; mov es:[si].EH_Count,0 ; set initial count = 0 ;AN000; ;-------------------------------------------------------------------------- ; Make new extent LRU extent ;-------------------------------------------------------------------------- mov es:[si].EH_Next_Extn_Ptr, -1 ; mark no next extent in sorted chain mov es:[si].EH_Prev_Extn_Ptr, -1 ; mark no previous extent in sorted chain ;AN000; mov es:[si].EH_Next_LRU_Ptr, -1 ; mark no next extent in MRU-LRU chain ;AN000; mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent in MRU-LRU chain clc ; jmp Insert_Exit ; exit ;AN000; ;-------------------------------------------------------------------------- ; Header found, Check to see any extent under this header. If not create ; new extent. If there are extents, search for the relative position of the ; given cluster number among the extents under current header. ;-------------------------------------------------------------------------- Insert_Find_Extent: mov di,Cur_Hdr_Ptr ; DI-->Current header mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under current hdr ;AN000; cmp si,-1 ; any extent under this header ? ;AN000; jne Find_relative_location ; yes, Find relative location of the ; given cluster numbers ;AN000; ; Else create new extent under the current header. CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; jnc ins_save_addrs2 ; found, jump ;AN000; jmp Insert_Exit ; else free area found is its own ;AN000; ; header, *** ERROR **** exit Ins_save_addrs2: mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Extn_Ptr,ax ; save new extent address ;AN000; CALL UPDATE_FREE_AREA ; update Free area pointers ;AN000; mov di,Drive_Hdr_Ptr ; DI-->Drive header pointer ;AN000; mov ax,New_Extn_Ptr ;AN000; mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; mov es:[si].FH_Next_Extn_Ptr,ax ; connect new extent to header ;AN000; mov es:[si].FH_MRU_EXTN_Ptr,ax mov si,New_Extn_Ptr ;### next extent start in the free_ptr ;AN000; mov bx,Logical_ClusNum ;AN000; mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; mov cx,Physical_ClusNum ;AN000; mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; mov es:[si].EH_Count,0 ; ;AN000; mov es:[si].EH_Next_Extn_Ptr,-1 ; mark this extent as last extent ;AN000; mov es:[si].EH_Next_LRU_Ptr,-1 ; ### mark this extent as last extent ;AN000; mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark there is no prev extent ;AN000; mov es:[si].EH_Prev_LRU_Ptr,-1 ; mark there is no prev LRU extent jmp Insert_Make_MRU ; make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Check if the given cluster number will be continuous to either High or Low ; end of any extent under current header or should create a new extent ; If not, check whether a new extent for the cluster is to be created ; between current and previous extent - Current and next extent or new ; extent at the bottom of the queue. ;-------------------------------------------------------------------------- Find_Relative_Location: CALL FIND_CLUSTER_LOCATION ; find relative position of new extent ;AN000; jnc chk_continuity ; position found ;AN000; clc ; clusters already exist in an extent. jmp Insert_exit ; return to DOS ;AN000; ;-------------------------------------------------------------------------- ; Extent found. Check for LOW end contiguous. If true insert in the current ; extent and update the count ;-------------------------------------------------------------------------- Chk_continuity: cmp find_flag,1 ; LO end contiguous to current extent? ;AN000; jne Insert_chk_HI ; no - check high end contiguous ;AN000; mov si,Cur_Extn_Ptr ; yes - insert and update ;AN000; mov cx,Logical_ClusNum ; save new logical and pysical ;AN000; mov es:[si].EH_Logic_Clus_Num,cx ; cluster numbers as first clusters ;AN000; mov cx,Physical_ClusNum mov es:[si].EH_Phys_Clus_Num,cx ;AN000; inc es:[si].EH_Count ; update extent range count ;AN000; mov di,Drive_Hdr_Ptr ; DI-->drive header cmp es:[di].Free_Ptr,0 ; any free buffer ?? je Chk_low_MRU ; no - make current extent MRU extent jmp Insert_Make_MRU ; yes - make current header MRU header ;AN000; Chk_Low_MRU: mov Cur_Extn_Ptr, si CALL Make_MRU_Extent ; Move extent next to current header jmp Insert_Make_MRU ; Make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Check if clusters are high end contiguous to current extent. If true ; increment count and then make the extent MRU extent only if no free ; buffer is available. ;-------------------------------------------------------------------------- Insert_Chk_HI: cmp find_flag,2 ; HI end contiguous to current extent? ;AN000; jne Insert_chk_between ; no, jump ;AN000; mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000; inc es:[si].EH_Count ; increment the cluster range count ;AN000; mov di,Drive_Hdr_Ptr ; DI-->current drive header cmp es:[di].Free_Ptr,0 ; any free buffers ?? je Chk_Hi_MRU ; no - make current extent MRU extent jmp Insert_Make_MRU ; yes - current header MRU header ;AN000; Chk_Hi_MRU: mov Cur_Extn_Ptr, si ; SI -->extent to be MRU CALL Make_MRU_Extent ; move extent next to current header jmp Insert_Make_MRU ; Make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Check to see the cluster number belongs to a new extent between current ; and Previous extent or header. If not it belongs to a new extent at the ; bottom end of the queue. ;-------------------------------------------------------------------------- Insert_Chk_Between: cmp find_flag,3 ; between current and previous exts?? ;AN000; je Connect_prev_next ; yes, jump ;AN000; cmp find_flag,5 ; between current and next extents?? ;AN000; jne Connect_to_end ; no, create new extent at bottom ;AN000; ; bottom of the queue jmp Connect_cur_next ; yes create new extent between ;AN000; ; current and next extent ;-------------------------------------------------------------------------- ; No, make new extent at the BOTTOM of the queue. ;-------------------------------------------------------------------------- CONNECT_TO_END: ; At this point SI-->Last extent in queue ;AN000; CALL FIND_FREE_BUFFER ; Check for free area ;AN000; jnc ins_save_addrs3 ;AN000; jmp Insert_Exit ; if free area found is its own ;AN000; ; header, *** ERROR *** exit Ins_Save_Addrs3: mov di,Drive_Hdr_Ptr ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Extn_Ptr,ax ; save new extent address ;AN000; CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; mov ax,New_Extn_Ptr ;AN000; mov di,Cur_Extn_Ptr ; SI-->Current extent ;AN000; cmp ax, di ; If free area got is the last jne Use_Cur_Extent ; last extent itself then use previous extent mov di, Prev_Extn_Ptr ; SI-->Previous extent Use_Cur_extent: mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to current or previous extent ;AN000; mov si,New_Extn_Ptr ; next extent start in the free_ptr ;AN000; mov es:[si].EH_Prev_Extn_Ptr, di ; set previous extent address mov bx,Logical_ClusNum ;AN000; mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; mov cx,Physical_ClusNum ;AN000; mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; mov es:[si].EH_Count,0 ; initial cluster range ; Make new extent last extent in the sorted chain mov es:[si].EH_Next_Extn_Ptr, -1 ; mark as Last extent of the queue ;AN000; ; make the new extent MRU extent in the MRU_LRU chain mov di,Cur_Hdr_Ptr ; DI-->Current header mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent mov di,ax mov es:[di].EH_Prev_LRU_Ptr,si ; connect previous to current extent jmp Insert_Make_MRU ; make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Make new extent between current and previous extents. If no previous extent ; connect the new extent to the current header. ;-------------------------------------------------------------------------- CONNECT_PREV_NEXT: CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; jnc Prev_Next_Update ; found, jump ;AN000; jmp Insert_Exit ; if free area found is its own ;AN000; ; header, **ERROR** exit Prev_Next_Update: mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Extn_Ptr,ax ; save new extent address ;AN000; ;AN000; CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000; cmp Prev_Extn_Ptr, -1 ; Any previous extents ?? ;AN000; jne join_to_Prev_Extn ; yes - connect new extent to previous ;AN000; ; extent ; No, connect new extent to header mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; mov di,New_Extn_Ptr ;AN000; mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under header mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to this extent mov es:[si].FH_Next_Extn_Ptr, di ; connect new extent to cur hdr ;AN000; mov es:[di].EH_Prev_Extn_Ptr, -1 ; address of previous extent (-1) since header mov bx,Logical_Clusnum ; ;AN000; mov es:[di].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000; mov cx,Physical_Clusnum ;AN000; mov es:[di].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; mov es:[di].EH_Count,0 ; set count ;AN000; mov si,ax ; SI-->previous MRU extent mov es:[si].EH_Prev_Extn_Ptr,di ; set prev extent of prev MRU extent ; Make the new extent MRU extent mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header mov di,New_Extn_Ptr ; SI-->current header ;AN000; mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header mov si,ax mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent Jmp Insert_Make_MRU ; make current header MRU hdr ;AN000; ; Connect new extent to previous extent Join_To_Prev_Extn: mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000; mov ax,Cur_Extn_Ptr ; connect previous extent ;AN000; cmp si,ax ; new extent is created from je join_set_adj ; current extent ?? mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000; mov ax,New_Extn_Ptr ; connect new extent to ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000; mov ax,Cur_Extn_Ptr jmp short Join_Set_Next ; current extent Join_set_adj: ; yes - mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000; mov bx,es:[si].EH_Next_Extn_Ptr ; get next extent address mov ax,New_Extn_Ptr ; connect new extent to ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000; mov ax, bx ; extent to next extent mov Cur_Extn_Ptr,bx ; change current extent Join_set_Next: ; from current extent mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ; current extent ;AN000; mov bx,Logical_Clusnum ; then save cluster numbers ;AN000; mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; mov cx,Physical_Clusnum ;AN000; mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; mov es:[si].EH_Count,0 ; ;AN000; mov ax, Prev_Extn_Ptr mov es:[si].EH_Prev_Extn_Ptr,ax ; connect previous to current extent mov di, Cur_Extn_Ptr ; setup previous extent link of mov es:[di].EH_Prev_Extn_Ptr,si ; current extent ; Make the new extent MRU extent mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header mov di,New_Extn_Ptr ; SI-->current header ;AN000; mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header mov si,ax mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent Jmp short Insert_Make_MRU ; make current header MRU hdr ;AN000; ;-------------------------------------------------------------------------- ; Make new extent between current and next extents. If no next extent ; connect the new extent to the end of queue. ;-------------------------------------------------------------------------- CONNECT_CUR_NEXT: mov si,Cur_Extn_Ptr ; current extent ;AN000; cmp es:[si].EH_Next_Extn_Ptr,-1 ; any next extent ?? ;AN000; jne join_to_next_extn ; yes, join to next extent ;AN000; jmp Connect_To_End ; make new extent at the bottom of ;AN000; ; the current queue Join_To_Next_Extn: CALL FIND_FREE_BUFFER ; Find free area ;AN000; jc Insert_Exit ; if free area found is its own ;AN000; ; header, exit mov di,Drive_Hdr_Ptr ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Extn_Ptr,ax ; save new extent address ;AN000; CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; ;AN000; mov si,Cur_Extn_Ptr ; SI-->Current extent mov DX,es:[si].EH_Next_Extn_Ptr ; DI-->Next extent ;AN000; mov ax,New_Extn_Ptr ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ;connect new extent to cur extent ;AN000; mov si,New_Extn_Ptr ; SI-->New extent, connect new ext ;AN000;;AN000; mov es:[si].EH_Next_Extn_Ptr,DX ; to next extent ;AN000; mov ax, Cur_Extn_Ptr ; AX = address of current extent mov es:[si].EH_Prev_Extn_Ptr, ax ; save address of previous extent mov bx,Logical_Clusnum ; then save cluster numbers ;AN000; mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; mov cx,Physical_Clusnum ;AN000; mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; mov es:[si].EH_Count,0 ; set cluster range ;AN000; mov di,DX ; setup prev extent link of the mov es:[di].EH_Prev_Extn_Ptr,si ; next extent ; Make the new extent MRU extent mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header mov di,New_Extn_Ptr ; SI-->current header ;AN000; mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header mov si,ax mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent ;-------------------------------------------------------------------------- ; Make the Current header MRU header. If the header is MRU header, then ; dont make the header MRU header. ;-------------------------------------------------------------------------- Insert_Make_MRU: cmp Prev_Hdr_Ptr, -1 ; first header ?? ;AN000; jne Ins_mru_hdr ; no, make MRU header ;AN000; clc ; make sure caary is clear jmp short insert_exit ; yes, exit ;AN000; Ins_MRU_Hdr: CALL MAKE_MRU_HEADER ; move header to top of OPEN Queue ;AN000; clc ; make sure caary is clear Insert_exit: CALL Check_it ; analyse the queue (debugging) ret ; EXIT ;AN000; FK_INSERT ENDP ;------------------------------------------------------------------------- ; PROCEDURE: FK_LOOKUP ; ; FUNCTION: Search through the OPEN Queue for a specific Header and ; extent. If header is not found, create a new header and ; make it MRU header. Else search for a specific extent which ; contains the logical cluster number. If the extent is not ; found, return partial information from previous extent or ; header. If extent is found, return physical cluster number ; corresponds to the given logical cluster number. ; ; INPUT: DL = drive number ; CX = First Physical Cluster Number of the file ; BX = Logical Cluster NUmber ; ; OUTPUT: If Carry = 0 Fully Found ; DI = Physical Cluster Number indexed by es:[BX] ; BX = Physical Cluster Number indexed by es:[BX-1] ; ; If Carry = 1 Partially Found ; BX = Last logical cluster number in previous extent ; DI = Last Physical Cluster Number indexed by es:[Last logic clus] ; ; If header not found, a new header will be created. In this case ; BX = First Logical Cluster number (0) ; DI = First Physical Cluster number of the header created ; ; NOTE: The clusters are fully found if the logical cluster has ; continuity to the previous logical cluster in the same ; extent or previous extent or previous header. ; ; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_Drive_Header ; ; REVISION HISTORY: New (5/87) ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;--------------------------------------------------------------- FK_LOOKUP PROC FAR ; on entry DS = seg ID of INIT push cs ; establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; mov Logical_ClusNum,bx mov func_cod,al ;-------------------------------------------------------------------------- ; Search for Drive header in the Cache buffer using Drive ID in DL ;-------------------------------------------------------------------------- CALL FIND_DRIVE_HEADER ; Search for drive header ;AN000; jnc Look_search_hdr ; found, search for file header ;AN000; jmp Look_Exit ; not found, error ;AN000; ;-------------------------------------------------------------------------- ; Search for a header in the OPEN Queue using given physical cluster number ;-------------------------------------------------------------------------- Look_Search_Hdr: inc es:[di].Extent_Count ; ;***; mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; ; in the OPEN Queue mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000; CALL FIND_FILE_HEADER ; find the header in CLOSE Queue ;AN000; jnc Look_Find_extent ; if found, find extent under this header ; else create a new header ;AN000; ;-------------------------------------------------------------------------- ; If the header is not found, create a new header at the top of OPEN queue. ; Insert physical cluster number and set next header and first extent pointers ; Return partially found information. ;-------------------------------------------------------------------------- pushf ; save carry set CALL MAKE_NEW_HEADER ; Make a new header at the top of the queue ;AN000; xor bx,bx ; BX = First Logical cluster number ;AN000; mov di, First_Phys_Clusnum ; DI = First physical cluster number popf ; carry should be set jmp Look_exit ; exit ;AN000; ;-------------------------------------------------------------------------- ; If the header is found, next search for the extent that contains the ; logical and physical cluster numbers. DI--> current header ;-------------------------------------------------------------------------- Look_Find_Extent: cmp es:[di].FH_Next_Extn_Ptr,-1 ; any extent under this header ?? ;AN000; jne look_search_extent ; yes, search for right extent ;AN000; xor bx,bx ; no, return partial info from header ;AN000; mov di,es:[di].FH_Phys_Clus_Num ; DI = first phys clus num ;AN000; push di ; ;AN000; push bx ; BX = 1st logc clus num = 0 ;AN000; mov fully_flag, 0 ; set partially found flag ;AN000; jmp look_make_MRU_hdr ; move header to top of the OPEN queue ;AN000; ;-------------------------------------------------------------------------- ; Search for cluster numbers in extents starting from 1st extent. ;-------------------------------------------------------------------------- Look_Search_Extent: mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under curr hdr ;AN000; mov Cur_Extn_Ptr,si ; save it ;AN000; mov cx,Logical_ClusNum ; CX = logic clus num to search for ;AN000; mov Prev_Extn_Ptr, -1 ; reset flags ;AN000; mov Extn_Flag, 0 ; ;AN000; cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000; jl Look_proc_less Look_Loop1: cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000; ; current extent matches ?? je Look_Proc_First ; yes, process 1st extent case ;AN000; mov ax,es:[si].EH_Logic_Clus_Num ; else check subsequent extents add ax,es:[si].EH_Count ; last logic clus num in cur extent ;AN000; cmp cx,ax ; extent found in the cur extent ?? jg Look_Next_Extn ; no,try next extent ;AN000;;AN000;;AN000; jmp Look_Extn_within ; yes, process current extent ;AN000; Look_Next_Extn: ; mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000; cmp ax,-1 ; is this last extent ?? ;AN000; je Look_last_done ; yes, get partial ;AN000; mov Prev_Extn_Ptr,si ; save previous extent address ;AN000; mov si,ax ;AN000; mov Cur_Extn_Ptr,si ; save current extent address ;AN000; cmp cx,es:[si].EH_Logic_Clus_Num ; logic clus num in cur extent ?? ;AN000; jge Look_Loop1 ; may be!!, check it out ;AN000; jmp Look_Proc_Prev ; else get partial info from ;AN000; ; previous extent ;------------------------------------------------------------------------- ; There are no further extents. In this case partially found. Return last ; logical and physical clusters of the last extent. ;------------------------------------------------------------------------- Look_Last_Done: mov si,Cur_Extn_Ptr ; SI-->Previous extent ;AN000; mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num ofprevext ;AN000; mov di,es:[si].EH_Phys_Clus_Num ; BX = first logic clus num ofprevext ;AN000; add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000; add bx,es:[si].EH_Count ; BX = last logic clus number in extent ;AN000; push di ; last logical cluster number ;AN000;;AN000; push bx ; last physical cluster number ;AN000; mov fully_flag,0 ; partially found case ;AN000; jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Less than starting logical cluster of first extent. In this case return ; header info as partially found. ;-------------------------------------------------------------------------- Look_Proc_Less: xor bx,bx ; BX = logical cluster number = 0 ;AN000; mov ax,es:[di].FH_Phys_Clus_Num ;AN000; push ax ; first phys clus of current hdr ;AN000; push bx ; first logic clus (0) of cur hdr ;AN000; mov fully_flag,0 ; partially found case ;AN000; jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; If first logical cluster number of the current extent matches with the given ; logical cluster number, see if previous logical cluster in previous header ; or extent is contiguous. If true, fully found. I this case return ; BX = first physical cluster of cuurent extent and DI = first physical ; cluster number of header if it is a header or last physical cluster number ; of previous extent. If this is not true, partially found case. In this case, ; return BX = last logical cluster number and DI = last physical cluster number ; from the previous extent. If no previous extent, then return DI = first ; physical cluster and BX = 0 from the header ; ; NOTE: The clusters are fully found if the logical cluster has ; continuity to the previous logical cluster in the same ; extent or previous extent or previous header. ;-------------------------------------------------------------------------- Look_Proc_First: mov si,Cur_Extn_Ptr ; SI-->current extent ;AN000; mov di,Cur_Hdr_Ptr ; DI-->current header ;AN000; cmp Prev_Extn_Ptr, -1 ; any previous extent ?? ;AN000; jne look_get_prev_extent ; yes, get from previous extent ;AN000; ;-------------------------------------------------------------------------- ; No, look for current header logical cluster number continuity ;-------------------------------------------------------------------------- mov ax,es:[si].EH_Logic_Clus_Num ; AX = First physical cluster number ;AN000; dec ax ; of current extent ;AN000; cmp ax,0 ; continuity to first logical clus num ;AN000; ; of current header which is (0) jne Look_first_partial ; no, partially found ;AN000; ; Yes, fully found mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000; ; current extent mov ax,es:[di].FH_Phys_Clus_Num ; AX = First physical cluster number ;AN000; ; of current header push bx ; BX = 1st phys clus of current extent ;AN000; push ax ; AX = 1st phys clus of prev header ;AN000; mov fully_flag,1 ; FULLY found case ;AN000; jmp Look_Make_MRU_Hdr ; mov cur header to top of the Queue ;AN000; Look_First_Partial: xor bx,bx ; BX = logical cluster number = 0 ;AN000; mov ax,es:[di].FH_Phys_Clus_Num ;AN000; push ax ; first phys clus of current hdr ;AN000; push bx ; first logic clus (0) of cur hdr ;AN000; mov fully_flag,0 ; partially found case ;AN000; jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000; ;-------------------------------------------------------------------------- ; Get last physical and logical cluster number of the previous extent ;-------------------------------------------------------------------------- Look_Get_Prev_Extent: mov di,Prev_Extn_Ptr ; DI-->Previous extent ;AN000; mov ax,es:[si].EH_Logic_Clus_Num ; AX = First logical cluster number ;AN000; dec ax ; of current extent ;AN000; mov bx,es:[di].EH_Logic_Clus_Num ; continuity to last logical clus num ;AN000; add bx,es:[di].EH_Count ; of previous extent ?? ;AN000; cmp ax,bx ;AN000; jne Look_first_partial2 ; no, partially found ;AN000; ; Fully found case mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000; mov ax,es:[di].EH_Phys_Clus_Num ; AX = Last physical cluster number ;AN000; add ax,es:[di].EH_Count ; from previous extent ;AN000; push bx ; BX = 1st phys clus num from cur extn ;AN000; push ax ; AX = last phys clus num from prev extn ;AN000; mov fully_flag,1 ; FULLY found case ;AN000; jmp short Look_Make_MRU_Hdr ; mov current header to top of OPEN que ;AN000; Look_First_Partial2: mov bx,es:[di].EH_Logic_Clus_Num ; BX = First Logical cluster number ;AN000; ; of current extent add bx,es:[di].EH_Count ; BX = Last Logic clus from prev extn ;AN000; mov ax,es:[di].EH_Phys_Clus_Num ; AX = First physical cluster number ;AN000; ; of previous extent add ax,es:[di].EH_Count ; last phys clus num of prev extent ;AN000; push ax ; AX = last phys clus of prev extent ;AN000; push bx ; BX = last logic clus of prev extent ;AN000; mov fully_flag,0 ; partially found case ;AN000; jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000; ;---------------------------------------------------------------------------- ; If the given cluster number matches with any logic cluster number starting ; from 2nd and above, then fully found. Return BX=Phys clus num[log_clusnum] ; and DI=Phys clus num[log_clusnum-1] ;---------------------------------------------------------------------------- Look_Extn_Within: mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000; sub cx,es:[si].EH_Logic_Clus_Num ;AN000; mov di,es:[si].EH_Phys_Clus_Num ; DI = first phys clus num of ;AN000; ; current extent add di,cx ; DI = Phys clus num [logic clus num] ;AN000; mov bx,di ; ;AN000; dec bx ; BX = Phys clus num [logic clus num -1] ;AN000; push di ; DI = Phys clus num [logic clus num] ;AN000; push bx ;AN000; mov fully_flag,1 ; fully found case ;AN000; jmp short Look_Make_MRU_Hdr ; make current header to top of OPEN Que ;AN000; ;-------------------------------------------------------------------------- ; Given extent is above the upper limit of the current extent, but lower than the ; next extent. In this case, cluters are partially found. Return BX = last ; logical cluster number of the previous extent and DI = last physical cluster ; number of the previous extent. ;---------------------------------------------------------------------------- Look_Proc_Prev: mov si,Prev_Extn_Ptr ; SI-->Previous extent ;AN000; mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num of prev ;AN000; ; extent mov di,es:[si].EH_Phys_Clus_Num ; BX = first phys clus num of prev ;AN000; ; extent add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000; add bx,es:[si].EH_Count ; BX = last logic clus number in extent push di ; save clusters to return ;AN000; push bx ;AN000; mov fully_flag,0 ; partially found case ;AN000; ;---------------------------------------------------------------------------- ; Move the current header to the top of the OPEN queue ;---------------------------------------------------------------------------- Look_Make_MRU_Hdr: cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000; je Look_Dont_Move_To_Top ; yes, dont move to top ;AN000; CALL MAKE_MRU_HEADER ;AN000; Look_Dont_Move_To_Top: cmp fully_flag, 0 ; fully found ?? ;AN000; je Look_set_carry ; no, partially found ;AN000; clc ; fully found ;AN000; jmp short Look_Restore ; restore registers ;AN000; Look_Set_Carry: stc ; set flag for partially found ;AN000; Look_restore: pop bx ; restore values to be reurned pop di ; to DOS Look_Exit: nop CALL Check_it ret ; exit FK_LOOKUP endp ;---------------------------------------------------------------- ; PROCEDURE: Fk_Truncate ; ; FUNCTION: Using the given physical and logical clutser numbers, ; find the extent which contains the given cluster number. ; Delete all clusters folloing the given cluster and the ; subsequent extents and free the buffers. ; ; INPUT: CX = First Physical Cluster Number of the file ; BX = Logical Cluster Number ; DL = Drive number ; ; OUTPUT: CY = 0 Extents are truncated ; ; CY = 1 Extent no found DI = 0 ; ; ROUTINES REFERENCED: Find_File_Header, Find_Extent ; ; REVISION HISTORY: New (5/87) ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;--------------------------------------------------------------- Fk_TRUNCATE PROC FAR push cs ; establish addressability ;AN000; pop ds ; DS --> code segment ;AN000; assume ds:Cseg_Seek ;AN000; mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; mov Logical_ClusNum,bx ;AN000; mov func_cod,al ;-------------------------------------------------------------------------- ; Search for Drive Cache buffer using Drive ID in DL ;-------------------------------------------------------------------------- CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; jnc Trunc_search_hdr ; if found, search for file header ;AN000; jmp Trunc_Exit ; if not found, error ;AN000; ;AN000; ;-------------------------------------------------------------------------- ; Search for a header in the OPEN Queue using given physical clusternum ;-------------------------------------------------------------------------- Trunc_Search_Hdr: inc es:[di].Extent_Count ; ;***; mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; ; in the OPEN Queue mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000; CALL FIND_FILE_HEADER ; find file header in OPEN Queue ;AN000; jnc Trunc_Find_extent ; if found, get extent ;AN000; ;-------------------------------------------------------------------------- ; If the header is not found, create a new header and make it as MRU header ; insert first physical cluster number in the header ;-------------------------------------------------------------------------- CALL MAKE_NEW_HEADER ; make new header ;AN000; clc ;AN000; jmp Trunc_exit ; exit ;AN000; ;-------------------------------------------------------------------------- ; Header is found. Next search for the extent which contains the ; given logical cluster number. ;-------------------------------------------------------------------------- Trunc_Find_Extent: ; ;AN000; mov Cur_Hdr_Ptr,di ; save current pointer ;AN000; mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent in the ;AN000; ; current header cmp si, -1 ; any extent under this header ?? ;AN000; je trunc_no_extent ; none, exit ;AN000; mov cx,Logical_Clusnum ; CX = given logical cluster number ;AN000; CALL FIND_EXTENT ; find the extent ;AN000; jnc Trunc_shrink_extent ; found extent ?? ;AN000; Trunc_No_Extent: ; extent not found xor di,di ; no, return DI = 0 ;AN000; clc ; clear carry jmp Trunc_exit ; exit ;AN000; ;-------------------------------------------------------------------------- ; Found extent. Shrink the current extent and delete all subsequent extents. ; If the given logic clus num is the first cluster number in current extent, ; then delete the current extent and the subsequent ones. ; DI--->Extent found (starting extent) ;-------------------------------------------------------------------------- Trunc_Shrink_Extent: mov bx,Logical_Clusnum ;AN000; cmp bx,es:[di].EH_Logic_Clus_Num ; first logic cluster match ?? ;AN000; jne shrink_cur_extent ; no, shrink current extent ;AN000; ;-------------------------------------------------------------------------- ; First logical clus num matched. mark previous header or extent as last ; DI--->Extent found (starting extent) ;-------------------------------------------------------------------------- mov si,es:[di].EH_Prev_Extn_Ptr ; SI-->Previous extent ;AN000; cmp si, -1 ; any previous extent ?? ;AN000; je trunc_no_prev ; no, jump ;AN000; mov es:[si].EH_Next_Extn_Ptr,-1 ; mark previous extent as last extn ;AN000; mov si,di ; save the current extent ptr ;AN000; mov cx, 0 ; CX = buffer release counter ;AN000; jmp trunc_more ; release successive extents ;AN000; ;-------------------------------------------------------------------------- ; Previous one is header. Mark so that there is no extents under it ;-------------------------------------------------------------------------- Trunc_No_Prev: mov si,Cur_Hdr_Ptr ; get current header ;AN000; mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000; mov es:[si].FH_MRU_Extn_Ptr, -1 mov si,di ; save the current extent ptr ;AN000; mov cx, 0 ; CX = buffer release counter ;AN000;;AN000; jmp short trunc_more ; release the extent ;AN000; Shrink_Cur_Extent: sub bx,es:[di].EH_Logic_Clus_Num ; compute the amount to shrunk ;AN000; dec bx ;AN000; mov es:[di].EH_Count,bx ; save it in count to shrink extent ;AN000; ;-------------------------------------------------------------------------- ; Mark the current extent as the last extent and delete subsequent extents. ;-------------------------------------------------------------------------- mov si,es:[di].EH_Next_Extn_Ptr ; SI-->Next extent ;AN000; cmp si,-1 ; current extent last extent ?? ;AN000; jne Trunc_Last_extent jmp Trunc_Make_MRU_Hdr ; YES, In this case no subsequent ;AN000; ; extents left to delete. Trunc_Last_Extent: mov es:[di].EH_Next_Extn_Ptr, -1 ; NO, mark last extent ;AN000; xor cx,cx ;AN000; ;-------------------------------------------------------------------------- ; Remove extents and release the buffer ; SI--->Current extent ;-------------------------------------------------------------------------- Trunc_More: push si ; save the beginning of first ;AN000; ; extent to be deleted TRUNC_LOOP: ; loop for subsequent extents mov ax, -2 ; mark current extent as free ;AN000; mov es:[si],ax ; discontinuous free areas ;AN000; add cx, SIZE Extent_Header ; add size of extent ;AN000; mov ax,es:[si].EH_Next_LRU_Ptr ; AX = address of Next LRU extent cmp ax, -1 ; any next LRU extent?? jne Trunc_Set_Next_LRU ; yes - there is a next LRU extent ;----------------------------------------------------------------------------- ; No - this is the LRU extent ;----------------------------------------------------------------------------- mov di,es:[si].EH_Prev_LRU_Ptr ; no - DI=address of previous LRU extent cmp di, -1 ; any prev LRU extent ?? je Trunc_Mark_Prev_Hdr ; no - previous is header mov es:[di].EH_Next_LRU_Ptr, -1 ; yes - mark previous extnt LRU extent jmp short Trunc_Chk_Next_ext ; no - check next adj extent Trunc_Mark_Prev_Hdr: mov di, Cur_Hdr_Ptr ; DI = address of current header mov es:[di].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000; mov es:[di].FH_MRU_Extn_Ptr, -1 jmp short Trunc_Chk_Next_Ext ; look for next extent ;----------------------------------------------------------------------------- ; There is a next LRU extent AX-->Next_LRU_Extent ;----------------------------------------------------------------------------- Trunc_Set_Next_LRU: mov di,es:[si].EH_Prev_LRU_Ptr ; DI = address of previous LRU extent cmp di, -1 ; any previous LRU extent ?? jne Trunc_Set_Prev_LRU ; yes - connect prev LRU to Next LRU mov di, Cur_Hdr_Ptr ; DI = address of current header mov es:[di].FH_MRU_Extn_Ptr, ax ; Connect next LRU extent to Hdr push si ; save current extent mov si,ax mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent pop si ; resetore current extent jmp short Trunc_Chk_Next_Ext Trunc_Set_Prev_LRU: ; DI-->Previous LRU extent mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous LRU to Next LRU extent push si ; save Current extent mov si,ax ; SI-->Next LRU extent mov es:[si].EH_Prev_LRU_Ptr, di ; set previous LRU header address pop si ; get current extent Trunc_Chk_Next_Ext: ; SI-->Current extent mov ax,es:[si].EH_Next_Extn_Ptr ; AX-->next extent ;AN000; cmp ax, -1 ; last extent ? ;AN000; je Trunc_Update_Free_Size ; yes, jump ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; connect freed buffers togther ;AN000; mov si,ax ; SI-->next extent ;AN000; jmp Trunc_Loop ; delete next extent ;AN000; ;------------------------------------------------------------------------- ; Update free size in the File header and connect the FREE_Ptr to the first ; extent released and connect the old Free_Ptr to end of the last extent ; SI--->Current extent ;------------------------------------------------------------------------- Trunc_Update_Free_Size: ; SI-->Last extent released mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; add es:[di].Free_Size,cx ; update free area in drive header ;AN000; Trunc_Join_Free_Area: ; At this point SI-->Last extent mov ax,es:[di].Free_Ptr ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ; connect last extent under this ;AN000; ; header to the Free area ;AN000; pop ax ; beginning of truncated extent ;AN000; mov es:[di].Free_Ptr,ax ; connect current extent to ;AN000; ; the beginning of truncated extent ;-------------------------------------------------------------------------- ; Make the Current header MRU header ( move current header to top of current Q) ;-------------------------------------------------------------------------- Trunc_make_MRU_Hdr: cmp Prev_Hdr_Ptr,-1 ; first header in the Queue?? ;AN000; jne Trunc_move_Hdr clc jmp short Trunc_Exit ; yes, dont move to top ;AN000; Trunc_move_Hdr: CALL MAKE_MRU_HEADER ; move header to TOP of the Queue ;AN000; clc Trunc_Exit: CALL Check_it ret ; return ;AN000; FK_TRUNCATE ENDP ;----------------------------------------------------------------------------- ; Procedure: PURGE_BUFFERS ; ; Function: Reset both extent and name cache buffers of a specific ; drive id ; ; Input: DL = drive ID ; ; Output: Buffers are initialized ; ; REVISION HISTORY: New (5/87) ; ; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" ; "Version 4.00 (C) Copyright 1988 Microsoft" ; "Licensed Material - Property of Microsoft " ; ;----------------------------------------------------------------------------- FK_PURGE PROC FAR ; Purge Cache buffers push cs pop ds ; DS=Code seg id used for addressing ASSUME ds:Cseg_Seek ; local variables ;AN000; mov si,Seek_Extent_Drive_Buff ; SI-->beginning of extent drive ;AN000; mov es,Seek_Name_Cache_Seg ; ES = addressability to Cseg_Init ;AN000; ASSUME es:Cseg_Init ; ;AN000; mov cx,Seek_Num_Of_drives ; number of drives Main_Loop2: ; ES:SI-->cache buffer mov ax,es:[si].Drive_Number ; get drive id cmp al,dl ; drive id found ?? je purge_buffer ; yes - purge drive id buffer mov ax, size Drive_Header ; ax size of drive heder add ax, es:[si].Buff_Size ; ax = offset to next header add si,ax ; (2/11)SI-->next drive header ;AN000; LOOP main_loop2 ; try next header Purge_Buffer: ; SI-->drive header mov es:[si].MRU_Hdr_Ptr,-1 ; Make OPEN QUEUE empty ;AN000; mov es:[si].CLOSE_Ptr,-1 ; Make CLOSE QUEUE empty ;AN000; mov cx,es:[si].BUFF_size ; drive extent cache size ;AN000; mov es:[si].FREE_Size,cx ; set drive free buffer size ;AN000; mov ax,si add ax, size Drive_Header ; ax = size of drive header mov es:[si].FREE_Ptr,ax ; set Free buffer address ; Makesure to fill extent cache buffer with zeros. Otherwise, Free Mark left ; previous run will generate illegal Free_Buff pointer. mov al,0 add si, size Drive_Header ; SI-->first extent area Ext_loop: ; fill extent cahe buffer with zeros mov es:[si],al ; CX = extent cache size inc si ; next byte Loop Ext_Loop ; make it zero FK_Exit: clc CALL Check_it ret ;AN000; FK_PURGE ENDP ;---------------------------------------------------------------------- ; ******* SUPPORT ROUTINES ******* ;---------------------------------------------------------------------- ; ;---------------------------------------------------------------------- ; PROCEDURE: Find_Drive_Header ; ; FUNCTION: Find starting address of drive header in extent Cache Buffer using ; drive ID in DL ; ; INPUT: DL = drive id ; Extent_Drive_Buff (Ptr to the beginning of extent buffer) ; ES--> Cache Buffer Segment ; ; OUTPUT: If Carry = 0 DI --> Drive header ; Drive_Hdr_Ptr = address of drive header ; ; If Carry = 1 Drive buffer not found ; ; NOTE: If drive id in DL is same as the drive id in previous request, ; no need to search the drive header. Use the previous drive header ; ;---------------------------------------------------------------------- FIND_DRIVE_HEADER PROC NEAR mov di,Drive_Hdr_Ptr ; DI-->address of prev drive header cmp drv_id,dl ; drive id same as previous drive id (1/11/88) jne Search_drv_hdr ; no - search drive header clc ; yes - dont search jmp short drive_exit ; exit Search_Drv_Hdr: mov cx,Seek_Num_of_Drives ; get number of drives ;AN000; mov si,Seek_Extent_Drive_Buff ; SI-->start of extend drive hdr ;AN000; Drive_Loop: mov al,es:[si] ; get drive ID from cache drive hdr ;AN000; cmp al,dl ; found ?? ;AN000; je drive_buff_found ; yes, exit ;AN000; cmp es:[si].Next_Drv_Hdr_Ptr,-1 ; last header ?? ;AN000; je drive_Buff_not_found ; yes - drive header not found ;AN000; mov si,es:[si].Next_Drv_Hdr_Ptr ; SI-->next drive header ;AN000; dec cx ; update drive count ;AN000; jz drive_Buff_not_found ; last drive ;AN000; jmp drive_Loop ; search for more ;AN000; Drive_Buff_Not_Found: ; drive buffer not found stc ; set carry flag ;AN000; jmp short Drive_Exit ; exit ;AN000; Drive_Buff_Found: ; drive buffer found mov drv_id,dl ; save drive id mov Drive_Hdr_ptr,si ; save drive buffer pointer ;AN000; mov di,si ; DI-->drive header ;AN000; clc ;AN000; Drive_Exit: ; return ret ;AN000; FIND_DRIVE_HEADER endp ;--------------------------------------------------------------- ; PROCEDURE: Find_File_Header ; ; FUNCTION: Find starting address of the specific file header with ; a specific starting physical cluster number. Also ; determine the type of header found. ; ; INPUT: SI --> First header in the queue ; CX = First Physical Cluster Number (file id) ; ES--> Cache Buffer Segment id ; ; OUTPUT: If Carry = 0 DI --> header found ; Cur_Hdr_Ptr = address of header found ; Prev_Hdr_Ptr = address of previous header ; ; Prev_Hdr_Ptr = -1 No Previous Header ; ; hdr_flag - Type of header found ; = 0 Header between first & last in queue ; = 1 Single header in the queue ; = 2 First header in the queue ; = 3 LRU (Last) header in the queue ; ; If Carry = 1 Header not found ; ;--------------------------------------------------------------- FIND_FILE_HEADER PROC NEAR push si ; save registers ;AN000; push cx ;AN000; cmp si, -1 ; any file header in this queue ?? ;AN000; jne Fh_search_hdr ; yes, search for it ;AN000; stc ; no, set carry and return ;AN000; jmp short Fh_Exit ;AN000; Fh_Search_Hdr: mov Prev_Hdr_Ptr,-1 ; reset flags ;AN000; mov Hdr_Flag, 0 ; reset header type flag ;AN000; Fh_Loop1: cmp es:[si].FH_Phys_Clus_Num,CX ; check current header ;AN000; jne Fh_next_header ; if not found branch ;AN000; mov di,si ; DI --> header found ;AN000; mov Cur_Hdr_Ptr,si ; save current Hdr pointer ;AN000; jmp short Fh_header_found ; then take exit ;AN000; Fh_Next_header: ; else try next header mov ax,es:[si].FH_Next_Hdr_ptr ; get address of next header ;AN000; cmp ax,-1 ; is this last header?? ;AN000; je Fh_not_found ; yes, header no found ;AN000; mov Prev_Hdr_Ptr,si ; save previous header ;AN000; mov si,ax ; SI= next header ;AN000; jmp Fh_Loop1 ; check next header ;AN000; ; Determine the type of header found Fh_Header_Found: ; header found cmp Prev_Hdr_Ptr, -1 ; any previous headers ?? ;AN000;;AN000; jne Fh_LRU ; yes, jump ;AN000; cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; any headers following this hdr ?? ;AN000; jne Fh_First ; yes, jump ;AN000; mov Hdr_Flag, 1 ; single header in the queue ;AN000; clc ; ;AN000; jmp short FH_Exit ; exit ;AN000; Fh_First: mov Hdr_Flag, 2 ; Header found is first header in QUE ;AN000; clc ; set flag ;AN000; jmp short FH_Exit ; exit ;AN000; Fh_LRU: cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; Last header in the queue ?? ;AN000; jne Fh_middle_hdr ; no, Header between first and last ;AN000; mov Hdr_Flag, 3 ; set flag indicating LRU header ;AN000; clc ;AN000; jmp short Fh_Exit ; exit ;AN000; ;AN000; Fh_Middle_Hdr: clc ;AN000; jmp short Fh_Exit ; exit ;AN000; Fh_Not_found: stc ; header not found ;AN000; Fh_Exit: pop cx ;AN000; pop si ;AN000; ret ; return ;AN000; FIND_FILE_HEADER ENDP ;--------------------------------------------------------------- ; PROCEDURE: Find_Extent ; ; FUNCTION: Find starting address of the specific Extent that contains ; the given logical cluster mumber. ; Verifiy that the extent found is the LRU Extent. ; ; INPUT: SI --> First Extent under current queue ; CX = Logical Cluster number to be searched ; ES--> Cache Buffer Segment Id ; ; OUTPUT: If Carry = 0 DI --> Extent found ; Cur_Extn_Ptr = address of extent found ; Prev_Extn_Ptr = address of previous extent ; IF Extn_Flag = 1, extent found is the only ; extent under this header ; ; If Carry = 1 Extent not found ; ; REVISION HISTORY: New (5/87) ;--------------------------------------------------------------- FIND_EXTENT PROC NEAR push si ; save registers ;AN000; push cx ;AN000; ;AN000; mov Prev_Extn_Ptr,-1 ; reset flags mov Extn_Flag, 0 ;AN000; ;AN000; Eh_Loop1: cmp cx,es:[si].EH_Logic_Clus_Num ;AN000; jl Eh_Next_Extn ; try next extent ;AN000; mov ax,es:[si].EH_Count ; get range ;AN000; add ax,es:[si].EH_Logic_Clus_Num ; get upper range ;AN000; cmp cx,ax ;AN000; jg Eh_Next_Extn ; try next extent ;AN000; Eh_Not_LRU: mov di,si ; DI --> Extent found ;AN000; mov Cur_Extn_Ptr,si ; save current extent pointer ;AN000; clc ; set flag ;AN000; jmp Eh_Extn_found ; then take exit ;AN000; Eh_Next_Extn: ; else try next extent mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000; cmp ax,-1 ; is this last extent?? ;AN000; je Eh_Not_Found ; yes, exit ;AN000; mov Prev_Extn_Ptr,si ; save previous extent ;AN000; mov si,ax ; SI=next extent ;AN000; jmp Eh_Loop1 ; check next extent ;AN000; stc ; else set flag for extent not found ;AN000; jmp short Eh_Exit ; then exit ;AN000; Eh_Extn_Found: ; Extent found cmp Prev_Extn_Ptr, -1 ; any previous extents ?? ;AN000; jne Eh_yes ; yes, jump ;AN000; cmp es:[di].Eh_Next_Extn_Ptr, -1 ; any extents following this extents ?? ;AN000; jne Eh_yes ; yes, jump ;AN000; mov Extn_Flag, 1 ; no, set flag indicating single extnt ;AN000; ; in the queue Eh_Yes: clc ;AN000; jmp short Eh_Exit ; exit ;AN000; Eh_Not_Found: ; extent not found stc ;AN000; Eh_Exit: pop cx ;AN000; pop si ;AN000; ret ; return ;AN000; FIND_EXTENT ENDP ;--------------------------------------------------------------------------- ; PROCEDURE: FIND_CLUSTER_LOCATION ; ; FUNCTION: Find starting address of a specific extent which identifies ; the relative position of the new cluster in the queue. ; ; INPUT: SI--> First extent under current header ; ES--> Cache Buffer Segment ; ; OUTPUT: If Carry = 0 Cluster location identified ; Cur_Extn_Ptr = Current extent ; Prev_Extn_Ptr = Previous extent ; ; Find_Flag = 1 Clusters are contiguous in ; the LO end of the current extent ; ; Find_Flag = 2 Clusters are contiguous in ; the HI end of the current extent ; ; Find_Flag = 3 Clusters belong to a new ; extent between current and previous ; extent ; ; Find_Flag = 4 Clusters belong to a new ; extent at the end of the queue ; Cur_Extn_Ptr-->Last extent in queue ; ; Find_Flag = 5 Clusters belong to a new ; extent between current and next ; ; If Carry = 1 Clusters already exist ; ;----------------------------------------------------------------------- FIND_CLUSTER_LOCATION PROC NEAR ;-------------------------------------------------------------------------- ; Check to see that the given logical cluster number falls within the ; current extent. If true it is an error. ;-------------------------------------------------------------------------- push di mov Prev_Extn_Ptr, -1 ; initialize the flag ;AN000; mov Cur_Extn_Ptr,si ; SI-->First extent under header ;AN000; mov Find_Flag, -1 ; reset with illegal value ;AN000; Fe_LOOP1: mov ax,es:[si].EH_Logic_Clus_Num ; AX = starting logi clus number ;AN000; mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; cmp bx,ax ; LOW end ?? ;AN000; jl Fe_Chk_Low_end ; yes - jump ;AN000; add ax,es:[si].EH_Count ; ending logical clus number ;AN000; cmp bx,ax ; HIGH end ?? ;AN000; jg Fe_Chk_High_end ; yes - jump ;AN000; ;-------------------------------------------------------------------------- ; Found the given logical cluster number within the extent. ; This is a normal condition. In this case the clusters wont be insterted. ;-------------------------------------------------------------------------- stc ; set flag jmp Fe_Extent_Exit ; return ;AN000; ;-------------------------------------------------------------------------- ; If not in the extent, then see the logical clus number has continuity at ; LOW end of the current extent. ;-------------------------------------------------------------------------- Fe_Chk_LOW_END: mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000; dec ax ; one below the lowest ;AN000; mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; cmp bx,ax ; contiguous at LOW end ?? ;AN000; jl Fe_Curr_Prev ; no, build a new extent between ;AN000; ; current and previous ; Logical clus has continuity at low end. Now check physical cluster number ; foe continuity. mov ax,es:[si].EH_Phys_Clus_Num ; starting Phys clus number ;AN000; dec ax ; one below the lowest in the extent ;AN000; mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000; cmp bx,ax ; within low end ?? ;AN000; jne Fe_Curr_Prev ; no, create a new extent between ;AN000; ; current and previous extent mov Find_Flag,1 ; yes, set flag for LOW END continuity ;AN000; jmp Fe_Extent_found ; then RETURN ;AN000; ;-------------------------------------------------------------------------- ; Check the logical clus number has continuity at High end of the current ; extent cluster range. Check physical cluster number has continuity at the ; high end. If true, check the first logical and phys cluster number is the ; the same as this one. In this case clusters exist and therefore wont be ; insterted. ;-------------------------------------------------------------------------- Fe_CHK_HIGH_END: mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000; add ax,es:[si].EH_Count ; ending logical clus number ;AN000; inc ax ;AN000; mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; cmp bx,ax ; within high end ?? ;AN000; jg Fe_Chk_Next_Extent ; no, check next extent ;AN000; ; Logical clus num has high end continuity, Check the Physical cluster number ; for continuity. mov ax,es:[si].EH_Phys_Clus_Num ; starting phys clus number ;AN000; add ax,es:[si].EH_Count ; ending phys clus number ;AN000; inc ax ;AN000; mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000; cmp bx,ax ; within high end ?? ;AN000; jne Fe_Chk_Next_Extent ; no - check next extent ;AN000; ; ; Yes - check first logical and physical cluster number of next extent mov di,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000; cmp di, -1 ; any next extent ?? je Fe_High_End ; none - jump mov ax,es:[di].EH_Logic_Clus_Num ; starting logi clus number ;AN000; cmp ax,Logical_Clusnum ; logical cluster matches ?? jne Fe_high_end ; no - jump mov ax,es:[di].EH_Phys_Clus_Num ; starting phys clus number ;AN000; cmp ax,Physical_Clusnum ; physical cluster match ?? jne Fe_High_End ; no -jump stc ; clusters already exist in next extent jmp short Fe_Extent_Exit ; return ;AN000; Fe_High_End: mov Find_Flag,2 ; set flag for HIGH end continuity ;AN000; jmp short Fe_Extent_found ; then RETURN ;AN000; Fe_Chk_Cur_Next: cmp es:[si].EH_Next_Extn_Ptr, -1 ; Current extent last extent ?? ;AN000; je Fe_flag_4 ; yes, set flag-4 ;AN000; mov Find_Flag,5 ; set flag for new extent between ;AN000; jmp short Fe_Extent_Found ; current and next extent ;AN000; Fe_Flag_4: mov Find_Flag,4 ; set flag for new extent at the ;AN000; jmp short Fe_Extent_Found ; bottom end of current queue ;AN000; ;-------------------------------------------------------------------------- ; Given cluster number has no continuity but must stay between current extent ; and previous extent ;-------------------------------------------------------------------------- Fe_CURR_PREV: mov Find_Flag,3 ; set flag for between current and prev ;AN000; jmp short Fe_Extent_found ; then RETURN ;AN000; ;-------------------------------------------------------------------------- ; Given cluster number has no continuity. Try the next extent. ;-------------------------------------------------------------------------- Fe_Chk_NEXT_EXTENT: ; else try next extent mov ax,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000; cmp ax,-1 ; is this last extent ?? ;AN000; je Extent_at_Bottom ; yes, Clustr belongs to a new ;AN000; ; extent at the bottom ;AN000; mov Prev_Extn_Ptr,si ; save current extend as previous extnt mov si,ax ; SI-->Next extent ;AN000; mov Cur_Extn_Ptr, si ; save new extent as cur extent ;AN000; jmp Fe_Loop1 ; check next extent ;AN000; ;-------------------------------------------------------------------------- ; Given cluster number has no continuity but stays in a new extent at ; bottom (last) of the current queue. ;-------------------------------------------------------------------------- Extent_AT_BOTTOM: mov Find_Flag,4 ; else set flag for new extent ;AN000; Fe_Extent_Found: clc ;AN000; Fe_Extent_Exit: pop di RET ; exit ;AN000; FIND_CLUSTER_LOCATION ENDP ;----------------------------------------------------------------------- ; PROCEDURE: FIND_LRU_HEADER ; ; FUNCTION: Find address of the LRU header in the current queue ; ; INPUT: SI --> First header in the current queue ; ES--> Cache Buffer Segment ; ; OUTPUT: DI --> LRU header found ; ; LRU_Prev_Hdr = Previous header address ; LRU_Hdr = Address of LRU header found ; If Hdr_Flag = 1 - Header found is only header in the queue ; ;----------------------------------------------------------------------- FIND_LRU_HEADER PROC NEAR push bx ;AN000; mov hdr_flag,0 ; initilialize flags ;AN000; mov LRU_Prev_Hdr, -1 ; ;AN000; Flh_Loop1: cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header is last hdr ? ;AN000; jne Flh_next_header ; if not check next header ;AN000; mov di,si ; DI --> LRU header found ;AN000; mov LRU_Hdr,si ; save it ;AN000; jmp short Flh_header_found ; then take exit ;AN000; Flh_Next_Header: ; else try next header mov LRU_Prev_Hdr,si ; save previous header address ;AN000; mov si,es:[si].FH_Next_Hdr_ptr ;AN000; jmp Flh_Loop1 ; check next header ;AN000; Flh_Header_Found: cmp LRU_Prev_Hdr, -1 ; any previous header ?? ;AN000; je F1h_Set_Flag ; no, set flag ;AN000; clc ; yes ;AN000; jmp short F1H_Exit ; exit ;AN000; F1h_Set_Flag: mov hdr_flag,1 ; LRU header is the only hdr in queue ;AN000; clc ;AN000; F1h_Exit: ; exit pop bx ;AN000; ret ;AN000; FIND_LRU_HEADER endp ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PROCEDURE: FIND_LRU_EXTENT ; ; FUNCTION: Find address of LRU Extent under current header ; ; INPUT: ES--> Cache Buffer Segment ; SI--> Header to be searched ; ; OUTPUT: If CY = 0 LRU_Prev_Extent = Previous extent to the LRU extent ; LRU_Extent = LRU extent found ; Extn_Flag = 1 Extent is the only extent under header ; ; If CY = 1 Not found ; ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FIND_LRU_EXTENT PROC NEAR mov LRU_Prev_Extent, -1 ; reset flags ;AN000; mov LRU_Extent, -1 ; ;AN000; mov Extn_Flag, 0 mov si, es:[si].FH_MRU_Extn_Ptr ; SI--> First extent under header cmp si, -1 ; any extent under this header ?? jne Fle_Loop1 ; yes - check extent stc ; no - set flag jmp Fle_Exit ; exit Fle_Loop1: cmp es:[si].EH_Next_LRU_Ptr,-1 ; last extent in the queue?? jne Fle_next_extent ; if not found branch ;AN000; mov LRU_Extent,si ; save LRU extent address jmp short Fle_Extend_found ; exit Fle_Next_Extent: ; else try next extend mov LRU_Prev_Extent,si ; save previous extent address mov si,es:[si].EH_Next_LRU_Ptr ; get address of next extent jmp Fle_Loop1 ; check next extent ;AN000; Fle_Extend_Found: cmp LRU_Prev_Extent, -1 ; any previous extent ?? je Fle_Set_Flag ; no - set flag clc ; ;AN000; jmp short Fle_Exit Fle_Set_Flag: mov Extn_Flag, 1 ; set flag to indicate only flag clc Fle_Exit: ret ; exit ;AN000; FIND_LRU_EXTENT ENDP ;---------------------------------------------------------------------- ; PROCEDURE: Make_New_Header ; ; FUNCTION: Create a new header in the next available free area. ; Initialize the new header and make it MRU header ( move it ; to the top of the queue). If no free space in OPEN queue, delete ; and extent from the CLOSE queue. If no space in CLOSE queue, then ; delete an extent from OPEN Queue to make space. ; ; INPUT: Drive_Hdr_Ptr - Address of drive header ; Free_Ptr - Address of FREE area ; ES--> Cache Buffer Segment ; ; OUTPUT: Header is created ; ;---------------------------------------------------------------------- MAKE_NEW_HEADER PROC ; Check if the OPEN Queue was previously empty using two cases. If open queue ; is empty, then the new header should be marked as first header in the queue. mov Open_Queue_Flag, 0 ; clear flag open queue empty ;AN000; mov di,Drive_Hdr_Ptr ;AN000; ; case - 1 mov ax,es:[di].Free_Size ; FREE size ;AN000; cmp es:[di].Buff_Size,ax ; both are equal ? ;AN000; je Make_Set_Entries ; if true, this is the first header ;AN000; ; case - 2 cmp es:[di].MRU_Hdr_Ptr, -1 ; check for empty mark ;AN000; je Make_Set_Entries ; yes, set flag queue empty ;AN000; jmp short Make_Set_Entry2 ; not empty ;AN000; Make_set_Entries: ; set up File Header entries ; When creating first header under drive header, mark header as first ; This flag is set for this purpose. mov Open_Queue_Flag, 1 ; set flag open queue was empty ;AN000; Make_Set_Entry2: CALL FIND_FREE_BUFFER ; Look for some Free area. If none ;AN000; ;AN000; mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov New_Hdr_Ptr,ax ; save new Header address mov ax,es:[di].Free_Size ;AN000; CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; ; create some free area ;----------------------------------------------------------------------------- ; Connect the new header to the Top of the OPEN Queue. If the Queue is ; previously empty, mark the new header indicating nothing under this header. ;----------------------------------------------------------------------------- Join_To_Drive_Buff: mov di, drive_Hdr_Ptr ; DI-->drive buffer ;AN000; mov si,New_Hdr_Ptr ;AN000; mov Cur_Hdr_Ptr, si ; save as current header pointer ;AN000; mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header mov es:[di].MRU_Hdr_Ptr,si ; make new header MRU hdr ; When a header is created, it should contain no extents mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header with no extents ;AN000; mov es:[si].FH_MRU_Extn_Ptr,-1 ; ###mark header with no extents ;AN000; mov es:[si].FH_Refer_Count,1 ; save starting file reference count ;AN000; mov ax,First_Phys_Clusnum ;AN000; mov es:[si].FH_Phys_Clus_Num,ax ; save physical cluster number ;AN000; cmp Open_Queue_Flag, 1 ; OPEN Queue empty ?? ;AN000; je Set_Single_Header ; no, jump ;AN000; clc ret ;AN000; Set_Single_Header: ; yes mark new header as last hdr mov si,New_Hdr_Ptr ;AN000; mov es:[si].FH_Next_Hdr_Ptr,-1 ; mark as only header ;AN000; clc ret ; exit MAKE_NEW_HEADER ENDP ;---------------------------------------------------------------------- ; PROCEDURE: Find_Free_Buffer ; ; FUNCTION: Find free buffer space. If no free space, delete last extent ; under last header in the CLOSE queue. If none in CLOSE queue, ; delete the last extent of the LRU header in the OPEN queue. ; ; INPUT: Drive_Hdr_Ptr - Pointer to drive header ; ES--> Cache Buffer Segment ; ; OUTPUT: Released Header or extent buffer space will be addded to the ; Free area as discontinuous free area. Free size in drive head ; will be updated. ; ; If CARRY = 0 ; Free_Flag: 0 - Free area is continuous ; 1 - Free area is discontinuous ; ; if CARRY = 1 Fatal error ( no free space to spare ) ; ; NOTE: The deleted buffers have size same as the size of a header or extent. ; Each buffers first location contains a marker (-2) to indicate that ; the buffer is a discontinuous buffer. Each buffer is connected to ; the next dicontinous buffer through the 4th word. ; ;---------------------------------------------------------------------- FIND_FREE_BUFFER PROC NEAR mov di,drive_Hdr_Ptr ; DI-->Drive Header ;AN000; cmp es:[di].free_size,0 ; any free area left ?? ;AN000; je Free_Chk_Close_List ; none, check CLOSE queue ;AN000; mov si,es:[di].Free_Ptr ; check for discontinuous ;AN000; mov ax, -2 ;AN000; cmp es:[si], ax ; discontinuous free buffer?? ;AN000; je Free_Set_One ; yes, set flag for discontinuous mov Free_Flag,0 ; no, clear flag ;AN000; clc ;AN000; jmp Free_Exit Free_Set_one: mov Free_Flag,1 ; set flag ;AN000; clc ;AN000; jmp Free_exit ; yes, Free space is available ;AN000; ; exit ;-------------------------------------------------------------------------- ; No free space , look for space in CLOSE Queue. Search for the LRU header ; delete the header and any extents under this header. ;-------------------------------------------------------------------------- Free_Chk_Close_List: mov si,es:[di].CLOSE_Ptr ; SI-->CLOSE queue ;AN000; cmp si,-1 ; anything in CLOSE Queue ?? ;AN000; jne Free_Chk_CLOSE_QUE ; yes - get space from CLOSE queue jmp short Free_Look_Open_Queue ; if none, make space from OPEN Queue ;AN000; ; Else get space from CLOSE queue Free_Chk_Close_QUE: ; SI-->CLOSE queue mov si,es:[di].CLOSE_Ptr ; select OPEN Queue ;AN000; CALL FIND_LRU_HEADER ; find LRU header in CLOSE Queue ;AN000; ; DI-->LRU header ; Makesure to save all local variables before calling DELETE ; since, this variables may be altered by DELETE routine. mov ax,Hdr_Flag push ax mov ax,Prev_Hdr_Ptr push ax mov ax,Queue_Type push ax mov ax,Cur_Hdr_Ptr push ax mov ax,First_Phys_Clusnum ; save original first phys from OPEN call push ax ; in the stack mov cx,es:[di].FH_Phys_Clus_Num ; CX= starting phys clus num of LRU header mov From_FreeBuff,1 ; set flag push ds mov ax,Cseg_Main mov ds,ax assume ds:Cseg_Main CALL VECTOR_DELETE ; delete the file pop ds assume ds:Cseg_Seek mov From_FreeBuff,0 ; clear flag mov Free_Flag,1 ; set flag to indicate discontinuous free area pop ax ; restore first phys clus mov First_Phys_Clusnum,ax ; save it back where it belongs pop ax ; restore current header mov Cur_Hdr_Ptr,ax ; save it back where it belongs pop ax ; restore current header mov Queue_Type,ax ; save it back where it belongs pop ax ; restore current header mov Prev_Hdr_Ptr,ax ; save it back where it belongs pop ax ; restore current header mov Hdr_Flag,ax ; save it back where it belongs clc jmp Free_exit ; exit ;AN000; ;---------------------------------------------------------------------------- ; No space available in CLOSE Queue . Now get some free space from OPEN Queue ; and add it to the free area. ;---------------------------------------------------------------------------- Free_Look_Open_Queue: mov si,es:[di].MRU_Hdr_Ptr ; SI-->First header in OPEN Queue ;AN000; CALL FIND_LRU_HEADER ; find last header in Queue ;AN000; ; DI-->last header mov si,es:[di].FH_MRU_Extn_Ptr ;### SI-->first extent in this header ;AN000; cmp si, -1 ; any extent under this header ?? ;AN000; jne Free_Open_Find_Extent ; yes, find last extent ;AN000; ; if no extents under this header, delete this header and free the space cmp di,Cur_Hdr_Ptr ; header found is its own header ?? ;AN000; jne Free_OPen_Mark_Prev ; no - free the header ;AN000; stc ; Yes - set carry, exit ;AN000; jmp Free_Exit ; ERROR exit ;AN000; Free_Open_Mark_Prev: ; mark previous header as LRU before deleting this header mov si,LRU_Prev_Hdr ; SI-->previous header ;AN000; mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous header as last hdr ;AN000; jmp Free_Open_Cl_Buffer ;AN000; Free_Open_Find_Extent: mov si,di ; SI-->header to be searched CALL FIND_LRU_EXTENT ; ### find last extent in the header ;AN000; mov di, LRU_Extent ; DI-->LRU extent cmp Extn_flag,1 ; Is this the only extent in the queue ? ;AN000; jne free_Open_prev_extn ; no, mark previous extent as last extn ;AN000; push di ; save pointer to Last extent ;AN000; mov di,LRU_Hdr ; DI-->LRU header ;AN000; mov es:[di].FH_Next_Extn_Ptr,-1 ; mark current HEADER with no extents ;AN000; mov es:[di].FH_MRU_Extn_Ptr,-1 ; ### mark current HEADER with no extents ;AN000; pop di ; DI-->LRU extent ;AN000; jmp Free_Open_Cl_Buffer ; release this extent ;AN000; ;---------------------------------------------------------------------- ; Mark Previous MRU extent as LRU extent and also connect the previous ; adjucent extent to the next adjcent extent. ;---------------------------------------------------------------------- Free_Open_Prev_Extn: ; mark previous MRU extent as LRU extnt mov si, es:[di].EH_Prev_LRU_Ptr ; no - SI-->Previous adj extent mov es:[si].EH_Next_LRU_Ptr, -1 ;mark previous extent as last extent ;AN000; cmp es:[di].EH_Next_Extn_Ptr, -1 ; any next adjucent extent ?? jne OPen_Join_extents ; yes - join previous to next mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent cmp si, -1 ; any previous adj extent ?? je Open_Prev_Hdrx ; no - previous is a header mov es:[si].EH_Next_Extn_Ptr, -1 ; mark previous extent as the last jmp short Free_Open_Cl_Buffer ; free the current extent Open_Prev_Hdrx: push di ; DI-->extent to be deleted mov di,LRU_Hdr ; DI-->LRU header mov es:[di].FH_Next_Extn_Ptr, -1 ; mark header with no extents mov es:[di].FH_MRU_Extn_Ptr, -1 ; mark header with no extents pop di jmp short Free_Open_Cl_Buffer ; free current extent Open_Join_Extents: ; DI-->current extent to be freed mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent cmp si, -1 ; any previous extent ?? je Open_Prev_Hdry ; no - previous is a header - join header ; to extent mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent mov es:[si].EH_Next_Extn_Ptr,ax ; connect prev adj extent to next adj extent push di ; save addrs of extent to be deleted mov di, ax ; SI = address of previous LRU extent mov es:[di].EH_Prev_Extn_Ptr,si ; address of next LRU extent pop di ; restore address jmp short Free_Open_Cl_Buffer ; free the extent Open_Prev_Hdry: mov si, LRU_Hdr ; SI-->LRU_Hdr mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent mov es:[si].FH_Next_Extn_Ptr,ax ; connect hdr to next adj extent mov si,ax ; SI = addrss of next adj extent mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark no previous extent mov di,LRU_Extent ; DI-->extent to be deleted ;---------------------------------------------------------------------------- ; Free the current Extent or Header ;---------------------------------------------------------------------------- Free_Open_Cl_Buffer: ; mov si,di ; SI-->LRU extent or header ;AN000; mov di,Drive_Hdr_Ptr ; DI-->drive buffer ;AN000; mov ax,es:[di].Free_Ptr ;AN000; mov es:[si].EH_Next_Extn_Ptr,ax ; connect Free ptr to last ;AN000; ; extent in the queue mov ax, -2 ; discontinuous mark (-2) ;AN000; mov es:[si], ax ; mark freed area as discontinuous ;AN000; mov es:[di].Free_Ptr,si ; connect header or extent to free area ;AN000; ; Increase the Free_Size entry in Drive Header mov ax, Size File_Header ; size is same for both header or extent ;AN000; add es:[di].Free_Size, ax ; update free buffer count ;AN000; mov Free_Flag,1 ; set flag for discontinuous free area ;AN000; clc Free_Exit: ; exit ret ; return ;AN000; FIND_FREE_BUFFER endp ;---------------------------------------------------------------------- ; PROCEDURE: Make_MRU_Header ; ; FUNCTION: Move header to the top of the queue. If the header is at the ; bottom of the queue, mark previous header as LRU header ; before moving the header to the top of the queue. ; ; INPUT: Drive_Hdr_Ptr - Points to drive header ; Cur_Hdr_Ptr - Points to current header ; ES--> Cache Buffer Segment ; ; OUTPUT: Header is moved to top of the current queue ; SI-->current header ; ;---------------------------------------------------------------------- MAKE_MRU_HEADER PROC NEAR mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header LRU header ;AN000; jne Move_close_gap ; no, jump ;AN000; ;AN000; mov di,Prev_Hdr_Ptr ; yes, make previous header mov es:[di].FH_Next_Hdr_Ptr,-1 ; LRU header ;AN000; jmp short move_to_top Move_Close_Gap: mov di,Prev_Hdr_Ptr ; yes, get previous header mov ax,es:[si].FH_Next_Hdr_Ptr ; get next header address mov es:[di].FH_Next_Hdr_Ptr,ax ; connect previous hdr to next hdr ;AN000; Move_To_Top: mov di,drive_Hdr_Ptr ; DI-->drive buffer ;AN000; mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000; mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header ;AN000; mov es:[di].MRU_Hdr_Ptr,si ; make current header MRU hdr ;AN000; ; ret Make_MRU_Header ENDP ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PROCEDURE: MAKE_MRU_EXTENT ; ; FUNCTION: Move Extent to the top of the queue. If the extent is at the ; bottom of the queue, mark previous extent as LRU extent ; before moving the extent to the top of the queue. If the extent ; is between first and last, then close the MRU-LRU chain gap. ; If the extent is already MRU then exit. ; ; This routine is called if clusters are inserted or looked up ; from an existing extent. ; ; INPUT: Cur_Hdr_Ptr - Address of current header ; Cur_Extn_Ptr - Address of current extent ; ES--> Cache Buffer Segment ; ; OUTPUT: Extent is moved next to the current header ; SI-->current extent ; ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MAKE_MRU_EXTENT PROC NEAR mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; mov ax,Cur_Extn_Ptr cmp es:[si].FH_MRU_Extn_Ptr, ax ; current extent already MRU?? ;AN000; je Make_MRU_Exit ; yes - exit mov si, Cur_Extn_Ptr ; SI-->Current extent mov di,es:[si].EH_Prev_LRU_Ptr ; get address of previous MRU extent cmp di, -1 ; any previous MRU extent ?? je Make_MRU_Exit ; none - exit- current extent is already MRU ; Close the gap (connect previous to next extent) mov si, Cur_Extn_Ptr cmp es:[si].EH_Next_LRU_Ptr, -1 ; current extent LRU extent ?? jne join_the_gap ; no - close the gap mov es:[di].EH_Next_LRU_Ptr, -1 ; mark the previous extent MRU jmp short move_MRU_Extent ; make mru extent Join_The_Gap: mov ax, es:[si].EH_Next_LRU_Ptr ; AX-->next LRU extent mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous to next mov bx,di ; BX-->prev LRU extent mov di,ax ; DI-->Next LRU extent mov es:[di].EH_Prev_LRU_Ptr, bx ; set previous LRU extent address ; Make the current extent MRU extent Move_MRU_Extent: mov di,Cur_Hdr_Ptr ; DI-->Current header mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent mov di,ax ;(12/29) set prev LRU addrs of prev MRU extent mov es:[di].EH_Prev_LRU_Ptr,si ;(12/29) Make_MRU_Exit: clc ret ; return MAKE_MRU_EXTENT ENDP ;---------------------------------------------------------------------- ; PROCEDURE: JOIN_PREV_TO_NEXT ; ; FUNCTION: Connect previous header to next header inorder to close the ; gap created when a header is moved to top of the Queue or to ; the top of CLOSE queue. If the file header is the first header ; under the current Drive header, connect header to the MRU_Hdr_Ptr. ; ; INPUT: Prev_Hdr_Ptr - Points to Previous header ; Cur_Hdr_Ptr - Points to Current Header ; Queue_Type - Queue Type: 0 = Open Queue ; 1 = Close Queue ; ES--> Cache Buffer Segment ; OUTPUT: Gap is closed ; ;---------------------------------------------------------------------- JOIN_PREV_TO_NEXT PROC cmp Prev_Hdr_Ptr, -1 ; current hdr first file header ?? ;AN000; jne join_prev_hdr ; no, close gap ;AN000; ; Yes, in this case close gap by connecting Drive header to next header mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; mov ax,es:[si].FH_Next_Hdr_Ptr ; AX-->Next Header ;AN000; cmp Queue_Type, 1 ; Is this Close Queue ?? ;AN000; je Join_Sel_Close_Ptr ; Yes, jump ;AN000; mov es:[di].MRU_Hdr_Ptr,ax ; join next header to Drive Header ;AN000; jmp short join_exit ; exit ;AN000; Join_Sel_Close_Ptr: mov es:[di].Close_Ptr,ax ; join next header to Drive Header ;AN000; jmp short join_exit ; exit ;AN000; ; Connect previous header to next header ( close the gap ) Join_Prev_Hdr: mov di,Prev_Hdr_Ptr ; DI-->Previous header ;AN000; mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; mov ax,es:[si].FH_Next_Hdr_Ptr ; connect previous header ;AN000; mov es:[di].FH_Next_Hdr_Ptr,ax ; to next header ;AN000; Join_Exit: ret ; exit ;AN000; JOIN_PREV_TO_NEXT ENDP ;---------------------------------------------------------------------- ; PROCEDURE: UPDATE_FREE_AREA ; ; FUNCTION: Update Free area pointer and Free area size before creating ; a new extent or new header ; ; INPUT: Prev_Hdr_Ptr - Points to Previous header ; Cur_Hdr_Ptr - Points to Current Header ; Queue_Type - Queue Type: 0 = Open Queue ; 1 = Close Queue ; Free_Flag - Free area type: 0 = continous free area ; 1 = non-contiguous free area ; ES--> Cache Buffer Segment ; ; ; OUTPUT: Free pool address and size is updated ; ;---------------------------------------------------------------------- UPDATE_FREE_AREA PROC mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; mov si,es:[di].Free_Ptr ; SI-->current free pointerted ;AN000; ; mov ax, Size Extent_Header ;AN000; sub es:[di].Free_Size, ax ; update free area size ;AN000; cmp Free_Flag, 1 ; continuous free area ?? ;AN000; jne ext_add_free_ptr ; yes - update free area pointer ;AN000; ;---------------------------------------------------------------------- ; If discontinuous Free area. Update the Free pointer by getting pointer ; to next free from the 4th word using header or extent structure. ; This is because the discontinuous areas are connected chained through ; the 4th word ;---------------------------------------------------------------------- mov ax,es:[si].FH_Next_Hdr_Ptr ; no, update FREE area pointer ;AN000; mov es:[di].Free_Ptr,ax ; using the Header structure ;AN000; jmp short Update_Free_Exit ; Exit ;AN000; ;---------------------------------------------------------------------- ; If continuous Free area. Next free area address is computed by adding ; the size of extent of header structure. ;---------------------------------------------------------------------- Ext_Add_Free_Ptr: mov ax, size File_Header ; calculate the address of ;AN000; add es:[di].Free_Ptr,ax ; next free area by adding size of ;AN000; ; a extent or header. Both same size Update_Free_Exit: ret ; exit ;AN000; UPDATE_FREE_AREA ENDP ;---------------------------------------------------------------------- ; Procedure: CHECK_IT Checks the validity of the queues ; ;---------------------------------------------------------------------- CHECK_IT PROC NEAR pushf ; save all registers push bx push di cmp check_flag,0 je check_exit mov ah,090h xor al,al xor cx,cx mov cl,func_cod mov di, Drive_Hdr_Ptr INT 2FH check_exit: pop di pop bx popf ret CHECK_IT ENDP ; Calculate the size of the Cseg_Seek module in bytes IF ($-Cseg_Seek) MOD 16 ;AN000; ORG ($-Cseg_Seek)+16-(($-Cseg_Seek) MOD 16) ;AN000; ENDIF ;AN000; END_SEEK label word CSEG_SEEK ENDS END