summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM
blob: 90b9118a0863e2b2d1fda1e9f0edc1ea18c96d63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
	Page 84,132 ;
Title	FASTOPEN

;--------------- INCLUDE FILES -----------------
.xcref
.xlist
debug=0 		  ;this is an equate only for DOSMAC.inc
INCLUDE DOSMAC.inc
.list
.cref
INCLUDE dirent.inc
INCLUDE fastsegs.inc	  ; Cannot declare this in DOS includes
INCLUDE fastopen.inc	  ; This include file also contains DOS equates


CSEG_MAIN   SEGMENT   PARA   PUBLIC 'CODE'       ; Cseg_Seek segment

EXTRN	VECTOR_DELETE:dword	; jump vector inside Cseg_Seek to make
				; a FAR call to FSeek Delete function within
				; the segment

CSEG_MAIN      ENDS


;*****************************************************************************
; ALL FastSeek functions are kept in a seperate segment.  They are accessed
; by a FAR indirect call from the MAIN routine.

; ADDRESSABILTY: DS is for accessing local data in Cseg_Seek segment
;		 ES is for accessing data in the extent cache buffer
;					  in the Cseg_Init segment
;		 On entry, only DS is set, ES is set to Cache segment later
;*****************************************************************************

CSEG_SEEK   SEGMENT   PARA   PUBLIC 'code'
	 assume  cs:cseg_seek,ds:nothing,es:nothing,ss:nothing

PUBLIC	 Seek_name_cache_seg									   ;AN000;
PUBLIC	 Seek_Num_Of_drives
PUBLIC	 Seek_extent_drive_Buff 								   ;AN000;
PUBLIC	 Seek_Total_Ext_Count									   ;AN000;
PUBLIC	 Seek_Total_Name_Count									   ;AN000;
PUBLIC	 Seek_Name_Drive_Buff									   ;AN000;
PUBLIC	 Seek_Name_Cache_Buff									   ;AN000;
PUBLIC	 End_Seek
PUBLIC	 Check_Flag
												   ;AN000;
PUBLIC	 Fk_Open
PUBLIC	 Fk_Close										   ;AN000;
PUBLIC	 Fk_Insert										   ;AN000;
PUBLIC	 Fk_Delete
PUBLIC	 Fk_Lookup										   ;AN000;
PUBLIC	 Fk_Truncate
PUBLIC	 Fk_Purge


;;---------- FASTSEEK LOCAL VARIABLES ---------------------

First_Phys_ClusNum   dw      0		; first phys clus num of file (file id) 	       ;AN000;
Logical_ClusNum      dw      0		; logical cluster num to be searched					     ;AN000;
Physical_ClusNum     dw      0		; physical clus num of above logical clus num								;AN000;
Extent_buff_Ptr      dw      0		; starting offset of extent cache			   ;AN000;
drv_id		     db      -1 	; drive id of last fastseek function
func_cod	     db      0		; function code

Cur_Hdr_Ptr	     dw      0		; address of current header				  ;AN000;
Cur_Extn_Ptr	     dw      0		; address of current extent				 ;AN000;
New_Extn_Ptr	     dw      0		; address of area where new extent will be created
New_Hdr_Ptr	     dw      0		; address of area where new header will be created	   ;AN000;
Prev_Hdr_Ptr	     dw      0		; address of previous header				  ;AN000;
Prev_Extn_Ptr	     dw      0		; address of previous extent				   ;AN000;

Prev_MRU_Extn_Ptr    dw      0		; address of previous MRU extent			       ;AN000;
LRU_Prev_Hdr	     dw      0		; address of previous hdr to the LRU header			  ;AN000;
LRU_Prev_Extent      dw      0		; address of previous extent to LRU extent							     ;AN000;
LRU_Extent	     dw      0		; address of LRU extent 				  ;AN000;
LRU_Hdr 	     dw      0		; address of LRU header 				  ;AN000;

Drive_Hdr_Ptr	     dw      0		; address of drive header of current drive				   ;AN000;
From_FreeBuff	     dw      0		; 1 = if call from Free_Buff routine					   ;AN000;
Hdr_Flag	     dw      0		; 1 = current header is the only
					; remaining header in Queue
Extn_Flag	     dw      0		; 1 = current extent is the only			   ;AN000;;AN000;
					; remaining extent under this header
Fully_Flag	     dw      0		; 1= cluster fully found in extent			   ;AN000;;AN000;
					; 0= cluster partially found
Find_Flag	     dw      0		; # = specifies the relative location of the new cluster							 ;AN000;
Open_Queue_Flag      dw      0		; 1 = if open queue is empty							     ;AN000;
Free_Flag	     dw      0		; Free area Type: 0 - continuous			    ;AN000;
					;		  1 - non-continuous
Queue_Type	     dw      0		; Queue Type:  0 - Open Queue				   ;AN000;
					;	       1 - Close Queue
phys_num	     dw      0		; ** for queue analyser
logic_num	     dw      0		; ** for queue analyser


; Following data area is initialized during initialization
Check_Flag		     dw      0
Seek_name_cache_seg	     dw      Cseg_Init	     ; Seg ID of Ccahe buffer
Seek_Num_Of_drives	     dw      0		     ; number of drives 			   ;AN000;
Seek_Total_Name_Count	     dw      0		     ; total name count
Seek_Total_Ext_Count	     dw      0		     ; total extent count
Seek_Name_Drive_Buff	     dw      0		     ; starting address of name drive buffers		;AN000;
Seek_Name_Cache_Buff	     dw      0		     ; starting address of name cahe buffers		;AN000;
Seek_extent_drive_Buff	     dw      0		     ; starting address of extent			;AN000;
						     ; cache in the cache buffer




;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; PROCEDURE: FK_OPEN
;
; FUNCTION: Create and initialize a file header  using	the  starting
;	    Physical  Cluster  number (file id) of the file.
;
;	    If the file header already exist in the OPEN Queue, then increase
;	    the file reference count by one and make the header
;	    MRU header.
;
;	    If header is not found in the OPEN Queue, then check to
;	    see if it exists in the CLOSE Queue.  If found in the
;	    CLOSE Queue, move the header and the extents to the top of
;	    OPEN Queue and make the header MRU header.
;
;	    If the header is not found in both Queues, create  a new
;	    header at the top of the OPEN Queue and initialize with the
;	    given first physical cluster number.
;
;	    If not enough space for new header in OPEN Queue, find the
;	    LRU header and Last Exetent in the CLOSED Queue. Delete this
;	    extent and use the space for the new header.  If none in
;	    CLOSE Queue, find the LRU header and the LRU extent in the
;	    OPEN Queue.  Delete this extent and use this space.
;
;
; INPUT:   CX = First Physical Cluster Number of the file
;	   DL = Drive ID
;
;
; OUTPUT:  Created a new file header. If header already exist, then the file
;	   reference count is incremented by one.
;
; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;-------------------------------------------------------------------------------


FK_OPEN    PROC    FAR

       push   cs			 ; establish addressability				   ;AN000;
       pop    ds			 ; DS --> code segment					   ;AN000;
       assume ds:Cseg_Seek									   ;AN000;
       mov    es, Seek_Name_Cache_Seg	 ; setup cache buff segment			   ;AN000;
       assume es:Cseg_Init		 ; ES --> cache buffer segment				   ;AN000;
       mov    First_Phys_Clusnum,cx	 ; save physical cluster number 			       ;AN000;
       mov    func_cod,al

;-------------------------------------------------------------------------------
; Search for Drive header in the cache buffer using Drive ID in DL
;-------------------------------------------------------------------------------
       CALL   FIND_DRIVE_HEADER 	 ; get drive buffer Header				   ;AN000;
					 ; DI-->drive header
       jnc    open_Search_Header	 ; header found - check for file header      ;AN000;
       jmp    open_exit 		 ; drive header not found - exit			 ;AN000;

;------------------------------------------------------------------------------
; Check if both OPEN and CLOSE Queues are empty.  If empty, create a new
; file header at the top of OPEN Queue.  If there are headers, search OPEN
; queue.  If found, increment file count by one.  If not found, check if
; the  file header exists in  CLOSE Queue.  If found, move header to the
; top of the OPEN Queue.
;------------------------------------------------------------------------------
Open_Search_Header:
       inc    es:[di].Extent_Count	 ; increment sequence count ( DEBUG)
       mov    ax,es:[di].Buff_Size	 ; total buffer size equal				   ;AN000;
       cmp    es:[di].Free_Size,ax	 ; to current free area 				   ;AN000;
       jne    Search_Open_List		 ; yes, check OPEN and CLOSE Queues			   ;AN000;
					 ; for header
       jmp    Open_Make_Hdr		 ; no, make new header					   ;AN000;


;------------------------------------------------------------------------------
; Search for  header in the OPEN Queues. If found, increment file reference
; count by one.
;------------------------------------------------------------------------------

Search_Open_List:
       mov   cx,First_Phys_Clusnum	 ; CX = first phys clus number				   ;AN000;
       mov   si,es:[di].MRU_Hdr_Ptr								   ;AN000;
       cmp   si, -1			 ; Any header in OPEN Queue ??				   ;AN000;
       je    Open_Chk_Close_list	 ; none, check CLOSE Queue				   ;AN000;

       CALL  FIND_FILE_HEADER		 ; search header in OPEN Queue				 ;AN000;
       jc    Open_chk_CLOSE_list	 ; if not found check in CLOSE Queue			   ;AN000;

;------------------------------------------------------------------------------
; Found in the OPEN Queue. Now, increment the file reference count by one
; and also make the header MRU header. If header found is LRU header then
; make previous header LRU header. If header is not LRU header, connect
; previous header to next header. If the header is the first header in the
; Queue, dont make it to MRU header since it is already at the top of Queue.
;------------------------------------------------------------------------------
					 ; DI-->Header found
       inc  es:[di].FH_refer_Count	 ; increment file reference count			;AN000;
       cmp   Hdr_Flag, 1		 ; current header Single header ??			;AN000;
       jne   Open_Chk_Last_Hdr		 ; No, Check for last header				;AN000;
       clc				 ; make sure caary is clear
       jmp   Open_Exit			 ; yes, exit						;AN000;

Open_Chk_Last_Hdr:
       cmp   Hdr_Flag, 3		 ; current header LRU header ?? 			;AN000;
       jne   Open_Join_Gap		 ; no, close the gap					;AN000;

Mark_Previous_Hdr:			 ; yes - mark previous hdr
       mov   si, Prev_Hdr_Ptr									   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,-1     ; yes, Mark previous Hdr LRU hdr			   ;AN000;

; Make current Hdr  MRU header. No need to close the gap
       CALL  MAKE_MRU_HEADER		 ; move header to top of Queue				   ;AN000;
       clc				 ; make sure caary is clear
       jmp   Open_Exit			 ; then EXIT						   ;AN000;


;-----------------------------------------------------------------------------
; Comes here if current header is first of many headers or in between a previous
; and next header. Make current header MRU header and close the gap.
;-----------------------------------------------------------------------------
Open_Join_Gap:
					 ; DI-->Current header
       cmp   Hdr_Flag, 2		 ; current Header First Hdr in Queue ?? 		   ;AN000;
       jne   Open_Make_MRU_Hdr		 ; no, jump						   ;AN000;
       clc				 ; MAKE SURE caary is clear
       jmp   Open_Exit			 ; yes, no need to make MRU hdr, or			   ;AN000;
					 ; or close the gap

Open_Make_MRU_Hdr:			 ; header is between 1st and last headers
       CALL  MAKE_MRU_HEADER		 ; move header to top of Queue				    ;AN000;

       clc				 ; make sure caary is clear
       jmp   Open_exit			 ; then EXIT						   ;AN000;


;------------------------------------------------------------------------------
; Look for a header in the CLOSE Queue.  If found, move file header and
; and extents (if any) to top of OPEN Queue. If not found in the CLOSE
; queue, create a new header at the top of OPEN queue.
;------------------------------------------------------------------------------
Open_Chk_Close_List:
       mov    di,drive_Hdr_Ptr		 ; DI-->current drive header				   ;AN000;
       cmp    es:[di].CLOSE_Ptr,-1	 ; anything in CLOSE Queue ??				   ;AN000;
       jne    open_search_hdr		 ; if any, search CLOSE Queue				   ;AN000;
       jmp    open_make_hdr		 ; if none, make a new header				   ;AN000;


;------------------------------------------------------------------------------
; CLOSE Queue is not empty, next search  for header in the CLOSE Queue using
; starting physical cluster number of the file.
;------------------------------------------------------------------------------
Open_Search_Hdr:			 ;
       mov   si,es:[di].Close_Ptr	 ; SI-->first header in the				;AN000;
					 ; in the CLOSE  Queue					   ;AN000;
       mov   cx,First_Phys_Clusnum	 ; CX = first phys clus number				   ;AN000;
       CALL  FIND_FILE_HEADER		 ; find file header in CLOSE Queue			    ;AN000;
					 ; DI-->header found
       jnc   open_chk_only_hdr		 ; if found, check only header				   ;AN000;
       jmp   short open_make_hdr	 ; if not, make a new header				   ;AN000;

;------------------------------------------------------------------------------
; Found header in the CLOSE Queue. Check if the header found is the single HDR
; in the CLOSE Queue, If single header, then, mark the CLOSE Queue as empty
; before copy the this header to the OPEN Queue.
;------------------------------------------------------------------------------
Open_Chk_only_Hdr:			 ;
       cmp   Hdr_flag, 1		 ; Only Header in the CLOSE Queue??				   ;AN000;
       jne   Open_chk_Last_header	 ; if not check header is LRU header			       ;AN000;

       mov   di,Drive_Hdr_Ptr		 ; only header in the CLOSE Queue			   ;AN000;
       mov   es:[di].Close_Ptr,-1	 ; mark CLOSE Queue as empty				   ;AN000;
       jmp   short Open_Move_Hdr	 ; then move header to OPEN Queue			   ;AN000;

;------------------------------------------------------------------------------
; Current header is not the only header in the CLOSE Queue. Now check if the
; current header is the LRU header in CLOSE Queue.  If true, mark previous
; header as LRU header before moving it from from CLOSE Queue to OPEN queue.
;------------------------------------------------------------------------------
Open_Chk_Last_Header:			 ;
       cmp   Hdr_Flag, 3		 ; Current header last header ??			   ;AN000;
       jne   Open_Close_gap		 ; no, close the gap before move it			;AN000;
					 ; to OPEN Queue
       mov   si, Prev_Hdr_Ptr									   ;AN000;
       mov   es:[si].Fh_Next_Hdr_Ptr,-1  ; yes, mark the previous hdr as last			   ;AN000;
       jmp   short open_move_Hdr	 ; header then move to the top of			   ;AN000;
					 ; OPEN Queue

;------------------------------------------------------------------------------
; Close the gap in the CLOSE Queue.
;------------------------------------------------------------------------------
Open_Close_Gap:
       mov   Queue_Type, 1		 ; set flag to indicate CLOSE Queue			   ;AN000;
       CALL  JOIN_PREV_TO_NEXT		 ; join previous header to next header			   ;AN000;

;------------------------------------------------------------------------------
; Now move the current header from CLOSE Queue to top of OPEN Queue
;------------------------------------------------------------------------------
Open_Move_Hdr:
       mov   si,Cur_Hdr_Ptr		 ; SI-->Current header					;AN000;
       mov   di,drive_Hdr_Ptr		 ; DI-->drive header					;AN000;

;------------------------------------------------------------------------------
;Update the file refernce count to 1 before move header to OPEN Queue
;------------------------------------------------------------------------------
       mov   es:[si].FH_Refer_Count, 1	    ; set refernce count = 1				   ;AN000;
       mov   ax,es:[di].MRU_Hdr_Ptr	    ; address of current MRU header			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax     ; connect new header to the 			   ;AN000;
					    ; current MRU header
       mov   es:[di].MRU_Hdr_Ptr,si	    ; make the header MRU header			   ;AN000;
       clc											   ;AN000;
       jmp   short open_exit		    ; then exit.					      ;AN000;

;------------------------------------------------------------------------------
; If header is not found in both OPEN  and CLOSE Queues, then make a new
; header in the next available free area and initialize the new header and
; make it MRU header (mov it to the top of the OPEN Queue).
; If no free space to create a new header, get space from CLOSE Queue.
; If none in CLOSE Queue, then get space from from OPEN Queue. See the
; Procedure (Find_Free_Buffer )
;------------------------------------------------------------------------------
Open_Make_Hdr:

       CALL   MAKE_NEW_HEADER		 ; create new header					   ;AN000;
       clc											   ;AN000;

Open_exit:
       CALL   Check_it
       ret				 ; return						   ;AN000;

Fk_Open   endp







;--------------------------------------------------------------------------
; PROCEDURE: FK_CLOSE
;
; FUNCTION:  Search for the header on OPEN Queue.  If the header is found,
;	     decrement the file reference count by one.  If the resultant
;	     count is zero, then move the header and the extents under it
;	     to the CLOSE Queue.  If not, make the header MRU header in the
;	     OPEN Queue.
;
; INPUT:     DL = Drive Number
;	     CX = First Physical Cluster Number of the file
;
; OUTPUT:    Moved the file header and the extents to the close Queue
;
; ROUTINES REFERENCED:	Find_File_Header, Find_Drive_Header
;
; REVISION HISTORY:  New  (5/87)
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;---------------------------------------------------------------------------

FK_CLOSE    PROC   FAR
												   ;AN000;
