From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/FAT.ASM | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 v2.0/source/FAT.ASM (limited to 'v2.0/source/FAT.ASM') diff --git a/v2.0/source/FAT.ASM b/v2.0/source/FAT.ASM new file mode 100644 index 0000000..b1a4863 --- /dev/null +++ b/v2.0/source/FAT.ASM @@ -0,0 +1,362 @@ +; +; FAT operations for MSDOS +; + +INCLUDE DOSSEG.ASM + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xlist +.xcref +INCLUDE DOSSYM.ASM +INCLUDE DEVSYM.ASM +.cref +.list + +TITLE FAT - FAT maintenance routines +NAME FAT + + i_need CURBUF,DWORD + i_need CLUSSPLIT,BYTE + i_need CLUSSAVE,WORD + i_need CLUSSEC,WORD + i_need THISDRV,BYTE + i_need DEVCALL,BYTE + i_need CALLMED,BYTE + i_need CALLRBYT,BYTE + i_need BUFFHEAD,DWORD + i_need CALLXAD,DWORD + i_need CALLBPB,DWORD + +SUBTTL UNPACK -- UNPACK FAT ENTRIES +PAGE + +ASSUME SS:DOSGROUP + procedure UNPACK,NEAR +ASSUME DS:DOSGROUP,ES:NOTHING + +; Inputs: +; BX = Cluster number +; ES:BP = Base of drive parameters +; Outputs: +; DI = Contents of FAT for given cluster +; Zero set means DI=0 (free cluster) +; SI Destroyed, No other registers affected. Fatal error if cluster too big. + + CMP BX,ES:[BP.dpb_max_cluster] + JA HURTFAT + CALL MAPCLUSTER +ASSUME DS:NOTHING + MOV DI,[DI] + JNC HAVCLUS + PUSH CX + MOV CL,4 + SHR DI,CL + POP CX + STC +HAVCLUS: + AND DI,0FFFH + PUSH SS + POP DS + return + +HURTFAT: + PUSH AX + MOV AH,80H ; Signal Bad FAT to INT int_fatal_abort handler + MOV DI,0FFFH ; In case INT int_fatal_abort returns (it shouldn't) + invoke FATAL + POP AX ; Try to ignore bad FAT + return +UNPACK ENDP + +SUBTTL PACK -- PACK FAT ENTRIES +PAGE + procedure PACK,NEAR +ASSUME DS:DOSGROUP,ES:NOTHING + +; Inputs: +; BX = Cluster number +; DX = Data +; ES:BP = Pointer to drive DPB +; Outputs: +; The data is stored in the FAT at the given cluster. +; SI,DX,DI all destroyed +; No other registers affected + + CALL MAPCLUSTER +ASSUME DS:NOTHING + MOV SI,[DI] + JNC ALIGNED + PUSH CX + MOV CL,4 + SHL DX,CL + POP CX + AND SI,0FH + JMP SHORT PACKIN +ALIGNED: + AND SI,0F000H +PACKIN: + OR SI,DX + MOV [DI],SI + LDS SI,[CURBUF] + MOV [SI.BUFDIRTY],1 + CMP BYTE PTR [CLUSSPLIT],0 + PUSH SS + POP DS +ASSUME DS:DOSGROUP + retz + PUSH AX + PUSH BX + PUSH CX + MOV AX,[CLUSSAVE] + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + ADD SI,BUFINSIZ + MOV [SI],AH + PUSH SS + POP DS +ASSUME DS:DOSGROUP + PUSH AX + MOV DX,[CLUSSEC] + MOV SI,1 + XOR AL,AL + invoke GETBUFFRB + LDS DI,[CURBUF] +ASSUME DS:NOTHING + MOV [DI.BUFDIRTY],1 + ADD DI,BUFINSIZ + DEC DI + ADD DI,ES:[BP.dpb_sector_size] + POP AX + MOV [DI],AL + PUSH SS + POP DS + POP CX + POP BX + POP AX + return +PACK ENDP + +SUBTTL MAPCLUSTER - BUFFER A FAT SECTOR +PAGE + procedure MAPCLUSTER,NEAR +ASSUME DS:DOSGROUP,ES:NOTHING + +; Inputs: +; ES:BP Points to DPB +; BX Is cluster number +; Function: +; Get a pointer to the cluster +; Outputs: +; DS:DI Points to contents of FAT for given cluster +; DS:SI Points to start of buffer +; Carry set if cluster data is in high 12 bits of word +; No other registers effected + + MOV BYTE PTR [CLUSSPLIT],0 + PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV AX,BX + SHR AX,1 + ADD AX,BX + XOR DX,DX + MOV CX,ES:[BP.dpb_sector_size] + DIV CX ; AX is FAT sector # DX is sector index + ADD AX,ES:[BP.dpb_first_FAT] + DEC CX + PUSH AX + PUSH DX + PUSH CX + MOV DX,AX + XOR AL,AL + MOV SI,1 + invoke GETBUFFRB + LDS SI,[CURBUF] +ASSUME DS:NOTHING + LEA DI,[SI.BufInSiz] + POP CX + POP AX + POP DX + ADD DI,AX + CMP AX,CX + JNZ MAPRET + MOV AL,[DI] + PUSH SS + POP DS +ASSUME DS:DOSGROUP + INC BYTE PTR [CLUSSPLIT] + MOV BYTE PTR [CLUSSAVE],AL + MOV [CLUSSEC],DX + INC DX + XOR AL,AL + MOV SI,1 + invoke GETBUFFRB + LDS SI,[CURBUF] +ASSUME DS:NOTHING + LEA DI,[SI.BufInSiz] + MOV AL,[DI] + PUSH SS + POP DS +ASSUME DS:DOSGROUP + MOV BYTE PTR [CLUSSAVE+1],AL + MOV DI,OFFSET DOSGROUP:CLUSSAVE +MAPRET: + POP DX + POP CX + POP BX + MOV AX,BX + SHR AX,1 + POP AX + return +MAPCLUSTER ENDP + +SUBTTL FATREAD -- CHECK DRIVE GET FAT +PAGE +ASSUME DS:DOSGROUP,ES:NOTHING + + procedure FAT_operation,NEAR +FATERR: + AND DI,STECODE ; Put error code in DI + MOV AH,2 ; While trying to read FAT + MOV AL,BYTE PTR [THISDRV] ; Tell which drive + invoke FATAL1 + + entry FATREAD +ASSUME DS:DOSGROUP,ES:NOTHING + +; Function: +; If disk may have been changed, FAT is read in and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; ES:BP = Base of drive parameters +; All other registers destroyed + + MOV AL,BYTE PTR [THISDRV] + invoke GETBP + MOV AL,DMEDHL + MOV AH,ES:[BP.dpb_UNIT] + MOV WORD PTR [DEVCALL],AX + MOV BYTE PTR [DEVCALL.REQFUNC],DEVMDCH + MOV [DEVCALL.REQSTAT],0 + MOV AL,ES:[BP.dpb_media] + MOV BYTE PTR [CALLMED],AL + PUSH ES + PUSH DS + MOV BX,OFFSET DOSGROUP:DEVCALL + LDS SI,ES:[BP.dpb_driver_addr] ; DS:SI Points to device header +ASSUME DS:NOTHING + POP ES ; ES:BX Points to call header + invoke DEVIOCALL2 + PUSH SS + POP DS +ASSUME DS:DOSGROUP + POP ES ; Restore ES:BP + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JNZ FATERR + XOR AH,AH + XCHG AH,ES:[BP.dpb_first_access] ; Reset dpb_first_access + MOV AL,BYTE PTR [THISDRV] ; Use physical unit number + OR AH,BYTE PTR [CALLRBYT] + JS NEWDSK ; new disk or first access? + JZ CHKBUFFDIRT + return ; If Media not changed +CHKBUFFDIRT: + INC AH ; Here if ?Media..Check buffers + LDS DI,[BUFFHEAD] +ASSUME DS:NOTHING +NBUFFER: ; Look for dirty buffers + CMP AX,WORD PTR [DI.BUFDRV] + retz ; There is a dirty buffer, assume Media OK + LDS DI,[DI.NEXTBUF] + CMP DI,-1 + JNZ NBUFFER +; If no dirty buffers, assume Media changed +NEWDSK: + invoke SETVISIT +NXBUFFER: + MOV [DI.VISIT],1 + CMP AL,[DI.BUFDRV] ; For this drive? + JNZ SKPBUFF + MOV WORD PTR [DI.BUFDRV],00FFH ; Free up buffer + invoke SCANPLACE +SKPBUFF: + invoke SKIPVISIT + JNZ NXBUFFER + LDS DI,ES:[BP.dpb_driver_addr] + TEST [DI.SDEVATT],ISFATBYDEV + JNZ GETFREEBUF + context DS + MOV BX,2 + CALL UNPACK ; Read the first FAT sector into CURBUF + LDS DI,[CURBUF] + JMP SHORT GOTGETBUF +GETFREEBUF: +ASSUME DS:NOTHING + PUSH ES ; Get a free buffer for BIOS to use + PUSH BP + LDS DI,[BUFFHEAD] + invoke BUFWRITE + POP BP + POP ES +GOTGETBUF: + ADD DI,BUFINSIZ + MOV WORD PTR [CALLXAD+2],DS + PUSH SS + POP DS +ASSUME DS:DOSGROUP + MOV WORD PTR [CALLXAD],DI + MOV AL,DBPBHL + MOV AH,BYTE PTR ES:[BP.dpb_UNIT] + MOV WORD PTR [DEVCALL],AX + MOV BYTE PTR [DEVCALL.REQFUNC],DEVBPB + MOV [DEVCALL.REQSTAT],0 + MOV AL,BYTE PTR ES:[BP.dpb_media] + MOV [CALLMED],AL + PUSH ES + PUSH DS + PUSH WORD PTR ES:[BP.dpb_driver_addr+2] + PUSH WORD PTR ES:[BP.dpb_driver_addr] + MOV BX,OFFSET DOSGROUP:DEVCALL + POP SI + POP DS ; DS:SI Points to device header +ASSUME DS:NOTHING + POP ES ; ES:BX Points to call header + invoke DEVIOCALL2 + POP ES ; Restore ES:BP + PUSH SS + POP DS +ASSUME DS:DOSGROUP + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JNZ FATERRJ + MOV AL,BYTE PTR ES:[BP.dpb_media] + LDS SI,[CALLBPB] +ASSUME DS:NOTHING + CMP AL,BYTE PTR [SI.BPMEDIA] + JZ DPBOK + invoke $SETDPB + LDS DI,[CALLXAD] ; Get back buffer pointer + MOV AL,BYTE PTR ES:[BP.dpb_FAT_count] + MOV AH,BYTE PTR ES:[BP.dpb_FAT_size] + MOV WORD PTR [DI.BUFWRTCNT-BUFINSIZ],AX ;Correct buffer info +DPBOK: + context ds + MOV AX,-1 + TEST ES:[BP.dpb_current_dir],AX + retz ; If root, leave as root + MOV ES:[BP.dpb_current_dir],AX ; Path may be bad, mark invalid + return + +FATERRJ: JMP FATERR + +FAT_operation ENDP + +do_ext + +CODE ENDS + END + \ No newline at end of file -- cgit v1.2.3