-
Notifications
You must be signed in to change notification settings - Fork 7
/
sys2.asm
executable file
·2621 lines (2440 loc) · 83.4 KB
/
sys2.asm
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
TITLE SYS-2- Program
include version.inc
INCLUDE SYSHDR.INC
page 80,132
BREAK <SYS2 - Program Organization>
;******************+ START OF PSEUDOCODE +**************************************
; Ä Ä Ä Ä Ä Ä Ä # ÚÄÄÄÄÄÄÄÄ#
; Read_Directory ÃÄÄÄÄÄ#Find_DPB ³
; Ä Ä Ä Ä Ä Ä Ä ÄÙ ÀÄÄÄÄÄÄÄÄÄÙ
; Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä#
; Verify_File_LocationÃ#
; Ä Ä Ä Ä Ä Ä Ä Ä Ä ÄÄÙ ³
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
; ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ# ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä Ä Ä Ä ¿
; Ã#Move_DIR_EntryÃÄÄ´Find_Empty_Entry ÃÄ#Direct_Access³
; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ#
; ³ À´Direct_Access³
; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
; ³ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; ³ ÚÄÄÄÄÄÄÄÄÄÄÄ# ÚÄÄÄÄÄÄÄÄÄÄ# ÚÄÄÄÄÄÄ#
; À#Free_ClusterÃÄÄÄÄ´Is_It_EmptyÃÄÄÄÄÄÄÄ#Unpack ³
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ
; ³ÚÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä ¿
; ôSearch_FATÃÄÄÄÄÄÄÄÄ´Unpack ³
; ³ÀÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
; ³ ³ÚÄÄÄÄÄ#
; ³ ôPack ³
; ³ ³ÀÄÄÄÄÄÄÙ
; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä ¿
; ³ ôFind_Empty_Cluster³Ä#Unpack ³
; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
; ³ ³ÚÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä Ä Ä Ä ¿
; ³ ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄ#Direct_Access³
; ³ ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
; ³ ³Ú Ä Ä Ä Ä Ä Ä ¿
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À´Direct_Access³
; ³ À Ä Ä Ä Ä Ä Ä Ù
; ³ÚÄÄÄÄÄÄÄÄÄ# ÚÄÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä ¿
; À´Search_DIRÃÄÄÄ#Search_LoopÃÄÄÄÄÄ´Unpack ³
; ÀÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
; ³ÚÄÄÄÄÄ#
; ôPack ³ Direct_Access
; ³ÀÄÄÄÄÄÄÙ
; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä ¿
; ôFind_Empty_Cluster³Ä#Unpack ³
; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
; ³ÚÄÄÄÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä ¿
; ôSub_DIR_Loop³Ä#Unpack ³
; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
; ³ÚÄÄÄÄÄÄÄÄ# Ú Ä Ä Ä Ä Ä Ä ¿
; ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄ#Direct_Access³
; ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
; ³Ú Ä Ä Ä Ä Ä Ä ¿
; À´Direct_Access³
; À Ä Ä Ä Ä Ä Ä Ù
;
;******************+ END OF PSEUDOCODE +*****************************************
BREAK <SYS2 - Data space>
DATA SEGMENT PARA PUBLIC
extrn TargDrvNum:BYTE, TargSpec:WORD, bio_owns_it:BYTE, DOS_VER:BYTE
extrn packet_sectors:WORD, packet_buffer:WORD, packet:WORD
public THIS_DPB, BUF, DIR_SECTOR, first_dir_sector
; $SALUT (4,25,30,41)
first_dir_sector dw ?
current_dir_sector dw ?
last_dir_sector dw ?
entries_per_sector db ?
current_entry db 3
source_ptr dw ?
ibmbio_status db ?
ibmdos_status db ?
FAT_sectors dw FAT_sect_size ; initailize it to 12 sectors
FAT_changed db 0 ; FAT must be written - its packed
FAT_2 db 0 ; if non zero, [packet] points at FAT 2
cluster_count dw ? ; number of clusters that must be free
last_cluster dw 0 ; cluster pointing to [current_cluster]
current_cluster dw 2 ; start at cluster 2
next_cluster dw 0 ; cluster [current_cluster] points at
empty_cluster dw 0 ; newly aquired cluster
cluster_low dw 0
cluster_high dw clusters_loaded
l_sector_offset dw ? ; this is the value required to convert
; a sector from a cluster # to a
; logical sector # for INT 25 & 26
DIR_cluster dw 0 ; Sub DIR cluster being processed
; = 0 - not processing s Sub DIR
; = 1 - starting to process
; (set by Search_Loop)
; = n - Sub DIR cluster now being
; processed. (set by Xfer_Data)
present_cluster dw ? ; current cluster for DIR search
sector_offset dw ? ; current sector in present_cluster
entry_number db ? ; DIR entry in current sector
FRAME_ptr dw ?
dir_sector_low dw ?
dir_sector_hi dw ?
DIR_offset dw ?
sector_count db 1
FRAME STRUC
p_cluster dw ? ; current cluster for DIR search
s_offset dw ? ; current sector in present_cluster
e_number db ? ; DIR entry in current sector
FRAME ENDS
BIGFAT DB 0 ;0=12 bit FAT, NZ=16bit FAT
EOFVAL DW 0FF8H ;0FF8 for 12 bit FAT,0FFF8 for 16 bit
BADVAL DW 0FF7H ;0FF7 for 12 bit FAT,0FFF7 for 16 bit
THIS_DPB DD ? ;Pointer to drive DPB
CSIZE DW ? ;Sectors per cluster
SSIZE DW ? ;bytes per sector
DSIZE DW ? ;# alloc units on disk
FSIZE DW ? ;# sectors in 1 FAT
first_FAT DW ? ; first cluster of first FAT
num_of_FATS db ? ; number of FATS
MCLUS DW ? ;DSIZE + 1
;
; The following is used as the source/destination for a name trans
;
ENTRY_BUF DB size dir_entry DUP (?)
DIR_BUF DB ( 34 * size frame) DUP (?) ; space for DIR frames - see Search_DIR
DIR_SECTOR DB 512 DUP (?) ; space for 1 DIR sector
BUF LABEL BYTE ; beginning of area for file reads
DATA ENDS
; $SALUT (4,4,9,41)
CODE SEGMENT PARA PUBLIC
ASSUME cs:CODE, ds:nothing, es:nothing
BREAK <SYS - Find_DPB >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Find_DPB
;*******************************************************************************
;
;Description: Find_DPB gets the pointer to the Target DPB and initializes all
; local valiables required by Move_DIR_Entry and Free_Cluster.
;
;NOTE: This routine contains code that is specific for DOS 3.3. It
; must be removed for subsequent releases. In and before
; DOS 3.3 the DPB was one byte smaller. The field dpb_FAT_size
; was changed from a byte to a word in DOS 4.00.
;
;
;Entry: Called by Verify_File_Location
;
;Called Procedures:
;
; INT 21 - 32h
;
;Input: al = Drive number
;
;Output: All local variables initalized
; DS:BX = pointer to DPB
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Find_DPB
;
; get DPB pointer (INT 21 - 32h)
; initalize first_dir_sector
; initalize current_dir_sector
; initalize current_cluster (0 for root)
; calculate # of clusters required by IBMBIO
; initalize [cluster_count]
; calculate # of dir sectors
; initalize [dir_sectors]
; initalize [current_entry] to #3
; allocate memory for FAT + 32 DIR frames
; allocate memory for data sectors
;
; ret
;
; END Find_DPB
;
;******************- END OF PSEUDOCODE -**************************************
PUBLIC Find_DPB
Find_DPB PROC NEAR
MOV AH,GET_DPB ;Get the DPB ;AN004;
INT 21H
mov ax,(disk_reset shl 8) ; reset the disk to protect all INT 26's
INT 21h ; that follow
; initalize current_entry to #3
ASSUME ds:nothing,es:DATA
MOV WORD PTR [THIS_DPB+2],DS ; ;AN004;
push es ; ;AN004;
pop ds ; ;AN004;
ASSUME ds:DATA
mov WORD PTR [THIS_DPB],bx ; ;AN004;
lds bx,[THIS_DPB] ; ;AN004;
ASSUME ds:nothing
mov ax,[bx.dpb_sector_size] ; ;AN004;
mov [SSIZE],ax ;Sector size in bytes ;AN004;
xor ax,ax ; ;AN004;
mov al,[bx.dpb_cluster_mask] ; ;AN004;
inc al ; ;AN004;
mov [CSIZE],ax ;Sectros per cluster ;AN004;
mov ax,[BX.dpb_first_FAT] ;First sector of FAT ;AN004;
mov [first_FAT],ax ; ;AN004;
mov al,[BX.dpb_FAT_count] ;Number of FATs ;AN004;
mov [num_of_FATS],al ; ;AN004;
mov ax,[bx.dpb_max_cluster] ; ;AN004;
mov [MCLUS],ax ;Bound for FAT searching ;AN004;
cmp ax,4096-10 ;Big or little FAT? ;AN004;
; $if ae ; ;AN004;
JNAE $$IF1
inc [BIGFAT] ; ;AN004;
mov [EOFVAL],0FFF8h ; ;AN004;
mov [BADVAL],0FFF7h ; ;AN004;
; $endif ; ;AN004;
$$IF1:
dec ax ; ;AN004;
mov [DSIZE],ax ;Total data clusters on disk ;AN004;
;--------------------------------------
; calculate # of dir sectors and
; initalize last_dir_sector
;--------------------------------------
mov ax,[bx.dpb_root_entries] ; max # of entries in the root ;AN004;
mov cx,size dir_entry ; size of each entry ;AN004;
mul cx ; size of root directory in bytes ;AN004;
; in AX:DX ;AN004;
mov cx,[SSIZE] ; # of bytes per sector ;AN004;
div cx ; = # of root directory sectors ;AN004;
cmp dx,0 ; any remainder ? ;AN004;
; $if nz ; ;AN004;
JZ $$IF3
inc ax ; ;AN004;
; $endif ; ;AN004;
$$IF3:
mov [first_dir_sector],ax ; save for last directory sector calc. ;AN004;
mov ax,[bx.dpb_FAT_size] ;Sectors for one fat ;AN004;
cmp DOS_VER,0 ; running on current version? ;AN019;
; $if ne ; BANG! - we'er running on DOS 3.3 ;AN019;
JE $$IF5
; dpb_FAT_size is only a BYTE
; so ajust it to a word
xor ah,ah ;AN019;
dec bx ; BACK UP the index into the DPB ;AN019;
mov WORD PTR [THIS_DPB],bx ; save it for later (dpb_next_free) ;AN021;
; Now everything else lines up !
; $endif
$$IF5:
mov [FSIZE],ax ; ;AN004;
mov ax,[SSIZE] ; ;AN004;
mov cx,SIZE dir_entry ; ;AN004;
div cx ; ;AN004;
dec ax ; first entry number is zero ;AN004;
mov [entries_per_sector],al ; ;AN004;
cmp [BIGFAT],0 ; is it a big fat ? ;AN004;
; $if e ; if not ;AN004;
JNE $$IF7
mov ax,[FSIZE] ; ;AN004;
mov [FAT_sectors],ax ; bring it down to the actual size ;AN004;
; $endif ; ;AN004;
$$IF7:
;--------------------------------------
; initalize first_dir_sector
; and current_dir_sector
;--------------------------------------
mov ax,[bx.dpb_dir_sector] ; first dir sector ;AN004;
mov [current_dir_sector],ax ; save it for later ;AN004;
xchg [first_dir_sector],ax ; save it and recover # of dir sectors ;AN004;
add ax,[first_dir_sector] ; # of last directory sector ;AN004;
mov [l_sector_offset],ax ; ;AN004;
dec ax ; ;AN004;
mov [last_dir_sector],ax ; save it for later ;AN004;
ret ; ;AN004;
Find_DPB ENDP
BREAK <SYS - Move_DIR_Entry >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Move_DIR_Entry
;*******************************************************************************
;
;Description: Move_DIR_Entry will move the entry pointed to by the caller into
; the first available location in the root, if one exists.
;
;Entry: Called by Verify_File_Location
;
;Called Procedures:
;
; Find_Empty_Entry - find an available entry
; Direct_Access - do an INT 25 & INT 26
;
;Input: first_dir_sector
; current_dir_sector
; last_dir_sector
; current_entry
; pointer set to source entry to be moved
;
;Output: CF = 0 - DIR entry moved to first available entry
; CF = 1 - Error, not able to free up entry
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Move_DIR_Entry
;
; set dest = entry_buffer
; save source pointer
; copy input entry to buffer
; if no error and
; call Find_Empty_Entry to find hole in directory
; if no error
; set source to entry_buffer
; set dest to hole pointer
; copy buffer to enpty entry
; if first_dir_sector != current_dir_sector
; set up for write
; call Direct_Access to write it out
; if no error
; set up for first_dir_sector
; set up for read
; call Direct_Access to read it in
; endif
; if no error
; recover source pointer
; null out entry being processed
; set up for write
; call Direct_Access to update the root
; endif
; endif
;
; ret
;
; END Move_DIR_Entry
;
;******************- END OF PSEUDOCODE -**************************************
PUBLIC Move_DIR_Entry
Move_DIR_Entry PROC NEAR
ASSUME ds:DATA ; must ensure this is true xxxxxxxxxxxxxxxxx
; source = source entry (#1 or #2) DS:SI
lea di,ENTRY_BUF ; dest = entry_buffer ;AN004;
mov [source_ptr],si ; save source pointer ;AN004;
mov ax,size dir_entry ; ;AN004;
mov cx,ax ; ;AN004;
rep movsb ; copy directory entry into entry buffer;AN004;
lea si,DIR_SECTOR ; start at beginning of directory ;AN004;
mov di,si ; save start for end calculation ;AN004;
shl ax,1 ; set pointer for current entry to #3 ;AN004;
add ax,si ; ;AN004;
mov si,ax ; ;AN004;
add di,[SSIZE] ; calculate end of directory ;AN004;
call Find_Empty_Entry ; find hole in directory ;AN004;
; $if nc ; if no error and ;AN004;
JC $$IF9
mov di,si ; dest = hole pointer ;AN004;
lea si,ENTRY_BUF ; source = entry_buffer ;AN004;
mov cx,size dir_entry ; ;AN004;
rep movsb ; copy buffer to DTA ;AN004;
mov ax,[first_dir_sector] ; ;AN004;
cmp ax,[current_dir_sector] ; ;AN004;
; $if ne ; if first_dir_sector != current_dir_sector;AN004;
JE $$IF10
mov ah,-1 ; set up for write ;AN004;
call Direct_Access ; write it out ;AN004;
; $if nc ; if no error ;AN004;
JC $$IF11
mov ax,[first_dir_sector] ; set up for first_dir_sector ;AN004;
mov [current_dir_sector],ax ; update current_dir_sector ;AN004;
mov [packet],ax ; ;AN004;
xor ah,ah ; set up for read ;AN004;
call Direct_Access ; read it in ;AN004;
; $endif ; ;AN004;
$$IF11:
; $endif ; ;AN004;
$$IF10:
; $if nc ; if no error ;AN004;
JC $$IF14
mov si,[source_ptr] ; recover source pointer ;AN004;
mov BYTE PTR [si],deleted ; delete entry being processed ;AN004;
mov BYTE PTR [si.dir_first],0 ; null out cluster # ;AN004;
cmp si,offset DIR_SECTOR ; are we at the first entry ? ;AN010;
; $if e,and ; if so - ;AN010;
JNE $$IF15
cmp BYTE PTR [si + size DIR_ENTRY],0 ; is second one a null entry? ;AN010;
; $if e ; if so - ;AN010;
JNE $$IF15
mov BYTE PTR [si + size DIR_ENTRY],deleted ; make it deleted ;AN010;
; $endif ; ;AN010;
$$IF15:
mov ah,-1 ; set up for write ;AN004;
call Direct_Access ; write it out ;AN004;
; $endif ; ;AN004;
$$IF14:
; $endif ; ;AN004;
$$IF9:
ret ; ;AN004;
Move_DIR_Entry ENDP
BREAK <SYS - Find_Empty_Entry >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Find_Empty_Entry
;*******************************************************************************
;
;Description: Find_Empty_Entry scans all root directory sectors looking for
; an empty entry.
;
; NOTE; It is assumed that each DIRectory entry is 32 bytes long
;
;Called Procedures:
;
; Direct_Acces - do INT 25
;
;Input: current_dir_sector
; last_dir_sector
; first_dir_sector in DTA buffer
; DS:SI set for first entry to check
; DS:DI set to end of directory (sector)
;
;Output: success pointer set to hole
; CF = 0 current_entry updated
; current_dir_sector updated
;
; fail message # set
; CF = 1
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Find_Empty_Entry
;
; search all available sectors
; search for hole (leaves pointer set to the hole)
; leave if empty
; leave if deleted
; advace to next entry
; exitif past end of sector
; set carry
; orelse
; endloop
; clear carry
; save current_entry
; endsrch
; exitif hole found (no CF)
; update current_entry
; orelse
; if not at end (current <= last)
; set for read
; call Direct_Access to read in next sector
; else
; load error message (no room for system files)
; set error (CF)
; endif
; leave if error (CF)
; update current_DIR_sector
; update current_entry
; endif
; endloop
; endsrch
;
; ret
;
; END Find_Empty_Entry
;
;******************- END OF PSEUDOCODE -**************************************
PUBLIC Find_Empty_Entry
Find_Empty_Entry PROC NEAR
; $search ; for sectors available ;AN004;
$$DO19:
; ;AN004;
; $search ; for hole - this leaves pointer set at;AN004;
$$DO20:
; the hole ;AN004;
cmp BYTE PTR [si],empty ; empty ? ;AN004;
; $leave e ; ;AN004;
JE $$EN20
cmp BYTE PTR [si],deleted ; deleted ? ;AN004;
; $leave e ; ;AN004;
JE $$EN20
add ax,size dir_entry ; advace to next entry ;AN004;
mov si,ax ; ;AN004;
cmp ax,di ; past end of sector ? ;AN004;
; $exitif ae ; at end ;AN004;
JNAE $$IF20
stc ; set carry ;AN004;
; $orelse ; ;AN004;
JMP SHORT $$SR20
$$IF20:
; $endloop ; ;AN004;
JMP SHORT $$DO20
$$EN20:
clc ; clear carry ;AN004;
; $endsrch ; ;AN004;
$$SR20:
; $exitif nc ; hole is found ;AN004;
JC $$IF19
; $orelse ; ;AN004;
JMP SHORT $$SR19
$$IF19:
inc [current_dir_sector] ; advance to next sector ;AN004;
mov ax,[current_dir_sector] ; ;AN004;
cmp ax,[last_dir_sector] ; past last_dir_sector ? ;AN004;
; $leave a ; if at end (current <= last) ;AN004;
JA $$EN19
lea si,DIR_SECTOR ; start at start of next sector ;AN004;
mov [packet],ax ; ;AN004;
xor ah,ah ; set for read ;AN004;
call Direct_Access ; read in next sector ;AN004;
; $if c ; if error ;AN004;
JNC $$IF30
dec [current_dir_sector] ; restore curren_dir_sector ;AN004;
; $endif ; ;AN004;
$$IF30:
; $leave c ; error ;AN004;
JC $$EN19
mov ax,si ; reset pointer to start ;AN004;
; $endloop a ; past last_dir_sector ;AN004;
JNA $$DO19
$$EN19:
mov ax,(util shl 8) + no_room ; set message# and class ;AN004;
stc ; ensure carry still set ;AN004;
; $endsrch ; ;AN004;
$$SR19:
ret ; ;AN004;
Find_Empty_Entry ENDP
BREAK <SYS - Direct_Access >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Direct_Access
;*******************************************************************************
;
;Description: Direct_Access
;
;Called Procedures:
;
; INT 25
; INT 26
;
;Input: ah = 0 - read
; ah = -1 - write
;
;Output: CF = 0 - Sectors moved
; CF = 1 - Message and class in AX
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Direct_Access
;
; save registers
; if read
; INT 25
; else
; zero ah
; INT 26
; endif
; save return flag
; clear stack
; if error
; set message# and class
; endif
; restore registers
;
; ret
;
; END Direct_Access
;
;******************- END OF PSEUDOCODE -**************************************
public Direct_Access
Direct_Access PROC NEAR
push si ; save registers ;AN004;
push bp ; save registers ;AN004;
cmp DOS_VER,0 ; ;AN019;
; $if e ; ;AN019;
JNE $$IF35
mov cx,-1 ; set up for INT ;AN004;
mov bx,offset packet ; ;AN004;
; $else ; ;AN019;
JMP SHORT $$EN35
$$IF35:
; If running on DOS 3.3 the INT 25
; interface is:
; al = drive number
; bx = buffer for read data
; cx = # of sectors
; dx = start sector
mov cx,word ptr [packet_sectors] ; ;AN019;
mov dx,[packet] ; get starting dir sector ;AN019;
mov bx,PACKET_BUFFER[0] ; ;AN019;
; $endif ; ;AN019;
$$EN35:
mov al,TargDrvNum ; set up drive number ;AN004;
dec al ; ;AN004;
cmp ah,0 ; ;AN004;
; $if e ; if read ;AN004;
JNE $$IF38
INT 25h ; INT 25 ;AN004;
; $else ; else ;AN004;
JMP SHORT $$EN38
$$IF38:
xor ah,ah ; zero ah ;AN004;
INT 26h ; INT 26 ;AN004;
; $endif ; endif ;AN004;
$$EN38:
;; ? ; save return flag ;AN004;
pop ax ; clear stack ;AN004;
pop bp ; ;AN004;
pop si ; ;AN004;
ret ; ;AN004;
Direct_Access ENDP
BREAK <SYS - Free_Cluster >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Free_Cluster processor
;*******************************************************************************
;
;Description: IBMBIO MUST have at lease cluster 2 as its first cluster. This
; routine ensures that cluster 2 and any additional clusters (if
; needed) ARE available. If they are chained, their data is copied
; into the first available cluster, and the needed cluster is
; is replaced by this cluster in the FAT
;
;Entry: Called by Verify_File_Location
;
;Called Procedures:
;
; Is_It_Empty - see if Cluster is empty
; Search_FAT - scan FAT to see if the cluster is chained
; Search_DIR - use FAT to walk directories looking for the cluster
;
; NOTES: Check_FAT and Check_DIR will do the processing requred to move
; data out of the cluster and fix up the FAT and the Dir (if needed).
;
;Input: All local DBP values initalized by Get_DPB
;
;Ouput: CF = 0 - Cluster available
; CF = 1 - Cluster not available
;
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Free_Cluster
;
; initialize [cluster_count]
; do until all copies of FAT attempted
; load FAT into memory (INT 25)
; leave if successful
; enddo
; do until [cluster_count] = 0
; call Is_It_Empty
; if not found and
; if no errors and
; call Search_FAT
; if not found and
; if no errors
; call Search_DIR
; endif
; leave if error
; enddo
;
; ret
;
; END Free_Cluster
;
;******************- END OF PSEUDOCODE -**************************************
public Free_Cluster
Free_Cluster PROC NEAR
mov ax,IBMLOADSIZE ; calculate # of clusters reqd ;AN004;
xor cx,cx ; ;AN004;
mov di,cx ; ;AN004;
dec di ; ;AN004;
mov cx,[CSIZE] ; by IBMLOAD (consecutive clusters ;AN004;
div cl ; for IBMBIO) ;AN004;
cmp ah,0 ; ;AN004;
; $if ne ; ;AN004;
JE $$IF41
inc al ; ;AN004;
xor ah,ah ; ;AN004;
; $endif ; ;AN004;
$$IF41:
inc ax ; will be decrimenter immediately upon ;AN004;
; entering complex do below
mov [cluster_count],ax ; save for later ;AN004;
mov ax,[FAT_sectors] ;only read needed sectors ;AN004;
mov [packet_sectors],ax ; ;AN004;
mov cl,[num_of_FATS] ;Number of FATs ;AN004;
mov ax,[first_FAT] ;First sector of FAT ;AN004;
mov [packet],ax ; ;AN004;
mov [packet_buffer],OFFSET BUF ; point to FAT buffer ;AN004;
call Load_FAT ; ;AN004;
; $if nc ; no error so far....... ;AN004;
JC $$IF43
; $do complex ; ;AN004;
JMP SHORT $$SD44
$$DO44:
mov [cluster_count],cx ; ;AN004;
call Is_It_Empty ; ;AN004;
; $leave c ; ;AN014;
JC $$EN44
cmp al,not_found ; ( -1 ?) ;AN004;
; $if e ; if not found ;AN004;
JNE $$IF46
call Search_FAT ; scan FAT to see if cluster chained ;AN004;
; $else ; ;AN004;
JMP SHORT $$EN46
$$IF46:
clc ; ;AN004;
; $endif ; ;AN004;
$$EN46:
; $leave c ; ;AN004;
JC $$EN44
cmp al,not_found ; if still not found ;AN004;
; $if e ; ;AN004;
JNE $$IF50
call Search_DIR ; scan DIR to see who starts with #2 ;AN004;
; $else ; ;AC013;
JMP SHORT $$EN50
$$IF50:
clc ; ensure carry is still clear ;AC013;
; $endif ; ;AN004;
$$EN50:
; $leave c ; ;AN004;
JC $$EN44
inc [current_cluster] ; ;AN004;
; $strtdo ; ;AN004;
$$SD44:
mov cx,[cluster_count] ; ;AN004;
; $enddo LOOP ; ;AN004;
LOOP $$DO44
$$EN44:
; $endif ; ;AN004;
$$IF43:
; $if c ; ;AN004;
JNC $$IF57
mov ax,(util shl 8) + no_room ; error message - no room to sys ;AN014;
; $endif ; ;AN004;
$$IF57:
ret ; ;AN004;
Free_Cluster ENDP
public Load_FAT
Load_FAT PROC NEAR
lea bx,[packet] ; ;AN004;
; $search ; ;AN004;
$$DO59:
xchg cx,di ; ;AN004;
push cx ; ;AN004;
push di ; ;AN004;
push dx ; ;AN004;
push bx ; ;AN004;
xor ah,ah ; ;AN004;
mov al,TargDrvNum ; set up drive number ;AN004;
dec al ; ;AN004;
cmp DOS_VER,0 ; if DOS 3.3 ;AN019;
; $if ne ; load registers for old style INT 25 ;AN019;
JE $$IF60
mov bx,[packet_buffer] ; ;AN019;
mov cx,[packet_sectors] ; ;AN019;
mov dx,[packet] ; ;AN019;
; $endif ; ;AN019;
$$IF60:
push bp ; ;AN019;
int 25h ;Read in the FAT ;AN004;
pop ax ;Flags ;AN004;
pop bp ; ;AN019;
; $exitif nc ; error - set up for next fat ;AN004;
JC $$IF59
add sp,8 ;Clean up stack ;AN004;
mov ax,1 ; ;AN004;
; mov [packet],ax ; reset to first FAT ;AN004;
; $orelse ; ;AN004;
JMP SHORT $$SR59
$$IF59:
pop bx ; ;AN004;
pop dx ; ;AN004;
pop cx ; ;AN004;
pop di ; ;AN004;
add [packet],dx ; point to start of next FAT ;AN004;
inc [FAT_2] ; ;AN004;
; $endloop LOOP ;Try next FAT ;AN004;
LOOP $$DO59
mov ax,(util shl 8) + no_room ; set message# and class ;AN004;
; $endsrch ; ;AN004;
$$SR59:
ret
Load_FAT ENDP
BREAK <SYS - Is_It_Empty >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Is_It_Empty
;*******************************************************************************
;
;Description: Is_It_Empty looks directly into the FAT to see if a specified
; cluster is allocated.
;
;Entry: Called by Free_Cluster
;
;Called Procedures:
;
; Unpack - unpack a FAT cluster number (CF set on error)
;
;Input: CX = cluster to check
; 12 sectors of FAT in BUF
;
;Output: CF = 0 AL = 0 - cluster 2 found empty
; AL =-1 - not found & no error
; CF = 1 - critical error
;
;Change History: Created 7/01/87 FG
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Is_It_Empty
;
; set up for call to Unpack
; set cluster # to [cluster_number]
; call Unpack
; if no error
; if cluster is not empty
; if bad cluster
; set error flag
; else
; if cluster belongs to IBMBIO
; if next cluster is not contiguous
; reset ownership flag
; endif
; set cluster empty (ax = 0)
; else
; save cluster number
; set cluster used (ax = -1)
; endif
; else
; set cluster empty (ax = 0)
; endif
; endif
;
; ret
;
; END Is_It_Empty
;
;******************- END OF PSEUDOCODE -**************************************
public Is_It_Empty
Is_It_Empty PROC NEAR
mov si,[current_cluster] ; set up for call to Unpack ;AN004;
call Unpack ; to find the value ;AN004;
; $if nc ; if no error ;AN004;
JC $$IF66
; $if nz ; cluster is not empty ;AN004;
JZ $$IF67
mov ax,di ; ;AN004;
cmp al,bad_sector ; ;AN004;
; $if e ; ;AN004;
JNE $$IF68
stc ; ;AN004;
; $else ; ;AN004;
JMP SHORT $$EN68
$$IF68:
cmp [bio_owns_it],0 ; is it owned by IBMBIO ? ;AN004;
; $if ne ; if it is ;AN004;
JE $$IF70
dec ax ; ;AN004;
cmp ax,[current_cluster] ; ;AN004;
; $if ne ; ;AC011;
JE $$IF71
dec [bio_owns_it] ; its not the owner form here on ;AC011;
; $endif ; ;AC011;
$$IF71:
xor ax,ax ; ;AN004;
clc ; its IBMBIO's anyway ;AC011;
; $else ; ;AN004;
JMP SHORT $$EN70
$$IF70:
mov [next_cluster],di ; ;AN004;
xor ax,ax ; reset fail flag ;AN004;
dec ax ; - its not empty ;AN014;
; $endif ; ;AN004;
$$EN70:
; $endif ; ;AN004;
$$EN68:
; $else ; its empty ! ;AN005;
JMP SHORT $$EN67
$$IF67:
xor ax,ax ; its empty - and no error ;AN014;
; $endif ; ;AN014;
$$EN67:
; $endif ; ;AN004;
$$IF66:
ret ; ;AN004;
Is_It_Empty ENDP
BREAK <SYS - Search_FAT >
;******************* START OF SPECIFICATIONS ***********************************
;Routine name: Search_FAT
;*******************************************************************************
;
;Description: Search_FAT for a [cluster_number]. If it is listed in the FAT,
; then its chained into a file. The data in the [cluster_number] is
; then buffered, and copied into an empty cluster, and the FAT is
; updated
;
;Called Procedures:
;
; Unpack - to find a FAT entry for a Cluster #
; Pack - to set a FAT entry for a Cluster #
; Find_Empty_Cluster - find an unused cluster
; Xfer_Data - transfere data from one cluster to another
; Direct_Access - absolute disk i/o
;
;Input: FAT in BUF
; [cluster_number] of specified cluster
;