summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/ROM.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/DOS/ROM.ASM')
-rw-r--r--v4.0/src/DOS/ROM.ASM938
1 files changed, 938 insertions, 0 deletions
diff --git a/v4.0/src/DOS/ROM.ASM b/v4.0/src/DOS/ROM.ASM
new file mode 100644
index 0000000..ca34409
--- /dev/null
+++ b/v4.0/src/DOS/ROM.ASM
@@ -0,0 +1,938 @@
1; SCCSID = @(#)rom.asm 1.1 85/04/10
2TITLE ROM - Miscellaneous routines
3NAME ROM
4; Misc Low level routines for doing simple FCB computations, Cache
5; reads and writes, I/O optimization, and FAT allocation/deallocation
6;
7; SKPCLP
8; FNDCLUS
9; BUFSEC
10; BUFRD
11; BUFWRT
12; NEXTSEC
13; OPTIMIZE
14; FIGREC
15; ALLOCATE
16; RESTFATBYT
17; RELEASE
18; RELBLKS
19; GETEOF
20;
21; Modification history:
22;
23; Created: ARR 30 March 1983
24;
25
26;
27; get the appropriate segment definitions
28;
29.xlist
30include dosseg.asm
31include fastseek.inc ; DOS 4.00
32include fastxxxx.inc ; DOS 4.00
33include version.inc
34
35CODE SEGMENT BYTE PUBLIC 'CODE'
36 ASSUME SS:DOSGROUP,CS:DOSGROUP
37
38.xcref
39INCLUDE DOSSYM.INC
40INCLUDE DEVSYM.INC
41include EA.inc
42.cref
43.list
44
45 i_need CLUSNUM,WORD
46 i_need NEXTADD,WORD
47 i_need LASTPOS,WORD
48 i_need SECCLUSPOS,BYTE
49 i_need FATBYT,WORD
50 i_need THISSFT,DWORD
51 i_need TRANS,BYTE
52 i_need BYTCNT1,WORD
53 i_need CURBUF,DWORD
54 i_need BYTSECPOS,WORD
55 i_need DMAADD,WORD
56 i_need SECPOS,DWORD ;F.C. >32mb
57 i_need VALSEC,DWORD ;F.C. >32mb
58 i_need ALLOWED,BYTE
59 i_need FSeek_drive,BYTE ; DOS 3.4
60 i_need FSeek_firclus,WORD ; DOS 3.4
61 i_need FSeek_logclus,WORD ; DOS 3.4
62 i_need FSeek_logsave,WORD ; DOS 3.4
63 i_need FastSeekFlg,BYTE ; DOS 3.4
64 i_need XA_condition,BYTE ; DOS 3.4
65 i_need HIGH_SECTOR,WORD ; DOS 3.4
66 i_need DISK_FULL,BYTE ; DOS 3.4
67 i_need Temp_VAR2,WORD ; DOS 3.4
68
69
70
71Break <FNDCLUS -- Skip over allocation units>
72
73; Inputs:
74; CX = No. of clusters to skip
75; ES:BP = Base of drive parameters
76; [THISSFT] point to SFT
77; Outputs:
78; BX = Last cluster skipped to
79; CX = No. of clusters remaining (0 unless EOF)
80; DX = Position of last cluster
81; Carry set if error (currently user FAILed to I 24)
82; DI destroyed. No other registers affected.
83
84 procedure FNDCLUS,NEAR
85 DOSAssume CS,<DS>,"FndClus"
86 ASSUME ES:NOTHING
87
88 Assert ISDPB,<ES,BP>,"FndCLus"
89;; 10/31/86 FastSeek
90 PUSH ES
91 LES DI,[THISSFT]
92 Assert ISSFT,<ES,DI>,"FndClus"
93 MOV [FSeek_logclus],CX ; presume CX is the position ;AN000;
94 MOV BX,ES:[DI.sf_lstclus]
95 MOV DX,ES:[DI.sf_cluspos]
96;; 10/31/86 FastSeek
97 OR BX,BX
98 JNZ YCLUS
99 JMP NOCLUS
100YCLUS:
101 SUB CX,DX
102 JNB FINDIT
103 ADD CX,DX
104 XOR DX,DX
105 MOV BX,ES:[DI.sf_firclus]
106FINDIT:
107;; 10/31/86 FastSeek
108
109
110 POP ES
111 OR CX,CX
112 JNZ skpclp
113 JMP RET10
114
115entry SKPCLP
116 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
117 JZ do_norm ; no ;AN000;
118 TEST [FastSeekflg],FS_begin ; do fastseek ;AN000;
119 JZ do_norm ; no ;AN000;
120 TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000;
121 JNZ do_norm ; yes ;AN000;
122 MOV [Temp_Var2],BX ; save physical cluster ;AN000;
123 ; PTR P005079
124SKPCLP2:
125 invoke FastSeek_Lookup ; ask for next cluster # ;AN000;
126 JNC clusfound ; yes, we got it ;AN000;
127 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
128 JNZ par_found ; yes, ;AN000;
129 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
130 JMP SHORT do_norm ;AN000;
131 ;AN000;
132par_found:
133 CALL FS_Trunc_EOF ; check EOF and truncate ;AN000;
134 JNC SKPCLP2 ; redo lookup ;AN000;
135noteof:
136 OR [FastSeekflg],FS_insert ; no, start to insert ;AN000;
137 CMP DX,[FSeek_logsave] ; is current better than new? ;AN000;
138 JBE OnCache ; no, let's use new ;AN000;
139 MOV [FSeek_logclus],DX ; use current ;AN000;
140 MOV BX,[Temp_Var2] ; retore pysical cluster ;AN000;
141 MOV DI,BX ; insert cureent cluster ;AN000;
142 invoke FastSeek_Insert ; insert cluster # to ;AN000;
143 INC [FSeek_logclus] ; get next inserted position ;AN000;
144 JMP SHORT do_norm
145OnCache:
146 MOV CX,[FSeek_logclus] ; get the number of clusters ;AN000;
147 SUB CX,[FSeek_logsave] ; we need to skip ;AN000;
148 MOV DX,[FSeek_logsave] ; cluster position ;AN000;
149dodo:
150 INC [FSeek_logsave] ; get next inserted position ;AN000;
151 PUSH [FSeek_logsave] ; logclus=logsave ;AN000;
152 POP [FSeek_logclus] ;AN000;
153
154do_norm:
155
156 invoke UNPACK
157 retc
158
159 invoke FastSeek_Insert ; insert cluster # to ;AN000;
160cluss: ;AN000;
161 PUSH BX ; FastSeek ;AN000;
162 MOV BX,DI
163 Invoke IsEOF
164 POP BX
165 JAE RET10
166 XCHG BX,DI
167 INC DX
168 INC [FSeek_logclus] ; increment for next inserted ;AN000;
169 LOOP SKPCLPX
170 JMP short RET10
171SKPCLPX:
172 JMP SKPCLP
173RET10: ;AN000;
174 AND [FastSeekflg],FS_no_insert ; clear insert mode
175 CLC
176 return
177NOCLUS:
178 POP ES
179 INC CX
180 DEC DX
181 CLC
182 return
183clusfound:
184 MOV DX,[FSeek_logclus] ; get cluster position ;AN000;
185 MOV BX,[FSeek_logsave] ; bx=previous cluster # PTM ;AN000;
186 DEC DX ;AN000;
187 MOV CX,1 ; we found it ;AN000;
188 JMP cluss ;AN000;
189
190EndProc FNDCLUS
191
192Break <BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER>
193
194; Inputs:
195; AH = priority of buffer
196; AL = 0 if buffer must be read, 1 if no pre-read needed
197; ES:BP = Base of drive parameters
198; [CLUSNUM] = Physical cluster number
199; [SECCLUSPOS] = Sector position of transfer within cluster
200; [BYTCNT1] = Size of transfer
201; Function:
202; Insure specified sector is in buffer, flushing buffer before
203; read if necessary.
204; Outputs:
205; ES:DI = Pointer to buffer
206; SI = Pointer to transfer address
207; CX = Number of bytes
208; [NEXTADD] updated
209; [TRANS] set to indicate a transfer will occur
210; Carry set if error (user FAILed to I 24)
211
212 procedure BUFSEC,NEAR
213 DOSAssume CS,<DS>,"BufSec"
214 ASSUME ES:NOTHING
215
216 Assert ISDPB,<ES,BP>,"BufSec"
217 MOV DX,[CLUSNUM]
218 MOV BL,[SECCLUSPOS]
219 MOV [ALLOWED],allowed_FAIL + allowed_RETRY + allowed_IGNORE
220 CALL FIGREC
221 invoke GETBUFFR
222 retc
223 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
224 MOV SI,[NEXTADD]
225 MOV DI,SI
226 MOV CX,[BYTCNT1]
227 ADD DI,CX
228 MOV [NEXTADD],DI
229 LES DI,[CURBUF]
230 Assert ISBUF,<ES,DI>,"BufSec"
231 OR ES:[DI.buf_flags],buf_isDATA
232 LEA DI,[DI].BUFINSIZ ; Point to buffer
233 ADD DI,[BYTSECPOS]
234 CLC
235 return
236EndProc BUFSEC
237
238Break <BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE>
239
240; Do a partial sector read via one of the system buffers
241; ES:BP Points to DPB
242; Carry set if error (currently user FAILed to I 24)
243
244 procedure BUFRD,NEAR
245 DOSAssume CS,<DS>,"BufRd"
246 ASSUME ES:NOTHING
247
248 Assert ISDPB,<ES,BP>,"BufRd"
249 PUSH ES
250 MOV AX,0
251 CALL BUFSEC
252 JNC BUF_OK
253BUF_IO_FAIL:
254 POP ES
255 JMP SHORT RBUFPLACED
256
257BUF_OK:
258 MOV BX,ES
259 MOV ES,[DMAADD+2]
260 MOV DS,BX
261ASSUME DS:NOTHING
262 XCHG DI,SI
263 SHR CX,1
264 JNC EVENRD
265 MOVSB
266EVENRD:
267 REP MOVSW
268 POP ES
269 LDS DI,[CURBUF]
270 Assert ISBUF,<DS,DI>,"BufRD/EvenRD"
271 LEA BX,[DI.BufInSiz]
272 SUB SI,BX ; Position in buffer
273 invoke PLACEBUF
274 Assert ISDPB,<ES,BP>,"BufRD/EvenRD"
275 CMP SI,ES:[BP.dpb_sector_size] ; Read Last byte?
276 JB RBUFPLACEDC ; No, leave buf where it is
277 invoke PLACEHEAD ; Make it prime candidate for chucking
278 ; even though it is MRU.
279RBUFPLACEDC:
280 CLC
281RBUFPLACED:
282 PUSH SS
283 POP DS
284 return
285EndProc BUFRD
286
287; Do a partial sector write via one of the system buffers
288; ES:BP Points to DPB
289; Carry set if error (currently user FAILed to I 24)
290
291 procedure BUFWRT,NEAR
292 DOSAssume CS,<DS>,"BufWrt"
293 ASSUME ES:NOTHING
294
295 Assert ISDPB,<ES,BP>,"BufWrt"
296 MOV AX,WORD PTR [SECPOS]
297 ADD AX,1 ; Set for next sector
298 MOV WORD PTR [SECPOS],AX ;F.C. >32mb ;AN000;
299 ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000;
300 MOV AX,WORD PTR [SECPOS+2] ;F.C. >32mb ;AN000;
301 CMP AX,WORD PTR [VALSEC+2] ;F.C. >32mb ;AN000;
302 MOV AL,1 ;F.C. >32mb ;AN000;
303 JA NOREAD ;F.C. >32mb ;AN000;
304 JB doread ;F.C. >32mb ;AN000;
305 MOV AX,WORD PTR [SECPOS] ;F.C. >32mb ;AN000;
306 CMP AX,WORD PTR [VALSEC] ; Has sector been written before?
307 MOV AL,1
308 JA NOREAD ; Skip preread if SECPOS>VALSEC
309doread:
310 XOR AL,AL
311NOREAD:
312 PUSH ES
313 CALL BUFSEC
314 JC BUF_IO_FAIL
315 MOV DS,[DMAADD+2]
316ASSUME DS:NOTHING
317 SHR CX,1
318 JNC EVENWRT
319 MOVSB
320EVENWRT:
321 REP MOVSW
322 POP ES
323 LDS BX,[CURBUF]
324 Assert ISBUF,<DS,BX>,"BufWrt/EvenWrt"
325
326 TEST [BX.buf_flags],buf_dirty ;LB. if already dirty ;AN000;
327 JNZ yesdirty ;LB. don't increment dirty count ;AN000;
328 invoke INC_DIRTY_COUNT ;LB. ;AN000;
329 OR [BX.buf_flags],buf_dirty
330yesdirty:
331 LEA SI,[BX.BufInSiz]
332 SUB DI,SI ; Position in buffer
333 MOV SI,DI
334 MOV DI,BX
335 invoke PLACEBUF
336 Assert ISDPB,<ES,BP>,"BufWrt/EvenWrt"
337 CMP SI,ES:[BP.dpb_sector_size] ; Written last byte?
338 JB WBUFPLACED ; No, leave buf where it is
339 invoke PLACEHEAD ; Make it prime candidate for chucking
340 ; even though it is MRU.
341WBUFPLACED:
342 CLC
343 PUSH SS
344 POP DS
345 return
346EndProc BUFWRT
347
348Break <NEXTSEC -- Compute next sector to read or write>
349
350; Compute the next sector to read or write
351; ES:BP Points to DPB
352
353 procedure NEXTSEC,NEAR
354 DOSAssume CS,<DS>,"NextSec"
355 ASSUME ES:NOTHING
356
357 Assert ISDPB,<ES,BP>,"NextSec"
358 TEST BYTE PTR [TRANS],-1
359 JZ CLRET
360 MOV AL,[SECCLUSPOS]
361 INC AL
362 CMP AL,ES:[BP.dpb_cluster_mask]
363 JBE SAVPOS
364 MOV BX,[CLUSNUM]
365 Invoke IsEOF
366 JAE NONEXT
367;; 11/5/86 FastSeek
368 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
369 JZ do_norm2 ; no ;AN000;
370 PUSH [LASTPOS] ; save logical cluster # ;AN000;
371 POP [FSeek_logclus] ;AN000;
372 INC [FSeek_logclus] ; get next cluster ;AN000;
373 ;AN000;
374 TEST [FastSeekflg],FS_begin ; from R/W ;AN000;
375 JZ do_norm2 ; no ;AN000;
376look2: ;AN000;
377 invoke FastSeek_Lookup ; call lookup ;AN000;
378 JNC clusgot ; found one ;AN000;
379
380 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
381 JNZ parfound2 ; yes, ;AN000;
382 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
383 JMP SHORT do_norm2 ;AN000;
384parfound2:
385 CALL FS_TRUNC_EOF ; check EOF ;AN000;
386 MOV BX,[CLUSNUM] ; don't need partially found cluster
387 OR [FastSeekflg],FS_insert ; prepared for cluster insertion ;AN000;
388 ; use the old bx ;AN000;
389 ;AN000;
390do_norm2:
391 invoke UNPACK
392 JC NONEXT
393 invoke FastSeek_Insert ; call insert ;AN000;
394 AND [FastSeekflg],FS_no_insert ; clear insert flag ;AN000;
395 ;AN000;
396clusgot:
397;; 11/5/86 FastSeek
398 MOV [CLUSNUM],DI
399 INC [LASTPOS]
400 MOV AL,0
401SAVPOS:
402 MOV [SECCLUSPOS],AL
403CLRET:
404 CLC
405 return
406NONEXT:
407 STC
408 return
409EndProc NEXTSEC
410
411Break <OPTIMIZE -- DO A USER DISK REQUEST WELL>
412
413; Inputs:
414; BX = Physical cluster
415; CX = No. of records
416; DL = sector within cluster
417; ES:BP = Base of drives parameters
418; [NEXTADD] = transfer address
419; Outputs:
420; AX = No. of records remaining
421; BX = Transfer address
422; CX = No. or records to be transferred
423; DX = Physical sector address (LOW)
424; [HIGH_SECTOR] = Physical sector address (HIGH)
425; DI = Next cluster
426; [CLUSNUM] = Last cluster accessed
427; [NEXTADD] updated
428; Carry set if error (currently user FAILed to I 24)
429; ES:BP unchanged. Note that segment of transfer not set.
430
431 procedure OPTIMIZE,NEAR
432 DOSAssume CS,<DS>,"Optimize"
433 ASSUME ES:NOTHING
434
435 Assert ISDPB,<ES,BP>,"Optimize"
436 PUSH DX
437 PUSH BX
438 MOV AL,ES:[BP.dpb_cluster_mask]
439 INC AL ; Number of sectors per cluster
440 MOV AH,AL
441 SUB AL,DL ; AL = Number of sectors left in first cluster
442 MOV DX,CX
443 MOV CX,0
444;;; 11/5/86 FastSeek
445 PUSH [LASTPOS] ; save logical cluster # ;AN000;
446 POP [FSeek_logclus] ;AN000;
447 INC [FSeek_logclus] ; get next cluster ;AN000;
448 ;AN000;
449OPTCLUS:
450; AL has number of sectors available in current cluster
451; AH has number of sectors available in next cluster
452; BX has current physical cluster
453; CX has number of sequential sectors found so far
454; DX has number of sectors left to transfer
455; ES:BP Points to DPB
456; ES:SI has FAT pointer
457
458 TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000;
459 JZ do_norm3 ; no ;AN000;
460 TEST [FastSeekflg],FS_begin ; from R/W ;AN000;
461 JZ do_norm3 ; no ;AN000;
462 TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000;
463 JNZ do_norm3 ; yes ;AN000;
464 invoke FastSeek_Lookup ; call lookup ;AN000;
465 JNC clusgot2 ; found one ;AN000;
466
467 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
468 JNZ par_found3 ; yes, ;AN000;
469 AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000;
470 JMP SHORT do_norm3 ;AN000;
471par_found3:
472 PUSH BX
473 CALL FS_TRUNC_EOF ; file entry not existing ;AN000;
474 POP BX ;AN000;
475 OR [FastSeekflg],FS_insert ; prepare for insertion ;AN000;
476 ; use old bx ;AN000;
477do_norm3:
478 invoke UNPACK
479 JC OP_ERR
480clusgot2:
481 invoke FastSeek_Insert ; call insert ;AN000;
482 INC [FSeek_logclus] ; insert to next position ;AN000;
483;;; 11/5/86 FastSeek ;AN000;
484 ADD CL,AL
485 ADC CH,0
486 CMP CX,DX
487 JAE BLKDON
488 MOV AL,AH
489 INC BX
490 CMP DI,BX
491 JZ OPTCLUS
492 DEC BX
493FINCLUS:
494 MOV [CLUSNUM],BX ; Last cluster accessed
495 SUB DX,CX ; Number of sectors still needed
496 PUSH DX
497 MOV AX,CX
498 MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size
499 MOV SI,[NEXTADD]
500 ADD AX,SI ; Adjust by size of transfer
501 MOV [NEXTADD],AX
502 POP AX ; Number of sectors still needed
503 POP DX ; Starting cluster
504 SUB BX,DX ; Number of new clusters accessed
505 ADD [LASTPOS],BX
506 POP BX ; BL = sector postion within cluster
507 invoke FIGREC
508 MOV BX,SI
509 AND [FastSeekflg],FS_no_insert ; clear insert flag
510 CLC
511 return
512
513OP_ERR:
514 ADD SP,4
515 AND [FastSeekflg],FS_no_insert ; clear insert flag
516 STC
517 return
518
519BLKDON:
520 SUB CX,DX ; Number of sectors in cluster we don't want
521 SUB AH,CL ; Number of sectors in cluster we accepted
522 DEC AH ; Adjust to mean position within cluster
523 MOV [SECCLUSPOS],AH
524 MOV CX,DX ; Anyway, make the total equal to the request
525 JMP SHORT FINCLUS
526EndProc OPTIMIZE
527
528Break <FIGREC -- Figure sector in allocation unit>
529
530; Inputs:
531; DX = Physical cluster number
532; BL = Sector postion within cluster
533; ES:BP = Base of drive parameters
534; Outputs:
535; DX = physical sector number (LOW)
536; [HIGH_SECTOR] Physical sector address (HIGH)
537; No other registers affected.
538
539 procedure FIGREC,NEAR
540ASSUME DS:NOTHING,ES:NOTHING
541
542 Assert ISDPB,<ES,BP>,"FigRec"
543 PUSH CX
544 MOV CL,ES:[BP.dpb_cluster_shift]
545 DEC DX
546 DEC DX
547 MOV [HIGH_SECTOR],0 ;F.C. >32mb
548 OR CL,CL ;F.C. >32mb
549 JZ noshift ;F.C. >32mb
550 XOR CH,CH ;F.C. >32mb
551rotleft: ;F.C. >32mb
552 CLC ;F.C. >32mb
553 RCL DX,1 ;F.C. >32mb
554 RCL [HIGH_SECTOR],1 ;F.C. >32mb
555 LOOP rotleft ;F.C. >32mb
556noshift:
557
558; SHL DX,CL
559 OR DL,BL
560 ADD DX,ES:[BP.dpb_first_sector]
561 ADC [HIGH_SECTOR],0 ;F.C. >32mb
562 POP CX
563 return
564EndProc FIGREC
565
566Break <ALLOCATE -- Assign disk space>
567
568;*** ALLOCATE - Allocate Disk Space
569;
570; ALLOCATE is called to allocate disk clusters. The new clusters are
571; FAT-chained onto the end of the existing file.
572;
573; The DPB contains the cluster # of the last free cluster allocated
574; (dpb_next_free). We start at this cluster and scan towards higher
575; numbered clusters, looking for the necessary free blocks.
576;
577; Once again, fancy terminology gets in the way of corrct coding. When
578; using next_free, start scanning AT THAT POINT and not the one following it.
579; This fixes the boundary condition bug when only free = next_free = 2.
580;
581; If we get to the end of the disk without satisfaction:
582;
583; if (dpb_next_free == 2) then we've scanned the whole disk.
584; return (insufficient_disk_space)
585; ELSE
586; dpb_next_free = 2; start scan over from the beginning.
587;
588; Note that there is no multitasking interlock. There is no race when
589; examining the entrys in an in-core FAT block since there will be no
590; context switch. When UNPACK context switches while waiting for a FAT read
591; we are done with any in-core FAT blocks, so again there is no race. The
592; only special concern is that V2 and V3 MSDOS left the last allocated
593; cluster as "00"; marking it EOF only when the entire alloc request was
594; satisfied. We can't allow another activation to think this cluster is
595; free, so we give it a special temporary mark to show that it is, indeed,
596; allocated.
597;
598; Note that when we run out of space this algorithem will scan from
599; dpb_next_free to the end, then scan from cluster 2 through the end,
600; redundantly scanning the later part of the disk. This only happens when
601; we run out of space, so sue me.
602;
603;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
604; C A V E A T P A T T E R S O N ;
605; ;
606; The use of FATBYT and RESTFATBYT is somewhat mysterious. Here is the
607; explanation:
608;
609; In the NUL file case (sf_firclus currently 0) ALLOCATE is called with
610; entry BX = 0. What needs to be done in this case is to stuff the cluster
611; number of the first cluster allocated in sf_firclus when the ALLOCATE is
612; complete. THIS VALUE IS SAVED TEMPORARILY IN CLUSTER 0, HENCE THE CURRENT
613; VALUE IN CLUSTER 0 MUST BE SAVED AND RESTORED. This is a side effect of
614; the fact that PACK and UNPACK don't treat requests for clusters 0 and 1 as
615; errors. This "stuff" is done by the call to PACK which is right before
616; the
617; LOOP findfre ; alloc more if needed
618; instruction when the first cluster is allocated to the nul file. The
619; value is recalled from cluster 0 and stored at sf_firclus at ads4:
620;
621; This method is obviously useless (because it is non-reentrant) for
622; multitasking, and will have to be changed. Storing the required value on
623; the stack is recommended. Setting sf_firclus at the PACK of cluster 0
624; (instead of actually doing the PACK) is BAD because it doesn't handle
625; problems with INT 24 well.
626;
627; C A V E A T P A T T E R S O N ;
628;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
629; ;
630; ENTRY BX = Last cluster of file (0 if null file)
631; CX = No. of clusters to allocate
632; ES:BP = Base of drive parameters
633; [THISSFT] = Points to SFT
634;
635; EXIT 'C' set if insufficient space
636; [FAILERR] can be tested to see the reason for failure
637; CX = max. no. of clusters that could be added to file
638; 'C' clear if space allocated
639; BX = First cluster allocated
640; FAT is fully updated
641; sf_FIRCLUS field of SFT set if file was null
642;
643; USES ALL but SI, BP
644
645 PROCEDURE ALLOCATE,NEAR
646
647 DOSAssume CS,<DS>,"Allocate"
648 ASSUME ES:NOTHING
649
650 Assert ISDPB,<ES,BP>,"Allocate"
651 PUSH BX ; save (bx)
652 XOR BX,BX
653 invoke UNPACK
654 MOV [FATBYT],DI ; save correct cluster 0 value
655 POP BX
656 retc ; abort if error [INTERR?]
657
658 PUSH CX
659 PUSH BX
660
661 MOV DX,BX
662 Assert ISDPB,<ES,BP>,"Allocate/Unpack"
663 mov bx,es:[bp.dpb_next_free]
664 cmp bx,2
665 ja findfre
666
667; couldn't find enough free space beyond dpb_next_free, or dpb_next_free is
668; <2 or >dpb_max_clus. Reset it and restart the scan
669
670ads1:
671 Assert ISDPB,<ES,BP>,"Alloc/ads1"
672 mov es:[bp.dpb_next_free],2
673 mov bx,1 ; Counter next instruction so first
674 ; cluster examined is 2
675
676; Scanning both forwards and backwards for a free cluster
677;
678; (BX) = forwards scan pointer
679; (CX) = clusters remaining to be allocated
680; (DX) = current last cluster in file
681; (TOS) = last cluster of file
682
683FINDFRE:
684 INC BX
685 Assert ISDPB,<ES,BP>,"Alloc/findfre"
686 CMP BX,ES:[BP.dpb_max_cluster]
687 JBE aupk
688 jmp ads7 ; at end of disk
689aupk:
690 invoke UNPACK ; check out this cluster
691 jc ads4 ; FAT error [INTERR?]
692 jnz findfre ; not free, keep on truckin
693
694; Have found a free cluster. Chain it to the file
695;
696; (BX) = found free cluster #
697; (DX) = current last cluster in file
698
699 mov es:[bp.dpb_next_free],bx ; next time start search here
700 xchg ax,dx ; save (dx) in ax
701 mov dx,1 ; mark this free guy as "1"
702 invoke PACK ; set special "temporary" mark
703 jc ads4 ; FAT error [INTERR?]
704 CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid?
705 JZ NO_ALLOC ; No
706 DEC ES:[BP.dpb_free_cnt] ; Reduce free count by 1
707NO_ALLOC:
708 xchg ax,dx ; (dx) = current last cluster in file
709 XCHG BX,DX
710 MOV AX,DX
711 invoke PACK ; link free cluster onto file
712 ; CAVEAT.. On Nul file, first pass stuffs
713 ; cluster 0 with FIRCLUS value.
714 jc ads4 ; FAT error [INTERR?]
715 xchg BX,AX ; (BX) = last one we looked at
716 mov dx,bx ; (dx) = current end of file
717 LOOP findfre ; alloc more if needed
718
719; We've successfully extended the file. Clean up and exit
720;
721; (BX) = last cluster in file
722
723 MOV DX,0FFFFH
724 invoke PACK ; mark last cluster EOF
725
726; Note that FAT errors jump here to clean the stack and exit. this saves us
727; 2 whole bytes. Hope its worth it...
728;
729; 'C' set iff error
730; calling (BX) and (CX) pushed on stack
731
732ads4: POP BX
733 POP CX ; Don't need this stuff since we're successful
734 retc
735 invoke UNPACK ; Get first cluster allocated for return
736 ; CAVEAT... In nul file case, UNPACKs cluster 0.
737 retc
738 invoke RESTFATBYT ; Restore correct cluster 0 value
739 retc
740 XCHG BX,DI ; (DI) = last cluster in file upon our entry
741 OR DI,DI ; clear 'C'
742 retnz ; we were extending an existing file
743
744; We were doing the first allocation for a new file. Update the SFT cluster
745; info
746;; Extended Attributes
747; TEST [XA_condition],XA_No_SFT ;FT. don't update SFT when from ;AN000;
748; JZ dofastk ;FT. GetSet_XA ;AN000;
749; AND [XA_condition],not XA_No_SFT ;FT. clear the bit ;AN000;
750; CLC ;FT. ;AN000;
751; ret ;FT. ;AN000;
752;; 11/6/86 FastSeek
753dofastk:
754 PUSH DX
755 MOV DL,ES:[BP.dpb_drive] ; get drive #
756
757 PUSH ES
758 LES DI,[THISSFT]
759 Assert ISSFT,<ES,DI>,"Allocate/ads4"
760 MOV ES:[DI.sf_firclus],BX
761 MOV ES:[DI.sf_lstclus],BX
762
763 TEST [FastSeekflg],Fast_yes ; fastseek installed
764 JZ do_norm5 ; no
765 TEST [FastSeekflg],FS_begin ; do fastseek
766 JZ do_norm5 ; no
767 PUSH CX
768 MOV CX,BX ; set up firclus #
769 MOV [FSeek_firclus],BX ; update firclus varible
770 invoke FastSeek_Open ; create this file entry
771 POP CX
772do_norm5:
773 POP ES
774;; 11/6/86 FastSeek
775 POP DX
776 return
777
778
779;** we're at the end of the disk, and not satisfied. See if we've scanned ALL
780; of the disk...
781
782ads7: cmp es:[bp.dpb_next_free],2
783if not debug
784 jz tmplab2 ;
785 jmp ads1 ; start scan from front of disk
786tmplab2:
787else
788 jz tmplab
789 jmp ads1
790tmplab:
791endif
792
793; Sorry, we've gone over the whole disk, with insufficient luck. Lets give
794; the space back to the free list and tell the caller how much he could have
795; had. We have to make sure we remove the "special mark" we put on the last
796; cluster we were able to allocate, so it doesn't become orphaned.
797;
798; (CX) = clusters remaining to be allocated
799; (TOS) = last cluster of file (before call to ALLOCATE)
800; (TOS+1) = # of clusters wanted to allocate
801
802
803 POP BX ; (BX) = last cluster of file
804 MOV DX,0FFFFH
805 invoke RELBLKS ; give back any clusters just alloced
806 POP AX ; No. of clusters requested
807 ; Don't "retc". We are setting Carry anyway,
808 ; Alloc failed, so proceed with return CX
809 ; setup.
810 SUB AX,CX ; AX=No. of clusters allocated
811 invoke RESTFATBYT ; Don't "retc". We are setting Carry anyway,
812 ; Alloc failed.
813; fmt <>,<>,<"$p: disk full in allocate\n">
814 MOV [DISK_FULL],1 ;MS. indicating disk full
815 STC
816 return
817
818EndProc ALLOCATE
819
820; SEE ALLOCATE CAVEAT
821; Carry set if error (currently user FAILed to I 24)
822
823 procedure RESTFATBYT,NEAR
824 DOSAssume CS,<DS>,"RestFATByt"
825 ASSUME ES:NOTHING
826
827 PUSH BX
828 PUSH DX
829 PUSH DI
830 XOR BX,BX
831 MOV DX,[FATBYT]
832 invoke PACK
833 POP DI
834 POP DX
835 POP BX
836 return
837EndProc RESTFATBYT
838
839Break <RELEASE -- DEASSIGN DISK SPACE>
840
841; Inputs:
842; BX = Cluster in file
843; ES:BP = Base of drive parameters
844; Function:
845; Frees cluster chain starting with [BX]
846; Carry set if error (currently user FAILed to I 24)
847; AX,BX,DX,DI all destroyed. Other registers unchanged.
848
849 procedure RELEASE,NEAR
850 DOSAssume CS,<DS>,"Release"
851 ASSUME ES:NOTHING
852
853 XOR DX,DX
854entry RELBLKS
855 DOSAssume CS,<DS>,"RelBlks"
856 Assert ISDPB,<ES,BP>,"RelBlks"
857
858; Enter here with DX=0FFFFH to put an end-of-file mark in the first cluster
859; and free the rest in the chain.
860
861 invoke UNPACK
862 retc
863 retz
864 MOV AX,DI
865 PUSH DX
866 invoke PACK
867 POP DX
868 retc
869 OR DX,DX
870 JNZ NO_DEALLOC ; Was putting EOF mark
871 CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid?
872 JZ NO_DEALLOC ; No
873 INC ES:[BP.dpb_free_cnt] ; Increase free count by 1
874NO_DEALLOC:
875 MOV BX,AX
876 dec ax ; check for "1"
877 retz ; is last cluster of incomplete chain
878 Invoke IsEOF
879 JB RELEASE ; Carry clear if JMP not taken
880ret12: return
881EndProc RELEASE
882
883Break <GETEOF -- Find the end of a file>
884
885; Inputs:
886; ES:BP Points to DPB
887; BX = Cluster in a file
888; DS = CS
889; Outputs:
890; BX = Last cluster in the file
891; Carry set if error (currently user FAILed to I 24)
892; DI destroyed. No other registers affected.
893
894 procedure GETEOF,NEAR
895 DOSAssume CS,<DS>,"GetEOF"
896 ASSUME ES:NOTHING
897
898 Assert ISDPB,<ES,BP>,"GetEof"
899 invoke UNPACK
900 retc
901 PUSH BX
902 MOV BX,DI
903 Invoke IsEOF
904 POP BX
905 JAE RET12 ; Carry clear if jmp
906 MOV BX,DI
907 JMP GETEOF
908EndProc GETEOF
909
910Break <FS_TRUNC_EOF - truncate EOF for Fastseek>
911
912; Inputs:
913; ES:BP Points to DPB
914; BX = Cluster in a file
915; Functions: if BX=EOF then truncate it from Fastseek Cache
916; Outputs:
917; carry set: not EOF
918; carry clear: EOF and do truncate
919
920 procedure FS_TRUNC_EOF,NEAR
921 ASSUME ES:NOTHING,DS:NOTHING
922
923 MOV BX,DI ; get beginning physical# ;AN000;
924 invoke IsEOF ; is EOF ;AN000;
925 JB noteof2 ; no ;AN000;
926 PUSH [FSeek_logclus] ; ;AN000;
927 PUSH [FSeek_logsave] ; logclus=logsave ;AN000;
928 POP [FSeek_logclus] ; delete EOF ;AN000;
929 invoke FastSeek_Truncate ; ;AN000;
930 POP [FSeek_logclus] ; redo the look up ;AN000;
931 CLC ;AN000;
932noteof2: ;AN000;
933 return ;AN000;
934EndProc FS_TRUNC_EOF ;AN000;
935
936CODE ENDS
937 END
938 \ No newline at end of file