]> wirehaze git hosting - MS-DOS.git/blob - v2.0/source/ROM.ASM

wirehaze git hosting

Merge pull request #151 from jamespack/spelling-fix
[MS-DOS.git] / v2.0 / source / ROM.ASM
1 ;
2 ; Disk utilities of MSDOS
3 ;
4
5 INCLUDE DOSSEG.ASM
6
7 CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10 .XLIST
11 .xcref
12 INCLUDE DOSSYM.ASM
13 INCLUDE DEVSYM.ASM
14 .cref
15 .list
16
17 TITLE ROM - miscellaneous routines
18 NAME ROM
19
20 i_need CLUSNUM,WORD
21 i_need NEXTADD,WORD
22 i_need LASTPOS,WORD
23 i_need SECCLUSPOS,BYTE
24 i_need FATBYT,WORD
25 i_need RECPOS,4
26 i_need THISFCB,DWORD
27 i_need TRANS,BYTE
28 i_need BYTCNT1,WORD
29 i_need CURBUF,DWORD
30 i_need BYTSECPOS,WORD
31 i_need DMAADD,WORD
32 i_need SECPOS,WORD
33 i_need VALSEC,WORD
34
35 procedure GET_random_record,NEAR
36 entry GETRRPOS1
37 MOV CX,1
38 entry GetRRPos
39 MOV DI,DX
40 CMP BYTE PTR [DI],-1
41 JNZ NORMFCB1
42 ADD DI,7
43 NORMFCB1:
44 MOV AX,WORD PTR [DI.fcb_RR]
45 MOV DX,WORD PTR [DI.fcb_RR+2]
46 return
47 GET_random_record ENDP
48
49 SUBTTL FNDCLUS -- Skip over allocation units
50 PAGE
51 procedure FNDCLUS,NEAR
52 ASSUME DS:DOSGROUP,ES:NOTHING
53
54 ; Inputs:
55 ; CX = No. of clusters to skip
56 ; ES:BP = Base of drive parameters
57 ; [THISFCB] point to FCB
58 ; Outputs:
59 ; BX = Last cluster skipped to
60 ; CX = No. of clusters remaining (0 unless EOF)
61 ; DX = Position of last cluster
62 ; DI destroyed. No other registers affected.
63
64 PUSH ES
65 LES DI,[THISFCB]
66 MOV BX,ES:[DI.fcb_LSTCLUS] ; fcb_lstclus is packed with dir clus
67 AND BX,0FFFh ; get rid of dir nibble
68 MOV DX,ES:[DI.fcb_CLUSPOS]
69 OR BX,BX
70 JZ NOCLUS
71 SUB CX,DX
72 JNB FINDIT
73 ADD CX,DX
74 XOR DX,DX
75 MOV BX,ES:[DI.fcb_FIRCLUS]
76 FINDIT:
77 POP ES
78 JCXZ RET10
79 entry SKPCLP
80 invoke UNPACK
81 CMP DI,0FF8H
82 JAE RET10
83 XCHG BX,DI
84 INC DX
85 LOOP SKPCLP
86 RET10: return
87
88 NOCLUS:
89 POP ES
90 INC CX
91 DEC DX
92 return
93 FNDCLUS ENDP
94
95 SUBTTL BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER
96 PAGE
97 procedure BUFSEC,NEAR
98 ASSUME DS:DOSGROUP,ES:NOTHING
99
100 ; Inputs:
101 ; AH = priority of buffer
102 ; AL = 0 if buffer must be read, 1 if no pre-read needed
103 ; ES:BP = Base of drive parameters
104 ; [CLUSNUM] = Physical cluster number
105 ; [SECCLUSPOS] = Sector position of transfer within cluster
106 ; [BYTCNT1] = Size of transfer
107 ; Function:
108 ; Insure specified sector is in buffer, flushing buffer before
109 ; read if necessary.
110 ; Outputs:
111 ; ES:DI = Pointer to buffer
112 ; SI = Pointer to transfer address
113 ; CX = Number of bytes
114 ; [NEXTADD] updated
115 ; [TRANS] set to indicate a transfer will occur
116
117 MOV DX,[CLUSNUM]
118 MOV BL,[SECCLUSPOS]
119 CALL FIGREC
120 invoke GETBUFFR
121 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
122 MOV SI,[NEXTADD]
123 MOV DI,SI
124 MOV CX,[BYTCNT1]
125 ADD DI,CX
126 MOV [NEXTADD],DI
127 LES DI,[CURBUF]
128 ADD DI,BUFINSIZ ; Point to buffer
129 ADD DI,[BYTSECPOS]
130 return
131 BUFSEC ENDP
132
133 SUBTTL BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE
134 PAGE
135 procedure BUFRD,NEAR
136 ASSUME DS:DOSGROUP,ES:NOTHING
137
138 ; Do a partial sector read via one of the system buffers
139 ; ES:BP Points to DPB
140
141 PUSH ES
142 MOV AX,LBRPRI SHL 8 ; Assume last byte read
143 CALL BUFSEC
144 MOV BX,ES
145 MOV ES,[DMAADD+2]
146 MOV DS,BX
147 ASSUME DS:NOTHING
148 XCHG DI,SI
149 SHR CX,1
150 JNC EVENRD
151 MOVSB
152 EVENRD:
153 REP MOVSW
154 POP ES
155 LDS DI,[CURBUF]
156 LEA BX,[DI.BufInSiz]
157 SUB SI,BX ; Position in buffer
158 invoke PLACEBUF
159 CMP SI,ES:[BP.dpb_sector_size]
160 JB RBUFPLACED
161 invoke PLACEHEAD
162 RBUFPLACED:
163 PUSH SS
164 POP DS
165 return
166 BUFRD ENDP
167
168 procedure BUFWRT,NEAR
169 ASSUME DS:DOSGROUP,ES:NOTHING
170
171 ; Do a partial sector write via one of the system buffers
172 ; ES:BP Points to DPB
173
174 MOV AX,[SECPOS]
175 INC AX ; Set for next sector
176 MOV [SECPOS],AX
177 CMP AX,[VALSEC] ; Has sector been written before?
178 MOV AL,1
179 JA NOREAD ; Skip preread if SECPOS>VALSEC
180 XOR AL,AL
181 NOREAD:
182 PUSH ES
183 CALL BUFSEC
184 MOV DS,[DMAADD+2]
185 ASSUME DS:NOTHING
186 SHR CX,1
187 JNC EVENWRT
188 MOVSB
189 EVENWRT:
190 REP MOVSW
191 POP ES
192 LDS BX,[CURBUF]
193 MOV BYTE PTR [BX.BUFDIRTY],1
194 LEA SI,[BX.BufInSiz]
195 SUB DI,SI ; Position in buffer
196 MOV SI,DI
197 MOV DI,BX
198 invoke PLACEBUF
199 CMP SI,ES:[BP.dpb_sector_size]
200 JB WBUFPLACED
201 invoke PLACEHEAD
202 WBUFPLACED:
203 PUSH SS
204 POP DS
205 return
206 BUFWRT ENDP
207
208 SUBTTL NEXTSEC -- Compute next sector to read or write
209 PAGE
210 procedure NEXTSEC,NEAR
211 ASSUME DS:DOSGROUP,ES:NOTHING
212
213 ; Compute the next sector to read or write
214 ; ES:BP Points to DPB
215
216 TEST BYTE PTR [TRANS],-1
217 JZ CLRET
218 MOV AL,[SECCLUSPOS]
219 INC AL
220 CMP AL,ES:[BP.dpb_cluster_mask]
221 JBE SAVPOS
222 MOV BX,[CLUSNUM]
223 CMP BX,0FF8H
224 JAE NONEXT
225 invoke UNPACK
226 MOV [CLUSNUM],DI
227 INC [LASTPOS]
228 MOV AL,0
229 SAVPOS:
230 MOV [SECCLUSPOS],AL
231 CLRET:
232 CLC
233 return
234 NONEXT:
235 STC
236 return
237 NEXTSEC ENDP
238
239 SUBTTL OPTIMIZE -- DO A USER DISK REQUEST WELL
240 PAGE
241 procedure OPTIMIZE,NEAR
242 ASSUME DS:DOSGROUP,ES:NOTHING
243
244 ; Inputs:
245 ; BX = Physical cluster
246 ; CX = No. of records
247 ; DL = sector within cluster
248 ; ES:BP = Base of drives parameters
249 ; [NEXTADD] = transfer address
250 ; Outputs:
251 ; AX = No. of records remaining
252 ; BX = Transfer address
253 ; CX = No. or records to be transferred
254 ; DX = Physical sector address
255 ; DI = Next cluster
256 ; [CLUSNUM] = Last cluster accessed
257 ; [NEXTADD] updated
258 ; ES:BP unchanged. Note that segment of transfer not set.
259
260 PUSH DX
261 PUSH BX
262 MOV AL,ES:[BP.dpb_cluster_mask]
263 INC AL ; Number of sectors per cluster
264 MOV AH,AL
265 SUB AL,DL ; AL = Number of sectors left in first cluster
266 MOV DX,CX
267 MOV CX,0
268 OPTCLUS:
269 ; AL has number of sectors available in current cluster
270 ; AH has number of sectors available in next cluster
271 ; BX has current physical cluster
272 ; CX has number of sequential sectors found so far
273 ; DX has number of sectors left to transfer
274 ; ES:BP Points to DPB
275 ; ES:SI has FAT pointer
276 invoke UNPACK
277 ADD CL,AL
278 ADC CH,0
279 CMP CX,DX
280 JAE BLKDON
281 MOV AL,AH
282 INC BX
283 CMP DI,BX
284 JZ OPTCLUS
285 DEC BX
286 FINCLUS:
287 MOV [CLUSNUM],BX ; Last cluster accessed
288 SUB DX,CX ; Number of sectors still needed
289 PUSH DX
290 MOV AX,CX
291 MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size
292 MOV SI,[NEXTADD]
293 ADD AX,SI ; Adjust by size of transfer
294 MOV [NEXTADD],AX
295 POP AX ; Number of sectors still needed
296 POP DX ; Starting cluster
297 SUB BX,DX ; Number of new clusters accessed
298 ADD [LASTPOS],BX
299 POP BX ; BL = sector postion within cluster
300 invoke FIGREC
301 MOV BX,SI
302 return
303 BLKDON:
304 SUB CX,DX ; Number of sectors in cluster we don't want
305 SUB AH,CL ; Number of sectors in cluster we accepted
306 DEC AH ; Adjust to mean position within cluster
307 MOV [SECCLUSPOS],AH
308 MOV CX,DX ; Anyway, make the total equal to the request
309 JMP SHORT FINCLUS
310 OPTIMIZE ENDP
311
312 SUBTTL FIGREC -- Figure sector in allocation unit
313 PAGE
314 procedure FIGREC,NEAR
315 ASSUME DS:NOTHING,ES:NOTHING
316
317 ; Inputs:
318 ; DX = Physical cluster number
319 ; BL = Sector postion within cluster
320 ; ES:BP = Base of drive parameters
321 ; Outputs:
322 ; DX = physical sector number
323 ; No other registers affected.
324
325 PUSH CX
326 MOV CL,ES:[BP.dpb_cluster_shift]
327 DEC DX
328 DEC DX
329 SHL DX,CL
330 OR DL,BL
331 ADD DX,ES:[BP.dpb_first_sector]
332 POP CX
333 return
334 FIGREC ENDP
335
336 SUBTTL GETREC -- Figure record in file from fcb
337 PAGE
338 procedure GETREC,NEAR
339 ASSUME DS:NOTHING,ES:NOTHING
340
341 ; Inputs:
342 ; DS:DX point to FCB
343 ; Outputs:
344 ; CX = 1
345 ; DX:AX = Record number determined by fcb_EXTENT and fcb_NR fields
346 ; DS:DI point to FCB
347 ; No other registers affected.
348
349 MOV DI,DX
350 CMP BYTE PTR [DI],-1 ; Check for extended FCB
351 JNZ NORMFCB2
352 ADD DI,7
353 NORMFCB2:
354 MOV CX,1
355 MOV AL,[DI.fcb_NR]
356 MOV DX,[DI.fcb_EXTENT]
357 SHL AL,1
358 SHR DX,1
359 RCR AL,1
360 MOV AH,DL
361 MOV DL,DH
362 MOV DH,0
363 return
364 GETREC ENDP
365
366 SUBTTL ALLOCATE -- Assign disk space
367 PAGE
368 procedure ALLOCATE,NEAR
369 ASSUME DS:DOSGROUP,ES:NOTHING
370
371 ; Inputs:
372 ; BX = Last cluster of file (0 if null file)
373 ; CX = No. of clusters to allocate
374 ; DX = Position of cluster BX
375 ; ES:BP = Base of drive parameters
376 ; [THISFCB] = Points to FCB
377 ; Outputs:
378 ; IF insufficient space
379 ; THEN
380 ; Carry set
381 ; CX = max. no. of records that could be added to file
382 ; ELSE
383 ; Carry clear
384 ; BX = First cluster allocated
385 ; FAT is fully updated including dirty bit
386 ; fcb_FIRCLUS field of FCB set if file was null
387 ; SI,BP unchanged. All other registers destroyed.
388
389 PUSH BX ; save the fat byte
390 XOR BX,BX
391 invoke UNPACK
392 MOV [FATBYT],DI
393 POP BX
394
395 PUSH DX
396 PUSH CX
397 PUSH BX
398 MOV AX,BX
399 CLUSALLOC:
400 MOV DX,BX
401 FINDFRE:
402 INC BX
403 CMP BX,ES:[BP.dpb_max_cluster]
404 JLE TRYOUT
405 CMP AX,1
406 JG TRYIN
407 POP BX
408 MOV DX,0FFFH
409 invoke RELBLKS
410 POP AX ; No. of clusters requested
411 SUB AX,CX ; AX=No. of clusters allocated
412 POP DX
413 invoke RESTFATBYT
414 INC DX ; Position of first cluster allocated
415 ADD AX,DX ; AX=max no. of cluster in file
416 MOV DL,ES:[BP.dpb_cluster_mask]
417 MOV DH,0
418 INC DX ; DX=records/cluster
419 MUL DX ; AX=max no. of records in file
420 MOV CX,AX
421 SUB CX,WORD PTR [RECPOS] ; CX=max no. of records that could be written
422 JA MAXREC
423 XOR CX,CX ; If CX was negative, zero it
424 MAXREC:
425 STC
426 return
427
428 TRYOUT:
429 invoke UNPACK
430 JZ HAVFRE
431 TRYIN:
432 DEC AX
433 JLE FINDFRE
434 XCHG AX,BX
435 invoke UNPACK
436 JZ HAVFRE
437 XCHG AX,BX
438 JMP SHORT FINDFRE
439 HAVFRE:
440 XCHG BX,DX
441 MOV AX,DX
442 invoke PACK
443 MOV BX,AX
444 LOOP CLUSALLOC
445 MOV DX,0FFFH
446 invoke PACK
447 POP BX
448 POP CX ; Don't need this stuff since we're successful
449 POP DX
450 invoke UNPACK
451 invoke RESTFATBYT
452 XCHG BX,DI
453 OR DI,DI
454 retnz
455 PUSH ES
456 LES DI,[THISFCB]
457 AND BX,0FFFh
458 MOV ES:[DI.fcb_FIRCLUS],BX
459 AND ES:[DI.fcb_LSTCLUS],0F000h ; clear out old lstclus
460 OR ES:[DI.fcb_LSTCLUS],BX ; or the new guy in...
461 POP ES
462 return
463 ALLOCATE ENDP
464
465 procedure RESTFATBYT,NEAR
466 ASSUME DS:DOSGROUP,ES:NOTHING
467
468 PUSH BX
469 PUSH DX
470 PUSH DI
471 XOR BX,BX
472 MOV DX,[FATBYT]
473 invoke PACK
474 POP DI
475 POP DX
476 POP BX
477 return
478 RESTFATBYT ENDP
479
480 SUBTTL RELEASE -- DEASSIGN DISK SPACE
481 PAGE
482 procedure RELEASE,NEAR
483 ASSUME DS:DOSGROUP,ES:NOTHING
484
485 ; Inputs:
486 ; BX = Cluster in file
487 ; ES:BP = Base of drive parameters
488 ; Function:
489 ; Frees cluster chain starting with [BX]
490 ; AX,BX,DX,DI all destroyed. Other registers unchanged.
491
492 XOR DX,DX
493 entry RELBLKS
494 ; Enter here with DX=0FFFH to put an end-of-file mark
495 ; in the first cluster and free the rest in the chain.
496 invoke UNPACK
497 retz
498 MOV AX,DI
499 invoke PACK
500 CMP AX,0FF8H
501 MOV BX,AX
502 JB RELEASE
503 RET12: return
504 RELEASE ENDP
505
506 SUBTTL GETEOF -- Find the end of a file
507 PAGE
508 procedure GETEOF,NEAR
509 ASSUME DS:DOSGROUP,ES:NOTHING
510
511 ; Inputs:
512 ; ES:BP Points to DPB
513 ; BX = Cluster in a file
514 ; DS = CS
515 ; Outputs:
516 ; BX = Last cluster in the file
517 ; DI destroyed. No other registers affected.
518
519 invoke UNPACK
520 CMP DI,0FF8H
521 JAE RET12
522 MOV BX,DI
523 JMP SHORT GETEOF
524 GETEOF ENDP
525
526 do_ext
527
528 CODE ENDS
529 END
530