📄 disk3.asm
字号:
page ,164
TITLE DISK3 - Disk utility routines
NAME Disk3
;
; Microsoft Confidential
; Copyright (C) Microsoft Corporation 1991
; All Rights Reserved.
;
;** Low level Read and write routines for local SFT I/O on files and devs
;
; DISKWRITE
; WRTERR
;
; Revision history:
;
; 1. AN000 version 4.00 Jan. 1988
; 2. SR; 10/12/89; Fixed bug in DISKWRITE that caused incorrect
; calculation of filesizes when they cross the 32M boundary
; if the filesize is not a multiple of 512 bytes
; AN002 - Sept. 1988, PTM#4977 fix (writing cluster bug) Bill Lawton
; M017 MD 8/30/90 - Rewrite SHR32 for better speed
; M039 DB 10/17/90 - Disk write optimization
.xlist
.xcref
include version.inc
include dosseg.inc
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
include dpb.inc
include sf.inc
include dosmac.inc ;M039
.cref
.list
Installed = TRUE
i_need READOP,BYTE
i_need DISK_FULL,BYTE
i_need THISSFT,DWORD
i_need DMAADD,DWORD
i_need SecClusPos,BYTE
i_need ClusNum,WORD
i_need Trans,BYTE
i_need BytPos,4
i_need SecPos,DWORD ;F.C. >32mb ;AN000;
i_need BytSecPos,WORD
i_need BytCnt1,WORD
i_need BytCnt2,WORD
i_need SecCnt,WORD
i_need ThisDPB,DWORD
i_need LastPos,WORD
i_need ValSec,WORD ;F.C. >32mb ;AN000;
i_need GrowCnt,DWORD
i_need ALLOWED,BYTE
I_need JShare,DWORD
I_need HIGH_SECTOR,WORD ;F.C. >32mb ;AN000;
; I_need HIGH_SECTOR_TEMP,WORD ;M039: Removed; F.C. >32mb ;AN000;
I_need EXTERR,WORD ; DOS 4.00 ;AN000;
I_need EXTERR_LOCUS,BYTE ; DOS 4.00 ;AN000;
I_need EXTERR_ACTION,BYTE ; DOS 4.00 ;AN000;
I_need EXTERR_CLASS,BYTE ; DOS 4.00 ;AN000;
I_need EXITHOLD,DWORD ; DOS 4.00 ;AN000;
;**RMFHFE** I_need DISK_FULL,BYTE ; DOS 4.00 ;AN000;
I_need SC_DRIVE,BYTE ; DOS 4.00 ;AN000;
I_need SC_CACHE_COUNT,WORD ; DOS 4.00 ;AN000;
I_need SC_STATUS,WORD ;M039
I_need CURSC_SECTOR,WORD ;M039
I_need CURSC_DRIVE,BYTE ;M039
I_need ThisDRV,BYTE ; DOS 4.00 ;AN000;
I_need User_In_AX,WORD ; DOS 4.00 ;AN000;
I_need DOS34_FLAG,WORD ; DOS 4.00 ;AN000;
I_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 ;AN000;
I_need TEMP_VAR,WORD ;M039
I_need TEMP_VAR2,WORD ;M039
DOSCODE Segment
ASSUME SS:DOSDATA,CS:DOSCODE
Break <DISKWRITE -- PERFORM USER DISK WRITE>
;----------------------------------------------------------------------------
;
; Procedure Name : DISKWRITE
;
; Inputs:
; Outputs of SETUP
; Function:
; Perform disk write
; Outputs:
; Carry clear
; CX = No. of bytes read
; ES:DI point to SFT
; SFT offset and cluster pointers updated
; Carry set
; CX = 0
; ES:DI point to SFT
; AX has error code
;----------------------------------------------------------------------------
;hkn; called by DOS_WRITE. DS already set up at this point.
procedure DISKWRITE,NEAR
DOSAssume <DS>,"DiskWrite"
Assert ISSFT,<ES,DI>,"DiskWrite"
invoke CHECK_WRITE_LOCK ;IFS. check write lock ;AN000;
JNC WRITE_OK ;IFS. lock check ok ;AN000;
return
WRTEOFJ:
JMP WRTEOF
WRITE_OK:
AND ES:[DI].SF_FLAGS,NOT (sf_close_nodate OR devid_file_clean)
; Mark file as dirty, clear no date on close
MOV AX,WORD PTR ES:[DI.sf_size] ;M039
MOV [TEMP_VAR],AX ;M039
MOV AX,WORD PTR ES:[DI.sf_size+2] ;M039
MOV [TEMP_VAR2],AX ;M039
; TEMP_VAR2:TEMP_VAR = Current file size (sf_size);M039
LES BP,[THISDPB]
Assert ISDPB,<ES,BP>,"DiskWrite/WriteOk"
invoke BREAKDOWN
MOV AX,WORD PTR [BYTPOS]
MOV DX,WORD PTR [BYTPOS+2]
JCXZ WRTEOFJ ;Make the file length = sf_position
ADD AX,CX
ADC DX,0 ;DX:AX = last byte to write + 1.
MOV BX,ES:[BP.dpb_sector_size]
CALL DIV32 ;DX:AX/BX = CX:AX + DX (rem.).
MOV SI,AX
MOV [HIGH_SECTOR],CX
; [HIGH_SECTOR]:SI = Last full sector to write.
OR DX,DX
PUSH DX ;M039: Free DX for use by SHR32
MOV DX,CX ;M039
JNZ CALCLUS
SUB AX,1 ;AX must be zero base indexed ;AC000;
SBB DX,0 ;M039 ;F.C. >32mb ;AN000;
CALCLUS:
CALL SHR32 ;F.C. >32mb ;AN000;
POP DX
; AX = Last cluster to write.
; DX = # of bytes in last sector to write (the "tail").
; BX = ES:[BP.dpb_sector_size]
PUSH AX
PUSH DX
;M039
mov dx,[TEMP_VAR2]
mov ax,[TEMP_VAR] ;DX:AX = current file size (in bytes).
call DIV32 ;DX:AX/BX = CX:AX + DX (rem.)
mov [TEMP_VAR2],cx
mov [VALSEC+2],cx
mov cx,ax
mov bx,si
; [HIGH_SECTOR]:BX = Last full sector to write.
; [VALSEC+2]:CX = Last full sector of current file.
; [TEMP_VAR2]:CX = Last full sector of current file.
; DX = # of bytes in last sector of current file.
;M039
OR DX,DX
JZ NORND
ADD AX,1 ;Round up if any remainder ;AC000;
ADC [VALSEC+2],0
NORND: MOV WORD PTR [VALSEC],AX
; [VALSEC] = Last sector of current file.
XOR AX,AX
MOV WORD PTR [GROWCNT],AX
MOV WORD PTR [GROWCNT+2],AX
POP AX
MOV DI,[HIGH_SECTOR] ;F.C. >32mb ;AN000;
CMP DI,[TEMP_VAR2] ;M039; F.C. >32mb ;AN000;
DLJB NOGROW ;F.C. >32mb ;AN000;
JZ lowsec ;F.C. >32mb ;AN000;
SUB BX,CX ;F.C. >32mb ;AN000;
SBB DI,[TEMP_VAR2] ;M039; F.C. >32mb di:bx no. of sectors ;AN000;
JMP short yesgrow ;F.C. >32mb ;AN000;
lowsec:
MOV DI,0 ;F.C. >32mb
SUB BX,CX ; Number of full sectors
JB NOGROW
JZ TESTTAIL
yesgrow:
MOV CX,DX
XCHG AX,BX
MUL ES:[BP.dpb_sector_size] ; Bytes of full sector growth
MOV [HIGH_SECTOR],DX ;F.C. >32mb save dx ;AN000;
MOV [TEMP_VAR2],AX ;M039; F.C. >32mb save ax ;AN000;
MOV AX,DI ;F.C. >32mb ;AN000;
MUL ES:[BP.dpb_sector_size] ;F.C. >32mb do higher word multiply ;AN000;
ADD AX,[HIGH_SECTOR] ;F.C. >32mb add lower value ;AN000;
MOV DX,AX ;F.C. >32mb DX:AX is the result of ;AN000;
MOV AX,[TEMP_VAR2] ;M039; F.C. >32mb a 32 bit multiply ;AN000;
SUB AX,CX ; Take off current "tail"
SBB DX,0 ; 32-bit extension
ADD AX,BX ; Add on new "tail"
ADC DX,0 ; ripple tim's head off
JMP SHORT SETGRW
HAVSTART:
;int 3
MOV CX,AX
invoke SKPCLP
JCXZ DOWRTJ
invoke ALLOCATE
JNC DOWRTJ
entry WRTERR
DOSAssume <DS>,"DiskWrite/WrtErr"
ASSUME ES:NOTHING
MOV AH,0FH ;MS. write/data/fail/abort ;AN000;
entry WRTERR22
MOV AL,[THISDRV] ;MS. ;AN000;
;**RMFHFE** CALL File_Handle_Fail_Error ;MS. issue disk full I24
;**RMFHFE** MOV CX,0 ;No bytes transferred
XOR CX,CX ; will be deleted
LES DI,[THISSFT]
Assert ISSFT,<ES,DI>,"DiskWrite/WrtErr"
CLC
return
DOWRTJ: JMP short DOWRT
ACC_ERRWJ:
JMP SET_ACC_ERRW
TESTTAIL:
SUB AX,DX
JBE NOGROW
XOR DX,DX
SETGRW:
MOV WORD PTR [GROWCNT],AX
MOV WORD PTR [GROWCNT+2],DX
NOGROW:
POP AX
MOV CX,[CLUSNUM] ; First cluster accessed
invoke FNDCLUS
JC ACC_ERRWJ
MOV [CLUSNUM],BX
MOV [LASTPOS],DX
SUB AX,DX ; Last cluster minus current cluster
JZ DOWRT ; If we have last clus, we must have first
JCXZ HAVSTART ; See if no more data
PUSH CX ; No. of clusters short of first
MOV CX,AX
invoke ALLOCATE
POP CX
JC WRTERR
MOV DX,[LASTPOS]
INC DX
DEC CX
JZ NOSKIP
invoke SKPCLP
JC ACC_ERRWJ
NOSKIP:
MOV [CLUSNUM],BX
MOV [LASTPOS],DX
DOWRT:
CMP [BYTCNT1],0
JZ WRTMID
MOV BX,[CLUSNUM]
invoke BUFWRT
JC ACC_ERRWJ
WRTMID:
MOV AX,[SECCNT]
OR AX,AX
JZ WRTLAST ;M039
ADD WORD PTR [SECPOS],AX
ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000;
invoke NEXTSEC
JC SET_ACC_ERRW ;M039
MOV BYTE PTR [TRANS],1 ; A transfer is taking place
MOV DL,[SECCLUSPOS]
MOV BX,[CLUSNUM]
MOV CX,[SECCNT]
WRTLP:
invoke OPTIMIZE
JC SET_ACC_ERRW
;M039
; DI = Next physical cluster.
; AX = # sectors remaining.
; [DMAADD+2]:BX = transfer address (source data address).
; CX = # of contiguous sectors to write. (These constitute a block of
; sectors, also termed an "Extent".)
; [HIGH_SECTOR]:DX = physical sector # of first sector in extent.
; ES:BP -> Drive Parameter Block (DPB).
;
; Purge the Buffer Queue and the Secondary Cache of any buffers which
; are in Extent; they are being over-written.
push di
push ax
call DskWrtBufPurge ;DS trashed.
ASSUME DS:NOTHING
;M039
;hkn; SS override for DMAADD and ALLOWED
MOV DS,WORD PTR [DMAADD+2]
MOV [ALLOWED],allowed_RETRY + allowed_FAIL + allowed_IGNORE
; put logic from DWRITE in-line here so we can modify it
; for DISK FULL conditions.
DWRITE_LUP:
invoke DSKWRITE
jz DWRITE_OKAY
; int 3
cmp al,error_handle_Disk_Full ; compressed volume full?
jz DWRITE_DISK_FULL
;hkn; SS override
MOV BYTE PTR [READOP],1
invoke HARDERRRW
CMP AL,1 ; Check for retry
JZ DWRITE_LUP
CMP AL,3 ; Check for FAIL
CLC
JNZ DWRITE_OKAY ; Ignore
STC
DWRITE_OKAY:
POP CX
POP BX
; CX = # sectors remaining.
; BX = Next physical cluster.
;hkn; SS override
Context DS
JC SET_ACC_ERRW
JCXZ WRTLAST
MOV DL,0
INC [LASTPOS] ; We'll be using next cluster
JMP WRTLP
DWRITE_DISK_FULL:
Context DS ;SQ 3-5-93 DS must be setup on return!
pop cx ; unjunk stack
pop bx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -