mirror of https://github.com/microsoft/MS-DOS.git
362 lines
9.9 KiB
NASM
362 lines
9.9 KiB
NASM
|
;
|
|||
|
; 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
|
|||
|
|