; Search for Drive header in the Cache buffer using Drive ID in DL
       push   cs			 ; establish addressability				   ;AN000;
       pop    ds			 ; DS --> code segment					   ;AN000;
       assume ds:Cseg_Seek									   ;AN000;
       mov    es, Seek_Name_Cache_Seg	 ; setup cache buff segment register			   ;AN000;
       assume es:Cseg_Init		 ; ES --> cache buffer segment				   ;AN000;
       mov    First_Phys_Clusnum, CX	 ; save phys cluster number				   ;AN000;
       mov    func_cod,al

       CALL   FIND_DRIVE_HEADER 	 ; search for drive header
					 ; DI-->Current drive buffer
       jnc    Close_search_hdr		 ; found, search for file header			   ;AN000;
       clc				 ; MAKE SURE carry is clear
       jmp    Close_Exit		 ; not found, error					   ;AN000;

;--------------------------------------------------------------------------
; Search for file header in the OPEN Queue using given physical cluster number
;--------------------------------------------------------------------------
Close_Search_Hdr:
       inc    es:[di].Extent_Count	 ; increment sequence coutn (DEBUG)
       mov   si,es:[di].MRU_Hdr_Ptr	 ; SI-->first header in OPEN Queue			   ;AN000;
       mov   cx,First_Phys_Clusnum	 ; CX = First phys clus num				   ;AN000;
       CALL  FIND_FILE_HEADER		 ; find the header in OPEN Queue
					 ; DI-->header found					;AN000;
       jnc   Close_Chk_Last_Hdr 	 ; jump if header found 				   ;AN000;
       clc				 ; clear carry							      ;AN000;
       jmp   short close_exit		 ; headr not found - exit					    ;AN000;

;--------------------------------------------------------------------------
; Check if the header found is the only header in the OPEN  Queue. If true
; go and decrement file reference count by one.
;--------------------------------------------------------------------------
Close_Chk_Last_Hdr:
       cmp   Hdr_Flag, 1		 ; Only header in the Queue ??				      ;AN000;
       je    Dec_Ref_Count		 ; yes -  decrement count, if count =0			     ;AN000;
					 ; then move to the top of CLOSE Queue
       cmp   Hdr_Flag, 3		 ; no - Last Header in the CLOSE Queue??			;AN000;
       jne   Close_Join_Hdr		 ; no, close gap					   ;AN000;
       mov   si,Prev_Hdr_Ptr		 ; make the previous header LRU Hdr			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr, -1    ; mark previous hdr 				   ;AN000;
       jmp   short Dec_Ref_Count	 ; decrement count and move to				   ;AN000;
					 ; CLOSE Queue

;--------------------------------------------------------------------------
; Connect previous header to next header to close the gap in OPEN Queue
;--------------------------------------------------------------------------
Close_Join_Hdr:
       mov   si,Cur_Hdr_Ptr		 ; SI-->Current header
       dec   es:[si].FH_Refer_Count	 ; decrement fiel refernce count
       cmp   es:[si].FH_Refer_Count,0	 ; count = 0 ??
       jne   Close_Make_MRU		 ; no - make current header MRU header

       mov   Queue_Type, 0		 ; else set flag to indicate OPEN Queue 			;AN000;
       CALL  JOIN_PREV_TO_NEXT		 ; close gap before move to CLOSE queue 					    ;AN000;
       jmp   short move_to_Close_List	 ; move header to CLOSE queue

;--------------------------------------------------------------------------
; Decrement the reference count by one.  If count = 0, then move the header to
; the top of CLOSE Queue.  Else, dont move to CLOSE queue, since the file has
; have multiple open before.  In this case make the header MRU header in the
; OPEN queue.
;--------------------------------------------------------------------------
Dec_Ref_Count:
       mov   si,Cur_Hdr_Ptr		  ; SI-->Current header 				;AN000;
       dec  es:[si].FH_Refer_Count	  ; decrement refernece count				   ;AN000;
       cmp  es:[si].FH_Refer_Count,0	  ; reference count = 0 ??				   ;AN000;
       je   Move_to_Close_List		  ; yes, move header to CLOSE Queue			   ;AN000;

;--------------------------------------------------------------------------
; Else, move current Header to top of OPEN Queue.  Move to the top of the queue
; only if the header is not the first header in the queue.
;--------------------------------------------------------------------------
Close_Make_MRU:
       cmp   Prev_Hdr_Ptr,-1		 ; first header in the Queue ?? 			   ;AN000;
       je    Dont_Move_To_Top		 ; yes, dont move to top				   ;AN000;

       CALL  MAKE_MRU_HEADER		 ; move header to top of queue				   ;AN000;

Dont_Move_To_Top:
       clc											   ;AN000;
       jmp   short Close_Exit		   ; exit						     ;AN000;


;--------------------------------------------------------------------------
; Move header to the top  of the CLOSE Queue. If the header is the only header
; header in the OPEN Queue, mark OPEN Queue empty.
;--------------------------------------------------------------------------
Move_To_Close_List:
       mov    si,Cur_Hdr_Ptr		    ; SI-->Cur_Hdr_Ptr					   ;AN000;
       cmp    hdr_flag,1		    ; single header in the Queue ??			      ;AN000;
       jne    Join_To_Close_List	    ; no, move header to CLOSE queue			       ;AN000;
       mov    di,Drive_Hdr_Ptr									   ;AN000;
       mov    es:[di].MRU_Hdr_Ptr, -1	    ; else mark OPEN Queue empty			      ;AN000;

Join_To_Close_List:
       mov    di,Drive_Hdr_Ptr		    ; DI-->current drive header 			      ;AN000;
       mov    ax,es:[di].Close_Ptr	    ; connect current header to the			   ;AN000;
       mov    es:[si].FH_Next_Hdr_Ptr,ax    ; previous first hdr in CLOSE queue 		   ;AN000;
       mov    es:[di].Close_Ptr,si	    ; make the current header first
					 ; header in the CLOSE queue
       clc											   ;AN000;

Close_Exit:
       CALL   Check_it
       ret				 ; return						   ;AN000;

FK_CLOSE   ENDP






;------------------------------------------------------------------------
;
; PROCEDURE: FK_DELETE
;
; FUNCTION:  Delete a specific header and extents under the header
;	     and release the buffers to the FREE pool
;
;	     Search OPEN Queue for file header. If found, delete header and
;	     extents and release the buffer to FREE area.  If not found in OPEN
;	     queue, search CLOSE Queue.  If found, delete header and extents
;	     under the header and release the area to FREE area.
;
; INPUT:   CX = First Physical Cluster Number of the file
;	   DL = drive id
;
; OUTPUT:  The file header and the extents are deleted
;
; ROUTINES REFERENCED:	Find_File_Header, Find_Drive_Header
;
; REVISION HISTORY:  New  (5/87)
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;-------------------------------------------------------------------------

FK_DELETE   PROC   FAR

       push   cs			 ; establish addressability				   ;AN000;
       pop    ds			 ; DS --> code segment					   ;AN000;
       assume ds:Cseg_Seek									   ;AN000;
       mov    es, Seek_Name_Cache_Seg	 ; setup cache buff segment register			   ;AN000;
       assume es:Cseg_Init		 ; ES --> cache buffer segment				   ;AN000;
       mov    First_Phys_Clusnum,cx	 ; save phys cluster number				   ;AN000;
       mov    func_cod,al

;--------------------------------------------------------------------------
; If the delete call is from Free_Buff, then go straight to file header
; search. Else usual delete request from DOS
;--------------------------------------------------------------------------
       cmp    From_FreeBuff,1		 ; call from Free_Buff routine ??
       je     Del_Search_Close_List	 ; yes - find file header in CLOSE queue

;--------------------------------------------------------------------------
; Search for Drive Cache buffer using Drive ID in DL
;--------------------------------------------------------------------------
       CALL   FIND_DRIVE_HEADER 	 ; get drive buffer					   ;AN000;
       jnc    Delete_search_hdr 	 ; found, search for file header			   ;AN000;
       jmp    Delete_Exit		 ; not found, error					   ;AN000;

;--------------------------------------------------------------------------
; Search for a header in the OPEN  Queue using given physical cluster  number
;--------------------------------------------------------------------------
Delete_Search_Hdr:
       inc    es:[di].Extent_Count	 ; ;***;
       mov   si,es:[di].MRU_Hdr_Ptr	 ; SI-->first header in the				;AN000;
					 ; in the OPEN queue					  ;AN000;
       cmp   si, -1			 ; any header in OPEN Queue ??				   ;AN000;
       je    Del_search_Close_list	 ; none, search CLOSE queue				   ;AN000;
       mov   cx,First_Phys_Clusnum	 ; CX = first phys clus number				   ;AN000;
       CALL  FIND_FILE_HEADER		 ; find the header in OPEN queue			  ;AN000;
       jnc   Del_Open_Last_Hdr		 ; if found, jump					   ;AN000;


;--------------------------------------------------------------------------
; Not found in OPEN queue. Search in CLOSE queue
;--------------------------------------------------------------------------
Del_Search_Close_List:
       mov   di,Drive_Hdr_Ptr									   ;AN000;
       mov   si,es:[di].Close_Ptr	 ; SI-->first header in the				;AN000;
					 ; in the CLOSE queue
       cmp   si, -1			 ; anything in CLOSE Queue ??				   ;AN000;
       jne   Del_scan_close_list	 ; yes, jump						   ;AN000;
       clc				 ; none, header not found				   ;AN000;
       jmp   delete_exit		 ; exit 						   ;AN000;

Del_Scan_Close_List:
       mov   cx,First_Phys_Clusnum	 ; CX = first phys clus number				   ;AN000;
       CALL  FIND_FILE_HEADER		 ; find the header in CLOSE queue			   ;AN000;
												   ;AN000;
       jnc   Del_Close_last_hdr 	 ; if found, chk if this header 			   ;AN000;
					 ; is the last header in CLOSE queue
       clc				 ; else, set header not found				   ;AN000;
       jmp   delete_exit		 ; and then exit					   ;AN000;


;-------------------------------------------------------------------------
; Header found in CLOSE queue. Check header found is the only single
; header left in the queue.
;-------------------------------------------------------------------------
Del_Close_Last_Hdr:
       cmp   Hdr_Flag, 1		 ; Single Header in CLOSE Queue ??			   ;AN000;
       jne   Del_Chk_LRU_Hdr		 ; no, check for LRU header				   ;AN000;

;--------------------------------------------------------------------------
; Yes, single header in the queue, make CLOSE_PTR empty before delete the
; header from the queue.
;--------------------------------------------------------------------------
       mov  di,Drive_Hdr_Ptr									   ;AN000;
       mov  es:[di].Close_Ptr, -1	 ; mark CLOSE_Ptr as empty				   ;AN000;
       jmp  short delete_Free_Buff	 ; release the deleted header				   ;AN000;

Del_Chk_LRU_Hdr:
       cmp   Hdr_Flag, 3		 ; Last Header in the CLOSE Queue ??			   ;AN000;
       jne   Del_Join_Hdr		 ; no, close gap					   ;AN000;
       mov   si,Prev_Hdr_Ptr		 ; make the previous header LRU Hdr			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr, -1    ; mark previous hdr 				   ;AN000;
       jmp   short delete_Free_Buff	 ; release the deleted header				   ;AN000;

;--------------------------------------------------------------------------
; Connect previous header to next header to close the gap in CLOSE Queue
;--------------------------------------------------------------------------
Del_Join_Hdr:
       mov   Queue_Type, 1		 ; set flag to indicate CLOSE Queue			   ;AN000;
       CALL  JOIN_PREV_TO_NEXT		 ; close gap						   ;AN000;
												   ;AN000;
       jmp   short Delete_Free_Buff	 ; release header to FREE area				   ;AN000;



;-------------------------------------------------------------------------
; Header found in OPEN queue. Check header found is the only single
; header left in the queue.
;-------------------------------------------------------------------------
Del_Open_Last_Hdr:
       cmp   Hdr_Flag, 1		 ; Single Header in OPEN Queue??			   ;AN000;
       jne   Del_Chk_Opn_LRU_Hdr	 ; no, check for LRU header				   ;AN000;

;--------------------------------------------------------------------------
; Yes, single header in the queue, mark OPEN Queue  empty before delete
;--------------------------------------------------------------------------
; the header from the queue.
       mov  di,Drive_Hdr_Ptr									   ;AN000;
       mov  es:[di].MRU_Hdr_Ptr, -1	 ; mark OPEN Queue as empty				   ;AN000;
       jmp  short delete_Free_Buff	 ; release the delete header				   ;AN000;

Del_Chk_OPN_LRU_Hdr:
       cmp   Hdr_Flag, 3		 ; Last Header in the CLOSE Queue ??			   ;AN000;
       jne   Del_Opn_Join_Hdr		 ; no, close gap					   ;AN000;
       mov   si,Prev_Hdr_Ptr		 ; make the previous header LRU Hdr			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr, -1    ; mark previous hdr 				   ;AN000;
       jmp   short Delete_Free_Buff	 ; release header to FREE area				   ;AN000;

;--------------------------------------------------------------------------
; Connect previous header to next header to close the gap in OPEN queue
;--------------------------------------------------------------------------
Del_Opn_Join_Hdr:
       mov   Queue_Type, 0		 ; set flag to indicate OPEN Queue			   ;AN000;
       CALL  JOIN_PREV_TO_NEXT		 ; close gap						   ;AN000;
												   ;AN000;

;----------------------------------------------------------------------------
; Header and extends found.  Mark the beginning of this free area with "-2".
; Connect this header to the FREE area. Mark all extnts under this header
; and chain them together through the 4th word. Connect the last extent to
; the OLD free area. This process will effectively release the header to the
; FREE area.  Finally update the FREE area size in the Drive header.
;
; NOTE:  The deleted buffers have size same as the size of a header or extent.
;	 Each buffers first location contains a marker (-2) to indicate that
;	 the buffer is a discontinuous buffer.	Each discontinuos buffer is
;	 connected to the next discontinuous buffer through the 4TH word.
;---------------------------------------------------------------------------

Delete_Free_buff:
       mov   di,Drive_Hdr_Ptr		 ; SI-->drive header					;AN000;
       mov   si,Cur_Hdr_Ptr		 ; DI-->current header					;AN000;

;-------------------------------------------------------------------------
; Put (-2) in the beginning of the released area to indicate that this is
; a discontinuous free area. Each Free area is 8 bytes which is same size
; as an extent or header.
;-------------------------------------------------------------------------
       mov   ax,-2										   ;AN000;
       mov   es:[si], ax									   ;AN000;
       cmp   es:[si].FH_Next_Extn_Ptr, -1   ; any extents under this header ??			   ;AN000;
       jne   del_look_extent		 ; yes, jump						   ;AN000;

;-------------------------------------------------------------------------
; There is no extents under this header.  Connect relased header to the
; Free area and update Free area size in drive header before exit.
;-------------------------------------------------------------------------
       mov   si,Cur_Hdr_Ptr		 ; SI-->Current Header					;AN000;
       mov   di,Drive_Hdr_Ptr		 ; DI-->Drive Header					;AN000;
       mov   ax,es:[di].Free_Ptr	    ; connect current header				   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr, ax    ; to the Free AREA					   ;AN000;
       mov   es:[di].Free_Ptr,si								   ;AN000;
       mov   cx, SIZE File_Header	 ; start with file header size				   ;AN000;
       mov   di,Drive_Hdr_Ptr									   ;AN000;
       add   es:[di].Free_Size,cx	    ; update free area size				   ;AN000;
       clc				    ; make sure caary is clear
       jmp   short Delete_Exit		    ; Then exit 					      ;AN000;


;-------------------------------------------------------------------------
; Yes, one or more extents under this header.  Connect the header to the
; the first extent through 4th word (FH_Next_Hdr_Ptr). Subsequent free
; extents are connected through the 4th word (EH_Next_Extn_Ptr). Next calculate
; the size of the header and possible extendta and update the free area
; size in the drive header.
;-------------------------------------------------------------------------
Del_Look_Extent:
       mov   si,Cur_Hdr_Ptr		    ; SI-->Current Header				      ;AN000;
       mov   ax, -2			    ; mark header as discontinuous			       ;AN000;
       mov   es:[si],ax 		    ; free area  (12/28)				   ;AN000;
       mov   cx, SIZE File_Header	    ; start with file header size			   ;AN000;

       mov   ax,es:[si].FH_Next_Extn_Ptr    ; AX-->first extent under this hdr			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax     ; connect this header to first extnt		    ;AN000;
					    ; through the 4th word				   ;AN000;
       mov   si,ax			    ; SI-->First extent 				   ;AN000;
       mov   ax, -2			    ; mark first extent as discontinous 		   ;AN000;
       mov   es:[si],ax 		    ; free area 					   ;AN000;

Delete_Loop:
       add   cx, SIZE Extent_Header	    ; add size of extent				   ;AN000;
       cmp   es:[si].EH_Next_Extn_Ptr, -1   ; current extent last extent ?					  ;AN000;
       je    Del_Update_Free_Size	    ; yes - jump  (12/28)				    ;AN000;
       mov   ax,es:[si].EH_Next_Extn_Ptr    ; get pointer to next extent			   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax     ; connect curr ext to next extent			   ;AN000;
       mov   si,ax			    ; SI-->next extent							     ;AN000;
       mov   ax, -2			    ; mark subsequent extents as			   ;AN000;
       mov   es:[si],ax 		    ; discontinuous free areas				   ;AN000;
       jmp   Delete_Loop		    ; adding the size until last extent 		   ;AN000;

Del_Update_Free_Size:
       mov   di,Drive_Hdr_Ptr									   ;AN000;
       add   es:[di].Free_Size,cx	    ; update free area in drive header			   ;AN000;
												   ;AN000;
