mirror of
https://github.com/microsoft/MS-DOS.git
synced 2025-08-21 13:17:07 +00:00
MS-DOS v2.0 Release
This commit is contained in:
508
v2.0/source/BUF.ASM
Normal file
508
v2.0/source/BUF.ASM
Normal file
@@ -0,0 +1,508 @@
|
||||
;
|
||||
; buffer management 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
|
||||
|
||||
i_need BuffHead,DWORD
|
||||
i_need PreRead,WORD
|
||||
i_need LastBuffer,DWORD
|
||||
i_need CurBuf,DWORD
|
||||
i_need WPErr,BYTE
|
||||
|
||||
SUBTTL SETVISIT,SKIPVISIT -- MANAGE BUFFER SCANS
|
||||
PAGE
|
||||
procedure SETVISIT,near
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; None
|
||||
; Function:
|
||||
; Set up a scan of I/O buffers
|
||||
; Outputs:
|
||||
; All visit flags = 0
|
||||
; NOTE: This pre-scan is needed because a hard disk error
|
||||
; may cause a scan to stop in the middle leaving some
|
||||
; visit flags set, and some not set.
|
||||
; DS:DI Points to [BUFFHEAD]
|
||||
; No other registers altered
|
||||
|
||||
LDS DI,[BUFFHEAD]
|
||||
PUSH AX
|
||||
XOR AX,AX
|
||||
SETLOOP:
|
||||
MOV [DI.VISIT],AL
|
||||
LDS DI,[DI.NEXTBUF]
|
||||
CMP DI,-1
|
||||
JNZ SETLOOP
|
||||
LDS DI,[BUFFHEAD]
|
||||
POP AX
|
||||
return
|
||||
|
||||
entry SKIPVISIT
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; DS:DI Points to a buffer
|
||||
; Function:
|
||||
; Skip visited buffers
|
||||
; Outputs:
|
||||
; DS:DI Points to next unvisited buffer
|
||||
; Zero is set if skip to LAST buffer
|
||||
; No other registers altered
|
||||
|
||||
CMP DI,-1
|
||||
retz
|
||||
CMP [DI.VISIT],1
|
||||
retnz
|
||||
LDS DI,[DI.NEXTBUF]
|
||||
JMP SHORT SKIPVISIT
|
||||
return
|
||||
SetVisit ENDP
|
||||
|
||||
|
||||
SUBTTL SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL
|
||||
PAGE
|
||||
procedure ScanPlace,near
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Inputs:
|
||||
; Same as PLACEBUF
|
||||
; Function:
|
||||
; Save scan location and call PLACEBUF
|
||||
; Outputs:
|
||||
; DS:DI Points to saved scan location
|
||||
; SI destroyed, other registers unchanged
|
||||
|
||||
PUSH ES
|
||||
LES SI,[DI.NEXTBUF] ; Save scan location
|
||||
CALL PLACEBUF
|
||||
PUSH ES
|
||||
POP DS ; Restore scan location
|
||||
MOV DI,SI
|
||||
POP ES
|
||||
return
|
||||
ScanPlace ENDP
|
||||
|
||||
NRETJ: JMP SHORT NRET
|
||||
|
||||
procedure PLACEBUF,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Input:
|
||||
; DS:DI points to buffer
|
||||
; Function:
|
||||
; Remove buffer from queue and re-insert it in proper place.
|
||||
; If buffer doesn't go at end, and isn't free, decrement
|
||||
; priorities.
|
||||
; NO registers altered
|
||||
;
|
||||
; DS:SI -- Curbuf, current buffer in list
|
||||
; ES:DI -- Buf, buffer passed as argument
|
||||
; BP:CX -- Pointsave, saved Buf.nextbuf
|
||||
; DX:BX -- Lastbuf, previous buffer in list
|
||||
; AL -- Inserted, Buf has been inserted
|
||||
; AH -- Removed, Buf has been removed
|
||||
|
||||
IF IBM
|
||||
IF NOT IBM
|
||||
invoke save_world
|
||||
XOR AX,AX ; Inserted = Removed = FALSE
|
||||
LES CX,[DI.NEXTBUF]
|
||||
MOV BP,ES ; Pointsave = Buf.nextbuf
|
||||
MOV SI,DS
|
||||
MOV ES,SI ; Buf is ES:DI
|
||||
LDS SI,[BUFFHEAD] ; Curbuf = HEAD
|
||||
CALL POINTCOMP ; Buf == HEAD?
|
||||
JNZ TNEWHEAD
|
||||
CMP CX,-1 ; Buf is LAST?
|
||||
JZ NRETJ ; Only one buffer, nothing to do
|
||||
MOV WORD PTR [BUFFHEAD],CX
|
||||
MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
|
||||
INC AH ; Removed = TRUE
|
||||
MOV DS,BP
|
||||
MOV SI,CX ; Curbuf = HEAD
|
||||
TNEWHEAD:
|
||||
MOV BL,ES:[DI.BUFPRI]
|
||||
CMP BL,[SI.BUFPRI]
|
||||
JGE BUFLOOP
|
||||
NEWHEAD: ; If Buf.pri < HEAD.pri
|
||||
MOV WORD PTR ES:[DI.NEXTBUF],SI
|
||||
MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = HEAD
|
||||
MOV WORD PTR [BUFFHEAD],DI
|
||||
MOV WORD PTR [BUFFHEAD+2],ES ; HEAD = Buf
|
||||
INC AL ; Inserted = TRUE
|
||||
OR AH,AH
|
||||
JNZ NRET ; If Removed == TRUE
|
||||
BUFLOOP:
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
LDS SI,[SI.NEXTBUF]
|
||||
CALL POINTCOMP
|
||||
POP SI
|
||||
POP DS
|
||||
JNZ TESTINS
|
||||
MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
|
||||
MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
|
||||
INC AH ; Removed = TRUE
|
||||
OR AL,AL
|
||||
JNZ SHUFFLE ; If Inserted == TRUE
|
||||
TESTINS:
|
||||
OR AL,AL
|
||||
JNZ LOOKBUF
|
||||
PUSH CX ; If NOT Inserted
|
||||
MOV CL,ES:[DI.BUFPRI]
|
||||
CMP CL,[SI.BUFPRI]
|
||||
POP CX
|
||||
JGE LOOKBUF
|
||||
PUSH DS ; If Buf.pri < Curbuf.pri
|
||||
MOV DS,DX
|
||||
MOV WORD PTR [BX.NEXTBUF],DI
|
||||
MOV WORD PTR [BX.NEXTBUF+2],ES ; Lastbuf.nextbuf = Buf
|
||||
POP DS
|
||||
MOV WORD PTR ES:[DI.NEXTBUF],SI
|
||||
MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = Curbuf
|
||||
INC AL ; Inserted = TRUE
|
||||
OR AH,AH
|
||||
JNZ SHUFFLE ; If Removed == TRUE
|
||||
LOOKBUF:
|
||||
MOV BX,SI
|
||||
MOV DX,DS ; Lastbuf = Curbuf
|
||||
CMP WORD PTR [SI.NEXTBUF],-1
|
||||
JZ ISLAST
|
||||
LDS SI,[SI.NEXTBUF] ; Curbuf = Curbuf.nextbuf
|
||||
JMP SHORT BUFLOOP
|
||||
ISLAST: ; If Curbuf is LAST
|
||||
MOV WORD PTR [SI.NEXTBUF],DI
|
||||
MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
|
||||
MOV WORD PTR ES:[DI.NEXTBUF],-1
|
||||
MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
|
||||
NRET:
|
||||
invoke restore_world
|
||||
return
|
||||
|
||||
SHUFFLE:
|
||||
LDS DI,[BUFFHEAD]
|
||||
DECLOOP:
|
||||
CMP [DI.BUFPRI],FREEPRI
|
||||
JZ NODEC
|
||||
DEC [DI.BUFPRI]
|
||||
NODEC:
|
||||
LDS DI,[DI.NEXTBUF]
|
||||
CMP DI,-1
|
||||
JNZ DECLOOP
|
||||
JMP SHORT NRET
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
invoke save_world
|
||||
LES CX,[DI.NEXTBUF]
|
||||
CMP CX,-1 ; Buf is LAST?
|
||||
JZ NRET ; Buffer already last
|
||||
MOV BP,ES ; Pointsave = Buf.nextbuf
|
||||
PUSH DS
|
||||
POP ES ; Buf is ES:DI
|
||||
LDS SI,[BUFFHEAD] ; Curbuf = HEAD
|
||||
CALL POINTCOMP ; Buf == HEAD?
|
||||
JNZ BUFLOOP
|
||||
MOV WORD PTR [BUFFHEAD],CX
|
||||
MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
|
||||
JMP SHORT LOOKEND
|
||||
|
||||
BUFLOOP:
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
LDS SI,[SI.NEXTBUF]
|
||||
CALL POINTCOMP
|
||||
JZ GOTTHEBUF
|
||||
POP AX
|
||||
POP AX
|
||||
JMP SHORT BUFLOOP
|
||||
|
||||
GOTTHEBUF:
|
||||
POP SI
|
||||
POP DS
|
||||
MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
|
||||
MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
|
||||
LOOKEND:
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
LDS SI,[SI.NEXTBUF]
|
||||
CMP SI,-1
|
||||
JZ GOTHEEND
|
||||
POP AX
|
||||
POP AX
|
||||
JMP SHORT LOOKEND
|
||||
|
||||
GOTHEEND:
|
||||
POP SI
|
||||
POP DS
|
||||
MOV WORD PTR [SI.NEXTBUF],DI
|
||||
MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
|
||||
MOV WORD PTR ES:[DI.NEXTBUF],-1
|
||||
MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
|
||||
NRET:
|
||||
invoke restore_world
|
||||
return
|
||||
|
||||
PLACEBUF ENDP
|
||||
|
||||
procedure PLACEHEAD,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; SAME AS PLACEBUF except places buffer at head
|
||||
|
||||
invoke save_world
|
||||
PUSH DS
|
||||
POP ES
|
||||
LDS SI,[BUFFHEAD]
|
||||
MOV WORD PTR [BUFFHEAD],DI
|
||||
MOV WORD PTR [BUFFHEAD+2],ES
|
||||
MOV WORD PTR ES:[DI.NEXTBUF],SI
|
||||
MOV WORD PTR ES:[DI.NEXTBUF+2],DS
|
||||
LOOKEND2:
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
LDS SI,[SI.NEXTBUF]
|
||||
CALL POINTCOMP
|
||||
JZ GOTHEEND2
|
||||
POP AX
|
||||
POP AX
|
||||
JMP SHORT LOOKEND2
|
||||
|
||||
GOTHEEND2:
|
||||
POP SI
|
||||
POP DS
|
||||
MOV WORD PTR [SI.NEXTBUF],-1
|
||||
MOV WORD PTR [SI.NEXTBUF+2],-1 ; Buf is LAST
|
||||
JMP SHORT NRET
|
||||
|
||||
PLACEHEAD ENDP
|
||||
|
||||
SUBTTL POINTCOMP -- 20 BIT POINTER COMPARE
|
||||
PAGE
|
||||
procedure PointComp,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality
|
||||
; DO NOT USE FOR < or >
|
||||
; No Registers altered
|
||||
|
||||
CMP SI,DI
|
||||
retnz
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
MOV CX,DS
|
||||
MOV DX,ES
|
||||
CMP CX,DX
|
||||
POP DX
|
||||
POP CX
|
||||
return
|
||||
PointComp ENDP
|
||||
|
||||
SUBTTL GETBUFFR -- GET A SECTOR INTO A BUFFER
|
||||
PAGE
|
||||
procedure GETBUFFR,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Input:
|
||||
; AH = Priority buffer is to have
|
||||
; AL = 0 means sector must be pre-read
|
||||
; ELSE no pre-read
|
||||
; DX = Desired physical sector number
|
||||
; ES:BP = Pointer to drive parameters
|
||||
; Function:
|
||||
; Get the specified sector into one of the I/O buffers
|
||||
; And shuffle the queue
|
||||
; Output:
|
||||
; [CURBUF] Points to the Buffer for the sector
|
||||
; DX,ES:BP unchanged, all other registers destroyed
|
||||
|
||||
XOR SI,SI
|
||||
entry GETBUFFRB
|
||||
MOV [PREREAD],AX
|
||||
MOV AL,ES:[BP.dpb_drive]
|
||||
LDS DI,[LASTBUFFER]
|
||||
ASSUME DS:NOTHING
|
||||
CMP DI,-1 ; Recency pointer valid?
|
||||
JZ SKBUF ; No
|
||||
CMP DX,[DI.BUFSECNO]
|
||||
JNZ SKBUF ; Wrong sector
|
||||
CMP AL,[DI.BUFDRV]
|
||||
JNZ SKBUF ; Wrong Drive
|
||||
JMP SHORT JUSTBUF ; Just asked for same buffer
|
||||
SKBUF:
|
||||
LDS DI,[BUFFHEAD]
|
||||
NXTBFF:
|
||||
CMP DX,[DI.BUFSECNO]
|
||||
JNZ BUMP
|
||||
CMP AL,[DI.BUFDRV]
|
||||
JNZ BUMP
|
||||
JMP SHORT SETINF
|
||||
BUMP:
|
||||
LDS DI,[DI.NEXTBUF]
|
||||
CMP DI,-1
|
||||
JNZ NXTBFF
|
||||
LDS DI,[BUFFHEAD]
|
||||
PUSH SI
|
||||
PUSH DX
|
||||
PUSH BP
|
||||
PUSH ES
|
||||
CALL BUFWRITE ; Write out the dirty buffer
|
||||
POP ES
|
||||
POP BP
|
||||
POP DX
|
||||
POP SI
|
||||
RDSEC: ; Read in the new sector
|
||||
TEST BYTE PTR [PREREAD],-1
|
||||
JNZ SETBUF
|
||||
LEA BX,[DI.BufInSiz] ; Point at buffer
|
||||
MOV CX,1
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH DX
|
||||
OR SI,SI
|
||||
JZ NORMSEC
|
||||
invoke FATSECRD
|
||||
JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs
|
||||
NORMSEC:
|
||||
invoke DREAD ; Buffer is marked free if read barfs
|
||||
GOTTHESEC:
|
||||
POP DX
|
||||
POP DI
|
||||
POP SI
|
||||
SETBUF:
|
||||
MOV [DI.BUFSECNO],DX
|
||||
MOV WORD PTR [DI.BUFDRVDP],BP
|
||||
MOV WORD PTR [DI.BUFDRVDP+2],ES
|
||||
XOR AH,AH
|
||||
MOV AL,ES:[BP.dpb_drive]
|
||||
MOV WORD PTR [DI.BUFDRV],AX
|
||||
SETINF:
|
||||
MOV AX,1 ; Default to not a FAT sector
|
||||
OR SI,SI
|
||||
JZ SETSTUFFOK
|
||||
MOV AL,ES:[BP.dpb_FAT_count]
|
||||
MOV AH,ES:[BP.dpb_FAT_size]
|
||||
SETSTUFFOK:
|
||||
MOV WORD PTR [DI.BUFWRTCNT],AX
|
||||
CALL PLACEBUF
|
||||
JUSTBUF:
|
||||
MOV WORD PTR [CURBUF+2],DS
|
||||
MOV WORD PTR [LASTBUFFER+2],DS
|
||||
PUSH SS
|
||||
POP DS
|
||||
ASSUME DS:DOSGROUP
|
||||
MOV WORD PTR [CURBUF],DI
|
||||
MOV WORD PTR [LASTBUFFER],DI
|
||||
return
|
||||
GETBUFFR ENDP
|
||||
|
||||
|
||||
SUBTTL FLUSHBUF -- WRITE OUT DIRTY BUFFERS
|
||||
PAGE
|
||||
procedure FlushBuf,NEAR
|
||||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||||
|
||||
; Input:
|
||||
; DS = DOSGROUP
|
||||
; AL = Physical unit number
|
||||
; = -1 for all units
|
||||
; Function:
|
||||
; Write out all dirty buffers for unit, and flag them as clean
|
||||
; DS Preserved, all others destroyed (ES too)
|
||||
|
||||
LDS DI,[BUFFHEAD]
|
||||
ASSUME DS:NOTHING
|
||||
MOV AH,-1
|
||||
NXTBUFF:
|
||||
CMP [DI.BUFDRV],AH
|
||||
JZ SKIPBFF ; Skip free buffers
|
||||
CMP AH,AL
|
||||
JZ DOBUFFER ; Do all dirty buffers
|
||||
CMP AL,[DI.BUFDRV]
|
||||
JNZ SKIPBFF ; Buffer not for this unit
|
||||
DOBUFFER:
|
||||
CMP BYTE PTR [DI.BUFDIRTY],0
|
||||
JZ SKIPBFF ; Buffer not dirty
|
||||
PUSH AX
|
||||
PUSH WORD PTR [DI.BUFDRV]
|
||||
CALL BUFWRITE
|
||||
POP AX
|
||||
XOR AH,AH ; Buffer is clean
|
||||
CMP AL,BYTE PTR [WPERR]
|
||||
JNZ NOZAP
|
||||
MOV AL,0FFH ; Invalidate buffer, it is inconsistent
|
||||
NOZAP:
|
||||
MOV WORD PTR [DI.BUFDRV],AX
|
||||
POP AX ; Search info
|
||||
SKIPBFF:
|
||||
LDS DI,[DI.NEXTBUF]
|
||||
CMP DI,-1
|
||||
JNZ NXTBUFF
|
||||
PUSH SS
|
||||
POP DS
|
||||
return
|
||||
FlushBuf ENDP
|
||||
|
||||
|
||||
SUBTTL BUFWRITE -- WRITE OUT A BUFFER IF DIRTY
|
||||
PAGE
|
||||
procedure BufWrite,NEAR
|
||||
ASSUME DS:NOTHING,ES:NOTHING
|
||||
|
||||
; Input:
|
||||
; DS:DI Points to the buffer
|
||||
; Function:
|
||||
; Write out all the buffer if dirty.
|
||||
; Output:
|
||||
; Buffer marked free
|
||||
; DS:DI Preserved, ALL others destroyed (ES too)
|
||||
|
||||
MOV AX,00FFH
|
||||
XCHG AX,WORD PTR [DI.BUFDRV] ; Free, in case write barfs
|
||||
CMP AL,0FFH
|
||||
retz ; Buffer is free.
|
||||
OR AH,AH
|
||||
retz ; Buffer is clean.
|
||||
CMP AL,BYTE PTR [WPERR]
|
||||
retz ; If in WP error zap buffer
|
||||
LES BP,[DI.BUFDRVDP]
|
||||
LEA BX,[DI.BufInSiz] ; Point at buffer
|
||||
MOV DX,[DI.BUFSECNO]
|
||||
MOV CX,WORD PTR [DI.BUFWRTCNT]
|
||||
MOV AL,CH ; [DI.BUFWRTINC]
|
||||
XOR CH,CH
|
||||
MOV AH,CH
|
||||
PUSH DI
|
||||
WRTAGAIN:
|
||||
PUSH CX
|
||||
PUSH AX
|
||||
MOV CX,1
|
||||
PUSH BX
|
||||
PUSH DX
|
||||
invoke DWRITE ; Write out the dirty buffer
|
||||
POP DX
|
||||
POP BX
|
||||
POP AX
|
||||
POP CX
|
||||
ADD DX,AX
|
||||
LOOP WRTAGAIN
|
||||
POP DI
|
||||
return
|
||||
BufWrite ENDP
|
||||
|
||||
do_ext
|
||||
|
||||
CODE ENDS
|
||||
END
|
Reference in New Issue
Block a user