summaryrefslogtreecommitdiff
path: root/v2.0/source/DISK.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v2.0/source/DISK.ASM')
-rw-r--r--v2.0/source/DISK.ASM1302
1 files changed, 1302 insertions, 0 deletions
diff --git a/v2.0/source/DISK.ASM b/v2.0/source/DISK.ASM
new file mode 100644
index 0000000..b1acd82
--- /dev/null
+++ b/v2.0/source/DISK.ASM
@@ -0,0 +1,1302 @@
1;
2; Disk routines for MSDOS
3;
4
5INCLUDE DOSSEG.ASM
6
7CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10.xlist
11.xcref
12INCLUDE DOSSYM.ASM
13INCLUDE DEVSYM.ASM
14.cref
15.list
16
17TITLE DISK - Disk utility routines
18NAME Disk
19
20 i_need COUTDSAV,BYTE
21 i_need COUTSAV,DWORD
22 i_need CINDSAV,BYTE
23 i_need CINSAV,DWORD
24 i_need CONSWAP,BYTE
25 i_need IDLEINT,BYTE
26 i_need THISFCB,DWORD
27 i_need DMAADD,DWORD
28 i_need DEVCALL,BYTE
29 i_need CALLSCNT,WORD
30 i_need CALLXAD,DWORD
31 i_need CONTPOS,WORD
32 i_need NEXTADD,WORD
33 i_need CONBUF,BYTE
34 i_need User_SS,WORD
35 i_need User_SP,WORD
36 i_need DSKStack,BYTE
37 i_need InDOS,BYTE
38 i_need NumIO,BYTE
39 i_need CurDrv,BYTE
40 i_need ThisDrv,BYTE
41 i_need ClusFac,BYTE
42 i_need SecClusPos,BYTE
43 i_need DirSec,WORD
44 i_need ClusNum,WORD
45 i_need NxtClusNum,WORD
46 i_need ReadOp,BYTE
47 i_need DskErr,BYTE
48 i_need RecCnt,WORD
49 i_need RecPos,4
50 i_need Trans,BYTE
51 i_need BytPos,4
52 i_need SecPos,WORD
53 i_need BytSecPos,WORD
54 i_need BytCnt1,WORD
55 i_need BytCnt2,WORD
56 i_need SecCnt,WORD
57 i_need ThisDPB,DWORD
58 i_need LastPos,WORD
59 i_need ValSec,WORD
60 i_need GrowCnt,DWORD
61
62SUBTTL LOAD -- MAIN READ ROUTINE AND DEVICE IN ROUTINES
63PAGE
64; * * * * Drivers for file input from devices * * * *
65
66 procedure SWAPBACK,NEAR
67ASSUME DS:DOSGROUP,ES:NOTHING
68 PUSH ES
69 PUSH DI
70 PUSH SI
71 PUSH BX
72 MOV BX,1
73 invoke get_sf_from_jfn
74 ADD DI,sf_fcb
75 MOV BL,BYTE PTR [COUTDSAV]
76 LDS SI,[COUTSAV]
77ASSUME DS:NOTHING
78 MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI
79 MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS
80 MOV ES:[DI.fcb_DEVID],BL
81 PUSH SS
82 POP DS
83ASSUME DS:DOSGROUP
84 XOR BX,BX
85 invoke get_sf_from_jfn
86 ADD DI,sf_fcb
87 MOV BL,BYTE PTR [CINDSAV]
88 LDS SI,[CINSAV]
89ASSUME DS:NOTHING
90 MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI
91 MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS
92 MOV ES:[DI.fcb_DEVID],BL
93 PUSH SS
94 POP DS
95ASSUME DS:DOSGROUP
96 MOV BYTE PTR [CONSWAP],0
97 MOV BYTE PTR [IDLEINT],1
98SWAPRET:
99 POP BX
100 POP SI
101 POP DI
102 POP ES
103 return
104SWAPBACK ENDP
105
106 procedure SWAPCON,NEAR
107ASSUME DS:DOSGROUP,ES:NOTHING
108 PUSH ES
109 PUSH DI
110 PUSH SI
111 PUSH BX
112 MOV BYTE PTR [CONSWAP],1
113 MOV BYTE PTR [IDLEINT],0
114 XOR BX,BX
115 invoke get_sf_from_jfn
116 ADD DI,sf_fcb
117 MOV BL,ES:[DI.fcb_DEVID]
118 MOV BYTE PTR [CINDSAV],BL
119 LDS SI,DWORD PTR ES:[DI.fcb_FIRCLUS]
120ASSUME DS:NOTHING
121 MOV WORD PTR [CINSAV],SI
122 MOV WORD PTR [CINSAV+2],DS
123 LDS SI,[THISFCB]
124 MOV BL,[SI.fcb_DEVID]
125 LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
126 MOV ES:[DI.fcb_DEVID],BL
127 MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI
128 MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS
129 PUSH SS
130 POP DS
131ASSUME DS:DOSGROUP
132 MOV BX,1
133 invoke get_sf_from_jfn
134 ADD DI,sf_fcb
135 MOV BL,ES:[DI.fcb_DEVID]
136 MOV BYTE PTR [COUTDSAV],BL
137 LDS SI,DWORD PTR ES:[DI.fcb_FIRCLUS]
138ASSUME DS:NOTHING
139 MOV WORD PTR [COUTSAV],SI
140 MOV WORD PTR [COUTSAV+2],DS
141 LDS SI,[THISFCB]
142 MOV BL,[SI.fcb_DEVID]
143 LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
144 MOV ES:[DI.fcb_DEVID],BL
145 MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI
146 MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS
147 PUSH SS
148 POP DS
149 JMP SWAPRET
150SWAPCON ENDP
151
152 procedure LOAD,NEAR
153ASSUME DS:NOTHING,ES:NOTHING
154;
155; Inputs:
156; DS:DI point to FCB
157; DX:AX = Position in file to read
158; CX = No. of records to read
159; Outputs:
160; DX:AX = Position of last record read
161; CX = No. of bytes read
162; ES:DI point to FCB
163; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set
164
165 call SETUP
166ASSUME DS:DOSGROUP
167 OR BL,BL ; Check for named device I/O
168 JS READDEV
169 call DISKREAD
170 return
171
172READDEV:
173ASSUME DS:DOSGROUP,ES:NOTHING
174 LES DI,[DMAADD]
175 TEST BL,40H ; End of file?
176 JZ ENDRDDEVJ3
177 TEST BL,ISNULL ; NUL device?
178 JZ TESTRAW ; NO
179 XOR AL,AL ; Indicate EOF
180ENDRDDEVJ3: JMP ENDRDDEVJ2
181
182DVRDRAW:
183ASSUME DS:DOSGROUP
184 PUSH ES
185 POP DS
186ASSUME DS:NOTHING
187DVRDRAWR:
188 MOV BX,DI ; DS:BX transfer addr
189 XOR DX,DX ; Start at 0
190 XOR AX,AX ; Media Byte, unit = 0
191 invoke SETREAD
192 LDS SI,[THISFCB]
193 invoke DEVIOCALL
194 MOV DX,DI ; DX is preserved by INT 24
195 MOV AH,86H ; Read error
196 MOV DI,[DEVCALL.REQSTAT]
197 TEST DI,STERR
198 JZ CRDROK ; No errors
199 invoke CHARHARD
200 MOV DI,DX
201 CMP AL,1
202 JZ DVRDRAWR ; Retry
203CRDROK:
204 MOV DI,DX
205 ADD DI,[CALLSCNT] ; Amount transferred
206 JMP SHORT ENDRDDEVJ2
207
208TESTRAW:
209 TEST BL,020H ; Raw mode?
210 JNZ DVRDRAW
211 TEST BL,ISCIN ; Is it console device?
212 JZ NOTRDCON
213 JMP READCON
214NOTRDCON:
215 MOV AX,ES
216 MOV DS,AX
217ASSUME DS:NOTHING
218 MOV BX,DI
219 XOR DX,DX
220 MOV AX,DX
221 PUSH CX
222 MOV CX,1
223 invoke SETREAD
224 POP CX
225 LDS SI,[THISFCB]
226 LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
227DVRDLP:
228 invoke DSKSTATCHK
229 invoke DEVIOCALL2
230 PUSH DI
231 MOV AH,86H
232 MOV DI,[DEVCALL.REQSTAT]
233 TEST DI,STERR
234 JZ CRDOK
235 invoke CHARHARD
236 POP DI
237 MOV [CALLSCNT],1
238 CMP AL,1
239 JZ DVRDLP ;Retry
240 XOR AL,AL ;Pick some random character
241 JMP SHORT DVRDIGN
242CRDOK:
243 POP DI
244 CMP [CALLSCNT],1
245 JNZ ENDRDDEVJ2
246 PUSH DS
247 MOV DS,WORD PTR [CALLXAD+2]
248 MOV AL,BYTE PTR [DI]
249 POP DS
250DVRDIGN:
251 INC WORD PTR [CALLXAD]
252 MOV [DEVCALL.REQSTAT],0
253 INC DI
254 CMP AL,1AH ; ^Z?
255 JZ ENDRDDEVJ
256 CMP AL,c_CR ; CR?
257 LOOPNZ DVRDLP
258ENDRDDEVJ:
259 DEC DI
260ENDRDDEVJ2:
261 JMP SHORT ENDRDDEV
262
263ASSUME DS:NOTHING,ES:NOTHING
264
265TRANBUF:
266 LODSB
267 STOSB
268 CMP AL,c_CR ; Check for carriage return
269 JNZ NORMCH
270 MOV BYTE PTR [SI],c_LF
271NORMCH:
272 CMP AL,c_LF
273 LOOPNZ TRANBUF
274 JNZ ENDRDCON
275 XOR SI,SI ; Cause a new buffer to be read
276 invoke OUT ; Transmit linefeed
277 OR AL,1 ; Clear zero flag--not end of file
278ENDRDCON:
279 PUSH SS
280 POP DS
281ASSUME DS:DOSGROUP
282 CALL SWAPBACK
283 MOV [CONTPOS],SI
284ENDRDDEV:
285 PUSH SS
286 POP DS
287ASSUME DS:DOSGROUP
288 MOV [NEXTADD],DI
289 JNZ SETFCBC ; Zero set if Ctrl-Z found in input
290 LES DI,[THISFCB]
291 AND ES:BYTE PTR [DI.fcb_DEVID],0FFH-40H ; Mark as no more data available
292SETFCBC:
293 call SETFCB
294 return
295
296ASSUME DS:NOTHING,ES:NOTHING
297
298READCON:
299ASSUME DS:DOSGROUP
300 CALL SWAPCON
301 MOV SI,[CONTPOS]
302 OR SI,SI
303 JNZ TRANBUF
304 CMP BYTE PTR [CONBUF],128
305 JZ GETBUF
306 MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template
307GETBUF:
308 PUSH CX
309 PUSH ES
310 PUSH DI
311 MOV DX,OFFSET DOSGROUP:CONBUF
312 invoke $STD_CON_STRING_INPUT ; Get input buffer
313 POP DI
314 POP ES
315 POP CX
316 MOV SI,2 + OFFSET DOSGROUP:CONBUF
317 CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character
318 JNZ TRANBUF
319 MOV AL,1AH
320 STOSB
321 DEC DI
322 MOV AL,10
323 invoke OUT ; Send linefeed
324 XOR SI,SI
325 JMP SHORT ENDRDCON
326
327LOAD ENDP
328
329SUBTTL STORE -- MAIN WRITE ROUTINE AND DEVICE OUT ROUTINES
330PAGE
331ASSUME DS:NOTHING,ES:NOTHING
332 procedure STORE,NEAR
333ASSUME DS:NOTHING,ES:NOTHING
334
335; Inputs:
336; DS:DI point to FCB
337; DX:AX = Position in file of disk transfer
338; CX = Record count
339; Outputs:
340; DX:AX = Position of last record written
341; CX = No. of records written
342; ES:DI point to FCB
343; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set
344
345 call SETUP
346ASSUME DS:DOSGROUP
347 OR BL,BL
348 JS WRTDEV
349 invoke DATE16
350 MOV ES:[DI.fcb_FDATE],AX
351 MOV ES:[DI.fcb_FTIME],DX
352 call DISKWRITE
353 return
354
355WRITECON:
356 PUSH DS
357 PUSH SS
358 POP DS
359ASSUME DS:DOSGROUP
360 CALL SWAPCON
361 POP DS
362ASSUME DS:NOTHING
363 MOV SI,BX
364 PUSH CX
365WRCONLP:
366 LODSB
367 CMP AL,1AH ; ^Z?
368 JZ CONEOF
369 invoke OUT
370 LOOP WRCONLP
371CONEOF:
372 POP AX ; Count
373 SUB AX,CX ; Amount actually written
374 POP DS
375ASSUME DS:DOSGROUP
376 CALL SWAPBACK
377 JMP SHORT ENDWRDEV
378
379DVWRTRAW:
380ASSUME DS:NOTHING
381 XOR AX,AX ; Media Byte, unit = 0
382 invoke SETWRITE
383 LDS SI,[THISFCB]
384 invoke DEVIOCALL
385 MOV DX,DI
386 MOV AH,87H
387 MOV DI,[DEVCALL.REQSTAT]
388 TEST DI,STERR
389 JZ CWRTROK
390 invoke CHARHARD
391 MOV BX,DX ; Recall transfer addr
392 CMP AL,1
393 JZ DVWRTRAW ; Try again
394CWRTROK:
395 POP DS
396ASSUME DS:DOSGROUP
397 MOV AX,[CALLSCNT] ; Get actual number of bytes transferred
398ENDWRDEV:
399 LES DI,[THISFCB]
400 XOR DX,DX
401 DIV ES:[DI.fcb_RECSIZ]
402 MOV CX,AX ; Partial record is ignored
403 call ADDREC
404 return
405
406ASSUME DS:DOSGROUP
407WRTDEV:
408 OR BL,40H ; Reset EOF for input
409 XOR AX,AX
410 JCXZ ENDWRDEV ; problem of creating on a device.
411 PUSH DS
412 MOV AL,BL
413 LDS BX,[DMAADD]
414ASSUME DS:NOTHING
415 MOV DI,BX
416 XOR DX,DX ; Set starting point
417 TEST AL,020H ; Raw?
418 JNZ DVWRTRAW
419 TEST AL,ISCOUT ; Console output device?
420 JNZ WRITECON
421 TEST AL,ISNULL
422 JNZ WRTNUL
423 MOV AX,DX
424 CMP BYTE PTR [BX],1AH ; ^Z?
425 JZ WRTCOOKDONE ; Yes, transfer nothing
426 PUSH CX
427 MOV CX,1
428 invoke SETWRITE
429 POP CX
430 LDS SI,[THISFCB]
431 LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
432DVWRTLP:
433 invoke DSKSTATCHK
434 invoke DEVIOCALL2
435 PUSH DI
436 MOV AH,87H
437 MOV DI,[DEVCALL.REQSTAT]
438 TEST DI,STERR
439 JZ CWROK
440 invoke CHARHARD
441 POP DI
442 MOV [CALLSCNT],1
443 CMP AL,1
444 JZ DVWRTLP
445 JMP SHORT DVWRTIGN
446CWROK:
447 POP DI
448 CMP [CALLSCNT],0
449 JZ WRTCOOKDONE
450DVWRTIGN:
451 INC DX
452 INC WORD PTR [CALLXAD]
453 INC DI
454 PUSH DS
455 MOV DS,WORD PTR [CALLXAD+2]
456 CMP BYTE PTR [DI],1AH ; ^Z?
457 POP DS
458 JZ WRTCOOKDONE
459 MOV [DEVCALL.REQSTAT],0
460 LOOP DVWRTLP
461WRTCOOKDONE:
462 MOV AX,DX
463 POP DS
464 JMP ENDWRDEV
465
466WRTNUL:
467 MOV DX,CX ;Entire transfer done
468 JMP WRTCOOKDONE
469
470STORE ENDP
471
472 procedure get_io_fcb,near
473ASSUME DS:NOTHING,ES:NOTHING
474; Convert JFN number in BX to FCB in DS:SI
475 PUSH SS
476 POP DS
477ASSUME DS:DOSGROUP
478 PUSH ES
479 PUSH DI
480 invoke get_sf_from_jfn
481 JC RET44P
482 MOV SI,DI
483 ADD SI,sf_fcb
484 PUSH ES
485 POP DS
486ASSUME DS:NOTHING
487RET44P:
488 POP DI
489 POP ES
490 return
491get_io_fcb ENDP
492
493SUBTTL GETTHISDRV -- FIND CURRENT DRIVE
494PAGE
495; Input: AL has drive identifier (1=A, 0=default)
496; Output: AL has physical drive (0=A)
497; Carry set if invalid drive (and AL is garbage anyway)
498 procedure GetThisDrv,NEAR
499ASSUME DS:NOTHING,ES:NOTHING
500 CMP BYTE PTR [NUMIO],AL
501 retc
502 DEC AL
503 JNS PHYDRV
504 MOV AL,[CURDRV]
505PHYDRV:
506 MOV BYTE PTR [THISDRV],AL
507 return
508GetThisDrv ENDP
509
510SUBTTL DIRREAD -- READ A DIRECTORY SECTOR
511PAGE
512 procedure DirRead,NEAR
513ASSUME DS:DOSGROUP,ES:NOTHING
514
515; Inputs:
516; AX = Directory block number (relative to first block of directory)
517; ES:BP = Base of drive parameters
518; [DIRSEC] = First sector of first cluster of directory
519; [CLUSNUM] = Next cluster
520; [CLUSFAC] = Sectors/Cluster
521; Function:
522; Read the directory block into [CURBUF].
523; Outputs:
524; [NXTCLUSNUM] = Next cluster (after the one skipped to)
525; [SECCLUSPOS] Set
526; ES:BP unchanged [CURBUF] Points to Buffer with dir sector
527; All other registers destroyed.
528
529 MOV CL,[CLUSFAC]
530 DIV CL ; AL # clusters to skip, AH position in cluster
531 MOV [SECCLUSPOS],AH
532 MOV CL,AL
533 XOR CH,CH
534 MOV DX,[DIRSEC]
535 ADD DL,AH
536 ADC DH,0
537 MOV BX,[CLUSNUM]
538 MOV [NXTCLUSNUM],BX
539 JCXZ FIRSTCLUSTER
540SKPCLLP:
541 invoke UNPACK
542 XCHG BX,DI
543 CMP BX,0FF8H
544 JAE HAVESKIPPED
545 LOOP SKPCLLP
546HAVESKIPPED:
547 MOV [NXTCLUSNUM],BX
548 MOV DX,DI
549 MOV BL,AH
550 invoke FIGREC
551 entry FIRSTCLUSTER
552 XOR AL,AL ; Indicate pre-read
553 MOV AH,DIRPRI
554 invoke GETBUFFR
555 ret
556DirRead ENDP
557
558SUBTTL FATSECRD -- READ A FAT SECTOR
559PAGE
560 procedure FATSecRd,NEAR
561ASSUME DS:NOTHING,ES:NOTHING
562
563; Inputs:
564; Same as DREAD
565; DS:BX = Transfer address
566; CX = Number of sectors
567; DX = Absolute record number
568; ES:BP = Base of drive parameters
569; Function:
570; Calls BIOS to perform FAT read.
571; Outputs:
572; Same as DREAD
573
574 MOV DI,CX
575 MOV CL,ES:[BP.dpb_FAT_count]
576 MOV AL,ES:[BP.dpb_FAT_size]
577 XOR AH,AH
578 MOV CH,AH
579 PUSH DX
580NXTFAT:
581 PUSH CX
582 PUSH AX
583 MOV CX,DI
584 CALL DSKREAD
585 POP AX
586 POP CX
587 JZ RET41P
588 ADD DX,AX
589 LOOP NXTFAT
590 POP DX
591 MOV CX,DI
592
593; NOTE FALL THROUGH
594
595SUBTTL DREAD -- DO A DISK READ
596PAGE
597 entry DREAD
598ASSUME DS:NOTHING,ES:NOTHING
599
600; Inputs:
601; DS:BX = Transfer address
602; CX = Number of sectors
603; DX = Absolute record number
604; ES:BP = Base of drive parameters
605; Function:
606; Calls BIOS to perform disk read. If BIOS reports
607; errors, will call HARDERR for further action.
608; DS,ES:BP preserved. All other registers destroyed.
609
610 CALL DSKREAD
611 retz
612 MOV BYTE PTR [READOP],0
613 invoke HARDERR
614 CMP AL,1 ; Check for retry
615 JZ DREAD
616 return ; Ignore otherwise
617RET41P: POP DX
618 return
619FATSecRd ENDP
620
621SUBTTL DSKREAD -- PHYSICAL DISK READ
622PAGE
623 procedure DskRead,NEAR
624ASSUME DS:NOTHING,ES:NOTHING
625
626; Inputs:
627; DS:BX = Transfer addr
628; CX = Number of sectors
629; DX = Absolute record number
630; ES:BP = Base of drive parameters
631; Function:
632; Call BIOS to perform disk read
633; Outputs:
634; DI = CX on entry
635; CX = Number of sectors unsuccessfully transfered
636; AX = Status word as returned by BIOS (error code in AL if error)
637; Zero set if OK (from BIOS)
638; Zero clear if error
639; SI Destroyed, others preserved
640
641 PUSH CX
642 MOV AH,ES:[BP.dpb_media]
643 MOV AL,ES:[BP.dpb_UNIT]
644 PUSH BX
645 PUSH ES
646 invoke SETREAD
647 JMP DODSKOP
648
649SUBTTL DWRITE -- SEE ABOUT WRITING
650PAGE
651 entry DWRITE
652ASSUME DS:NOTHING,ES:NOTHING
653
654; Inputs:
655; DS:BX = Transfer address
656; CX = Number of sectors
657; DX = Absolute record number
658; ES:BP = Base of drive parameters
659; Function:
660; Calls BIOS to perform disk write. If BIOS reports
661; errors, will call HARDERR for further action.
662; BP preserved. All other registers destroyed.
663
664 CALL DSKWRITE
665 retz
666 MOV BYTE PTR [READOP],1
667 invoke HARDERR
668 CMP AL,1 ; Check for retry
669 JZ DWRITE
670 return
671
672SUBTTL DSKWRITE -- PHYSICAL DISK WRITE
673PAGE
674 entry DSKWRITE
675ASSUME DS:NOTHING,ES:NOTHING
676
677; Inputs:
678; DS:BX = Transfer addr
679; CX = Number of sectors
680; DX = Absolute record number
681; ES:BP = Base of drive parameters
682; Function:
683; Call BIOS to perform disk read
684; Outputs:
685; DI = CX on entry
686; CX = Number of sectors unsuccessfully transfered
687; AX = Status word as returned by BIOS (error code in AL if error)
688; Zero set if OK (from BIOS)
689; Zero clear if error
690; SI Destroyed, others preserved
691
692 PUSH CX
693 MOV AH,ES:[BP.dpb_media]
694 MOV AL,ES:[BP.dpb_UNIT]
695 PUSH BX
696 PUSH ES
697 invoke SETWRITE
698DODSKOP:
699 MOV CX,DS ; Save DS
700 POP DS ; DS:BP points to DPB
701 PUSH DS
702 LDS SI,DS:[BP.dpb_driver_addr]
703 invoke DEVIOCALL2
704 MOV DS,CX ; Restore DS
705 POP ES ; Restore ES
706 POP BX
707 MOV CX,[CALLSCNT] ; Number of sectors transferred
708 POP DI
709 SUB CX,DI
710 NEG CX ; Number of sectors not transferred
711 MOV AX,[DEVCALL.REQSTAT]
712 TEST AX,STERR
713 return
714DskRead ENDP
715
716SUBTTL SETUP -- SETUP A DISK READ OR WRITE FROM USER
717PAGE
718ASSUME DS:DOSGROUP,ES:NOTHING
719
720 procedure SETUP,NEAR
721ASSUME DS:NOTHING,ES:NOTHING
722
723; Inputs:
724; DS:DI point to FCB
725; DX:AX = Record position in file of disk transfer
726; CX = Record count
727; Outputs:
728; DS = DOSGROUP
729; BL = fcb_DEVID from FCB
730; CX = No. of bytes to transfer (0 = 64K)
731; [THISDPB] = Base of drive parameters
732; [RECCNT] = Record count
733; [RECPOS] = Record position in file
734; ES:DI Points to FCB
735; [THISFCB] = ES:DI
736; [NEXTADD] = Displacement of disk transfer within segment
737; [SECPOS] = Position of first sector
738; [BYTPOS] = Byte position in file
739; [BYTSECPOS] = Byte position in first sector
740; [CLUSNUM] = First cluster
741; [SECCLUSPOS] = Sector within first cluster
742; [DSKERR] = 0 (no errors yet)
743; [TRANS] = 0 (No transfers yet)
744; [THISDRV] = Physical drive unit number
745
746 PUSH AX
747 MOV AL,[DI]
748 DEC AL
749 MOV BYTE PTR [THISDRV],AL
750 MOV AL,[DI.fcb_DEVID]
751 MOV SI,[DI.fcb_RECSIZ]
752 OR SI,SI
753 JNZ HAVRECSIZ
754 MOV SI,128
755 MOV [DI.fcb_RECSIZ],SI
756HAVRECSIZ:
757 MOV WORD PTR [THISFCB+2],DS
758 PUSH SS
759 POP DS ; Set DS to DOSGROUP
760ASSUME DS:DOSGROUP
761 MOV WORD PTR [THISFCB],DI
762 OR AL,AL ; Is it a device?
763 JNS NOTDEVICE
764 XOR AL,AL ; Fake in drive 0 so we can get BP
765NOTDEVICE:
766 invoke GETBP
767 POP AX
768 JNC CheckRecLen
769 XOR CX,CX
770 MOV BYTE PTR [DSKERR],4
771 POP BX
772 return
773
774CheckRecLen:
775 CMP SI,64 ; Check if highest byte of RECPOS is significant
776 JB SMALREC
777 XOR DH,DH ; Ignore MSB if record >= 64 bytes
778SMALREC:
779 MOV [RECCNT],CX
780 MOV WORD PTR [RECPOS],AX
781 MOV WORD PTR [RECPOS+2],DX
782 MOV BX,WORD PTR [DMAADD]
783 MOV [NEXTADD],BX
784 MOV BYTE PTR [DSKERR],0
785 MOV BYTE PTR [TRANS],0
786 MOV BX,DX
787 MUL SI
788 MOV WORD PTR [BYTPOS],AX
789 PUSH DX
790 MOV AX,BX
791 MUL SI
792 POP BX
793 ADD AX,BX
794 ADC DX,0 ; Ripple carry
795 JNZ EOFERR
796 MOV WORD PTR [BYTPOS+2],AX
797 MOV DX,AX
798 MOV AX,WORD PTR [BYTPOS]
799 MOV BX,ES:[BP.dpb_sector_size]
800 CMP DX,BX ; See if divide will overflow
801 JNC EOFERR
802 DIV BX
803 MOV [SECPOS],AX
804 MOV [BYTSECPOS],DX
805 MOV DX,AX
806 AND AL,ES:[BP.dpb_cluster_mask]
807 MOV [SECCLUSPOS],AL
808 MOV AX,CX ; Record count
809 MOV CL,ES:[BP.dpb_cluster_shift]
810 SHR DX,CL
811 MOV [CLUSNUM],DX
812 MUL SI ; Multiply by bytes per record
813 MOV CX,AX
814 ADD AX,WORD PTR [DMAADD] ; See if it will fit in one segment
815 ADC DX,0
816 JZ OK ; Must be less than 64K
817 MOV AX,WORD PTR [DMAADD]
818 NEG AX ; Amount of room left in segment
819 JNZ PARTSEG
820 DEC AX
821PARTSEG:
822 XOR DX,DX
823 DIV SI ; How many records will fit?
824 MOV [RECCNT],AX
825 MUL SI ; Translate that back into bytes
826 MOV BYTE PTR [DSKERR],2 ; Flag that trimming took place
827 MOV CX,AX
828 JCXZ NOROOM
829OK:
830 LES DI,[THISFCB]
831 MOV BL,ES:[DI.fcb_DEVID]
832 return
833
834EOFERR:
835 MOV BYTE PTR [DSKERR],1
836 XOR CX,CX
837NOROOM:
838 LES DI,[THISFCB]
839 POP BX ; Kill return address
840 return
841SETUP ENDP
842
843SUBTTL BREAKDOWN -- CUT A USER READ OR WRITE INTO PIECES
844PAGE
845 procedure BREAKDOWN,near
846ASSUME DS:DOSGROUP,ES:NOTHING
847
848; Inputs:
849; CX = Length of disk transfer in bytes
850; ES:BP = Base of drive parameters
851; [BYTSECPOS] = Byte position witin first sector
852; Outputs:
853; [BYTCNT1] = Bytes to transfer in first sector
854; [SECCNT] = No. of whole sectors to transfer
855; [BYTCNT2] = Bytes to transfer in last sector
856; AX, BX, DX destroyed. No other registers affected.
857
858 MOV AX,[BYTSECPOS]
859 MOV BX,CX
860 OR AX,AX
861 JZ SAVFIR ; Partial first sector?
862 SUB AX,ES:[BP.dpb_sector_size]
863 NEG AX ; Max number of bytes left in first sector
864 SUB BX,AX ; Subtract from total length
865 JAE SAVFIR
866 ADD AX,BX ; Don't use all of the rest of the sector
867 XOR BX,BX ; And no bytes are left
868SAVFIR:
869 MOV [BYTCNT1],AX
870 MOV AX,BX
871 XOR DX,DX
872 DIV ES:[BP.dpb_sector_size] ; How many whole sectors?
873 MOV [SECCNT],AX
874 MOV [BYTCNT2],DX ; Bytes remaining for last sector
875 OR DX,[BYTCNT1]
876 retnz ; NOT (BYTCNT1 = BYTCNT2 = 0)
877 CMP AX,1
878 retnz
879 MOV AX,ES:[BP.dpb_sector_size] ; Buffer EXACT one sector I/O
880 MOV [BYTCNT2],AX
881 MOV [SECCNT],DX ; DX = 0
882 return
883BreakDown ENDP
884
885SUBTTL DISKREAD -- PERFORM USER DISK READ
886PAGE
887 procedure DISKREAD,NEAR
888ASSUME DS:DOSGROUP,ES:NOTHING
889
890; Inputs:
891; Outputs of SETUP
892; Function:
893; Perform disk read
894; Outputs:
895; DX:AX = Position of last record read
896; CX = No. of records read
897; ES:DI point to FCB
898; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set
899
900 MOV AX,ES:WORD PTR [DI.fcb_FILSIZ]
901 MOV BX,ES:WORD PTR [DI.fcb_FILSIZ+2]
902 SUB AX,WORD PTR [BYTPOS]
903 SBB BX,WORD PTR [BYTPOS+2]
904 JB RDERR
905 JNZ ENUF
906 OR AX,AX
907 JZ RDERR
908 CMP AX,CX
909 JAE ENUF
910 MOV CX,AX
911ENUF:
912 LES BP,[THISDPB]
913 CALL BREAKDOWN
914 MOV CX,[CLUSNUM]
915 invoke FNDCLUS
916 OR CX,CX
917 JZ SHORT SKIPERR
918RDERR:
919 JMP WRTERR
920RDLASTJ:JMP RDLAST
921SETFCBJ2: JMP SETFCB
922
923SKIPERR:
924
925 MOV [LASTPOS],DX
926 MOV [CLUSNUM],BX
927 CMP [BYTCNT1],0
928 JZ RDMID
929 invoke BUFRD
930RDMID:
931 CMP [SECCNT],0
932 JZ RDLASTJ
933 invoke NEXTSEC
934 JC SETFCBJ2
935 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
936ONSEC:
937 MOV DL,[SECCLUSPOS]
938 MOV CX,[SECCNT]
939 MOV BX,[CLUSNUM]
940RDLP:
941 invoke OPTIMIZE
942 PUSH DI
943 PUSH AX
944 PUSH BX
945 MOV DS,WORD PTR [DMAADD+2]
946ASSUME DS:NOTHING
947 PUSH DX
948 PUSH CX
949 CALL DREAD
950 POP BX
951 POP DX
952 ADD BX,DX ; Upper bound of read
953 MOV AL,ES:[BP.dpb_drive]
954 invoke SETVISIT
955NXTBUF: ; Must see if one of these sectors is buffered
956 MOV [DI.VISIT],1 ; Mark as visited
957 CMP AL,[DI.BUFDRV]
958 JNZ DONXTBUF ; Not for this drive
959 CMP [DI.BUFSECNO],DX
960 JC DONXTBUF ; Below first sector
961 CMP [DI.BUFSECNO],BX
962 JNC DONXTBUF ; Above last sector
963 CMP BYTE PTR [DI.BUFDIRTY],0
964 JZ CLBUFF ; Buffer is clean, so OK
965; A sector has been read in when a dirty copy of it is in a buffer
966; The buffered sector must now be read into the right place
967 POP AX ; Recall transfer address
968 PUSH AX
969 PUSH DI ; Save search environment
970 PUSH DX
971 SUB DX,[DI.BUFSECNO] ; How far into transfer?
972 NEG DX
973 MOV SI,DI
974 MOV DI,AX
975 MOV AX,DX
976 MOV CX,ES:[BP.dpb_sector_size]
977 MUL CX
978 ADD DI,AX ; Put the buffer here
979 ADD SI,BUFINSIZ
980 SHR CX,1
981 PUSH ES
982 MOV ES,WORD PTR [DMAADD+2]
983 REP MOVSW
984 JNC EVENMOV
985 MOVSB
986EVENMOV:
987 POP ES
988 POP DX
989 POP DI
990 MOV AL,ES:[BP.dpb_drive]
991CLBUFF:
992 invoke SCANPLACE
993DONXTBUF:
994 invoke SKIPVISIT
995 JNZ NXTBUF
996 PUSH SS
997 POP DS
998ASSUME DS:DOSGROUP
999 POP CX
1000 POP CX
1001 POP BX
1002 JCXZ RDLAST
1003 CMP BX,0FF8H
1004 JAE SETFCB
1005 MOV DL,0
1006 INC [LASTPOS] ; We'll be using next cluster
1007 JMP RDLP
1008
1009RDLAST:
1010 MOV AX,[BYTCNT2]
1011 OR AX,AX
1012 JZ SETFCB
1013 MOV [BYTCNT1],AX
1014 invoke NEXTSEC
1015 JC SETFCB
1016 MOV [BYTSECPOS],0
1017 invoke BUFRD
1018
1019 entry SETFCB
1020 LES SI,[THISFCB]
1021 MOV AX,[NEXTADD]
1022 MOV DI,AX
1023 SUB AX,WORD PTR [DMAADD] ; Number of bytes transfered
1024 XOR DX,DX
1025 MOV CX,ES:[SI.fcb_RECSIZ]
1026 DIV CX ; Number of records
1027 CMP AX,[RECCNT] ; Check if all records transferred
1028 JZ FULLREC
1029 MOV BYTE PTR [DSKERR],1
1030 OR DX,DX
1031 JZ FULLREC ; If remainder 0, then full record transfered
1032 MOV BYTE PTR [DSKERR],3 ; Flag partial last record
1033 SUB CX,DX ; Bytes left in last record
1034 PUSH ES
1035 MOV ES,WORD PTR [DMAADD+2]
1036 XCHG AX,BX ; Save the record count temporarily
1037 XOR AX,AX ; Fill with zeros
1038 SHR CX,1
1039 JNC EVENFIL
1040 STOSB
1041EVENFIL:
1042 REP STOSW
1043 XCHG AX,BX ; Restore record count to AX
1044 POP ES
1045 INC AX ; Add last (partial) record to total
1046FULLREC:
1047 MOV CX,AX
1048 MOV DI,SI ; ES:DI point to FCB
1049SETCLUS:
1050 TEST ES:[DI].fcb_DEVID,-1
1051 JS ADDREC ; don't set clisters if device
1052 MOV AX,[CLUSNUM]
1053 AND ES:[DI.fcb_LSTCLUS],0F000h ; fcb_lstclus is packed with dir clus
1054 OR ES:[DI.fcb_LSTCLUS],AX ; drop in the correct part of fcb_lstclus
1055 MOV AX,[LASTPOS]
1056 MOV ES:[DI.fcb_CLUSPOS],AX
1057 entry AddRec
1058 MOV AX,WORD PTR [RECPOS]
1059 MOV DX,WORD PTR [RECPOS+2]
1060 JCXZ RET28 ; If no records read, don't change position
1061 DEC CX
1062 ADD AX,CX ; Update current record position
1063 ADC DX,0
1064 INC CX
1065RET28: return
1066DISKREAD ENDP
1067
1068SUBTTL DISKWRITE -- PERFORM USER DISK WRITE
1069PAGE
1070 procedure DISKWRITE,NEAR
1071ASSUME DS:DOSGROUP,ES:NOTHING
1072
1073; Inputs:
1074; Outputs of SETUP
1075; Function:
1076; Perform disk write
1077; Outputs:
1078; DX:AX = Position of last record written
1079; CX = No. of records written
1080; ES:DI point to FCB
1081; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set
1082
1083 AND BL,3FH ; Mark file as dirty
1084 MOV ES:[DI.fcb_DEVID],BL
1085 LES BP,[THISDPB]
1086 CALL BREAKDOWN
1087 MOV AX,WORD PTR [BYTPOS]
1088 MOV DX,WORD PTR [BYTPOS+2]
1089 JCXZ WRTEOFJ
1090 ADD AX,CX
1091 ADC DX,0 ; AX:DX=last byte accessed
1092 DIV ES:[BP.dpb_sector_size] ; AX=last sector accessed
1093 MOV BX,AX ; Save last full sector
1094 OR DX,DX
1095 JNZ CALCLUS
1096 DEC AX ; AX must be zero base indexed
1097CALCLUS:
1098 MOV CL,ES:[BP.dpb_cluster_shift]
1099 SHR AX,CL ; Last cluster to be accessed
1100 PUSH AX
1101 PUSH DX ; Save the size of the "tail"
1102 PUSH ES
1103 LES DI,[THISFCB]
1104 MOV AX,ES:WORD PTR [DI.fcb_FILSIZ]
1105 MOV DX,ES:WORD PTR [DI.fcb_FILSIZ+2]
1106 POP ES
1107 DIV ES:[BP.dpb_sector_size]
1108 MOV CX,AX ; Save last full sector of current file
1109 OR DX,DX
1110 JZ NORNDUP
1111 INC AX ; Round up if any remainder
1112NORNDUP:
1113 MOV [VALSEC],AX ; Number of sectors that have been written
1114 XOR AX,AX
1115 MOV WORD PTR [GROWCNT],AX
1116 MOV WORD PTR [GROWCNT+2],AX
1117 POP AX
1118 SUB BX,CX ; Number of full sectors
1119 JB NOGROW
1120 JZ TESTTAIL
1121 MOV CX,DX
1122 XCHG AX,BX
1123 MUL ES:[BP.dpb_sector_size] ; Bytes of full sector growth
1124 SUB AX,CX ; Take off current "tail"
1125 SBB DX,0 ; 32-bit extension
1126 ADD AX,BX ; Add on new "tail"
1127 ADC DX,0 ; ripple tim's head off
1128 JMP SHORT SETGRW
1129
1130HAVSTART:
1131 MOV CX,AX
1132 invoke SKPCLP
1133 JCXZ DOWRTJ
1134 invoke ALLOCATE
1135 JNC DOWRTJ
1136WRTERR:
1137 XOR CX,CX
1138 MOV BYTE PTR [DSKERR],1
1139 MOV AX,WORD PTR [RECPOS]
1140 MOV DX,WORD PTR [RECPOS+2]
1141 LES DI,[THISFCB]
1142 return
1143
1144DOWRTJ: JMP DOWRT
1145
1146WRTEOFJ:
1147 JMP WRTEOF
1148
1149TESTTAIL:
1150 SUB AX,DX
1151 JBE NOGROW
1152 XOR DX,DX
1153SETGRW:
1154 MOV WORD PTR [GROWCNT],AX
1155 MOV WORD PTR [GROWCNT+2],DX
1156NOGROW:
1157 POP AX
1158 MOV CX,[CLUSNUM] ; First cluster accessed
1159 invoke FNDCLUS
1160 MOV [CLUSNUM],BX
1161 MOV [LASTPOS],DX
1162 SUB AX,DX ; Last cluster minus current cluster
1163 JZ DOWRT ; If we have last clus, we must have first
1164 JCXZ HAVSTART ; See if no more data
1165 PUSH CX ; No. of clusters short of first
1166 MOV CX,AX
1167 invoke ALLOCATE
1168 POP AX
1169 JC WRTERR
1170 MOV CX,AX
1171 MOV DX,[LASTPOS]
1172 INC DX
1173 DEC CX
1174 JZ NOSKIP
1175 invoke SKPCLP
1176NOSKIP:
1177 MOV [CLUSNUM],BX
1178 MOV [LASTPOS],DX
1179DOWRT:
1180 CMP [BYTCNT1],0
1181 JZ WRTMID
1182 MOV BX,[CLUSNUM]
1183 invoke BUFWRT
1184WRTMID:
1185 MOV AX,[SECCNT]
1186 OR AX,AX
1187 JZ WRTLAST
1188 ADD [SECPOS],AX
1189 invoke NEXTSEC
1190 MOV BYTE PTR [TRANS],1 ; A transfer is taking place
1191 MOV DL,[SECCLUSPOS]
1192 MOV BX,[CLUSNUM]
1193 MOV CX,[SECCNT]
1194WRTLP:
1195 invoke OPTIMIZE
1196 PUSH DI
1197 PUSH AX
1198 PUSH DX
1199 PUSH BX
1200 MOV AL,ES:[BP.dpb_drive]
1201 MOV BX,CX
1202 ADD BX,DX ; Upper bound of write
1203 invoke SETVISIT
1204ASSUME DS:NOTHING
1205NEXTBUFF: ; Search for buffers
1206 MOV [DI.VISIT],1 ; Mark as visited
1207 CMP AL,[DI.BUFDRV]
1208 JNZ DONEXTBUFF ; Not for this drive
1209 CMP [DI.BUFSECNO],DX
1210 JC DONEXTBUFF ; Buffer is not in range of write
1211 CMP [DI.BUFSECNO],BX
1212 JNC DONEXTBUFF ; Buffer is not in range of write
1213 MOV WORD PTR [DI.BUFDRV],00FFH ; Free the buffer, it is being over written
1214 invoke SCANPLACE
1215DONEXTBUFF:
1216 invoke SKIPVISIT
1217 JNZ NEXTBUFF
1218 POP BX
1219 POP DX
1220 MOV DS,WORD PTR [DMAADD+2]
1221 CALL DWRITE
1222 POP CX
1223 POP BX
1224 PUSH SS
1225 POP DS
1226ASSUME DS:DOSGROUP
1227 JCXZ WRTLAST
1228 MOV DL,0
1229 INC [LASTPOS] ; We'll be using next cluster
1230 JMP SHORT WRTLP
1231
1232WRTERRJ: JMP WRTERR
1233
1234WRTLAST:
1235 MOV AX,[BYTCNT2]
1236 OR AX,AX
1237 JZ FINWRT
1238 MOV [BYTCNT1],AX
1239 invoke NEXTSEC
1240 MOV [BYTSECPOS],0
1241 invoke BUFWRT
1242FINWRT:
1243 LES DI,[THISFCB]
1244 MOV AX,WORD PTR [GROWCNT]
1245 MOV CX,WORD PTR [GROWCNT+2]
1246 OR AX,AX
1247 JNZ UPDATE_size
1248 OR CX,CX
1249 JZ SAMSIZ
1250Update_size:
1251 ADD WORD PTR ES:[DI.fcb_FILSIZ],AX
1252 ADC WORD PTR ES:[DI.fcb_FILSIZ+2],CX
1253SAMSIZ:
1254 MOV CX,[RECCNT]
1255 JMP SETCLUS
1256
1257WRTEOF:
1258 MOV CX,AX
1259 OR CX,DX
1260 JZ KILLFIL
1261 SUB AX,1
1262 SBB DX,0
1263 DIV ES:[BP.dpb_sector_size]
1264 MOV CL,ES:[BP.dpb_cluster_shift]
1265 SHR AX,CL
1266 MOV CX,AX
1267 invoke FNDCLUS
1268 JCXZ RELFILE
1269 invoke ALLOCATE
1270 JC WRTERRJ
1271UPDATE:
1272 LES DI,[THISFCB]
1273 MOV AX,WORD PTR [BYTPOS]
1274 MOV ES:WORD PTR [DI.fcb_FILSIZ],AX
1275 MOV AX,WORD PTR [BYTPOS+2]
1276 MOV ES:WORD PTR [DI.fcb_FILSIZ+2],AX
1277 XOR CX,CX
1278 JMP ADDREC
1279
1280RELFILE:
1281 MOV DX,0FFFH
1282 invoke RELBLKS
1283 JMP SHORT UPDATE
1284
1285KILLFIL:
1286 XOR BX,BX
1287 PUSH ES
1288 LES DI,[THISFCB]
1289 MOV ES:[DI.fcb_CLUSPOS],BX
1290 XCHG BX,ES:[DI.fcb_FIRCLUS]
1291 AND ES:[DI.fcb_LSTCLUS],0F000H
1292 POP ES
1293 OR BX,BX
1294 JZ UPDATE
1295 invoke RELEASE
1296 JMP SHORT UPDATE
1297DISKWRITE ENDP
1298do_ext
1299
1300CODE ENDS
1301 END
1302