; At this point SI-->Last extent
       mov   di,Drive_Hdr_Ptr		    ; DI-->drive header 				;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax     ; connect last extent under this			   ;AN000;
					    ; header to the Free area
       mov   ax,Cur_Hdr_Ptr		    ; AX-->Current header							;AN000;
       mov   es:[di].Free_Ptr,ax	    ; connect header being deleted to			   ;AN000;
					    ; the free pool				     ;AN000;
Delete_Exit:
       clc
       cmp    check_flag,0
       jne    open_chk_Que
       clc
       ret
Open_Chk_Que:
       CALL  Check_it
       ret				    ; exit						   ;AN000;

FK_DELETE   ENDP








;--------------------------------------------------------------------------
; PROCEDURE: FK_INSERT
;
; FUNCTION:  Search for a specific  extent  using the starting physical
;	     cluster  number  and  the given  logical  cluster number.
;	     Insert  the given	physical  cluster number in the extent
;	     indexed by the given logical cluster number. If extent is
;	     not found, create a new extent. If free space is not
;	     available, take free space free CLOSE or OPEN Queue.
;
; INPUT    DL = drive number
;	   CX = First Physical Cluster Number of the file
;	   BX = Logical Cluster Number
;	   DI = Physical Cluster Number
;
; OUTPUT:  Physical cluster number is inserted.  If extent is not found,
;	   a new file is created
;
; ROUTINES REFERENCED:	Find_File_Header,  Find_Extent, Find_LRU_Header
;
; REVISION HISTORY:  New  (5/87)
;
;------------------------------------------------------------------------

FK_INSERT   PROC   FAR
	push   cs			    ; Establish addressability				     ;AN000;
	pop    ds			    ; DS --> code segment				     ;AN000;
	assume ds:Cseg_Seek									   ;AN000;
	mov    es, Seek_Name_Cache_Seg	    ; setup cache buff segment register 		     ;AN000;
	assume es:Cseg_Init		    ; ES --> cache buffer segment			     ;AN000;

	mov   first_phys_clusNum,cx	    ; save cluster numbers				     ;AN000;
	mov   Logical_ClusNum,bx								   ;AN000;
	mov   Physical_ClusNum,di								   ;AN000;
	mov    func_cod,al

; Search for Drive Cache buffer using Drive ID in DL
       CALL   FIND_DRIVE_HEADER 	    ; get drive buffer					      ;AN000;
       jnc    Insert_Search_Hdr 	    ; found, search for file header			      ;AN000;
       jmp    Insert_Exit		    ; not found, error					      ;AN000;

;--------------------------------------------------------------------------
; If there are no free buffers and there is only a single header in the
; OPEN queue then there is no headers in the CLOSE queue, then the new
; clusters wont be insterted. This is because, file header should not consume
; its own extent if no free space is available.
;--------------------------------------------------------------------------
Insert_Search_Hdr:
       inc    es:[di].Extent_Count	    ; increment sequence count (DEBUGGING)
       mov   si,es:[di].MRU_Hdr_Ptr	    ; SI-->first header in OPEN queue		     ;AN000;
       cmp   es:[si].FH_Next_Hdr_Ptr, -1    ; only one header in OPEN queue??
       je    insert_chk_buff		    ; yes - check free buffer
       jmp   short insert_Inc_count	    ; no - go and insert clusters

