summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FASTOPEN
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/FASTOPEN')
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTINIT.ASM2970
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM2052
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK7
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL28
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT615
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTP.ASM131
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM2944
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTSEGS.INC20
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTSM.ASM145
-rw-r--r--v4.0/src/CMD/FASTOPEN/MAKEFILE47
10 files changed, 8959 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM b/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM
new file mode 100644
index 0000000..db21b58
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM
@@ -0,0 +1,2970 @@
1 Page 84,132 ;
2
3TITLE FASTINIT - initialization code for FASTOPEN (May 13, 1988)
4
5;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
6; The entire Fastopen component is divided into 5 modules. They are:
7; Fastopen initialization routine-1, Fastopen initialization routine-2,
8; Fastopen which manages the directory/file cache buffers, the Fastseek
9; which manages the cluster information cache buffers and the
10; cache buffer which holds both directory and cluster information.
11;
12; These modules resides in different segments for the reason that they can
13; be overlayed conditionally, depending on the user request. For example
14; initially all segments are loaded into the memory. If fastopen reature is
15; not requested, the segment which contains Fastseek will be overlayed over
16; original Fastopen to save space. Segmentation is also usefull when Fastopen
17; and Fstseek need to copy into Expanded memory. Following figure shows
18; memory map of the FastOpen.
19;
20; Modules Segment
21;
22; Ú-------------------¿
23; ³ MAIN ³ CSEG_MAIN
24; Ã-------------------´
25; ³ FASTINIT1 ³ CSEG_MAIN
26; Ã-------------------´
27; ³ ³
28; ³ FASTOPEN ³ CSEG_OPEN
29; ³ ³
30; Ã-------------------´
31; ³ ³
32; ³ FASTSEEK ³ CSEG_SEEK
33; ³ ³
34; Ã-------------------´
35; ³ FASTINIT2 ³ CSEG_INIT
36; Ã-------------------´
37; ³ ³
38; ³ NAME AND ³
39; ³ EXTENT ³
40; ³ CACHE BUFFERS ³ CSEG_INIT
41; ³ ³
42; À-------------------Ù
43;
44; MAIN: This module provides DOS entry point into FASTOPEN. It also
45; dispatch various Fastopen and Fastseek functions. This module is
46; in the file FASTOPEN.asm
47;
48; FASTINIT-1: This module is called INIT_TREE which is also a part of the
49; Cseg_Main segment. This basically initializes both
50; Name and Extent drive headers, and sets up name and extent
51; cache buffers. This module can be found in the file
52; FASTINIT.asm
53;
54; FASTINIT-1: This module is called INIT which is part of the Cseg_Init
55; segment. This module parses the user commad, check memory
56; requirements, overlay Fastopen and Fastseek code and finally
57; installs the Fastopen to be stay resident. This module is
58; eventually overlayed by the cache buffers created during the
59; buffer initialization by FASTINIT-1 ( See INIT_TREE)
60; This module can be found in FASTINIT.asm
61;
62; FASTOPEN: This module is a collection of four Fastopen functions which
63; manage the File/Directory cache buffers. These functions are
64; in the file FASTOPEN.asm
65;
66; FASTSEEK: This module is a collection of six FastSeek functions which
67; manage queues associated with the cluster information
68; cache buffers. This module is found in the file FASTSEEK.asm.
69;
70;
71; Fastopen Code and Cache buffer Relocation
72; -----------------------------------------
73; If user specifies both n and m in the user command and /x, then
74; Cseg_Open, Cseg_Seek and Cseg_Init will be copied into a 16K page of the
75; Expanded Memory. If only n is specified, then Cseg_Open and Cseg_Init will
76; be copied. If only m is specified, then Cseg_Seek and Cseg_init will be
77; copied. After this the total size of the segments transferred will be
78; deblocked from the low memory to save available user space.
79;
80; If /x is not specified and only n is specified, then the Cseg_Init will
81; moved over to Cseg_Seek which is followed by a deblock of memory. If only
82; m is specified, then Cseg_Seek will moved over to Cseg_Open and the
83; Cseg_Init will be moved over to Cseg_Seek then deblocks the size Cseg_Open.
84;
85; WARNING: After every move you have to recalculate the Seg ID of moved
86; modules depending on how far it has been displaced and then
87; replace the Seg ID in the jump vectors used for accessing
88; functions in the moved modules. A wrong Seg ID can cause
89; instant System CRASH ...@%+(@!$#@@*&...
90;
91; Future Enhancements:
92;
93; 1. Modify Fastopen so that it can be run on removable media (Diskette).
94; At present only fixed disk is supported.
95;
96; 2. Allocate all Extent buffers during initialization. Now they are
97; done in run time. This may avoid using flags (-2) for discontinuous
98; buffers. Using (-2) requires buffers be filled with '0's during PURGE.
99;
100; 3. Mark the LRU extent every time buffer is changed, so that the
101; the buffers need not be searched during buffer recycling
102;
103; 4; Currently Fastopen code and cache is kept in one 16K page of the
104; Extended Memory. This puts a restriction on the size of the cache
105; buffer available in EMS usually about 8K. This can be avoided by
106; keeping code and cache buffers in two seperated pages, so that maximum
107; of 16K is available for cache buffers.
108;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
109;
110IF1
111 %OUT ASSEMBLING: FASTINIT - FASTOPEN initialization
112ENDIF
113NAME FASTINIT
114
115.XCREF
116.XLIST
117
118
119TRUE EQU 0FFFFh ;AN000;
120FALSE EQU 0 ;AN000;
121
122DBCS = FALSE ;AN000;
123Installed = TRUE ;AN000;
124
125IFNDEF DEBUG
126 DEBUG = FALSE
127ENDIF
128
129INCLUDE dosmac.inc ;AN000;
130INCLUDE vector.inc ;AN000;
131INCLUDE filemode.inc ;AN000;
132INCLUDE mult.inc ;AN000;
133include version.inc
134
135.LIST
136.CREF
137
138INCLUDE fastsegs.inc ;AN000;
139INCLUDE fastopen.inc ;AN000;
140INCLUDE SYSCALL.INC ; ;AN000;
141
142;-----------------------------------------------------------------------
143; EQUATES
144;-----------------------------------------------------------------------
145Top_mem EQU 02h ;Top of memory index in PSP ;AN000;
146Min_entry_num EQU 10 ;minimum name cache entries ;AN000;
147Max_entry_num EQU 999 ;maximum name cache entries ;AN000;
148Default_names EQU 34 ;default name cache entries ;AN000;
149Debug EQU 0 ;for callinstall ;AN000;
150Len_source_xname EQU 4 ;used for xname translate ;AN000;
151No_siblings EQU -1 ;indicate no siblings ;AN000;
152No_child EQU -1 ;indicate no children ;AN000;
153No_backward EQU -1 ;no backward pt yet ;AN000;
154Max_drives EQU 24 ;maximum number of drives allowed ;AN000;
155
156
157; ----------------- MESSAGE EQUATES -------------------------------------
158
159Not_enough_mem EQU 2 ;AN000;
160Invalid_switch EQU 3 ;AN000;
161Install1 EQU 4 ;AN000;
162Already_install EQU 5 ;AN000;
163Incorrect_param EQU 6 ;AN000;
164Too_many_entries EQU 7 ;AN000;
165Dup_drive EQU 8 ;AN000;
166Invalid_extent EQU 11 ;AN000;
167Invalid_name EQU 12 ;AN000;
168Ems_failed EQU 13 ;AN000;
169Ems_not_install EQU 14 ;AN000;
170Invalid_drive EQU 15 ;AN000;
171No_page_space EQU 16 ;AN000;
172Bad_Use_Message EQU 17
173Many_Ext_Entries EQU 18
174Many_Name_Entries EQU 19
175
176
177;------------ E M S SUPPORT EQUATES -------------------------------
178
179EMS_GET_STATUS EQU 40H ;AN000;
180EMS_GET_NUM_PAGES EQU 42H ;AN000;
181EMS_ALLOC_PAGES EQU 43H ;AN000;
182EMS_MAP_HANDLE EQU 44H ;AN000;
183EMS_GET_VERSION EQU 46H ;AN000;
184EMS_SAVE_STATE EQU 47H ;AN000;
185EMS_RESTORE_STATE EQU 48H ;AN000;;AN000;
186EMS_PAGE_SIZE EQU 4FH ;AN000;;AN000;
187EMS_2F_HANDLER EQU 1BH ;AN000;;AN000;
188
189IF NOT IBMCOPYRIGHT
190
191EMS_GET_COUNT EQU 5801H
192
193ELSE
194
195EMS_GET_COUNT EQU 5800H ;AN000;
196
197ENDIF
198
199EMS_GET_FRAME_ADDR EQU 5800H ;AN000;
200EMS_HANDLE_NAME EQU 53H
201EMS_INT EQU 67H ;AN000;
202SINGLE_SEGMENT EQU 1 ;AN000;
203
204
205;-------------------- STRUCTURES ---------------------------------
206
207PAGE_FRAME_STRUC STRUC ; EMS page frame structure ;AN000;
208
209 PAGE_SEG DW ? ;EMS page segment ;AN000;
210 PAGE_NUM DW ? ;EMS page number (only one page is used) ;AN000;
211
212PAGE_FRAME_STRUC ENDS
213
214BUFFER_ENTRY_SIZE EQU TYPE PAGE_FRAME_STRUC
215
216
217SUB_LIST STRUC ; Message handler sublist structure ;AN000;
218 DB 11 ; ;AN000;
219 DB 0 ; ;AN000;
220DATA_OFF DW 0 ; offset of data to be inserted ;AN000;
221DATA_SEG DW 0 ; offset of data to be inserted ;AN000;
222MSG_ID DB 0 ; n of %n ;AN000;
223FLAGS DB 0 ; Flags ;AN000;
224MAX_WIDTH DB 0 ; Maximum field width ;AN000;
225MIN_WIDTH DB 0 ; Minimum field width ;AN000;
226PAD_CHAR DB 0 ; character for pad field ;AN000;
227SUB_LIST ENDS ;AN000;
228
229;-------------------------------------------------------------------------------
230; Following two segments are used to define external variable that
231; are defined in two other segments.
232;-------------------------------------------------------------------------------
233
234CSEG_OPEN SEGMENT PARA PUBLIC 'CODE' ; Cseg_Open segment
235 EXTRN Open_name_cache_seg:word
236 EXTRN Open_Name_Drive_Buff:word
237 EXTRN End_Open:byte
238 EXTRN Chk_Flag:word
239 EXTRN VECTOR_LOOKUP:dword ; jump vector inside Cseg_Main to make
240 ; a FAR call to Fopen LookUp function within
241 ; the segment
242CSEG_OPEN ENDS
243
244
245CSEG_SEEK SEGMENT PARA PUBLIC 'CODE' ; Cseg_Seek segment
246 EXTRN Seek_Extent_Drive_buff:word
247 EXTRN Seek_Name_Drive_buff:word
248 EXTRN Seek_Name_Cache_buff:word
249 EXTRN Seek_Name_Cache_Seg:word
250 EXTRN Seek_Num_Of_Drives:word
251 EXTRN Seek_Total_Ext_Count:word
252 EXTRN Seek_Total_Name_Count:word
253 EXTRN End_Seek:byte
254 EXTRN Check_Flag:word
255 EXTRN VECTOR_DELETE:dword ; jump vector inside Cseg_Seek to make
256 ; a FAR call to FSeek Delete function within
257 ; the segment
258CSEG_SEEK ENDS
259
260
261
262
263
264;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
265CSEG_MAIN SEGMENT PARA PUBLIC 'CODE' ; MAIN segment
266
267; This segment is a continuation of the Cseg_Main segment in Fastopen.asm
268; and contains code to initializes name and extent drive buffers
269;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
270ASSUME CS:cseg_main,DS:nothing,SS:stack,ES:nothing
271
272EXTRN MAIN:FAR ;AN000;
273
274IF BUFFERFLAG
275
276extrn restore_page_state:near ; HKN 8/25/88
277
278extrn ems_save_handle1:word ; HKN
279extrn ems_page_number:word ; HKN
280
281ENDIF
282
283EXTRN Main_Total_Ext_Count:word ;AN000;
284EXTRN Main_Total_Name_Count:word ;AN000;
285EXTRN Main_Name_Drive_Buff:word ;AN000;
286EXTRN Main_Name_Cache_Buff:word ;AN000;
287EXTRN Main_Name_Cache_Seg:word ;AN000;
288EXTRN Main_Parambuff:byte ;AN000;
289EXTRN Main_extent_drive_Buff:word ;AN000;
290EXTRN Main_Num_Of_drives:word ;AN000;
291EXTRN Main_Ext_Count:word ;AN000;
292EXTRN Main_Ext_Cache_Size:word ;AN000;
293EXTRN Main_EMS_FLAG:word ;AN000;
294EXTRN Main_Res_Segs:word ;AN000;
295EXTRN Main_EMS_PAGE_SEG:word ;AN000;
296EXTRN Main_EMS_PAGE_SIZE:word ;AN000;
297
298EXTRN FOPEN_Insert:dword ;AN000;
299EXTRN FOPEN_Update:dword ;AN000;
300EXTRN FOPEN_Delete:dword ;AN000;
301EXTRN FOPEN_Lookup:dword ;AN000;
302IF BUFFERFLAG
303EXTRN FOPEN_Purge:dword
304ENDIF
305
306EXTRN FSEEK_Open:dword
307EXTRN FSEEK_Close:dword
308EXTRN FSEEK_Insert:dword
309EXTRN FSEEK_Delete:dword
310EXTRN FSEEK_Lookup:dword
311EXTRN FSEEK_Truncate:dword
312EXTRN FSEEK_Purge:dword
313
314;*************************************************************************
315;
316;SUBROUTINE: INIT_TREE (FASTINIT-1)
317;
318;FUNCTION: This routine builds 'N' name directory buffers under each drive
319; header. The second half of this routine initializes the extent
320; drive headers and makes the Fastopen code resident.
321;
322;INPUT: Drive_cache_header, End_Caches
323;
324;OUTPUT: Name_cache and Extent Cache entries installed for every
325; drive requested.
326;
327;*************************************************************************
328 IF ($-Cseg_Main) MOD 16 ;AN000;
329 ORG ($-Cseg_Main)+16-(($-Cseg_Main) MOD 16) ;AN000;
330 ENDIF ;AN000;
331End_Main1 label word ;AN000;
332
333
334INIT_TREE:
335 mov ax,cseg_Main ;get addressiblity to ;AN000;
336 mov ds,ax ;DS --> Cseg_Main ;AN000;
337 ASSUME ds:cseg_Main ;AN000;
338
339 cmp Main_Total_Name_Count,0 ;initialize Name drive headers?? ;AN000;
340 je Init_Ext_Drive_Hdrs ;no, init extent drive headers ;AN000;
341
342;-----------------------------------------------------------------------------
343; Following code adds 'n' directory entry buffers to each Name Drive headers,
344; depending on the value of 'n' specified with each drive ID
345;-----------------------------------------------------------------------------
346 mov si,Main_Name_Drive_Buff ;SI-->first Name drive cache buff
347 mov bx,Main_Name_Cache_Buff ;BX-->Name cache buffer
348 xor dx,dx
349 xor ax,ax
350
351 mov ax,Main_Name_Cache_Seg ;get addresability to CSeg_Init
352 mov ds,ax ;DS=addressablity to Cseg_Init
353 ASSUME ds:cseg_Init
354
355Set_Up_Cache:
356 mov [si].DCH_LRU_ROOT,bx ;set to point to first name
357 mov [si].DCH_NAME_BUFF,bx ;set to point to first name
358 mov cx,[si].DCH_num_entries ;get number of name records
359
360;-----------------------------------------------------------------------------
361; set up MRU and LRU pointers
362; AX points to last name record
363; BX points to current name record
364; DX points to next name record
365;-----------------------------------------------------------------------------
366 mov [bx].nMRU_ptr,-1 ;make first MRU -1
367 jmp short set_start
368
369Set_Up_Names:
370 mov [bx].nMRU_ptr,ax ;set up MRU
371 add ax,size name_record
372
373Set_Start:
374 mov [bx].nChild_ptr,no_child ;no children or siblings
375 mov [bx].nsibling_ptr,no_siblings ; right now
376 mov [bx].nBackward_ptr,no_backward
377 push es
378 push di
379 push ax
380
381 push ds
382 pop es ;ES-->name cache buffer
383 ASSUME es:Cseg_Init
384
385 mov ax, ' '
386 mov di, bx
387 add di, nCmpct_Dir_Info ;blank out the Dir name area
388 stosb ;the directory buffer
389 stosw
390 stosw
391 stosw
392 stosw
393 stosw
394
395 pop ax
396 pop di
397 pop es
398
399 mov dx,bx ;get name offset
400 add dx,size name_record ;get start of next name
401 dec cx ;decrement num_entries
402 jcxz get_next_drive ;if zero - get next drive
403 mov [bx].nLRU_ptr,dx ;LRU pointer - next name
404 add bx,size name_record ;
405 jmp set_up_names
406
407Get_Next_Drive:
408 mov [bx].nLRU_ptr,-1 ;LRU pointer - next name
409
410 mov [si].DCH_MRU_ROOT,bx ;set to point to last name
411 mov bx,dx ;get pointer to next name
412 cmp [si].dch_sibling_ptr,no_siblings ;is there any more to set up??
413 jz Init_Ext_Drive_Hdrs ; no - set extent drive headers
414 add ax,size name_record ; yes - get next name directory buffer
415 add si,size drive_cache_header ;point to next drive header
416 jmp set_up_cache
417
418
419;----------------------------------------------------------------------------
420; The following section initializes the Extent Drive Headers.
421; DS has addressability to MAIN segment (CSEG_MAIN) and ES has
422; addressability to Cache buffer segment (CSEG_INIT)
423;----------------------------------------------------------------------------
424Init_Ext_Drive_Hdrs:
425 mov ax,cseg_Main ;AN000;
426 mov ds,ax ;DS-->Cseg_Main ;AN000;
427 ASSUME ds:cseg_Main ;AN000;
428 ;AN000;
429 cmp Main_Total_Ext_Count,0 ;initialize extent drive buffers ?? ;AN000;
430 jne init_extent_cache ;yes - continue
431 jmp Init_exit ;no - exit ;AN000;
432
433;============================================================================
434; Fill extent cache buffer with zeros. Otherwise a (-2) left in the buffer
435; could generate a wrong Free buffer pointer since (-2) is the free buffer
436; mark.
437
438Init_Extent_Cache:
439 mov cx, Main_Ext_Cache_Size ; CX = extent buffer size ;AN000;
440 mov si,Main_Extent_Drive_Buff ; SI-->start of extent cache buff ;AN000;
441 push ds ;AN000;
442 mov ax,Main_Name_Cache_Seg
443 mov ds,ax ; DS-->new init seg (init segment ;AN000;
444 ASSUME ds:Cseg_Init ;AN000;
445 mov al,0 ; pattern "0" ;AN000;
446
447Next_Byte: ; may be in Extended memory)
448 mov [si],al ;AN000;
449 inc si ;AN000;
450 LOOP next_byte ;AN000;
451 pop ds ; retore original init seg ID ;AN000;
452;============================================================================
453
454
455Init_Set_Cache:
456 mov si,Main_Extent_Drive_Buff ; SI-->first extent drive header ;AN000;
457 mov cx,Main_num_of_drives ; number of drives
458 mov dx,0 ; drive counter
459 lea di,Main_ParamBuff ; DS:DI-->parameter buff contains ;AN000;
460 ; drive ID and number of extents ;AN000;
461 mov es,Main_name_cache_seg ; ES = addressability to Cseg_Init ;AN000;
462 ASSUME es:Cseg_Init ; ;AN000;
463 ;AN000;
464INIT_LOOP: ; ES:SI-->cache buffer ;AN000;
465 push cx ; save counter ;AN000;
466 add di,dx ; points to drive ID of this driv ;AN000;
467 xor ax,ax ;AN000;
468 mov ax,[di+2] ; get Extent Count ;AN000;
469 cmp ax, -1 ; any extent under this drive ?? ;AN000;
470 je skip_this_drive ; no - dont create header for this ;AN000;
471 ; this drive
472 mov ax,0 ; *** for debugging sequence count
473 mov es:[si].EXTENT_COUNT,ax ; *** use this area for sequence counting
474 xor ax,ax ;AN000;
475 mov ax,[di] ; get drive ID from drive ID buff ;AN000;
476 mov es:[si].DRIVE_NUMBER,ax ; save drive ID in drive header ;AN000;
477 mov bx, size Drive_Header ;AN000;
478 add bx,si ; BX-->Free area ;AN000;
479 mov es:[si].FREE_PTR,bx ; pointing to free area ;AN000;
480 ;AN000;
481 mov es:[si].MRU_HDR_PTR,-1 ; mark OPEN QUEUE empty ;AN000;
482 mov es:[si].CLOSE_PTR,-1 ; make CLOSE QUEUE empty ;AN000;
483 xor ax,ax ;AN000;
484 mov ax,[di+2] ; get extent count (n) ;AN000;
485 mov cx, size Extent_Header ; get extent size ;AN000;
486 mul cx ; AX=total cache for this drive ;AN000;
487 mov es:[si].BUFF_SIZE,ax ; save it as initial available size ;AN000;
488 mov es:[si].FREE_SIZE,ax ; save it as initial free size
489 add ax, size Drive_Header ; (2/9/88)
490 add ax,si ; AX-->offset to next drive hdr ;AN000;
491 mov es:[si].Next_Drv_hdr_Ptr,ax ; save next drive header ptr in ;AN000;
492 ; current drive header ;AN000;
493 mov bx,ax ;AN000;
494 mov ax,si ; save current header pointer ;AN000;
495 mov si,bx ; DS:SI-->next drive header ;AN000;
496 ;AN000;
497SKIP_THIS_DRIVE: ;AN000;
498 add dx,4 ; update index to next drive/extent ;AN000;
499 pop cx ; restore loop count ;AN000;
500 LOOP init_loop ; repeat for next drive number ;AN000;
501 ;AN000;
502 mov si,ax ;AN000;
503 mov es:[si].Next_Drv_hdr_Ptr,-1 ; mark current header as last
504 ; drive header
505;----------------------------------------------------------------------------
506; Close handles 0 - 4
507;----------------------------------------------------------------------------
508 mov bx,0
509Handle_Loop:
510 mov ah,03EH
511 INT 21H
512 inc bx
513 cmp bx,5
514 jne Handle_Loop
515
516;----------------------------------------------------------------------------
517; Get PSP segment and find the program environment segment and deallocate
518; the environment space.
519;----------------------------------------------------------------------------
520INIT_EXIT:
521 push ds
522 mov si,0081H
523 mov ah,62H
524 INT 21H ; get program PSP segment ;AN000;
525
526 mov ds,bx ; DS = PSP segment ;AN000;
527 mov si,02CH ; SI-->address of enviroment segment
528 mov ax,[si] ; AX = environment seg id
529 cmp ax,0 ; environment present ??
530 je dont_dealloc ; no - dont deallocate
531 mov es,ax
532 mov ah,49H
533 INT 21H ; deallocate environment
534Dont_Dealloc:
535 pop ds ; restore DS
536
537;----------------------------------------------------------------------------
538; Keep resident the Fastopen code and cache buffers. The size of the resident
539; area is in (Main_Res_Segs). Size may vary depending on whether Fastopen or
540; Fastseek or both or extent memory is specified.
541;----------------------------------------------------------------------------
542
543IF BUFFERFLAG
544
545 call restore_page_state ; HKN 8/25/88
546
547ENDIF
548
549 mov ah,KEEP_PROCESS ;remain resident
550 mov al,0 ;return code
551 mov dx,Main_Res_Segs ;size of area in paragraph
552 INT 21h ;keep resident and then return
553 ;control to DOS
554
555;----------------------------------------------------------------------------
556; Calculate the size of the MAIN module in bytes. First potion of this
557; segment can be found in the Fastopen.asm
558;----------------------------------------------------------------------------
559 IF ($-Cseg_Main) MOD 16 ;AN000;
560 ORG ($-Cseg_Main)+16-(($-Cseg_Main) MOD 16) ;AN000;
561 ENDIF ;AN000;
562End_Main label word ;AN000;
563
564
565CSEG_MAIN ENDS ; End of Cseg_Main segment
566page
567
568
569;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
570
571CSEG_INIT SEGMENT PUBLIC PARA 'CODE'
572
573;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
574 ASSUME cs:cseg_init,ds:cseg_init,ss:stack,es:cseg_init
575
576 EXTRN SYSPARSE:NEAR ;AN000;
577 EXTRN SYSLOADMSG:NEAR ;AN000;
578 EXTRN SYSDISPMSG:NEAR ;AN000;
579
580IF BUFFERFLAG
581 extrn save_ems_page_state:far ; HKN 8/25/88
582ENDIF
583
584
585;----------------------------------------------------------------------------
586; The cache buffers start from the first location of Cseg_Init.
587; First portion is the NAME DRIVE HEADERS, which is followed by
588; NAME CACHE BUFFER, which is followed by EXTENT DRIVE HEADER. Under each
589; extent drive header its cache buffer. 24 Name drive buffers are allocated
590; during assembly time. Remaining drive and cache buffers are allocated
591; during run time. Eventhough 24 name cache buffers are allocated during
592; assembly time, this number may be reduced to the specified number of drive
593; numbers during run time by overlaying other drive buffers over the unused ones.
594; The initialization code will be overlayed by name and extent cache buffs
595; during second half of the initialization which is in the MAIN module (see INit_Tree).
596;-----------------------------------------------------------------------------
597
598Drive_header_start label byte ;Name cache drive buffer
599Drive_Cache Drive_Cache_Header max_drives DUP (<>) ; header for 24 drives are reserved
600
601;-----------------------------------------------------------------------------
602; Anything below this point will be overlayed by the Cache Buffers
603; MSG retriever is placed after Cache buffer, so that the area can be
604;-----------------------------------------------------------------------------
605;=============================================================================
606; Non_Resident Data Area
607;=============================================================================
608INIT_VECTOR DD INIT_TREE ;jump vector to INIT_TREE ;AN000;
609MAIN_VECTOR DD MAIN ;entry point to MAIN routine ;AN000;
610source_xname DB " :\",0 ;used for xname translate ;AN000;
611target_xname DB 65 DUP (0) ;used for xname translate ;AN000;
612user_drive db 0 ;current user drive ;AN000;
613psp_seg dw 0 ;segment of psp ;AN000;
614stack_seg_start dw 0 ;segment of temporary stack ;AN000;
615stack_seg_end dw 0 ;AN000;
616num_of_drives dw 0 ;number of user specified drives ;AN000;
617Ext_Mem dw 0 ;=1 if exteded memory is enabled ;AN000;
618drive_id db " :",0 ;AN000;
619Parambuff db 50 dup (0)
620Parmbuff_Ptr dw 0 ;AN000;
621FRAME_COUNT dw 0 ;EMS frame count
622
623IF IBMCOPYRIGHT
624
625FRAME_BUFFER DB 30h DUP(0) ;EMS frame buffer
626
627ELSE
628
629FRAME_BUFFER DB 100h DUP(0) ; EMS frame buffer
630
631ENDIF
632
633IF BUFFERFLAG
634FST_PAGE DW 0,0 ; holds the second highest page above 640k
635ENDIF
636
637Cmdline_buff db 135 dup (0) ;command line buffer ;AN000;
638name_cache_seg dw Cseg_Init ;default to Init1 seg ;AN000;
639Ext_Count dw 0 ;total name extent entries ;AN000;
640extent_drive_Buff dw 0 ;ptr to extent drive ;AN000;
641name_cache_Buff dw 0 ;pointer to Name cache buffer ;AN000;
642EMS_FLAG dw 0 ;EMI flag 1= if EMI is enabled ;AN000;
643CHECK_QUEUE dw 0 ; = 1 if analyser is activated
644RES_SEGS dw 010H+020H ;PSP SIZE + STACK SIZE resident segment size
645EMS_PAGE_SEG DW 0 ;EMS code page segment ID ;AN000;
646EMS_PAGE_NUM DW 0 ;EMS physical page number ;AN000;
647Total_Ext_Count DW 0 ;Total extent entry count ;AN000;
648Total_Name_Count DW 0 ;Total Name entry count ;AN000;
649Total_Cache_Size DW 0 ;Total cache buffer size (name+extent) buffer ;AN000;
650Name_Cache_Size DW 0 ;Total name cache size (header + entry buffs)
651Name_Count DW 0 ;name entry count
652Name_Drive_Buff DW 0 ;name driver buffer address ;AN000;
653Ext_Cache_Size DW 0 ;extent buffer size ;AN000;
654Open_SegID DW 0 ;SegId of Cseg_Open after relocation ;AN000;
655Seek_SegID DW 0 ;SegId of Cseg_Seek " " ;AN000;
656Init_SegID DW 0 ;SegId of Cseg_Init " " ;AN000;
657MAIN_Size DW 0 ;size of Cseg_Main in Paragraph ;AN000;
658OPEN_Size DW 0 ;size of Cseg_Open in paragraph ;AN000;
659SEEK_Size DW 0 ;size of Cseg_Seek in paragraph ;AN000;
660
661;-----------------------------------------------------------------------;
662; EMS Support ;
663;-----------------------------------------------------------------------;
664EXT_HANDLE DW ? ; EMS handle for reference ;AN000;
665EMS_PAGESIZE DW ? ; EMS handle for reference ;AN000;
666EMS_FRAME_ADDR DW ? ; EMS handle for reference ;AN000;
667CURR_EMS_PAGE DB ? ; Current EMS page number ;AN000;
668HANDLE_NAME DB 'FASTOPEN',0 ; EMS handle name ;AN000;
669
670IF BUFFERFLAG
671SAVE_MAP_ADDR DD ? ; HKN 8/25/88
672ENDIF
673
674;---------------------------------------------------------------------------
675; PARSER Support
676;---------------------------------------------------------------------------
677CURRENT_PARM DW 81H ;POINTER INTO COMMAND OF CUREENT OPERANT ;AN000;
678NEXT_PARM DW 0 ;POINTER INTO COMMAND OF NEXT OPERAND ;AN000;
679ORDINAL DW 0 ;ORDINAL NUMBER OF MAIN PARSER LOOP ;AN000;
680ORDINAL1 DW 0 ;ORDINAL NUMBER OF COMPLEX ITEM LOOP ;AN000;
681PREV_TYPE DB 0 ;PREVIOUS POSITIONAL PARAMETER TYPE
682
683;---------------------------------------------------------------------------
684; PRINT_STDOUT input parameter save area
685;----------------------------------------------------------------------------
686SUBST_COUNT DW 0 ;message substitution count ;AN000;
687MSG_CLASS DB 0 ;message class ;AN000;
688INPUT_FLAG DB 0 ;Type of INT 21 used for KBD ;AN000;
689MSG_NUM DW 0 ;message number ;AN000;
690
691
692;----------------------------------------------------------------------------
693; Following three sublists are used by the Message Retriever
694;----------------------------------------------------------------------------
695SUBLIST1 LABEL DWORD ;SUBSTITUTE LIST 1
696 DB 11 ;sublist size ;AN000;
697 DB 0 ;reserved ;AN000;
698 DD 0 ;substition data Offset ;AN000;
699 DB 1 ;n of %n ;AN000;
700 DB 0 ;data type ;AN000;
701 DB 0 ;maximum field width ;AN000;
702 DB 0 ;minimum field width ;AN000;
703 DB 0 ;characters for Pad field ;AN000;
704
705
706SUBLIST2 LABEL DWORD ;SUBSTITUTE LIST 2
707 DB 11 ;sublist size ;AN000;
708 DB 0 ;reserved ;AN000;
709 DD 0 ;substition data Offset ;AN000;
710 DB 2 ;n of %n ;AN000;
711 DB 0 ;data type ;AN000;
712 DB 0 ;maximum field width ;AN000;
713 DB 0 ;minimum field width ;AN000;
714 DB 0 ;characters for Pad field ;AN000;
715
716
717
718;--------------------------------------------------------------------------
719; PARSER Control Blocks and Buffers
720;--------------------------------------------------------------------------
721
722PARMS label word
723 DW parmsx ;AN000;
724 DB 1 ; number of delemeters ;AN000;
725 DB 1 ; extra delimeters length ;AN000;
726 DB "=" ; extra delimeter expected ;AN000;
727 DB 0 ; extra end of line length ;AN000;
728 DB 0 ;AN000;
729
730
731PARMSX label byte ;AN000;
732par_min DB 1 ; min, max positional operands allowed ;AN000;
733par_max DB 2 ; min, max positional operands allowed ;AN000;
734 DW Pos1 ; offset into positonal-1 control block ;AN000;
735 DW Pos2 ; offset into positonal-1 control block ;AN000;
736par_sw DB 1 ; one switch ;AN000;
737 DW Switch ; offset into switch-1 control bloc ;AN000;
738 DB 0 ; no keywords ;AN000;
739 DB 0 ; 0 ;AN000;
740
741
742
743;------------------ POS2 CONTROL BLOCK --------------------------------------
744
745POS1 label word ; positional-1 control definition
746Pos1Type DW 0100H ; control type flag (drive only) ;AN000;
747 DW 0 ; function flags ;AN000;
748 DW Result ; offset into result buffer ;AN000;
749 DW value_pos1 ; offset value list buffer ;AN000;
750 DB 0 ; number of keyword/switch synonyms ;AN000;
751
752
753Value_Pos1 label byte ; postional parameter value expected ;AN000;
754 DB 0 ; no values expected ;AN000;
755
756
757
758;---------------- POS1 CONTROL BLOCK ----------------------------------------
759
760POS2 label word ; positional-2 control definition ;AN000;
761Pos2Type DW 08502H ; Control type (complex/integer/drive/ ;AN000;
762 ; repeat) ;AN000;
763 DW 0 ; function flags ;AN000;
764 DW Result ; offset into result buffer ;AN000;
765 DW value_pos2 ; offset value list buffer ;AN000;
766 DB 0 ; number of keyword/switch synonyms ;AN000;
767
768Value_Pos2 label byte
769 DB 0 ; either (n) or (m) will be returned
770
771
772
773;--------------- RESULT BUFFER ---------------------------------------------
774
775RESULT label byte ; postional2 parameter result buffer ;AN000;
776PosType DB ? ; type of operand returned ;AN000;
777Postag DB ? ; type of item tage returned ;AN000;
778synonym DW ? ; offset into synonyms returned ;AN000;
779valuelo DW ? ; space for drive number/integer/strin ;AN000;
780valuehi DW ? ;AN000;
781
782
783;---------------- SWITCH CONTROL BLOCK ------------------------------------------
784
785SWITCH label word ; switch control definition
786 DW 0 ; no match flag ;AN000;
787 DW 0 ; no function flags ;AN000;
788 DW Result ; offset into result buffer ;AN000;
789 DW value_sw1 ; offset value list buffer ;AN000;
790 DB 1 ; number of keyword/switch synonyms ;AN000;
791E_Switch DB "/X" ; /X option for extended memory access ;AN000;
792 DB 0 ;AN000;
793
794
795Result_sw1 label byte ; switch parameter result ;AN000;
796 DB ? ; type of operand returned ;AN000;
797 DB ? ; type of item tage returned ;AN000;
798Swval DW ? ; offset into synonyms returned ;AN000;
799 DB ? ; switch value ;AN000;
800
801
802Value_sw1 label byte ; switch parameter value expected ;AN000;
803 DB 0 ; no values expected ;AN000;
804
805
806
807
808
809
810
811;-----------------------------------------------------------------------------
812; INIT (FASTINIT-2)
813;-----------------------------------------------------------------------------
814;
815;SUBROUTINE: INIT
816;
817;FUNCTION: Performs FASTOPEN initialization function
818;
819;
820;NOTE: This routine is the starting routine of FASTOPEN
821;
822;-----------------------------------------------------------------------------
823
824START:
825 ; on entry DS and ES -->PSP ;AN000;
826 push cs ; DS-->Cseg_Init ;AN000;
827 pop ds ;AN000;
828 ASSUME ds:cseg_init ;AN000;
829 mov psp_seg,es ; save PSP segment for later use ;AN000;
830 push cs ;AN000;
831 pop es ; ES-->Cseg_Init ;AN000;
832 ASSUME es:cseg_init ;AN000;
833
834 CALL SYSLOADMSG ; Preload messages ;AN000;
835 jnc Parse_cmd_line ; If no error, parse command line ;AN000;
836
837 mov ax,1 ;AN000;
838 CALL SYSDISPMSG ; display error ;AN000;
839
840 mov ah,04ch ; Terminate ;AN000;
841 mov al,0 ; Errorlevel 0 (Compatible) ;AN000;
842 INT 021h ; exit to DOS
843
844Parse_Cmd_Line: ;AN000;
845 CALL PARSE ;Parse command line ;AN000;
846 lea si,parambuff ;drive ID buff address ;AN000;
847 mov ax,Total_name_Count ; ;AN000;
848 mov ax,Total_ext_Count ;AN000;
849 mov ax,num_of_drives ;AN000;
850 mov ax,ext_mem ;AN000;
851 jnc Check_Installed ;no, check if Fastopen already installed
852 jmp error_exit ;yes - exit ;AN000;
853
854Check_Installed:
855 CALL CHECK_INSTALL ; Fastopen installed ??
856 jnc Save_SegIDs ; no - save segment IDs
857 jmp error_exit ; yes - exit
858
859;-----------------------------------------------------------------------------
860; Set seg IDs of three segments.
861;-----------------------------------------------------------------------------
862Save_SegIds:
863 mov Open_SegID, Cseg_Open ;AN000;
864 mov Seek_SegID, Cseg_Seek ;AN000;
865 mov Init_SegID, Cseg_Init ;AN000;
866
867;-----------------------------------------------------------------------------
868; Compute the size of segments and cache buffers. Setup a temporary stack
869; to be used by the second half of initilization.
870;-----------------------------------------------------------------------------
871 CALL CHECK_MEM ;See if we have enough memory ;AN000;
872 jnc chk_extended_mem ;yes, check for extended memory ;AN000;
873 jmp error_exit ;no - display not enough mem msg ;AN000;
874
875;-----------------------------------------------------------------------------
876; Check if Extended Memeory is specified. If true, check if Extended memory is
877; available. Get segid of one extended memory page.
878;-----------------------------------------------------------------------------
879Chk_Extended_Mem:
880 cmp ext_mem,1 ; enable EMS ?? ;AN000;
881 jne Set_Data_Areas ; no, set data areas ;AN000;
882
883 CALL SET_EMS ; set expanded memory ;AN000;
884 jnc Set_Data_Areas ; if no error ;AN000;
885 jmp error_exit ; error exit ;AN000;
886
887;------------------------------------------------------------------------------
888; Copy Data and segid of Init segments to Main, Open and Seek segments.
889; If code is relocated, segids have to be adjusted later. (See Adjust_SegID)
890;------------------------------------------------------------------------------
891Set_Data_Areas:
892 CALL COPY_DATA ; copy data to other segments ;AN000;
893
894;-----------------------------------------------------------------------------
895; Relocate code to extended memory if extended memory is specified or
896; relocate in lower memory itself.
897;-----------------------------------------------------------------------------
898Relocate_Code:
899 CALL RELOCATE_SEGMENT ; Relocate the code cnd buffers ;AN000;
900
901;-----------------------------------------------------------------------------
902; Adjust the segids and jump vectors in other segments after code relocation
903;-----------------------------------------------------------------------------
904 CALL ADJUST_SEGIDS ; adjust segment ids after relocation ;AN000;
905
906;-----------------------------------------------------------------------------
907; Display FASTOPEN INSTALLED message. This must be done prior to the actual
908; installation.
909;-----------------------------------------------------------------------------
910Disp_Install_Msg: ; display FASTOPEN installed message
911 MOV AX,INSTALL1 ; message number ;AN000;
912 MOV MSG_NUM,AX ; set message number ;AN000;
913 MOV SUBST_COUNT,0 ; no message ;AN000;
914 MOV MSG_CLASS,-1 ; message class ;AN000;
915 MOV INPUT_FLAG,0 ; no input ;AN000;
916 CALL PRINT_STDOUT ; show message ;AN000;
917
918;-----------------------------------------------------------------------------
919; Install Fastopen
920;-----------------------------------------------------------------------------
921 CALL INSTALL_FASTOPEN ; Install Fastopen ;AN000;
922 jnc Setup_Stack ; Installed Ok, setup stack ;AN000;
923 jmp error_exit ; error - exit
924
925
926;----------------------------------------------------------------------------
927; Set Stack Values. This stack is used by the cache buffer initilization
928; portion of the code. This stack area will be eventually overlayed and
929; wont be used by either Fastopen or Fastseek functions in MAIN module.
930;----------------------------------------------------------------------------
931SETUP_STACK:
932 nop ;AN000;
933 CLI ;no interrupts allowed during stach change ;AN000;
934 mov SS,Stack_Seg_Start ;set up new stack ;AN000;
935 mov SP,0 ; ;AN000;
936 STI ;interrupts ok now ;AN000;
937 jmp INIT_VECTOR ;Jump to Cseg_Main to do second
938 ;phase of the initialization
939ERROR_EXIT:
940 mov al,1 ;set up return code
941 mov ah,exit ;set function code
942 INT INT_COMMAND ;exit to DOS
943
944
945
946
947;----------------------------------------------------------------------------
948; CHECK_INSTALL
949;----------------------------------------------------------------------------
950; Input: None
951;
952; Output:
953; IF Carry = 0 - Fastopen is not already installed
954;
955; IF Carry = 1 - Fastopen is already installed
956;
957;----------------------------------------------------------------------------
958; Use CALLINSTALL macro to see if FASTOPEN is already installed.
959; If carry flag set then FASTOPEN is installed. In this case display
960; Already Installed message.
961;----------------------------------------------------------------------------
962
963CHECK_INSTALL PROC NEAR
964
965 push ax ;save every registers that may
966 push bx ;be destroyed by DOS
967 push cx
968 push dx
969 push si
970 push di
971 push bp
972
973 push ds
974 mov bx, 1 ;Fastopen function code
975 mov si, -1 ;special check install code
976 CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed
977 pop ds
978 jc Install_Msg ;yes, display already installed
979 ;message
980;----------------------------------------------------------------------------
981; Check if Fastseek function is enabled. If true display Installed message
982;---------------------------------------------------------------------------- ;AN000;
983 push ds ;AN000;
984 mov si, -1 ;special check installed code
985 mov bx, 2 ;for Fastseek
986 CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed ;AN000;
987 pop ds ;AN000;
988 jnc Chk_Install_Exit ; no, exit ;AN000;
989
990Install_Msg: ;installed previously display message
991 MOV AX,ALREADY_INSTALL ;message number ;AN000;
992 MOV MSG_NUM,AX ;set message number ;AN000;
993 MOV SUBST_COUNT,0 ;no message substitution ;AN000;
994 MOV MSG_CLASS,-1 ;message class ;AN000;
995 MOV INPUT_FLAG,0 ;no input ;AN000;
996 CALL PRINT_STDOUT ;show message "Already Installed"
997 stc
998
999Chk_Install_Exit:
1000 pop bp ;restore registers
1001 pop di
1002 pop si
1003 pop dx
1004 pop cx
1005 pop bx
1006 pop ax
1007 ret ;return
1008
1009CHECK_INSTALL ENDP
1010
1011
1012
1013
1014
1015;----------------------------------------------------------------------------
1016; INSTALL_FASTOPEN
1017;----------------------------------------------------------------------------
1018; Input: Addrss of entry point to Fastopen resident code
1019;
1020; Output:
1021; IF Carry = 0
1022; Entry point to FASTOPEN resident code set
1023;
1024; IF Carry = 1 Error
1025;
1026; Calls: none
1027;----------------------------------------------------------------------------
1028; Use CALLINSTALL macro to see if FASTOPEN is already installed.
1029; If FASTOPEN is not installed, install it.
1030; If carry flag set then FASTOPEN is installed. In this case display
1031; already installed message.
1032;----------------------------------------------------------------------------
1033
1034INSTALL_FASTOPEN PROC NEAR
1035
1036 push ax ;Save every registers,point reg since
1037 push bx ;DOS may destroy it.
1038 push cx
1039 push dx
1040 push si
1041 push di
1042 push bp
1043
1044 cmp Total_Name_Count, 0 ;FastOpen enabled ?? ;AN000;
1045 je Install_Ext ;no - jump
1046
1047 push ds ;yes - install fastopen
1048 mov bx, 1 ;tell DOS that this is the
1049 lds si,Main_Vector
1050 CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed
1051 pop ds
1052 jc Install_Exit ;error - exit
1053
1054;----------------------------------------------------------------------------
1055; Check if Fastseek functions are enabled. If true, pass MAIN routine entry
1056; point and the Fastseek enabled information to DOS
1057;---------------------------------------------------------------------------- ;AN000;
1058Install_Ext:
1059 cmp Total_Ext_Count, 0 ; Fastseek enabled ?? ;AN000;
1060 jne ext_install ; yes - install fastseek ;AN000;
1061 clc ;AN000;
1062 jmp short Install_Exit ; no, exit ;AN000;
1063
1064Ext_Install:
1065 push ds ;AN000;
1066 mov bx, 2 ;tell DOS that this is the ;AN000;
1067 lds si,Main_Vector ;fastseek entry point ;AN000;
1068 CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed ;AN000;
1069 pop ds ;AN000;
1070 jnc short install_exit
1071 jmp short install_exit
1072
1073Installx_Msg: ;installed previously display message
1074 MOV AX,ALREADY_INSTALL ;message number ;AN000;
1075 MOV MSG_NUM,AX ;set message number ;AN000;
1076 MOV SUBST_COUNT,0 ;no message substitution ;AN000;
1077 MOV MSG_CLASS,-1 ;message class ;AN000;
1078 MOV INPUT_FLAG,0 ;no input ;AN000;
1079 CALL PRINT_STDOUT ;show message "Already Installed"
1080 stc
1081
1082Install_Exit:
1083 pop bp ;restore registers
1084 pop di
1085 pop si
1086 pop dx
1087 pop cx
1088 pop bx
1089 pop ax
1090 ret ;return
1091
1092INSTALL_FASTOPEN ENDP
1093
1094
1095
1096
1097
1098
1099;----------------------------------------------------------------------------
1100; CHECK_MEM
1101;----------------------------------------------------------------------------
1102; Function: Compute the total size of memory required by the Fasteopen.
1103; This includes both code and the cache buffers.
1104;
1105; Input: Name_Count, extent_count, Drive_cache, num_of_drives
1106;
1107; Output: Memory is validated, Resident segment size is calculated
1108; Temporary stack segment is set
1109;----------------------------------------------------------------------------
1110CHECK_MEM PROC NEAR ; DS-->Cseg_init
1111
1112;** Compute the total resident segment size and then add the cache buffer
1113;** size. The Resident segment size should be adjusted again after relocation.
1114
1115 mov Total_Cache_Size,0 ;reset total cache size (Name +Ext)
1116 mov Name_Cache_Size,0 ;reset Name cache buffer size
1117 mov ax, offset End_Main ;size of Main_Seg in bytes ;AN000;
1118 add ax,15 ;AN000;
1119 mov cl,4 ;convert size to paragraph ;AN000;
1120 shr ax,cl ;by dividng by 16 ;AN000;
1121 mov MAIN_Size, ax ;save MAIN segment size in para ;AN000;
1122 add Res_Segs,ax ;update resident seg count ;AN000;
1123 ;AN000;
1124 mov ax, offset End_Open ;size of Open_Seg in bytes ;AN000;
1125 add ax,15 ;AN000;
1126 mov cl,4 ;convert it to paragraph ;AN000;
1127 shr ax,cl ;AN000;
1128 mov OPEN_Size, ax ;save OPEN segment size in para ;AN000;
1129 add RES_SEGS,ax ;update resident seg count ;AN000;
1130 ;AN000;
1131 mov ax, offset End_Seek ;add size of Seek_Seg
1132 add ax,15 ;AN000;
1133 mov cl,4 ;AN000;
1134 shr ax,cl ; convert to para (divide by 16) ;AN000;
1135 mov SEEK_Size, ax ;save Seek segment size in para ;AN000;
1136 add RES_SEGS,ax ;update resident seg count ;AN000;
1137
1138;----------------------------------------------------------------------------
1139; Calculate the size of the NAME DRIVE HEADER BUFFERS
1140;----------------------------------------------------------------------------
1141 xor ax,ax ;reset the cache size register
1142 cmp total_Name_Count,0 ;Fastopen enabled ??
1143 je Check_ext_cache ;no - compute extent cache size
1144
1145 mov bx,offset DRIVE_CACHE ;get beginning of cache buff
1146 xor ax,ax
1147 mov al,size drive_cache_header ;get size of one name entry
1148 mul Num_Of_drives ;get total needed for drive cache
1149 add ax,bx ;set up correct offset
1150 add ax,15 ;round up to paragraph boundary
1151 mov cl,4
1152 shr ax,cl ;convert to paragraphs
1153 add RES_SEGS,ax ;update resident seg count
1154 mov Total_Cache_Size, ax ;update total cache buff size
1155 mov Name_Cache_Size, ax ;size in paragraph
1156
1157; Calculate the offset of the Name cache buffers
1158 shl ax,cl ;AX = offset to Name cache buff
1159 mov NAME_CACHE_BUFF,ax ;save Name cache address
1160
1161;-----------------------------------------------------------------------------
1162; Compute the size of the NAME CACHE buffer
1163;-----------------------------------------------------------------------------
1164 mov ax,size Name_Record
1165 mul Total_Name_Count
1166 add ax,15 ;round up to paragraph boundary
1167 mov cl,4
1168 shr ax,cl ;convert to paragraphs ( divide 16)
1169 add RES_SEGS,ax ;AX = End of Name cache buffers
1170 add Total_Cache_Size,ax ;update total cache buff size
1171 add Name_Cache_Size, ax ;
1172
1173Check_Ext_Cache:
1174 cmp total_ext_count,0 ;Fastseek enabled ??
1175 je Set_Stack ;no, set stack
1176
1177;---------------------------------------------------------------------------
1178; Compute the size of the Extent cache including drive headers
1179;---------------------------------------------------------------------------
1180Compute_Ext_Cache: ;calculate the extent buff offset
1181 mov ax,Name_Cache_Size
1182 mov cl,4
1183 shl ax,cl ;convert to bytes ( multiply by 16) ;AN000;
1184 mov EXTENT_DRIVE_BUFF, ax ;save EXTENT DRIVE BUFFER address ;AN000;
1185
1186 mov ax, size Drive_Header ;AN000;
1187 mul num_Of_drives ;calc size of drive header buff ;AN000;
1188 mov bx,ax ;save AX in BX ;AN000;
1189 mov ax, size Extent_Header ;size of one extent ;AN000;
1190 mul Total_Ext_Count ;calc size of extent buffers ;AN000;
1191 add ax,bx ;AX = size of extent buff in bytes ;AN000;
1192 mov ext_cache_size,ax ;save it for later use ;AN000;
1193 add ax,15 ;round up to paragraph boundary ;AN000;
1194 mov cl,4 ;AN000;
1195 shr ax,cl ;convert to paragraphs ;AN000;
1196 add RES_SEGS,ax ;update resident seg count ;AN000;
1197 add Total_Cache_Size,ax ;update total cache buff size
1198
1199
1200;----------------------------------------------------------------------------
1201; Setup stack segment followed by the extent cache buffers. This is a
1202; temporary stack used by the drive buffer initilization code in the
1203; Cseg_Main segment. This stack will be overlayed by the cache buffers.
1204;----------------------------------------------------------------------------
1205Set_Stack:
1206 mov ax,RES_SEGS ;AX=size of code and buffs in para
1207 add ax,PSP_Seg ;AX=segID of stack
1208 mov Stack_Seg_Start,ax ;start of the new STACK
1209 add ax,20h ;add the size of the stack
1210 mov Stack_Seg_End,ax ;get end of what we need
1211
1212 push ds ;
1213 mov ds,PSP_Seg ;access PSP for memory size
1214 mov si,Top_mem
1215 LODSW ;get total memory size
1216 pop ds
1217 sub ax,Stack_Seg_End ;see if there is enough for us
1218 jc Not_Enough_Memory ;no - error exit
1219 sub ax,1000h ;will there still be 64K ??
1220 jnc Check_Reloc_Size ;and return
1221
1222Not_Enough_Memory:
1223 MOV AX,NOT_ENOUGH_MEM ;message number ;AN000;
1224 MOV MSG_NUM,AX ;set message number ;AN000;
1225 MOV SUBST_COUNT,0 ;no message substitution ;AN000;
1226 MOV MSG_CLASS,-1 ;message class ;AN000;
1227 MOV INPUT_FLAG,0 ;no input ;AN000;
1228 CALL PRINT_STDOUT ;show message "Insufficient Memory" ;AN000;
1229 stc ;set error flag ;AN000;
1230 jmp short Set_Mem_Ret ;return ;AN000;
1231
1232;------------------------------------------------------------------------------
1233; If relocation is needed, then recalculate the size of resident segment
1234; If extended memory relocation, OPEN, SEEK and INIT segments will be
1235; eliminated from the current resident seg.
1236;-----------------------------------------------------------------------------
1237Check_Reloc_Size:
1238 cmp Ext_Mem,1 ; extended memory relocation ??
1239 jne Set_Mem_Exit ; no - exit ;AN000;
1240
1241;-----------------------------------------------------------------------------
1242; Check to see that the both code and the cache buffers fit in the
1243; exteneded memory one 16K page. Since the entire code segment and the
1244; cache buffers are going to be moved to XMA, that amount should be
1245; reduced from the size that should reside in the low memory.
1246;-----------------------------------------------------------------------------
1247 xor ax,ax
1248 xor bx,bx
1249 cmp total_Name_Count,0 ;Fastseek enabled ??
1250 je Skip_name_size ;no - skip name size
1251 mov ax, OPEN_SIZE ;size of Open seg in para ;AN000;
1252Skip_Name_Size:
1253 cmp total_ext_count,0 ;Fastseek enabled ??
1254 je Skip_Ext_Size ;no - skip extent size
1255 mov bx, SEEK_Size ;size of Seek_Seg in para ;AN000;
1256Skip_Ext_Size:
1257 add ax,bx
1258 add ax, Total_Cache_Size ;size of Init_Seg in para ;AN000;
1259 cmp ax, 0404H ;Less than 16K ?? ;AN000;
1260 jge Not_Enough_Space ;no - display message ;AN000;
1261
1262 mov ax, OPEN_SIZE ;size of Open seg in para ;AN000;
1263 add ax, SEEK_Size ;size of Seek_Seg in para ;AN000;
1264 add ax, Total_Cache_Size ;reduce resident seg size ;AN000;
1265 sub RES_SEGS,ax ;update resident seg count ;AN000;
1266
1267;-----------------------------------------------------------------------------
1268; If the code is to be moved to extended memory. There is no reason to
1269; keep Init_Tree in main memory. Remove that also to save space in base memory
1270;-----------------------------------------------------------------------------
1271 mov ax, offset End_Main1 ;size of Main_Seg until Init_Tree (bytes) ;AN000;
1272 add ax,15 ;AN000;
1273 mov cl,4 ;convert size to paragraph ;AN000;
1274 shr ax,cl ;by dividng by 16 ;AN000;
1275 mov bx,Main_Size ;bx=total size of Main seg including Init_Tree
1276 sub bx,ax ;bx=size after reducing Init_Tree
1277 sub RES_SEGS,bx ;update base memory resident seg count ;AN000;
1278 jmp short Set_Mem_Exit
1279 ;
1280Not_Enough_Space:
1281 MOV AX,NO_PAGE_SPACE ; not enough space in EMS page
1282 MOV MSG_NUM,AX ; set message number
1283 MOV SUBST_COUNT,0 ; no message
1284 MOV MSG_CLASS,-1 ; message class
1285 MOV INPUT_FLAG,0 ; no input
1286 CALL PRINT_STDOUT ; display message
1287 mov Ext_Mem, 0 ; RESET XMA FLAG
1288 stc
1289 jmp set_mem_ret
1290
1291Set_Mem_Exit: ;AN000;
1292 clc ;AN000;
1293
1294Set_Mem_Ret:
1295 ret ;AN000;
1296
1297CHECK_MEM endp
1298
1299
1300
1301
1302
1303;----------------------------------------------------------------------------
1304; RELOCATE
1305;----------------------------------------------------------------------------
1306; Function: Relocate Fastopen code and buffer in base memory or in
1307; Extended Memory. If base memory relocation, then
1308; relocate Cseg_Seek over Cseg_Open segment if the user
1309; didn't specify Fastopen (n). Relocate Cseg_Init over Cseg_Seek
1310; if user didn't specify Fastseek feature(m). If extended memory
1311; relocation, copy Cseg_Open, Cseg_Seek and Cseg_Init to
1312; a single page in extented memory if both Fastopen and Fastseek
1313; (n and m) are specified. Copy Cseg_open and Cseg_Init only if Fastseek
1314; feature (m) is not specified. Copy Cseg_Seek and Cseg_Init if
1315; FastOpen feature (n) is not specified
1316;
1317;----------------------------------------------------------------------------
1318
1319RELOCATE_SEGMENT PROC NEAR
1320 cmp Ext_Mem,1 ; Extended memory enabled ?? ;AN000;
1321 je Set_Seg_Ids ; yes - do extented memory relocation
1322 jmp Reloc_Low_Mem ; no - do low memory relocation ;AN000;
1323
1324;----------------------------------------------------------------------------
1325; Move Fastopen, FastSeek or both to the Extended memory
1326;----------------------------------------------------------------------------
1327Set_Seg_Ids:
1328 cld ; clear direction flag (increment si and di)
1329 cmp Total_Name_Count,0 ; Fastopen enabled ??
1330 jne Set_Open_Seg ; yes - set open seg in extented memory
1331
1332 mov ax,EMS_Page_Seg ; AX = seg id of Cseg_Seek in ext mem
1333 mov Seek_SegID,ax ; save it
1334 jmp Set_Seek_Seg ; no - fastopen, set Seek segment
1335
1336;-----------------------------------------------------------------------------
1337; ---- Extended Memory Relocation -----
1338; Setup Cseg_Open segment in Extended Memory
1339;------------------------------------------------------------------------------
1340Set_Open_Seg:
1341 mov ax,Cseg_Init ;
1342 mov ds,ax ; DS-->Cseg_Init
1343 ASSUME ds:Cseg_Init
1344 mov ax,EMS_Page_Seg ; AX = seg id of Cseg_Open in ext mem
1345 mov Open_SegID,ax ; save it
1346
1347Copy_Open_Seg:
1348 mov ax, offset End_Open ; size of Open seg in bytes ;AN000;
1349 mov cl,1
1350 shr ax,cl ; convert to words ;AN000;
1351 mov cx,ax ; CX = number of WORDS to transfer ;AN000;
1352 xor si,si ; offset of the source in low memory ;AN000;
1353 xor di,di ; offset of the destination in XMA ;AN000;
1354 mov ax,Cseg_Open ; set source segID ;AN000;
1355 mov ds,ax ; DS-->Cseg_Open ;AN000;
1356 ASSUME ds:Cseg_Open ;AN000;
1357 mov ax,Open_SegID ; set destination XMA seg id ;AN000;
1358 mov es,ax ; ES-->Extended memory page ;AN000;
1359 ASSUME es:nothing ;AN000;
1360 REP MOVSW ; copy Open segment to extended memory
1361 ; SI-->Cseg_Seek segment
1362 mov ax,Cseg_Init ; no - only Fastseek specified
1363 mov ds,ax ; DS-->Cseg_Init
1364 ASSUME ds:Cseg_Init
1365 cmp Total_Ext_Count,0 ; Fastseek enabled ??
1366 jne Set_Seek_id ; yes -set seek id
1367
1368 mov ax,Cseg_Seek ; only Fastopen is enabled ;AN000;
1369 sub ax,Cseg_Open ; AX = size of Cesg_Open segment ;AN000;
1370 add ax,EMS_Page_Seg ; AX = new seg ID of Cseg_Init in ext ;AN000;
1371 mov Init_SegID,ax ; only if Fastopen is specified ;AN000;
1372 jmp Copy_Init_Seg ; copy init_seg to extended memory
1373
1374;-----------------------------------------------------------------------------
1375; Setup Cseg_Seek segment in Extended Memory
1376;------------------------------------------------------------------------------
1377Set_Seek_Id:
1378 mov ax,Cseg_Seek ;
1379 sub ax,Cseg_Open ; AX = size of Cesg_Open segment ;AN000;
1380 add ax,EMS_Page_Seg ; AX = new seg ID of Cseg_Seek in ;AN000;
1381 mov Seek_SegID,ax ; extended memory ;AN000;
1382 jmp Copy_Seek_Seg
1383
1384Set_Seek_Seg: ; only Fastseek is specified
1385 xor si,si ; offset of the source in low memory ;AN000;
1386 xor di,di ; offset of the destination in XMA ;AN000;
1387
1388Copy_Seek_Seg:
1389 mov ax, offset End_Seek ;size of Cseg_Seek in bytes ;AN000;
1390 mov cl,1
1391 shr ax,cl ; convert to words ;AN000;
1392 mov cx,ax ; CX = number of WORDS to transfer ;AN000;
1393 xor si,si ; offset of the source in low memory ;AN000;
1394 xor di,di ; offset of the destination in XMA ;AN000;
1395 mov ax,Cseg_Seek ; set source segID ;AN000;
1396 mov ds,ax
1397 ASSUME ds:Cseg_Seek ;AN000;
1398 mov ax,Seek_SegID ; set destination XMA seg id ;AN000;
1399 mov es,ax
1400 ASSUME es:nothing ;AN000;
1401 REP MOVSW ; copy Seek segment to extended memory
1402 ; SI-->Cseg_Init segment
1403 mov ax,Cseg_Init ; no - only Fastseek specified
1404 mov ds,ax ; DS-->Cseg_Init
1405 ASSUME ds:Cseg_Init
1406 cmp total_Name_Count,0 ; FastOpen enabled ??
1407 jne Set_Init_Seg ; yes - set Init Segment
1408
1409 mov ax,Cseg_Init
1410 sub ax,Cseg_Seek ; ax = size of Cseg_Seek
1411 add ax,EMS_Page_Seg ; Cseg_Init id only if Fastseek is specified
1412 mov Init_SegID,ax ;
1413 jmp copy_init_seg ; copy cseg_init area to extentde memory
1414
1415;-----------------------------------------------------------------------------
1416; Setup Cseg_Init segment in Extended Memory
1417;------------------------------------------------------------------------------
1418Set_Init_seg:
1419 mov ax,Cseg_Init ; yes - set init seg id
1420 sub ax,Cseg_Open ; AX = size of Open_Cseg+Seek_Cseg
1421 add ax,EMS_Page_Seg ; new Cseg_Init id in XMA if both
1422 mov Init_SegID,ax ; Fastopen and Fastseek are enabled ;AN000;
1423
1424Copy_Init_Seg: ; comes here if no Cseg_Seek is required
1425 xor si,si ; offset of the source in low memory ;AN000;
1426 xor di,di ; offset of the destination in XMA ;AN000;
1427 mov ax, Total_Cache_Size ; size of Init seg area to be copied ;AN000;
1428 mov cl,4 ; in paragraph ;AN000;
1429 shl ax,cl ; convert to number of bytes ;AN000;
1430 mov cl,1 ;
1431 shr ax,cl ; convert to number ofwords ;AN000;
1432 mov cx,ax ; CX = number of WORDS to transfer ;AN000;
1433 mov ax,Cseg_Init ; set source segID ;AN000;
1434 mov ds,ax
1435 ASSUME ds:Cseg_Init ;AN000;
1436 mov ax,Init_SegID ; set destination XMA seg id ;AN000;
1437 mov es,ax
1438 ASSUME es:nothing ;AN000;
1439 REP MOVSW ; copy Init segment to extended memory
1440 jmp reloc_exit ; then return ;AN000;
1441
1442
1443;NOTE: No need to adjust the resident segment size (Res_Segs) since it is
1444; done in the routine (Check_Mem).
1445
1446
1447;-----------------------------------------------------------------------
1448; ---- LOW MEMORY RELOCATION ----
1449; Reloctae FastOpen or FastSeek or both in the low memory and adjust the
1450; resident size of the code.
1451;-----------------------------------------------------------------------
1452Reloc_LOW_Mem:
1453 cmp Total_Name_Count,0 ; Fastopen function enabled ??
1454 jne Check_Seek ; yes, check Fastseek function
1455
1456; Relocate Cseg_Seek segment over Cseg_Open segment
1457 mov ax, offset End_Seek ; size of Cseg_Seek in bytes ;AN000;
1458 mov cl,1
1459 shr ax,cl ; convert to words ;AN000;
1460 mov cx,ax ; CX = number of WORDS to transfer ;AN000;
1461 xor si,si ; offset of the source ;AN000;
1462 xor di,di ; offset of the destination ;AN000;;AN000;
1463 mov ax,Cseg_Seek ; set source segID ;AN000;
1464 mov ds,ax ; DS:SI-->Cseg_Seek ;AN000;
1465 ASSUME ds:Cseg_Seek ;AN000;
1466 mov ax,Cseg_Open ; set destination seg id ;AN000;
1467 mov es,ax ; ES:DI--> Cseg_Open ;AN000;
1468 ASSUME es:Cseg_Open ;AN000;
1469 ;AN000;
1470 REP MOVSW ; relocate code and cache buffer
1471 mov ax,OPEN_Size ; reduce Open seg size from
1472 sub RES_SEGS,ax ; the resident size
1473
1474;-----------------------------------------------------------------------
1475; Compute the new segID after relocation and save it
1476;-----------------------------------------------------------------------
1477 mov ax,Cseg_Init ;
1478 mov ds,ax ; DS-->Cseg_Init
1479 ASSUME ds:Cseg_Init
1480 mov ax,Cseg_Open ; AX = seg id of Cseg_Open in ext mem
1481 mov Seek_SegID,ax ; save it
1482 ;AN000;
1483 mov ax,Seek_Size ; AX = size of Cseg_Seek
1484 add ax,Cseg_Open ; AX = new seg ID of Cseg_Init in ext ;AN000;
1485 mov Init_SegID,ax ; save it ;AN000;
1486 jmp short reloc_exit ;then return ;AN000;
1487
1488Check_Seek:
1489 cmp Total_Ext_Count,0 ; Fastseek function enabled ??
1490 jne Reloc_Exit ; yes, no need for relocation
1491
1492;-----------------------------------------------------------------------
1493; Relocate first portion of the Cseg_Init over Cseg_Seek segment. The size
1494; this portion should be same as the current size of Drive cache headers
1495; Anything more will overlay on Cseg_Init code which is currently active.
1496;-----------------------------------------------------------------------
1497 mov ax, size Drive_Cache_Header ; size of one drive cache hdr
1498 mov cx,Max_Drives ; CX = maximum number of drives
1499 mul cx ; AX = size of Cseg_Init portion
1500 mov cl,1
1501 shr ax,cl ; AX = size of portion in words
1502 mov cx,ax ; CX = number of WORDS to transfer ;AN000;
1503 mov si,0 ; offset of the source ;AN000;
1504 mov di,0 ; offset of the destination ;AN000;;AN000;
1505 mov ax,Cseg_Init ; set source segID ;AN000;
1506 mov ds,ax ; DS:SI-->Cseg_Seek ;AN000;
1507 ASSUME ds:Cseg_Init ;AN000;
1508 mov ax,Cseg_Seek ; set destination seg id ;AN000;
1509 mov es,ax ; ES:DI--> Cseg_Open ;AN000;
1510 ASSUME es:Cseg_Seek ;AN000;
1511 ;AN000;
1512 REP MOVSW ; relocate Cseg_Init over Cseg_Seek
1513 mov ax,Seek_Size ; reduce Seek seg size from
1514 sub RES_SEGS,ax ; the resident size
1515
1516;-----------------------------------------------------------------------
1517; Compute the new segID after reloaction and save it
1518;-----------------------------------------------------------------------
1519 mov ax,Cseg_Init ;
1520 mov ds,ax ; DS-->Cseg_Init
1521 ASSUME ds:Cseg_Init
1522 mov ax,Cseg_Seek ; AX = seg id of Cseg_Open in ext mem
1523 mov Init_SegID,ax
1524
1525Reloc_Exit:
1526; copy the latest RES_SEGS size to Cseg_Main
1527 mov ax,Cseg_Init ; ;AN000;
1528 mov ds,ax ; DS-->Cseg_Init ;AN000;
1529 ASSUME ds:Cseg_Init ;AN000;
1530 mov ax,Cseg_Main ; set destination seg id ;AN000;;AN000;
1531 mov es,ax ; ES--> Cseg_Main ;AN000; ;AN000;
1532 ASSUME es:Cseg_Main ;AN000;;AN000;
1533 mov ax,Res_Segs ;AN000;
1534 mov es:Main_Res_Segs,ax ; save it ;AN000;
1535
1536 RET ;AN000;
1537
1538RELOCATE_SEGMENT ENDP
1539
1540
1541
1542
1543
1544
1545;-----------------------------------------------------------------------
1546; Procedure: COPY_DATA
1547;-----------------------------------------------------------------------
1548; Copy data values from Cseg_Init to other segments. I the code is relocated,
1549; seg IDs should be updated after relocation. This is done in "Update_SegID"
1550;
1551; Input: Variables inside Cseg_Open, CsegSeek and Cseg_Main segments
1552;
1553; Output: Data values copied to the above segments
1554;
1555;
1556;-----------------------------------------------------------------------
1557
1558COPY_DATA PROC NEAR
1559
1560 mov ax,cseg_init ;AN000;
1561 mov ds,ax ;DS--> Cseg_Init ;AN000;
1562 ASSUME ds:Cseg_init ;AN000;
1563 mov ax,cseg_Main ;AN000;
1564 mov es,ax ;ES--> CSEG_MAIN ;AN000;
1565 ASSUME es:Cseg_Main ;AN000;
1566 ;AN000;
1567 mov es:Main_Name_Cache_Seg, Cseg_Init ;AN000;
1568 mov ax,Num_Of_Drives ;AN000;
1569 mov es:Main_Num_Of_Drives,ax ;AN000;
1570 mov ax,ext_count ;AN000;
1571 mov es:Main_Ext_Count,ax ;AN000;
1572 mov ax,Extent_Drive_Buff ;AN000;
1573 mov es:Main_Extent_Drive_Buff,ax ;AN000;
1574 mov ax,Name_Cache_Buff ;AN000;
1575 mov es:Main_Name_Cache_Buff,ax ;AN000;
1576 mov ax,Name_Drive_Buff ;AN000;
1577 mov es:Main_Name_Drive_Buff,ax ;AN000;
1578 mov ax,Ems_Flag
1579 mov es:Main_EMS_FLAG,ax
1580 mov ax,EMS_PAGE_Seg ;AN000;
1581 mov es:Main_EMS_PAGE_Seg,ax ;AN000;
1582
1583IF BUFFERFLAG
1584 mov ax, EMS_PAGE_NUM
1585 mov es:ems_page_number, ax ;HKN
1586ENDIF
1587
1588 mov ax,EMS_PAGE_SIZE ;AN000;
1589 mov es:Main_EMS_PAGE_SIZE,ax ;AN000;
1590 mov ax,Total_Ext_Count ;AN000;
1591 mov es:Main_Total_Ext_Count,ax ;AN000;
1592 mov ax,Ext_Cache_Size ;AN000;
1593 mov es:Main_Ext_Cache_Size,ax ;AN000;
1594 mov ax,Total_Name_Count ;AN000;
1595 mov es:Main_Total_Name_Count,ax
1596
1597; Copy drive buffer to MAIN segment
1598 lea si,ParamBuff ;AN000;
1599 lea di,es:Main_ParamBuff ;AN000;
1600 mov cx,50 ;AN000;
1601
1602Paramloop:
1603 mov al,[si] ;AN000;
1604 mov es:[di],al ;AN000;
1605 inc si ;AN000;
1606 inc di ;AN000;
1607 LOOP paramloop ;AN000;
1608
1609;-----------------------------------------------------------------------
1610; Copy data values to OPEN segment (Cseg_Open)
1611;-----------------------------------------------------------------------
1612 mov ax,cseg_Open ;AN000;
1613 mov es,ax ;ES--> CSEG_Open ;AN000;
1614 ASSUME es:Cseg_Open ;AN000;
1615 mov si,offset drive_cache ;AN000;
1616 mov es:Open_Name_Drive_Buff,si ;AN000;
1617 mov es:Open_Name_Cache_Seg,Cseg_Init ;AN000;
1618 mov ax,check_Queue
1619 mov es:chk_Flag,ax
1620
1621;-----------------------------------------------------------------------
1622; Copy data values to SEEK segment (Cseg_Seek) for Fastseek functions
1623;-----------------------------------------------------------------------
1624 mov ax,cseg_Seek ;AN000;
1625 mov es,ax ;ES--> CSEG_Seek ;AN000;
1626 ASSUME es:Cseg_Seek ;AN000;
1627 mov si,Extent_Drive_Buff ;AN000;
1628 mov es:Seek_Extent_Drive_Buff,si ;AN000;
1629 mov es:Seek_Name_Cache_Seg,Cseg_Init ;AN000;
1630 mov ax,Num_Of_Drives ;AN000;
1631 mov es:Seek_Num_Of_Drives,ax ;AN000;
1632 mov ax,Total_Ext_Count ;AN000;
1633 mov es:Seek_Total_Ext_Count,ax ;AN000;
1634 mov ax,Total_Name_Count ;AN000;
1635 mov es:Seek_Total_name_Count,ax ;AN000;
1636 mov ax,Name_Cache_Buff ;AN000;
1637 mov es:Seek_Name_Cache_Buff,ax ;AN000;
1638 mov ax,Name_Drive_Buff ;AN000;
1639 mov es:Seek_Name_Drive_Buff,ax ;AN000;
1640 mov ax,check_Queue
1641 mov es:check_Flag,ax
1642 ;AN000;
1643 mov ax,cseg_Init ;AN000;
1644 mov es,ax ;ES addressability to CSEG_Init ;AN000;
1645 ASSUME es:Cseg_Init ;AN000;
1646 ;AN000;
1647 ret
1648
1649COPY_DATA ENDP
1650
1651
1652
1653
1654;-----------------------------------------------------------------------
1655; Procedure: ADJUST_SEGIDS
1656;-----------------------------------------------------------------------
1657; Function: Adjust segment Ids of various segments after relocation
1658;
1659; Input: SegID Vectors
1660;
1661; Output: SegIDs vectors are adjusted
1662;
1663; Note: The following segid and vectors are set previously either during
1664; link time or during initialization time. These SegIDS needs to
1665; be changed after the code and buffers are relocated.
1666;-----------------------------------------------------------------------
1667
1668ADJUST_SEGIDS PROC NEAR
1669
1670 mov ax,Cseg_Init ;AN000;
1671 mov ds,ax ;DS addressability to Cseg_Init ;AN000;
1672 ASSUME ds:Cseg_init ;AN000;;AN000;
1673 mov ax,cseg_Main ;AN000;
1674 mov es,ax ;ES addressability to CSEG_MAIN ;AN000;
1675 ASSUME es:Cseg_Main ;AN000;
1676
1677 mov bx, Init_segID ; copy seg ID of Init_Seg to ;AN000;
1678 mov es:Main_Name_Cache_Seg, bx ; Main seg ;AN000;
1679
1680 cmp Total_Name_Count,0 ; Fastopen function enabled ??
1681 je Adjust_Seek ; yes, Adjust Cseg_Seek ID
1682
1683 mov ax,Open_SegID ;AN000;
1684 mov es,ax ; ES addressability to CSEG_Open ;AN000;
1685 ASSUME es:Cseg_Open ; copy segid of init_seg to ;AN000;
1686 mov es:Open_Name_Cache_Seg, bx ; Open segment
1687
1688Adjust_Seek:
1689 cmp Total_Ext_Count,0 ;Fastopen function enabled ??
1690 je Adjust_Vectors ;yes, check Fastseek function
1691
1692 mov ax,Seek_SegID ;AN000;
1693 mov es,ax ; ES addressability to CSEG_Seek ;AN000;
1694 ASSUME es:Cseg_Seek ;AN000;
1695 mov es:Seek_Name_Cache_Seg, bx ;AN000;
1696
1697
1698; Adjust seg ids of jump vectors to Fastopen and Fastseek functions ;AN000;
1699Adjust_Vectors:
1700 mov ax,cseg_Main ;AN000;
1701 mov es,ax ;ES addressability to CSEG_MAIN ;AN000;
1702 ASSUME es:Cseg_Main ;AN000;
1703 ;DS addressability to Cseg_Init
1704 mov ax, Open_SegID ;AN000;
1705 mov word ptr es:FOPEN_Insert + word, ax ;AN000;
1706 mov word ptr es:FOPEN_Update + word, ax ;AN000;
1707 mov word ptr es:FOPEN_Delete + word, ax ;AN000;
1708 mov word ptr es:FOPEN_Lookup + word, ax ;AN000;
1709IF BUFFERFLAG
1710 mov word ptr es:FOPEN_Purge + word, ax ;TEL 9/29
1711ENDIF
1712
1713
1714 mov ax, Seek_SegID ;AN000;
1715 mov word ptr es:FSEEK_Open + word, ax ;AN000;
1716 mov word ptr es:FSEEK_Close + word, ax ;AN000;
1717 mov word ptr es:FSEEK_Insert + word, ax ;AN000;
1718 mov word ptr es:FSEEK_Delete + word, ax ;AN000;
1719 mov word ptr es:FSEEK_Lookup + word, ax ;AN000;
1720 mov word ptr es:FSEEK_Truncate + word, ax ;AN000;
1721 mov word ptr es:FSEEK_Purge + word, ax ;AN000;
1722
1723 cmp Total_Name_Count,0 ; Fastopen function enabled ??
1724 je Adjust_Delete ; no , exit
1725
1726; Change the segID of single Jump Vector inside Cseg_Main
1727 mov ax,cseg_Main ;AN000;;AN000;
1728 mov es,ax ;ES addressability to CSEG_MAIN ;AN000;;AN000;
1729 ASSUME es:Cseg_Main ;AN000;;AN000;
1730 mov ax,Open_SegID ;AN000;
1731 mov word ptr es:Vector_LookUp + word, ax ;;AN000;AN000;
1732
1733Adjust_Delete:
1734 cmp Total_Ext_Count,0 ; Fastseek function enabled ??
1735 je Adjust_Exit ; no , exit
1736
1737; Change the segID of single Jump Vector inside Cseg_Main
1738 mov ax,cseg_Main ;AN000;;AN000;
1739 mov es,ax ;ES addressability to CSEG_MAIN ;AN000;;AN000;
1740 ASSUME es:Cseg_Main ;AN000;;AN000;
1741 mov ax,Seek_SegID ;AN000;
1742 mov word ptr es:Vector_Delete + word, ax ;;AN000;AN000;
1743
1744Adjust_Exit:
1745 ret ;AN000;
1746 ;return
1747ADJUST_SEGIDS ENDP
1748
1749
1750
1751
1752
1753
1754
1755
1756;******************************************************************************
1757; *
1758; * MODULE: PARSE
1759; *
1760; * FUNCTION: Parse command line
1761; *
1762; * INPUT: FASTOPEN d: {=n | (n,m) } ... /x à
1763; * where à activates queue analyser for debugging
1764; *
1765; * OUTPUT: Command line is parsed
1766; *
1767; * RETURN SEQUENCE:
1768; *
1769; * If CY = 0 No error
1770; *
1771; * If CY = 1 Error
1772; *
1773; * EXTERNAL REFERENCES: SYSPARSE
1774; *
1775; *************************************************************************
1776
1777EOL EQU -1 ; Indicator for End-Of-Line
1778NOERROR EQU 0 ; Return Indicator for No Errors
1779
1780
1781PARSE PROC NEAR
1782
1783 mov num_of_drives,0 ; initialize drive count
1784 mov name_count,0
1785 mov ext_count,0
1786 mov Total_name_count,0 ;AN000;
1787 mov Total_ext_count,0 ;AN000;
1788 mov Prev_Type,0 ;AN000;
1789 mov Ext_Mem,0 ;AN000;
1790 mov Check_Queue,0 ;AN000;
1791 lea si,parambuff ; drive ID buff address ;AN000;
1792 mov parmbuff_Ptr,si ; save it ;AN000;
1793
1794;----------------------------------------------------------------------------
1795; Get command string address from PSP
1796;----------------------------------------------------------------------------
1797 mov si,0081H
1798 mov ah,62H
1799 INT 21H ; get program PSP segment ;AN000;
1800 mov PSP_Seg,bx ; save PSP segment ;AN000;
1801 ;AN000;
1802 mov ds,bx ; DS = PSP segment ;AN000;
1803 mov si,0081h ; SI-->beginning of parameter string in PSP
1804 lea di,cmdline_buff ; DI-->command param buffer ;AN000;
1805 mov cx,127 ; copy 127 bytes from PSP ;AN000;
1806
1807;----------------------------------------------------------------------------
1808; Copy command parameters from PSP to the command buffer
1809;----------------------------------------------------------------------------
1810Cmdloop:
1811 mov al,ds:[si] ; DS:SI-->Command line ;AN000;
1812 mov es:[di],al ; ES:DI-->program command buffer ;AN000;
1813 inc si ;AN000;
1814 inc di ;AN000;
1815 LOOP cmdloop ; copy command line
1816 push cs ;AN000;
1817 pop ds ;AN000;
1818
1819;----------------------------------------------------------------------------
1820; set parametrs for SysParse call
1821;----------------------------------------------------------------------------
1822 xor cx,cx ; no params processed so far ;AN000;
1823 MOV ORDINAL,CX ; SAVE initial ordinal value ;AN000;
1824 lea si,cmdline_buff ; ES:SI-->command line ;AN000;
1825 lea di,parms ; ES:DI-->parameter
1826 MOV CURRENT_PARM,SI ; pointer to next positional ;AN000;
1827
1828 mov ax,0100h ; Drive only
1829 mov pos1type,ax ; set positional control block 1 ;AN000;
1830 mov ax,08502h ; Numeric/Complex/Drive/Repeat
1831 mov pos2type,ax ; set positional control block 2 ;AN000;
1832 mov al,1 ; minimum 1 positional ;AN000;
1833 mov Par_Min,al ;
1834 mov al,2 ;AN000;
1835 mov Par_Max,al ; maximum 1 positional ;AN000;
1836 jmp short set_param
1837
1838;----------------------------------------------------------------------------
1839; MAIN PARSE LOOP
1840;----------------------------------------------------------------------------
1841PARSE_LOOP: ; MAIN PARSE LOOP
1842 mov ax,08502h ; number/drive ID/comlex/repeat
1843 mov pos1type,ax ; set positional control block ;AN000;
1844 mov ax,08502h ;
1845 mov pos2type,ax ;
1846 mov al,1 ; minimum 1 positional ;AN000;
1847 mov Par_Min,al ; set min
1848 mov al,2 ; maximum 2 positionals ;AN000;
1849 mov Par_Max,al ; set max ;AN000;
1850
1851Set_Param:
1852 mov Par_sw,1 ; set switch flag in PARSMX
1853 xor dx,dx
1854 push cs ;AN000;
1855 pop es ; ES=DS=CS ;AN000;
1856 LEA DI,PARMS ; ES:DI = PARSE CONTROL DEFINITON ;AN000;
1857 MOV SI,CURRENT_PARM ; DS:SI = next positional ;AN000;
1858 XOR DX,DX ; RESERVED, INIT TO ZERO ;AN000;
1859 MOV CX,ORDINAL ; OPERAND ORDINAL, INITIALLY ;AN000;
1860
1861 CALL SYSPARSE ; Parse current positional
1862
1863 mov Next_Parm,si ; save pointer to next positional ;AN000;
1864 mov ORDINAL,CX ; save current ordinal ;AN000;
1865 cmp ax,EOL ; END-OF-COMMAND string ?? ;AN000;
1866 jne Parse_chk_Error ; no - check error
1867
1868
1869;----------------------------------------------------------------------------
1870; If previous positional is a drive ID without Name or Extent count then assign
1871; default counts .
1872;----------------------------------------------------------------------------
1873 cmp Prev_Type,6 ; previous param = drive ID ;AN000;
1874 jne Take_Exit ; no - exit ;AN000;
1875 ;AN000;
1876 CALL PROC_DEFAULT ; yes - setup default counts for previous drive ;AN000;
1877 jnc Take_Exit ; exit ;AN000;
1878 jmp parse_Error ; error exit ;AN000;
1879
1880Take_Exit:
1881 CALL Verify_Counts ; verify the Total counts
1882 jnc Counts_OK ; exit if count ok
1883 jmp parse_error ; else error exit
1884
1885Counts_Ok:
1886 jmp parse_exit ; normal - exit
1887
1888
1889;----------------------------------------------------------------------------
1890; CHECK ERROR CONDITIONS
1891;----------------------------------------------------------------------------
1892Parse_Chk_Error: ; check for error conditions
1893 cmp ax,NOERROR ; any parse error ??
1894 jne verify_missing_oper ; yes - check missing operand
1895 jmp Chk_Result ; no - check result buffer ;AN000;
1896
1897Verify_Missing_Oper:
1898 cmp ax,2 ; yes - missing operand error??
1899 jne disp_error ; no - jump ;AN000;
1900
1901 cmp Prev_Type,0 ; yes - any previous parameters ??
1902 jne Chk_Prev_Drive ; yes, previous drive id ;AN000;
1903 mov MSG_CLASS,2
1904 MOV MSG_NUM,AX ; set message number ;AN000;
1905 MOV SUBST_COUNT,0 ; no message substitution ;AN000;
1906 MOV INPUT_FLAG,0 ; no input ;AN000;
1907 CALL PRINT_STDOUT ; show message ;AN000;
1908 stc ; set error flag ;AN000;
1909 jmp Parse_Exit ; exit
1910
1911;----------------------------------------------------------------------------
1912; If previous positional is drive ID without counts then assign default counts
1913;----------------------------------------------------------------------------
1914Chk_prev_drive:
1915 cmp Prev_Type,6 ; previous param = drive ID ?? ;AN000;
1916 jne Take_Exit1 ; no - exit ;AN000;
1917
1918 CALL PROC_DEFAULT ; yes - assign default ID
1919 jnc Take_Exit1 ; no error, verify counts ;AN000;
1920 jmp parse_Error ; error exit ;AN000;
1921
1922Take_Exit1:
1923 CALL Verify_Counts ; verify the Total counts
1924 jnc Counts_right ; count ok - check special case
1925 jmp parse_error ; error - exit
1926
1927Counts_right:
1928 cmp Prev_Type,0 ; no previous param ? (Special case) ;AN000;
1929 je invalid_operand ; no, exit ( FASTOPEN >TEMP ) case ;AN000;
1930 clc ;AN000;
1931 jmp parse_exit ; exit
1932
1933Invalid_Operand: ; else error
1934 jmp bad_param
1935
1936Disp_Error:
1937 cmp ax, 3 ; invalid switch type ??
1938 jne bad_param ; no -
1939 jmp Bad_Switch
1940
1941;----------------------------------------------------------------------------
1942; If user entered à to activate the analyser, than verify the previous
1943; drive case. If true, assign default name extent entries, set activation
1944; flag and take normal exit.
1945;----------------------------------------------------------------------------
1946Bad_Param:
1947 mov si,Current_Parm ; SI-->current parameter (analyser hook)
1948 mov al,0e0h ; à (hidden character to activate analyser)
1949 cmp [si],al ; activate analyser ??
1950 jne set_disp_param ; no - normal error
1951 mov Check_Queue,1 ; yes - set flag to activate analyser
1952 clc
1953 jmp Chk_Prev_Drive ; exit
1954
1955Set_Disp_Param:
1956 mov di,Next_Parm ; ending address of bad param (1/6/88)
1957 mov al,0
1958 mov ds:[di],al ; set termination character
1959 LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000;
1960 MOV AX,CURRENT_PARM ; starting address of bad parameter ;AN000;
1961 MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000;
1962 MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000;
1963 MOV [SI].MSG_ID,0 ; message ID ;AN000;
1964 MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000;
1965 MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000;
1966 MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000;
1967 mov ax,incorrect_param ; Error Code ;AN000;
1968 MOV MSG_NUM,AX ; set message number ;AN000;
1969 MOV SUBST_COUNT,1 ; substitution count ;AN000;
1970 MOV MSG_CLASS,-1 ; message class ;AN000;
1971 MOV INPUT_FLAG,0 ; no input ;AN000;
1972 CALL PRINT_STDOUT ; display message ;AN000;
1973 stc ; error flag
1974 jmp Parse_Exit ; exit (1/6/88 P2670)
1975
1976
1977;----------------------------------------------------------------------------
1978; CHECK POSITIONAL PARAMETER TYPE
1979;----------------------------------------------------------------------------
1980Chk_Result:
1981 push es ; get DS back to Program data segment ;AN000;
1982 pop ds ;AN000;
1983 cmp postype,1 ; number ?? ;AN000;
1984 jne chk_switch ;AN000;
1985 jmp short Proc_Name ; yes, process name entry ;AN000;
1986
1987chk_switch:
1988 cmp postype,3 ; switch ?? ;AN000;
1989 je Proc_sw ; yes, process switch ;AN000;
1990 cmp postype,6 ; drive id ?? ;AN000;
1991 je Proc_driveid ; yes, Process Drive ID ;AN000;
1992 cmp postype,4 ; complex item ?? ;AN000;
1993 jne disp_msg ;AN000;
1994 jmp Proc_complex ; yes, process Complex item ;AN000;
1995
1996disp_msg:
1997 mov ax,incorrect_param ; no, check reult buffer ;AN000;
1998 jmp bad_param ; else error ;AN000;
1999
2000Proc_Sw: jmp Proc_Switch ; process switch ;AN000;
2001
2002
2003
2004;----------------------------------------------------------------------------
2005; PROCESS DRIVE ID
2006;----------------------------------------------------------------------------
2007PROC_DRIVEID: ; PROCESS DRIVE ID
2008 cmp Prev_Type,6 ; previous param = drive ID ;AN000;
2009 jne check_drive_id ; no, jump ;AN000;
2010 ;AN000;
2011; if not set default name and extent entry count for previous drive
2012 CALL PROC_DEFAULT ; setup default counts ;AN000;
2013 jnc Check_Drive_id ; ;AN000;
2014 jmp parse_Error ;AN000;
2015
2016Check_Drive_Id: ; process current drive ID
2017 mov ax,ValueLo ; get drive letter number from result buff ;AN000;
2018 ; C:=3 D:=4 etc, Parser drive id convention ;AN000;
2019 add al,040H ; convert to drive letter ;AN000;
2020
2021 CALL CHECK_DRIVE ; validate drive ID ?? ;AN000;
2022 jnc set_drive_id ; yes, jump ;AN000;
2023 jmp Parse_Exit ; no, invalid drive id , exit ;AN000;
2024
2025Set_Drive_Id:
2026 inc num_of_drives ; update the drive count ;AN000;
2027 xor ax,ax ;AN000;
2028 mov ax,valuelo ; get drive number ;AN000;
2029 xor ah,ah ; only low byte is valid ;AN000;;AN000;
2030 mov di,ParmBuff_Ptr ; DS:DI-->driveID buffer ;AN000;
2031 dec ax ; C:=2 D:=3 E:=4 etc Fastopen drive id ;AN000;
2032 mov [di],ax ; save drive in Drive ID table ;AN000;
2033 add parmbuff_ptr,2 ; points to next extent count area ;AN000;
2034 mov al,PosTYpe ; set previous type before look for next ;AN000;
2035 mov Prev_Type,al ; positional parameter ;AN000;
2036 mov si,Next_Parm ; get pointer to next param (switch) ;AN000;
2037 mov Current_Parm,si ; ;AN000;
2038 jmp Parse_Loop ; look for next posistional parameter ;AN000;
2039
2040
2041;----------------------------------------------------------------------------
2042; PROCESS INTEGER ( C:=n ) followed by drive ID
2043;----------------------------------------------------------------------------
2044PROC_NAME:
2045 cmp Prev_Type, 6 ; previous type = drive ID
2046 je Get_Name_Value ; yes - jump
2047 mov ax,incorrect_param ; error code ;AN000;
2048 jmp bad_param
2049
2050Get_Name_Value:
2051 xor ax,ax ;AN000;
2052 mov ax,valuelo ; get name value ;AN000;
2053 cmp ax,10 ; check validity of the count ;AN000;
2054 jl Bad_Name_Count
2055 cmp ax,999 ;AN000;
2056 jle save_name_count ; count OK, save it ;AN000;
2057
2058Bad_Name_Count: ; bad name count
2059 mov ax,Invalid_Name ; error code ;AN000;
2060 jmp parse_error ; error - exit ;AN000;
2061
2062Save_Name_Count:
2063 mov name_count,ax ; save it (name count)
2064 add Total_Name_Count,ax ; update total name count
2065 mov di,ParmBuff_Ptr ; DS:DI-->driveID buffer ;AN000;
2066 mov ax,-1 ;AN000;
2067 mov [di],ax ; MARK this drive has no extent entry ;AN000;
2068 add parmbuff_ptr,2 ; points to extent count area ;AN000;
2069
2070Set_Drive_Hdr:
2071 mov ax,Name_Count ; get name count entry ;AN000;
2072 CALL SET_DRIVE_CACHE_HEADER ; Set Name cache header ;AN000;
2073 jnc set_min_max ; no error set min and max ;AN000;
2074 jmp parse_Error ; display error ;AN000;
2075
2076Set_Min_Max:
2077 mov al,1 ;AN000;
2078 mov Par_Min,al ; change min-max ;AN000;
2079 mov al,2 ;AN000;;AN000;
2080 mov Par_Max,al ;AN000;
2081 mov al,PosTYpe ; set previous type before look for next ;AN000;
2082 mov Prev_Type,al ;AN000;
2083 mov si,Next_Parm ; get pointer to next param (switch) ;AN000;
2084 mov Current_Parm,si ; ;AN000;
2085 mov ordinal,0 ;AN000;
2086 Jmp Parse_Loop ; parse nexy positional ;AN000;
2087
2088
2089;----------------------------------------------------------------------------
2090; PROCESS COMPLEX (n,m) followed by a drive id
2091;----------------------------------------------------------------------------
2092PROC_COMPLEX:
2093 cmp Prev_Type, 6 ; previous type = drive ID ??
2094 je Get_Cmplx_Item ; yes - ok
2095 mov ax,incorrect_param ; no - error, previous must be drive id ;AN000;
2096 jmp bad_param ; display error
2097
2098Get_Cmplx_Item:
2099 mov al, PosType ;
2100 mov Prev_Type,al ; save current type as previous
2101 lea di,valuelo ; DI-->result buffer ;AN000;
2102 mov si,[di] ; get next positional param address ;AN000;
2103 mov current_parm,si ; SI-->first complex item ;AN000;
2104 mov ax,08001h ; Control ( Numeric/Optional ) ;AN000;
2105 mov Pos1Type,ax ; change pos-param control block flag ;AN000;
2106 mov Pos2Type,ax ;AN000;
2107 mov al,1 ; atleast 1 or maximun two positionals in complex item ;AN000;
2108 mov Par_Min,al ; set minimum = 1
2109 mov al,2 ;AN000;
2110 mov Par_Max,al ; set maximum = 2 ;AN000;
2111 mov ordinal1,0 ; initialize ordinal for complex item loop ;AN000;
2112 mov par_sw,0 ; reset switch flag in PARMSX
2113
2114COMPLX_LOOP:
2115 xor dx,dx
2116 LEA DI,PARMS ;ES:DI = PARSE CONTROL DEFINITON ;AN000;
2117 MOV SI,CURRENT_PARM ;SI = COMMAND STRING, NEXT PARM ;AN000;
2118 XOR DX,DX ;RESERVED, INIT TO ZERO ;AN000;
2119 MOV CX,ORDINAL1 ;OPERAND ORDINAL, INITIALLY ZERO ;AN000;
2120
2121 CALL SYSPARSE ; parse positional param in complex item
2122
2123 cmp ax,NOERROR ; parse error ??
2124 je Chk_Complex_Result ; no, check result buffer ;AN000;
2125 cmp ax,EOL ; END-OF-COMMAND string ?? ;AN000;
2126 jne Complex_Error ; no, check error
2127 mov si,Next_Parm ; Set pointer to next param (4/3/88)
2128 mov Current_Parm,si ; set next param address before parsing ;AN000;
2129 jmp Parse_Loop ; go to main parse loop
2130
2131Complex_Error:
2132 mov ax,Incorrect_Param ; no, check reult buffer ;AN000;
2133 jmp bad_param ; display error
2134
2135;-------------------------------------------------------------------------------
2136; Ckeck The Result Buffer
2137;-------------------------------------------------------------------------------
2138Chk_Complex_Result:
2139 mov ordinal1,cx ; save current ordinal ;AN000; ;AN000;
2140 cmp postype,1 ; positional type = number ??
2141 je Proc_Complex_Name ; yes, process name entry ;AN000;
2142 cmp postype,3 ; positional type = String ??
2143 je Miss_param ; yes, process missing parameter
2144 mov ax,incorrect_param ; no, check reult buffer ;AN000;
2145 jmp bad_param
2146
2147Miss_Param:
2148 mov current_parm,si ; save current chara pointer ;AN000;
2149 jmp complx_loop ; get extent count
2150
2151
2152;-------------------------------------------------------------------------------
2153; PROCESS NAME ENTRY (n)
2154;-------------------------------------------------------------------------------
2155Proc_Complex_Name: ; PROCESS COMPLEX ITEM
2156 mov current_parm,si ; save current chara pointer ;AN000;
2157 cmp cx,2 ; second positional in the complex ;AN000;
2158 je proc_extent_entry ; yes, process Extent count ;AN000;
2159 xor ax,ax ; eles process Name Count ;AN000;
2160 mov ax,valuelo ; get name value from result buffer ;AN000;
2161 cmp ax,10 ; validate the name value for higher ;AN000;
2162 jl Name_Error ; and lower boundries ;AN000;
2163 cmp ax,Max_Entry_Num ; name entry count ok ??
2164 jg Name_Error ; no - error
2165 jmp short Store_Name_Count ; yes - store it
2166
2167Name_Error: ; invalid name count
2168 mov ax,invalid_name ; error code ;AN000;
2169 jmp parse_error ; display error
2170
2171Store_Name_Count:
2172 mov Name_Count,ax ; save it (name count) ;AN000; ;AN000;
2173 add Total_name_count,ax ; update total name count ;AN000; ;AN000;
2174
2175 CALL SET_DRIVE_CACHE_HEADER ; Set Name cache header ;AN000;
2176 jc Cant_Set_Header ; jump if error ;AN000;
2177 jmp Complx_loop ; look for extent count ;AN000;
2178
2179Cant_Set_Header:
2180 jmp Parse_Error ; error exit
2181
2182
2183;-------------------------------------------------------------------------------
2184; PROCESS EXTENT ENTRY (m)
2185;-------------------------------------------------------------------------------
2186Proc_Extent_Entry:
2187 mov ax,valuelo ; get extent count entry
2188 cmp ax,1 ; validate entry between 1 an 10 ;AN000;
2189 jl Extent_Error ;AN000;
2190 cmp ax,10
2191 jl set_default_ext ; if <10 set default entry 12
2192 cmp ax,Max_Entry_Num ; >999 ??
2193 jg Extent_Error ; yes - error
2194 jmp short Store_Extent_Count ; value OK, save it
2195
2196Set_Default_Ext: ; for count 1 throug 9 set default count 12
2197 mov ax,12
2198 jmp short Store_Extent_Count
2199
2200Extent_Error: ; invalid entry error
2201 mov ax,invalid_extent ; error code
2202 jmp parse_error ; display error ;AN000;
2203
2204Store_Extent_Count:
2205 mov ext_count,ax ; save the count
2206 add Total_Ext_count,ax ; update total extent count
2207 mov di,parmbuff_ptr ; DI-->drive/extent buffer ;AN000;
2208 mov [di],ax ; save in buffer ;AN000;
2209 add parmbuff_ptr,2 ; move pointer to next extent in buffer ;AN000;
2210 mov si,Next_Parm ; get pointer to next param
2211 mov Current_Parm,si ; set next param address before parsing ;AN000;
2212 mov Par_Sw,1 ; set switch flag in PARMSX
2213 Jmp Parse_Loop ; parse next positional parameter ;AN000;
2214
2215
2216;----------------------------------------------------------------------------
2217; PROCESS SWITCH (/X) OPTION
2218;----------------------------------------------------------------------------
2219Proc_Switch:
2220 cmp Prev_Type,0 ; any previous type ??
2221 je Switch_Error ; no - error
2222 cmp Ext_Mem,0 ; switch previously specified ?? ;AN000;
2223 je set_sw_flag ; no, set flag ;AN000;
2224
2225Switch_Error:
2226 mov ax,incorrect_param ; error code ;AN000;
2227 jmp bad_param ; error - /x could be specified only once
2228
2229Set_Sw_flag:
2230 cmp Prev_Type,6 ; previous param = drive ID 12/15 P2939 ;AN000;
2231 jne sw_save_Ptr ; no - continue 12/15 p2939 ;AN000;
2232 ;AN000;
2233 CALL PROC_DEFAULT ; yes setup default counts for previous drive ;AN000;
2234 jnc sw_save_ptr ; no error - continue 12/15 p2939 ;AN000;
2235 jmp short parse_Error ; error - exit 12/15 P2939 ;AN000;
2236
2237Sw_save_ptr:
2238 mov current_parm,si ; save current chara pointer ;AN000;
2239 mov bx,synonym ; get synonym (/x) ;AN000; ;AN000;
2240 cmp bx,offset e_switch ; /X ?? ;AN000;
2241 je set_extflag ; yes - check result buffer ;AN000;
2242 jmp Bad_Switch ; error exit
2243
2244Set_ExtFlag: ; no, check reult buffer
2245 mov Ext_Mem,1 ; yes, set Hi Memory flag ;AN000;
2246 mov si,Current_parm ; -->next parameter ;AN000;
2247 mov al,PosTYpe ; set prevvious type before look for next ;AN000;
2248 mov Prev_Type,al ;AN000;
2249 jmp parse_loop ;AN000;
2250
2251Bad_Switch:
2252 mov di,Next_Parm ; ending address of bad param 1/6/88
2253 mov al,0
2254 mov ds:[di],al ; set termination character
2255 LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000;
2256 MOV AX,CURRENT_PARM ; starting address of bad parameter ;AN000;
2257 MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000;
2258 MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000;
2259 MOV [SI].MSG_ID,0 ; message ID ;AN000;
2260 MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000;
2261 MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000;
2262 MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000;
2263 MOV BX,Invalid_Switch ; get message number
2264 MOV MSG_NUM,BX ; set message number ;AN000;
2265 MOV SUBST_COUNT,1 ; substitution count ;AN000;
2266 MOV MSG_CLASS,-1 ; message class ;AN000;
2267 MOV INPUT_FLAG,0 ; no input ;AN000;
2268 CALL PRINT_STDOUT ; display message ;AN000;
2269 stc ; error flag
2270 jmp Parse_Exit ; exit (1/6/88 P2670)
2271
2272
2273
2274;----------------------------------------------------------------------------
2275; PROCESS PARSE ERROR
2276;----------------------------------------------------------------------------
2277PARSE_ERROR: ; AX = meassage number
2278 MOV MSG_CLASS,-1 ; message class ;AN000;
2279 MOV MSG_NUM,AX ; set message number ;AN000;
2280 MOV SUBST_COUNT,0 ; no message substitution ;AN000;
2281 MOV INPUT_FLAG,0 ; no input ;AN000;
2282 CALL PRINT_STDOUT ; show message ;AN000;
2283 stc ; set error flag ;AN000;
2284
2285Parse_Exit: ; EXIT
2286 push cs ;AN000;
2287 pop ds ; DS - Program data area seg ;AN000;
2288 ret ;AN000; ;AN000;
2289PARSE ENDP ; end of parser
2290
2291
2292
2293
2294;----------------------------------------------------------------------------
2295;
2296; Procedure: PROC_DEFAULT
2297;
2298; Function: Process default parameters if name and extend counts
2299; are not specified with the drive id.
2300;
2301;----------------------------------------------------------------------------
2302
2303PROC_DEFAULT PROC ; PROCESS DEFAULT
2304 push si ; makesure to save next chara pointer ;AN000;
2305 mov ax,30h ; get default name count ;AN000;
2306 mov name_count,ax ; save it ;AN000;
2307 add Total_name_count,ax ; update total name count ;AN000;
2308 mov ext_count,ax ; save it ;AN000; ;AN000;
2309 add Total_Ext_count,ax ; save it ;AN000; ;AN000;
2310 mov di,ParmBuff_Ptr ; DS:DI-->parameter buffer ;AN000;
2311 mov [di],ax ; save in buffer ;AN000;
2312 add Parmbuff_ptr,2 ; points to next drive id position
2313 mov ax,Name_Count ;AN000;
2314 CALL Set_drive_Cache_Header ; Set Name cache header ;AN000;
2315
2316Default_Exit:
2317 pop si ;AN000;
2318 ret ; return ;AN000;
2319
2320PROC_DEFAULT ENDP
2321
2322
2323
2324
2325;----------------------------------------------------------------------------
2326; Procedure: VERIFY_COUNTS
2327;
2328; Function: Verify the validity of the name and extent counts
2329
2330;----------------------------------------------------------------------------
2331VERIFY_COUNTS PROC NEAR
2332
2333; Check the validity of NAME and EXTENT count entries
2334 cmp Total_ext_count,0 ; any extent param ?? ;AN000;
2335 je Chk_Name_Count ; no, dont check extent count ;AN000;
2336 cmp Total_ext_count, Max_Entry_Num ; check lower boundry ;AN000;
2337 jg invalid_ext ; error if not within ;AN000;
2338 clc ; Extent Count is valid
2339
2340; Extent count is OK, check Name count
2341Chk_Name_Count:
2342 cmp Total_Name_Count,0 ; any name param ?? ;AN000;
2343 je Verify_Exit ; no, dont check extent count ;AN000;
2344
2345 cmp Total_name_count, Max_Entry_Num ;AN000;
2346 jg invalid_name_entry ;AN000;
2347 clc ; Name count is OK ;AN000;
2348 jmp short verify_exit ; exit ;AN000;
2349
2350Invalid_ext:
2351 mov ax,many_ext_entries ; AX = error code ;AN000;
2352 stc
2353 jmp short verify_exit ;AN000;
2354
2355Invalid_name_entry:
2356 mov ax,many_name_entries ; AX = error code ;AN000;
2357 stc ;AN000;
2358
2359Verify_Exit: ;
2360
2361 RET ;AN000;
2362
2363VERIFY_COUNTS ENDP
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375;=========================================================================
2376; CHECK_DRIVE
2377;-----------------------------------------------------------------------
2378;
2379; INPUT: AL - Drive letter
2380;
2381; OUTPUT:
2382; If Carry = 0
2383; user_drive set to current entered drive letter
2384; num_Of_drives incremented
2385; If Carry = 1 error
2386;-----------------------------------------------------------------------
2387; 1) see if drive is valid and removable using int 21h IOCTL
2388;
2389; 2) use int 21h name translate to make sure that the drive is not
2390; redirected, substed, on another machine, or in any other way shape
2391; or form hosed.
2392;=========================================================================
2393
2394CHECK_DRIVE PROC NEAR
2395
2396 CALL Convert_To_Caps ; make sure it is a capital letter
2397 mov byte ptr user_drive,al ; save it in user drive
2398 mov byte ptr source_xname,al ; put in source string for call
2399
2400 mov bl,al ;put drive letter in bl
2401 sub bl,"A"-1 ;convert to 1 based number
2402
2403 mov ah,ioctl ;set up for removable call
2404 mov al,8 ;function code
2405 INT int_command
2406
2407 cmp ax,1 ;is drive fixed?
2408 jz okay_drive ;yes - see if it's subst
2409 cmp ax,0fh ;is drive valid?
2410 jnz hosed_drive ;yes - but hosed
2411
2412 mov ax,invalid_drive ; set bad drive message
2413 jmp short drive_Error ; display error message
2414
2415Okay_Drive:
2416 lea si,source_xname ; set up for name translate
2417 lea di,target_xname
2418 mov ax,xNameTrans SHL 8
2419 INT int_command ;do the translation
2420
2421 lea si,source_xname ;compare source and target drive
2422 lea di,target_xname
2423
2424 mov cx,Len_source_xname ;get count of invalid chars
2425 repz cmpsb ;compare until mismatch found
2426 jz check_drive_end ;no mismatch - exit
2427
2428Hosed_Drive:
2429 MOV AX,BAD_USE_MESSAGE ; message number
2430
2431Drive_Error:
2432 push ax ; save message number
2433 mov ax,Valuelo ; get drive letter number from result buff
2434 ; C:=3 D:=4 etc, Parser drive id convention
2435 add al,040H ; convert to drive letter
2436 lea si,Drive_Id ; DS:SI-->drive letter save area
2437 mov [si],al ; save drive letter in buffer
2438
2439 LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000;
2440 MOV AX,OFFSET DRIVE_ID ;AN000;
2441 MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000;
2442 MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000;
2443 MOV [SI].MSG_ID,1 ; message ID ;AN000;
2444 MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000;
2445 MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000;
2446 MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000;
2447 POP AX ; restore message number ;AN000;
2448 MOV MSG_NUM,AX ; set message number ;AN000;
2449 MOV SUBST_COUNT,1 ; substitution count ;AN000;
2450 MOV MSG_CLASS,-1 ; message class ;AN000;
2451 MOV INPUT_FLAG,0 ; no input ;AN000;
2452 CALL PRINT_STDOUT ; display message ;AN000;
2453 stc ; error flag
2454
2455Check_Drive_End:
2456 ret ; return
2457
2458CHECK_DRIVE endp
2459
2460
2461
2462
2463
2464;=========================================================================
2465; Procedure: SET_DRIVE_CACHE_HEADER
2466;
2467; Function: Set name cache drive header
2468;
2469; Input: ax contains number of entries for num_entries
2470; user_drive contains user drive for drive_letter
2471; num_Of_drives contains number of caches set up so far
2472; drive_cache offset of drive cache headers start
2473; Output:
2474; If successful:
2475; drive cache header set up
2476; user_drive reset to blank
2477; num_Of_drives incremented
2478; else
2479; bx set to error flag
2480; dx points to error message
2481;-----------------------------------------------------------------------
2482; 1) see if drive too many drives have been entered.
2483; 2) Walk through drive cache headers to make sure that the drive
2484; letter was not previously entered.
2485; 3) Set up drive cache header
2486;=========================================================================
2487
2488SET_DRIVE_CACHE_HEADER PROC NEAR
2489
2490 mov cx,num_of_drives ;get current count of drives
2491 mov bx,offset drive_cache ;get start of name drive cache
2492 mov dl,user_drive ;get user entered drive
2493 dec cx ;is this the 1st drive entered ?
2494 jcxz set_it_up ;yes - don't check
2495
2496 cmp num_Of_drives,max_drives ;no - check for maximum num of drives
2497 jng we_have_room ;yes - go check for dup drives
2498 mov ax,too_many_entries ;set up for error message
2499 stc ;set up error flag
2500 jmp short set_dheader_exit ;and exit
2501
2502;-----------------------------------------------------------------------
2503; Search through the drive headers to see the duplicate drive exist.
2504; If a new drive header at the bottom of the chain for the new drive.
2505; If no drives exist, then create the new header as the first drive header.
2506;-----------------------------------------------------------------------
2507We_Have_Room: ;BX-->current drive header
2508 cmp dl,[bx].dch_drive_letter ;drive header exist for this drive??
2509 jnz not_dup_drive ;no - continue
2510 mov ax,dup_drive ;yes - set up for error message
2511 stc
2512 jmp short set_dheader_exit ;exit
2513
2514Not_Dup_Drive:
2515 cmp [bx].dch_sibling_ptr,no_siblings ;any more header to search ??
2516 jz set_drive_sibling ;no - go create the new drive header
2517 add bx,size drive_cache_header ;yes - get pointer to next drive header
2518 jmp short we_have_room ;check it
2519
2520Set_drive_sibling:
2521 mov cx,bx ;save current header address
2522 add cx,size drive_cache_header ;pointer to next header
2523 mov [bx].dch_sibling_ptr,cx ;set pointer to new header from current hdr
2524 mov bx,cx ;BX-->new header
2525
2526Set_it_up:
2527 mov [bx].dch_drive_letter,dl ;save drive letter in new header
2528 mov [bx].dch_sibling_ptr,no_siblings ;mark new header as last header in chain
2529 mov [bx].dch_num_entries,ax ;save name count in new header
2530
2531Set_dheader_Exit: ; Exit
2532 ret
2533
2534SET_DRIVE_CACHE_HEADER ENDP
2535
2536
2537
2538
2539
2540subttl Convert to caps
2541page
2542;=========================================================================
2543; Procedure: Convert_to_caps
2544;
2545; CONVERT LOWER CASE CHARACTERS TO UPPER CASE
2546; Convert character in al to a capital letter.
2547
2548;=========================================================================
2549
2550CONVERT_TO_CAPS PROC NEAR
2551
2552 cmp al,"a"
2553 JNAE no_convert
2554 cmp al,"z"
2555 JNBE no_convert
2556 sub al,32
2557
2558No_Convert:
2559 ret ;and return
2560
2561CONVERT_TO_CAPS ENDP
2562
2563
2564
2565
2566
2567
2568
2569;=========================================================================
2570; SET_EMS : THIS MODULE SETS EMS FOR FASTOPEN CODE AND DATA
2571; PAGE 0 IN HIGH MEMORY IS MAPPED FOR CODE USING
2572; THE PHYSICAL PAGE FRAME AND PAGE 1 IS
2573; MAPPED FOR DATA USING PHYSICAL PAGE FRAME NUMBER
2574; TWO PHYSICAL PAGE FRAME SEG IDs ARE SAVED AND
2575; THEY WILL BE USED BY THE (MAIN) ROUTINE.
2576;
2577; INPUTS : NONE
2578;
2579; OUTPUTS : CY - ERROR
2580;
2581; NC - EMS_PAGE_SEG - SEG ID OF SINGLE PAGE FRAME
2582;=========================================================================
2583
2584SET_EMS PROC NEAR
2585 CALL EMS_CHECK1 ;SEE IF EMS INSTALLED ;AN000;
2586 JNC EMS_GET_PAGE ; yes, get page ;AN000;
2587
2588 MOV EMS_FLAG,0 ; Flag EMS not installed ;AN000;
2589 STC ; Make sure carry is Clear ;AN000;
2590 JMP EMS_EXIT ; Leave check routine ;AN000;
2591
2592EMS_GET_PAGE:
2593 PUSH ES ; save ES,DI they may destroy by 2F
2594 PUSH DI
2595
2596IF NOT BUFFERFLAG
2597
2598 MOV AH,EMS_2F_HANDLER
2599 XOR AL,AL
2600 INT 2FH ; see 2F is there
2601 CMP AL,0FFH
2602 JNE EMS_PAGE_ERR ; error, if not
2603
2604 MOV AH,EMS_2F_HANDLER
2605 MOV AL,0FFH
2606 MOV DI,0FEH
2607 INT 2FH ; get EMS page
2608 OR AH,AH
2609 JNZ EMS_PAGE_ERR
2610 MOV EMS_PAGE_SEG,ES ; SAVE PAGE SEG ID
2611 MOV EMS_PAGE_NUM,DI ; SAVE PHYSICAL PAGE NUMBER
2612
2613ELSE
2614
2615;---------------------------------------------------------------HKN 8/25/88
2616; Fastopen must get an EMS page like a well behaved program and
2617; should not grab a reserved page from the BIOS.
2618;
2619 mov cx, FRAME_COUNT
2620 xor ax, ax
2621 mov bx, ax
2622 mov dx, ax
2623
2624get_page:
2625 cmp es:[di], 0a000h ; is the page in ax above 640K
2626 jb next_page ; if no get next_page
2627
2628 mov bx, di ; we have a valid page
2629
2630 inc dx ; count the # of pages above 640K
2631
2632 cmp dx, 1
2633 je next_page
2634 sub di, 4
2635 mov ax, es:[di]
2636 mov [FST_PAGE], ax
2637 mov ax, es:[di+2]
2638 mov [FST_PAGE+2], ax
2639 mov di, bx ; restore di
2640
2641next_page:
2642 add di, 4
2643 loop get_page
2644 jne found_page
2645 jmp ems_page_err
2646
2647found_page:
2648; int 3
2649 cmp dx, 1
2650 jne second_last_page
2651 mov di, bx
2652 mov ax, es:[di]
2653 mov ems_page_seg, ax
2654 mov ax, es:[di+2]
2655 mov ems_page_num, ax
2656 jmp save_state
2657
2658second_last_page:
2659 mov ax, [FST_PAGE]
2660 mov ems_page_seg, ax
2661 mov ax, [FST_PAGE+2]
2662 mov ems_page_num, ax
2663
2664save_state:
2665 push es
2666 mov ax, Cseg_Main
2667 mov es, ax
2668 assume es:Cseg_Main
2669
2670 mov word ptr save_map_addr, offset es:save_ems_page_state
2671 mov word ptr save_map_addr + 2, ax
2672
2673 mov ax, ems_page_seg
2674 mov es:Main_EMS_PAGE_SEG, ax
2675 pop es
2676 assume es:Cseg_Init
2677 call [save_map_addr]
2678 jc ems_page_err
2679
2680;--------------------------------------------------------------------------
2681
2682ENDIF
2683
2684 POP DI
2685 POP ES
2686 JMP SHORT EMS_ALLOCATE_PAGE
2687
2688EMS_PAGE_ERR:
2689 POP DI
2690 POP ES
2691 STC ;yes, page not found ;AN000;
2692 JMP SHORT EMS_ERROR ;error exit ;AN000;
2693
2694;-----------------------------------------------------------------------
2695; Allocate one page
2696;-----------------------------------------------------------------------
2697EMS_ALLOCATE_PAGE:
2698 MOV BX,1 ;one page ;AN000;
2699 MOV AH,EMS_ALLOC_PAGES ;set op code ;AN000;
2700 INT EMS_INT ;allocate page ;AN000;
2701 OR AH,AH ;Was there an error allocating? ;AN000;
2702 JNZ EMS_ERROR ;yes - display error ;AN000;
2703 MOV EXT_HANDLE,DX ;no -Save EMS handle
2704
2705IF BUFFERFLAG
2706
2707;------------------------------------------------------HKN 8/25/88
2708; Must save ems handle in Cseg_Main also.
2709
2710 push es
2711 push ax
2712 mov ax, Cseg_Main
2713 mov es, ax
2714 assume es:Cseg_Main
2715 mov es:ems_save_handle1, dx
2716 pop ax
2717 pop es
2718 assume es:Cseg_Init
2719
2720ENDIF
2721
2722;-----------------------------------------------------------------------
2723; SET HANDLE NAME TO THE PAGE HANDLE
2724;-----------------------------------------------------------------------
2725 PUSH DS ;AN000;
2726 POP ES ;AN000;
2727 ASSUME ES:CSEG_INIT ;AN000;
2728 LEA SI,HANDLE_NAME ; DS:SI-->Handle name string ;AN000;
2729 MOV DX,EXT_HANDLE ; handle number ;AN000;
2730 MOV AH,EMS_HANDLE_NAME ;AN000;
2731 MOV AL,1 ; set op code code ;AN000;
2732 INT 67H ; set handle ;AN000;
2733 OR AH,AH ;AN000;
2734 JNZ EMS_ERROR ; jump if error ;AN000;
2735
2736;-----------------------------------------------------------------------
2737; Map logical page 0 in physical page frame FE (P254)
2738;-----------------------------------------------------------------------
2739 CALL MAP_FRAME ;map two pages ;AN000;
2740 JNC EMS_GET_SIZE ;no error, normal exit ;AN000;
2741
2742;-----------------------------------------------------------------------
2743; Get partial page map size
2744;-----------------------------------------------------------------------
2745EMS_GET_SIZE:
2746 MOV AH,EMS_PAGE_SIZE ;Allocate requested pages ;AN000;
2747 MOV AL,2
2748 INT EMS_INT ; ;AN000;
2749 OR AH,AH
2750 JNZ EMS_ERROR
2751 XOR AH,AH
2752 MOV EMS_PAGESIZE,AX ;save EMS page size
2753 CLC
2754 JMP SHORT EMS_EXIT
2755
2756EMS_ERROR:
2757 MOV AX,EMS_FAILED ;error message ;AN000;
2758 MOV MSG_NUM,AX ;save message number
2759 MOV SUBST_COUNT,0 ;no message substitution ;AN000;
2760 MOV MSG_CLASS,-1 ;message class ;AN000;
2761 MOV INPUT_FLAG,0 ;no input ;AN000;
2762 CALL PRINT_STDOUT ;show message "Incorrect Parameter" ;AN000;
2763 STC ; set error flag ;AN000;
2764
2765EMS_EXIT:
2766 RET ; Return ;AN000;
2767
2768SET_EMS ENDP
2769
2770
2771
2772
2773
2774
2775;=========================================================================
2776; EMS_CHECK1 : THIS MODULE DETERMINES WHETHER OR NOT EMS IS
2777; INSTALLED FOR THIS SESSION.
2778;
2779; INPUTS : NONE
2780;
2781; OUTPUTS : ES:BX - FRAME ARRAY
2782; CY - EMS NOT AVAILABLE
2783; NC - EMS AVAILABLE
2784;=========================================================================
2785
2786EMS_CHECK1 PROC NEAR ;EMS INSTALL CHECK
2787
2788 PUSH DS ;save ds ;AN000;
2789 XOR AX,AX ;set ax to 0 ;AN000;
2790 MOV DS,AX ;set ds to 0 ;AN000;
2791 CMP DS:WORD PTR[067h*4+0],0 ;see if int 67h is there ;AN000;
2792 POP DS ;restore ds ;AN000;
2793 JE EMS_NOT_INST1 ;no, EMS not installed ;AN000;
2794
2795 MOV AH,EMS_GET_STATUS ;YES, GET STATUS ;AN000;
2796 INT EMS_INT ;INT 67H ;AN000;
2797 CMP AH,0 ;EMS MANAGER PRESENT ??
2798 JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED
2799
2800 MOV AH,EMS_GET_VERSION ;YES, GET STATUS ;AN000; ;AN000;
2801 INT EMS_INT ;INT 67H ;AN000;;AN000;
2802 CMP AH,0 ;EMS MANAGER PRESENT ?? ;AN000;
2803 JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED ;AN000;
2804
2805 CMP AL,40H ;VERSION 4.0 ?? ;AN000;
2806 JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED ;AN000;
2807
2808 MOV AX,EMS_GET_COUNT
2809 INT EMS_INT ;GET ARRAY COUNT
2810 CMP AH,0
2811 JNE EMS_NOT_INST1
2812
2813 MOV FRAME_COUNT,CX
2814 MOV AX, BUFFER_ENTRY_SIZE
2815 MUL CX ; CALCULATE THE ARRAY SIZE BE RESERVED
2816
2817IF NOT IBMCOPYRIGHT
2818 CMP AX, 100h
2819ELSE
2820 CMP AX, 30H
2821ENDIF
2822
2823 JG EMS_NOT_INST1
2824
2825 MOV AX,EMS_GET_FRAME_ADDR ;YES, GET FRAME ADDRESS ;AN000;
2826 PUSH DS ;SWAP DS & ES ;AN000;
2827 POP ES ; ;AN000;
2828 LEA DI,FRAME_BUFFER ;ES:DI--> RESULT BUFFER ;AN000;
2829 INT EMS_INT ;GET FRAME ADDRESSES ;AN000;
2830 CMP AH,0 ;IS EMS INSTALLED ;AN000;
2831 JNE EMS_NOT_INST1 ;NO,exit
2832 CMP CX,FRAME_COUNT ; ;AN000;
2833 JNE SHORT EMS_NOT_INST1
2834
2835 CLC
2836 MOV EMS_FLAG,1 ; EMS IS ACTIVE, SET FLAG
2837 JMP EMS_CHECK1_EXIT
2838
2839EMS_NOT_INST1: ;EMS NOT INSTALLED
2840 MOV AX,EMS_NOT_INSTALL ;error message ;AN000;
2841 MOV MSG_NUM,AX ;set message number ;AN000;
2842 MOV SUBST_COUNT,0 ;no message substitution ;AN000;
2843 MOV MSG_CLASS,-1 ;message class ;AN000;
2844 MOV INPUT_FLAG,0 ;no input ;AN000;
2845 CALL PRINT_STDOUT ;show message
2846 STC ;FLAG EMS NOT INSTALLED ;AN000;
2847 ;AN000;
2848EMS_CHECK1_EXIT: ;EXIT ROUTINE
2849 RET ;RETURN TO CALLER ;AN000;
2850
2851EMS_CHECK1 ENDP
2852
2853
2854
2855
2856;=========================================================================
2857; MAP_FRAME : THIS MODULE MAPS TWO LOGICAL PAGES IN THE HIGH
2858; MEMORY TO TWO PHYSICAL PAGE FEAMES IN THE LOW
2859; MEMORY.
2860;
2861; INPUTS : EXT_HANDLE - HANDLE
2862;
2863; OUTPUTD CY - ERROR
2864; NC - PAGE IS MAPPED
2865;=========================================================================
2866
2867MAP_FRAME PROC NEAR ; MAP physical page frames
2868 PUSH BX ; DMS;
2869 XOR BX,BX ; Logical page 0 ;AN000;
2870 MOV AX,EMS_PAGE_NUM ; AL=Physical Page frame number ;AN000;
2871 MOV AH,EMS_MAP_HANDLE ; AH=EMS function to map page ;AN000;
2872 MOV DX,EXT_HANDLE ; EMS handle ;AN000;
2873 INT EMS_INT ;AN000;
2874 OR AH,AH ; Was there an error allocating? ;AN000;
2875 JNZ MAP_ERROR ; yes - set flag ;AN000;
2876 CLC
2877 JMP SHORT MAP_EXIT ; no - exit ;AN000;
2878
2879MAP_ERROR:
2880 STC ; set error flag ;AN000;
2881
2882MAP_EXIT:
2883 POP BX ;AN000;
2884 RET ; return ;AN000;
2885
2886
2887MAP_FRAME ENDP
2888
2889
2890
2891
2892
2893
2894
2895
2896;************************************************************
2897;*
2898;* SUBROUTINE NAME: PRINT_STDOUT
2899;*
2900;* SUBROUTINE FUNCTION:
2901;* Display the requested message to the specified handle
2902;*
2903;* INPUT:
2904;* Paramters in parater storage area
2905;* DS:SI-->Substitution List
2906;* ES:DI-->PTR to input buffer if buffered keyboard
2907;* input is specified (DL = 0A)
2908;* OUTPUT:
2909;* AX = Single character entered if DL=01
2910;* OR
2911;* ES:DI-->input buffer where string is returned if DL=0A
2912;*
2913;* The message corresponding to the requested msg number will
2914;* be written to Standard Out. Message substitution will
2915;* be performed if specified
2916;*
2917;* NORMAL EXIT:
2918;* Message will be successfully written to requested handle.
2919;*
2920;* ERROR EXIT:
2921;* None. Note that theoretically an error can be returned from
2922;* SYSDISPMSG, but there is nothing that the application can do.
2923;*
2924;* INTERNAL REFERENCES: SysDispMsg
2925;*
2926;* EXTERNAL REFERENCES:
2927;* None
2928;*
2929;************************************************************
2930PRINT_STDOUT PROC NEAR
2931 PUSH BX ;AN000;
2932 PUSH CX ;AN000;
2933 PUSH DX ;AN000;
2934
2935 MOV AX,MSG_NUM ; Message ID ;AN000;
2936 MOV BX,STDOUT ; standard input message handle ;AN000;
2937 MOV CX,SUBST_COUNT ; message substitution count ;AN000;
2938 MOV DH,MSG_CLASS ; message class ;AN000;
2939 MOV DL,INPUT_FLAG ; Type of INT 10 for KBD input ;AN000;
2940
2941 CALL SYSDISPMSG ; AX=Extended key value if wait ;AN000;
2942 ;for key ;AN000;
2943 JNC DISP_DONE ; If CARRY SET then registers
2944 ;will contain extended error info ;AN000;
2945 ; AX - Extended error Number
2946 ; BH - Error Class
2947 ; BL - Suggested action
2948DISP_DONE: ; CH - Locus
2949 POP DX ;AN000;
2950 POP CX ;AN000;
2951 POP BX ;AN000;
2952 ;AN000;
2953 RET
2954PRINT_STDOUT ENDP
2955
2956
2957CSEG_INIT ENDS
2958
2959
2960;===========================================================================
2961;;; STACK SEGMENT SIZE = 20 PARAGRAPHS
2962;===========================================================================
2963
2964STACK SEGMENT PARA STACK 'STACK'
2965 DB 64 dup("STACK ") ; 512 WORD STACK AREA ;AN000;
2966STACK ENDS
2967
2968
2969END START
2970
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM
new file mode 100644
index 0000000..5594abd
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM
@@ -0,0 +1,2052 @@
1 Page 84,132 ;
2Title FASTOPEN
3;Date: May 13,1988
4;==============================================================================
5; EQUATES
6;==============================================================================
7Is_drive_head EQU 00000001b ;AN000;
8Is_delete EQU 00000010b ;AN000;
9Is_insert EQU 00000100b ;AN000;
10Not_drive_head EQU 11111110b ;AN000;
11Not_delete EQU 11111101b ;AN000;
12Not_insert EQU 11111011b
13
14EMS_SAVE_STATE EQU 4FH ;AN000;
15EMS_RESTORE_STATE EQU 4FH ;AN000;
16EMS_INT EQU 67H ;AN000;
17DOS_PAGE1 EQU 0FEH ;AN000;
18
19
20;==============================================================================
21; INCLUDE FILES
22;==============================================================================
23.xcref
24.xlist
25debug=0 ; an equate only for DOSMAC.inc ;AN000;
26INCLUDE DOSMAC.inc ;AN000;
27.list
28.cref
29INCLUDE dirent.inc ;AN000;
30INCLUDE fastsegs.inc ; this cannot include in Fastopen.inc
31INCLUDE fastopen.inc ; this include file also contains DOS equates ;AN000;
32include version.inc
33
34;==============================================================================
35
36
37
38EXTRN FK_OPEN:FAR ;AN000;
39EXTRN FK_CLOSE:FAR ;AN000;
40EXTRN FK_INSERT:FAR ;AN000;
41EXTRN FK_DELETE:FAR ;AN000;
42EXTRN FK_LOOKUP:FAR ;AN000;
43EXTRN FK_TRUNCATE:FAR ;AN000;
44EXTRN FK_PURGE:FAR ;AN000;
45
46
47;============================================================================
48
49CSEG_MAIN SEGMENT PARA PUBLIC 'code'
50 ASSUME cs:cseg_main, ds:nothing,es:nothing,ss:nothing
51;============================================================================
52
53PUBLIC MAIN ;AN000;
54
55IF BUFFERFLAG
56PUBLIC SAVE_EMS_PAGE_STATE
57PUBLIC EMS_PAGE_NUMBER
58ENDIF
59
60PUBLIC RESTORE_PAGE_STATE
61PUBLIC EMS_SAVE_HANDLE1
62
63PUBLIC Main_name_cache_seg ;AN000;
64PUBLIC Main_Num_Of_drives ;AN000;
65PUBLIC Main_Ext_Count ;AN000;
66PUBLIC Main_extent_drive_Buff ;AN000;
67PUBLIC Main_ext_cache_size ;AN000;
68PUBLIC Main_name_cache_Buff ;AN000;
69PUBLIC Main_EMS_FLAG ;AN000;
70PUBLIC Main_Res_Segs ;AN000;
71PUBLIC Main_EMS_PAGE_SIZE ;AN000;
72PUBLIC Main_EMS_PAGE_SEG ;AN000;
73PUBLIC Main_Total_Ext_Count ;AN000;
74PUBLIC Main_Total_Name_Count ;AN000;
75PUBLIC Main_Name_Drive_Buff ;AN000;
76PUBLIC Main_ParamBuff ;AN000;
77
78PUBLIC FOPEN_Insert ;AN000;
79PUBLIC FOPEN_Update ;AN000;
80PUBLIC FOPEN_Delete ;AN000;
81PUBLIC FOPEN_Lookup ;AN000;
82PUBLIC FOPEN_PURGE ;AN000;
83
84PUBLIC FSEEK_Open ;AN000;
85PUBLIC FSEEK_Close ;AN000;
86PUBLIC FSEEK_Insert ;AN000;
87PUBLIC FSEEK_Delete ;AN000;
88PUBLIC FSEEK_Lookup ;AN000;
89PUBLIC FSEEK_Truncate ;AN000;
90PUBLIC FSEEK_Purge ;AN000;
91
92PUBLIC VECTOR_LookUp ;AN000;
93PUBLIC VECTOR_Delete ;AN000;
94
95
96; Following data variables are accessed by all other segments
97call_cnt DW 0 ;AN000;
98Purge_Flag DW 0 ; =1 if last call is PURGE function
99Prev_drv_id DB -1 ; previous request drive id
100Main_name_cache_seg DW Cseg_Init ; default to Init1 seg ;AN000;
101Main_Num_Of_drives DW 0 ; number of drives ;AN000;
102Main_Ext_Count DW 0 ; total name extent entries ;AN000;
103Main_extent_drive_Buff DW 0 ; addrs to extent drive ;AN000;
104Main_name_cache_Buff DW 0 ; address of Name cache buffer ;AN000;
105Main_ext_cache_size DW 0 ; extent cache size
106Main_EMS_FLAG DW 0 ; EMI flag 1= if EMI is enabled ;AN000;
107Main_Res_Segs DW 0 ; number of segs to be stay resident ;AN000;
108Main_Total_Ext_Count DW 0 ; Total extent count entries ;AN000;
109Main_Total_Name_Count DW 0 ; Total name count entries ;AN000;
110Main_Name_Drive_Buff DW 0 ; EMS data page segment ID ;AN000;
111Main_ParamBuff DW 50 dup (0) ; Drive ID/extent count buffer ;AN000;
112
113; The following structure is for saving and restoring EMS page state
114EMS_PAGE_MAP LABEL WORD
115Main_EMS_SEG_COUNT DW 1 ; EMS segment count
116Main_EMS_PAGE_SEG DW 0 ; EMS page segment ID ;AN000;
117
118
119Main_EMS_PAGE_SIZE DW 0 ; EMS page size ;AN000;
120EMS_PAGE_ARRAY DW 30 dup (0) ; EMS state save array
121
122; The following data values are used by MAIN segment
123EMS_SAVE_LOG_PAGE1 DW ? ;HOLDS PREVIOUS PAGE1 ;AN000;
124EMS_SAVE_HANDLE1 DW ? ;HOLDS PREVIOUS handle1 ;AN000;
125
126IF BUFFERFLAG
127;----------------------------------------------------------HKN 8/26/88
128
129EMS_PAGE_NUMBER DW ? ; holds the ems
130 ; physical page no.
131
132ENDIF
133;
134;-----------------------------------------------------------------------------
135; Fastopen/Fastseek function jump vectors
136; Inititally the jump vectors have default offset and segment values.
137; If the modules are relocated, the offset and the segID in the jump vectors
138; may be changed to the new segID of the new location.
139;-----------------------------------------------------------------------------
140FOPEN_Insert DD Insert ;AN000;
141FOPEN_Update DD Update ;AN000;
142FOPEN_Delete DD delete ;AN000;
143FOPEN_Lookup DD lookup ;AN000;
144FOPEN_Purge DD FP_purge ;AN000;
145
146FSEEK_Open DD Fk_Open ;AN000;
147FSEEK_Close DD Fk_Close ;AN000;
148FSEEK_Insert DD Fk_Insert ;AN000;
149FSEEK_Delete DD Fk_Delete ;AN000;
150FSEEK_Lookup DD Fk_Lookup ;AN000;
151FSEEK_Truncate DD Fk_Truncate ;AN000;
152FSEEK_Purge DD Fk_Purge ;AN000;
153
154VECTOR_LookUp DD LookUp ; jump vector to LookUp used by Insert call
155VECTOR_Delete DD Fk_Delete ; jump vector to Delete used by Free_buffer routine
156
157
158
159
160
161;==============================================================================
162
163MAIN PROC FAR ; FAR procedure for FAR call from DOS
164 push cx ; save DOS registers ;AN000;
165 push dx ; makesure to restore the necessary ;AN000;
166 push ds ; ones on return ;AN000;
167 push es ;AN000;
168 push bp ;AN000;
169 push di ;AN000;
170 push bx ;AN000;
171
172;-----------------------------------------------------------------------------
173; The cache buffers are maintained in a seperate segement whose segment ID is
174; in Name_Cache_Seg. The ES will be used as the seg register during the access
175; of data in the cache buffers, while DS will be used to access the Fastopen
176; resident and non-resident data area.
177;-----------------------------------------------------------------------------
178 cmp cs:Main_EMS_flag,1 ; EMS enabled ?? ;AN000;
179 jne dispatch_funcs ; no - dispatch functions ;AN000;
180 ; yes - save EMS page state
181IF NOT BUFFERFLAG
182
183;-----------------------------------------------------------------------------
184; SAVE EMS PAGE STATE
185;-----------------------------------------------------------------------------
186 PUSH AX ; save registers
187 PUSH CX
188 PUSH DX ;AN000;
189 PUSH DS ;AN000;
190 PUSH ES ;AN000;
191 PUSH BP ;AN000;
192 PUSH SI ;AN000;
193 PUSH DI ;AN000;
194 PUSH BX ;AN000;
195 MOV AX, SEG EMS_PAGE_MAP ; get segid
196 MOV DS,AX
197 LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc
198 MOV AX, SEG EMS_PAGE_ARRAY ; get segid
199 MOV ES,AX
200 LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY
201 MOV AH,EMS_SAVE_STATE ;
202 MOV AL,0 ; subfunction code
203 INT EMS_INT ; save page state ;AN000;
204
205 POP BX ;AN000;
206 POP DI ;AN000;
207 POP SI ;AN000;
208 POP BP ;AN000;
209 POP ES ;AN000;
210 POP DS ;AN000;
211 POP DX ;AN000;
212 POP CX ;AN000;
213
214 CMP AH,0 ; save ok??
215 JNE SAVE_FAILED ; no, error
216 POP AX ; clear stack
217
218ELSE
219
220
221;------------------------------------------------------------HKN 8/26/88--
222; Before dispatching off the fastopen functions we must do the
223; following:
224; 1. save the map for this page
225; 2. map this page to log. page 0 with the fastopen handle in
226; ems_save_handle1.
227; 3. dispatch
228;
229
230; int 3
231
232 push ax
233 push cx
234 push dx
235 push ds
236 push es
237 push bp
238 push si
239 push di
240 push bx
241
242 call far ptr save_ems_page_state
243 jc ems_failed
244
245 call map_page
246 jc ems_failed
247
248 pop bx
249 pop di
250 pop si
251 pop bp
252 pop es
253 pop ds
254 pop dx
255 pop cx
256 POP AX ; restore registers
257
258 JMP DISPATCH_FUNCS ; yes, dispatch functions
259
260EMS_FAILED:
261 pop bx
262 pop di
263 pop si
264 pop bp
265 pop es
266 pop ds
267 pop dx
268 pop cx
269
270ENDIF
271
272IF NOT BUFFERFLAG
273SAVE_FAILED:
274ENDIF
275
276 POP AX ; restore registers
277
278 POP BX ; no, restore DOS registers ;AN000;
279 POP DI ;AN000;
280 POP BP ;AN000;
281 POP ES ;AN000;
282 POP DS ;AN000;
283 POP DX ;AN000;
284 POP CX ;AN000;
285 STC
286 JMP ERROR_RET ; error return
287
288
289;-----------------------------------------------------------------------------
290; FASTOPEN/FASTSEEK DISPATCHER
291;-----------------------------------------------------------------------------
292DISPATCH_FUNCS:
293 cmp al,5 ; buffer purge ??
294 je Check_Drive_id ; yes - check drive id
295 cmp al,11 ; Fastopen function call ?? ;AN000;
296 jge Check_drive_id ; no - dispatch Fastseek functions
297 jmp Dispatch_fopen ; yes - dispatch Fastopen functions ;AN000;
298
299
300;-----------------------------------------------------------------------------
301; Check to see the Drive ID in DL is the valid. If not error and return DI=1
302; if Fastseek LookUp function. Makesure to preserve AL, DS, SI and DI
303;-----------------------------------------------------------------------------
304CHECK_DRIVE_ID:
305 cmp cs:Prev_drv_id, dl ; current id same as previous valid
306 je Dispatch_Fseek ; yes - dont check drive ID
307
308 push si ;AN000;
309 push bx ;DS=addressability to Cseg_Main ;AN000;
310 push cx ;AN000;
311 lea si,cs:Main_ParamBuff ; DS:SI-->drive ID buffer ;AN000;
312 mov cx,cs:Main_Num_Of_Drives ; number of drives ;AN000;
313
314Get_Drive_Id: ;AN000;
315 mov bx,cs:[si] ;AN000;
316 cmp bl,dl ; drive ID match ?? ;AN000;
317 je drive_found ; yes, drive ID found ;AN000;
318 add si,4 ; (2/11) no, move pointer to next ID ;AN000;
319 LOOP get_drive_id ; check next drive id ;AN000;
320
321Drive_Not_Found: ; drive id not found
322 pop cx ; restore registers ;AN000;
323 pop bx ;AN000;
324 pop si ;AN000;
325 jmp Error_Exit ; return
326
327Drive_Found: ; drive ID found
328 mov cs:Prev_drv_id,dl ; save drive id as prev drive id
329 pop cx ; restore registers ;AN000;
330 pop bx ; and do the specified function ;AN000;
331 pop si ;AN000;
332
333;-----------------------------------------------------------------------------
334; FASTSEEK FUNCTION DISPATCHER
335;-----------------------------------------------------------------------------
336DISPATCH_FSEEK:
337 cmp al,010H
338 jle Fsk_Cont
339 inc cs:call_cnt ;AN000;
340; cmp cs:call_cnt,0efffH ; for debugging
341; jne fsk_cont ; for debugging
342
343
344Fsk_Cont:
345 push cs ; set addressability
346 pop ds ; CS = DS = Cseg_Main segment
347 ASSUME ds:Cseg_Main
348 cmp al,FONC_Purge ; PURGE call ?? ;AN000;
349 je chk_05 ; yes - continue ;AN000;
350
351 mov cs:Purge_Flag, 0 ; reset purge flag
352 cmp al,FSK_Open ; OPEN call ;AN000;
353 jne chk_12 ; jump if not ;AN000;
354 CALL FSEEK_OPEN ;AN000;
355 jmp exit ;AN000;
356Chk_12:
357 cmp al,FSK_Close ; CLOSE ?? ;AN000;
358 jne chk_14 ;AN000;
359 CALL FSEEK_CLOSE ; process close function ;AN000;
360 jmp exit ;AN000;
361Chk_14:
362 cmp al,FSK_Lookup ; LOOKUP ?? ;AN000;
363 jne chk_15 ;AN000;
364 CALL FSEEK_LOOKUP ; process lookup ;AN000;
365 CALL RESTORE_PAGE_STATE ; restore EMS page ;AN000;
366 pop dx ; dont restore original BX and DI ;AN000;
367 pop dx ; from DOS since BX and DI contins return values ;AN000;
368 jmp exit_1 ; exit
369
370Chk_15:
371 cmp al,FSK_Insert ; INSERT ?? ;AN000;
372 jne chk_13 ;AN000;
373 CALL FSEEK_INSERT ; Process insert ;AN000;
374 jmp exit ;AN000;
375Chk_13:
376 cmp al,FSK_DELETE ; DELETE ?? ;AN000;
377 jne chk_16 ;AN000;
378 CALL FSEEK_DELETE ; process delete ;AN000;
379 jmp short exit ;AN000;
380Chk_16:
381 cmp al,FSK_Trunc ; TRUNCATE ?? ;AN000;
382 jne Chk_05 ;
383 CALL FSEEK_TRUNCATE ; process truncate ;AN000;
384 jmp short exit ;AN000;
385
386Chk_05:
387 cmp cs:Purge_Flag, 1 ; previous call is purge ?? ;AN000;
388 jne Purge_buffs ; no - purge the buffers
389 clc ; yes - exit
390 jmp short exit ;AN000;
391
392Purge_Buffs:
393 mov cs:Purge_Flag,1 ; set purge flag
394 cmp CS:Main_Total_Ext_Count,0 ; reset fseek buffs??
395 je reset_fopen ; no - reset fopen
396 CALL FSEEK_PURGE ; reset extent cache ;AN000;
397
398Reset_Fopen:
399 cmp CS:Main_Total_Name_Count,0 ; reset fopen buffs??
400 je Reset_Exit ; no - reset f
401 CALL CS:FOPEN_PURGE ; reset extent cache ;AN000;
402
403Reset_Exit:
404 clc
405 jmp short exit ;AN000;
406
407
408; NOTE: Carry Flag state from Function calls must be correctly returned
409; to the DOS, especially from Fastseek Lookup function
410
411
412;-----------------------------------------------------------------------------
413; FASTOPEN FUNCTION DISPATCHER
414;-----------------------------------------------------------------------------
415DISPATCH_FOPEN: ; dispatch FOPEN functions
416 cld ;AN000;
417 mov cs:Purge_Flag, 0 ; reset purge flag
418 cmp al, FONC_update ;AN000;
419 jne Chk_02 ;AN000;
420 CALL CS:Fopen_Update ; UPDATE ;AN000;
421 jmp short exit ;AN000;
422
423Chk_02:
424 cmp al, FONC_insert ;AN000;
425 jne Chk_01 ;AN000;
426 CALL CS:Fopen_Insert ; INSERT ;AN000;
427 jmp short exit ;AN000;
428Chk_01:
429 cmp al, FONC_look_up ;AN000;
430 jne chk_03 ;AN000;
431 CALL CS:Fopen_lookup ; LOOKUP ;AN000;
432 jmp short exit ;AN000;
433Chk_03:
434 cmp al, FONC_delete ;AN000;
435 jne Error_Exit ;AN000;
436 CALL CS:Fopen_delete ; DELETE ;AN000;
437 jmp short exit ;AN000;
438
439
440
441;-----------------------------------------------------------------------------
442; EXIT TO DOS FROM FUNCTIONS
443;-----------------------------------------------------------------------------
444
445ERROR_EXIT: ; EXIT from invalid drive id search loop
446 CALL RESTORE_PAGE_STATE ; restore frame buff status ;AN000;
447 ; on return AX should have function code
448 pop bx ; restore first two regs of DOS
449 pop di ;AN000;
450 cmp al,FSK_Lookup ;AN000;
451 jne exit_2 ;AN000;
452 mov di,1 ; set error flag - invalid drive id ;AN000;
453 stc ;AN000;
454 jmp short Exit_1 ;AN000;
455
456EXIT_2:
457 clc ;AN000;
458 jmp short Exit_1 ;AN000;
459
460
461; Normal Exit from Fastopen Functions except Fastseek Lookup function
462EXIT:
463 CALL RESTORE_PAGE_STATE ; restore EMS page state ;AN000;;AN000;
464 pop bx ; restore BX ;AN000;
465 pop di ; restore DI ;AN000;
466
467
468; Exit from FastSeek Lookup function. Dont restore BX and DI
469EXIT_1:
470 pop bp ; restore remaining DOS registers
471 pop es ; except BX and DI since they contain ;AN000;
472 pop ds ; return values. ;AN000;
473 pop dx ;AN000;
474 pop cx ;AN000;
475
476ERROR_RET:
477 ret ;AN000;
478
479MAIN ENDP
480
481IF BUFFERFLAG
482;---------------------------------------------------------------------------
483; Procedure name : save_ems_page_state
484;
485; Description:
486; Saves the state of the page whose physical segment value is
487; specified in Main_EMS_PAGE_SEG.
488;---------------------------------------------------------------------------
489
490SAVE_EMS_PAGE_STATE PROC FAR
491
492 PUSH AX ; save registers
493 PUSH CX
494 PUSH DX ;AN000;
495 PUSH DS ;AN000;
496 PUSH ES ;AN000;
497 PUSH BP ;AN000;
498 PUSH SI ;AN000;
499 PUSH DI ;AN000;
500 PUSH BX ;AN000;
501
502 MOV AX, SEG EMS_PAGE_MAP ; get segid
503 MOV DS,AX
504 LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc
505 MOV AX, SEG EMS_PAGE_ARRAY ; get segid
506 MOV ES,AX
507 LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY
508 MOV AH,EMS_SAVE_STATE ;
509 MOV AL,0 ; subfunction code
510 INT EMS_INT ; save page state ;AN000;
511
512 POP BX ;AN000;
513 POP DI ;AN000;
514 POP SI ;AN000;
515 POP BP ;AN000;
516 POP ES ;AN000;
517 POP DS ;AN000;
518 POP DX ;AN000;
519 POP CX ;AN000;
520
521 CMP AH,0 ; save ok??
522 JE SAVE_OK ;
523 STC
524 JMP SHORT DONE
525SAVE_OK:
526 CLC
527DONE:
528 POP AX
529 RET
530
531SAVE_EMS_PAGE_STATE ENDP
532
533ENDIF
534
535
536;-----------------------------------------------------------------------------
537; PROCERDURE: RESTORE_PAGE_STATE
538;
539; Function: Restore state of EMS page
540;
541; Input: None
542; Output: Page is restored
543;
544;-----------------------------------------------------------------------------
545
546RESTORE_PAGE_STATE PROC NEAR ;RESTORE EMS PAGE STATE
547 PUSHF ;save flag ;AN000;
548 CMP CS:MAIN_EMS_FLAG, 0 ;EMS enabled ?? ;AN000;
549 JNE REST_PUSH_REGS ;yes, restore registers
550 JMP SHORT RESTORE_EXIT ;no, exit ;AN000;
551 ;yes, restore page registers
552REST_PUSH_REGS:
553 PUSH AX ; save function code
554 PUSH CX ; save caller registers ;AN000;
555 PUSH DX ;AN000;
556 PUSH DS ;AN000;
557 PUSH ES ;AN000;
558 PUSH BP ;AN000;
559 PUSH SI ;AN000;
560 PUSH DI ;AN000;
561 PUSH BX ;AN000;
562
563 MOV AX, SEG EMS_PAGE_ARRAY
564 MOV DS,AX
565 LEA SI,EMS_PAGE_ARRAY ; DS:SI-->Page array
566 MOV AH,EMS_RESTORE_STATE ;
567 MOV AL,1 ;
568 INT EMS_INT ; restre page state ;AN000;
569 CMP AH,0 ; restore OK ??
570 JE REST_POP_REGS ; yes
571 STC ; set carry
572
573REST_POP_REGS:
574 POP BX ; RESTORE REGISTERS ;AN000;
575 POP DI ;AN000;
576 POP SI ;AN000;
577 POP BP ;AN000;
578 POP ES ;AN000;
579 POP DS ;AN000;
580 POP DX ;AN000;
581 POP CX ;AN000;
582 POP AX ; restore function code
583
584RESTORE_EXIT:
585 POPF
586 RET ;AN000;
587
588RESTORE_PAGE_STATE ENDP
589
590
591IF BUFFERFLAG
592
593;---------------------------------------------------------HKN 8/26/88-------
594; procedure name : map_page
595; Inputs : ems_page_number = physical page frame
596; number.
597; ems_save_handle1 = emm_handle.
598; Output : CY - error
599; NC - page is mapped to logical page 0
600;----------------------------------------------------------------------------
601map_page proc near
602
603 push ax
604 push bx
605 push dx
606
607 xor bx, bx
608 mov ax, cs:ems_page_number ; contains the page number obtained
609 ; during fastopen intialization.
610 mov ah, 44h
611 mov dx, cs:ems_save_handle1 ; contains the emm handle that was
612 ; obtained during fast init.
613 int ems_int
614 or ah, ah
615 jnz err_map_page
616 clc
617 jmp short map_page_done
618
619err_map_page:
620 stc
621
622map_page_done:
623 pop dx
624 pop bx
625 pop ax
626 ret
627
628map_page endp
629
630ENDIF
631
632
633 ; NOTE:
634CSEG_MAIN ENDS ; End of the first portion of the
635 ; Cseg_Main segment. Remaining
636 ; portion is in Fastinit.asm
637
638;-----------------------------------------------------------------------------
639
640
641
642
643
644;==============================================================================
645; All Fastopen functions are kept in a seperate segment. These are accessed
646; by a FAR indirect call from the MAIN routine.
647; ADDRESSABILTY: CS is used for accessing local data in Cseg_Open segment
648; DS is used for accessing data in the drive cache buffer
649; in the Cseg_Init segment
650; ES is used for accessing data in the name cache buffer
651; in the Cseg_Init segment
652;
653;*****************************************************************************
654CSEG_OPEN SEGMENT PARA PUBLIC 'code'
655 ASSUME cs:cseg_open,ds:nothing,es:nothing,ss:nothing
656;*****************************************************************************
657
658PUBLIC Open_name_cache_seg ;AN000;
659PUBLIC Open_name_Drive_Buff ;AN000;
660PUBLIC End_Open ;AN000;
661PUBLIC Chk_Flag ;AN000;
662
663;---- FastOpen Functions Local Variables --------------
664
665Current_Node DW ? ;address of current node entry buffer ;AN000;
666Current_Sibling DW ? ;address of current sibling node entry buffer ;AN000;
667Current_Drive DW ? ;address of current drive header ;AN000;
668Matching_Node DW -1 ;flag ;AN000;
669From_Delete DW 0 ;= 1 if call is from DELETE function ;AN000;
670Old_SI DW 0 ;SI save area ;AN000;
671Flag DB 0 ;AN000;
672Level DB 0 ;depth level of the path ;AN000;
673Dir_Info_Buffer DD ? ;Dir_Info buffer inside DOS ;AN000;
674Extended_Info_Buffer DD ? ;Extended Info buffer inside DOS ;AN000;
675New_FEI_clusnum DW 0 ;AN000;
676Packed_Name DB 11 dup (0) ;Space for packed dir name ;AN000;
677Top DW 0 ;AN000;
678Temp DW 0 ;AN000;
679Bottom DW 0 ;AN000;
680Depth DB 0 ;AN000;
681
682Chk_Flag dw 0 ; flag used by the analyser
683func_cod db 0 ; function code for analyser
684
685;Following data area is filled during initialization
686Open_name_cache_seg DW Cseg_Init ; address of name cache buffer
687Open_name_Drive_Buff DW 0 ; address of first drive buffer
688
689
690
691
692;
693;==============================================================================
694; Pathname Tree Search
695;
696; Element of each path name is represented by a node in the tree. First
697; node is connected to the the Drive header through first child pointer
698; (DCH_Child_Ptr). The first node may have one or more nodes underneath.
699; The first one is called the Child of this node and the others are the siblings
700; of the child node. Previous node is connected to the first node through
701; the child pointer (nChild_Ptr) and the siblings are connected through the
702; sibling pointer (nSibling_Ptr). Each node is connected to the previous
703; node through a backward pointer (nBackward_Ptr). For example, to go to the
704; previous node from any of the siblings. It is necessary to go to the
705; child through previous siblings (if any) and then to the previous from the
706; child. All this backward movement is using nBackward_Ptr.
707; Similarly to go to a child or sibling, nChild_ptr or nSibling_Ptr should be
708; used. The strucure of drive header and the node are defined in Fastopen.inc
709;
710
711;==============================================================================
712;Subroutine: LOOKUP
713;
714;INPUT:
715; DS:SI -> path (drive letter D: will be validated by Find_Drive_Cache_hdr)
716; ES:DI -> DIR_INFO buffer to be returned inside DOS
717; ES:CX -> FASTOPEN_Extended_Info buffer inside DOS
718; ES:BP -> Drive_Cache_Heade
719;
720;
721;OUTPUT:
722; If the whole path is found,
723; DS:SI--> 0
724; ES:DI--> DIR_INFO buffer is filled with directory info
725; ES:CX--> EXT_INFO buffer is filled with extended info
726;
727; If partially found the path,
728; DS:SI--> '\' after the matching directory name
729; ES:DI--> DIR_INFO buffer is filled with directory info
730; ES:CX--> EXT_INFO buffer is filled with extended info
731;
732; If the Name_cache tree is empty, i.e.,no root directory name,
733; DS:SI--> '\' after ':'
734; ES:DI--> DIR_INFO buffer is undetermined
735; ES:CX--> EXT_INFO buffer is undetermined
736;
737;==============================================================================
738
739LOOKUP PROC FAR
740
741 mov cs:func_cod,al ; save function code
742 cmp From_Delete, 0 ;call from DELETE function ??
743 je Look_Pack_Dir ;no, dont restore DS
744 mov DS,bx ;yes, restore DS
745 ASSUME DS:Cseg_Init
746 jmp short Look_save_regs ;save registers
747
748Look_Pack_Dir:
749 CALL PACK_DIR_NAME ;on return drive letter => DL,
750
751 CALL FIND_DRIVE_CACHE_HEADER ;find drive header address
752 ;on return ES:BP-->drive header
753 jnc look_save_regs ;drive buffer found
754 jmp lookup_error ;drive buffer not found
755
756Look_Save_Regs:
757 push es
758 push di
759 push cx
760 mov ax, cs:Open_Name_Cache_Seg ;AN000;
761 mov es, ax ;ES = Name_Cache_Seg ;AN000;
762 ASSUME es:Cseg_Init ;AN000;
763 CALL SET_LRU ;set the Real LRU, if any.
764
765 or cs:Flag,Is_drive_head ;level of the tree. Drive header
766 mov cs:Matching_Node, -1 ;Nothing found yet.
767 mov cs:Current_Drive, BP ;drive header
768 mov cs:Level, 0 ;path level is 0
769
770Lookup_Path:
771 mov cs:Current_Node, BP ;save current node address
772 mov cs:Current_Sibling,0fffeh ;set no sibligs yet.
773 mov cs:Old_SI, si ;save current path address
774
775 CALL PACK_DIR_NAME ;get the next dir name from the path
776 jc Lookup_Done ;yes, found the whole path.
777
778 test cs:Flag, Is_drive_head ;dir name = drive header ?
779 jz Lp_Path1 ;no-
780
781 push ds ;yes-drive header
782 mov ds,cs:Open_Name_Cache_Seg
783 ASSUME ds:Cseg_Init
784 mov BP, DS:[BP.DCH_Child_ptr] ;BP-->first child node under drive hdr
785 pop ds
786 ASSUME ds:nothing
787 jmp short Lp_Path2
788
789Lp_Path1:
790 mov BP, ES:[BP.nChild_ptr] ;BP--> child of current node
791
792Lp_Path2:
793 cmp BP, -1 ;no child?
794 je Lookup_Done ;Not found or partially found
795 mov cs:Current_Node, BP ;current_node = found node
796 and cs:Flag, Not_drive_head ;reset the flag.
797
798Lp_Cmpare:
799 CALL CMPARE ;look for path in current node
800 je Lookup_Found ;Yes, found a match. Next level for
801 ;possible remianing path
802
803 mov BP, ES:[BP.nSibling_ptr] ;not found. Any siblings?
804 mov cs:Current_Sibling,BP
805 cmp BP, -1 ;any more sibling?
806 je Lookup_Done ;no - done
807
808 mov cs:Current_Node, BP ;yes- make the found sibling as a current
809 jmp short Lp_Cmpare ;node and search path in this node
810
811Lookup_Found:
812 inc cs:Level
813 mov cs:Matching_Node,BP ;Used by Unfold_Name_Record
814
815 CALL PRE_LRU_STACK ;set the TEMP_LRU_Stack
816 jmp Lookup_Path ;continue to the next dir
817
818Lookup_Done:
819 mov si, cs:Old_SI
820 pop cx ;restore Extended_Info buffer
821 pop di ;restore Dir_Info buffer
822 pop es ;the segment for the above buffers
823
824 cmp ax, -1
825 je Lookup_ERR ;error occured in Pack_Dir_Name.
826 clc ;clear carry.
827 jmp short Lookup_Done1
828
829Lookup_ERR: ;error exit
830 stc
831
832Lookup_Done1:
833 test cs:Flag, is_delete ;called by delete?
834 jnz Lookup_Return
835 jc Lookup_Exit ;If it was an error, don't change the carry flag
836
837 CALL UNFOLD_NAME_RECORD ;unfold the current node's record
838Lookup_Exit:
839 jmp short Lookup_Return ;return to DOS.
840
841Lookup_Error: ;error exit
842 stc
843 mov ax,-1
844
845Lookup_Return: ;return to Delete routine.
846 CALL Check_It ;check tree structure
847 ret
848
849LOOKUP ENDP
850
851
852
853
854
855;==============================================================================
856;SUBROUTINE: INSERT
857;
858;INPUT: DS:DI -> Dir_Info in DOS
859; ES:BX -> Fastopen_Extended_Info in DOS
860; Current_Node, Current_Sibling, Current_Drive, Flag
861;
862;OUTPUT: Information inserted into Name_cache_tree.
863;
864; Any Sequential Insert operation should be preceded by a Look_up
865; operation. For ex., if the DOS wants to insert C:\DIR1\DIR2\File1
866; and suppose there is no matching name cache record for DIR1 in the tree.
867; Firstly DOS will try to look up C:\DIR1\DIR2\File1. FASTOPEN will
868; return to DOS with DS:SI points to "\" after the drive letter.
869; Then, DOS will simply ask an insert operation with DS:DI, ES:BX
870; points to the information on "DIR1". FASTOPEN will insert DIR1
871; onto the tree. After that DOS will ask another insert
872; operation for DIR2. FASTOPEN will insert DIR2. Finally DOS will
873; ask to insert File1.
874;
875; Suppose when DOS try to look up C:\DIR1\DIR2\File2 at this moment.
876; FASTOPEN will return to DOS with DS:SI points to "\" after DIR2 (since
877; DIR2 information is already in the name cache tree). Then DOS will ask
878; to insert File2.
879;
880; Any Insert operation of subdirectory name which is deeper than (Number_
881; of_Entries - 1) will not be inserted but will just return.
882; Also, for the safety reason, if the would be freed node (=LRU node) is
883; the same as the Current_Node, there will be no insertion. (This is a simple
884; safety valve. A more smart logic can look for the next **legitimately
885; available** LRU node to use, or sometimes, simply replace the contents of the
886; entry if adequate. But this will increase the complexity greatly, and I
887; think the current logic is still practical enough to use despite of the
888; possible small window of performance degradation in a very special cases. J.K.)
889;
890;==============================================================================
891
892INSERT PROC FAR
893 mov cs:func_cod,al ; save function code
894 inc cs:Level ;increment directory level
895 xor ax,ax
896 mov al, cs:Level
897 inc al
898 mov bp, cs:Current_Drive ;BP-->address of current drive header
899 push ds
900 mov ds,cs:Open_Name_Cache_Seg ;DS=name cache segment
901
902 ASSUME ds:Cseg_Init ;AN000;
903 cmp ax, ds:[bp.DCH_Num_Entries] ;Level > (Num_Entries - 1) ?
904 pop ds
905 ASSUME ds:nothing
906 jbe Insert_it ;no- insert it
907 jmp short Insert_return ;yes return
908
909Insert_it:
910 or cs:Flag, is_insert
911
912 CALL GET_FREE_NODE ;AX = offset value of the available
913 ;name_record in Name_Cache_Seg.
914 jc I_Exit ;Current node = would-be freed node.
915
916 CALL MAKE_NAME_RECORD ;Fill the above name record entry.
917 ;ES was changed to Name_Cache_Seg.
918
919 mov bp, cs:Current_Node ;set BP to current_node
920 mov bx, bp ;save it into bx
921 cmp cs:Current_Sibling,0fffeh ;current node sibling node ??
922 je I_Child ;no-child of preceding node
923 mov es:[bp.nSibling_ptr], ax ;yes-make new node sibling of
924 jmp short I_Done ;current node
925
926I_Child: ;set nChild_ptr
927 test cs:Flag,Is_drive_head ;drive level?
928 jnz I_Child_first ;Yes, must be the first child
929 mov es:[bp.nChild_ptr], ax ;no-make ndew node child of
930 jmp short I_Done ;current node
931
932I_Child_first: ;this is the first child in this drive.
933 push ds
934 mov ds,cs:Open_Name_Cache_Seg ;AN000;
935 ASSUME ds:Cseg_Init ;AN000;
936 mov ds:[bp.DCH_Child_ptr],ax ;make new node 1st child current drive
937 pop ds
938 ASSUME ds:nothing
939 mov bx, cs:Current_Drive ;change bx to Current_Drive
940 and cs:Flag, Not_drive_head ;reset the flag
941
942I_Done:
943 mov bp, ax
944 mov es:[bp.nBackward_ptr],bx ;set the backward ptr of the inserted node.
945
946 CALL PRE_LRU_STACK ;save this inserted record temporarily.
947
948 mov cs:Current_Node,bp ;make new node current node
949 ;any subsequent insert operation
950 mov cs:Current_Sibling,0fffeh ;should be installed as a child
951
952I_Exit:
953 and cs:Flag, not_insert ;set not insert flag
954
955Insert_return:
956 CALL Check_It ;check tree structure
957 ret ;return
958
959INSERT ENDP
960
961
962
963
964
965
966;==============================================================================
967;Subroutine: DELETE
968;
969;INPUT: DS:SI -> path
970; ES:BP -> drive_cache_header (for Look_Up operation)
971;
972;OUTPUT: if found, then remove the matching Name_Record will be removed from
973; the tree and from the LRU chain. The freed entry will be placed
974; on top of the LRU chain.
975;
976;==============================================================================
977
978DELETE PROC FAR
979
980 mov cs:func_cod,al ; save function code
981 CALL PACK_DIR_NAME ;drive letter => DL, ;AN000;
982
983 CALL FIND_DRIVE_CACHE_HEADER ;find drive header address
984 ;on return ES:BP-->drive header
985 jc d_err_exit ;error exit
986
987 or cs:Flag, is_delete ;set the flag for Look_up.
988 push ds ;save DS in BX since it is going to be
989 pop bx ;changed for jumping to other segment
990 push ds
991 mov ax,cseg_Main
992 mov ds,ax ;DS=Main segment ID
993 assume ds:Cseg_Main
994 mov cs:From_Delete, 1 ;set flag indicate that the call
995 ;is from DELETE function
996 CALL VECTOR_LOOKUP ;FAR call to Lookup function
997
998 mov cs:From_Delete, 0 ;reset from delete flag
999 pop ds
1000 ASSUME ds:nothing
1001 jc D_err_Exit ;indirectly in the same segment
1002
1003 cmp byte ptr ds:[si], 0 ;found the whole path?
1004 jne D_err_Exit ;No.
1005
1006;At this point, Current_Node = BP.
1007 mov bx, cs:Open_Name_Cache_Seg
1008 mov es, bx ;set ES to name_cache_seg.
1009 ASSUME es:Cseg_Init
1010
1011Delete_Node:
1012 cmp es:[bp.nChild_ptr], -1 ;No children?
1013 jne D_err_Exit
1014 CALL REMOVEFROMTREE ;remove the node while maintaing the
1015 ;integrity of the tree.
1016
1017 mov es:[bp.nCmpct_Dir_Info], ' ' ;mark that this entry is free!!!
1018
1019D_LRU_MRU:
1020 CALL REMOVEFROMLRUCHAIN ;Remove BP from the LRU,MRU chain
1021
1022 mov si, cs:Current_Drive ;Now let the deleted node to be the
1023 push ds ; LRU node
1024 mov ds,cs:Open_Name_Cache_Seg
1025 ASSUME ds:Cseg_Init ;AN000;
1026
1027 mov bx, ds:[si.DCH_LRU_ROOT] ;es:bx -> first node
1028 mov es:[bp.nLRU_ptr],bx ;Target.nLRU_ptr -> first node
1029 mov es:[bx.nMRU_ptr],bp ;First_node.nMRU_ptr -> target
1030 mov ds:[si.DCH_LRU_ROOT],bp ;LRU_ROOT -> target
1031 mov es:[bp.nMRU_ptr],-1
1032 pop ds
1033 ASSUME ds:nothing
1034 jmp short D_Exit ;exit
1035
1036D_err_Exit: ;error exit
1037 stc
1038 mov ax, -1
1039
1040D_Exit:
1041 and cs:Flag, not_delete ;reset the flag
1042 CALL Check_It ;check tree structure
1043 ret ;return
1044
1045DELETE ENDP
1046
1047
1048
1049
1050
1051;==============================================================================
1052;Subroutine: UPDATE
1053;
1054;INPUT: If AH = 0, then update Dir_Entry area.
1055; ES:DI -> Dir_entry ("dir_first" is the key to search).
1056; DL = Logical Drive number (0 = A, 1 = B, ...).
1057;
1058; If AH = 1, then update "Fastopen_extended_info.FEI_clusnum".
1059; DL = Logical Drive number (0 = A, 1 = B, ...)
1060; CX = The value of "dir_first" to search.
1061; BP = new value of FEI_clusnum in the extended_info area.
1062;
1063; If AH = 2, then delete the entry. Same effect as Delete function
1064; except this time the keys used to delete are;
1065; DL = logical drive number
1066; CX = the value of "dir_first" to search.
1067;
1068; If AH = 3, then delete the entry. Same effect as Delete function
1069; except this time the keys used to delete are;
1070; DL = logical drive number
1071; DH = directory position
1072; DI = directory sector (low value)
1073; CX = directory sector (high value)
1074;
1075;
1076;OUT: if found, then data is updated
1077; else CY and AX = -1.
1078;
1079; This routine use "starting cluster number" and "drive letter"
1080; as a key to find the name record. Usually the reason is DOS
1081; does not have any "full path" information about the file when
1082; it has to call this routine to update the information.
1083; It follows the MRU chain until it finds the name record or
1084; until it reaches the free name record (identified by the
1085; Directory name starting with ' '), or until the end of
1086; the MRU chain.
1087;
1088;==============================================================================
1089
1090UPDATE PROC FAR
1091
1092 mov cs:func_cod,al ; save function code
1093 cmp ah, 0 ;update directory entry ?
1094 je Update_Dir_Entry ;yes-
1095 cmp ah, 1 ;update extended info ?
1096 je Update_Extended_clusnum ;yes-
1097 cmp ah, 2 ;delete based on first clus num ?
1098 je Update_Delete ;yes-
1099 cmp ah, 3 ;delete based directory sector ?
1100 je Update_Delete1 ;yes-
1101
1102U_ERROR: ;no - error exit
1103 stc
1104 jmp short Update_Exit
1105
1106Update_Delete: ; same as delete
1107 CALL FIND_CLUSTER_NUMBER ; find name entry using first cluster
1108 jc U_ERROR
1109 jmp Delete_Node ; if found, delete entry
1110
1111Update_Delete1: ; same as delete (PTR P3718 3/10/88)
1112 CALL FIND_DIR_SECTOR ; find name entry using directory
1113 jc U_ERROR ; sector and directory position
1114 jmp Delete_Node ; if found, delete node
1115
1116Update_Dir_Entry:
1117 mov cx, es:[di.dir_first]
1118 push es ;save Dir_Info pointer ES:DI
1119 push di
1120 CALL FIND_CLUSTER_NUMBER
1121 pop si ;restore Dir_Info pointer in DS:SI
1122 pop ds
1123 jc U_ERROR ;error-if not found
1124
1125 push bp ;found the entry
1126 pop di
1127 add di, nCmpct_Dir_Info ;ES:DI->Name_Record.nCmpct_Dir_Info
1128 mov cx, ODI_head_leng
1129 REP MOVSB ;update Cmpct_dir_info head section
1130 add si, ODI_skip_leng
1131 mov cx, ODI_tail_leng
1132 REP MOVSB ;update tail section
1133 jmp short Update_Exit ;exit
1134
1135Update_Extended_clusnum: ;update extended info field
1136 mov cs:New_FEI_clusnum,bp
1137 CALL FIND_CLUSTER_NUMBER ;Find entry based first cluster number
1138 jc U_ERROR
1139
1140 add bp, nExtended_Info ;es:bp -> Name_record.nExtended_Info
1141 mov bx, cs:New_FEI_clusnum
1142 mov es:[bp.FEI_clusnum],bx
1143
1144Update_Exit:
1145 CALL Check_It ;check tree structure
1146 ret ;return
1147
1148UPDATE ENDP
1149
1150
1151
1152
1153
1154
1155;==============================================================================
1156;Subroutine: FP_PURGE Rest Name Cache Buffers
1157;
1158;INPUT: Main_Name_Drive_Buff - Offset to Name cache buffer
1159; Main_Name_Cache_Seg - Name cache seg id
1160; DL = Drive ID
1161;
1162;OUT: Buffer is purged
1163;
1164;==============================================================================
1165
1166FP_PURGE PROC FAR
1167
1168 mov si,Open_Name_Drive_Buff ; SI-->first Name drive cache buff
1169 mov es,Open_Name_Cache_Seg ; ES = name cache seg ID
1170 mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer
1171 inc dl ; DL=drive number
1172 add dl,040H ; convert drive num to drive letter
1173
1174; Search for the name drive header corresponds to the drive letter
1175Purge_Drv_Loop:
1176 cmp es:[si].DCH_Drive_Letter,dl ; drive letter match ??
1177 je Purge_drive_cache ; yes - set drive cache
1178 add si, size Drive_Cache_Header ; no - get address of next drive cache
1179 jmp purge_drv_loop ; try next name drive header
1180
1181Purge_Drive_Cache: ; SI-->drive header
1182 mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer
1183 mov cx,es:[si].DCH_num_entries ; get number of name records
1184 mov ax,bx ; save last name record address
1185 mov es:[bx].nMRU_ptr, -1 ; make first MRU -1
1186 jmp short set_start
1187
1188Set_Up_Names:
1189 mov es:[bx].nMRU_ptr,ax ;save last name record as MRU entry
1190 add ax, size Name_Record ;AX = last name record = current name record
1191
1192Set_Start:
1193 mov es:[bx].nChild_ptr, -1 ;no children or siblings
1194 mov es:[bx].nsibling_ptr, -1 ;right now
1195 mov es:[bx].nBackward_ptr, -1
1196
1197 push di
1198 push ax
1199 mov ax, ' ' ;AX = ' '
1200 mov di, bx ;DI-->current name record
1201 add di, nCmpct_Dir_Info ;blank out the Dir name area
1202 stosb ;in the name record
1203 stosw
1204 stosw
1205 stosw
1206 stosw
1207 stosw
1208 pop ax ; AX = last name record address
1209 pop di
1210
1211 dec cx ;update record count
1212 jcxz purge_exit ;exit if last name record is done
1213 mov dx,bx
1214 add dx, size Name_Record ;DX-->next name record
1215 mov es:[bx].nLRU_ptr,dx ;set LRU pointer - next name record
1216 add bx, size Name_Record
1217 jmp set_up_names ;set next name record
1218
1219Purge_exit:
1220 clc
1221 ret
1222
1223FP_PURGE ENDP
1224
1225
1226
1227;----------------------------------------------------------------------------
1228; FASTOPEN SUPPORT ROUTINES
1229;----------------------------------------------------------------------------
1230;
1231; PROCEDURE: Find_Drive_Cache_Header
1232;
1233; Function: Validate drive ID and find address of drive cache header
1234;
1235;IN: DL - drive letter
1236; Drive_Header_Start ;label
1237; Flag.
1238;
1239;OUT: If CY = 0 Drive Header found
1240; ES:BP -> Drive_Cache_Header,
1241;
1242; If CY = 1 Drive Header not found
1243;
1244;----------------------------------------------------------------------------
1245
1246FIND_DRIVE_CACHE_HEADER PROC NEAR
1247
1248 mov bp, cs:Open_name_drive_buff
1249 push ds
1250 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1251 ASSUME ds:Cseg_Init ;DS:BP-->first drive header ;AN000;
1252
1253FDCH_while:
1254 cmp byte ptr ds:[bp.DCH_Drive_Letter], dl ; drive letter match
1255 jne fdch_chk_end ; no - check next header
1256 clc ; yes - exit
1257 jmp short FDCH_Exit
1258
1259FDCH_Chk_End:
1260 cmp byte ptr ds:[bp.DCH_Sibling_ptr], -1 ; is this last header ?
1261 je FDCH_Not_Found ; yes - header not found
1262 add bp, size Drive_Cache_Header ; no - get next header
1263 jmp short FDCH_while ; look for match
1264
1265FDCH_Not_Found:
1266 stc ;not found
1267
1268FDCH_Exit: ;ES:BP-->header if found
1269 pop ds
1270 ASSUME ds:nothing ;return
1271 ret
1272
1273FIND_DRIVE_CACHE_HEADER endp
1274
1275
1276
1277
1278;----------------------------------------------------------------------
1279; PROCEDURE: GET_FREE_NODE
1280;
1281; called by Insert. The LRU node pointed DCH_LRU_ROOT is returned in AX
1282; and DCH_LRU_ROOT points to the following node in LRU chain.
1283; If the node is not an empty node, then it will be removed from the
1284; tree.
1285;
1286; IN: Current_Drive, Current_Node
1287;
1288; OUT: AX = offset of the free node in Name_Cache_Seg
1289; Other registers saved.
1290;----------------------------------------------------------------------
1291
1292GET_FREE_NODE PROC NEAR
1293
1294 push es ;save registers
1295 push di
1296 push si
1297 push bp
1298
1299 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1300 mov es, ax ;ES=Name cache segment ;AN000;
1301 ASSUME es:Cseg_Init ;AN000;
1302 mov si, cs:Current_Drive ;SI-->drive_cache_header
1303 push ds
1304 mov ds,cs:Open_Name_Cache_Seg
1305 ASSUME ds:Cseg_Init
1306 mov ax, ds:[si.DCH_LRU_ROOT] ;get the LRU node
1307 pop ds
1308 ASSUME ds:nothing
1309
1310 cmp ax, cs:current_Node ;LRU node=Current Node ??
1311 je GFN_skip ;yes-
1312
1313 mov bp, ax ;BP=Current node
1314 mov di, es:[bp.nLRU_ptr] ;DI= current LRU node's following node
1315 mov es:[di.nMRU_ptr],-1 ;set that node's MRU ptr
1316 push ds
1317 mov ds,cs:Open_Name_Cache_Seg ;DS=Name cache segment
1318 ASSUME ds:Cseg_Init
1319 mov ds:[si.DCH_LRU_ROOT],di ;connect previous node to
1320 pop ds ;next node
1321 ASSUME ds:nothing
1322
1323 cmp byte ptr es:[bp.nCmpct_Dir_Info],' ';an empty node?
1324 je GFN_OK ;then no problem.
1325
1326 CALL RemoveFromTree ;otherwise, it should be removed
1327 ;from the tree.
1328GFN_OK:
1329 clc
1330 jmp short GFN_ret
1331
1332GFN_Skip:
1333 stc
1334
1335GFN_ret:
1336 pop bp
1337 pop si
1338 pop di
1339 pop es
1340 ret ;return
1341
1342GET_FREE_NODE endp
1343
1344
1345
1346
1347;
1348;----------------------------------------------------------------------
1349; PROCEDURE: PRE_LRU_STACK
1350;
1351; When called by Look_up, Insert routine, the requested target node (BP)
1352; will be temporarily removed from LRU,MRU chain (until SET_LRU routine
1353; call), and will be pushed into a logical stack. Actually, this routine
1354; will not use a stack, but try to get the effect of the use of stack
1355; to keep the history of target nodes in "REVERSE" LRU order as follows;
1356; { inc Depth;
1357; if Depth == 1 then Bottom = BP;
1358; Bottom.LRU_ptr = -1;
1359; Bottom.MRU_ptr = -1;
1360; else if Depth == 2 then Top = BP;
1361; Top.LRU_ptr = Bottom;
1362; Bottom.MRU_ptr = Top;
1363; Top.MRU_ptr = -1;
1364; else if Depth >= 3 then Temp = Top;
1365; Top = BP;
1366; Top.LRU_ptr = Temp;
1367; Temp.MRU_ptr = Top;
1368; Top.MRU_ptr = -1;
1369; }
1370;
1371;IN: Depth, Top, Bottom, Temp,
1372; Requested target node (BP)
1373; ES = Name_Cache_Seg
1374;
1375;OUT: Target node removed from LRU,MRU chain.
1376; Target node's history saved in reverse LRU order.
1377; If called by "Delete" routine, then will just exit.
1378; If called by "Insert" routine, then will not attempt
1379; to remove the target node.
1380;----------------------------------------------------------------------
1381
1382PRE_LRU_STACK PROC NEAR
1383
1384 test cs:Flag, is_delete ;invoked by Delete routine
1385 jnz PLS_Exit
1386 test cs:Flag, is_insert ;called by Insert routine
1387 jnz PLS_Push
1388
1389 CALL RemoveFromLRUChain ;remove BP from the chain.
1390
1391PLS_Push:
1392 push di
1393
1394 inc cs:Depth
1395 cmp cs:Depth, 1
1396 jne PLS_Top
1397 mov cs:Bottom, bp ;bottom = bp
1398 mov es:[bp.nLRU_ptr], -1
1399 jmp short PLS_Done
1400
1401PLS_Top:
1402 cmp cs:Depth, 2
1403 jne PLS_Temp
1404 mov cs:Top, bp ;Top = bp
1405 mov di, cs:bottom ;di = bottom
1406
1407PLS_com:
1408 mov es:[bp.nLRU_ptr],di ;Top.LRU_ptr = bottom
1409 mov es:[di.nMRU_ptr],bp ;Bottom.MRU_ptr = top
1410 jmp short PLS_Done
1411
1412PLS_Temp:
1413 mov di, cs:Top ;di = Top
1414 mov cs:Temp, di ;Temp = di
1415 mov cs:Top, bp ;Top = bp
1416 jmp short PLS_com
1417
1418PLS_Done:
1419 mov es:[bp.nMRU_ptr],-1
1420 pop di
1421
1422PLS_Exit:
1423 ret
1424
1425PRE_LRU_STACK endp
1426;
1427
1428
1429
1430
1431
1432;----------------------------------------------------------------------
1433;PROCEDURE: SET_LRU
1434;
1435;INPUT: Depth, Top, Bottom, Current_Drive, ES = Name_Cache_Seg
1436;
1437;OUT: If Depth == 0 then exit
1438; Pre_LRU_Stack procedure already maintained a reverse order LRU
1439; mini chain. Set_LRU will just put the top after the last node
1440; of the current LRU chain;
1441; { Get the last node of LRU chain.
1442; if Depth == 0 then exit;
1443; if Depth == 1 then Last_Node.LRU_ptr = Bottom;
1444; Bottom.MRU_ptr = Last_Node;
1445; MRU_ROOT = Bottom;
1446; if Depth >= 2 then Last_Node.LRU_ptr = Top;
1447; Top.MRU_ptr = Last_Node;
1448; MRU_ROOT = Bottom;
1449; Depth = 0;
1450; }
1451;----------------------------------------------------------------------
1452
1453SET_LRU PROC NEAR
1454
1455 cmp cs:Depth, 0 ;nothing in the stack?
1456 je SL_Exit
1457
1458 push si
1459 push di
1460 push bx
1461 mov si, cs:Current_Drive ;cs:si -> Drive_Cache_Header
1462 push ds
1463 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1464 ASSUME ds:Cseg_Init ;AN000;
1465 mov di, ds:[si.DCH_MRU_ROOT] ;es:di -> Last node in LRU chain
1466
1467 cmp cs:Depth, 1
1468 jne SL_Other
1469
1470 mov bx, cs:Bottom
1471 mov es:[di.nLRU_ptr],bx ;Last_Node.LRU_ptr = Bottom
1472 mov es:[bx.nMRU_ptr],di ;Bottom.MRU_ptr = Last_Node
1473 mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT = Bottom
1474 jmp short SL_Done
1475
1476SL_Other: ;Depth >= 2
1477 mov bx, cs:Top
1478 mov es:[di.nLRU_ptr],bx
1479 mov es:[bx.nMRU_ptr],di
1480 mov bx, cs:Bottom
1481 mov ds:[si.DCH_MRU_ROOT],bx
1482
1483SL_Done:
1484 pop ds
1485 ASSUME ds:nothing
1486 mov cs:Depth, 0 ;reset the Depth
1487 pop bx
1488 pop di
1489 pop si
1490
1491SL_Exit:
1492 ret
1493
1494Set_LRU endp
1495
1496
1497
1498
1499
1500;----------------------------------------------------------------------
1501; Procedure RemoveFromLRUChain
1502;
1503;IN: Target node (BP) to be removed
1504; Current_drive
1505; ES - Name_Cache_Seg
1506;
1507;OUT: Target node removed from the LRU,MRU chain. LRU,MRU chain
1508; updated.
1509;
1510;----------------------------------------------------------------------
1511
1512RemoveFromLRUChain PROC near
1513
1514 push bx
1515 push di
1516 push si
1517
1518 mov si, cs:Current_drive ;cs:si-> Drive_cache_header
1519 mov bx, es:[bp.nMRU_ptr] ;es:bx-> Preceding node
1520 mov di, es:[bp.nLRU_ptr] ;es:di-> Following node
1521 cmp bx, -1 ;Is target the first node?
1522 je RFLC_first_node
1523 cmp di, -1 ;Is target the last node of LRU chain?
1524 je RFLC_last_node
1525 mov es:[bx.nLRU_ptr],di ;Preceding.LRU_ptr->following node
1526 mov es:[di.nMRU_ptr],bx ;Following.MRU_ptr->preceding node
1527 jmp short RFLC_done
1528
1529RFLC_first_node:
1530 push ds
1531 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1532 ASSUME ds:Cseg_Init ;AN000;
1533 mov ds:[si.DCH_LRU_ROOT],di ;LRU_ROOT-> following node
1534 pop ds
1535 ASSUME ds:nothing
1536 mov es:[di.nMRU_ptr], -1 ;Following node's MRU_ptr
1537 jmp short RFLC_done
1538
1539RFLC_last_node:
1540 push ds
1541 mov ds,cs:Open_Name_Cache_Seg
1542 ASSUME ds:Cseg_Init
1543 mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT-> preceding node
1544 mov es:[bx.nLRU_ptr], -1 ;Preceding node's LRU_ptr
1545 pop ds
1546 ASSUME ds:nothing
1547
1548RFLC_done:
1549 pop si
1550 pop di
1551 pop bx
1552 ret
1553
1554RemoveFromLRUChain endp
1555;
1556
1557
1558
1559;----------------------------------------------------------------------
1560; Proceure RemoveFromTree
1561;
1562;IN: BP - offset of node to be removed from the tree
1563; This node shoud not be a subdirectory that is not empty!!!
1564; ES - Name_Cache_Seg
1565; Current_Drive
1566;
1567;OUT: The node will be freed from the tree.
1568; The neighbor's Child_ptr, Sibling_ptr, Backward_ptr are adjusted
1569; accordingly.
1570; The freed node's child_ptr, sibling_ptr, backward_ptr are reset to -1.
1571;----------------------------------------------------------------------
1572
1573REMOVEFROMTREE PROC NEAR
1574
1575 push bx
1576 push dx
1577
1578 mov bx, es:[bp.nBackward_ptr] ;get the preceding node
1579 mov dx, es:[bp.nSibling_ptr] ;get the sibling node
1580 cmp bx, cs:Current_Drive
1581 je RFT_First_Child ;bp is the first child
1582 cmp es:[bx.nChild_ptr],bp
1583 je RFT_Child ;bp is the child of the preceding node
1584 mov es:[bx.nSibling_ptr],dx ;bp is the Sibling of the preceding node
1585 ;Update the preceding node's Sibling ptr
1586 jmp short RFT_Reset
1587
1588RFT_First_Child:
1589 push ds
1590 mov ds,cs:Open_Name_Cache_Seg ;AN000;
1591 ASSUME ds:Cseg_Init ;AN000;
1592 mov ds:[bx.DCH_Child_ptr],dx
1593 pop ds
1594 ASSUME ds:nothing
1595 jmp short RFT_Reset
1596
1597RFT_Child:
1598 mov es:[bx.nChild_ptr],dx
1599
1600RFT_Reset: ;reset the deleted node's tree pointers
1601 mov es:[bp.nChild_ptr],-1
1602 mov es:[bp.nSibling_ptr],-1
1603 mov es:[bp.nBackward_ptr],-1
1604
1605 xchg dx,bx ;now, dx=preceding node, bx=following node
1606 cmp bx,-1 ;end of sibling?
1607 je RFT_ret
1608 mov es:[bx.nBackward_ptr],dx;modify backward_ptr of the sibling node
1609
1610RFT_ret:
1611 pop dx
1612 pop bx
1613 ret ;return
1614
1615REMOVEFROMTREE endp
1616;
1617
1618
1619
1620
1621;----------------------------------------------------------------------
1622; Procedure CMPARE
1623;
1624;IN: Packed name
1625; BP = target node
1626;
1627;OUT: ZERO flag set when compare O.K.
1628; DI destroyed.
1629;----------------------------------------------------------------------
1630
1631CMPARE PROC near
1632
1633 push ds
1634 push si
1635 mov cx, 11
1636 push cs
1637 pop ds
1638 mov si, offset cs:Packed_Name ;ds:si -> Packed_Name
1639 mov di,bp
1640 add di,nCmpct_Dir_Info ;es:di -> bp.nCmpact_Dir_Info
1641 REPE CMPSB
1642 pop si
1643 pop ds
1644 ret
1645CMPARE endp
1646
1647
1648
1649
1650;
1651;----------------------------------------------------------------------
1652; Procedure: MAKE_NAME_RECORD
1653;
1654;IN: DS:DI -> Dir_Info, ES:BX -> Extended_Info
1655; AX = offset of the Name_Record entry in Name_Cache_Seg.
1656;
1657;OUT: Name_Record in Name_Cache_Seg filled.
1658; nLRU_ptr, nChild_ptr, nSibling_ptr and nMRU_ptr are set to -1 for now.
1659; ES, SI, DI destroyed. ES will be Name_Cache_Seg.
1660;----------------------------------------------------------------------
1661
1662MAKE_NAME_RECORD PROC NEAR
1663
1664 push ds ;save DS
1665 push ax
1666
1667 push es ;save Extended_Info seg in DOS
1668 push di
1669 pop si ;DS:SI -> Dir_Info
1670 mov di, cs:Open_Name_Cache_Seg ;AN000;
1671 mov es, di ;AN000;
1672 ASSUME es:Cseg_Init ;AN000;
1673 mov di, ax ;ES:DI -> Name_Record
1674 mov ax, -1
1675 mov es:[di.nLRU_ptr],ax ;initialize pointers
1676 mov es:[di.nChild_ptr],ax
1677 mov es:[di.nSibling_ptr],ax
1678 mov es:[di.nMRU_ptr],ax
1679 add di, nCmpct_Dir_Info ;ES:DI -> Name_Record.nCmpct_Dir_Info
1680 mov cx, ODI_head_leng ;currently 10.
1681 rep movsb ;Move header part
1682 add si, ODI_skip_leng ;DS:SI -> tail part of Dir_Info
1683 mov cx, ODI_tail_leng
1684 REP MOVSB ;move tail part.
1685
1686 pop ds ;restore Extended_Info seg in DS!!!
1687 mov si, bx ;DS:SI -> Extended_Info
1688 mov cx, size Fastopen_Extended_Info
1689 rep movsb ;Move Extended_Info
1690 pop ax
1691 pop ds ;Restore DS
1692
1693 ret ;return
1694
1695MAKE_NAME_RECORD ENDP
1696;
1697
1698
1699
1700
1701;----------------------------------------------------------------------
1702; Procedure Unfold_Name_Record
1703;
1704;IN: Matching_Node, ES:DI -> Dir_Info buffer, ES:CX -> Extended_Info buffer
1705;
1706;OUT: if no matching node is found, then just return
1707; else Dir_Info, Extended_Info buffer are filled.
1708;----------------------------------------------------------------------
1709
1710Unfold_Name_Record PROC near
1711
1712 cmp cs:Matching_Node, -1
1713 je UNR_Exit ;just exit
1714 push ds
1715 push si
1716 push di
1717 push cx ;save extended_info addr
1718
1719 mov si, cs:Open_Name_Cache_Seg ;AN000;
1720 mov ds, si ;AN000;
1721 ASSUME ds:Cseg_Init ;AN000;
1722 mov si, cs:Matching_Node
1723 add si, nCmpct_Dir_Info ;DS:SI -> Cmpct_Dir_Info
1724
1725 mov cx, ODI_head_leng ;Dir_Info header length
1726 REP MOVSB ;Cmpct_Dir_Info.CDI_file_name -> ODI_head
1727
1728 add di, ODI_skip_leng ;length of Skiped part of Dir_Info
1729 mov cx, ODI_tail_leng ;Dir_Info tail length
1730 REP movsb ;Cmpct_Dir_Info.CDI_Time -> ODI_tail
1731 ;At this moment, SI -> nExtended_Info
1732
1733 pop di ;ES:DI -> Extended_info
1734 push di ;save di again for cx.
1735 mov cx, size Fastopen_Extended_Info
1736 REP movsb
1737
1738 pop cx ;restore extended_info addr
1739 pop di
1740 pop si
1741 pop ds
1742 ASSUME ds:nothing
1743UNR_Exit:
1744 ret ;return
1745
1746Unfold_Name_Record endp
1747;
1748
1749
1750
1751
1752;----------------------------------------------------------------------
1753; PROCEDURE: PACK DIR_NAME
1754;
1755; Parse the name off of DS:SI into Packed_Name. If called first time and
1756; DS:[SI+1] = ':' then it is ASSUMEd to be a drive letter and it will be
1757; returned in DL and SI will points to '\' after ':'. If it was a directory
1758; name then Packed_Name will be set and SI points to '\' or 0 after the
1759; parsed directory name or filename. This routine will check DS:[SI] when
1760; called to see if it points to '\' or 0. If it points to '\' then
1761; it is ASSUMEd that the user want to skip the delimiter. If it was 0,
1762; then this routine will set carry. So, with a given drive,path string,
1763; the user is going to keep calling this routine until it returns
1764; with carry set that tells the end.
1765;----------------------------------------------------------------------
1766
1767PACK_DIR_NAME PROC NEAR
1768
1769 cmp byte ptr ds:[si], 0 ;end of path ??
1770 jne PDN_Drive ;no-check for drive letter
1771 stc
1772 jmp short PDN_Exit ;yes-exit
1773
1774PDN_Drive:
1775 cmp byte ptr ds:[si+1], ':' ;drive letter terminater?
1776 jnz PDN_chk_skip ;no -
1777 mov dl, byte ptr ds:[si] ;yes-set DL to the drive letter
1778 inc si
1779 inc si ;set SI -> '\' after ':'
1780 jmp short PDN_Exit ;then exit
1781
1782PDN_chk_skip:
1783 cmp byte ptr ds:[si], '\' ;delimeter?
1784 jne PDN_Path ;no-
1785 inc si ;yes-skip delimiter
1786 cmp byte ptr ds:[si], 0 ;end of path ??
1787 jne PDN_Path ;no-pack path name
1788 stc ;yes-In fact, the input from DOS was
1789 mov ax, -1 ;D:\,0. FASTOPEN will treate
1790 jmp short PDN_Exit ;this as an error.
1791
1792PDN_Path: ;pack path name
1793 push es
1794 push di
1795 push ax
1796
1797 push cs
1798 pop es
1799 mov di, offset cs:Packed_Name ;ES:DI-->pack buffer
1800
1801 mov ax,' '
1802 STOSB ;blank out the Packed_Name
1803 STOSW
1804 STOSW
1805 STOSW
1806 STOSW
1807 STOSW
1808 mov di, offset cs:Packed_Name
1809
1810PDN_GetName:
1811 LODSB ;DS:SI => AL, SI++
1812 cmp al,'.'
1813 jz PDN_SetExt
1814 or al,al
1815 jz PDN_GetDone
1816 cmp al,'\'
1817 jz PDN_GetDone
1818 STOSB
1819 jmp short PDN_GetName
1820
1821PDN_SetExt:
1822 mov di, offset cs:Packed_Name+8
1823
1824PDN_GetExt:
1825 LODSB
1826 or al,al
1827 jz PDN_GetDone
1828 cmp al,'\'
1829 jz PDN_GetDone
1830
1831PDN_StoExt:
1832 STOSB
1833 jmp PDN_GetExt
1834
1835PDN_GetDone:
1836 dec si ;set SI back to the delimeter or 0.
1837 pop ax
1838 pop di
1839 pop es
1840
1841PDN_Exit:
1842 ret
1843
1844PACK_DIR_NAME endp
1845
1846
1847
1848
1849
1850;----------------------------------------------------------------------
1851; PROCEDURE: FIND_CLUSTER_NUMBER
1852;
1853;IN: DL = driver # (0 = A, 1 = B,...)
1854; CX = The value of Dir_First in Name_Record to search.
1855; Search Name_Record entries to find the matching starting cluster number.
1856; The search uses MRU chain for efficiency.
1857;
1858;OUT: ES = Name_Cache_Seg
1859; BP = Name_Record
1860; if not found, carry bit.
1861; ES, BP register changed.
1862;----------------------------------------------------------------------
1863
1864FIND_CLUSTER_NUMBER PROC NEAR
1865
1866 push ax
1867 push cx
1868 push dx
1869 add dl, 'A' ;convert to a drive letter
1870
1871 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1872 jc FCN_exit ;exit if not found
1873
1874 mov dx, cx ;save the key in DX ;AN000;
1875 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1876 mov es, ax ;AN000;
1877 ASSUME es:Cseg_Init
1878
1879 CALL SET_LRU ;clean up the LRU stack
1880
1881 mov cs:Current_Drive,bp ;set Current_Drive (You should not set
1882 ;Current_Drive before SET_LRU at any time!!!
1883 push ds
1884 mov ds,cs:Open_Name_Cache_Seg
1885 ASSUME ds:Cseg_Init
1886 mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try
1887 mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing
1888 pop ds
1889 ASSUME ds:nothing
1890
1891FCN_while:
1892 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1893 je FCN_not_found ;then no reason to continue search.
1894
1895 cmp dx, es:[bp.nCmpct_Dir_Info.CDI_cluster] ;matching starting cluster # ?
1896 je FCN_exit ;found it!!!
1897
1898 mov bp, es:[bp.nMRU_ptr] ;next MRU entry address
1899 cmp bp, -1 ;It was the end of MRU chain?
1900 je FCN_not_found ;not found. End of search
1901 LOOP FCN_while ;else compare cluster and contine...
1902
1903FCN_Not_found:
1904 stc
1905
1906FCN_exit:
1907 pop dx
1908 pop cx
1909 pop ax
1910 ret
1911
1912FIND_CLUSTER_NUMBER ENDP
1913
1914
1915
1916
1917;----------------------------------------------------------------------
1918; PROCEDURE: FIND_DIR_SECTOR (PTR 3718 3/10/88)
1919;
1920; Search Name_Record using directory sector and directory position
1921; for the name entry.
1922;
1923;IN: DL = driver # (0 = A, 1 = B,...)
1924; DI = Dirctory sector Low value
1925; CX = Dirctory sector high value
1926; DH = Dirctory position
1927;
1928;OUT: ES = Name_Cache_Seg
1929; BP = Name_Record
1930; if not found, carry bit.
1931; ES, BP register changed.
1932;----------------------------------------------------------------------
1933
1934FIND_DIR_SECTOR PROC NEAR
1935
1936 push ax
1937 push cx
1938 push dx
1939 add dl, 'A' ;convert to a drive letter
1940
1941 CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found
1942 jc FDIR_exit ; error if not found
1943
1944 mov ax, cs:Open_Name_Cache_Seg ;AN000;
1945 mov es, ax ;AN000;
1946 ASSUME es:Cseg_Init
1947
1948 CALL SET_LRU ;clean up the LRU stack
1949
1950 mov ax,cx ; save directory sector high value
1951 mov cs:Current_Drive,bp ;set Current_Drive (You should not set
1952 ;Current_Drive before SET_LRU at any time!!!
1953 push ds
1954 mov ds,cs:Open_Name_Cache_Seg
1955 ASSUME ds:Cseg_Init
1956 mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try
1957 mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing
1958 pop ds
1959 ASSUME ds:nothing
1960
1961FDIR_while:
1962 cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ?
1963 je FDIR_NOT_FOUND ;then no reason to continue search.
1964
1965 cmp di, word ptr es:[bp.nExtended_Info.FEI_dirsec] ;matching directory sector hi?
1966 jne FDIR_Next ;check next entry
1967
1968 cmp ax, word ptr es:[bp.nExtended_Info.FEI_dirsec+2] ;matching directory sector low ?
1969 jne FDIR_Next ;check next entry
1970
1971 cmp dh, es:[bp.nExtended_Info.FEI_dirpos] ;matching directory postion ?
1972 je FDIR_Exit ;check next entry
1973
1974FDIR_Next:
1975 mov bp, es:[bp.nMRU_ptr] ;next MRU entry address
1976 cmp bp, -1 ;It was the end of MRU chain?
1977 je FDIR_not_found ;not found. End of search
1978 loop FDIR_while ;else compare cluster and contine...
1979
1980FDIR_Not_found: ; no found
1981 stc
1982
1983FDIR_exit:
1984 pop dx
1985 pop cx
1986 pop ax
1987 ret
1988
1989FIND_DIR_SECTOR ENDP
1990
1991
1992
1993
1994
1995;--------------------------------------------------------------------------
1996; Procedure: CHECK_IT Call Fastopen Tree Analyser to check the
1997; consistency of the Directory/File Tree strucutre.
1998;--------------------------------------------------------------------------
1999CHECK_IT PROC NEAR
2000
2001 pushf ; save all registers
2002 push ax
2003 push bx
2004 push cx
2005 push dx
2006 push si
2007 push di
2008 push ds
2009 push es
2010 cmp cs:Chk_flag,0 ;Fastopen analyser enabled ??
2011 je Check_Exit ;no - exit
2012
2013 mov ax,cs:Open_Name_Cache_Seg ;yes-set multiplex function call
2014 mov es,ax
2015 mov ah,091h ;load Multiplex ID
2016 xor al,al
2017 xor cx,cx
2018 mov cl,cs:func_cod ;CL=Fastopen Function code
2019 mov di,cs:Current_Drive ;ES:DI-->current drive header
2020 INT 2FH ;call the analyser
2021
2022Check_Exit:
2023 pop es ;restore all registers
2024 pop ds
2025 pop di
2026 pop si
2027 pop dx
2028 pop cx
2029 pop bx
2030 pop ax
2031 popf ;return
2032 ret
2033
2034CHECK_IT ENDP
2035
2036
2037
2038
2039
2040; Calculate the size of the CSEG_OPEN Module in bytes
2041 IF ($-Cseg_Open) MOD 16 ;AN000;
2042 ORG ($-Cseg_Open)+16-(($-Cseg_Open) MOD 16) ;AN000;
2043 ENDIF ;AN000;
2044
2045END_OPEN label word
2046
2047
2048
2049
2050CSEG_OPEN ends
2051 end
2052 \ No newline at end of file
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK b/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK
new file mode 100644
index 0000000..eb37c6e
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK
@@ -0,0 +1,7 @@
1FASTOPEN.OBJ+
2FASTSEEK.OBJ+
3FASTINIT.OBJ+
4FASTP.OBJ+
5FASTSM.OBJ
6FASTOPEN.EXE,/m;
7 \ No newline at end of file
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL b/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL
new file mode 100644
index 0000000..25c7c5e
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL
@@ -0,0 +1,28 @@
1;==========================================================
2; FASTOPEN MESSAGE SKELETON FILE
3;==========================================================
4
5:util FASTOPEN ;AN000;
6:class A ;System message class ;AN000;
7:use 1 COMMON1 ;MSG 1 is always "Incorrect DOS Version" ;AN000;
8:use 6 PARSE10 ;Invalid parameter message ;AN000;
9:use 3 PARSE3 ;Invalid Switch
10
11:def 4 CR,LF,"FASTOPEN installed",CR,LF ;AN000;
12:def 5 CR,LF,"FASTOPEN already installed",CR,LF ;AN000;
13:def 7 CR,LF,"Too many drive entries",CR,LF ;AN000;
14:def 8 CR,LF,"Same drive specified more than once",CR,LF ;AN000;
15:def 9 CR,LF,"Invalid parameter",CR,LF ;AN000;
16:def 11 CR,LF,"Invalid extent entry",CR,LF ;AN000;
17:def 12 CR,LF,"Invalid number of file/directory entries",CR,LF ;AN000;;AN000;
18:def 13 CR,LF,"Cannot setup expanded memory",CR,LF ;AN000;;AN000;
19:def 14 CR,LF,"Expanded memory not available",CR,LF ;AN000;;AN000;
20:def 15 CR,LF,"Invalid drive specification %1",CR,LF ;AN000;;AN000;
21:def 16 CR,LF,"Not enough space in EMS. Low memory is used",CR,LF ;AN000;
22:def 17 CR,LF,"Cannot use FASTOPEN for drive %1",CR,LF
23:def 18 CR,LF,"Too many extent entries",CR,LF ;AN000;
24:def 19 CR,LF,"Too many file/directory entries",CR,LF ;AN000;
25
26:end
27
28;==========================================================
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
new file mode 100644
index 0000000..b1cf286
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
@@ -0,0 +1,615 @@
1
2.*
3.pm 5
4:gdoc sec=''
5:frontm
6:titlep
7:title.FASTOPEN UTILITY HIGH LEVEL DESIGN
8:date.
9:author.J. K.
10:ETITLEP
11:toc
12:body
13.DH NUM
14.*.pa
15&SYSDATE.
16.*:H1.INTRODUCTION
17.*:H1.ARCHITECTURE OVERVIEW
18
19:H1.FASTOPEN DESIGN
20:H2.FASTOPEN UTILITY
21:H3.FASTOPEN Overview
22FASTOPEN is a utility that allows DOS to maintain the information about
23files that have been opened. The purpose is to reduce the number of times DOS
24has to look into the directory area of the disk for information on the file once
25the information is stored by FASTOPEN. In real life, many application
26programs, especially current database systems on the market, tend to open the
27same file repeatedly and every open operation needs an access to the disk if the
28information does not exist in the DOS buffer. The FASTOPEN utility will
29eliminate these disk accesses, and hence will increase the efficiency of DOS
30performance.
31
32
33:H3.FASTOPEN Operational Description
34Conceptually FASTOPEN itself is a database maintained by DOS. The data will
35be stored and maintained in the system RAM.
36
37FASTOPEN is a user-installable, stay resident utility loaded by entering a
38command
39.fo off
40 1). FASTOPEN D:{=L} ...
41
42where "..." means a possible repetition.
43
44 "D:" is a drive letter for a non_removable media.
45
46 "L" is the maxium number of files and subdirectories that can be
47 stored in the drive cache. The default value is 34, minimum
48 value, 10. The total number for all the drives is less
49 than 1000.
50
51.fo on
52
53:H4.Name Caching
54FASTOPEN will keep the history of the accessed subdirectory and file
55information in LRU fashion. The data are stored in a partial tree
56structure that represents all the recently accessed files and
57subdirectories of that drive. The number of entries entered by the
58user, or the default number of 34, represents the maximum number of
59nodes and leaves of the tree. As it suggests, the bigger the
60number is, the more the efficient it will be. Currently each additional
61increase of the entry will take 36 bytes, which is the fixed length of
62a node.
63
64The number entered by the user should be bigger than the deepest nesting
65of path entries in the drive.
66
67The operation on this name cache is similar to the operation on the
68physical drive.
69With the look up request, FASTOPEN will traverse the name cache tree from the
70root to the bottom to find the requested path, filename. If found, then the
71pointer to the file or subdirectory information packet will be returned, else FASTOPEN
72will return the string pointer that points up to the matching subdirectory name.
73In this case, if DOS wants to insert the rest of the subdirectory/file information
74an insert operation should be requested for every subdirectory/file. FASTOPEN
75will use the information from the previous Look_up operation for a sequence of Insert operations.
76
77At this moment, if there are any free entries left, then it will be used.
78Otherwise, FASTOPEN will delete the least recently used leaf. Any node cannot
79be deleted until the node becomes an empty leaf, i.e., without children.
80If a file or a directory has been removed, then DOS will update the name
81cache tree with the Delete request. The path, file will be looked up
82first, and if found, then the corresponding entries will be free to the
83free entry chain. If not found, then still it is O.K. since the matching file
84entries had been removed by the LRU scheme.
85
86
87:H3.Fastopen Interface
88When installed, by the nature of the functionality, FASTOPEN becomes
89a part of DOS and a private communication mechanism will be
90established.
91Inside DOS, vector pointers are established for FASTOPEN and will be
92initialized by the call "CALLinstall" macro by the FASTOPEN initialization.
93The structure of the FASTOPEN entry will look like;
94
95.fo off
96FASTOPEN_ENTRY struc
97FASTOPEN_ENTRY_SIZE dw 4 ;size of the following
98FASTOPEN_NAME_CACHING dd ?
99;FASTOPEN_FATCHAIN_CACHING dd ? ;not for DOS 3.3
100;NUMBER_OF_SFTS dw ? ;# of files - 3
101FASTOPEN_ENTRY ends
102.fo on
103
104The initial vector pointer for FASTOPEN_NAME_CACHING
105points to a dummy routine in DOS which simply set the carry flag and set AX to 0FFFFh.
106
107When FASTOPEN is installed, then this vectors table will be established to
108point to the matching procedures in FASTOPEN module.
109
110The register AL will contain subfunction value on entry to FASTOPEN.
111
112.fo off
113;FASTOPEN NAME CACHING Subfunctions
114fastopen_name_look_up equ 1
115fastopen_name_insert equ 2
116fastopen_name_delete equ 3
117;fastopen_name_purge equ 4 ;Not for DOS 3.3
118
119.fo off
1201. Name Caching
121
122 a. Look up
123 IN) DS:SI -> d:path
124 ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN
125 ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN
126 OUT)
127 if found, DS:SI -> the last character of the path, i.e., 0.
128 ES:DI -> DIR INFO
129 ES:CX -> Extended INFO (explained in the data structure)
130 else if there exist the name cache for the drive, but could not
131 completely find the matching path,
132 DS:SI -> "\" following the directory that FASTOPEN can
133 find the match,
134 Will points to "\" after "d:" if no matching
135 root directory is found.
136 ES:DI -> Compct_Dir_Info of the subdirectory FASTOPEN
137 can find the match.
138 ES:CX -> the matching directory's Extended INFO
139 If cannot find the matching root directory entry, then
140 ES:DI, ES:CX are undetermined.
141 else carry flag set and AX = 0FFFFh.
142
143 b. Insert
144 IN) DS:DI -> DIR info
145 ES:BX -> Extended info
146
147 OUT)
148 If failed, then carry flag set and AX = 0FFFFh.
149 Insert operation handles only one file or subdirectory at a time.
150 So, usually insert operations are performed in a sequential manner.
151 A look up operation should be performed before any new sequential
152 insert operation.
153 FASTOPEN will keep the information of the pervious look up
154 operation in CURRENT_NODE. The CURRENT_NODE points to the matching
155 directory node of the previous Look up operation. The next insert
156 operation will use this CURRENT_NODE information to insert the
157 directory or file information. So, DOS will call only one Look_
158 up operation and possibly several Insert operation to insert the
159 path.
160
161 For example, suppose DOS wants to look up C:\DIR1\DIR2\FILE1 and
162 FASTOPEN only has the inforamtion up to C:DIR1. After the
163 look up operation, FASTOPEN will return with DS:SI points "\"
164 following C:\DIR1.
165 At this moment, if DOS decides to insert this information,then
166 it sets DS:DI to DIR_INFO, and ES:BX to EXTENDED_INFO of the
167 subdirectory DIR2, and will request an insert operation.
168 When control returned back to DOS, then it will set this time
169 DS:DI and ES:BX to those of FILE1, and will call an another
170 insert operation.
171 At the first insert operation, FASTOPEN automatically knows
172 that those informaton given by DOS belong to the child of
173 C:\DIR1, and will install it as a child. In the second operation,
174 again FASTOPEN knows that it is for the child of C:\DIR1\DIR2
175 and will accordingly install the information for FILE1.
176
177 c. Delete
178 IN) DS:SI -> d:path
179
180 OUT)
181 If failed, then carry flag set and AX = 0FFFFh.
182
183.fo on
184
185:H3.FASTOPEN Special Considerations
186FASTOPEN uses the following DOS function calls in its initialization
187rouitine. No DOS or BIOS function calls are allowed inside the
188main routine that is resident once installed.
189:ul
190:li.AH = 40h, Int 21h; Write to device for the messages,
191:li.AH = 31h, Int 21h; Terminate Process and Remain Resident,
192:li.AH = 48h, AH = 49h, AH = 4Ah, Int 21h; Allocate, free and
193modify memory block.
194:eul
195:p.
196
197To prevent the corruption of any DOS operation, once FASTOPEN is
198loaded it cannot be reloaded.
199
200
201:H4.FASTOPEN Top Level Design
202
203:H5.Data Structure
204
205The structures of the records in FASTOPEN are:
206
207.fo off
208NAME_record struc
209 LRU_pointer dw -1
210 Child_pointer dw -1
211 Sibling_pointer dw -1
212 MRU_pointer dw -1
213 Compct_Dir_info db 22 dup (?)
214 Extended_Info db 5 dup (?)
215NAME_record ends
216
217Extended_Info struc
218dirpos db 0
219dirsec dw 0
220clusnum dw 0
221Extended_Info ends
222
223Drive_cache_header struc
224LRU_ROOT dw 0 ;Start of LRU chain for this Name cache
225Child_ptr dw -1 ;points to the name cache
226Sibling_ptr dw -1 ;points to the next drive header
227MRU_ROOT dw 0 ;set to the end of LRU chain
228Drive_letter db 'C'
229Num_Entries dw 0
230Name_Cache_start dw 0 ;Start of name cache for this drive
231Drive_cache_header ends
232
233Cmpct_Dir_Info struc
234CD_File_name db 11 dup (0)
235CD_File_attr db ?
236CD_time dw ?
237CD_date dw ?
238CD_cluster dw ?
239CD_Filesize dd ?
240Cmpct_Dir_Info ends
241
242Dir_Info struc ;= full directory entry information.
243DI_head db 12 dup (?)
244DI_skip db 10 dup (0) ;reserved area. All the time 0.
245DI_tail db 10 dup (?)
246Dir_Info ends
247
248.fo
249
250
251:H5.FASTOPEN Hierarch
252:H6.FASTOPEN Components
253
254.fo off
255
256 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
257 ³ FASTOPEN ³
258 ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ
259 ³
260 ³
261 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
262 ³ ³
263 V V
264ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
265³ INIT ³ ³ MAIN ³
266ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ
267 ³
268 V
269 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
270 ³ ³
271 ³ LOOK_UP, INSERT, DELETE, INIT_TREE ³
272 ³ ³
273 ³ (SUPPORTING MODULES) ³
274 ³ ³
275 ³ GET_FREE_NODE, PRE_LRU_STACK, ³
276 ³ SET_LRU, MAKE_NAME_RECORD, ³
277 ³ UNFOLD_NAME_RECORD, PACK_DIR_NAME, ³
278 ³ REMOVEFROMLRUCHAIN ³
279 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
280
281.fo
282
283:H6.FASTOPEN Memory Structure
284
285.fo off
286 Lo_memory ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÄÂÄ
287 ³ LOOK_UP, ³ ³
288 ³ INSERT, ³ M
289 ³ DELETE, ³ A
290 ³ & Supporting Routines ³ I
291 ³ ³ N
292 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³
293 ³ INIT_TREE ³ ³
294 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÄÅÄ
295 ³ DRIVE_CACHE_HEADER ³ I
296 ³ (After Init, this ³ N
297 ³ area will be used ³ I
298 ³ for name caches.) ³ T
299 ³ SHOW_ERR_MESSAGE ³ ³
300 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÄÁÄ
301
302 High_memory
303.fo
304
305.pa
306:H5.FASTOPEN Component Interfaces
307
308.fo off
309;*************************************************************************
310;
311;SUBROUTINE: INIT
312;
313;INPUT:
314;
315;OUTPUT:
316;
317;DESCRIPTION:
318;
319; 1:(Installation check)
320; { Get the entry pointer of FASTOPEN from DOS.
321; Check the signature ($FASTOPEN01$)
322; If already installed,
323; then Show 'FASTOPEN already installed'; Exit
324; }
325;
326; 2:(Parse the command line)
327; Input: User input
328;
329; Output: Total_Entry_Num.
330; Drive_Cache_Headers set.
331; End_Cache_Header.
332;
333; { For every drive entered
334; { Drive sanity check;
335; Get_Num;
336; if success and Total_Entry_Num < 1000, then
337; Set Drive_Cache_Header;
338; }
339; }
340;
341; 3:(Check the system memory) - Check if the system has enough
342; memory for the Name caches.
343; Name cache will start from the
344; End_Cache_Header.
345;
346; Input: Total_Entry_Num, End_Cache_Header, End_Init,
347; Output: End_Caches
348; {
349; Needed_space = size of (Name_Record) * Total_Entry_Num;
350; Needed_space = Needed_space - (End_Init - End_Cache_Header);
351; Free allocated memory from End_Init (AH = 4Ah);
352; Set memory block from End_Init to Needed_Space (AH = 48h);
353; if fail, Show 'Insufficient memory for FASTOPEN cache';
354; Set End_Caches;
355; }
356;
357; 4: jmp to INIT_TREE
358;
359;*************************************************************************
360
361
362.pa
363.fo off
364;*************************************************************************
365;
366;SUBROUTINE: INIT_TREE
367;
368;INPUT: Drive_cache_header, End_Caches
369;
370;OUTPUT:Name_cache entries installed for every drive requested.
371; LRU chain established for every drive.
372; FASTOPEN entry pointer set in DOS.
373; Terminate & stay resident. (Up to End_Caches)
374;
375;DESCRIPTION:
376;
377; 1:(Install_Name_Cache)
378; Input: Drive cache header, End_cache_header (= Name cache start)
379; Output:According to the information in the header,
380; the name cache entries will be established.
381; Also, LRU chain, MRU_pointer are established.
382;
383; { Buffer_start = End_cache_header;
384; For every drive header
385; { LRU_ROOT = Buffer_start;
386; For (i=1;i=Num_Entries;i++)
387; { MRU_pointer = Buffer_start;
388; Buffer_start= Buffer_start + size_of (Name_record);
389; if i = Num_Entries then LRU_pointer = -1
390; else LRU_pointer = Buffer_start;
391; }
392; }
393; }
394;
395; 2:(Set FASTOPEN entry pointer in DOS)
396; Use CALL INSTALL macro.
397;
398; 3: Terminate and stay resident up to Buffer_start;
399;
400;*************************************************************************
401
402
403.pa
404.fo off
405;*************************************************************************
406;
407;SUBROUTINE: MAIN
408;
409;INPUT: Called by DOS throught Look_up, Insert, Delete requests.
410;
411;OUTPUT:Request performed based on LRU scheme.
412; CX, DX, DS, ES, BP value saved. Other register are destroyed.
413;
414;DESCRIPTION:
415; Call Pack_Dir_Name ;get the drive letter in BL
416; Call Get_Drive_Cache_Header ;find the matching drive header
417; if not found, then AX = 0ffffh, Carry set
418; else if AL = Look_up then Call Look_up
419; else if AL = Insert then Call Insert
420; else if AL = Delete then Call Delete
421; else AX = 0ffffh, Carry set.
422;
423; MAJOR SUBROUTINES:
424; (Look_up) - Refer to Look_up subroutine.
425; (Delete) - Refer to Delete subroutine.
426; (Insert) - Refer to Insert subroutine.
427;
428; SUPPORTING SUBROUTINES:
429; 1:(Get_Free_Node) - Get the entry from the LRU_ROOT,
430; Set LRU_ROOT to the next entry of the
431; LRU chain
432; Input: none
433; Output:Entry address. LRU_ROOT updated to the next entry.
434;
435; 2:(Pre_LRU_Stack) - This is needed to implement LRU scheme in
436; a tree structure. Since the order of traversing a tree is
437; from the root to bottom and from left to right, the direct
438; implementation of LRU will result the parent the least mostly
439; used one instead of the child. This is exactly in the reverse
440; order to what had been expected. This procedure will
441; solve this problem without loss of any efficiency. In the
442; Look_up operation and found the match, the found entris will
443; be saved with each of its LRU, MRU pointer modified to reflect
444; the desired LRU order.
445; These created mini LRU chain will be attached to the
446; LRU chain again by SET_LRU. SET_LRU and PRE_LRU_STACK
447; should work in a synchronized fashion. SET_LRU routine
448; will be called in the beginning of every Look_up, Insert
449; operation. PRE_LRU_Stack will be called whenever a matching
450; entry is found in a Look_up operation, or whenever a new
451; entry is inserted by the Insert operation.
452; Input: Current_Drive,Target node.
453; Output:Depth, Top, Bottom set
454;
455; 3:(SET_LRU)
456; Input: Depth, Top, Bottom, Current_Drive
457; Output:Mini LRU chain created by Pre_LRU_Stack will be
458; placed at the end of LRU chain.
459;
460; 4:(MAKE_NAME_RECORD) - At Insert time, BOS will give
461; two types of information. DS:DI -> Dir_Info, ES:BX -> Extended_
462; Info. The Name_Record is composed of Cmpct_Dir_Info and
463; Extend_Info. MAKE_NAME_RECORD will simply make a Name_Record
464; from the informations from DOS.
465; Input: Dir_Info, Extended_Info
466; Output:Name_Record
467;
468; 5:(UNFOLD_NAME_RECORD) - Inverse function of above. When Look_up
469; operation finishes, then unfold the Name_Record of the current_
470; node for DOS. If the Current_Node is a drive_cache_header,
471; then will just return.
472; Input: CS:Current_Node, ES, DI, BX set for the buffer
473; Output:ES:DI->Dir_Info, ES:BX->Extended_Info buffer in DOS.
474;
475; 6:(PACK_DIR_NAME) - At Look_up or Delete operation, DS:SI points
476; to the requested full path, for ex., "C:\DIR1.EXT\DIR2\FILE.EXT",
477; 0. This routine is smart enough to recognize ":","\" and 0 as
478; a delimeter and will parse until the next delimeter and leave
479; SI to the next delimeter found. Also, if it is a drive name
480; it will set SI to the "\" after ":" for consistency and
481; it will set BL to the drive letter.
482; The main function of this routine is "pack" the given directory
483; name into 11 bytes format. PACKED_NAME will be filled with
484; the result. For example, when it is called the first time,
485; DL = "C" and SI will point to "\" before DIR1.EXT.
486; The second time, PACKED_NAME will be filled with
487; "DIR1 EXT" and SI will points to "\" before "DIR2".
488; Likewize, if this routine is called the fourth time,
489; FILE.EXT has been parsed and DS:SI will points to 0.
490; When this routine is called again, then it will return
491; with carry signaling that it has reached the end.
492; The user is required to call this routine consequtively
493; until it returns with carry.
494; Input:
495; Output:
496;
497;*************************************************************************
498
499
500.pa
501.fo off
502;*************************************************************************
503;
504;SUBROUTINE: LOOK_UP
505;
506;INPUT: DS:SI -> path
507; ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN
508; ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN
509; CS:BP -> Matching Drive_cache_header
510;
511;OUTPUT:if found, DS:SI -> the last character of the path, i.e., 0.
512; ES:DI -> DIR_INFO
513; ES:CX -> Extended_INFO (explained in the data structure)
514; else if there exist the name cache for the drive, but could not
515; completely find the matching path,
516; DS:SI -> "\" following the directory that FASTOPEN can
517; find the match,
518; Will points to "\" after "d:" if no matching
519; root directory is found.
520; ES:DI -> Dir_Info of the subdirectory FASTOPEN
521; can find the match.
522; ES:CX -> the matching directory's Extended INFO
523; If cannot find the matching root directory entry, then
524; ES:DI, ES:BX are undetermined.
525; If the requested path is "D:\,0" then FASTOPEN will
526; return with carry flag set and, AX = 0ffffh.
527; else carry flag set and AX = 0FFFFh.
528;
529;GLOBAL VARIABLES:
530; CURRENT_NODE,
531; CURRENT_SIBLING,
532;
533;DESCRIPTION:
534; Save Dir_Info, Extended_Info buffer address in DOS.
535; Set ES to Name_Cache_Seg
536; SET_LRU;
537; 1:
538; Current_Node = BP
539; Current_Sibling = 0
540; PACK_DIR_NAME (from the path);
541; if CX = 0, then jmp to 3 /*Found*/;
542; Find_child (from the current_node);
543; if not found then jmp to 3
544; 2: Compare Packed_name with Child_pointer.CD_filename
545; if yes, then PRE_LRU_STACK; JMP to 1
546; else Find_Sibling;Current_sibling=Sibling_pointer
547; if found a sibling, then Current_Node = Current_Sibling
548; jmp to 2
549; else jmp to 3;
550; 3: UNFOLD_NAME_RECORD /*for the info packet to DOS */
551; Exit
552;
553;*************************************************************************
554
555
556.pa
557.fo off
558;*************************************************************************
559;
560;SUBROUTINE: INSERT
561;
562;INPUT: DS:DI -> DIR info
563; ES:BX -> Extended info
564;
565;OUTPUT:Automatic insertion based on CURRENT_NODE, CURRENT_SIBLING
566; If failed, then carry flag set and AX = 0FFFFh.
567; Insert operation handles only one file or subdirectory at a time.
568; So, usually insert operations are performed in a sequential manner.
569; A look up operation should be performed before any new sequential
570; insert operation.
571;
572;GLOBAL VARIABLES:
573; CURRENT_NODE,
574; CURRENT_SIBLING,
575;
576;DESCRIPTION:
577;
578; Make_Name_Record ;Make Name Record from the input
579; Get_Free_Node
580; Set_LRU ;(from TEMP_LRU_STACK)
581; if current_sibling <> 0 (or current_sibling=0FFh)
582; then Install as a sibling of Current_Node
583; else Install as a child under Current_Node;
584; Pre_LRU_stack ;(pre operation for LRU)
585; Exit
586;
587;*************************************************************************
588
589
590.pa
591.fo off
592;*************************************************************************
593;
594;SUBROUTINE: Delete
595;
596;INPUT: DS:SI -> d:path
597;
598;OUTPUT: If found, then remove the item from the Tree and from the
599; LRU chain. Move that slot to the Top of the LRU chain.
600;
601;GLOBAL VARIABLES:
602;
603;DESCRIPTION:
604; Look_Up
605; If ds:si -> 0, then Remove that entry from Tree, LRU chain,
606; Put that entry to the top of LRU chain
607; else AX = 0FFFFh, Carry set,
608; Exit
609;
610;*************************************************************************
611
612
613.fo
614:egdoc.
615
diff --git a/v4.0/src/CMD/FASTOPEN/FASTP.ASM b/v4.0/src/CMD/FASTOPEN/FASTP.ASM
new file mode 100644
index 0000000..561417c
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTP.ASM
@@ -0,0 +1,131 @@
1 PAGE 90,132 ;A2
2 TITLE fastp.asm - fastopen SYSTEM COMMAND LINE PARSER
3;****************** START OF SPECIFICATIONS *****************************
4; MODULE NAME: fastp.asm
5;
6; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT
7; configuration expected by the modules of fastopen.
8;
9;FUNCTION: The common code of the DOS command line PARSER is optimized by
10; the setting of certain switches that cause the conditional
11; assembly of only the required portions of the common PARSER.
12;
13; ENTRY POINT: SYSPARSE, near
14;
15; INPUT:
16; ES - has seg id of the SEGMENT
17; that contains the input control blocks,
18; defined below.
19;
20; DI - offset into ES of the PARMS INPUT BLOCK
21;
22; DS - has seg id of the SEGMENT
23; that contains the DOS input COMMAND
24; string, which is originally presented at 81h
25; in the PSP.
26;
27; SI - offset into DS of the text of the DOS input COMMAND string
28; as originally presented at 81H in the PSP.
29;
30; DX - zero
31;
32; CX - ordinal value, intially zero, updated on each subsequent call
33; to the value returned in CX on the previous call.
34;
35; CS - points to the segment containing the
36; INCLUDE PARSE.ASM statement
37;
38; DS - also points to the segment containing the INCLUDE
39; PARSE.ASM statement.
40;
41; EXIT-NORMAL: Output registers:
42; AX - return code:
43; RC_No_Error equ 0 ; No error
44; RC_EOL equ -1 ; End of command line
45;
46; DX - Offset into ES of the selected RESULT BLOCK.
47; BL - terminated delimiter code
48; CX - new operand ordinal
49; SI - set past scanned operand
50;
51; EXIT-ERROR: Output registers:
52; AX - return code:
53; RC_Too_Many equ 1 ; Too many operands
54; RC_Op_Missing equ 2 ; Required operand missing
55; RC_Not_In_SW equ 3 ; Not in switch list provided
56; RC_Not_In_Key equ 4 ; Not in keyword list provided
57; RC_Out_Of_Range equ 6 ; Out of range specified
58; RC_Not_In_Val equ 7 ; Not in value list provided
59; RC_Not_In_Str equ 8 ; Not in string list provided
60; RC_Syntax equ 9 ; Syntax error
61;
62; INTERNAL REFERENCES:
63; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM)
64;
65; DATA AREAS: none
66;
67; EXTERNAL REFERENCES:
68; ROUTINES: none
69;
70; DATA AREAS: control blocks pointed to by input registers.
71;
72; NOTES:
73;
74; For LINK instructions, refer to the PROLOG of the main module,
75; fastopen.asm.
76;
77; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
78;
79; COPYRIGHT: "MS DOS FASTOPEN Utility"
80; "Version 4.00 (C)Copyright 1988 Microsoft "
81; "Licensed Material - Property of Microsoft "
82;
83;PROGRAM AUTHOR: DOS 4.00 P L
84;
85;****************** END OF SPECIFICATIONS *****************************
86 IF1 ; ;AN000;
87 %OUT COMPONENT=fastopen, MODULE=fastp.asm...
88 ENDIF ; ;AN000;
89; = = = = = = = = = = = =
90 HEADER <MACRO DEFINITION> ; ;AN000;
91; = = = = = = = = = = = =
92
93HEADER MACRO TEXT ;; ;AN000;
94.XLIST
95 SUBTTL TEXT
96.LIST
97 PAGE ;; ;AN000;
98 ENDM ;; ;AN000;
99
100; = = = = = = = = = = = =
101 HEADER <SYSPARSE - SYSTEM COMMAND LINE PARSER> ; ;AN000;
102CSEG_INIT SEGMENT PARA PUBLIC 'CODE' ;
103 ASSUME CS:CSEG_INIT,DS:CSEG_INIT,ES:CSEG_INIT
104
105 PUBLIC SYSPARSE ;SUBROUTINE ENTRY POINT ;AN000;
106
107
108INCSW EQU 1 ;INCLUDE PSDATA.INC ;AN000;
109FARSW EQU 0 ;CALL THE PARSER BY NEAR CALL
110DATESW EQU 0 ;SUPPRESS DATE CHECKING ;AN000;
111TIMESW EQU 0 ;SUPPRESS TIME CHECKING ;AN000;
112FILESW EQU 0 ;SUPPRESS CHECKING FILE SPECIFICATION ;AN000;
113CAPSW EQU 0 ;SUPPRESS FILE TABLE CAPS ;AN000;
114CMPXSW EQU 1 ;SUPPRESS CHECKING COMPLEX LIST
115DRVSW EQU 1 ;SUPPRESS SUPPORT OF DRIVE ONLY FORMAT
116QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT ;AN000;
117NUMSW EQU 1 ;SUPPRESS CHECKING NUMERIC VALUE
118KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT ;AN000;
119SWSW EQU 1 ;DO SUPPORT SWITCHES ;AN000;
120VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 ;AN000;
121VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 ;AN000;
122VAL3SW EQU 0 ;DO SUPPORT VALUE DEFINITION 3
123
124
125 IF1 ; ;AN000;
126 %OUT COMPONENT=fastopen, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM...
127 %OUT COMPONENT=fastopen, SUBCOMPONENT=PARSE, MODULE=PSDATA.INC...
128 ENDIF ; ;AN000;
129 INCLUDE PARSE.ASM ; ;AN000;
130CSEG_INIT ENDS ;
131 END ; ;AN000;
diff --git a/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM b/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM
new file mode 100644
index 0000000..90b9118
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM
@@ -0,0 +1,2944 @@
1 Page 84,132 ;
2Title FASTOPEN
3
4;--------------- INCLUDE FILES -----------------
5.xcref
6.xlist
7debug=0 ;this is an equate only for DOSMAC.inc
8INCLUDE DOSMAC.inc
9.list
10.cref
11INCLUDE dirent.inc
12INCLUDE fastsegs.inc ; Cannot declare this in DOS includes
13INCLUDE fastopen.inc ; This include file also contains DOS equates
14
15
16CSEG_MAIN SEGMENT PARA PUBLIC 'CODE' ; Cseg_Seek segment
17
18EXTRN VECTOR_DELETE:dword ; jump vector inside Cseg_Seek to make
19 ; a FAR call to FSeek Delete function within
20 ; the segment
21
22CSEG_MAIN ENDS
23
24
25;*****************************************************************************
26; ALL FastSeek functions are kept in a seperate segment. They are accessed
27; by a FAR indirect call from the MAIN routine.
28
29; ADDRESSABILTY: DS is for accessing local data in Cseg_Seek segment
30; ES is for accessing data in the extent cache buffer
31; in the Cseg_Init segment
32; On entry, only DS is set, ES is set to Cache segment later
33;*****************************************************************************
34
35CSEG_SEEK SEGMENT PARA PUBLIC 'code'
36 assume cs:cseg_seek,ds:nothing,es:nothing,ss:nothing
37
38PUBLIC Seek_name_cache_seg ;AN000;
39PUBLIC Seek_Num_Of_drives
40PUBLIC Seek_extent_drive_Buff ;AN000;
41PUBLIC Seek_Total_Ext_Count ;AN000;
42PUBLIC Seek_Total_Name_Count ;AN000;
43PUBLIC Seek_Name_Drive_Buff ;AN000;
44PUBLIC Seek_Name_Cache_Buff ;AN000;
45PUBLIC End_Seek
46PUBLIC Check_Flag
47 ;AN000;
48PUBLIC Fk_Open
49PUBLIC Fk_Close ;AN000;
50PUBLIC Fk_Insert ;AN000;
51PUBLIC Fk_Delete
52PUBLIC Fk_Lookup ;AN000;
53PUBLIC Fk_Truncate
54PUBLIC Fk_Purge
55
56
57;;---------- FASTSEEK LOCAL VARIABLES ---------------------
58
59First_Phys_ClusNum dw 0 ; first phys clus num of file (file id) ;AN000;
60Logical_ClusNum dw 0 ; logical cluster num to be searched ;AN000;
61Physical_ClusNum dw 0 ; physical clus num of above logical clus num ;AN000;
62Extent_buff_Ptr dw 0 ; starting offset of extent cache ;AN000;
63drv_id db -1 ; drive id of last fastseek function
64func_cod db 0 ; function code
65
66Cur_Hdr_Ptr dw 0 ; address of current header ;AN000;
67Cur_Extn_Ptr dw 0 ; address of current extent ;AN000;
68New_Extn_Ptr dw 0 ; address of area where new extent will be created
69New_Hdr_Ptr dw 0 ; address of area where new header will be created ;AN000;
70Prev_Hdr_Ptr dw 0 ; address of previous header ;AN000;
71Prev_Extn_Ptr dw 0 ; address of previous extent ;AN000;
72
73Prev_MRU_Extn_Ptr dw 0 ; address of previous MRU extent ;AN000;
74LRU_Prev_Hdr dw 0 ; address of previous hdr to the LRU header ;AN000;
75LRU_Prev_Extent dw 0 ; address of previous extent to LRU extent ;AN000;
76LRU_Extent dw 0 ; address of LRU extent ;AN000;
77LRU_Hdr dw 0 ; address of LRU header ;AN000;
78
79Drive_Hdr_Ptr dw 0 ; address of drive header of current drive ;AN000;
80From_FreeBuff dw 0 ; 1 = if call from Free_Buff routine ;AN000;
81Hdr_Flag dw 0 ; 1 = current header is the only
82 ; remaining header in Queue
83Extn_Flag dw 0 ; 1 = current extent is the only ;AN000;;AN000;
84 ; remaining extent under this header
85Fully_Flag dw 0 ; 1= cluster fully found in extent ;AN000;;AN000;
86 ; 0= cluster partially found
87Find_Flag dw 0 ; # = specifies the relative location of the new cluster ;AN000;
88Open_Queue_Flag dw 0 ; 1 = if open queue is empty ;AN000;
89Free_Flag dw 0 ; Free area Type: 0 - continuous ;AN000;
90 ; 1 - non-continuous
91Queue_Type dw 0 ; Queue Type: 0 - Open Queue ;AN000;
92 ; 1 - Close Queue
93phys_num dw 0 ; ** for queue analyser
94logic_num dw 0 ; ** for queue analyser
95
96
97; Following data area is initialized during initialization
98Check_Flag dw 0
99Seek_name_cache_seg dw Cseg_Init ; Seg ID of Ccahe buffer
100Seek_Num_Of_drives dw 0 ; number of drives ;AN000;
101Seek_Total_Name_Count dw 0 ; total name count
102Seek_Total_Ext_Count dw 0 ; total extent count
103Seek_Name_Drive_Buff dw 0 ; starting address of name drive buffers ;AN000;
104Seek_Name_Cache_Buff dw 0 ; starting address of name cahe buffers ;AN000;
105Seek_extent_drive_Buff dw 0 ; starting address of extent ;AN000;
106 ; cache in the cache buffer
107
108
109
110
111;-------------------------------------------------------------------------------
112;-------------------------------------------------------------------------------
113; PROCEDURE: FK_OPEN
114;
115; FUNCTION: Create and initialize a file header using the starting
116; Physical Cluster number (file id) of the file.
117;
118; If the file header already exist in the OPEN Queue, then increase
119; the file reference count by one and make the header
120; MRU header.
121;
122; If header is not found in the OPEN Queue, then check to
123; see if it exists in the CLOSE Queue. If found in the
124; CLOSE Queue, move the header and the extents to the top of
125; OPEN Queue and make the header MRU header.
126;
127; If the header is not found in both Queues, create a new
128; header at the top of the OPEN Queue and initialize with the
129; given first physical cluster number.
130;
131; If not enough space for new header in OPEN Queue, find the
132; LRU header and Last Exetent in the CLOSED Queue. Delete this
133; extent and use the space for the new header. If none in
134; CLOSE Queue, find the LRU header and the LRU extent in the
135; OPEN Queue. Delete this extent and use this space.
136;
137;
138; INPUT: CX = First Physical Cluster Number of the file
139; DL = Drive ID
140;
141;
142; OUTPUT: Created a new file header. If header already exist, then the file
143; reference count is incremented by one.
144;
145; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header
146;
147; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
148; "Version 4.00 (C) Copyright 1988 Microsoft"
149; "Licensed Material - Property of Microsoft "
150;
151;-------------------------------------------------------------------------------
152
153
154FK_OPEN PROC FAR
155
156 push cs ; establish addressability ;AN000;
157 pop ds ; DS --> code segment ;AN000;
158 assume ds:Cseg_Seek ;AN000;
159 mov es, Seek_Name_Cache_Seg ; setup cache buff segment ;AN000;
160 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
161 mov First_Phys_Clusnum,cx ; save physical cluster number ;AN000;
162 mov func_cod,al
163
164;-------------------------------------------------------------------------------
165; Search for Drive header in the cache buffer using Drive ID in DL
166;-------------------------------------------------------------------------------
167 CALL FIND_DRIVE_HEADER ; get drive buffer Header ;AN000;
168 ; DI-->drive header
169 jnc open_Search_Header ; header found - check for file header ;AN000;
170 jmp open_exit ; drive header not found - exit ;AN000;
171
172;------------------------------------------------------------------------------
173; Check if both OPEN and CLOSE Queues are empty. If empty, create a new
174; file header at the top of OPEN Queue. If there are headers, search OPEN
175; queue. If found, increment file count by one. If not found, check if
176; the file header exists in CLOSE Queue. If found, move header to the
177; top of the OPEN Queue.
178;------------------------------------------------------------------------------
179Open_Search_Header:
180 inc es:[di].Extent_Count ; increment sequence count ( DEBUG)
181 mov ax,es:[di].Buff_Size ; total buffer size equal ;AN000;
182 cmp es:[di].Free_Size,ax ; to current free area ;AN000;
183 jne Search_Open_List ; yes, check OPEN and CLOSE Queues ;AN000;
184 ; for header
185 jmp Open_Make_Hdr ; no, make new header ;AN000;
186
187
188;------------------------------------------------------------------------------
189; Search for header in the OPEN Queues. If found, increment file reference
190; count by one.
191;------------------------------------------------------------------------------
192
193Search_Open_List:
194 mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000;
195 mov si,es:[di].MRU_Hdr_Ptr ;AN000;
196 cmp si, -1 ; Any header in OPEN Queue ?? ;AN000;
197 je Open_Chk_Close_list ; none, check CLOSE Queue ;AN000;
198
199 CALL FIND_FILE_HEADER ; search header in OPEN Queue ;AN000;
200 jc Open_chk_CLOSE_list ; if not found check in CLOSE Queue ;AN000;
201
202;------------------------------------------------------------------------------
203; Found in the OPEN Queue. Now, increment the file reference count by one
204; and also make the header MRU header. If header found is LRU header then
205; make previous header LRU header. If header is not LRU header, connect
206; previous header to next header. If the header is the first header in the
207; Queue, dont make it to MRU header since it is already at the top of Queue.
208;------------------------------------------------------------------------------
209 ; DI-->Header found
210 inc es:[di].FH_refer_Count ; increment file reference count ;AN000;
211 cmp Hdr_Flag, 1 ; current header Single header ?? ;AN000;
212 jne Open_Chk_Last_Hdr ; No, Check for last header ;AN000;
213 clc ; make sure caary is clear
214 jmp Open_Exit ; yes, exit ;AN000;
215
216Open_Chk_Last_Hdr:
217 cmp Hdr_Flag, 3 ; current header LRU header ?? ;AN000;
218 jne Open_Join_Gap ; no, close the gap ;AN000;
219
220Mark_Previous_Hdr: ; yes - mark previous hdr
221 mov si, Prev_Hdr_Ptr ;AN000;
222 mov es:[si].FH_Next_Hdr_Ptr,-1 ; yes, Mark previous Hdr LRU hdr ;AN000;
223
224; Make current Hdr MRU header. No need to close the gap
225 CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000;
226 clc ; make sure caary is clear
227 jmp Open_Exit ; then EXIT ;AN000;
228
229
230;-----------------------------------------------------------------------------
231; Comes here if current header is first of many headers or in between a previous
232; and next header. Make current header MRU header and close the gap.
233;-----------------------------------------------------------------------------
234Open_Join_Gap:
235 ; DI-->Current header
236 cmp Hdr_Flag, 2 ; current Header First Hdr in Queue ?? ;AN000;
237 jne Open_Make_MRU_Hdr ; no, jump ;AN000;
238 clc ; MAKE SURE caary is clear
239 jmp Open_Exit ; yes, no need to make MRU hdr, or ;AN000;
240 ; or close the gap
241
242Open_Make_MRU_Hdr: ; header is between 1st and last headers
243 CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000;
244
245 clc ; make sure caary is clear
246 jmp Open_exit ; then EXIT ;AN000;
247
248
249;------------------------------------------------------------------------------
250; Look for a header in the CLOSE Queue. If found, move file header and
251; and extents (if any) to top of OPEN Queue. If not found in the CLOSE
252; queue, create a new header at the top of OPEN queue.
253;------------------------------------------------------------------------------
254Open_Chk_Close_List:
255 mov di,drive_Hdr_Ptr ; DI-->current drive header ;AN000;
256 cmp es:[di].CLOSE_Ptr,-1 ; anything in CLOSE Queue ?? ;AN000;
257 jne open_search_hdr ; if any, search CLOSE Queue ;AN000;
258 jmp open_make_hdr ; if none, make a new header ;AN000;
259
260
261;------------------------------------------------------------------------------
262; CLOSE Queue is not empty, next search for header in the CLOSE Queue using
263; starting physical cluster number of the file.
264;------------------------------------------------------------------------------
265Open_Search_Hdr: ;
266 mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000;
267 ; in the CLOSE Queue ;AN000;
268 mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000;
269 CALL FIND_FILE_HEADER ; find file header in CLOSE Queue ;AN000;
270 ; DI-->header found
271 jnc open_chk_only_hdr ; if found, check only header ;AN000;
272 jmp short open_make_hdr ; if not, make a new header ;AN000;
273
274;------------------------------------------------------------------------------
275; Found header in the CLOSE Queue. Check if the header found is the single HDR
276; in the CLOSE Queue, If single header, then, mark the CLOSE Queue as empty
277; before copy the this header to the OPEN Queue.
278;------------------------------------------------------------------------------
279Open_Chk_only_Hdr: ;
280 cmp Hdr_flag, 1 ; Only Header in the CLOSE Queue?? ;AN000;
281 jne Open_chk_Last_header ; if not check header is LRU header ;AN000;
282
283 mov di,Drive_Hdr_Ptr ; only header in the CLOSE Queue ;AN000;
284 mov es:[di].Close_Ptr,-1 ; mark CLOSE Queue as empty ;AN000;
285 jmp short Open_Move_Hdr ; then move header to OPEN Queue ;AN000;
286
287;------------------------------------------------------------------------------
288; Current header is not the only header in the CLOSE Queue. Now check if the
289; current header is the LRU header in CLOSE Queue. If true, mark previous
290; header as LRU header before moving it from from CLOSE Queue to OPEN queue.
291;------------------------------------------------------------------------------
292Open_Chk_Last_Header: ;
293 cmp Hdr_Flag, 3 ; Current header last header ?? ;AN000;
294 jne Open_Close_gap ; no, close the gap before move it ;AN000;
295 ; to OPEN Queue
296 mov si, Prev_Hdr_Ptr ;AN000;
297 mov es:[si].Fh_Next_Hdr_Ptr,-1 ; yes, mark the previous hdr as last ;AN000;
298 jmp short open_move_Hdr ; header then move to the top of ;AN000;
299 ; OPEN Queue
300
301;------------------------------------------------------------------------------
302; Close the gap in the CLOSE Queue.
303;------------------------------------------------------------------------------
304Open_Close_Gap:
305 mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000;
306 CALL JOIN_PREV_TO_NEXT ; join previous header to next header ;AN000;
307
308;------------------------------------------------------------------------------
309; Now move the current header from CLOSE Queue to top of OPEN Queue
310;------------------------------------------------------------------------------
311Open_Move_Hdr:
312 mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000;
313 mov di,drive_Hdr_Ptr ; DI-->drive header ;AN000;
314
315;------------------------------------------------------------------------------
316;Update the file refernce count to 1 before move header to OPEN Queue
317;------------------------------------------------------------------------------
318 mov es:[si].FH_Refer_Count, 1 ; set refernce count = 1 ;AN000;
319 mov ax,es:[di].MRU_Hdr_Ptr ; address of current MRU header ;AN000;
320 mov es:[si].FH_Next_Hdr_Ptr,ax ; connect new header to the ;AN000;
321 ; current MRU header
322 mov es:[di].MRU_Hdr_Ptr,si ; make the header MRU header ;AN000;
323 clc ;AN000;
324 jmp short open_exit ; then exit. ;AN000;
325
326;------------------------------------------------------------------------------
327; If header is not found in both OPEN and CLOSE Queues, then make a new
328; header in the next available free area and initialize the new header and
329; make it MRU header (mov it to the top of the OPEN Queue).
330; If no free space to create a new header, get space from CLOSE Queue.
331; If none in CLOSE Queue, then get space from from OPEN Queue. See the
332; Procedure (Find_Free_Buffer )
333;------------------------------------------------------------------------------
334Open_Make_Hdr:
335
336 CALL MAKE_NEW_HEADER ; create new header ;AN000;
337 clc ;AN000;
338
339Open_exit:
340 CALL Check_it
341 ret ; return ;AN000;
342
343Fk_Open endp
344
345
346
347
348
349
350
351;--------------------------------------------------------------------------
352; PROCEDURE: FK_CLOSE
353;
354; FUNCTION: Search for the header on OPEN Queue. If the header is found,
355; decrement the file reference count by one. If the resultant
356; count is zero, then move the header and the extents under it
357; to the CLOSE Queue. If not, make the header MRU header in the
358; OPEN Queue.
359;
360; INPUT: DL = Drive Number
361; CX = First Physical Cluster Number of the file
362;
363; OUTPUT: Moved the file header and the extents to the close Queue
364;
365; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header
366;
367; REVISION HISTORY: New (5/87)
368;
369; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
370; "Version 4.00 (C) Copyright 1988 Microsoft"
371; "Licensed Material - Property of Microsoft "
372;
373;---------------------------------------------------------------------------
374
375FK_CLOSE PROC FAR
376 ;AN000;
377; Search for Drive header in the Cache buffer using Drive ID in DL
378 push cs ; establish addressability ;AN000;
379 pop ds ; DS --> code segment ;AN000;
380 assume ds:Cseg_Seek ;AN000;
381 mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000;
382 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
383 mov First_Phys_Clusnum, CX ; save phys cluster number ;AN000;
384 mov func_cod,al
385
386 CALL FIND_DRIVE_HEADER ; search for drive header
387 ; DI-->Current drive buffer
388 jnc Close_search_hdr ; found, search for file header ;AN000;
389 clc ; MAKE SURE carry is clear
390 jmp Close_Exit ; not found, error ;AN000;
391
392;--------------------------------------------------------------------------
393; Search for file header in the OPEN Queue using given physical cluster number
394;--------------------------------------------------------------------------
395Close_Search_Hdr:
396 inc es:[di].Extent_Count ; increment sequence coutn (DEBUG)
397 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN Queue ;AN000;
398 mov cx,First_Phys_Clusnum ; CX = First phys clus num ;AN000;
399 CALL FIND_FILE_HEADER ; find the header in OPEN Queue
400 ; DI-->header found ;AN000;
401 jnc Close_Chk_Last_Hdr ; jump if header found ;AN000;
402 clc ; clear carry ;AN000;
403 jmp short close_exit ; headr not found - exit ;AN000;
404
405;--------------------------------------------------------------------------
406; Check if the header found is the only header in the OPEN Queue. If true
407; go and decrement file reference count by one.
408;--------------------------------------------------------------------------
409Close_Chk_Last_Hdr:
410 cmp Hdr_Flag, 1 ; Only header in the Queue ?? ;AN000;
411 je Dec_Ref_Count ; yes - decrement count, if count =0 ;AN000;
412 ; then move to the top of CLOSE Queue
413 cmp Hdr_Flag, 3 ; no - Last Header in the CLOSE Queue?? ;AN000;
414 jne Close_Join_Hdr ; no, close gap ;AN000;
415 mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000;
416 mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000;
417 jmp short Dec_Ref_Count ; decrement count and move to ;AN000;
418 ; CLOSE Queue
419
420;--------------------------------------------------------------------------
421; Connect previous header to next header to close the gap in OPEN Queue
422;--------------------------------------------------------------------------
423Close_Join_Hdr:
424 mov si,Cur_Hdr_Ptr ; SI-->Current header
425 dec es:[si].FH_Refer_Count ; decrement fiel refernce count
426 cmp es:[si].FH_Refer_Count,0 ; count = 0 ??
427 jne Close_Make_MRU ; no - make current header MRU header
428
429 mov Queue_Type, 0 ; else set flag to indicate OPEN Queue ;AN000;
430 CALL JOIN_PREV_TO_NEXT ; close gap before move to CLOSE queue ;AN000;
431 jmp short move_to_Close_List ; move header to CLOSE queue
432
433;--------------------------------------------------------------------------
434; Decrement the reference count by one. If count = 0, then move the header to
435; the top of CLOSE Queue. Else, dont move to CLOSE queue, since the file has
436; have multiple open before. In this case make the header MRU header in the
437; OPEN queue.
438;--------------------------------------------------------------------------
439Dec_Ref_Count:
440 mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000;
441 dec es:[si].FH_Refer_Count ; decrement refernece count ;AN000;
442 cmp es:[si].FH_Refer_Count,0 ; reference count = 0 ?? ;AN000;
443 je Move_to_Close_List ; yes, move header to CLOSE Queue ;AN000;
444
445;--------------------------------------------------------------------------
446; Else, move current Header to top of OPEN Queue. Move to the top of the queue
447; only if the header is not the first header in the queue.
448;--------------------------------------------------------------------------
449Close_Make_MRU:
450 cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000;
451 je Dont_Move_To_Top ; yes, dont move to top ;AN000;
452
453 CALL MAKE_MRU_HEADER ; move header to top of queue ;AN000;
454
455Dont_Move_To_Top:
456 clc ;AN000;
457 jmp short Close_Exit ; exit ;AN000;
458
459
460;--------------------------------------------------------------------------
461; Move header to the top of the CLOSE Queue. If the header is the only header
462; header in the OPEN Queue, mark OPEN Queue empty.
463;--------------------------------------------------------------------------
464Move_To_Close_List:
465 mov si,Cur_Hdr_Ptr ; SI-->Cur_Hdr_Ptr ;AN000;
466 cmp hdr_flag,1 ; single header in the Queue ?? ;AN000;
467 jne Join_To_Close_List ; no, move header to CLOSE queue ;AN000;
468 mov di,Drive_Hdr_Ptr ;AN000;
469 mov es:[di].MRU_Hdr_Ptr, -1 ; else mark OPEN Queue empty ;AN000;
470
471Join_To_Close_List:
472 mov di,Drive_Hdr_Ptr ; DI-->current drive header ;AN000;
473 mov ax,es:[di].Close_Ptr ; connect current header to the ;AN000;
474 mov es:[si].FH_Next_Hdr_Ptr,ax ; previous first hdr in CLOSE queue ;AN000;
475 mov es:[di].Close_Ptr,si ; make the current header first
476 ; header in the CLOSE queue
477 clc ;AN000;
478
479Close_Exit:
480 CALL Check_it
481 ret ; return ;AN000;
482
483FK_CLOSE ENDP
484
485
486
487
488
489
490;------------------------------------------------------------------------
491;
492; PROCEDURE: FK_DELETE
493;
494; FUNCTION: Delete a specific header and extents under the header
495; and release the buffers to the FREE pool
496;
497; Search OPEN Queue for file header. If found, delete header and
498; extents and release the buffer to FREE area. If not found in OPEN
499; queue, search CLOSE Queue. If found, delete header and extents
500; under the header and release the area to FREE area.
501;
502; INPUT: CX = First Physical Cluster Number of the file
503; DL = drive id
504;
505; OUTPUT: The file header and the extents are deleted
506;
507; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header
508;
509; REVISION HISTORY: New (5/87)
510;
511; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
512; "Version 4.00 (C) Copyright 1988 Microsoft"
513; "Licensed Material - Property of Microsoft "
514;
515;-------------------------------------------------------------------------
516
517FK_DELETE PROC FAR
518
519 push cs ; establish addressability ;AN000;
520 pop ds ; DS --> code segment ;AN000;
521 assume ds:Cseg_Seek ;AN000;
522 mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000;
523 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
524 mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000;
525 mov func_cod,al
526
527;--------------------------------------------------------------------------
528; If the delete call is from Free_Buff, then go straight to file header
529; search. Else usual delete request from DOS
530;--------------------------------------------------------------------------
531 cmp From_FreeBuff,1 ; call from Free_Buff routine ??
532 je Del_Search_Close_List ; yes - find file header in CLOSE queue
533
534;--------------------------------------------------------------------------
535; Search for Drive Cache buffer using Drive ID in DL
536;--------------------------------------------------------------------------
537 CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000;
538 jnc Delete_search_hdr ; found, search for file header ;AN000;
539 jmp Delete_Exit ; not found, error ;AN000;
540
541;--------------------------------------------------------------------------
542; Search for a header in the OPEN Queue using given physical cluster number
543;--------------------------------------------------------------------------
544Delete_Search_Hdr:
545 inc es:[di].Extent_Count ; ;***;
546 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000;
547 ; in the OPEN queue ;AN000;
548 cmp si, -1 ; any header in OPEN Queue ?? ;AN000;
549 je Del_search_Close_list ; none, search CLOSE queue ;AN000;
550 mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000;
551 CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000;
552 jnc Del_Open_Last_Hdr ; if found, jump ;AN000;
553
554
555;--------------------------------------------------------------------------
556; Not found in OPEN queue. Search in CLOSE queue
557;--------------------------------------------------------------------------
558Del_Search_Close_List:
559 mov di,Drive_Hdr_Ptr ;AN000;
560 mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000;
561 ; in the CLOSE queue
562 cmp si, -1 ; anything in CLOSE Queue ?? ;AN000;
563 jne Del_scan_close_list ; yes, jump ;AN000;
564 clc ; none, header not found ;AN000;
565 jmp delete_exit ; exit ;AN000;
566
567Del_Scan_Close_List:
568 mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000;
569 CALL FIND_FILE_HEADER ; find the header in CLOSE queue ;AN000;
570 ;AN000;
571 jnc Del_Close_last_hdr ; if found, chk if this header ;AN000;
572 ; is the last header in CLOSE queue
573 clc ; else, set header not found ;AN000;
574 jmp delete_exit ; and then exit ;AN000;
575
576
577;-------------------------------------------------------------------------
578; Header found in CLOSE queue. Check header found is the only single
579; header left in the queue.
580;-------------------------------------------------------------------------
581Del_Close_Last_Hdr:
582 cmp Hdr_Flag, 1 ; Single Header in CLOSE Queue ?? ;AN000;
583 jne Del_Chk_LRU_Hdr ; no, check for LRU header ;AN000;
584
585;--------------------------------------------------------------------------
586; Yes, single header in the queue, make CLOSE_PTR empty before delete the
587; header from the queue.
588;--------------------------------------------------------------------------
589 mov di,Drive_Hdr_Ptr ;AN000;
590 mov es:[di].Close_Ptr, -1 ; mark CLOSE_Ptr as empty ;AN000;
591 jmp short delete_Free_Buff ; release the deleted header ;AN000;
592
593Del_Chk_LRU_Hdr:
594 cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000;
595 jne Del_Join_Hdr ; no, close gap ;AN000;
596 mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000;
597 mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000;
598 jmp short delete_Free_Buff ; release the deleted header ;AN000;
599
600;--------------------------------------------------------------------------
601; Connect previous header to next header to close the gap in CLOSE Queue
602;--------------------------------------------------------------------------
603Del_Join_Hdr:
604 mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000;
605 CALL JOIN_PREV_TO_NEXT ; close gap ;AN000;
606 ;AN000;
607 jmp short Delete_Free_Buff ; release header to FREE area ;AN000;
608
609
610
611;-------------------------------------------------------------------------
612; Header found in OPEN queue. Check header found is the only single
613; header left in the queue.
614;-------------------------------------------------------------------------
615Del_Open_Last_Hdr:
616 cmp Hdr_Flag, 1 ; Single Header in OPEN Queue?? ;AN000;
617 jne Del_Chk_Opn_LRU_Hdr ; no, check for LRU header ;AN000;
618
619;--------------------------------------------------------------------------
620; Yes, single header in the queue, mark OPEN Queue empty before delete
621;--------------------------------------------------------------------------
622; the header from the queue.
623 mov di,Drive_Hdr_Ptr ;AN000;
624 mov es:[di].MRU_Hdr_Ptr, -1 ; mark OPEN Queue as empty ;AN000;
625 jmp short delete_Free_Buff ; release the delete header ;AN000;
626
627Del_Chk_OPN_LRU_Hdr:
628 cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000;
629 jne Del_Opn_Join_Hdr ; no, close gap ;AN000;
630 mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000;
631 mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000;
632 jmp short Delete_Free_Buff ; release header to FREE area ;AN000;
633
634;--------------------------------------------------------------------------
635; Connect previous header to next header to close the gap in OPEN queue
636;--------------------------------------------------------------------------
637Del_Opn_Join_Hdr:
638 mov Queue_Type, 0 ; set flag to indicate OPEN Queue ;AN000;
639 CALL JOIN_PREV_TO_NEXT ; close gap ;AN000;
640 ;AN000;
641
642;----------------------------------------------------------------------------
643; Header and extends found. Mark the beginning of this free area with "-2".
644; Connect this header to the FREE area. Mark all extnts under this header
645; and chain them together through the 4th word. Connect the last extent to
646; the OLD free area. This process will effectively release the header to the
647; FREE area. Finally update the FREE area size in the Drive header.
648;
649; NOTE: The deleted buffers have size same as the size of a header or extent.
650; Each buffers first location contains a marker (-2) to indicate that
651; the buffer is a discontinuous buffer. Each discontinuos buffer is
652; connected to the next discontinuous buffer through the 4TH word.
653;---------------------------------------------------------------------------
654
655Delete_Free_buff:
656 mov di,Drive_Hdr_Ptr ; SI-->drive header ;AN000;
657 mov si,Cur_Hdr_Ptr ; DI-->current header ;AN000;
658
659;-------------------------------------------------------------------------
660; Put (-2) in the beginning of the released area to indicate that this is
661; a discontinuous free area. Each Free area is 8 bytes which is same size
662; as an extent or header.
663;-------------------------------------------------------------------------
664 mov ax,-2 ;AN000;
665 mov es:[si], ax ;AN000;
666 cmp es:[si].FH_Next_Extn_Ptr, -1 ; any extents under this header ?? ;AN000;
667 jne del_look_extent ; yes, jump ;AN000;
668
669;-------------------------------------------------------------------------
670; There is no extents under this header. Connect relased header to the
671; Free area and update Free area size in drive header before exit.
672;-------------------------------------------------------------------------
673 mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000;
674 mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000;
675 mov ax,es:[di].Free_Ptr ; connect current header ;AN000;
676 mov es:[si].FH_Next_Hdr_Ptr, ax ; to the Free AREA ;AN000;
677 mov es:[di].Free_Ptr,si ;AN000;
678 mov cx, SIZE File_Header ; start with file header size ;AN000;
679 mov di,Drive_Hdr_Ptr ;AN000;
680 add es:[di].Free_Size,cx ; update free area size ;AN000;
681 clc ; make sure caary is clear
682 jmp short Delete_Exit ; Then exit ;AN000;
683
684
685;-------------------------------------------------------------------------
686; Yes, one or more extents under this header. Connect the header to the
687; the first extent through 4th word (FH_Next_Hdr_Ptr). Subsequent free
688; extents are connected through the 4th word (EH_Next_Extn_Ptr). Next calculate
689; the size of the header and possible extendta and update the free area
690; size in the drive header.
691;-------------------------------------------------------------------------
692Del_Look_Extent:
693 mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000;
694 mov ax, -2 ; mark header as discontinuous ;AN000;
695 mov es:[si],ax ; free area (12/28) ;AN000;
696 mov cx, SIZE File_Header ; start with file header size ;AN000;
697
698 mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under this hdr ;AN000;
699 mov es:[si].FH_Next_Hdr_Ptr,ax ; connect this header to first extnt ;AN000;
700 ; through the 4th word ;AN000;
701 mov si,ax ; SI-->First extent ;AN000;
702 mov ax, -2 ; mark first extent as discontinous ;AN000;
703 mov es:[si],ax ; free area ;AN000;
704
705Delete_Loop:
706 add cx, SIZE Extent_Header ; add size of extent ;AN000;
707 cmp es:[si].EH_Next_Extn_Ptr, -1 ; current extent last extent ? ;AN000;
708 je Del_Update_Free_Size ; yes - jump (12/28) ;AN000;
709 mov ax,es:[si].EH_Next_Extn_Ptr ; get pointer to next extent ;AN000;
710 mov es:[si].FH_Next_Hdr_Ptr,ax ; connect curr ext to next extent ;AN000;
711 mov si,ax ; SI-->next extent ;AN000;
712 mov ax, -2 ; mark subsequent extents as ;AN000;
713 mov es:[si],ax ; discontinuous free areas ;AN000;
714 jmp Delete_Loop ; adding the size until last extent ;AN000;
715
716Del_Update_Free_Size:
717 mov di,Drive_Hdr_Ptr ;AN000;
718 add es:[di].Free_Size,cx ; update free area in drive header ;AN000;
719 ;AN000;
720; At this point SI-->Last extent
721 mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000;
722 mov ax,es:[di].Free_Ptr ;AN000;
723 mov es:[si].FH_Next_Hdr_Ptr,ax ; connect last extent under this ;AN000;
724 ; header to the Free area
725 mov ax,Cur_Hdr_Ptr ; AX-->Current header ;AN000;
726 mov es:[di].Free_Ptr,ax ; connect header being deleted to ;AN000;
727 ; the free pool ;AN000;
728Delete_Exit:
729 clc
730 cmp check_flag,0
731 jne open_chk_Que
732 clc
733 ret
734Open_Chk_Que:
735 CALL Check_it
736 ret ; exit ;AN000;
737
738FK_DELETE ENDP
739
740
741
742
743
744
745
746
747;--------------------------------------------------------------------------
748; PROCEDURE: FK_INSERT
749;
750; FUNCTION: Search for a specific extent using the starting physical
751; cluster number and the given logical cluster number.
752; Insert the given physical cluster number in the extent
753; indexed by the given logical cluster number. If extent is
754; not found, create a new extent. If free space is not
755; available, take free space free CLOSE or OPEN Queue.
756;
757; INPUT DL = drive number
758; CX = First Physical Cluster Number of the file
759; BX = Logical Cluster Number
760; DI = Physical Cluster Number
761;
762; OUTPUT: Physical cluster number is inserted. If extent is not found,
763; a new file is created
764;
765; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_LRU_Header
766;
767; REVISION HISTORY: New (5/87)
768;
769;------------------------------------------------------------------------
770
771FK_INSERT PROC FAR
772 push cs ; Establish addressability ;AN000;
773 pop ds ; DS --> code segment ;AN000;
774 assume ds:Cseg_Seek ;AN000;
775 mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000;
776 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
777
778 mov first_phys_clusNum,cx ; save cluster numbers ;AN000;
779 mov Logical_ClusNum,bx ;AN000;
780 mov Physical_ClusNum,di ;AN000;
781 mov func_cod,al
782
783; Search for Drive Cache buffer using Drive ID in DL
784 CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000;
785 jnc Insert_Search_Hdr ; found, search for file header ;AN000;
786 jmp Insert_Exit ; not found, error ;AN000;
787
788;--------------------------------------------------------------------------
789; If there are no free buffers and there is only a single header in the
790; OPEN queue then there is no headers in the CLOSE queue, then the new
791; clusters wont be insterted. This is because, file header should not consume
792; its own extent if no free space is available.
793;--------------------------------------------------------------------------
794Insert_Search_Hdr:
795 inc es:[di].Extent_Count ; increment sequence count (DEBUGGING)
796 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN queue ;AN000;
797 cmp es:[si].FH_Next_Hdr_Ptr, -1 ; only one header in OPEN queue??
798 je insert_chk_buff ; yes - check free buffer
799 jmp short insert_Inc_count ; no - go and insert clusters
800
801Insert_Chk_Buff:
802 cmp es:[di].Free_Size, 0 ; any free buffers ??
803 jne Insert_Inc_Count ; yes - go insert clusters
804 cmp es:[di].Close_Ptr, -1 ; any headers in close queue?? (1/7/88 ;AN000;
805 jne Insert_Inc_Count ; yes - go insert clusters
806 clc ; no - dont insert clusters
807 jmp Insert_Exit ; exit
808
809insert_Inc_Count:
810 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the OPEN queue ;AN000;
811 mov cx,first_phys_clusnum ; CX = physical cluster number ;AN000;
812 CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000;
813 ; DI-->Header
814 jc Insert_Make_Hdr ; header not found, make new header ;AN000;
815 jmp Insert_Find_extent ; header is found, now go and ;AN000;
816 ; search for the extent
817
818;--------------------------------------------------------------------------
819; If header not found, create a new header in the free area and connect it
820; to the top of the OPEN queue. Mark the new header with no extents. Insert
821; the first logical and physical cluster number into the header. At this
822; point CX=First Physical Cluster number.
823;--------------------------------------------------------------------------
824Insert_Make_Hdr:
825 CALL MAKE_NEW_HEADER ; make a new header at the top ;AN000;
826 ; top of the queue
827;--------------------------------------------------------------------------
828; Now the header is created, next create an extent and put both logical and
829; physical cluster number in the extent. The new extent should be
830; created at the bottom end of the current queue, except if AX =3,
831; then the new extent will be created between current and previous extent.
832; Use Find_Free_Buffer to check the free space.
833;--------------------------------------------------------------------------
834 CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000;
835 jnc ins_save_addrs1 ; found, jump ;AN000;
836 jmp Insert_Exit ; if free area found is its own ;AN000;
837 ; header, exit
838Ins_Save_Addrs1:
839 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
840 mov ax,es:[di].Free_Ptr ;AN000;
841 mov New_Extn_Ptr,ax ; save new extent address ;AN000;
842 CALL UPDATE_FREE_AREA ; update Free area ;AN000;
843
844 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
845 mov ax,New_Extn_Ptr ; beginning of new extent ;AN000;
846 mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000;
847 mov es:[si].FH_Next_Extn_Ptr,ax ; connect current header to adj CHAIN ;AN000;
848 mov es:[si].FH_MRU_EXTN_Ptr,ax ; connect current header to LRU chain ;AN000;
849 mov si,New_Extn_Ptr ; SI-->New extent
850 mov bx,Logical_ClusNum ;AN000;
851 mov es:[si].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000;
852 mov cx,Physical_ClusNum ;AN000;
853 mov es:[si].EH_Phys_Clus_Num,cx ; insert physical clus num ;AN000;
854 mov es:[si].EH_Count,0 ; set initial count = 0 ;AN000;
855
856;--------------------------------------------------------------------------
857; Make new extent LRU extent
858;--------------------------------------------------------------------------
859 mov es:[si].EH_Next_Extn_Ptr, -1 ; mark no next extent in sorted chain
860 mov es:[si].EH_Prev_Extn_Ptr, -1 ; mark no previous extent in sorted chain ;AN000;
861 mov es:[si].EH_Next_LRU_Ptr, -1 ; mark no next extent in MRU-LRU chain ;AN000;
862 mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent in MRU-LRU chain
863 clc ;
864 jmp Insert_Exit ; exit ;AN000;
865
866;--------------------------------------------------------------------------
867; Header found, Check to see any extent under this header. If not create
868; new extent. If there are extents, search for the relative position of the
869; given cluster number among the extents under current header.
870;--------------------------------------------------------------------------
871Insert_Find_Extent:
872 mov di,Cur_Hdr_Ptr ; DI-->Current header
873 mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under current hdr ;AN000;
874 cmp si,-1 ; any extent under this header ? ;AN000;
875 jne Find_relative_location ; yes, Find relative location of the
876 ; given cluster numbers ;AN000;
877
878; Else create new extent under the current header.
879 CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000;
880 jnc ins_save_addrs2 ; found, jump ;AN000;
881 jmp Insert_Exit ; else free area found is its own ;AN000;
882 ; header, *** ERROR **** exit
883Ins_save_addrs2:
884 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
885 mov ax,es:[di].Free_Ptr ;AN000;
886 mov New_Extn_Ptr,ax ; save new extent address ;AN000;
887
888 CALL UPDATE_FREE_AREA ; update Free area pointers ;AN000;
889
890 mov di,Drive_Hdr_Ptr ; DI-->Drive header pointer ;AN000;
891 mov ax,New_Extn_Ptr ;AN000;
892 mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000;
893 mov es:[si].FH_Next_Extn_Ptr,ax ; connect new extent to header ;AN000;
894 mov es:[si].FH_MRU_EXTN_Ptr,ax
895 mov si,New_Extn_Ptr ;### next extent start in the free_ptr ;AN000;
896 mov bx,Logical_ClusNum ;AN000;
897 mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000;
898 mov cx,Physical_ClusNum ;AN000;
899 mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000;
900 mov es:[si].EH_Count,0 ; ;AN000;
901 mov es:[si].EH_Next_Extn_Ptr,-1 ; mark this extent as last extent ;AN000;
902 mov es:[si].EH_Next_LRU_Ptr,-1 ; ### mark this extent as last extent ;AN000;
903 mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark there is no prev extent ;AN000;
904 mov es:[si].EH_Prev_LRU_Ptr,-1 ; mark there is no prev LRU extent
905 jmp Insert_Make_MRU ; make current header MRU header ;AN000;
906
907
908;--------------------------------------------------------------------------
909; Check if the given cluster number will be continuous to either High or Low
910; end of any extent under current header or should create a new extent
911; If not, check whether a new extent for the cluster is to be created
912; between current and previous extent - Current and next extent or new
913; extent at the bottom of the queue.
914;--------------------------------------------------------------------------
915Find_Relative_Location:
916 CALL FIND_CLUSTER_LOCATION ; find relative position of new extent ;AN000;
917 jnc chk_continuity ; position found ;AN000;
918 clc ; clusters already exist in an extent.
919 jmp Insert_exit ; return to DOS ;AN000;
920
921;--------------------------------------------------------------------------
922; Extent found. Check for LOW end contiguous. If true insert in the current
923; extent and update the count
924;--------------------------------------------------------------------------
925Chk_continuity:
926 cmp find_flag,1 ; LO end contiguous to current extent? ;AN000;
927 jne Insert_chk_HI ; no - check high end contiguous ;AN000;
928 mov si,Cur_Extn_Ptr ; yes - insert and update ;AN000;
929 mov cx,Logical_ClusNum ; save new logical and pysical ;AN000;
930 mov es:[si].EH_Logic_Clus_Num,cx ; cluster numbers as first clusters ;AN000;
931 mov cx,Physical_ClusNum
932 mov es:[si].EH_Phys_Clus_Num,cx ;AN000;
933 inc es:[si].EH_Count ; update extent range count ;AN000;
934 mov di,Drive_Hdr_Ptr ; DI-->drive header
935 cmp es:[di].Free_Ptr,0 ; any free buffer ??
936 je Chk_low_MRU ; no - make current extent MRU extent
937 jmp Insert_Make_MRU ; yes - make current header MRU header ;AN000;
938
939Chk_Low_MRU:
940 mov Cur_Extn_Ptr, si
941 CALL Make_MRU_Extent ; Move extent next to current header
942 jmp Insert_Make_MRU ; Make current header MRU header ;AN000;
943
944;--------------------------------------------------------------------------
945; Check if clusters are high end contiguous to current extent. If true
946; increment count and then make the extent MRU extent only if no free
947; buffer is available.
948;--------------------------------------------------------------------------
949Insert_Chk_HI:
950 cmp find_flag,2 ; HI end contiguous to current extent? ;AN000;
951 jne Insert_chk_between ; no, jump ;AN000;
952 mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000;
953 inc es:[si].EH_Count ; increment the cluster range count ;AN000;
954 mov di,Drive_Hdr_Ptr ; DI-->current drive header
955 cmp es:[di].Free_Ptr,0 ; any free buffers ??
956 je Chk_Hi_MRU ; no - make current extent MRU extent
957 jmp Insert_Make_MRU ; yes - current header MRU header ;AN000;
958
959Chk_Hi_MRU:
960 mov Cur_Extn_Ptr, si ; SI -->extent to be MRU
961 CALL Make_MRU_Extent ; move extent next to current header
962 jmp Insert_Make_MRU ; Make current header MRU header ;AN000;
963
964
965;--------------------------------------------------------------------------
966; Check to see the cluster number belongs to a new extent between current
967; and Previous extent or header. If not it belongs to a new extent at the
968; bottom end of the queue.
969;--------------------------------------------------------------------------
970Insert_Chk_Between:
971 cmp find_flag,3 ; between current and previous exts?? ;AN000;
972 je Connect_prev_next ; yes, jump ;AN000;
973
974 cmp find_flag,5 ; between current and next extents?? ;AN000;
975 jne Connect_to_end ; no, create new extent at bottom ;AN000;
976 ; bottom of the queue
977 jmp Connect_cur_next ; yes create new extent between ;AN000;
978 ; current and next extent
979
980;--------------------------------------------------------------------------
981; No, make new extent at the BOTTOM of the queue.
982;--------------------------------------------------------------------------
983CONNECT_TO_END: ; At this point SI-->Last extent in queue ;AN000;
984 CALL FIND_FREE_BUFFER ; Check for free area ;AN000;
985 jnc ins_save_addrs3 ;AN000;
986 jmp Insert_Exit ; if free area found is its own ;AN000;
987 ; header, *** ERROR *** exit
988Ins_Save_Addrs3:
989 mov di,Drive_Hdr_Ptr ;AN000;
990 mov ax,es:[di].Free_Ptr ;AN000;
991 mov New_Extn_Ptr,ax ; save new extent address ;AN000;
992 CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000;
993
994 mov ax,New_Extn_Ptr ;AN000;
995 mov di,Cur_Extn_Ptr ; SI-->Current extent ;AN000;
996 cmp ax, di ; If free area got is the last
997 jne Use_Cur_Extent ; last extent itself then use previous extent
998 mov di, Prev_Extn_Ptr ; SI-->Previous extent
999
1000Use_Cur_extent:
1001 mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to current or previous extent ;AN000;
1002 mov si,New_Extn_Ptr ; next extent start in the free_ptr ;AN000;
1003 mov es:[si].EH_Prev_Extn_Ptr, di ; set previous extent address
1004 mov bx,Logical_ClusNum ;AN000;
1005 mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000;
1006 mov cx,Physical_ClusNum ;AN000;
1007 mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000;
1008 mov es:[si].EH_Count,0 ; initial cluster range
1009
1010; Make new extent last extent in the sorted chain
1011 mov es:[si].EH_Next_Extn_Ptr, -1 ; mark as Last extent of the queue ;AN000;
1012; make the new extent MRU extent in the MRU_LRU chain
1013 mov di,Cur_Hdr_Ptr ; DI-->Current header
1014 mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent
1015 mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent
1016 mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000;
1017 mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent
1018 mov di,ax
1019 mov es:[di].EH_Prev_LRU_Ptr,si ; connect previous to current extent
1020 jmp Insert_Make_MRU ; make current header MRU header
1021 ;AN000;
1022
1023
1024;--------------------------------------------------------------------------
1025; Make new extent between current and previous extents. If no previous extent
1026; connect the new extent to the current header.
1027;--------------------------------------------------------------------------
1028CONNECT_PREV_NEXT:
1029 CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000;
1030 jnc Prev_Next_Update ; found, jump ;AN000;
1031 jmp Insert_Exit ; if free area found is its own ;AN000;
1032 ; header, **ERROR** exit
1033Prev_Next_Update:
1034 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
1035 mov ax,es:[di].Free_Ptr ;AN000;
1036 mov New_Extn_Ptr,ax ; save new extent address ;AN000;
1037 ;AN000;
1038 CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000;
1039
1040 mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000;
1041 cmp Prev_Extn_Ptr, -1 ; Any previous extents ?? ;AN000;
1042 jne join_to_Prev_Extn ; yes - connect new extent to previous ;AN000;
1043 ; extent
1044; No, connect new extent to header
1045 mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000;
1046 mov di,New_Extn_Ptr ;AN000;
1047 mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under header
1048 mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to this extent
1049 mov es:[si].FH_Next_Extn_Ptr, di ; connect new extent to cur hdr ;AN000;
1050 mov es:[di].EH_Prev_Extn_Ptr, -1 ; address of previous extent (-1) since header
1051 mov bx,Logical_Clusnum ; ;AN000;
1052 mov es:[di].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000;
1053 mov cx,Physical_Clusnum ;AN000;
1054 mov es:[di].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000;
1055 mov es:[di].EH_Count,0 ; set count ;AN000;
1056 mov si,ax ; SI-->previous MRU extent
1057 mov es:[si].EH_Prev_Extn_Ptr,di ; set prev extent of prev MRU extent
1058
1059; Make the new extent MRU extent
1060 mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000;
1061 mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header
1062 mov di,New_Extn_Ptr ; SI-->current header ;AN000;
1063 mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent
1064 mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000;
1065 mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header
1066 mov si,ax
1067 mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent
1068 Jmp Insert_Make_MRU ; make current header MRU hdr ;AN000;
1069
1070; Connect new extent to previous extent
1071Join_To_Prev_Extn:
1072 mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000;
1073 mov ax,Cur_Extn_Ptr ; connect previous extent ;AN000;
1074 cmp si,ax ; new extent is created from
1075 je join_set_adj ; current extent ??
1076
1077 mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000;
1078 mov ax,New_Extn_Ptr ; connect new extent to ;AN000;
1079 mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000;
1080 mov ax,Cur_Extn_Ptr
1081 jmp short Join_Set_Next ; current extent
1082
1083Join_set_adj: ; yes -
1084 mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000;
1085 mov bx,es:[si].EH_Next_Extn_Ptr ; get next extent address
1086 mov ax,New_Extn_Ptr ; connect new extent to ;AN000;
1087 mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000;
1088 mov ax, bx ; extent to next extent
1089 mov Cur_Extn_Ptr,bx ; change current extent
1090
1091Join_set_Next: ; from current extent
1092 mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000;
1093 mov es:[si].EH_Next_Extn_Ptr,ax ; current extent ;AN000;
1094 mov bx,Logical_Clusnum ; then save cluster numbers ;AN000;
1095 mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000;
1096 mov cx,Physical_Clusnum ;AN000;
1097 mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000;
1098 mov es:[si].EH_Count,0 ; ;AN000;
1099 mov ax, Prev_Extn_Ptr
1100 mov es:[si].EH_Prev_Extn_Ptr,ax ; connect previous to current extent
1101 mov di, Cur_Extn_Ptr ; setup previous extent link of
1102 mov es:[di].EH_Prev_Extn_Ptr,si ; current extent
1103
1104; Make the new extent MRU extent
1105 mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000;
1106 mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header
1107 mov di,New_Extn_Ptr ; SI-->current header ;AN000;
1108 mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent
1109 mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000;
1110 mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header
1111 mov si,ax
1112 mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent
1113 Jmp short Insert_Make_MRU ; make current header MRU hdr ;AN000;
1114
1115
1116
1117;--------------------------------------------------------------------------
1118; Make new extent between current and next extents. If no next extent
1119; connect the new extent to the end of queue.
1120;--------------------------------------------------------------------------
1121CONNECT_CUR_NEXT:
1122 mov si,Cur_Extn_Ptr ; current extent ;AN000;
1123 cmp es:[si].EH_Next_Extn_Ptr,-1 ; any next extent ?? ;AN000;
1124 jne join_to_next_extn ; yes, join to next extent ;AN000;
1125 jmp Connect_To_End ; make new extent at the bottom of ;AN000;
1126 ; the current queue
1127Join_To_Next_Extn:
1128 CALL FIND_FREE_BUFFER ; Find free area ;AN000;
1129 jc Insert_Exit ; if free area found is its own ;AN000;
1130 ; header, exit
1131 mov di,Drive_Hdr_Ptr ;AN000;
1132 mov ax,es:[di].Free_Ptr ;AN000;
1133 mov New_Extn_Ptr,ax ; save new extent address ;AN000;
1134
1135 CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000;
1136 ;AN000;
1137 mov si,Cur_Extn_Ptr ; SI-->Current extent
1138 mov DX,es:[si].EH_Next_Extn_Ptr ; DI-->Next extent ;AN000;
1139 mov ax,New_Extn_Ptr ;AN000;
1140 mov es:[si].EH_Next_Extn_Ptr,ax ;connect new extent to cur extent ;AN000;
1141
1142 mov si,New_Extn_Ptr ; SI-->New extent, connect new ext ;AN000;;AN000;
1143 mov es:[si].EH_Next_Extn_Ptr,DX ; to next extent ;AN000;
1144 mov ax, Cur_Extn_Ptr ; AX = address of current extent
1145 mov es:[si].EH_Prev_Extn_Ptr, ax ; save address of previous extent
1146 mov bx,Logical_Clusnum ; then save cluster numbers ;AN000;
1147 mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000;
1148 mov cx,Physical_Clusnum ;AN000;
1149 mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000;
1150 mov es:[si].EH_Count,0 ; set cluster range ;AN000;
1151 mov di,DX ; setup prev extent link of the
1152 mov es:[di].EH_Prev_Extn_Ptr,si ; next extent
1153
1154; Make the new extent MRU extent
1155 mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000;
1156 mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header
1157 mov di,New_Extn_Ptr ; SI-->current header ;AN000;
1158 mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent
1159 mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000;
1160 mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header
1161 mov si,ax
1162 mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent
1163
1164
1165;--------------------------------------------------------------------------
1166; Make the Current header MRU header. If the header is MRU header, then
1167; dont make the header MRU header.
1168;--------------------------------------------------------------------------
1169Insert_Make_MRU:
1170 cmp Prev_Hdr_Ptr, -1 ; first header ?? ;AN000;
1171 jne Ins_mru_hdr ; no, make MRU header ;AN000;
1172 clc ; make sure caary is clear
1173 jmp short insert_exit ; yes, exit ;AN000;
1174
1175Ins_MRU_Hdr:
1176 CALL MAKE_MRU_HEADER ; move header to top of OPEN Queue ;AN000;
1177 clc ; make sure caary is clear
1178
1179Insert_exit:
1180 CALL Check_it ; analyse the queue (debugging)
1181 ret ; EXIT ;AN000;
1182
1183FK_INSERT ENDP
1184
1185
1186
1187
1188
1189
1190
1191
1192;-------------------------------------------------------------------------
1193; PROCEDURE: FK_LOOKUP
1194;
1195; FUNCTION: Search through the OPEN Queue for a specific Header and
1196; extent. If header is not found, create a new header and
1197; make it MRU header. Else search for a specific extent which
1198; contains the logical cluster number. If the extent is not
1199; found, return partial information from previous extent or
1200; header. If extent is found, return physical cluster number
1201; corresponds to the given logical cluster number.
1202;
1203; INPUT: DL = drive number
1204; CX = First Physical Cluster Number of the file
1205; BX = Logical Cluster NUmber
1206;
1207; OUTPUT: If Carry = 0 Fully Found
1208; DI = Physical Cluster Number indexed by es:[BX]
1209; BX = Physical Cluster Number indexed by es:[BX-1]
1210;
1211; If Carry = 1 Partially Found
1212; BX = Last logical cluster number in previous extent
1213; DI = Last Physical Cluster Number indexed by es:[Last logic clus]
1214;
1215; If header not found, a new header will be created. In this case
1216; BX = First Logical Cluster number (0)
1217; DI = First Physical Cluster number of the header created
1218;
1219; NOTE: The clusters are fully found if the logical cluster has
1220; continuity to the previous logical cluster in the same
1221; extent or previous extent or previous header.
1222;
1223; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_Drive_Header
1224;
1225; REVISION HISTORY: New (5/87)
1226;
1227; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
1228; "Version 4.00 (C) Copyright 1988 Microsoft"
1229; "Licensed Material - Property of Microsoft "
1230;
1231;---------------------------------------------------------------
1232
1233FK_LOOKUP PROC FAR ; on entry DS = seg ID of INIT
1234
1235 push cs ; establish addressability ;AN000;
1236 pop ds ; DS --> code segment ;AN000;
1237 assume ds:Cseg_Seek ;AN000;
1238 mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000;
1239 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
1240 mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000;
1241 mov Logical_ClusNum,bx
1242 mov func_cod,al
1243
1244;--------------------------------------------------------------------------
1245; Search for Drive header in the Cache buffer using Drive ID in DL
1246;--------------------------------------------------------------------------
1247 CALL FIND_DRIVE_HEADER ; Search for drive header ;AN000;
1248 jnc Look_search_hdr ; found, search for file header ;AN000;
1249 jmp Look_Exit ; not found, error ;AN000;
1250
1251;--------------------------------------------------------------------------
1252; Search for a header in the OPEN Queue using given physical cluster number
1253;--------------------------------------------------------------------------
1254Look_Search_Hdr:
1255 inc es:[di].Extent_Count ; ;***;
1256 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000;
1257 ; in the OPEN Queue
1258 mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000;
1259 CALL FIND_FILE_HEADER ; find the header in CLOSE Queue
1260 ;AN000;
1261 jnc Look_Find_extent ; if found, find extent under this header
1262 ; else create a new header ;AN000;
1263;--------------------------------------------------------------------------
1264; If the header is not found, create a new header at the top of OPEN queue.
1265; Insert physical cluster number and set next header and first extent pointers
1266; Return partially found information.
1267;--------------------------------------------------------------------------
1268 pushf ; save carry set
1269 CALL MAKE_NEW_HEADER ; Make a new header at the top of the queue ;AN000;
1270 xor bx,bx ; BX = First Logical cluster number ;AN000;
1271 mov di, First_Phys_Clusnum ; DI = First physical cluster number
1272 popf ; carry should be set
1273 jmp Look_exit ; exit ;AN000;
1274
1275
1276;--------------------------------------------------------------------------
1277; If the header is found, next search for the extent that contains the
1278; logical and physical cluster numbers. DI--> current header
1279;--------------------------------------------------------------------------
1280Look_Find_Extent:
1281 cmp es:[di].FH_Next_Extn_Ptr,-1 ; any extent under this header ?? ;AN000;
1282 jne look_search_extent ; yes, search for right extent ;AN000;
1283
1284 xor bx,bx ; no, return partial info from header ;AN000;
1285 mov di,es:[di].FH_Phys_Clus_Num ; DI = first phys clus num ;AN000;
1286 push di ; ;AN000;
1287 push bx ; BX = 1st logc clus num = 0 ;AN000;
1288 mov fully_flag, 0 ; set partially found flag ;AN000;
1289 jmp look_make_MRU_hdr ; move header to top of the OPEN queue ;AN000;
1290
1291
1292;--------------------------------------------------------------------------
1293; Search for cluster numbers in extents starting from 1st extent.
1294;--------------------------------------------------------------------------
1295Look_Search_Extent:
1296 mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under curr hdr ;AN000;
1297 mov Cur_Extn_Ptr,si ; save it ;AN000;
1298 mov cx,Logical_ClusNum ; CX = logic clus num to search for ;AN000;
1299 mov Prev_Extn_Ptr, -1 ; reset flags ;AN000;
1300 mov Extn_Flag, 0 ; ;AN000;
1301 cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000;
1302 jl Look_proc_less
1303
1304Look_Loop1:
1305 cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000;
1306 ; current extent matches ??
1307 je Look_Proc_First ; yes, process 1st extent case ;AN000;
1308 mov ax,es:[si].EH_Logic_Clus_Num ; else check subsequent extents
1309 add ax,es:[si].EH_Count ; last logic clus num in cur extent ;AN000;
1310 cmp cx,ax ; extent found in the cur extent ??
1311 jg Look_Next_Extn ; no,try next extent ;AN000;;AN000;;AN000;
1312 jmp Look_Extn_within ; yes, process current extent ;AN000;
1313
1314Look_Next_Extn: ;
1315 mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000;
1316 cmp ax,-1 ; is this last extent ?? ;AN000;
1317 je Look_last_done ; yes, get partial ;AN000;
1318
1319 mov Prev_Extn_Ptr,si ; save previous extent address ;AN000;
1320 mov si,ax ;AN000;
1321 mov Cur_Extn_Ptr,si ; save current extent address ;AN000;
1322 cmp cx,es:[si].EH_Logic_Clus_Num ; logic clus num in cur extent ?? ;AN000;
1323 jge Look_Loop1 ; may be!!, check it out ;AN000;
1324
1325 jmp Look_Proc_Prev ; else get partial info from ;AN000;
1326 ; previous extent
1327;-------------------------------------------------------------------------
1328; There are no further extents. In this case partially found. Return last
1329; logical and physical clusters of the last extent.
1330;-------------------------------------------------------------------------
1331Look_Last_Done:
1332 mov si,Cur_Extn_Ptr ; SI-->Previous extent ;AN000;
1333 mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num ofprevext ;AN000;
1334 mov di,es:[si].EH_Phys_Clus_Num ; BX = first logic clus num ofprevext ;AN000;
1335 add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000;
1336 add bx,es:[si].EH_Count ; BX = last logic clus number in extent ;AN000;
1337 push di ; last logical cluster number ;AN000;;AN000;
1338 push bx ; last physical cluster number ;AN000;
1339 mov fully_flag,0 ; partially found case ;AN000;
1340 jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000;
1341
1342
1343
1344;--------------------------------------------------------------------------
1345; Less than starting logical cluster of first extent. In this case return
1346; header info as partially found.
1347;--------------------------------------------------------------------------
1348Look_Proc_Less:
1349 xor bx,bx ; BX = logical cluster number = 0 ;AN000;
1350 mov ax,es:[di].FH_Phys_Clus_Num ;AN000;
1351 push ax ; first phys clus of current hdr ;AN000;
1352 push bx ; first logic clus (0) of cur hdr ;AN000;
1353 mov fully_flag,0 ; partially found case ;AN000;
1354 jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000;
1355
1356
1357
1358;--------------------------------------------------------------------------
1359; If first logical cluster number of the current extent matches with the given
1360; logical cluster number, see if previous logical cluster in previous header
1361; or extent is contiguous. If true, fully found. I this case return
1362; BX = first physical cluster of cuurent extent and DI = first physical
1363; cluster number of header if it is a header or last physical cluster number
1364; of previous extent. If this is not true, partially found case. In this case,
1365; return BX = last logical cluster number and DI = last physical cluster number
1366; from the previous extent. If no previous extent, then return DI = first
1367; physical cluster and BX = 0 from the header
1368;
1369; NOTE: The clusters are fully found if the logical cluster has
1370; continuity to the previous logical cluster in the same
1371; extent or previous extent or previous header.
1372;--------------------------------------------------------------------------
1373Look_Proc_First:
1374 mov si,Cur_Extn_Ptr ; SI-->current extent ;AN000;
1375 mov di,Cur_Hdr_Ptr ; DI-->current header ;AN000;
1376 cmp Prev_Extn_Ptr, -1 ; any previous extent ?? ;AN000;
1377 jne look_get_prev_extent ; yes, get from previous extent ;AN000;
1378
1379;--------------------------------------------------------------------------
1380; No, look for current header logical cluster number continuity
1381;--------------------------------------------------------------------------
1382 mov ax,es:[si].EH_Logic_Clus_Num ; AX = First physical cluster number ;AN000;
1383 dec ax ; of current extent ;AN000;
1384 cmp ax,0 ; continuity to first logical clus num ;AN000;
1385 ; of current header which is (0)
1386 jne Look_first_partial ; no, partially found ;AN000;
1387
1388
1389; Yes, fully found
1390 mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000;
1391 ; current extent
1392 mov ax,es:[di].FH_Phys_Clus_Num ; AX = First physical cluster number ;AN000;
1393 ; of current header
1394 push bx ; BX = 1st phys clus of current extent ;AN000;
1395 push ax ; AX = 1st phys clus of prev header ;AN000;
1396 mov fully_flag,1 ; FULLY found case ;AN000;
1397 jmp Look_Make_MRU_Hdr ; mov cur header to top of the Queue ;AN000;
1398
1399
1400Look_First_Partial:
1401 xor bx,bx ; BX = logical cluster number = 0 ;AN000;
1402 mov ax,es:[di].FH_Phys_Clus_Num ;AN000;
1403 push ax ; first phys clus of current hdr ;AN000;
1404 push bx ; first logic clus (0) of cur hdr ;AN000;
1405 mov fully_flag,0 ; partially found case ;AN000;
1406 jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000;
1407
1408
1409;--------------------------------------------------------------------------
1410; Get last physical and logical cluster number of the previous extent
1411;--------------------------------------------------------------------------
1412Look_Get_Prev_Extent:
1413 mov di,Prev_Extn_Ptr ; DI-->Previous extent ;AN000;
1414 mov ax,es:[si].EH_Logic_Clus_Num ; AX = First logical cluster number ;AN000;
1415 dec ax ; of current extent ;AN000;
1416 mov bx,es:[di].EH_Logic_Clus_Num ; continuity to last logical clus num ;AN000;
1417 add bx,es:[di].EH_Count ; of previous extent ?? ;AN000;
1418 cmp ax,bx ;AN000;
1419 jne Look_first_partial2 ; no, partially found ;AN000;
1420
1421; Fully found case
1422 mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000;
1423 mov ax,es:[di].EH_Phys_Clus_Num ; AX = Last physical cluster number ;AN000;
1424 add ax,es:[di].EH_Count ; from previous extent ;AN000;
1425 push bx ; BX = 1st phys clus num from cur extn ;AN000;
1426 push ax ; AX = last phys clus num from prev extn ;AN000;
1427 mov fully_flag,1 ; FULLY found case ;AN000;
1428 jmp short Look_Make_MRU_Hdr ; mov current header to top of OPEN que ;AN000;
1429
1430
1431Look_First_Partial2:
1432 mov bx,es:[di].EH_Logic_Clus_Num ; BX = First Logical cluster number ;AN000;
1433 ; of current extent
1434 add bx,es:[di].EH_Count ; BX = Last Logic clus from prev extn ;AN000;
1435 mov ax,es:[di].EH_Phys_Clus_Num ; AX = First physical cluster number ;AN000;
1436 ; of previous extent
1437 add ax,es:[di].EH_Count ; last phys clus num of prev extent ;AN000;
1438 push ax ; AX = last phys clus of prev extent ;AN000;
1439 push bx ; BX = last logic clus of prev extent ;AN000;
1440 mov fully_flag,0 ; partially found case ;AN000;
1441 jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000;
1442
1443
1444
1445;----------------------------------------------------------------------------
1446; If the given cluster number matches with any logic cluster number starting
1447; from 2nd and above, then fully found. Return BX=Phys clus num[log_clusnum]
1448; and DI=Phys clus num[log_clusnum-1]
1449;----------------------------------------------------------------------------
1450Look_Extn_Within:
1451 mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000;
1452 sub cx,es:[si].EH_Logic_Clus_Num ;AN000;
1453 mov di,es:[si].EH_Phys_Clus_Num ; DI = first phys clus num of ;AN000;
1454 ; current extent
1455 add di,cx ; DI = Phys clus num [logic clus num] ;AN000;
1456 mov bx,di ; ;AN000;
1457 dec bx ; BX = Phys clus num [logic clus num -1] ;AN000;
1458 push di ; DI = Phys clus num [logic clus num] ;AN000;
1459 push bx ;AN000;
1460 mov fully_flag,1 ; fully found case ;AN000;
1461 jmp short Look_Make_MRU_Hdr ; make current header to top of OPEN Que ;AN000;
1462
1463
1464;--------------------------------------------------------------------------
1465; Given extent is above the upper limit of the current extent, but lower than the
1466; next extent. In this case, cluters are partially found. Return BX = last
1467; logical cluster number of the previous extent and DI = last physical cluster
1468; number of the previous extent.
1469;----------------------------------------------------------------------------
1470Look_Proc_Prev:
1471 mov si,Prev_Extn_Ptr ; SI-->Previous extent ;AN000;
1472 mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num of prev ;AN000;
1473 ; extent
1474 mov di,es:[si].EH_Phys_Clus_Num ; BX = first phys clus num of prev ;AN000;
1475 ; extent
1476 add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000;
1477 add bx,es:[si].EH_Count ; BX = last logic clus number in extent
1478 push di ; save clusters to return ;AN000;
1479 push bx ;AN000;
1480 mov fully_flag,0 ; partially found case ;AN000;
1481
1482;----------------------------------------------------------------------------
1483; Move the current header to the top of the OPEN queue
1484;----------------------------------------------------------------------------
1485Look_Make_MRU_Hdr:
1486 cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000;
1487 je Look_Dont_Move_To_Top ; yes, dont move to top ;AN000;
1488
1489 CALL MAKE_MRU_HEADER ;AN000;
1490
1491Look_Dont_Move_To_Top:
1492 cmp fully_flag, 0 ; fully found ?? ;AN000;
1493 je Look_set_carry ; no, partially found ;AN000;
1494 clc ; fully found ;AN000;
1495 jmp short Look_Restore ; restore registers ;AN000;
1496
1497Look_Set_Carry:
1498 stc ; set flag for partially found ;AN000;
1499
1500Look_restore:
1501 pop bx ; restore values to be reurned
1502 pop di ; to DOS
1503
1504Look_Exit:
1505 nop
1506 CALL Check_it
1507 ret ; exit
1508
1509FK_LOOKUP endp
1510
1511
1512
1513
1514
1515
1516
1517;----------------------------------------------------------------
1518; PROCEDURE: Fk_Truncate
1519;
1520; FUNCTION: Using the given physical and logical clutser numbers,
1521; find the extent which contains the given cluster number.
1522; Delete all clusters folloing the given cluster and the
1523; subsequent extents and free the buffers.
1524;
1525; INPUT: CX = First Physical Cluster Number of the file
1526; BX = Logical Cluster Number
1527; DL = Drive number
1528;
1529; OUTPUT: CY = 0 Extents are truncated
1530;
1531; CY = 1 Extent no found DI = 0
1532;
1533; ROUTINES REFERENCED: Find_File_Header, Find_Extent
1534;
1535; REVISION HISTORY: New (5/87)
1536;
1537; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
1538; "Version 4.00 (C) Copyright 1988 Microsoft"
1539; "Licensed Material - Property of Microsoft "
1540;
1541;---------------------------------------------------------------
1542
1543Fk_TRUNCATE PROC FAR
1544
1545 push cs ; establish addressability ;AN000;
1546 pop ds ; DS --> code segment ;AN000;
1547 assume ds:Cseg_Seek ;AN000;
1548 mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000;
1549 assume es:Cseg_Init ; ES --> cache buffer segment ;AN000;
1550 mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000;
1551 mov Logical_ClusNum,bx ;AN000;
1552 mov func_cod,al
1553
1554;--------------------------------------------------------------------------
1555; Search for Drive Cache buffer using Drive ID in DL
1556;--------------------------------------------------------------------------
1557 CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000;
1558 jnc Trunc_search_hdr ; if found, search for file header ;AN000;
1559 jmp Trunc_Exit ; if not found, error ;AN000;
1560 ;AN000;
1561;--------------------------------------------------------------------------
1562; Search for a header in the OPEN Queue using given physical clusternum
1563;--------------------------------------------------------------------------
1564Trunc_Search_Hdr:
1565 inc es:[di].Extent_Count ; ;***;
1566 mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000;
1567 ; in the OPEN Queue
1568 mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000;
1569
1570 CALL FIND_FILE_HEADER ; find file header in OPEN Queue ;AN000;
1571 jnc Trunc_Find_extent ; if found, get extent ;AN000;
1572
1573;--------------------------------------------------------------------------
1574; If the header is not found, create a new header and make it as MRU header
1575; insert first physical cluster number in the header
1576;--------------------------------------------------------------------------
1577 CALL MAKE_NEW_HEADER ; make new header ;AN000;
1578 clc ;AN000;
1579 jmp Trunc_exit ; exit ;AN000;
1580
1581
1582;--------------------------------------------------------------------------
1583; Header is found. Next search for the extent which contains the
1584; given logical cluster number.
1585;--------------------------------------------------------------------------
1586Trunc_Find_Extent: ; ;AN000;
1587 mov Cur_Hdr_Ptr,di ; save current pointer ;AN000;
1588 mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent in the ;AN000;
1589 ; current header
1590 cmp si, -1 ; any extent under this header ?? ;AN000;
1591 je trunc_no_extent ; none, exit ;AN000;
1592 mov cx,Logical_Clusnum ; CX = given logical cluster number ;AN000;
1593
1594 CALL FIND_EXTENT ; find the extent ;AN000;
1595 jnc Trunc_shrink_extent ; found extent ?? ;AN000;
1596
1597Trunc_No_Extent: ; extent not found
1598 xor di,di ; no, return DI = 0 ;AN000;
1599 clc ; clear carry
1600 jmp Trunc_exit ; exit ;AN000;
1601
1602
1603
1604;--------------------------------------------------------------------------
1605; Found extent. Shrink the current extent and delete all subsequent extents.
1606; If the given logic clus num is the first cluster number in current extent,
1607; then delete the current extent and the subsequent ones.
1608; DI--->Extent found (starting extent)
1609;--------------------------------------------------------------------------
1610Trunc_Shrink_Extent:
1611 mov bx,Logical_Clusnum ;AN000;
1612 cmp bx,es:[di].EH_Logic_Clus_Num ; first logic cluster match ?? ;AN000;
1613 jne shrink_cur_extent ; no, shrink current extent ;AN000;
1614
1615;--------------------------------------------------------------------------
1616; First logical clus num matched. mark previous header or extent as last
1617; DI--->Extent found (starting extent)
1618;--------------------------------------------------------------------------
1619 mov si,es:[di].EH_Prev_Extn_Ptr ; SI-->Previous extent ;AN000;
1620 cmp si, -1 ; any previous extent ?? ;AN000;
1621 je trunc_no_prev ; no, jump ;AN000;
1622 mov es:[si].EH_Next_Extn_Ptr,-1 ; mark previous extent as last extn ;AN000;
1623 mov si,di ; save the current extent ptr ;AN000;
1624 mov cx, 0 ; CX = buffer release counter ;AN000;
1625 jmp trunc_more ; release successive extents ;AN000;
1626
1627;--------------------------------------------------------------------------
1628; Previous one is header. Mark so that there is no extents under it
1629;--------------------------------------------------------------------------
1630Trunc_No_Prev:
1631 mov si,Cur_Hdr_Ptr ; get current header ;AN000;
1632 mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000;
1633 mov es:[si].FH_MRU_Extn_Ptr, -1
1634 mov si,di ; save the current extent ptr ;AN000;
1635 mov cx, 0 ; CX = buffer release counter ;AN000;;AN000;
1636 jmp short trunc_more ; release the extent ;AN000;
1637
1638
1639Shrink_Cur_Extent:
1640 sub bx,es:[di].EH_Logic_Clus_Num ; compute the amount to shrunk ;AN000;
1641 dec bx ;AN000;
1642 mov es:[di].EH_Count,bx ; save it in count to shrink extent ;AN000;
1643
1644;--------------------------------------------------------------------------
1645; Mark the current extent as the last extent and delete subsequent extents.
1646;--------------------------------------------------------------------------
1647 mov si,es:[di].EH_Next_Extn_Ptr ; SI-->Next extent ;AN000;
1648 cmp si,-1 ; current extent last extent ?? ;AN000;
1649 jne Trunc_Last_extent
1650 jmp Trunc_Make_MRU_Hdr ; YES, In this case no subsequent ;AN000;
1651 ; extents left to delete.
1652Trunc_Last_Extent:
1653 mov es:[di].EH_Next_Extn_Ptr, -1 ; NO, mark last extent ;AN000;
1654 xor cx,cx ;AN000;
1655
1656;--------------------------------------------------------------------------
1657; Remove extents and release the buffer
1658; SI--->Current extent
1659;--------------------------------------------------------------------------
1660Trunc_More:
1661 push si ; save the beginning of first ;AN000;
1662 ; extent to be deleted
1663TRUNC_LOOP: ; loop for subsequent extents
1664 mov ax, -2 ; mark current extent as free ;AN000;
1665 mov es:[si],ax ; discontinuous free areas ;AN000;
1666 add cx, SIZE Extent_Header ; add size of extent ;AN000;
1667
1668 mov ax,es:[si].EH_Next_LRU_Ptr ; AX = address of Next LRU extent
1669 cmp ax, -1 ; any next LRU extent??
1670 jne Trunc_Set_Next_LRU ; yes - there is a next LRU extent
1671
1672;-----------------------------------------------------------------------------
1673; No - this is the LRU extent
1674;-----------------------------------------------------------------------------
1675 mov di,es:[si].EH_Prev_LRU_Ptr ; no - DI=address of previous LRU extent
1676 cmp di, -1 ; any prev LRU extent ??
1677 je Trunc_Mark_Prev_Hdr ; no - previous is header
1678 mov es:[di].EH_Next_LRU_Ptr, -1 ; yes - mark previous extnt LRU extent
1679 jmp short Trunc_Chk_Next_ext ; no - check next adj extent
1680
1681Trunc_Mark_Prev_Hdr:
1682 mov di, Cur_Hdr_Ptr ; DI = address of current header
1683 mov es:[di].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000;
1684 mov es:[di].FH_MRU_Extn_Ptr, -1
1685 jmp short Trunc_Chk_Next_Ext ; look for next extent
1686
1687;-----------------------------------------------------------------------------
1688; There is a next LRU extent AX-->Next_LRU_Extent
1689;-----------------------------------------------------------------------------
1690Trunc_Set_Next_LRU:
1691 mov di,es:[si].EH_Prev_LRU_Ptr ; DI = address of previous LRU extent
1692 cmp di, -1 ; any previous LRU extent ??
1693 jne Trunc_Set_Prev_LRU ; yes - connect prev LRU to Next LRU
1694
1695 mov di, Cur_Hdr_Ptr ; DI = address of current header
1696 mov es:[di].FH_MRU_Extn_Ptr, ax ; Connect next LRU extent to Hdr
1697 push si ; save current extent
1698 mov si,ax
1699 mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent
1700 pop si ; resetore current extent
1701 jmp short Trunc_Chk_Next_Ext
1702
1703
1704Trunc_Set_Prev_LRU: ; DI-->Previous LRU extent
1705 mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous LRU to Next LRU extent
1706 push si ; save Current extent
1707 mov si,ax ; SI-->Next LRU extent
1708 mov es:[si].EH_Prev_LRU_Ptr, di ; set previous LRU header address
1709 pop si ; get current extent
1710
1711
1712Trunc_Chk_Next_Ext: ; SI-->Current extent
1713 mov ax,es:[si].EH_Next_Extn_Ptr ; AX-->next extent ;AN000;
1714 cmp ax, -1 ; last extent ? ;AN000;
1715 je Trunc_Update_Free_Size ; yes, jump ;AN000;
1716
1717 mov es:[si].FH_Next_Hdr_Ptr,ax ; connect freed buffers togther ;AN000;
1718 mov si,ax ; SI-->next extent ;AN000;
1719 jmp Trunc_Loop ; delete next extent ;AN000;
1720
1721;-------------------------------------------------------------------------
1722; Update free size in the File header and connect the FREE_Ptr to the first
1723; extent released and connect the old Free_Ptr to end of the last extent
1724; SI--->Current extent
1725;-------------------------------------------------------------------------
1726Trunc_Update_Free_Size: ; SI-->Last extent released
1727 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
1728 add es:[di].Free_Size,cx ; update free area in drive header ;AN000;
1729
1730Trunc_Join_Free_Area:
1731; At this point SI-->Last extent
1732 mov ax,es:[di].Free_Ptr ;AN000;
1733 mov es:[si].EH_Next_Extn_Ptr,ax ; connect last extent under this ;AN000;
1734 ; header to the Free area ;AN000;
1735 pop ax ; beginning of truncated extent ;AN000;
1736 mov es:[di].Free_Ptr,ax ; connect current extent to ;AN000;
1737 ; the beginning of truncated extent
1738
1739;--------------------------------------------------------------------------
1740; Make the Current header MRU header ( move current header to top of current Q)
1741;--------------------------------------------------------------------------
1742Trunc_make_MRU_Hdr:
1743 cmp Prev_Hdr_Ptr,-1 ; first header in the Queue?? ;AN000;
1744 jne Trunc_move_Hdr
1745 clc
1746 jmp short Trunc_Exit ; yes, dont move to top ;AN000;
1747
1748Trunc_move_Hdr:
1749 CALL MAKE_MRU_HEADER ; move header to TOP of the Queue ;AN000;
1750 clc
1751
1752Trunc_Exit:
1753 CALL Check_it
1754 ret ; return ;AN000;
1755
1756FK_TRUNCATE ENDP
1757
1758
1759
1760
1761
1762
1763
1764
1765;-----------------------------------------------------------------------------
1766; Procedure: PURGE_BUFFERS
1767;
1768; Function: Reset both extent and name cache buffers of a specific
1769; drive id
1770;
1771; Input: DL = drive ID
1772;
1773; Output: Buffers are initialized
1774;
1775; REVISION HISTORY: New (5/87)
1776;
1777; COPYRIGHT: "MS DOS 4.00 Fastopen Utility"
1778; "Version 4.00 (C) Copyright 1988 Microsoft"
1779; "Licensed Material - Property of Microsoft "
1780;
1781;-----------------------------------------------------------------------------
1782
1783FK_PURGE PROC FAR ; Purge Cache buffers
1784
1785 push cs
1786 pop ds ; DS=Code seg id used for addressing
1787 ASSUME ds:Cseg_Seek ; local variables ;AN000;
1788
1789 mov si,Seek_Extent_Drive_Buff ; SI-->beginning of extent drive ;AN000;
1790 mov es,Seek_Name_Cache_Seg ; ES = addressability to Cseg_Init ;AN000;
1791 ASSUME es:Cseg_Init ; ;AN000;
1792 mov cx,Seek_Num_Of_drives ; number of drives
1793
1794Main_Loop2: ; ES:SI-->cache buffer
1795 mov ax,es:[si].Drive_Number ; get drive id
1796 cmp al,dl ; drive id found ??
1797 je purge_buffer ; yes - purge drive id buffer
1798 mov ax, size Drive_Header ; ax size of drive heder
1799 add ax, es:[si].Buff_Size ; ax = offset to next header
1800 add si,ax ; (2/11)SI-->next drive header ;AN000;
1801 LOOP main_loop2 ; try next header
1802
1803Purge_Buffer: ; SI-->drive header
1804 mov es:[si].MRU_Hdr_Ptr,-1 ; Make OPEN QUEUE empty ;AN000;
1805 mov es:[si].CLOSE_Ptr,-1 ; Make CLOSE QUEUE empty ;AN000;
1806 mov cx,es:[si].BUFF_size ; drive extent cache size ;AN000;
1807 mov es:[si].FREE_Size,cx ; set drive free buffer size ;AN000;
1808 mov ax,si
1809 add ax, size Drive_Header ; ax = size of drive header
1810 mov es:[si].FREE_Ptr,ax ; set Free buffer address
1811
1812; Makesure to fill extent cache buffer with zeros. Otherwise, Free Mark left
1813; previous run will generate illegal Free_Buff pointer.
1814 mov al,0
1815 add si, size Drive_Header ; SI-->first extent area
1816Ext_loop: ; fill extent cahe buffer with zeros
1817 mov es:[si],al ; CX = extent cache size
1818 inc si ; next byte
1819 Loop Ext_Loop ; make it zero
1820
1821FK_Exit:
1822 clc
1823 CALL Check_it
1824 ret ;AN000;
1825
1826FK_PURGE ENDP
1827
1828
1829
1830
1831
1832
1833
1834;----------------------------------------------------------------------
1835; ******* SUPPORT ROUTINES *******
1836;----------------------------------------------------------------------
1837;
1838;----------------------------------------------------------------------
1839; PROCEDURE: Find_Drive_Header
1840;
1841; FUNCTION: Find starting address of drive header in extent Cache Buffer using
1842; drive ID in DL
1843;
1844; INPUT: DL = drive id
1845; Extent_Drive_Buff (Ptr to the beginning of extent buffer)
1846; ES--> Cache Buffer Segment
1847;
1848; OUTPUT: If Carry = 0 DI --> Drive header
1849; Drive_Hdr_Ptr = address of drive header
1850;
1851; If Carry = 1 Drive buffer not found
1852;
1853; NOTE: If drive id in DL is same as the drive id in previous request,
1854; no need to search the drive header. Use the previous drive header
1855;
1856;----------------------------------------------------------------------
1857
1858FIND_DRIVE_HEADER PROC NEAR
1859
1860 mov di,Drive_Hdr_Ptr ; DI-->address of prev drive header
1861 cmp drv_id,dl ; drive id same as previous drive id (1/11/88)
1862 jne Search_drv_hdr ; no - search drive header
1863 clc ; yes - dont search
1864 jmp short drive_exit ; exit
1865
1866Search_Drv_Hdr:
1867 mov cx,Seek_Num_of_Drives ; get number of drives ;AN000;
1868 mov si,Seek_Extent_Drive_Buff ; SI-->start of extend drive hdr ;AN000;
1869
1870Drive_Loop:
1871 mov al,es:[si] ; get drive ID from cache drive hdr ;AN000;
1872 cmp al,dl ; found ?? ;AN000;
1873 je drive_buff_found ; yes, exit ;AN000;
1874 cmp es:[si].Next_Drv_Hdr_Ptr,-1 ; last header ?? ;AN000;
1875 je drive_Buff_not_found ; yes - drive header not found ;AN000;
1876 mov si,es:[si].Next_Drv_Hdr_Ptr ; SI-->next drive header ;AN000;
1877 dec cx ; update drive count ;AN000;
1878 jz drive_Buff_not_found ; last drive ;AN000;
1879 jmp drive_Loop ; search for more ;AN000;
1880
1881Drive_Buff_Not_Found: ; drive buffer not found
1882 stc ; set carry flag ;AN000;
1883 jmp short Drive_Exit ; exit ;AN000;
1884
1885Drive_Buff_Found: ; drive buffer found
1886 mov drv_id,dl ; save drive id
1887 mov Drive_Hdr_ptr,si ; save drive buffer pointer ;AN000;
1888 mov di,si ; DI-->drive header ;AN000;
1889 clc ;AN000;
1890
1891Drive_Exit: ; return
1892 ret ;AN000;
1893
1894FIND_DRIVE_HEADER endp
1895
1896
1897
1898
1899
1900;---------------------------------------------------------------
1901; PROCEDURE: Find_File_Header
1902;
1903; FUNCTION: Find starting address of the specific file header with
1904; a specific starting physical cluster number. Also
1905; determine the type of header found.
1906;
1907; INPUT: SI --> First header in the queue
1908; CX = First Physical Cluster Number (file id)
1909; ES--> Cache Buffer Segment id
1910;
1911; OUTPUT: If Carry = 0 DI --> header found
1912; Cur_Hdr_Ptr = address of header found
1913; Prev_Hdr_Ptr = address of previous header
1914;
1915; Prev_Hdr_Ptr = -1 No Previous Header
1916;
1917; hdr_flag - Type of header found
1918; = 0 Header between first & last in queue
1919; = 1 Single header in the queue
1920; = 2 First header in the queue
1921; = 3 LRU (Last) header in the queue
1922;
1923; If Carry = 1 Header not found
1924;
1925;---------------------------------------------------------------
1926
1927FIND_FILE_HEADER PROC NEAR
1928
1929 push si ; save registers ;AN000;
1930 push cx ;AN000;
1931
1932 cmp si, -1 ; any file header in this queue ?? ;AN000;
1933 jne Fh_search_hdr ; yes, search for it ;AN000;
1934 stc ; no, set carry and return ;AN000;
1935 jmp short Fh_Exit ;AN000;
1936
1937Fh_Search_Hdr:
1938 mov Prev_Hdr_Ptr,-1 ; reset flags ;AN000;
1939 mov Hdr_Flag, 0 ; reset header type flag ;AN000;
1940
1941Fh_Loop1:
1942 cmp es:[si].FH_Phys_Clus_Num,CX ; check current header ;AN000;
1943 jne Fh_next_header ; if not found branch ;AN000;
1944 mov di,si ; DI --> header found ;AN000;
1945 mov Cur_Hdr_Ptr,si ; save current Hdr pointer ;AN000;
1946 jmp short Fh_header_found ; then take exit ;AN000;
1947
1948Fh_Next_header: ; else try next header
1949 mov ax,es:[si].FH_Next_Hdr_ptr ; get address of next header ;AN000;
1950 cmp ax,-1 ; is this last header?? ;AN000;
1951 je Fh_not_found ; yes, header no found ;AN000;
1952
1953 mov Prev_Hdr_Ptr,si ; save previous header ;AN000;
1954 mov si,ax ; SI= next header ;AN000;
1955 jmp Fh_Loop1 ; check next header ;AN000;
1956
1957; Determine the type of header found
1958Fh_Header_Found: ; header found
1959 cmp Prev_Hdr_Ptr, -1 ; any previous headers ?? ;AN000;;AN000;
1960 jne Fh_LRU ; yes, jump ;AN000;
1961 cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; any headers following this hdr ?? ;AN000;
1962 jne Fh_First ; yes, jump ;AN000;
1963 mov Hdr_Flag, 1 ; single header in the queue ;AN000;
1964 clc ; ;AN000;
1965 jmp short FH_Exit ; exit ;AN000;
1966
1967Fh_First:
1968 mov Hdr_Flag, 2 ; Header found is first header in QUE ;AN000;
1969 clc ; set flag ;AN000;
1970 jmp short FH_Exit ; exit ;AN000;
1971
1972Fh_LRU:
1973 cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; Last header in the queue ?? ;AN000;
1974 jne Fh_middle_hdr ; no, Header between first and last ;AN000;
1975 mov Hdr_Flag, 3 ; set flag indicating LRU header ;AN000;
1976 clc ;AN000;
1977 jmp short Fh_Exit ; exit ;AN000;
1978 ;AN000;
1979Fh_Middle_Hdr:
1980 clc ;AN000;
1981 jmp short Fh_Exit ; exit ;AN000;
1982
1983Fh_Not_found:
1984 stc ; header not found ;AN000;
1985
1986Fh_Exit:
1987 pop cx ;AN000;
1988 pop si ;AN000;
1989 ret ; return ;AN000;
1990
1991FIND_FILE_HEADER ENDP
1992
1993
1994
1995
1996
1997
1998
1999;---------------------------------------------------------------
2000; PROCEDURE: Find_Extent
2001;
2002; FUNCTION: Find starting address of the specific Extent that contains
2003; the given logical cluster mumber.
2004; Verifiy that the extent found is the LRU Extent.
2005;
2006; INPUT: SI --> First Extent under current queue
2007; CX = Logical Cluster number to be searched
2008; ES--> Cache Buffer Segment Id
2009;
2010; OUTPUT: If Carry = 0 DI --> Extent found
2011; Cur_Extn_Ptr = address of extent found
2012; Prev_Extn_Ptr = address of previous extent
2013; IF Extn_Flag = 1, extent found is the only
2014; extent under this header
2015;
2016; If Carry = 1 Extent not found
2017;
2018; REVISION HISTORY: New (5/87)
2019;---------------------------------------------------------------
2020
2021FIND_EXTENT PROC NEAR
2022
2023 push si ; save registers ;AN000;
2024 push cx ;AN000;
2025 ;AN000;
2026 mov Prev_Extn_Ptr,-1 ; reset flags
2027 mov Extn_Flag, 0 ;AN000;
2028 ;AN000;
2029Eh_Loop1:
2030 cmp cx,es:[si].EH_Logic_Clus_Num ;AN000;
2031 jl Eh_Next_Extn ; try next extent ;AN000;
2032 mov ax,es:[si].EH_Count ; get range ;AN000;
2033 add ax,es:[si].EH_Logic_Clus_Num ; get upper range ;AN000;
2034 cmp cx,ax ;AN000;
2035 jg Eh_Next_Extn ; try next extent ;AN000;
2036
2037Eh_Not_LRU:
2038 mov di,si ; DI --> Extent found ;AN000;
2039 mov Cur_Extn_Ptr,si ; save current extent pointer ;AN000;
2040 clc ; set flag ;AN000;
2041 jmp Eh_Extn_found ; then take exit ;AN000;
2042
2043Eh_Next_Extn: ; else try next extent
2044 mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000;
2045 cmp ax,-1 ; is this last extent?? ;AN000;
2046 je Eh_Not_Found ; yes, exit ;AN000;
2047 mov Prev_Extn_Ptr,si ; save previous extent ;AN000;
2048 mov si,ax ; SI=next extent ;AN000;
2049 jmp Eh_Loop1 ; check next extent ;AN000;
2050
2051 stc ; else set flag for extent not found ;AN000;
2052 jmp short Eh_Exit ; then exit ;AN000;
2053
2054Eh_Extn_Found: ; Extent found
2055 cmp Prev_Extn_Ptr, -1 ; any previous extents ?? ;AN000;
2056 jne Eh_yes ; yes, jump ;AN000;
2057 cmp es:[di].Eh_Next_Extn_Ptr, -1 ; any extents following this extents ?? ;AN000;
2058 jne Eh_yes ; yes, jump ;AN000;
2059 mov Extn_Flag, 1 ; no, set flag indicating single extnt ;AN000;
2060 ; in the queue
2061Eh_Yes:
2062 clc ;AN000;
2063 jmp short Eh_Exit ; exit ;AN000;
2064
2065Eh_Not_Found: ; extent not found
2066 stc ;AN000;
2067
2068Eh_Exit:
2069 pop cx ;AN000;
2070 pop si ;AN000;
2071
2072 ret ; return ;AN000;
2073
2074FIND_EXTENT ENDP
2075
2076
2077
2078
2079
2080
2081;---------------------------------------------------------------------------
2082; PROCEDURE: FIND_CLUSTER_LOCATION
2083;
2084; FUNCTION: Find starting address of a specific extent which identifies
2085; the relative position of the new cluster in the queue.
2086;
2087; INPUT: SI--> First extent under current header
2088; ES--> Cache Buffer Segment
2089;
2090; OUTPUT: If Carry = 0 Cluster location identified
2091; Cur_Extn_Ptr = Current extent
2092; Prev_Extn_Ptr = Previous extent
2093;
2094; Find_Flag = 1 Clusters are contiguous in
2095; the LO end of the current extent
2096;
2097; Find_Flag = 2 Clusters are contiguous in
2098; the HI end of the current extent
2099;
2100; Find_Flag = 3 Clusters belong to a new
2101; extent between current and previous
2102; extent
2103;
2104; Find_Flag = 4 Clusters belong to a new
2105; extent at the end of the queue
2106; Cur_Extn_Ptr-->Last extent in queue
2107;
2108; Find_Flag = 5 Clusters belong to a new
2109; extent between current and next
2110;
2111; If Carry = 1 Clusters already exist
2112;
2113;-----------------------------------------------------------------------
2114
2115
2116FIND_CLUSTER_LOCATION PROC NEAR
2117
2118;--------------------------------------------------------------------------
2119; Check to see that the given logical cluster number falls within the
2120; current extent. If true it is an error.
2121;--------------------------------------------------------------------------
2122 push di
2123 mov Prev_Extn_Ptr, -1 ; initialize the flag ;AN000;
2124 mov Cur_Extn_Ptr,si ; SI-->First extent under header ;AN000;
2125 mov Find_Flag, -1 ; reset with illegal value
2126 ;AN000;
2127Fe_LOOP1:
2128 mov ax,es:[si].EH_Logic_Clus_Num ; AX = starting logi clus number ;AN000;
2129 mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000;
2130 cmp bx,ax ; LOW end ?? ;AN000;
2131 jl Fe_Chk_Low_end ; yes - jump ;AN000;
2132 add ax,es:[si].EH_Count ; ending logical clus number ;AN000;
2133 cmp bx,ax ; HIGH end ?? ;AN000;
2134 jg Fe_Chk_High_end ; yes - jump ;AN000;
2135
2136;--------------------------------------------------------------------------
2137; Found the given logical cluster number within the extent.
2138; This is a normal condition. In this case the clusters wont be insterted.
2139;--------------------------------------------------------------------------
2140 stc ; set flag
2141 jmp Fe_Extent_Exit ; return ;AN000;
2142
2143
2144;--------------------------------------------------------------------------
2145; If not in the extent, then see the logical clus number has continuity at
2146; LOW end of the current extent.
2147;--------------------------------------------------------------------------
2148Fe_Chk_LOW_END:
2149 mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000;
2150 dec ax ; one below the lowest ;AN000;
2151 mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000;
2152 cmp bx,ax ; contiguous at LOW end ?? ;AN000;
2153 jl Fe_Curr_Prev ; no, build a new extent between ;AN000;
2154 ; current and previous
2155; Logical clus has continuity at low end. Now check physical cluster number
2156; foe continuity.
2157 mov ax,es:[si].EH_Phys_Clus_Num ; starting Phys clus number ;AN000;
2158 dec ax ; one below the lowest in the extent ;AN000;
2159 mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000;
2160 cmp bx,ax ; within low end ?? ;AN000;
2161 jne Fe_Curr_Prev ; no, create a new extent between ;AN000;
2162 ; current and previous extent
2163 mov Find_Flag,1 ; yes, set flag for LOW END continuity ;AN000;
2164 jmp Fe_Extent_found ; then RETURN ;AN000;
2165
2166
2167;--------------------------------------------------------------------------
2168; Check the logical clus number has continuity at High end of the current
2169; extent cluster range. Check physical cluster number has continuity at the
2170; high end. If true, check the first logical and phys cluster number is the
2171; the same as this one. In this case clusters exist and therefore wont be
2172; insterted.
2173;--------------------------------------------------------------------------
2174Fe_CHK_HIGH_END:
2175 mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000;
2176 add ax,es:[si].EH_Count ; ending logical clus number ;AN000;
2177 inc ax ;AN000;
2178 mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000;
2179 cmp bx,ax ; within high end ?? ;AN000;
2180 jg Fe_Chk_Next_Extent ; no, check next extent ;AN000;
2181
2182; Logical clus num has high end continuity, Check the Physical cluster number
2183; for continuity.
2184 mov ax,es:[si].EH_Phys_Clus_Num ; starting phys clus number ;AN000;
2185 add ax,es:[si].EH_Count ; ending phys clus number ;AN000;
2186 inc ax ;AN000;
2187 mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000;
2188 cmp bx,ax ; within high end ?? ;AN000;
2189 jne Fe_Chk_Next_Extent ; no - check next extent ;AN000;
2190 ;
2191; Yes - check first logical and physical cluster number of next extent
2192 mov di,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000;
2193 cmp di, -1 ; any next extent ??
2194 je Fe_High_End ; none - jump
2195 mov ax,es:[di].EH_Logic_Clus_Num ; starting logi clus number ;AN000;
2196 cmp ax,Logical_Clusnum ; logical cluster matches ??
2197 jne Fe_high_end ; no - jump
2198 mov ax,es:[di].EH_Phys_Clus_Num ; starting phys clus number ;AN000;
2199 cmp ax,Physical_Clusnum ; physical cluster match ??
2200 jne Fe_High_End ; no -jump
2201 stc ; clusters already exist in next extent
2202 jmp short Fe_Extent_Exit ; return ;AN000;
2203
2204Fe_High_End:
2205 mov Find_Flag,2 ; set flag for HIGH end continuity ;AN000;
2206 jmp short Fe_Extent_found ; then RETURN ;AN000;
2207
2208
2209Fe_Chk_Cur_Next:
2210 cmp es:[si].EH_Next_Extn_Ptr, -1 ; Current extent last extent ?? ;AN000;
2211 je Fe_flag_4 ; yes, set flag-4 ;AN000;
2212
2213 mov Find_Flag,5 ; set flag for new extent between ;AN000;
2214 jmp short Fe_Extent_Found ; current and next extent ;AN000;
2215
2216Fe_Flag_4:
2217 mov Find_Flag,4 ; set flag for new extent at the ;AN000;
2218 jmp short Fe_Extent_Found ; bottom end of current queue ;AN000;
2219
2220;--------------------------------------------------------------------------
2221; Given cluster number has no continuity but must stay between current extent
2222; and previous extent
2223;--------------------------------------------------------------------------
2224Fe_CURR_PREV:
2225 mov Find_Flag,3 ; set flag for between current and prev ;AN000;
2226 jmp short Fe_Extent_found ; then RETURN ;AN000;
2227
2228
2229;--------------------------------------------------------------------------
2230; Given cluster number has no continuity. Try the next extent.
2231;--------------------------------------------------------------------------
2232Fe_Chk_NEXT_EXTENT: ; else try next extent
2233 mov ax,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000;
2234 cmp ax,-1 ; is this last extent ?? ;AN000;
2235 je Extent_at_Bottom ; yes, Clustr belongs to a new ;AN000;
2236 ; extent at the bottom ;AN000;
2237 mov Prev_Extn_Ptr,si ; save current extend as previous extnt
2238 mov si,ax ; SI-->Next extent ;AN000;
2239 mov Cur_Extn_Ptr, si ; save new extent as cur extent ;AN000;
2240 jmp Fe_Loop1 ; check next extent ;AN000;
2241
2242
2243;--------------------------------------------------------------------------
2244; Given cluster number has no continuity but stays in a new extent at
2245; bottom (last) of the current queue.
2246;--------------------------------------------------------------------------
2247Extent_AT_BOTTOM:
2248 mov Find_Flag,4 ; else set flag for new extent ;AN000;
2249
2250Fe_Extent_Found:
2251 clc ;AN000;
2252
2253Fe_Extent_Exit:
2254 pop di
2255
2256 RET ; exit ;AN000;
2257
2258
2259FIND_CLUSTER_LOCATION ENDP
2260
2261
2262
2263
2264
2265
2266
2267;-----------------------------------------------------------------------
2268; PROCEDURE: FIND_LRU_HEADER
2269;
2270; FUNCTION: Find address of the LRU header in the current queue
2271;
2272; INPUT: SI --> First header in the current queue
2273; ES--> Cache Buffer Segment
2274;
2275; OUTPUT: DI --> LRU header found
2276;
2277; LRU_Prev_Hdr = Previous header address
2278; LRU_Hdr = Address of LRU header found
2279; If Hdr_Flag = 1 - Header found is only header in the queue
2280;
2281;-----------------------------------------------------------------------
2282
2283FIND_LRU_HEADER PROC NEAR
2284
2285 push bx ;AN000;
2286 mov hdr_flag,0 ; initilialize flags ;AN000;
2287 mov LRU_Prev_Hdr, -1 ; ;AN000;
2288
2289Flh_Loop1:
2290 cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header is last hdr ? ;AN000;
2291 jne Flh_next_header ; if not check next header ;AN000;
2292 mov di,si ; DI --> LRU header found ;AN000;
2293 mov LRU_Hdr,si ; save it ;AN000;
2294 jmp short Flh_header_found ; then take exit ;AN000;
2295
2296Flh_Next_Header: ; else try next header
2297 mov LRU_Prev_Hdr,si ; save previous header address ;AN000;
2298 mov si,es:[si].FH_Next_Hdr_ptr ;AN000;
2299 jmp Flh_Loop1 ; check next header ;AN000;
2300
2301Flh_Header_Found:
2302 cmp LRU_Prev_Hdr, -1 ; any previous header ?? ;AN000;
2303 je F1h_Set_Flag ; no, set flag ;AN000;
2304 clc ; yes ;AN000;
2305 jmp short F1H_Exit ; exit ;AN000;
2306
2307F1h_Set_Flag:
2308 mov hdr_flag,1 ; LRU header is the only hdr in queue ;AN000;
2309 clc ;AN000;
2310
2311F1h_Exit: ; exit
2312 pop bx ;AN000;
2313
2314 ret ;AN000;
2315
2316FIND_LRU_HEADER endp
2317
2318
2319
2320
2321;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2322; PROCEDURE: FIND_LRU_EXTENT
2323;
2324; FUNCTION: Find address of LRU Extent under current header
2325;
2326; INPUT: ES--> Cache Buffer Segment
2327; SI--> Header to be searched
2328;
2329; OUTPUT: If CY = 0 LRU_Prev_Extent = Previous extent to the LRU extent
2330; LRU_Extent = LRU extent found
2331; Extn_Flag = 1 Extent is the only extent under header
2332;
2333; If CY = 1 Not found
2334;
2335;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2336
2337FIND_LRU_EXTENT PROC NEAR
2338
2339 mov LRU_Prev_Extent, -1 ; reset flags ;AN000;
2340 mov LRU_Extent, -1 ; ;AN000;
2341 mov Extn_Flag, 0
2342 mov si, es:[si].FH_MRU_Extn_Ptr ; SI--> First extent under header
2343 cmp si, -1 ; any extent under this header ??
2344 jne Fle_Loop1 ; yes - check extent
2345 stc ; no - set flag
2346 jmp Fle_Exit ; exit
2347
2348Fle_Loop1:
2349 cmp es:[si].EH_Next_LRU_Ptr,-1 ; last extent in the queue??
2350 jne Fle_next_extent ; if not found branch ;AN000;
2351 mov LRU_Extent,si ; save LRU extent address
2352 jmp short Fle_Extend_found ; exit
2353
2354Fle_Next_Extent: ; else try next extend
2355 mov LRU_Prev_Extent,si ; save previous extent address
2356 mov si,es:[si].EH_Next_LRU_Ptr ; get address of next extent
2357 jmp Fle_Loop1 ; check next extent ;AN000;
2358
2359Fle_Extend_Found:
2360 cmp LRU_Prev_Extent, -1 ; any previous extent ??
2361 je Fle_Set_Flag ; no - set flag
2362 clc ; ;AN000;
2363 jmp short Fle_Exit
2364
2365Fle_Set_Flag:
2366 mov Extn_Flag, 1 ; set flag to indicate only flag
2367 clc
2368
2369Fle_Exit:
2370 ret ; exit ;AN000;
2371
2372FIND_LRU_EXTENT ENDP
2373
2374
2375
2376
2377
2378
2379
2380;----------------------------------------------------------------------
2381; PROCEDURE: Make_New_Header
2382;
2383; FUNCTION: Create a new header in the next available free area.
2384; Initialize the new header and make it MRU header ( move it
2385; to the top of the queue). If no free space in OPEN queue, delete
2386; and extent from the CLOSE queue. If no space in CLOSE queue, then
2387; delete an extent from OPEN Queue to make space.
2388;
2389; INPUT: Drive_Hdr_Ptr - Address of drive header
2390; Free_Ptr - Address of FREE area
2391; ES--> Cache Buffer Segment
2392;
2393; OUTPUT: Header is created
2394;
2395;----------------------------------------------------------------------
2396
2397MAKE_NEW_HEADER PROC
2398
2399; Check if the OPEN Queue was previously empty using two cases. If open queue
2400; is empty, then the new header should be marked as first header in the queue.
2401 mov Open_Queue_Flag, 0 ; clear flag open queue empty ;AN000;
2402 mov di,Drive_Hdr_Ptr ;AN000;
2403
2404; case - 1
2405 mov ax,es:[di].Free_Size ; FREE size ;AN000;
2406 cmp es:[di].Buff_Size,ax ; both are equal ? ;AN000;
2407 je Make_Set_Entries ; if true, this is the first header ;AN000;
2408
2409; case - 2
2410 cmp es:[di].MRU_Hdr_Ptr, -1 ; check for empty mark ;AN000;
2411 je Make_Set_Entries ; yes, set flag queue empty ;AN000;
2412 jmp short Make_Set_Entry2 ; not empty ;AN000;
2413
2414Make_set_Entries: ; set up File Header entries
2415; When creating first header under drive header, mark header as first
2416; This flag is set for this purpose.
2417 mov Open_Queue_Flag, 1 ; set flag open queue was empty ;AN000;
2418
2419Make_Set_Entry2:
2420 CALL FIND_FREE_BUFFER ; Look for some Free area. If none ;AN000;
2421 ;AN000;
2422 mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000;
2423 mov ax,es:[di].Free_Ptr ;AN000;
2424 mov New_Hdr_Ptr,ax ; save new Header address
2425 mov ax,es:[di].Free_Size ;AN000;
2426
2427 CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000;
2428 ; create some free area
2429
2430;-----------------------------------------------------------------------------
2431; Connect the new header to the Top of the OPEN Queue. If the Queue is
2432; previously empty, mark the new header indicating nothing under this header.
2433;-----------------------------------------------------------------------------
2434Join_To_Drive_Buff:
2435 mov di, drive_Hdr_Ptr ; DI-->drive buffer ;AN000;
2436 mov si,New_Hdr_Ptr ;AN000;
2437 mov Cur_Hdr_Ptr, si ; save as current header pointer ;AN000;
2438 mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000;
2439 mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header
2440 mov es:[di].MRU_Hdr_Ptr,si ; make new header MRU hdr
2441
2442; When a header is created, it should contain no extents
2443 mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header with no extents ;AN000;
2444 mov es:[si].FH_MRU_Extn_Ptr,-1 ; ###mark header with no extents ;AN000;
2445 mov es:[si].FH_Refer_Count,1 ; save starting file reference count ;AN000;
2446 mov ax,First_Phys_Clusnum ;AN000;
2447 mov es:[si].FH_Phys_Clus_Num,ax ; save physical cluster number ;AN000;
2448
2449 cmp Open_Queue_Flag, 1 ; OPEN Queue empty ?? ;AN000;
2450 je Set_Single_Header ; no, jump ;AN000;
2451 clc
2452 ret ;AN000;
2453
2454Set_Single_Header: ; yes mark new header as last hdr
2455 mov si,New_Hdr_Ptr ;AN000;
2456 mov es:[si].FH_Next_Hdr_Ptr,-1 ; mark as only header ;AN000;
2457 clc
2458 ret ; exit
2459
2460MAKE_NEW_HEADER ENDP
2461
2462
2463
2464
2465
2466
2467;----------------------------------------------------------------------
2468; PROCEDURE: Find_Free_Buffer
2469;
2470; FUNCTION: Find free buffer space. If no free space, delete last extent
2471; under last header in the CLOSE queue. If none in CLOSE queue,
2472; delete the last extent of the LRU header in the OPEN queue.
2473;
2474; INPUT: Drive_Hdr_Ptr - Pointer to drive header
2475; ES--> Cache Buffer Segment
2476;
2477; OUTPUT: Released Header or extent buffer space will be addded to the
2478; Free area as discontinuous free area. Free size in drive head
2479; will be updated.
2480;
2481; If CARRY = 0
2482; Free_Flag: 0 - Free area is continuous
2483; 1 - Free area is discontinuous
2484;
2485; if CARRY = 1 Fatal error ( no free space to spare )
2486;
2487; NOTE: The deleted buffers have size same as the size of a header or extent.
2488; Each buffers first location contains a marker (-2) to indicate that
2489; the buffer is a discontinuous buffer. Each buffer is connected to
2490; the next dicontinous buffer through the 4th word.
2491;
2492;----------------------------------------------------------------------
2493
2494FIND_FREE_BUFFER PROC NEAR
2495
2496 mov di,drive_Hdr_Ptr ; DI-->Drive Header ;AN000;
2497 cmp es:[di].free_size,0 ; any free area left ?? ;AN000;
2498 je Free_Chk_Close_List ; none, check CLOSE queue ;AN000;
2499
2500 mov si,es:[di].Free_Ptr ; check for discontinuous ;AN000;
2501 mov ax, -2 ;AN000;
2502 cmp es:[si], ax ; discontinuous free buffer?? ;AN000;
2503 je Free_Set_One ; yes, set flag for discontinuous
2504
2505 mov Free_Flag,0 ; no, clear flag ;AN000;
2506 clc ;AN000;
2507 jmp Free_Exit
2508
2509Free_Set_one:
2510 mov Free_Flag,1 ; set flag ;AN000;
2511 clc ;AN000;
2512 jmp Free_exit ; yes, Free space is available ;AN000;
2513 ; exit
2514
2515
2516;--------------------------------------------------------------------------
2517; No free space , look for space in CLOSE Queue. Search for the LRU header
2518; delete the header and any extents under this header.
2519;--------------------------------------------------------------------------
2520Free_Chk_Close_List:
2521 mov si,es:[di].CLOSE_Ptr ; SI-->CLOSE queue ;AN000;
2522 cmp si,-1 ; anything in CLOSE Queue ?? ;AN000;
2523 jne Free_Chk_CLOSE_QUE ; yes - get space from CLOSE queue
2524 jmp short Free_Look_Open_Queue ; if none, make space from OPEN Queue ;AN000;
2525
2526
2527; Else get space from CLOSE queue
2528Free_Chk_Close_QUE: ; SI-->CLOSE queue
2529 mov si,es:[di].CLOSE_Ptr ; select OPEN Queue ;AN000;
2530 CALL FIND_LRU_HEADER ; find LRU header in CLOSE Queue ;AN000;
2531 ; DI-->LRU header
2532
2533; Makesure to save all local variables before calling DELETE
2534; since, this variables may be altered by DELETE routine.
2535 mov ax,Hdr_Flag
2536 push ax
2537 mov ax,Prev_Hdr_Ptr
2538 push ax
2539 mov ax,Queue_Type
2540 push ax
2541 mov ax,Cur_Hdr_Ptr
2542 push ax
2543 mov ax,First_Phys_Clusnum ; save original first phys from OPEN call
2544 push ax ; in the stack
2545 mov cx,es:[di].FH_Phys_Clus_Num ; CX= starting phys clus num of LRU header
2546 mov From_FreeBuff,1 ; set flag
2547
2548 push ds
2549 mov ax,Cseg_Main
2550 mov ds,ax
2551 assume ds:Cseg_Main
2552 CALL VECTOR_DELETE ; delete the file
2553 pop ds
2554 assume ds:Cseg_Seek
2555
2556 mov From_FreeBuff,0 ; clear flag
2557 mov Free_Flag,1 ; set flag to indicate discontinuous free area
2558 pop ax ; restore first phys clus
2559 mov First_Phys_Clusnum,ax ; save it back where it belongs
2560 pop ax ; restore current header
2561 mov Cur_Hdr_Ptr,ax ; save it back where it belongs
2562 pop ax ; restore current header
2563 mov Queue_Type,ax ; save it back where it belongs
2564 pop ax ; restore current header
2565 mov Prev_Hdr_Ptr,ax ; save it back where it belongs
2566 pop ax ; restore current header
2567 mov Hdr_Flag,ax ; save it back where it belongs
2568 clc
2569 jmp Free_exit ; exit ;AN000;
2570
2571
2572
2573;----------------------------------------------------------------------------
2574; No space available in CLOSE Queue . Now get some free space from OPEN Queue
2575; and add it to the free area.
2576;----------------------------------------------------------------------------
2577Free_Look_Open_Queue:
2578 mov si,es:[di].MRU_Hdr_Ptr ; SI-->First header in OPEN Queue ;AN000;
2579 CALL FIND_LRU_HEADER ; find last header in Queue ;AN000;
2580 ; DI-->last header
2581 mov si,es:[di].FH_MRU_Extn_Ptr ;### SI-->first extent in this header ;AN000;
2582 cmp si, -1 ; any extent under this header ?? ;AN000;
2583 jne Free_Open_Find_Extent ; yes, find last extent ;AN000;
2584
2585; if no extents under this header, delete this header and free the space
2586 cmp di,Cur_Hdr_Ptr ; header found is its own header ?? ;AN000;
2587 jne Free_OPen_Mark_Prev ; no - free the header ;AN000;
2588 stc ; Yes - set carry, exit ;AN000;
2589 jmp Free_Exit ; ERROR exit ;AN000;
2590
2591Free_Open_Mark_Prev: ; mark previous header as LRU before deleting this header
2592 mov si,LRU_Prev_Hdr ; SI-->previous header ;AN000;
2593 mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous header as last hdr ;AN000;
2594 jmp Free_Open_Cl_Buffer ;AN000;
2595
2596Free_Open_Find_Extent:
2597 mov si,di ; SI-->header to be searched
2598 CALL FIND_LRU_EXTENT ; ### find last extent in the header ;AN000;
2599 mov di, LRU_Extent ; DI-->LRU extent
2600 cmp Extn_flag,1 ; Is this the only extent in the queue ? ;AN000;
2601 jne free_Open_prev_extn ; no, mark previous extent as last extn ;AN000;
2602 push di ; save pointer to Last extent ;AN000;
2603 mov di,LRU_Hdr ; DI-->LRU header ;AN000;
2604 mov es:[di].FH_Next_Extn_Ptr,-1 ; mark current HEADER with no extents ;AN000;
2605 mov es:[di].FH_MRU_Extn_Ptr,-1 ; ### mark current HEADER with no extents ;AN000;
2606 pop di ; DI-->LRU extent ;AN000;
2607 jmp Free_Open_Cl_Buffer ; release this extent ;AN000;
2608
2609;----------------------------------------------------------------------
2610; Mark Previous MRU extent as LRU extent and also connect the previous
2611; adjucent extent to the next adjcent extent.
2612;----------------------------------------------------------------------
2613Free_Open_Prev_Extn: ; mark previous MRU extent as LRU extnt
2614 mov si, es:[di].EH_Prev_LRU_Ptr ; no - SI-->Previous adj extent
2615 mov es:[si].EH_Next_LRU_Ptr, -1 ;mark previous extent as last extent ;AN000;
2616
2617 cmp es:[di].EH_Next_Extn_Ptr, -1 ; any next adjucent extent ??
2618 jne OPen_Join_extents ; yes - join previous to next
2619
2620 mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent
2621 cmp si, -1 ; any previous adj extent ??
2622 je Open_Prev_Hdrx ; no - previous is a header
2623 mov es:[si].EH_Next_Extn_Ptr, -1 ; mark previous extent as the last
2624 jmp short Free_Open_Cl_Buffer ; free the current extent
2625
2626Open_Prev_Hdrx:
2627 push di ; DI-->extent to be deleted
2628 mov di,LRU_Hdr ; DI-->LRU header
2629 mov es:[di].FH_Next_Extn_Ptr, -1 ; mark header with no extents
2630 mov es:[di].FH_MRU_Extn_Ptr, -1 ; mark header with no extents
2631 pop di
2632 jmp short Free_Open_Cl_Buffer ; free current extent
2633
2634Open_Join_Extents: ; DI-->current extent to be freed
2635 mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent
2636 cmp si, -1 ; any previous extent ??
2637 je Open_Prev_Hdry ; no - previous is a header - join header
2638 ; to extent
2639 mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent
2640 mov es:[si].EH_Next_Extn_Ptr,ax ; connect prev adj extent to next adj extent
2641 push di ; save addrs of extent to be deleted
2642 mov di, ax ; SI = address of previous LRU extent
2643 mov es:[di].EH_Prev_Extn_Ptr,si ; address of next LRU extent
2644 pop di ; restore address
2645 jmp short Free_Open_Cl_Buffer ; free the extent
2646
2647Open_Prev_Hdry:
2648 mov si, LRU_Hdr ; SI-->LRU_Hdr
2649 mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent
2650 mov es:[si].FH_Next_Extn_Ptr,ax ; connect hdr to next adj extent
2651 mov si,ax ; SI = addrss of next adj extent
2652 mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark no previous extent
2653 mov di,LRU_Extent ; DI-->extent to be deleted
2654
2655;----------------------------------------------------------------------------
2656; Free the current Extent or Header
2657;----------------------------------------------------------------------------
2658Free_Open_Cl_Buffer: ;
2659 mov si,di ; SI-->LRU extent or header ;AN000;
2660 mov di,Drive_Hdr_Ptr ; DI-->drive buffer ;AN000;
2661 mov ax,es:[di].Free_Ptr ;AN000;
2662 mov es:[si].EH_Next_Extn_Ptr,ax ; connect Free ptr to last ;AN000;
2663 ; extent in the queue
2664 mov ax, -2 ; discontinuous mark (-2) ;AN000;
2665 mov es:[si], ax ; mark freed area as discontinuous ;AN000;
2666 mov es:[di].Free_Ptr,si ; connect header or extent to free area ;AN000;
2667
2668; Increase the Free_Size entry in Drive Header
2669 mov ax, Size File_Header ; size is same for both header or extent ;AN000;
2670 add es:[di].Free_Size, ax ; update free buffer count ;AN000;
2671 mov Free_Flag,1 ; set flag for discontinuous free area ;AN000;
2672 clc
2673Free_Exit: ; exit
2674 ret ; return ;AN000;
2675
2676FIND_FREE_BUFFER endp
2677
2678
2679
2680
2681
2682
2683;----------------------------------------------------------------------
2684; PROCEDURE: Make_MRU_Header
2685;
2686; FUNCTION: Move header to the top of the queue. If the header is at the
2687; bottom of the queue, mark previous header as LRU header
2688; before moving the header to the top of the queue.
2689;
2690; INPUT: Drive_Hdr_Ptr - Points to drive header
2691; Cur_Hdr_Ptr - Points to current header
2692; ES--> Cache Buffer Segment
2693;
2694; OUTPUT: Header is moved to top of the current queue
2695; SI-->current header
2696;
2697;----------------------------------------------------------------------
2698
2699MAKE_MRU_HEADER PROC NEAR
2700
2701 mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000;
2702 cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header LRU header ;AN000;
2703 jne Move_close_gap ; no, jump ;AN000;
2704 ;AN000;
2705 mov di,Prev_Hdr_Ptr ; yes, make previous header
2706 mov es:[di].FH_Next_Hdr_Ptr,-1 ; LRU header ;AN000;
2707 jmp short move_to_top
2708
2709Move_Close_Gap:
2710 mov di,Prev_Hdr_Ptr ; yes, get previous header
2711 mov ax,es:[si].FH_Next_Hdr_Ptr ; get next header address
2712 mov es:[di].FH_Next_Hdr_Ptr,ax ; connect previous hdr to next hdr
2713 ;AN000;
2714Move_To_Top:
2715 mov di,drive_Hdr_Ptr ; DI-->drive buffer ;AN000;
2716 mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000;
2717 mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header ;AN000;
2718 mov es:[di].MRU_Hdr_Ptr,si ; make current header MRU hdr ;AN000;
2719 ;
2720 ret
2721
2722Make_MRU_Header ENDP
2723
2724
2725
2726
2727
2728
2729;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2730; PROCEDURE: MAKE_MRU_EXTENT
2731;
2732; FUNCTION: Move Extent to the top of the queue. If the extent is at the
2733; bottom of the queue, mark previous extent as LRU extent
2734; before moving the extent to the top of the queue. If the extent
2735; is between first and last, then close the MRU-LRU chain gap.
2736; If the extent is already MRU then exit.
2737;
2738; This routine is called if clusters are inserted or looked up
2739; from an existing extent.
2740;
2741; INPUT: Cur_Hdr_Ptr - Address of current header
2742; Cur_Extn_Ptr - Address of current extent
2743; ES--> Cache Buffer Segment
2744;
2745; OUTPUT: Extent is moved next to the current header
2746; SI-->current extent
2747;
2748;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2749
2750MAKE_MRU_EXTENT PROC NEAR
2751
2752 mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000;
2753 mov ax,Cur_Extn_Ptr
2754 cmp es:[si].FH_MRU_Extn_Ptr, ax ; current extent already MRU?? ;AN000;
2755 je Make_MRU_Exit ; yes - exit
2756
2757 mov si, Cur_Extn_Ptr ; SI-->Current extent
2758 mov di,es:[si].EH_Prev_LRU_Ptr ; get address of previous MRU extent
2759 cmp di, -1 ; any previous MRU extent ??
2760 je Make_MRU_Exit ; none - exit- current extent is already MRU
2761
2762; Close the gap (connect previous to next extent)
2763 mov si, Cur_Extn_Ptr
2764 cmp es:[si].EH_Next_LRU_Ptr, -1 ; current extent LRU extent ??
2765 jne join_the_gap ; no - close the gap
2766 mov es:[di].EH_Next_LRU_Ptr, -1 ; mark the previous extent MRU
2767 jmp short move_MRU_Extent ; make mru extent
2768
2769Join_The_Gap:
2770 mov ax, es:[si].EH_Next_LRU_Ptr ; AX-->next LRU extent
2771 mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous to next
2772 mov bx,di ; BX-->prev LRU extent
2773 mov di,ax ; DI-->Next LRU extent
2774 mov es:[di].EH_Prev_LRU_Ptr, bx ; set previous LRU extent address
2775
2776
2777; Make the current extent MRU extent
2778Move_MRU_Extent:
2779 mov di,Cur_Hdr_Ptr ; DI-->Current header
2780 mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent
2781 mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent
2782 mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent
2783 mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent
2784
2785 mov di,ax ;(12/29) set prev LRU addrs of prev MRU extent
2786 mov es:[di].EH_Prev_LRU_Ptr,si ;(12/29)
2787
2788Make_MRU_Exit:
2789 clc
2790 ret ; return
2791
2792MAKE_MRU_EXTENT ENDP
2793
2794
2795
2796
2797
2798
2799;----------------------------------------------------------------------
2800; PROCEDURE: JOIN_PREV_TO_NEXT
2801;
2802; FUNCTION: Connect previous header to next header inorder to close the
2803; gap created when a header is moved to top of the Queue or to
2804; the top of CLOSE queue. If the file header is the first header
2805; under the current Drive header, connect header to the MRU_Hdr_Ptr.
2806;
2807; INPUT: Prev_Hdr_Ptr - Points to Previous header
2808; Cur_Hdr_Ptr - Points to Current Header
2809; Queue_Type - Queue Type: 0 = Open Queue
2810; 1 = Close Queue
2811; ES--> Cache Buffer Segment
2812; OUTPUT: Gap is closed
2813;
2814;----------------------------------------------------------------------
2815
2816JOIN_PREV_TO_NEXT PROC
2817
2818 cmp Prev_Hdr_Ptr, -1 ; current hdr first file header ?? ;AN000;
2819 jne join_prev_hdr ; no, close gap ;AN000;
2820
2821; Yes, in this case close gap by connecting Drive header to next header
2822 mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000;
2823 mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000;
2824 mov ax,es:[si].FH_Next_Hdr_Ptr ; AX-->Next Header ;AN000;
2825 cmp Queue_Type, 1 ; Is this Close Queue ?? ;AN000;
2826 je Join_Sel_Close_Ptr ; Yes, jump ;AN000;
2827 mov es:[di].MRU_Hdr_Ptr,ax ; join next header to Drive Header ;AN000;
2828 jmp short join_exit ; exit ;AN000;
2829
2830Join_Sel_Close_Ptr:
2831 mov es:[di].Close_Ptr,ax ; join next header to Drive Header ;AN000;
2832 jmp short join_exit ; exit ;AN000;
2833
2834
2835; Connect previous header to next header ( close the gap )
2836Join_Prev_Hdr:
2837 mov di,Prev_Hdr_Ptr ; DI-->Previous header ;AN000;
2838 mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000;
2839 mov ax,es:[si].FH_Next_Hdr_Ptr ; connect previous header ;AN000;
2840 mov es:[di].FH_Next_Hdr_Ptr,ax ; to next header ;AN000;
2841
2842Join_Exit:
2843 ret ; exit ;AN000;
2844
2845JOIN_PREV_TO_NEXT ENDP
2846
2847
2848
2849
2850
2851
2852;----------------------------------------------------------------------
2853; PROCEDURE: UPDATE_FREE_AREA
2854;
2855; FUNCTION: Update Free area pointer and Free area size before creating
2856; a new extent or new header
2857;
2858; INPUT: Prev_Hdr_Ptr - Points to Previous header
2859; Cur_Hdr_Ptr - Points to Current Header
2860; Queue_Type - Queue Type: 0 = Open Queue
2861; 1 = Close Queue
2862; Free_Flag - Free area type: 0 = continous free area
2863; 1 = non-contiguous free area
2864; ES--> Cache Buffer Segment
2865;
2866;
2867; OUTPUT: Free pool address and size is updated
2868;
2869;----------------------------------------------------------------------
2870
2871UPDATE_FREE_AREA PROC
2872
2873 mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000;
2874 mov si,es:[di].Free_Ptr ; SI-->current free pointerted ;AN000;
2875 ;
2876 mov ax, Size Extent_Header ;AN000;
2877 sub es:[di].Free_Size, ax ; update free area size ;AN000;
2878
2879 cmp Free_Flag, 1 ; continuous free area ?? ;AN000;
2880 jne ext_add_free_ptr ; yes - update free area pointer ;AN000;
2881
2882;----------------------------------------------------------------------
2883; If discontinuous Free area. Update the Free pointer by getting pointer
2884; to next free from the 4th word using header or extent structure.
2885; This is because the discontinuous areas are connected chained through
2886; the 4th word
2887;----------------------------------------------------------------------
2888 mov ax,es:[si].FH_Next_Hdr_Ptr ; no, update FREE area pointer ;AN000;
2889 mov es:[di].Free_Ptr,ax ; using the Header structure ;AN000;
2890 jmp short Update_Free_Exit ; Exit ;AN000;
2891
2892;----------------------------------------------------------------------
2893; If continuous Free area. Next free area address is computed by adding
2894; the size of extent of header structure.
2895;----------------------------------------------------------------------
2896Ext_Add_Free_Ptr:
2897 mov ax, size File_Header ; calculate the address of ;AN000;
2898 add es:[di].Free_Ptr,ax ; next free area by adding size of ;AN000;
2899 ; a extent or header. Both same size
2900Update_Free_Exit:
2901 ret ; exit ;AN000;
2902
2903UPDATE_FREE_AREA ENDP
2904
2905
2906
2907
2908;----------------------------------------------------------------------
2909; Procedure: CHECK_IT Checks the validity of the queues
2910;
2911;----------------------------------------------------------------------
2912
2913CHECK_IT PROC NEAR
2914
2915 pushf ; save all registers
2916 push bx
2917 push di
2918 cmp check_flag,0
2919 je check_exit
2920 mov ah,090h
2921 xor al,al
2922 xor cx,cx
2923 mov cl,func_cod
2924 mov di, Drive_Hdr_Ptr
2925 INT 2FH
2926check_exit:
2927 pop di
2928 pop bx
2929 popf
2930 ret
2931
2932CHECK_IT ENDP
2933
2934
2935
2936; Calculate the size of the Cseg_Seek module in bytes
2937 IF ($-Cseg_Seek) MOD 16 ;AN000;
2938 ORG ($-Cseg_Seek)+16-(($-Cseg_Seek) MOD 16) ;AN000;
2939 ENDIF ;AN000;
2940END_SEEK label word
2941
2942
2943CSEG_SEEK ENDS
2944 END
diff --git a/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC b/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC
new file mode 100644
index 0000000..fd6c46d
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC
@@ -0,0 +1,20 @@
1
2
3
4.seq
5stack segment Stack 'STACK' ; represents STACK ;AN000;
6stack ends ;AN000;
7
8cseg_main segment Public 'CODE'; represents MAIN
9cseg_main ends
10
11cseg_open segment Public 'CODE'; represents FASTOPEN ;AN000;
12cseg_open ends ;AN000;
13
14cseg_seek segment Public 'CODE'; represents FASTSEEK ;AN000;
15cseg_seek ends ;AN000;
16
17cseg_init segment Public 'CODE' ; represents INIT
18cseg_init ends
19
20 \ No newline at end of file
diff --git a/v4.0/src/CMD/FASTOPEN/FASTSM.ASM b/v4.0/src/CMD/FASTOPEN/FASTSM.ASM
new file mode 100644
index 0000000..b2dad14
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTSM.ASM
@@ -0,0 +1,145 @@
1 PAGE 90,132 ;A2
2 TITLE fastsm.SAL - fastopen SYSTEM MESSAGES
3;****************** START OF SPECIFICATIONS *****************************
4; MODULE NAME: fastsm.SAL
5
6; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT
7; configuration expected by the modules of fastopen.
8
9;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a
10; part of the fastopen module by using INCLUDE to bring in the
11; common portion, in SYSMSG.INC. This included code contains
12; the routines to initialize for message services, to find
13; where a particular message is, and to display a message.
14
15; ENTRY POINT: SYSDISPMSG:near
16; SYSGETMSG:near
17; SYSLOADMSG:near
18
19; INPUT:
20; AX = MESSAGE NUMBER
21; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12)
22; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE
23; CX = NUMBER OF %PARMS, 0 IF NONE
24; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW
25; CALL SYSDISPMSG ;DISPLAY THE MESSAGE
26
27; If carry set, extended error already called:
28; AX = EXTENDED MESSAGE NUMBER
29; BH = ERROR CLASS
30; BL = SUGGESTED ACTION
31; CH = LOCUS
32; _ _ _ _ _ _ _ _ _ _ _ _
33
34; AX = MESSAGE NUMBER
35; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG)
36; CALL SYSGETMSG ;FIND WHERE A MSG IS
37
38; If carry set, error
39; CX = 0, MESSAGE NOT FOUND
40; If carry not set, ok, and resulting regs are:
41; CX = MESSAGE SIZE
42; DS:SI = MESSAGE TEXT
43; _ _ _ _ _ _ _ _ _ _ _ _
44
45; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION
46; If carry not set:
47; CX = SIZE OF MSGS LOADED
48
49; If carry is set, regs preset up for SYSDISPMSG, as:
50; AX = ERROR CODE IF CARRY SET
51; AX = 1, INCORRECT DOS VERSION
52; DH =-1, (Utility msg)
53; OR,
54; AX = 1, Error loading messages
55; DH = 0, (Message manager error)
56; BX = STDERR
57; CX = NO_REPLACE
58; DL = NO_INPUT
59
60; EXIT-NORMAL: CARRY is not set
61
62; EXIT-ERROR: CARRY is set
63; Call Get Extended Error for reason code, for SYSDISPMSG and
64; SYSGETMSG.
65
66; INTERNAL REFERENCES:
67; ROUTINES: (Generated by the MSG_SERVICES macro)
68; SYSLOADMSG
69; SYSDISPMSG
70; SYSGETMSG
71
72; DATA AREAS:
73
74; INCLUDE SYSMSG.INC ;Permit System Message handler definition
75;
76; EXTERNAL REFERENCES:
77; ROUTINES: none
78
79; DATA AREAS: control blocks pointed to by input registers.
80
81; NOTES:
82
83; To assemble these modules, the alphabetical or sequential
84; ordering of segments may be used.
85
86; For LINK instructions, refer to the PROLOG of the main module,
87; fastopen.asm.
88
89; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
90;
91; COPYRIGHT: "MS DOS FASTOPEN Utility"
92; "Version 4.00 (C)Copyright 1988 Microsoft "
93; "Licensed Material - Property of Microsoft "
94;
95;****************** END OF SPECIFICATIONS *****************************
96 IF1 ; ;AN000;
97 %OUT COMPONENT=fastopen, MODULE=fastsm.asm...
98 ENDIF ; ;AN000;
99; = = = = = = = = = = = =
100
101HEADER MACRO TEXT ;; ;AN000;
102.XLIST ;;
103 SUBTTL TEXT
104.LIST ;;
105 PAGE ;; ;AN000;
106 ENDM ;; ;AN000;
107; = = = = = = = = = = = =
108 INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000;
109 MSG_UTILNAME <fastopen> ;IDENTIFY THE COMPONENT ;AN000;
110; = = = = = = = = = = = =
111 HEADER <DEFINITION OF MESSAGES> ; ;AN000;
112CSEG_INIT SEGMENT PARA PUBLIC 'CODE' ;
113 ASSUME CS:CSEG_INIT ;ESTABLISHED BY CALLER
114 ASSUME DS:CSEG_INIT ;ESTABLISHED BY CALLER
115 ASSUME ES:CSEG_INIT ;ESTABLISHED BY CALLER
116
117 PUBLIC COPYRIGHT ; ;AN000;
118COPYRIGHT DB "MS DOS FASTOPEN Utility " ; ;AN000;
119 INCLUDE COPYRIGH.INC ; ;AN000;
120 HEADER <MESSAGE DATA AREAS> ; ;AN000;
121 MSG_SERVICES <MSGDATA> ;WORKAREAS FOR SYSTEM MESSAGE HANDLER ;AN000;
122; = = = = = = = = = = = =
123 HEADER <SYSTEM MESSAGE HANDLER> ; ;AN000;
124 PUBLIC SYSLOADMSG ; ;AN000;
125 PUBLIC SYSDISPMSG ; ;AN000;
126
127
128 MSG_SERVICES <FASTOPEN.CLA,FASTOPEN.CL1,FASTOPEN.CL2> ;
129
130 ;DEFAULT=CHECK DOS VERSION
131 ;DEFAULT=NEARmsg
132 ;DEFAULT=INPUTmsg
133 ;DEFAULT=NUMmsg
134 ;DEFAULT=NO TIMEmsg
135 ;DEFAULT=NO DATEmsg
136
137.xlist
138.xcref
139 MSG_SERVICES <LOADmsg,GETmsg,DISPLAYmsg,INPUTmsg,CHARmsg,NUMmsg> ;AN000;
140 include msgdcl.inc
141.cref
142.list
143; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
144CSEG_INIT ENDS ;
145 END ; ;AN000;
diff --git a/v4.0/src/CMD/FASTOPEN/MAKEFILE b/v4.0/src/CMD/FASTOPEN/MAKEFILE
new file mode 100644
index 0000000..8911afe
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/MAKEFILE
@@ -0,0 +1,47 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12all: fastopen.exe
13
14fastopen.ctl: fastopen.skl makefile $(msg)\$(COUNTRY).msg
15
16fastopen.obj: fastopen.asm $(inc)\fastopen.inc \
17 makefile
18
19fastseek.obj: fastseek.asm $(inc)\fastopen.inc \
20 makefile
21
22fastinit.obj: fastinit.asm $(inc)\dossym.inc $(inc)\fastopen.inc \
23 makefile
24
25fastp.obj: fastp.asm \
26 makefile \
27 $(inc)\psdata.inc \
28 $(inc)\parse.asm
29
30fastsm.obj: fastsm.asm \
31 makefile \
32 $(inc)\versiona.inc \
33 $(inc)\copyrigh.inc \
34 $(inc)\sysmsg.inc \
35 $(inc)\msgserv.asm \
36 fastopen.ctl \
37 fastopen.cl1 \
38 fastopen.cl2 \
39 fastopen.cla \
40
41fastopen.exe: fastopen.obj \
42 fastopen.lnk \
43 fastseek.obj \
44 fastinit.obj \
45 fastp.obj \
46 fastsm.obj
47 link @fastopen.lnk