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/BUF.ASM | 508 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100644 v2.0/source/BUF.ASM (limited to 'v2.0/source/BUF.ASM') diff --git a/v2.0/source/BUF.ASM b/v2.0/source/BUF.ASM new file mode 100644 index 0000000..f1ad800 --- /dev/null +++ b/v2.0/source/BUF.ASM @@ -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 -- cgit v1.2.3