Insert_Chk_Buff:
       cmp   es:[di].Free_Size, 0	    ; any free buffers ??
       jne   Insert_Inc_Count		    ; yes - go insert clusters
       cmp   es:[di].Close_Ptr, -1	    ; any headers in close queue?? (1/7/88   ;AN000;
       jne   Insert_Inc_Count		    ; yes - go insert clusters
       clc				    ; no - dont insert clusters
       jmp   Insert_Exit		    ; exit

insert_Inc_Count:
       mov   si,es:[di].MRU_Hdr_Ptr	    ; SI-->first header in the OPEN queue			  ;AN000;
       mov   cx,first_phys_clusnum	    ; CX = physical cluster number			      ;AN000;
       CALL  FIND_FILE_HEADER		    ; find the header in OPEN queue			      ;AN000;
					    ; DI-->Header
       jc    Insert_Make_Hdr		    ; header not found, make new header 		      ;AN000;
       jmp   Insert_Find_extent 	    ; header is found, now go and			      ;AN000;
					    ; search for the extent

;--------------------------------------------------------------------------
; If header not found, create a new header in the free area and connect it
; to the top of the OPEN queue.  Mark the new header with no extents. Insert
; the first logical and physical cluster number into the header.  At this
; point CX=First Physical Cluster number.
;--------------------------------------------------------------------------
Insert_Make_Hdr:
       CALL  MAKE_NEW_HEADER		    ; make a new header at the top			      ;AN000;
					    ; top of the queue
;--------------------------------------------------------------------------
; Now the header is created, next create an extent and put both logical and
; physical cluster number in the extent. The new extent should be
; created at the bottom end of the current queue, except if AX =3,
; then the new extent will be created between current and previous extent.
; Use Find_Free_Buffer to check the free space.
;--------------------------------------------------------------------------
       CALL  FIND_FREE_BUFFER		    ; get free area for new extent			      ;AN000;
       jnc   ins_save_addrs1		    ; found, jump					      ;AN000;
       jmp   Insert_Exit		    ; if free area found is its own			      ;AN000;
					    ; header, exit
Ins_Save_Addrs1:
       mov   di,Drive_Hdr_Ptr		    ; DI-->Drive header 				      ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Extn_Ptr,ax		    ; save new extent address				      ;AN000;
       CALL  UPDATE_FREE_AREA		    ; update Free area					      ;AN000;

       mov   di,Drive_Hdr_Ptr		    ; DI-->Drive header 				      ;AN000;
       mov   ax,New_Extn_Ptr		    ; beginning of new extent				      ;AN000;
       mov   si,Cur_Hdr_Ptr		    ; SI-->Current header				      ;AN000;
       mov   es:[si].FH_Next_Extn_Ptr,ax    ; connect current header to adj CHAIN		   ;AN000;
       mov   es:[si].FH_MRU_EXTN_Ptr,ax     ; connect current header to LRU chain		   ;AN000;
       mov   si,New_Extn_Ptr		    ; SI-->New extent
       mov   bx,Logical_ClusNum 								   ;AN000;
       mov   es:[si].EH_Logic_Clus_Num,bx   ; insert logical  clus num					   ;AN000;
       mov   cx,Physical_ClusNum								   ;AN000;
       mov   es:[si].EH_Phys_Clus_Num,cx    ; insert physical clus num			      ;AN000;
       mov   es:[si].EH_Count,0 	    ; set initial count = 0							;AN000;

;--------------------------------------------------------------------------
; Make new extent LRU extent
;--------------------------------------------------------------------------
       mov   es:[si].EH_Next_Extn_Ptr, -1   ; mark no next extent in sorted chain
       mov   es:[si].EH_Prev_Extn_Ptr, -1   ; mark no previous extent in sorted chain		  ;AN000;
       mov   es:[si].EH_Next_LRU_Ptr, -1    ; mark no next extent in MRU-LRU chain		   ;AN000;
       mov   es:[si].EH_Prev_LRU_Ptr, -1    ; mark no previous extent in MRU-LRU chain
       clc				    ;
       jmp   Insert_Exit		    ; exit			      ;AN000;

;--------------------------------------------------------------------------
; Header found, Check to see any extent under this header.  If not create
; new extent. If there are extents, search for the relative position of the
; given cluster number among the extents under current header.
;--------------------------------------------------------------------------
Insert_Find_Extent:
       mov  di,Cur_Hdr_Ptr		    ; DI-->Current header
       mov  si,es:[di].FH_Next_Extn_Ptr     ; SI-->first extent under current hdr			   ;AN000;
       cmp  si,-1			    ; any extent under this header ?			      ;AN000;
       jne  Find_relative_location	    ; yes, Find relative location of the
					    ; given cluster numbers				      ;AN000;

; Else create new  extent under the current header.
       CALL  FIND_FREE_BUFFER		    ; get free area for new extent			      ;AN000;
       jnc   ins_save_addrs2		    ; found, jump					      ;AN000;
       jmp   Insert_Exit		    ; else free area found is its own			      ;AN000;
					    ; header, *** ERROR **** exit
Ins_save_addrs2:
       mov   di,Drive_Hdr_Ptr		    ; DI-->Drive header 				      ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Extn_Ptr,ax		    ; save new extent address				      ;AN000;

       CALL  UPDATE_FREE_AREA		    ; update Free area pointers 			      ;AN000;

       mov   di,Drive_Hdr_Ptr		    ; DI-->Drive header pointer 			      ;AN000;
       mov   ax,New_Extn_Ptr									   ;AN000;
       mov   si,Cur_Hdr_Ptr		    ; SI-->Current header				      ;AN000;
       mov   es:[si].FH_Next_Extn_Ptr,ax    ; connect  new extent to header			  ;AN000;
       mov   es:[si].FH_MRU_EXTN_Ptr,ax
       mov   si,New_Extn_Ptr		    ;### next extent start in the free_ptr			 ;AN000;
       mov   bx,Logical_ClusNum 								   ;AN000;
       mov   es:[si].EH_Logic_Clus_Num,bx   ; insert logical					   ;AN000;
       mov   cx,Physical_ClusNum								   ;AN000;
       mov   es:[si].EH_Phys_Clus_Num,cx    ; insert physical cluster numbe			   ;AN000;
       mov   es:[si].EH_Count,0 	    ;							   ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,-1    ; mark this extent as last extent			   ;AN000;
       mov   es:[si].EH_Next_LRU_Ptr,-1     ; ### mark this extent as last extent		       ;AN000;
       mov   es:[si].EH_Prev_Extn_Ptr,-1    ; mark there is no prev extent			   ;AN000;
       mov   es:[si].EH_Prev_LRU_Ptr,-1     ; mark there is no prev LRU extent
       jmp   Insert_Make_MRU		    ; make current header MRU header			   ;AN000;


;--------------------------------------------------------------------------
; Check if the given cluster number will be continuous to either High or Low
; end of any extent under current header or should create a new extent
; If not, check whether a new extent for the cluster is to be created
; between current and previous extent - Current and next extent or new
; extent at the bottom of the queue.
;--------------------------------------------------------------------------
Find_Relative_Location:
       CALL FIND_CLUSTER_LOCATION	   ; find relative position  of new extent		    ;AN000;
       jnc  chk_continuity		   ; position found			    ;AN000;
       clc				   ; clusters already exist in an extent.
       jmp  Insert_exit 		   ; return to DOS					   ;AN000;

;--------------------------------------------------------------------------
; Extent found.  Check for LOW end contiguous. If true insert in the current
; extent and update the count
;--------------------------------------------------------------------------
Chk_continuity:
       cmp  find_flag,1 		   ; LO end contiguous to current extent?		     ;AN000;
       jne  Insert_chk_HI		   ; no - check high end contiguous						    ;AN000;
       mov  si,Cur_Extn_Ptr		   ; yes - insert and update				    ;AN000;
       mov  cx,Logical_ClusNum		   ; save new logical and pysical			     ;AN000;
       mov  es:[si].EH_Logic_Clus_Num,cx   ; cluster numbers as first clusters			   ;AN000;
       mov  cx,Physical_ClusNum
       mov  es:[si].EH_Phys_Clus_Num,cx 							   ;AN000;
       inc  es:[si].EH_Count		   ; update extent range count				     ;AN000;
       mov  di,Drive_Hdr_Ptr		   ; DI-->drive header
       cmp  es:[di].Free_Ptr,0		   ; any free buffer ??
       je   Chk_low_MRU 		   ; no - make current extent MRU extent
       jmp   Insert_Make_MRU		   ; yes - make current header MRU header			   ;AN000;

Chk_Low_MRU:
       mov   Cur_Extn_Ptr, si
       CALL  Make_MRU_Extent		   ; Move extent next to current header
       jmp   Insert_Make_MRU		   ; Make current header MRU header			     ;AN000;

;--------------------------------------------------------------------------
; Check if clusters are  high end contiguous to current extent.  If true
; increment count and then make the extent MRU extent only if no free
; buffer is available.
;--------------------------------------------------------------------------
Insert_Chk_HI:
       cmp  find_flag,2 		   ; HI end contiguous to current extent?		     ;AN000;
       jne  Insert_chk_between		   ; no, jump						     ;AN000;
       mov  si,Cur_Extn_Ptr		   ; SI-->Current extent				  ;AN000;
       inc  es:[si].EH_Count		   ; increment the cluster range count			     ;AN000;
       mov  di,Drive_Hdr_Ptr		   ; DI-->current drive header
       cmp  es:[di].Free_Ptr,0		   ; any free buffers ??
       je   Chk_Hi_MRU			   ; no - make current extent MRU extent
       jmp   Insert_Make_MRU		   ; yes - current header MRU header			      ;AN000;

Chk_Hi_MRU:
       mov   Cur_Extn_Ptr, si		   ; SI -->extent to be MRU
       CALL  Make_MRU_Extent		   ; move extent next to current header
       jmp   Insert_Make_MRU		   ; Make current header MRU header			     ;AN000;


;--------------------------------------------------------------------------
; Check to see the cluster number belongs to a new extent between current
; and Previous extent or header. If not it belongs to a new extent at the
; bottom end of the queue.
;--------------------------------------------------------------------------
Insert_Chk_Between:
       cmp   find_flag,3		  ; between current and previous exts?? 		    ;AN000;
       je    Connect_prev_next		  ; yes, jump						    ;AN000;

       cmp   find_flag,5		  ; between current and next extents??			    ;AN000;
       jne   Connect_to_end		  ; no, create new extent at bottom			    ;AN000;
					  ; bottom of the queue
       jmp   Connect_cur_next		  ; yes create new extent between			    ;AN000;
					  ; current and next extent

;--------------------------------------------------------------------------
; No, make new extent at the BOTTOM of the queue.
;--------------------------------------------------------------------------
CONNECT_TO_END: 			  ; At this point  SI-->Last extent in queue							      ;AN000;
       CALL  FIND_FREE_BUFFER		  ; Check for free area 				     ;AN000;
       jnc   ins_save_addrs3									   ;AN000;
       jmp   Insert_Exit		  ; if free area found is its own			    ;AN000;
					  ; header, *** ERROR *** exit
Ins_Save_Addrs3:
       mov   di,Drive_Hdr_Ptr									   ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Extn_Ptr,ax		  ; save new extent address				    ;AN000;
       CALL  UPDATE_FREE_AREA		  ; update Free_Ptr and Free_Size			    ;AN000;

       mov   ax,New_Extn_Ptr									   ;AN000;
       mov   di,Cur_Extn_Ptr		  ; SI-->Current extent 				    ;AN000;
       cmp   ax, di			  ; If free area got is  the last
       jne   Use_Cur_Extent		  ; last extent itself then use previous extent
       mov   di, Prev_Extn_Ptr		  ; SI-->Previous extent

Use_Cur_extent:
       mov   es:[di].EH_Next_Extn_Ptr,ax    ; connect new extent to current or previous extent	  ;AN000;
       mov   si,New_Extn_Ptr		    ; next extent start in the free_ptr 		   ;AN000;
       mov   es:[si].EH_Prev_Extn_Ptr, di   ; set previous extent address
       mov   bx,Logical_ClusNum 								   ;AN000;
       mov   es:[si].EH_Logic_Clus_Num,bx   ; insert logical					   ;AN000;
       mov   cx,Physical_ClusNum								   ;AN000;
       mov   es:[si].EH_Phys_Clus_Num,cx    ; insert physical cluster numbe			   ;AN000;
       mov   es:[si].EH_Count,0 	    ; initial cluster range

; Make new extent last extent in the sorted chain
       mov   es:[si].EH_Next_Extn_Ptr, -1   ; mark as Last extent of the queue			   ;AN000;
; make the new extent MRU extent in the MRU_LRU chain
       mov   di,Cur_Hdr_Ptr		    ; DI-->Current header
       mov   ax,es:[di].FH_MRU_Extn_Ptr     ; AX-->Previous MRU extent
       mov   es:[si].EH_NEXT_LRU_Ptr,ax     ; connect previous to  current extent
       mov   es:[si].EH_Prev_LRU_Ptr, -1    ; mark no previous LRU extent			   ;AN000;
       mov   es:[di].FH_MRU_Extn_Ptr,si     ; make current extent MRU extent
       mov   di,ax
       mov   es:[di].EH_Prev_LRU_Ptr,si     ; connect previous to  current extent
       jmp   Insert_Make_MRU		    ; make current header MRU header
												   ;AN000;


;--------------------------------------------------------------------------
; Make new extent between current and previous extents. If no previous extent
; connect the new extent to the current header.
;--------------------------------------------------------------------------
CONNECT_PREV_NEXT:
       CALL  FIND_FREE_BUFFER		 ; get free area for new extent 			   ;AN000;
       jnc   Prev_Next_Update		 ; found, jump						   ;AN000;
       jmp   Insert_Exit		 ; if free area found is its own			   ;AN000;
					 ; header, **ERROR** exit
Prev_Next_Update:
       mov   di,Drive_Hdr_Ptr		 ; DI-->Drive header					   ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Extn_Ptr,ax		 ; save new extent address				   ;AN000;
												   ;AN000;
       CALL  UPDATE_FREE_AREA		 ; update Free_Ptr and Free_Size			   ;AN000;

       mov   di,Drive_Hdr_Ptr		 ; DI-->Drive Header					   ;AN000;
       cmp   Prev_Extn_Ptr, -1		 ; Any previous extents ??				   ;AN000;
       jne   join_to_Prev_Extn		 ; yes - connect new extent to previous 	     ;AN000;
					 ; extent
; No, connect new extent to header
       mov   si,Cur_Hdr_Ptr		 ; SI-->current header					   ;AN000;
       mov   di,New_Extn_Ptr									   ;AN000;
       mov   ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under header
       mov   es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to this extent
       mov   es:[si].FH_Next_Extn_Ptr, di    ; connect new extent to cur hdr		   ;AN000;
       mov   es:[di].EH_Prev_Extn_Ptr, -1    ; address of previous extent (-1) since header
       mov   bx,Logical_Clusnum 	    ;							   ;AN000;
       mov   es:[di].EH_Logic_Clus_Num,bx   ; insert logical clus num				 ;AN000;
       mov   cx,Physical_Clusnum								   ;AN000;
       mov   es:[di].EH_Phys_Clus_Num,cx    ; insert physical cluster numbe			   ;AN000;
       mov   es:[di].EH_Count,0 	    ; set count 					   ;AN000;
       mov   si,ax			    ; SI-->previous MRU extent
       mov   es:[si].EH_Prev_Extn_Ptr,di    ; set prev extent of prev MRU extent

; Make the new extent MRU extent
       mov   si,Cur_Hdr_Ptr		    ; SI-->current header				      ;AN000;
       mov   ax,es:[si].FH_MRU_EXTN_Ptr     ; AX-->MRU extent under header
       mov   di,New_Extn_Ptr		    ; SI-->current header				      ;AN000;
       mov   es:[di].EH_Next_LRU_Ptr,ax     ; connect new extent to current extent
       mov   es:[di].EH_Prev_LRU_Ptr, -1    ; mark no previous LRU extent			   ;AN000;
       mov   es:[si].FH_MRU_Extn_Ptr,di     ; connect new extent to header
       mov   si,ax
       mov   es:[si].EH_Prev_LRU_Ptr,di     ; connect previous to  current extent
       Jmp   Insert_Make_MRU		    ; make current header MRU hdr			   ;AN000;

; Connect new extent to previous extent
Join_To_Prev_Extn:
       mov   si,New_Extn_Ptr		    ; SI-->New extent, connect new to			   ;AN000;
       mov   ax,Cur_Extn_Ptr		    ; connect previous extent				      ;AN000;
       cmp   si,ax			    ; new extent is created from
       je    join_set_adj		    ; current extent ??

       mov   si,Prev_Extn_Ptr		    ; no - SI-->Previous extent 				   ;AN000;
       mov   ax,New_Extn_Ptr		    ; connect new extent to		     ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,ax    ; previous extent					   ;AN000;
       mov   ax,Cur_Extn_Ptr
       jmp   short Join_Set_Next	    ; current extent

Join_set_adj:				    ; yes -
       mov   si,Prev_Extn_Ptr		    ; no - SI-->Previous extent 				   ;AN000;
       mov   bx,es:[si].EH_Next_Extn_Ptr    ; get next extent address
       mov   ax,New_Extn_Ptr		    ; connect new extent to		     ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,ax    ; previous extent					   ;AN000;
       mov   ax, bx			    ; extent to next extent
       mov   Cur_Extn_Ptr,bx		    ; change current extent

Join_set_Next:				    ; from current extent
       mov   si,New_Extn_Ptr		    ; SI-->New extent, connect new to			   ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,ax    ; current extent					   ;AN000;
       mov   bx,Logical_Clusnum 	    ; then save cluster numbers 			   ;AN000;
       mov   es:[si].EH_Logic_Clus_Num,bx   ; insert logical					   ;AN000;
       mov   cx,Physical_Clusnum								   ;AN000;
       mov   es:[si].EH_Phys_Clus_Num,cx    ; insert physical cluster numbe			   ;AN000;
       mov   es:[si].EH_Count,0 	    ;							   ;AN000;
       mov   ax, Prev_Extn_Ptr
       mov   es:[si].EH_Prev_Extn_Ptr,ax    ; connect previous to  current extent
       mov   di, Cur_Extn_Ptr		    ; setup previous extent link of
       mov   es:[di].EH_Prev_Extn_Ptr,si    ; current extent

; Make the new extent MRU extent
       mov   si,Cur_Hdr_Ptr		    ; SI-->current header				      ;AN000;
       mov   ax,es:[si].FH_MRU_EXTN_Ptr     ; AX-->MRU extent under header
       mov   di,New_Extn_Ptr		    ; SI-->current header				      ;AN000;
       mov   es:[di].EH_Next_LRU_Ptr,ax     ; connect new extent to current extent
       mov   es:[di].EH_Prev_LRU_Ptr, -1    ; mark no previous LRU extent			   ;AN000;
       mov   es:[si].FH_MRU_Extn_Ptr,di     ; connect new extent to header
       mov   si,ax
       mov   es:[si].EH_Prev_LRU_Ptr,di     ; connect previous to  current extent
       Jmp   short Insert_Make_MRU	    ; make current header MRU hdr			   ;AN000;



;--------------------------------------------------------------------------
; Make new extent between current and next extents. If no next extent
; connect the new extent to the end of queue.
;--------------------------------------------------------------------------
CONNECT_CUR_NEXT:
       mov   si,Cur_Extn_Ptr		 ; current extent					   ;AN000;
       cmp   es:[si].EH_Next_Extn_Ptr,-1    ; any next extent ??				   ;AN000;
       jne   join_to_next_extn		 ; yes, join to next extent				   ;AN000;
       jmp   Connect_To_End		 ; make new extent at the bottom of			   ;AN000;
					 ; the current queue
Join_To_Next_Extn:
       CALL  FIND_FREE_BUFFER		 ; Find free area					   ;AN000;
       jc    Insert_Exit		 ; if free area found is its own			   ;AN000;
					 ; header, exit
       mov   di,Drive_Hdr_Ptr									   ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Extn_Ptr,ax		 ; save new extent address				   ;AN000;

       CALL  UPDATE_FREE_AREA		 ; update Free_Ptr and Free_Size			   ;AN000;
												   ;AN000;
       mov   si,Cur_Extn_Ptr		 ; SI-->Current extent
       mov   DX,es:[si].EH_Next_Extn_Ptr    ; DI-->Next extent					   ;AN000;
       mov   ax,New_Extn_Ptr									   ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,ax    ;connect new extent to cur extent			   ;AN000;

       mov   si,New_Extn_Ptr		    ; SI-->New extent, connect new ext			   ;AN000;;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,DX    ; to next  extent					   ;AN000;
       mov   ax, Cur_Extn_Ptr		    ; AX = address of current extent
       mov   es:[si].EH_Prev_Extn_Ptr, ax   ; save address of previous extent
       mov   bx,Logical_Clusnum 	    ; then save cluster numbers 			   ;AN000;
       mov   es:[si].EH_Logic_Clus_Num,bx   ; insert logical					   ;AN000;
       mov   cx,Physical_Clusnum								   ;AN000;
       mov   es:[si].EH_Phys_Clus_Num,cx    ; insert physical cluster numbe			   ;AN000;
       mov   es:[si].EH_Count,0 	    ; set cluster range 				   ;AN000;
       mov   di,DX			    ; setup prev extent link of the
       mov   es:[di].EH_Prev_Extn_Ptr,si    ; next extent

; Make the new extent MRU extent
       mov   si,Cur_Hdr_Ptr		    ; SI-->current header				      ;AN000;
       mov   ax,es:[si].FH_MRU_EXTN_Ptr     ; AX-->MRU extent under header
       mov   di,New_Extn_Ptr		    ; SI-->current header				      ;AN000;
       mov   es:[di].EH_Next_LRU_Ptr,ax     ; connect new extent to current extent
       mov   es:[di].EH_Prev_LRU_Ptr, -1    ; mark no previous LRU extent			   ;AN000;
       mov   es:[si].FH_MRU_Extn_Ptr,di     ; connect new extent to header
       mov   si,ax
       mov   es:[si].EH_Prev_LRU_Ptr,di     ; connect previous to  current extent


;--------------------------------------------------------------------------
; Make the Current header MRU header. If the header is MRU header, then
; dont make the header MRU header.
;--------------------------------------------------------------------------
Insert_Make_MRU:
       cmp   Prev_Hdr_Ptr, -1		    ; first header ??					      ;AN000;
       jne   Ins_mru_hdr		    ; no, make MRU header				      ;AN000;
       clc				    ; make sure caary is clear
       jmp   short insert_exit		    ; yes, exit 					      ;AN000;

Ins_MRU_Hdr:
       CALL  MAKE_MRU_HEADER		    ; move header to top of OPEN Queue			      ;AN000;
       clc				    ; make sure caary is clear

Insert_exit:
       CALL  Check_it			    ; analyse the queue (debugging)
       ret				    ; EXIT						   ;AN000;

FK_INSERT   ENDP








;-------------------------------------------------------------------------
; PROCEDURE: FK_LOOKUP
;
; FUNCTION:  Search through the OPEN Queue for a specific Header and
;	     extent.  If header is not found, create a new header and
;	     make it MRU header.  Else search for a specific extent which
;	     contains the logical cluster number.  If the extent is not
;	     found, return partial information from previous extent or
;	     header.  If extent is found, return physical cluster number
;	     corresponds to the given logical cluster number.
;
; INPUT:     DL = drive number
;	     CX = First Physical Cluster Number of the file
;	     BX = Logical Cluster NUmber
;
; OUTPUT:    If Carry = 0   Fully Found
;	       DI = Physical Cluster Number indexed by es:[BX]
;	       BX = Physical Cluster Number indexed by es:[BX-1]
;
;	     If Carry = 1   Partially Found
;	       BX = Last logical cluster number in previous extent
;	       DI = Last Physical Cluster Number indexed by es:[Last logic clus]
;
;	     If header not found, a new header will be created.  In this case
;	       BX = First Logical Cluster number (0)
;	       DI = First Physical Cluster number of the header created
;
; NOTE:     The clusters are fully found if the logical cluster has
;	    continuity to the previous logical cluster in the same
;	    extent or previous extent or previous header.
;
; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_Drive_Header
;
; REVISION HISTORY:  New  (5/87)
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;---------------------------------------------------------------

FK_LOOKUP   PROC   FAR		   ; on entry DS = seg ID of INIT

       push   cs			 ; establish addressability				   ;AN000;
       pop    ds			 ; DS --> code segment					   ;AN000;
       assume ds:Cseg_Seek									   ;AN000;
       mov    es, Seek_Name_Cache_Seg	 ; setup cache buff segment register			   ;AN000;
       assume es:Cseg_Init		 ; ES --> cache buffer segment				   ;AN000;
       mov    First_Phys_Clusnum,cx	 ; save phys cluster number				   ;AN000;
       mov    Logical_ClusNum,bx
       mov    func_cod,al

;--------------------------------------------------------------------------
; Search for Drive header in the Cache buffer using Drive ID in DL
;--------------------------------------------------------------------------
       CALL   FIND_DRIVE_HEADER 	 ; Search for drive header				   ;AN000;
       jnc    Look_search_hdr		 ; found, search for file header			   ;AN000;
       jmp    Look_Exit 		 ; not found, error					   ;AN000;

;--------------------------------------------------------------------------
; Search for a header in the OPEN  Queue using given physical cluster number
;--------------------------------------------------------------------------
Look_Search_Hdr:
       inc    es:[di].Extent_Count	 ; ;***;
       mov   si,es:[di].MRU_Hdr_Ptr	 ; SI-->first header in the				;AN000;
					 ; in the OPEN Queue
       mov   cx,First_Phys_Clusnum	 ; CX = Physical Cluster number 			   ;AN000;
       CALL  FIND_FILE_HEADER		 ; find the header in CLOSE Queue
												   ;AN000;
       jnc   Look_Find_extent		 ; if found, find extent under this header
					 ; else create a new header				   ;AN000;
;--------------------------------------------------------------------------
; If the header is not found, create a new header at the top of OPEN queue.
; Insert physical cluster number and set next header and first extent pointers
; Return partially found information.
;--------------------------------------------------------------------------
       pushf				 ; save carry set
       CALL  MAKE_NEW_HEADER		 ; Make a new header at the top of the queue		   ;AN000;
       xor   bx,bx			 ; BX = First Logical cluster number		   ;AN000;
       mov   di, First_Phys_Clusnum	 ; DI = First physical cluster number
       popf				 ; carry should be set
       jmp   Look_exit			 ; exit 						   ;AN000;


;--------------------------------------------------------------------------
; If the header is found, next search for the extent that contains the
; logical and physical cluster numbers. DI--> current header
;--------------------------------------------------------------------------
Look_Find_Extent:
       cmp   es:[di].FH_Next_Extn_Ptr,-1 ; any extent under this header ??			   ;AN000;
       jne   look_search_extent 	 ; yes, search for right extent 			   ;AN000;

       xor   bx,bx			 ; no, return partial info from header			   ;AN000;
       mov   di,es:[di].FH_Phys_Clus_Num ; DI = first phys clus num				   ;AN000;
       push  di 			 ;							   ;AN000;
       push  bx 			 ; BX = 1st logc clus num = 0				   ;AN000;
       mov   fully_flag, 0		 ; set partially found flag				   ;AN000;
       jmp   look_make_MRU_hdr		 ; move header to top of the OPEN queue 		   ;AN000;


;--------------------------------------------------------------------------
; Search for cluster numbers in extents starting from 1st extent.
;--------------------------------------------------------------------------
Look_Search_Extent:
       mov   si,es:[di].FH_Next_Extn_Ptr    ; SI-->first extent under curr hdr			   ;AN000;
       mov   Cur_Extn_Ptr,si		    ; save it						   ;AN000;
       mov   cx,Logical_ClusNum 	    ; CX = logic clus num to search for 		   ;AN000;
       mov   Prev_Extn_Ptr, -1		    ; reset flags					   ;AN000;
       mov   Extn_Flag, 0		    ;							   ;AN000;
       cmp   cx,es:[si].EH_Logic_Clus_Num   ; 1st logic clus num in the 			   ;AN000;
       jl    Look_proc_less

Look_Loop1:
       cmp   cx,es:[si].EH_Logic_Clus_Num   ; 1st logic clus num in the 			   ;AN000;
					    ; current extent matches ??
       je    Look_Proc_First		    ; yes, process 1st extent case			   ;AN000;
       mov   ax,es:[si].EH_Logic_Clus_Num   ; else check subsequent extents
       add   ax,es:[si].EH_Count	    ; last logic clus num in cur extent 		   ;AN000;
       cmp   cx,ax			    ; extent found in the cur extent ??
       jg    Look_Next_Extn		    ; no,try next extent				   ;AN000;;AN000;;AN000;
       jmp   Look_Extn_within		    ; yes, process current extent			   ;AN000;

Look_Next_Extn: 			    ;
       mov   ax,es:[si].EH_Next_Extn_ptr    ; get address of next extent			   ;AN000;
       cmp   ax,-1			    ; is this last extent ??				   ;AN000;
       je    Look_last_done		    ; yes, get partial					   ;AN000;

       mov   Prev_Extn_Ptr,si		    ; save previous extent address			   ;AN000;
       mov   si,ax										   ;AN000;
       mov   Cur_Extn_Ptr,si		    ; save current extent address			   ;AN000;
       cmp   cx,es:[si].EH_Logic_Clus_Num   ; logic clus num in cur extent ??			   ;AN000;
       jge   Look_Loop1 		    ; may be!!, check it out				   ;AN000;

       jmp   Look_Proc_Prev		    ; else get partial info from			   ;AN000;
					    ; previous extent
;-------------------------------------------------------------------------
; There are no further extents.  In this case partially found. Return last
; logical and physical clusters of the last extent.
;-------------------------------------------------------------------------
Look_Last_Done:
      mov   si,Cur_Extn_Ptr	       ; SI-->Previous extent					   ;AN000;
      mov   bx,es:[si].EH_Logic_Clus_Num  ; DI = first logic clus num ofprevext 		   ;AN000;
      mov   di,es:[si].EH_Phys_Clus_Num   ; BX = first logic clus num ofprevext 		   ;AN000;
      add   di,es:[si].EH_Count        ; DI = last phys clus number in extent			   ;AN000;
      add   bx,es:[si].EH_Count        ; BX = last logic clus number in extent			   ;AN000;
      push  di			       ; last logical cluster number				   ;AN000;;AN000;
      push  bx			       ; last physical cluster number				   ;AN000;
      mov   fully_flag,0	       ; partially found case					   ;AN000;
      jmp   Look_Make_MRU_Hdr	       ; make current header MRU header 			   ;AN000;



;--------------------------------------------------------------------------
; Less than starting logical cluster of first extent.  In this case return
; header info as partially found.
;--------------------------------------------------------------------------
Look_Proc_Less:
      xor   bx,bx		       ; BX = logical cluster number = 0			   ;AN000;
      mov   ax,es:[di].FH_Phys_Clus_Num 							   ;AN000;
      push  ax			       ; first phys clus of current hdr 			   ;AN000;
      push  bx			       ; first logic clus (0) of cur hdr			   ;AN000;
      mov   fully_flag,0	       ; partially found case					   ;AN000;
      jmp   Look_Make_MRU_Hdr	       ; make current header MRU header 			   ;AN000;



;--------------------------------------------------------------------------
; If first logical cluster number of the current extent matches with the given
; logical cluster number, see if previous logical cluster in previous header
; or extent is contiguous. If true, fully found. I this case return
; BX = first physical cluster of cuurent extent and DI = first physical
; cluster number of header if it is a header or last physical cluster number
; of previous extent.  If this is not true, partially found case. In this case,
; return BX = last logical cluster number  and DI = last physical cluster number
; from the previous extent.  If no previous extent, then return DI = first
; physical cluster and BX = 0  from the header
;
; NOTE:     The clusters are fully found if the logical cluster has
;	    continuity to the previous logical cluster in the same
;	    extent or previous extent or previous header.
;--------------------------------------------------------------------------
Look_Proc_First:
      mov   si,Cur_Extn_Ptr	       ; SI-->current extent					   ;AN000;
      mov   di,Cur_Hdr_Ptr	       ; DI-->current header					   ;AN000;
      cmp   Prev_Extn_Ptr, -1	       ; any previous extent ?? 				   ;AN000;
      jne   look_get_prev_extent       ; yes, get from previous extent				   ;AN000;

;--------------------------------------------------------------------------
; No, look for current header logical cluster number continuity
;--------------------------------------------------------------------------
      mov   ax,es:[si].EH_Logic_Clus_Num   ; AX = First physical cluster number 		   ;AN000;
      dec   ax				   ; of current extent					   ;AN000;
      cmp   ax,0		       ; continuity to first logical clus num			   ;AN000;
				       ; of current header which is (0)
      jne   Look_first_partial	       ; no, partially found					   ;AN000;


; Yes, fully found
      mov   bx,es:[si].EH_Phys_Clus_Num   ; BX = First physical cluster number			   ;AN000;
					  ; current extent
      mov   ax,es:[di].FH_Phys_Clus_Num   ; AX = First physical cluster number			   ;AN000;
					  ; of current header
      push  bx			       ; BX = 1st phys clus of current extent			   ;AN000;
      push  ax			       ; AX = 1st phys clus of prev header			   ;AN000;
      mov   fully_flag,1	       ; FULLY found case					   ;AN000;
      jmp   Look_Make_MRU_Hdr	       ; mov cur header to top of the Queue			   ;AN000;


Look_First_Partial:
      xor   bx,bx		       ; BX = logical cluster number = 0			   ;AN000;
      mov   ax,es:[di].FH_Phys_Clus_Num 							   ;AN000;
      push  ax			       ; first phys clus of current hdr 			   ;AN000;
      push  bx			       ; first logic clus (0) of cur hdr			   ;AN000;
      mov   fully_flag,0	       ; partially found case					   ;AN000;
      jmp   short Look_Make_MRU_Hdr    ; make current header MRU header 			   ;AN000;


;--------------------------------------------------------------------------
; Get last physical and logical cluster number of the previous extent
;--------------------------------------------------------------------------
Look_Get_Prev_Extent:
      mov   di,Prev_Extn_Ptr	       ; DI-->Previous extent					   ;AN000;
      mov   ax,es:[si].EH_Logic_Clus_Num   ; AX = First logical cluster number			   ;AN000;
      dec   ax				   ; of current extent					   ;AN000;
      mov   bx,es:[di].EH_Logic_Clus_Num  ; continuity to last logical clus num 		   ;AN000;
      add   bx,es:[di].EH_Count 	  ; of previous extent ??				   ;AN000;
      cmp   ax,bx										   ;AN000;
      jne   Look_first_partial2 	  ; no, partially found 				      ;AN000;

; Fully found case
      mov   bx,es:[si].EH_Phys_Clus_Num   ; BX = First physical cluster number			   ;AN000;
      mov   ax,es:[di].EH_Phys_Clus_Num   ; AX = Last physical cluster number			   ;AN000;
      add   ax,es:[di].EH_Count 	  ; from previous extent				   ;AN000;
      push  bx				  ; BX = 1st phys clus num from cur extn		      ;AN000;
      push  ax				  ; AX = last phys clus num from prev extn		      ;AN000;
      mov   fully_flag,1		  ; FULLY found case					      ;AN000;
      jmp   short Look_Make_MRU_Hdr	  ; mov current header to top of OPEN que		      ;AN000;


Look_First_Partial2:
      mov   bx,es:[di].EH_Logic_Clus_Num  ; BX = First Logical cluster number			   ;AN000;
					  ; of current extent
      add   bx,es:[di].EH_Count 	  ; BX = Last Logic clus from prev extn 		   ;AN000;
      mov   ax,es:[di].EH_Phys_Clus_Num   ; AX = First physical cluster number			   ;AN000;
					  ; of previous extent
      add   ax,es:[di].EH_Count 	  ; last phys clus num of prev extent			   ;AN000;
      push  ax				  ;  AX = last phys clus of prev extent 		      ;AN000;
      push  bx				  ;  BX = last logic clus of prev extent		      ;AN000;
      mov   fully_flag,0		  ; partially found case				      ;AN000;
      jmp   short Look_Make_MRU_Hdr	  ; make current header MRU header			      ;AN000;



;----------------------------------------------------------------------------
; If the given cluster number matches with any logic cluster number starting
; from 2nd and above, then fully found.  Return BX=Phys clus num[log_clusnum]
; and DI=Phys clus num[log_clusnum-1]
;----------------------------------------------------------------------------
Look_Extn_Within:
      mov   si,Cur_Extn_Ptr	       ; SI-->Current extent					   ;AN000;
      sub   cx,es:[si].EH_Logic_Clus_Num							   ;AN000;
      mov   di,es:[si].EH_Phys_Clus_Num   ; DI = first phys clus num of 			   ;AN000;
					  ; current extent
      add   di,cx		       ; DI = Phys clus num [logic clus num]			   ;AN000;
      mov   bx,di		       ;							   ;AN000;
      dec   bx			       ; BX = Phys clus num [logic clus num -1] 		   ;AN000;
      push  di			       ; DI = Phys clus num [logic clus num]			   ;AN000;
      push  bx											   ;AN000;
      mov   fully_flag,1	       ; fully found case					   ;AN000;
      jmp   short Look_Make_MRU_Hdr    ; make current header to top of OPEN Que 		   ;AN000;


;--------------------------------------------------------------------------
; Given extent is above the upper limit of the current extent, but lower than the
; next extent.	In this case, cluters are partially found.  Return BX = last
; logical cluster number of the previous extent and DI = last physical cluster
; number of the previous extent.
;----------------------------------------------------------------------------
Look_Proc_Prev:
      mov   si,Prev_Extn_Ptr		  ; SI-->Previous extent				   ;AN000;
      mov   bx,es:[si].EH_Logic_Clus_Num  ; DI = first logic clus num of prev			   ;AN000;
					  ; extent
      mov   di,es:[si].EH_Phys_Clus_Num   ; BX = first phys clus num of prev			   ;AN000;
					  ; extent
      add   di,es:[si].EH_Count 	; DI = last phys clus number in extent			   ;AN000;
      add   bx,es:[si].EH_Count 	; BX = last logic clus number in extent
      push  di				; save clusters to return				   ;AN000;
      push  bx											   ;AN000;
      mov   fully_flag,0		; partially found case					   ;AN000;

;----------------------------------------------------------------------------
; Move the current header to the top of the OPEN queue
;----------------------------------------------------------------------------
Look_Make_MRU_Hdr:
       cmp   Prev_Hdr_Ptr,-1		; first header in the Queue ??				   ;AN000;
       je    Look_Dont_Move_To_Top	; yes, dont move to top 				  ;AN000;

       CALL   MAKE_MRU_HEADER									   ;AN000;

Look_Dont_Move_To_Top:
       cmp  fully_flag, 0		; fully found ??					   ;AN000;
       je   Look_set_carry		; no, partially found					   ;AN000;
       clc				; fully found						   ;AN000;
       jmp  short Look_Restore		; restore registers							      ;AN000;

Look_Set_Carry:
       stc				; set flag for partially found								 ;AN000;

Look_restore:
       pop  bx				; restore values to be reurned
       pop  di				; to DOS

Look_Exit:
       nop
       CALL   Check_it
       ret				; exit

FK_LOOKUP   endp







;----------------------------------------------------------------
; PROCEDURE: Fk_Truncate
;
; FUNCTION:  Using the given physical and logical clutser numbers,
;	     find the extent which contains the given cluster number.
;	     Delete all clusters folloing the given cluster and the
;	     subsequent extents and free the buffers.
;
; INPUT:   CX = First Physical Cluster Number of the file
;	   BX = Logical Cluster Number
;	   DL = Drive number
;
; OUTPUT:  CY = 0   Extents are truncated
;
;	   CY = 1   Extent no found   DI = 0
;
; ROUTINES REFERENCED:	Find_File_Header, Find_Extent
;
; REVISION HISTORY:  New  (5/87)
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;---------------------------------------------------------------

Fk_TRUNCATE   PROC   FAR

       push   cs			 ; establish addressability				   ;AN000;
       pop    ds			 ; DS --> code segment					   ;AN000;
       assume ds:Cseg_Seek									   ;AN000;
       mov    es, Seek_Name_Cache_Seg	 ; setup cache buff segment register			   ;AN000;
       assume es:Cseg_Init		 ; ES --> cache buffer segment				   ;AN000;
       mov    First_Phys_Clusnum,cx	 ; save phys cluster number				   ;AN000;
       mov    Logical_ClusNum,bx								   ;AN000;
       mov    func_cod,al

;--------------------------------------------------------------------------
; Search for Drive Cache buffer using Drive ID in DL
;--------------------------------------------------------------------------
       CALL   FIND_DRIVE_HEADER 	 ; get drive buffer					   ;AN000;
       jnc    Trunc_search_hdr		 ; if found, search for file header			   ;AN000;
       jmp    Trunc_Exit		 ; if not found, error					   ;AN000;
												   ;AN000;
;--------------------------------------------------------------------------
; Search for a header in the OPEN Queue using given physical clusternum
;--------------------------------------------------------------------------
Trunc_Search_Hdr:
       inc    es:[di].Extent_Count	 ; ;***;
       mov   si,es:[di].MRU_Hdr_Ptr    ; SI-->first header in the				;AN000;
				       ; in the OPEN Queue
       mov   cx,First_Phys_Clusnum     ; CX = Physical Cluster number				   ;AN000;

       CALL  FIND_FILE_HEADER	       ; find file header in OPEN Queue 			   ;AN000;
       jnc   Trunc_Find_extent	       ; if found, get extent					   ;AN000;

;--------------------------------------------------------------------------
; If the header is not found, create a new header and make it as MRU header
; insert first physical cluster number in the header
;--------------------------------------------------------------------------
       CALL  MAKE_NEW_HEADER		; make new header					   ;AN000;
       clc											   ;AN000;
       jmp   Trunc_exit 		; exit							   ;AN000;


;--------------------------------------------------------------------------
; Header is found.  Next search for the extent which contains the
; given logical cluster number.
;--------------------------------------------------------------------------
Trunc_Find_Extent:			;							   ;AN000;
       mov  Cur_Hdr_Ptr,di		; save current pointer					   ;AN000;
       mov  si,es:[di].FH_Next_Extn_Ptr    ; SI-->first extent in the				;AN000;
					; current header
       cmp  si, -1			; any extent under this header ??			   ;AN000;
       je   trunc_no_extent		; none, exit						   ;AN000;
       mov  cx,Logical_Clusnum		; CX = given logical cluster number			   ;AN000;

       CALL FIND_EXTENT 		; find the extent					   ;AN000;
       jnc  Trunc_shrink_extent 	; found extent ??					   ;AN000;

Trunc_No_Extent:			; extent not found
       xor  di,di			; no, return DI = 0					   ;AN000;
       clc				; clear carry
       jmp  Trunc_exit			; exit							   ;AN000;



;--------------------------------------------------------------------------
; Found extent.  Shrink the current extent and delete all subsequent extents.
; If the given logic clus num is the first cluster number in current extent,
; then delete the current extent and the subsequent ones.
;	  DI--->Extent found (starting extent)
;--------------------------------------------------------------------------
Trunc_Shrink_Extent:
       mov  bx,Logical_Clusnum									   ;AN000;
       cmp  bx,es:[di].EH_Logic_Clus_Num  ; first logic cluster match ??			   ;AN000;
       jne  shrink_cur_extent		  ; no, shrink current extent				   ;AN000;

;--------------------------------------------------------------------------
; First logical clus num matched. mark previous header or extent as last
;	  DI--->Extent found (starting extent)
;--------------------------------------------------------------------------
       mov  si,es:[di].EH_Prev_Extn_Ptr   ; SI-->Previous extent				   ;AN000;
       cmp  si, -1			  ; any previous extent ??				   ;AN000;
       je   trunc_no_prev		  ; no, jump						   ;AN000;
       mov  es:[si].EH_Next_Extn_Ptr,-1   ; mark previous extent as last extn			   ;AN000;
       mov  si,di			  ; save the current extent ptr 			   ;AN000;
       mov  cx, 0			  ; CX = buffer release counter 			   ;AN000;
       jmp  trunc_more			  ; release successive extents				   ;AN000;

;--------------------------------------------------------------------------
; Previous one is header. Mark so that there is no extents under it
;--------------------------------------------------------------------------
Trunc_No_Prev:
       mov  si,Cur_Hdr_Ptr		  ; get current header					   ;AN000;
       mov  es:[si].FH_Next_Extn_Ptr,-1   ; mark header for no extent				;AN000;
       mov  es:[si].FH_MRU_Extn_Ptr, -1
       mov  si,di			  ; save the current extent ptr 			   ;AN000;
       mov  cx, 0			  ; CX = buffer release counter 			   ;AN000;;AN000;
       jmp  short trunc_more		  ; release the extent					   ;AN000;


Shrink_Cur_Extent:
       sub  bx,es:[di].EH_Logic_Clus_Num  ; compute the amount to shrunk			   ;AN000;
       dec  bx											   ;AN000;
       mov  es:[di].EH_Count,bx 	  ; save it in count to shrink extent			   ;AN000;

;--------------------------------------------------------------------------
; Mark the current extent as the last extent and delete subsequent extents.
;--------------------------------------------------------------------------
       mov  si,es:[di].EH_Next_Extn_Ptr   ; SI-->Next extent					   ;AN000;
       cmp  si,-1			  ; current extent last extent ??			   ;AN000;
       jne  Trunc_Last_extent
       jmp  Trunc_Make_MRU_Hdr		  ; YES, In this case no subsequent			   ;AN000;
					  ; extents left to delete.
Trunc_Last_Extent:
       mov  es:[di].EH_Next_Extn_Ptr, -1  ; NO, mark last extent				   ;AN000;
       xor  cx,cx										   ;AN000;

;--------------------------------------------------------------------------
; Remove extents and release the buffer
;      SI--->Current extent
;--------------------------------------------------------------------------
Trunc_More:
       push  si 			 ; save the beginning of first				   ;AN000;
					 ; extent to be deleted
TRUNC_LOOP:				 ; loop for subsequent extents
       mov   ax, -2			 ; mark current extent as free				   ;AN000;
       mov   es:[si],ax 		 ; discontinuous free areas				   ;AN000;
       add   cx, SIZE Extent_Header	 ; add size of extent					   ;AN000;

       mov   ax,es:[si].EH_Next_LRU_Ptr  ; AX = address of Next LRU extent
       cmp   ax, -1			 ; any next LRU extent??
       jne   Trunc_Set_Next_LRU 	 ; yes - there is a next LRU extent

;-----------------------------------------------------------------------------
;  No - this is the LRU extent
;-----------------------------------------------------------------------------
       mov   di,es:[si].EH_Prev_LRU_Ptr  ; no - DI=address of previous LRU extent
       cmp   di, -1			 ; any prev LRU extent ??
       je    Trunc_Mark_Prev_Hdr	 ; no - previous is header
       mov   es:[di].EH_Next_LRU_Ptr, -1 ; yes - mark previous extnt LRU extent
       jmp   short Trunc_Chk_Next_ext	 ; no - check next adj extent

Trunc_Mark_Prev_Hdr:
       mov   di, Cur_Hdr_Ptr		 ; DI = address of current header
       mov   es:[di].FH_Next_Extn_Ptr,-1   ; mark header for no extent				 ;AN000;
       mov   es:[di].FH_MRU_Extn_Ptr, -1
       jmp   short Trunc_Chk_Next_Ext		 ; look for next extent

;-----------------------------------------------------------------------------
; There is a next LRU extent	AX-->Next_LRU_Extent
;-----------------------------------------------------------------------------
Trunc_Set_Next_LRU:
       mov   di,es:[si].EH_Prev_LRU_Ptr  ; DI = address of previous LRU extent
       cmp   di, -1			 ; any previous LRU extent ??
       jne   Trunc_Set_Prev_LRU 	 ; yes - connect prev LRU to Next LRU

       mov   di, Cur_Hdr_Ptr		 ; DI = address of current header
       mov   es:[di].FH_MRU_Extn_Ptr, ax   ; Connect next LRU extent to Hdr
       push  si 			 ; save current extent
       mov   si,ax
       mov   es:[si].EH_Prev_LRU_Ptr, -1  ; mark no previous extent
       pop   si 			 ; resetore current extent
       jmp   short Trunc_Chk_Next_Ext


Trunc_Set_Prev_LRU:			  ; DI-->Previous LRU extent
       mov   es:[di].EH_Next_LRU_Ptr,ax   ; connect previous LRU to Next LRU extent
       push  si 			  ; save Current extent
       mov   si,ax			  ; SI-->Next LRU extent
       mov   es:[si].EH_Prev_LRU_Ptr, di  ; set previous LRU header address
       pop   si 			  ; get current extent


Trunc_Chk_Next_Ext:			 ; SI-->Current extent
       mov   ax,es:[si].EH_Next_Extn_Ptr ; AX-->next extent					   ;AN000;
       cmp   ax, -1			 ; last extent ?					;AN000;
       je    Trunc_Update_Free_Size	 ; yes, jump						   ;AN000;

       mov   es:[si].FH_Next_Hdr_Ptr,ax  ; connect freed buffers togther			   ;AN000;
       mov   si,ax			 ; SI-->next extent					   ;AN000;
       jmp   Trunc_Loop 		 ; delete next extent					   ;AN000;

;-------------------------------------------------------------------------
; Update free size in the File header and connect the FREE_Ptr to the first
; extent released and connect the old Free_Ptr to end of the last extent
;      SI--->Current extent
;-------------------------------------------------------------------------
Trunc_Update_Free_Size: 		 ; SI-->Last extent released
       mov   di,Drive_Hdr_Ptr		 ; DI-->Drive header					   ;AN000;
       add   es:[di].Free_Size,cx	 ; update free area in drive header			   ;AN000;

Trunc_Join_Free_Area:
; At this point SI-->Last extent
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   es:[si].EH_Next_Extn_Ptr,ax ; connect last extent under this			   ;AN000;
					 ; header to the Free area				   ;AN000;
       pop   ax 			 ; beginning of truncated extent			   ;AN000;
       mov   es:[di].Free_Ptr,ax	 ; connect current extent to				   ;AN000;
					 ; the beginning of truncated extent

;--------------------------------------------------------------------------
; Make the Current header MRU header ( move current header to top of current Q)
;--------------------------------------------------------------------------
Trunc_make_MRU_Hdr:
      cmp   Prev_Hdr_Ptr,-1		 ; first header in the Queue??				   ;AN000;
      jne   Trunc_move_Hdr
      clc
      jmp   short Trunc_Exit		 ; yes, dont move to top				   ;AN000;

Trunc_move_Hdr:
      CALL  MAKE_MRU_HEADER		 ; move header to TOP of the Queue			   ;AN000;
      clc

Trunc_Exit:
      CALL  Check_it
      ret				 ; return						   ;AN000;

FK_TRUNCATE	ENDP








;-----------------------------------------------------------------------------
; Procedure:  PURGE_BUFFERS
;
; Function:   Reset both extent and name cache buffers of a specific
;	      drive id
;
; Input:      DL = drive ID
;
; Output:     Buffers are initialized
;
; REVISION HISTORY:  New  (5/87)
;
; COPYRIGHT:  "MS DOS 4.00 Fastopen Utility"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Property of Microsoft  "
;
;-----------------------------------------------------------------------------

FK_PURGE   PROC    FAR	       ; Purge Cache buffers

       push   cs
       pop    ds			  ; DS=Code seg id used for addressing
       ASSUME  ds:Cseg_Seek		  ; local variables				      ;AN000;

       mov    si,Seek_Extent_Drive_Buff   ; SI-->beginning of extent drive			   ;AN000;
       mov    es,Seek_Name_Cache_Seg	  ; ES = addressability to Cseg_Init			   ;AN000;
       ASSUME  es:Cseg_Init		  ;							   ;AN000;
       mov    cx,Seek_Num_Of_drives	  ; number of drives

Main_Loop2:				  ; ES:SI-->cache buffer
       mov    ax,es:[si].Drive_Number	  ; get drive id
       cmp    al,dl			  ; drive id found ??
       je     purge_buffer		  ; yes - purge drive id buffer
       mov    ax, size Drive_Header	  ; ax size of drive heder
       add    ax, es:[si].Buff_Size	  ; ax = offset to next header
       add    si,ax			  ; (2/11)SI-->next drive header			      ;AN000;
       LOOP   main_loop2		  ; try next header

Purge_Buffer:				  ; SI-->drive header
       mov    es:[si].MRU_Hdr_Ptr,-1	  ; Make OPEN  QUEUE empty				   ;AN000;
       mov    es:[si].CLOSE_Ptr,-1	  ; Make CLOSE QUEUE empty				   ;AN000;
       mov    cx,es:[si].BUFF_size	  ; drive extent cache size				   ;AN000;
       mov    es:[si].FREE_Size,cx	  ; set drive free buffer size				       ;AN000;
       mov    ax,si
       add    ax, size Drive_Header	  ; ax = size of drive header
       mov    es:[si].FREE_Ptr,ax	  ; set Free buffer address

; Makesure to fill extent cache buffer with zeros.  Otherwise, Free Mark left
; previous run will generate illegal Free_Buff pointer.
       mov    al,0
       add    si, size Drive_Header	  ; SI-->first extent area
Ext_loop:				  ; fill extent cahe buffer with zeros
       mov    es:[si],al		  ; CX = extent cache size
       inc    si			  ; next byte
       Loop   Ext_Loop			  ; make it zero

FK_Exit:
       clc
       CALL  Check_it
       ret											   ;AN000;

FK_PURGE    ENDP







;----------------------------------------------------------------------
;	  ******* SUPPORT  ROUTINES *******
;----------------------------------------------------------------------
;
;----------------------------------------------------------------------
; PROCEDURE: Find_Drive_Header
;
; FUNCTION: Find starting address of drive header in extent Cache Buffer using
;	    drive ID in DL
;
; INPUT:   DL = drive id
;	   Extent_Drive_Buff  (Ptr to the beginning of extent buffer)
;	   ES--> Cache Buffer Segment
;
; OUTPUT:  If Carry = 0    DI --> Drive header
;			   Drive_Hdr_Ptr = address of drive header
;
;	   If Carry = 1    Drive buffer not found
;
; NOTE:    If drive id in DL is same as the drive id in previous request,
;	   no need to search the drive header. Use the previous drive header
;
;----------------------------------------------------------------------

FIND_DRIVE_HEADER    PROC     NEAR

       mov    di,Drive_Hdr_Ptr		; DI-->address of prev drive header
       cmp    drv_id,dl 		; drive id same as previous drive id  (1/11/88)
       jne    Search_drv_hdr		; no - search drive header
       clc				; yes - dont search
       jmp    short drive_exit		; exit

Search_Drv_Hdr:
       mov   cx,Seek_Num_of_Drives	; get number of drives								 ;AN000;
       mov   si,Seek_Extent_Drive_Buff	; SI-->start of extend drive hdr			;AN000;

Drive_Loop:
       mov   al,es:[si] 		; get drive ID from cache drive hdr			   ;AN000;
       cmp   al,dl			; found ??						      ;AN000;
       je    drive_buff_found		; yes, exit						      ;AN000;
       cmp   es:[si].Next_Drv_Hdr_Ptr,-1   ; last header ??					  ;AN000;
       je    drive_Buff_not_found	   ; yes - drive header not found							 ;AN000;
       mov   si,es:[si].Next_Drv_Hdr_Ptr   ; SI-->next drive header				   ;AN000;
       dec   cx 			; update drive count							       ;AN000;
       jz    drive_Buff_not_found	; last drive						      ;AN000;
       jmp   drive_Loop 		; search for more					      ;AN000;

Drive_Buff_Not_Found:			; drive buffer not found
       stc				; set carry flag					      ;AN000;
       jmp   short Drive_Exit		; exit							      ;AN000;

Drive_Buff_Found:			; drive buffer found
       mov   drv_id,dl			; save drive id
       mov   Drive_Hdr_ptr,si		; save drive buffer pointer				      ;AN000;
       mov   di,si			; DI-->drive header					   ;AN000;
       clc											   ;AN000;

Drive_Exit:				; return
       ret											   ;AN000;

FIND_DRIVE_HEADER     endp





;---------------------------------------------------------------
; PROCEDURE: Find_File_Header
;
; FUNCTION: Find starting address of the specific file header with
;	    a specific starting physical cluster number.  Also
;	    determine the type of header found.
;
; INPUT:   SI --> First header in the queue
;	   CX = First Physical Cluster Number (file id)
;	   ES--> Cache Buffer Segment id
;
; OUTPUT:  If Carry = 0    DI --> header found
;			   Cur_Hdr_Ptr	= address of header found
;			   Prev_Hdr_Ptr = address of previous header
;
;			   Prev_Hdr_Ptr = -1   No Previous Header
;
;			   hdr_flag  -	Type of header found
;				   =  0   Header between first & last in queue
;				   =  1   Single header in the queue
;				   =  2   First header in the queue
;				   =  3   LRU (Last) header in the queue
;
;	   If Carry = 1    Header not found
;
;---------------------------------------------------------------

FIND_FILE_HEADER    PROC    NEAR

       push  si 			; save registers					   ;AN000;
       push  cx 										   ;AN000;

       cmp   si, -1			; any file header in this queue ??			   ;AN000;
       jne   Fh_search_hdr		; yes, search for it					   ;AN000;
       stc				; no, set carry and return				   ;AN000;
       jmp   short Fh_Exit										 ;AN000;

Fh_Search_Hdr:
       mov   Prev_Hdr_Ptr,-1		; reset flags						   ;AN000;
       mov   Hdr_Flag, 0		; reset header type flag				   ;AN000;

Fh_Loop1:
       cmp   es:[si].FH_Phys_Clus_Num,CX   ; check current header				   ;AN000;
       jne   Fh_next_header		; if not found branch					   ;AN000;
       mov   di,si			; DI --> header found					;AN000;
       mov   Cur_Hdr_Ptr,si		; save current Hdr pointer				   ;AN000;
       jmp   short Fh_header_found	; then take exit					   ;AN000;

Fh_Next_header: 			; else try next header
       mov   ax,es:[si].FH_Next_Hdr_ptr    ; get address of next header 			   ;AN000;
       cmp   ax,-1			; is this last header?? 				   ;AN000;
       je    Fh_not_found		; yes, header no found					   ;AN000;

       mov   Prev_Hdr_Ptr,si		; save previous header					   ;AN000;
       mov   si,ax			; SI= next header					   ;AN000;
       jmp   Fh_Loop1			; check next header					   ;AN000;

; Determine the type of header found
Fh_Header_Found:			; header found
       cmp   Prev_Hdr_Ptr, -1		; any previous headers ??				   ;AN000;;AN000;
       jne   Fh_LRU			; yes, jump						   ;AN000;
       cmp   es:[si].Fh_Next_Hdr_Ptr, -1  ; any headers following this hdr ??			   ;AN000;
       jne   Fh_First			; yes, jump						   ;AN000;
       mov   Hdr_Flag, 1		; single header in the queue				   ;AN000;
       clc				;							   ;AN000;
       jmp   short FH_Exit		; exit							   ;AN000;

Fh_First:
       mov   Hdr_Flag, 2		; Header found is first header in QUE			   ;AN000;
       clc				; set flag						   ;AN000;
       jmp   short FH_Exit		; exit							   ;AN000;

Fh_LRU:
       cmp   es:[si].Fh_Next_Hdr_Ptr, -1   ; Last header in the queue ??			   ;AN000;
       jne   Fh_middle_hdr		; no, Header between first and last			   ;AN000;
       mov   Hdr_Flag, 3		; set flag indicating LRU header			   ;AN000;
       clc											   ;AN000;
       jmp   short Fh_Exit		; exit							   ;AN000;
												   ;AN000;
Fh_Middle_Hdr:
       clc											   ;AN000;
       jmp   short Fh_Exit		; exit							   ;AN000;

Fh_Not_found:
       stc				; header not found					   ;AN000;

Fh_Exit:
       pop  cx											   ;AN000;
       pop  si											   ;AN000;
       ret				; return						   ;AN000;

FIND_FILE_HEADER    ENDP







;---------------------------------------------------------------
; PROCEDURE: Find_Extent
;
; FUNCTION: Find starting address of the specific Extent that contains
;	    the given logical cluster mumber.
;	    Verifiy that the extent found is the LRU Extent.
;
; INPUT:   SI --> First Extent under current queue
;	   CX = Logical Cluster number to be searched
;	   ES--> Cache Buffer Segment Id
;
; OUTPUT:  If Carry = 0    DI --> Extent found
;			   Cur_Extn_Ptr  = address of extent found
;			   Prev_Extn_Ptr = address of previous extent
;			   IF Extn_Flag = 1, extent found  is the  only
;					     extent under this header
;
;	   If Carry = 1    Extent not found
;
; REVISION HISTORY:  New  (5/87)
;---------------------------------------------------------------

FIND_EXTENT	 PROC	 NEAR

       push  si 			    ; save registers					   ;AN000;
       push  cx 										   ;AN000;
												   ;AN000;
       mov   Prev_Extn_Ptr,-1		    ; reset flags
       mov   Extn_Flag, 0									   ;AN000;
												   ;AN000;
Eh_Loop1:
       cmp   cx,es:[si].EH_Logic_Clus_Num							   ;AN000;
       jl    Eh_Next_Extn		    ; try next extent					   ;AN000;
       mov   ax,es:[si].EH_Count	    ; get range 					   ;AN000;
       add   ax,es:[si].EH_Logic_Clus_Num   ; get upper range					   ;AN000;
       cmp   cx,ax										   ;AN000;
       jg    Eh_Next_Extn		    ; try next extent					   ;AN000;

Eh_Not_LRU:
       mov   di,si			    ; DI --> Extent found				   ;AN000;
       mov   Cur_Extn_Ptr,si		    ; save current extent pointer			      ;AN000;
       clc				    ; set flag						      ;AN000;
       jmp   Eh_Extn_found		    ; then take exit					      ;AN000;

Eh_Next_Extn:				    ; else try next extent
       mov   ax,es:[si].EH_Next_Extn_ptr    ; get address of next extent			    ;AN000;
       cmp   ax,-1			    ; is this last extent??				      ;AN000;
       je    Eh_Not_Found		    ; yes, exit 					      ;AN000;
       mov   Prev_Extn_Ptr,si		    ; save previous extent				      ;AN000;
       mov   si,ax			    ; SI=next extent					      ;AN000;
       jmp   Eh_Loop1			    ; check next extent 				      ;AN000;

       stc				    ; else set flag for extent not found		      ;AN000;
       jmp   short Eh_Exit		    ; then exit 					      ;AN000;

Eh_Extn_Found:				    ; Extent found
       cmp   Prev_Extn_Ptr, -1		    ; any previous extents ??				      ;AN000;
       jne   Eh_yes			    ; yes, jump 					      ;AN000;
       cmp   es:[di].Eh_Next_Extn_Ptr, -1   ; any extents following this extents ??		    ;AN000;
       jne   Eh_yes			    ; yes, jump 					      ;AN000;
       mov   Extn_Flag, 1		    ; no, set flag indicating single extnt		      ;AN000;
					    ; in the queue
Eh_Yes:
       clc											   ;AN000;
       jmp   short Eh_Exit		    ; exit							  ;AN000;

Eh_Not_Found:				    ; extent not found
       stc											   ;AN000;

Eh_Exit:
       pop  cx											   ;AN000;
       pop  si											   ;AN000;

       ret				; return						   ;AN000;

FIND_EXTENT	 ENDP






;---------------------------------------------------------------------------
; PROCEDURE: FIND_CLUSTER_LOCATION
;
; FUNCTION:  Find starting address of a specific extent which identifies
;	     the relative position of the new cluster in the queue.
;
; INPUT:     SI--> First extent under current header
;	     ES--> Cache Buffer Segment
;
; OUTPUT:    If Carry = 0    Cluster location identified
;	     Cur_Extn_Ptr =  Current extent
;	     Prev_Extn_Ptr = Previous extent
;
;			     Find_Flag =  1  Clusters are  contiguous in
;					  the LO end of the current extent
;
;			     Find_Flag =  2  Clusters are contiguous in
;					  the HI end of the current extent
;
;			     Find_Flag =  3  Clusters  belong to a new
;					  extent between current and previous
;					  extent
;
;			     Find_Flag =  4  Clusters belong to a new
;					  extent at the end of the queue
;					  Cur_Extn_Ptr-->Last extent in queue
;
;			     Find_Flag =  5  Clusters belong to a new
;					  extent between current and next
;
;	    If Carry = 1    Clusters already exist
;
;-----------------------------------------------------------------------


FIND_CLUSTER_LOCATION	PROC   NEAR

;--------------------------------------------------------------------------
; Check to see that the given logical cluster number falls within the
; current extent. If true it is an error.
;--------------------------------------------------------------------------
       push  di
       mov   Prev_Extn_Ptr, -1		; initialize the flag					   ;AN000;
       mov   Cur_Extn_Ptr,si		; SI-->First extent under header			   ;AN000;
       mov   Find_Flag, -1		; reset with illegal value
												   ;AN000;
Fe_LOOP1:
       mov   ax,es:[si].EH_Logic_Clus_Num  ; AX = starting logi clus number				;AN000;
       mov   bx,Logical_Clusnum 	; BX = given logical clus num				   ;AN000;
       cmp   bx,ax			; LOW end ??					;AN000;
       jl    Fe_Chk_Low_end		; yes - jump					;AN000;
       add   ax,es:[si].EH_Count	; ending logical clus number				   ;AN000;
       cmp   bx,ax			; HIGH end ??					    ;AN000;
       jg    Fe_Chk_High_end		; yes - jump						;AN000;

;--------------------------------------------------------------------------
; Found the given logical cluster number within the extent.
; This is a normal condition.  In this case the clusters wont be insterted.
;--------------------------------------------------------------------------
       stc				; set flag
       jmp   Fe_Extent_Exit		; return						   ;AN000;


;--------------------------------------------------------------------------
; If not in the extent, then see the logical clus number has continuity at
; LOW end of the current extent.
;--------------------------------------------------------------------------
Fe_Chk_LOW_END:
       mov   ax,es:[si].EH_Logic_Clus_Num  ; starting logi clus number				   ;AN000;
       dec   ax 			; one below the lowest					   ;AN000;
       mov   bx,Logical_Clusnum 	; BX = given logical clus num				   ;AN000;
       cmp   bx,ax			; contiguous at LOW end ??				   ;AN000;
       jl    Fe_Curr_Prev		; no, build a new extent between			   ;AN000;
					; current and previous
; Logical clus has continuity at low end.  Now check physical cluster number
; foe continuity.
       mov   ax,es:[si].EH_Phys_Clus_Num   ; starting Phys clus number				   ;AN000;
       dec   ax 			; one below the lowest in the extent			   ;AN000;
       mov   bx,Physical_Clusnum	; BX = given logical clus num				   ;AN000;
       cmp   bx,ax			; within low end ??					   ;AN000;
       jne   Fe_Curr_Prev		; no, create a new extent between			   ;AN000;
					; current and previous extent
       mov   Find_Flag,1		; yes, set flag for LOW END continuity			   ;AN000;
       jmp   Fe_Extent_found		; then RETURN						   ;AN000;


;--------------------------------------------------------------------------
; Check  the logical clus number has continuity at High end of the current
; extent cluster range. Check physical cluster number has continuity at the
; high end.  If true, check the first logical and phys cluster number is the
; the same as this one.  In this case clusters exist and therefore wont be
; insterted.
;--------------------------------------------------------------------------
Fe_CHK_HIGH_END:
       mov   ax,es:[si].EH_Logic_Clus_Num  ; starting logi clus number				   ;AN000;
       add   ax,es:[si].EH_Count	; ending logical clus number				   ;AN000;
       inc   ax 										   ;AN000;
       mov   bx,Logical_Clusnum 	; BX = given logical clus num				   ;AN000;
       cmp   bx,ax			; within high end ??					   ;AN000;
       jg    Fe_Chk_Next_Extent 	; no, check next extent 				   ;AN000;

; Logical clus num has high end continuity, Check the Physical cluster number
; for continuity.
       mov   ax,es:[si].EH_Phys_Clus_Num    ; starting phys clus number 			   ;AN000;
       add   ax,es:[si].EH_Count	; ending phys clus number				   ;AN000;
       inc   ax 										   ;AN000;
       mov   bx,Physical_Clusnum	; BX = given logical clus num				   ;AN000;
       cmp   bx,ax			; within high end ??					   ;AN000;
       jne   Fe_Chk_Next_Extent 	; no - check next extent		 ;AN000;
					;
; Yes - check first logical and physical cluster number of next extent
       mov   di,es:[si].EH_Next_Extn_Ptr   ; get address of next extent 			   ;AN000;
       cmp   di, -1			; any next extent ??
       je    Fe_High_End		; none - jump
       mov   ax,es:[di].EH_Logic_Clus_Num  ; starting logi clus number				   ;AN000;
       cmp   ax,Logical_Clusnum 	; logical cluster matches ??
       jne   Fe_high_end		; no - jump
       mov   ax,es:[di].EH_Phys_Clus_Num    ; starting phys clus number 			   ;AN000;
       cmp   ax,Physical_Clusnum	; physical cluster match ??
       jne   Fe_High_End		; no -jump
       stc				; clusters already exist in next extent
       jmp   short Fe_Extent_Exit	; return						   ;AN000;

Fe_High_End:
       mov   Find_Flag,2		; set flag for HIGH end continuity			   ;AN000;
       jmp   short Fe_Extent_found	; then RETURN						   ;AN000;


Fe_Chk_Cur_Next:
       cmp  es:[si].EH_Next_Extn_Ptr, -1   ; Current extent last extent ??			   ;AN000;
       je   Fe_flag_4			; yes, set flag-4					   ;AN000;

       mov   Find_Flag,5		; set flag for new extent between			   ;AN000;
       jmp   short Fe_Extent_Found	; current and next extent				   ;AN000;

Fe_Flag_4:
       mov   Find_Flag,4		; set flag for new extent at the			   ;AN000;
       jmp   short Fe_Extent_Found	; bottom end of current queue				   ;AN000;

;--------------------------------------------------------------------------
; Given cluster number has no  continuity but must stay between current extent
; and previous extent
;--------------------------------------------------------------------------
Fe_CURR_PREV:
       mov   Find_Flag,3		; set flag for between current and prev 		   ;AN000;
       jmp   short Fe_Extent_found	; then RETURN						   ;AN000;


;--------------------------------------------------------------------------
; Given cluster number has no  continuity. Try the next extent.
;--------------------------------------------------------------------------
Fe_Chk_NEXT_EXTENT:			; else try next extent
       mov   ax,es:[si].EH_Next_Extn_Ptr   ; get address of next extent 			   ;AN000;
       cmp   ax,-1			; is this last extent ??				   ;AN000;
       je    Extent_at_Bottom		; yes, Clustr belongs to a new				   ;AN000;
					; extent at the bottom					   ;AN000;
       mov   Prev_Extn_Ptr,si		; save current extend as previous extnt
       mov   si,ax			; SI-->Next extent					   ;AN000;
       mov   Cur_Extn_Ptr, si		; save new extent as cur extent 			   ;AN000;
       jmp   Fe_Loop1			; check next extent					   ;AN000;


;--------------------------------------------------------------------------
; Given cluster number has no  continuity but stays in a new extent at
; bottom (last) of the current queue.
;--------------------------------------------------------------------------
Extent_AT_BOTTOM:
       mov   Find_Flag,4		; else set flag for new extent				   ;AN000;

Fe_Extent_Found:
       clc											   ;AN000;

Fe_Extent_Exit:
       pop    di

       RET				; exit							   ;AN000;


FIND_CLUSTER_LOCATION	 ENDP







;-----------------------------------------------------------------------
; PROCEDURE: FIND_LRU_HEADER
;
; FUNCTION: Find address of the LRU header in the current queue
;
; INPUT:   SI --> First header in the current queue
;	   ES--> Cache Buffer Segment
;
; OUTPUT:  DI --> LRU header found
;
;	   LRU_Prev_Hdr = Previous header address
;	   LRU_Hdr	= Address of LRU header found
;	   If Hdr_Flag	= 1  -	Header found is only header in the queue
;
;-----------------------------------------------------------------------

FIND_LRU_HEADER    PROC    NEAR

       push  bx 										   ;AN000;
       mov   hdr_flag,0 		; initilialize flags					   ;AN000;
       mov   LRU_Prev_Hdr, -1		;							   ;AN000;

Flh_Loop1:
       cmp   es:[si].FH_Next_Hdr_Ptr,-1 ; current header is last hdr ?				   ;AN000;
       jne   Flh_next_header		; if not  check next header				   ;AN000;
       mov   di,si			; DI --> LRU header found				   ;AN000;
       mov   LRU_Hdr,si 		; save it						   ;AN000;
       jmp   short Flh_header_found	; then take exit					   ;AN000;

Flh_Next_Header:			; else try next header
       mov   LRU_Prev_Hdr,si		 ; save previous header address 			   ;AN000;
       mov   si,es:[si].FH_Next_Hdr_ptr 							   ;AN000;
       jmp   Flh_Loop1			; check next header					   ;AN000;

Flh_Header_Found:
       cmp  LRU_Prev_Hdr, -1		; any previous header ??				   ;AN000;
       je   F1h_Set_Flag		; no, set flag						   ;AN000;
       clc				; yes							   ;AN000;
       jmp  short F1H_Exit		; exit							   ;AN000;

F1h_Set_Flag:
       mov  hdr_flag,1			; LRU header is the only hdr in queue			   ;AN000;
       clc											   ;AN000;

F1h_Exit:				; exit
       pop  bx											   ;AN000;

       ret											   ;AN000;

FIND_LRU_HEADER    endp




;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PROCEDURE: FIND_LRU_EXTENT
;
; FUNCTION: Find  address of LRU  Extent under current header
;
; INPUT:   ES--> Cache Buffer Segment
;	   SI--> Header to be searched
;
; OUTPUT:  If  CY =  0	 LRU_Prev_Extent = Previous extent to the LRU extent
;			 LRU_Extent	 = LRU extent found
;			 Extn_Flag = 1	 Extent is the only extent under header
;
;	   If  CY =  1	 Not found
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

FIND_LRU_EXTENT    PROC     NEAR

       mov   LRU_Prev_Extent, -1	   ; reset flags							;AN000;
       mov   LRU_Extent, -1		   ;									;AN000;
       mov   Extn_Flag, 0
       mov   si, es:[si].FH_MRU_Extn_Ptr   ; SI--> First extent under header
       cmp   si, -1			   ; any extent under this header ??
       jne   Fle_Loop1			   ; yes - check extent
       stc				   ; no - set flag
       jmp   Fle_Exit			   ; exit

Fle_Loop1:
       cmp   es:[si].EH_Next_LRU_Ptr,-1    ; last extent in the queue??
       jne   Fle_next_extent		   ; if not found branch				     ;AN000;
       mov   LRU_Extent,si		   ; save LRU extent address
       jmp   short Fle_Extend_found	   ; exit

Fle_Next_Extent:			   ; else try next extend
       mov   LRU_Prev_Extent,si 	   ; save previous extent address
       mov   si,es:[si].EH_Next_LRU_Ptr    ; get address of next extent
       jmp   Fle_Loop1			   ; check next extent					     ;AN000;

Fle_Extend_Found:
       cmp   LRU_Prev_Extent, -1	   ; any previous extent ??
       je    Fle_Set_Flag		   ; no - set flag
       clc				   ;							      ;AN000;
       jmp   short Fle_Exit

Fle_Set_Flag:
       mov   Extn_Flag, 1		   ; set flag to indicate only flag
       clc

Fle_Exit:
       ret				   ; exit						      ;AN000;

FIND_LRU_EXTENT    ENDP







;----------------------------------------------------------------------
; PROCEDURE: Make_New_Header
;
; FUNCTION: Create a new header in the next available free area.
;	    Initialize the new header and make it MRU header ( move it
;	    to the top of the queue). If no free space in OPEN queue, delete
;	    and extent from the CLOSE queue.  If no space in CLOSE queue, then
;	    delete an extent from OPEN Queue to make space.
;
; INPUT:   Drive_Hdr_Ptr  - Address of drive header
;	   Free_Ptr	  - Address of FREE area
;	   ES--> Cache Buffer Segment
;
; OUTPUT:  Header is created
;
;----------------------------------------------------------------------

MAKE_NEW_HEADER     PROC

; Check if the OPEN Queue was previously empty using two cases. If open queue
; is empty, then the new header should be marked as first header in the queue.
       mov   Open_Queue_Flag, 0 	 ; clear flag open queue empty				   ;AN000;
       mov   di,Drive_Hdr_Ptr									   ;AN000;

; case - 1
       mov   ax,es:[di].Free_Size	 ; FREE size						   ;AN000;
       cmp   es:[di].Buff_Size,ax	 ; both are equal ?					   ;AN000;
       je    Make_Set_Entries		 ; if true, this is the first header			   ;AN000;

; case - 2
       cmp   es:[di].MRU_Hdr_Ptr, -1	 ; check for empty mark 				   ;AN000;
       je    Make_Set_Entries		 ; yes, set flag queue empty				   ;AN000;
       jmp   short Make_Set_Entry2	 ; not empty						   ;AN000;

Make_set_Entries:			 ; set up File Header entries
; When creating first header under drive header, mark header as first
; This flag is set for this purpose.
       mov   Open_Queue_Flag, 1 	 ; set flag open queue was empty			  ;AN000;

Make_Set_Entry2:
       CALL  FIND_FREE_BUFFER		 ; Look for some Free area. If none			   ;AN000;
												   ;AN000;
       mov   di,Drive_Hdr_Ptr		 ; DI-->Drive header					   ;AN000;
       mov   ax,es:[di].Free_Ptr								   ;AN000;
       mov   New_Hdr_Ptr,ax		 ; save new Header address
       mov   ax,es:[di].Free_Size								   ;AN000;

       CALL  UPDATE_FREE_AREA		 ; update Free_Ptr and Free_Size			   ;AN000;
					 ; create some free area

;-----------------------------------------------------------------------------
; Connect the new header to the Top of the OPEN Queue.	If the Queue is
; previously empty, mark the new header indicating nothing under this header.
;-----------------------------------------------------------------------------
Join_To_Drive_Buff:
       mov   di, drive_Hdr_Ptr		 ; DI-->drive buffer					   ;AN000;
       mov   si,New_Hdr_Ptr									   ;AN000;
       mov   Cur_Hdr_Ptr, si		 ; save as current header pointer			   ;AN000;
       mov   ax,es:[di].MRU_Hdr_Ptr	 ; connect current header to				   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax  ; previous MRU header
       mov   es:[di].MRU_Hdr_Ptr,si	 ; make new header MRU hdr

; When a header is created, it should contain no extents
       mov   es:[si].FH_Next_Extn_Ptr,-1    ; mark header with no extents			   ;AN000;
       mov   es:[si].FH_MRU_Extn_Ptr,-1     ; ###mark header with no extents			      ;AN000;
       mov   es:[si].FH_Refer_Count,1	    ; save starting file reference count		   ;AN000;
       mov   ax,First_Phys_Clusnum								   ;AN000;
       mov   es:[si].FH_Phys_Clus_Num,ax    ; save physical cluster number			   ;AN000;

       cmp   Open_Queue_Flag, 1 	 ; OPEN Queue empty ??					   ;AN000;
       je    Set_Single_Header		 ; no, jump						   ;AN000;
       clc
       ret											   ;AN000;

Set_Single_Header:			 ; yes mark new header as last hdr
       mov   si,New_Hdr_Ptr									   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,-1     ; mark as only header				   ;AN000;
       clc
       ret				    ; exit

MAKE_NEW_HEADER    ENDP






;----------------------------------------------------------------------
; PROCEDURE: Find_Free_Buffer
;
; FUNCTION: Find free buffer space. If no free space, delete last extent
;	    under last header in the CLOSE queue.   If none in CLOSE queue,
;	    delete the last extent of the LRU header in the OPEN queue.
;
; INPUT:   Drive_Hdr_Ptr - Pointer to drive header
;	   ES--> Cache Buffer Segment
;
; OUTPUT:  Released Header or extent buffer space will be addded to the
;	   Free area as discontinuous free area.  Free size in drive head
;	   will be updated.
;
;	   If  CARRY = 0
;	       Free_Flag: 0 - Free area is continuous
;			  1 - Free area is discontinuous
;
;	   if  CARRY = 1   Fatal error ( no free space to spare )
;
; NOTE:   The deleted buffers have size same as the size of a header or extent.
;	  Each buffers first location contains a marker (-2) to indicate that
;	  the buffer is a discontinuous buffer.  Each buffer is connected to
;	  the next dicontinous buffer through the 4th word.
;
;----------------------------------------------------------------------

FIND_FREE_BUFFER    PROC     NEAR

       mov    di,drive_Hdr_Ptr	       ; DI-->Drive Header					   ;AN000;
       cmp    es:[di].free_size,0      ; any free area left ??					   ;AN000;
       je     Free_Chk_Close_List      ; none, check CLOSE queue				    ;AN000;

       mov    si,es:[di].Free_Ptr      ; check for discontinuous				   ;AN000;
       mov    ax, -2										   ;AN000;
       cmp    es:[si], ax	       ; discontinuous free buffer??					      ;AN000;
       je     Free_Set_One	       ; yes, set flag for discontinuous

       mov    Free_Flag,0	       ; no, clear flag 					   ;AN000;
       clc											   ;AN000;
       jmp    Free_Exit

Free_Set_one:
       mov    Free_Flag,1	       ; set flag						   ;AN000;
       clc											   ;AN000;
       jmp    Free_exit 	       ; yes, Free space is available				   ;AN000;
				       ; exit


;--------------------------------------------------------------------------
; No free space ,  look for space in CLOSE Queue. Search for the LRU header
; delete the header and any extents under this header.
;--------------------------------------------------------------------------
Free_Chk_Close_List:
       mov    si,es:[di].CLOSE_Ptr     ; SI-->CLOSE queue					    ;AN000;
       cmp    si,-1		       ; anything in CLOSE Queue ??				   ;AN000;
       jne    Free_Chk_CLOSE_QUE       ; yes - get space from CLOSE queue
       jmp    short Free_Look_Open_Queue     ; if none, make space from OPEN Queue			 ;AN000;


; Else get space from CLOSE queue
Free_Chk_Close_QUE:		       ; SI-->CLOSE queue
       mov    si,es:[di].CLOSE_Ptr     ; select OPEN Queue					   ;AN000;
       CALL   FIND_LRU_HEADER	       ; find LRU  header in CLOSE Queue				 ;AN000;
				       ; DI-->LRU header

; Makesure to save all local variables	before calling DELETE
; since, this variables may be altered by DELETE routine.
       mov    ax,Hdr_Flag
       push   ax
       mov    ax,Prev_Hdr_Ptr
       push   ax
       mov    ax,Queue_Type
       push   ax
       mov    ax,Cur_Hdr_Ptr
       push   ax
       mov    ax,First_Phys_Clusnum    ; save original first phys from OPEN call
       push   ax		       ; in the stack
       mov    cx,es:[di].FH_Phys_Clus_Num  ; CX= starting phys clus num of LRU header
       mov    From_FreeBuff,1	       ; set flag

       push   ds
       mov    ax,Cseg_Main
       mov    ds,ax
       assume ds:Cseg_Main
       CALL   VECTOR_DELETE	       ; delete the file
       pop    ds
       assume ds:Cseg_Seek

       mov    From_FreeBuff,0	       ; clear flag
       mov    Free_Flag,1	       ; set flag to indicate discontinuous free area
       pop    ax		       ; restore first phys clus
       mov    First_Phys_Clusnum,ax    ; save it back where it belongs
       pop    ax		       ; restore current header
       mov    Cur_Hdr_Ptr,ax	       ; save it back where it belongs
       pop    ax		       ; restore current header
       mov    Queue_Type,ax	       ; save it back where it belongs
       pop    ax		       ; restore current header
       mov    Prev_Hdr_Ptr,ax	       ; save it back where it belongs
       pop    ax		       ; restore current header
       mov    Hdr_Flag,ax	       ; save it back where it belongs
       clc
       jmp    Free_exit 	       ; exit							   ;AN000;



;----------------------------------------------------------------------------
; No space available in CLOSE Queue . Now get some free space from OPEN Queue
; and add it to the free area.
;----------------------------------------------------------------------------
Free_Look_Open_Queue:
       mov    si,es:[di].MRU_Hdr_Ptr   ; SI-->First header in OPEN Queue			;AN000;
       CALL   FIND_LRU_HEADER	       ; find last header in Queue				   ;AN000;
				       ; DI-->last header
       mov    si,es:[di].FH_MRU_Extn_Ptr ;### SI-->first extent in this header			     ;AN000;
       cmp    si, -1		       ; any extent under this header ??			   ;AN000;
       jne    Free_Open_Find_Extent    ; yes, find last extent					   ;AN000;

; if no extents under this header, delete this header and free the space
       cmp    di,Cur_Hdr_Ptr	       ; header found is its own header ??			;AN000;
       jne    Free_OPen_Mark_Prev      ; no - free the header				  ;AN000;
       stc			       ; Yes - set carry, exit						 ;AN000;
       jmp    Free_Exit 	       ; ERROR	exit					    ;AN000;

Free_Open_Mark_Prev:		       ; mark previous header as LRU before deleting this header
       mov    si,LRU_Prev_Hdr	       ; SI-->previous header					   ;AN000;
       mov    es:[si].FH_Next_Hdr_Ptr, -1  ; mark previous header as last hdr			   ;AN000;
       jmp    Free_Open_Cl_Buffer								   ;AN000;

Free_Open_Find_Extent:
       mov    si,di		       ; SI-->header to be searched
       CALL   FIND_LRU_EXTENT	       ; ### find last extent in the header			       ;AN000;
       mov    di, LRU_Extent	       ; DI-->LRU extent
       cmp    Extn_flag,1	       ; Is this the only extent in the queue ? 		   ;AN000;
       jne    free_Open_prev_extn      ; no, mark previous extent as last extn			   ;AN000;
       push   di		       ; save pointer to Last extent				   ;AN000;
       mov    di,LRU_Hdr	       ; DI-->LRU header					   ;AN000;
       mov    es:[di].FH_Next_Extn_Ptr,-1 ; mark current HEADER with no extents 		       ;AN000;
       mov    es:[di].FH_MRU_Extn_Ptr,-1  ; ### mark current HEADER with no extents			   ;AN000;
       pop    di		       ; DI-->LRU extent					  ;AN000;
       jmp    Free_Open_Cl_Buffer      ; release this extent					   ;AN000;

;----------------------------------------------------------------------
; Mark Previous MRU extent as LRU extent and also connect the previous
; adjucent extent to the next adjcent extent.
;----------------------------------------------------------------------
Free_Open_Prev_Extn:			    ; mark previous MRU extent as LRU extnt
       mov    si, es:[di].EH_Prev_LRU_Ptr   ; no -  SI-->Previous adj extent
       mov    es:[si].EH_Next_LRU_Ptr, -1   ;mark previous extent as last extent	     ;AN000;

       cmp    es:[di].EH_Next_Extn_Ptr, -1  ; any next adjucent extent ??
       jne    OPen_Join_extents 	    ; yes - join previous to next

       mov    si, es:[di].EH_Prev_Extn_Ptr  ; no -  SI-->Previous adj extent
       cmp    si, -1			    ; any previous adj extent ??
       je     Open_Prev_Hdrx		    ; no - previous is a header
       mov    es:[si].EH_Next_Extn_Ptr, -1  ; mark previous extent as the last
       jmp    short Free_Open_Cl_Buffer     ; free the current extent

Open_Prev_Hdrx:
       push   di			    ; DI-->extent to be deleted
       mov    di,LRU_Hdr		    ; DI-->LRU header
       mov    es:[di].FH_Next_Extn_Ptr, -1  ; mark header with no extents
       mov    es:[di].FH_MRU_Extn_Ptr, -1   ; mark header with no extents
       pop    di
       jmp    short Free_Open_Cl_Buffer     ; free current extent

Open_Join_Extents:			    ; DI-->current extent to be freed
       mov    si, es:[di].EH_Prev_Extn_Ptr  ; no -  SI-->Previous adj extent
       cmp    si, -1			    ; any previous extent ??
       je     Open_Prev_Hdry		    ; no - previous is a header - join header
					    ; to extent
       mov    ax, es:[di].EH_Next_Extn_Ptr  ; AX = address of next adjucent extent
       mov    es:[si].EH_Next_Extn_Ptr,ax   ; connect prev adj extent to next adj extent
       push   di			    ; save addrs of extent to be deleted
       mov    di, ax			    ; SI = address of previous LRU extent
       mov    es:[di].EH_Prev_Extn_Ptr,si   ; address of next LRU extent
       pop    di			    ; restore address
       jmp    short Free_Open_Cl_Buffer     ; free the extent

Open_Prev_Hdry:
       mov    si, LRU_Hdr		    ; SI-->LRU_Hdr
       mov    ax, es:[di].EH_Next_Extn_Ptr  ; AX = address of next adjucent extent
       mov    es:[si].FH_Next_Extn_Ptr,ax   ; connect hdr to next adj extent
       mov    si,ax			    ; SI = addrss of next adj extent
       mov    es:[si].EH_Prev_Extn_Ptr,-1   ; mark no previous extent
       mov    di,LRU_Extent		    ; DI-->extent to be deleted

;----------------------------------------------------------------------------
; Free the current Extent or Header
;----------------------------------------------------------------------------
Free_Open_Cl_Buffer:		       ;
       mov    si,di		       ; SI-->LRU extent or header				  ;AN000;
       mov    di,Drive_Hdr_Ptr	       ; DI-->drive buffer					   ;AN000;
       mov    ax,es:[di].Free_Ptr								   ;AN000;
       mov    es:[si].EH_Next_Extn_Ptr,ax   ; connect Free ptr to last				   ;AN000;
				       ; extent in the queue
       mov    ax, -2		       ; discontinuous mark (-2)				   ;AN000;
       mov    es:[si], ax	       ; mark freed area as discontinuous			   ;AN000;
       mov    es:[di].Free_Ptr,si      ; connect header or extent to free area			   ;AN000;

; Increase the Free_Size entry in Drive Header
       mov    ax, Size File_Header     ; size is same for both header or extent 		   ;AN000;
       add    es:[di].Free_Size, ax    ; update free buffer count				   ;AN000;
       mov    Free_Flag,1	       ; set flag for discontinuous free area			   ;AN000;
       clc
Free_Exit:			       ; exit
      ret			       ; return 						   ;AN000;

FIND_FREE_BUFFER    endp






;----------------------------------------------------------------------
; PROCEDURE: Make_MRU_Header
;
; FUNCTION: Move header to the top of the queue. If the header is at the
;	    bottom of the queue, mark previous header as LRU header
;	    before moving the header to the top of the queue.
;
; INPUT:   Drive_Hdr_Ptr  - Points to drive header
;	   Cur_Hdr_Ptr	  - Points to current header
;	   ES--> Cache Buffer Segment
;
; OUTPUT:  Header is moved to top of the current queue
;	   SI-->current header
;
;----------------------------------------------------------------------

MAKE_MRU_HEADER    PROC    NEAR

       mov   si,Cur_Hdr_Ptr		 ; SI-->Current Header					   ;AN000;
       cmp   es:[si].FH_Next_Hdr_Ptr,-1  ; current header LRU header				   ;AN000;
       jne   Move_close_gap		 ; no, jump						   ;AN000;
												   ;AN000;
       mov   di,Prev_Hdr_Ptr		 ; yes, make previous header
       mov   es:[di].FH_Next_Hdr_Ptr,-1  ; LRU header						   ;AN000;
       jmp   short move_to_top

Move_Close_Gap:
       mov   di,Prev_Hdr_Ptr		 ; yes, get previous header
       mov   ax,es:[si].FH_Next_Hdr_Ptr     ; get next header address
       mov   es:[di].FH_Next_Hdr_Ptr,ax  ; connect previous hdr to next hdr
												   ;AN000;
Move_To_Top:
       mov   di,drive_Hdr_Ptr		 ; DI-->drive buffer					   ;AN000;
       mov   ax,es:[di].MRU_Hdr_Ptr	 ; connect current header to				   ;AN000;
       mov   es:[si].FH_Next_Hdr_Ptr,ax  ; previous MRU header					   ;AN000;
       mov   es:[di].MRU_Hdr_Ptr,si	 ; make current header MRU hdr				   ;AN000;
					 ;
       ret

Make_MRU_Header  ENDP






;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PROCEDURE: MAKE_MRU_EXTENT
;
; FUNCTION: Move Extent to the top of the queue. If the extent is at the
;	    bottom of the queue, mark previous extent as LRU extent
;	    before moving the extent to the top of the queue. If the extent
;	    is between first and last, then close the MRU-LRU chain gap.
;	    If the extent is already MRU then exit.
;
;	    This routine is called if clusters are inserted or looked up
;	    from an existing extent.
;
; INPUT:    Cur_Hdr_Ptr   - Address of current header
;	    Cur_Extn_Ptr  - Address of current extent
;	    ES--> Cache Buffer Segment
;
; OUTPUT:   Extent is moved next to the current header
;	    SI-->current extent
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

MAKE_MRU_EXTENT     PROC    NEAR

       mov   si,Cur_Hdr_Ptr		 ; SI-->Current Header					   ;AN000;
       mov   ax,Cur_Extn_Ptr
       cmp   es:[si].FH_MRU_Extn_Ptr, ax     ; current extent already MRU??				 ;AN000;
       je    Make_MRU_Exit		 ; yes - exit

       mov   si, Cur_Extn_Ptr		 ; SI-->Current extent
       mov   di,es:[si].EH_Prev_LRU_Ptr  ; get address of previous MRU extent
       cmp   di, -1			 ; any previous MRU extent ??
       je    Make_MRU_Exit		 ; none - exit- current extent is already MRU

; Close the gap (connect previous to next extent)
       mov   si, Cur_Extn_Ptr
       cmp   es:[si].EH_Next_LRU_Ptr, -1    ; current extent LRU extent ??
       jne   join_the_gap		    ; no - close the gap
       mov   es:[di].EH_Next_LRU_Ptr, -1    ; mark the previous extent MRU
       jmp   short move_MRU_Extent	    ; make mru extent

Join_The_Gap:
       mov   ax, es:[si].EH_Next_LRU_Ptr ; AX-->next LRU extent
       mov   es:[di].EH_Next_LRU_Ptr,ax  ; connect previous to next
       mov   bx,di			 ; BX-->prev LRU extent
       mov   di,ax			 ; DI-->Next LRU extent
       mov   es:[di].EH_Prev_LRU_Ptr, bx  ; set previous LRU extent address


; Make the current extent  MRU extent
Move_MRU_Extent:
       mov   di,Cur_Hdr_Ptr		    ; DI-->Current header
       mov   ax,es:[di].FH_MRU_Extn_Ptr     ; AX-->Previous MRU extent
       mov   es:[si].EH_NEXT_LRU_Ptr,ax     ; connect previous to  current extent
       mov   es:[di].FH_MRU_Extn_Ptr,si     ; make current extent MRU extent
       mov   es:[si].EH_Prev_LRU_Ptr, -1    ; mark no previous LRU extent

       mov   di,ax			    ;(12/29) set prev LRU addrs of prev MRU extent
       mov   es:[di].EH_Prev_LRU_Ptr,si     ;(12/29)

Make_MRU_Exit:
       clc
       ret				    ; return

MAKE_MRU_EXTENT     ENDP






;----------------------------------------------------------------------
; PROCEDURE: JOIN_PREV_TO_NEXT
;
; FUNCTION: Connect previous header to next header inorder to close the
;	    gap created when a header is moved to top of the Queue or to
;	    the top of CLOSE queue.  If the file header is the first header
;	    under the current Drive header, connect header to the MRU_Hdr_Ptr.
;
; INPUT:   Prev_Hdr_Ptr   - Points to Previous header
;	   Cur_Hdr_Ptr	  - Points to Current Header
;	   Queue_Type	  - Queue Type:  0 = Open Queue
;					 1 = Close Queue
;	   ES--> Cache Buffer Segment
; OUTPUT:  Gap is closed
;
;----------------------------------------------------------------------

JOIN_PREV_TO_NEXT    PROC

       cmp   Prev_Hdr_Ptr, -1		 ; current hdr first file header ??			   ;AN000;
       jne   join_prev_hdr		 ; no, close gap					   ;AN000;

; Yes, in this case close gap by connecting  Drive header to next header
       mov   di,Drive_Hdr_Ptr		 ; DI-->drive header					   ;AN000;
       mov   si,Cur_Hdr_Ptr		 ; SI-->Current header					   ;AN000;
       mov   ax,es:[si].FH_Next_Hdr_Ptr  ; AX-->Next Header					   ;AN000;
       cmp   Queue_Type, 1		 ; Is this Close Queue ??				   ;AN000;
       je    Join_Sel_Close_Ptr 	 ; Yes, jump						   ;AN000;
       mov   es:[di].MRU_Hdr_Ptr,ax	 ; join next header to Drive Header			   ;AN000;
       jmp   short join_exit		 ; exit 						   ;AN000;

Join_Sel_Close_Ptr:
       mov   es:[di].Close_Ptr,ax	 ; join next header to Drive Header			   ;AN000;
       jmp   short join_exit		 ; exit 						   ;AN000;


; Connect previous header to next header  ( close the gap )
Join_Prev_Hdr:
       mov   di,Prev_Hdr_Ptr		 ; DI-->Previous header 				   ;AN000;
       mov   si,Cur_Hdr_Ptr		 ; SI-->Current Header					   ;AN000;
       mov   ax,es:[si].FH_Next_Hdr_Ptr  ; connect previous header				   ;AN000;
       mov   es:[di].FH_Next_Hdr_Ptr,ax  ; to next header					   ;AN000;

Join_Exit:
       ret				 ; exit 						   ;AN000;

JOIN_PREV_TO_NEXT   ENDP






;----------------------------------------------------------------------
; PROCEDURE: UPDATE_FREE_AREA
;
; FUNCTION:  Update Free area pointer and Free area size before creating
;	     a new extent or new header
;
; INPUT:   Prev_Hdr_Ptr   - Points to Previous header
;	   Cur_Hdr_Ptr	  - Points to Current Header
;	   Queue_Type	  - Queue Type:  0 = Open Queue
;					 1 = Close Queue
;	   Free_Flag	  - Free area type:  0 = continous free area
;					     1 = non-contiguous free area
;	   ES--> Cache Buffer Segment
;
;
; OUTPUT:  Free pool address and size is updated
;
;----------------------------------------------------------------------

UPDATE_FREE_AREA     PROC

       mov   di,Drive_Hdr_Ptr		 ; DI-->drive header					   ;AN000;
       mov   si,es:[di].Free_Ptr	 ; SI-->current free pointerted 			  ;AN000;
					 ;
       mov   ax, Size Extent_Header								   ;AN000;
       sub   es:[di].Free_Size, ax	 ; update free area size				   ;AN000;

       cmp   Free_Flag, 1		 ; continuous free area ??				   ;AN000;
       jne   ext_add_free_ptr		 ; yes - update free area pointer			    ;AN000;

;----------------------------------------------------------------------
; If discontinuous Free area. Update the Free pointer by getting pointer
; to next free from the 4th word using header or extent structure.
; This is because the discontinuous areas are connected chained through
; the 4th word
;----------------------------------------------------------------------
       mov   ax,es:[si].FH_Next_Hdr_Ptr  ; no, update FREE area pointer 			   ;AN000;
       mov   es:[di].Free_Ptr,ax	 ; using the Header structure				   ;AN000;
       jmp   short Update_Free_Exit	 ; Exit 						   ;AN000;

;----------------------------------------------------------------------
; If continuous Free area. Next free area address is computed by adding
; the size of extent of header structure.
;----------------------------------------------------------------------
Ext_Add_Free_Ptr:
       mov   ax, size File_Header	 ; calculate the address of				   ;AN000;
       add   es:[di].Free_Ptr,ax	 ; next free area by adding size of			   ;AN000;
					 ; a extent or header. Both same size
Update_Free_Exit:
       ret				 ; exit 						   ;AN000;

UPDATE_FREE_AREA     ENDP




;----------------------------------------------------------------------
; Procedure: CHECK_IT	   Checks the validity of the queues
;
;----------------------------------------------------------------------

CHECK_IT   PROC    NEAR

       pushf				      ; save all registers
       push   bx
       push   di
       cmp    check_flag,0
       je     check_exit
       mov    ah,090h
       xor    al,al
       xor    cx,cx
       mov    cl,func_cod
       mov    di, Drive_Hdr_Ptr
       INT    2FH
check_exit:
       pop    di
       pop    bx
       popf
       ret

CHECK_IT    ENDP



; Calculate the size of the Cseg_Seek module in bytes
	IF  ($-Cseg_Seek) MOD 16								   ;AN000;
	   ORG ($-Cseg_Seek)+16-(($-Cseg_Seek) MOD 16)						   ;AN000;
	ENDIF											   ;AN000;
END_SEEK   label   word


CSEG_SEEK    ENDS
     END