diff options
Diffstat (limited to 'v2.0/source/BUF.ASM')
| -rw-r--r-- | v2.0/source/BUF.ASM | 508 |
1 files changed, 508 insertions, 0 deletions
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 @@ | |||
| 1 | ; | ||
| 2 | ; buffer management for MSDOS | ||
| 3 | ; | ||
| 4 | |||
| 5 | INCLUDE DOSSEG.ASM | ||
| 6 | |||
| 7 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 8 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 9 | |||
| 10 | .xlist | ||
| 11 | .xcref | ||
| 12 | INCLUDE DOSSYM.ASM | ||
| 13 | INCLUDE DEVSYM.ASM | ||
| 14 | .cref | ||
| 15 | .list | ||
| 16 | |||
| 17 | i_need BuffHead,DWORD | ||
| 18 | i_need PreRead,WORD | ||
| 19 | i_need LastBuffer,DWORD | ||
| 20 | i_need CurBuf,DWORD | ||
| 21 | i_need WPErr,BYTE | ||
| 22 | |||
| 23 | SUBTTL SETVISIT,SKIPVISIT -- MANAGE BUFFER SCANS | ||
| 24 | PAGE | ||
| 25 | procedure SETVISIT,near | ||
| 26 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 27 | |||
| 28 | ; Inputs: | ||
| 29 | ; None | ||
| 30 | ; Function: | ||
| 31 | ; Set up a scan of I/O buffers | ||
| 32 | ; Outputs: | ||
| 33 | ; All visit flags = 0 | ||
| 34 | ; NOTE: This pre-scan is needed because a hard disk error | ||
| 35 | ; may cause a scan to stop in the middle leaving some | ||
| 36 | ; visit flags set, and some not set. | ||
| 37 | ; DS:DI Points to [BUFFHEAD] | ||
| 38 | ; No other registers altered | ||
| 39 | |||
| 40 | LDS DI,[BUFFHEAD] | ||
| 41 | PUSH AX | ||
| 42 | XOR AX,AX | ||
| 43 | SETLOOP: | ||
| 44 | MOV [DI.VISIT],AL | ||
| 45 | LDS DI,[DI.NEXTBUF] | ||
| 46 | CMP DI,-1 | ||
| 47 | JNZ SETLOOP | ||
| 48 | LDS DI,[BUFFHEAD] | ||
| 49 | POP AX | ||
| 50 | return | ||
| 51 | |||
| 52 | entry SKIPVISIT | ||
| 53 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 54 | |||
| 55 | ; Inputs: | ||
| 56 | ; DS:DI Points to a buffer | ||
| 57 | ; Function: | ||
| 58 | ; Skip visited buffers | ||
| 59 | ; Outputs: | ||
| 60 | ; DS:DI Points to next unvisited buffer | ||
| 61 | ; Zero is set if skip to LAST buffer | ||
| 62 | ; No other registers altered | ||
| 63 | |||
| 64 | CMP DI,-1 | ||
| 65 | retz | ||
| 66 | CMP [DI.VISIT],1 | ||
| 67 | retnz | ||
| 68 | LDS DI,[DI.NEXTBUF] | ||
| 69 | JMP SHORT SKIPVISIT | ||
| 70 | return | ||
| 71 | SetVisit ENDP | ||
| 72 | |||
| 73 | |||
| 74 | SUBTTL SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL | ||
| 75 | PAGE | ||
| 76 | procedure ScanPlace,near | ||
| 77 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 78 | |||
| 79 | ; Inputs: | ||
| 80 | ; Same as PLACEBUF | ||
| 81 | ; Function: | ||
| 82 | ; Save scan location and call PLACEBUF | ||
| 83 | ; Outputs: | ||
| 84 | ; DS:DI Points to saved scan location | ||
| 85 | ; SI destroyed, other registers unchanged | ||
| 86 | |||
| 87 | PUSH ES | ||
| 88 | LES SI,[DI.NEXTBUF] ; Save scan location | ||
| 89 | CALL PLACEBUF | ||
| 90 | PUSH ES | ||
| 91 | POP DS ; Restore scan location | ||
| 92 | MOV DI,SI | ||
| 93 | POP ES | ||
| 94 | return | ||
| 95 | ScanPlace ENDP | ||
| 96 | |||
| 97 | NRETJ: JMP SHORT NRET | ||
| 98 | |||
| 99 | procedure PLACEBUF,NEAR | ||
| 100 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 101 | |||
| 102 | ; Input: | ||
| 103 | ; DS:DI points to buffer | ||
| 104 | ; Function: | ||
| 105 | ; Remove buffer from queue and re-insert it in proper place. | ||
| 106 | ; If buffer doesn't go at end, and isn't free, decrement | ||
| 107 | ; priorities. | ||
| 108 | ; NO registers altered | ||
| 109 | ; | ||
| 110 | ; DS:SI -- Curbuf, current buffer in list | ||
| 111 | ; ES:DI -- Buf, buffer passed as argument | ||
| 112 | ; BP:CX -- Pointsave, saved Buf.nextbuf | ||
| 113 | ; DX:BX -- Lastbuf, previous buffer in list | ||
| 114 | ; AL -- Inserted, Buf has been inserted | ||
| 115 | ; AH -- Removed, Buf has been removed | ||
| 116 | |||
| 117 | IF IBM | ||
| 118 | IF NOT IBM | ||
| 119 | invoke save_world | ||
| 120 | XOR AX,AX ; Inserted = Removed = FALSE | ||
| 121 | LES CX,[DI.NEXTBUF] | ||
| 122 | MOV BP,ES ; Pointsave = Buf.nextbuf | ||
| 123 | MOV SI,DS | ||
| 124 | MOV ES,SI ; Buf is ES:DI | ||
| 125 | LDS SI,[BUFFHEAD] ; Curbuf = HEAD | ||
| 126 | CALL POINTCOMP ; Buf == HEAD? | ||
| 127 | JNZ TNEWHEAD | ||
| 128 | CMP CX,-1 ; Buf is LAST? | ||
| 129 | JZ NRETJ ; Only one buffer, nothing to do | ||
| 130 | MOV WORD PTR [BUFFHEAD],CX | ||
| 131 | MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave | ||
| 132 | INC AH ; Removed = TRUE | ||
| 133 | MOV DS,BP | ||
| 134 | MOV SI,CX ; Curbuf = HEAD | ||
| 135 | TNEWHEAD: | ||
| 136 | MOV BL,ES:[DI.BUFPRI] | ||
| 137 | CMP BL,[SI.BUFPRI] | ||
| 138 | JGE BUFLOOP | ||
| 139 | NEWHEAD: ; If Buf.pri < HEAD.pri | ||
| 140 | MOV WORD PTR ES:[DI.NEXTBUF],SI | ||
| 141 | MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = HEAD | ||
| 142 | MOV WORD PTR [BUFFHEAD],DI | ||
| 143 | MOV WORD PTR [BUFFHEAD+2],ES ; HEAD = Buf | ||
| 144 | INC AL ; Inserted = TRUE | ||
| 145 | OR AH,AH | ||
| 146 | JNZ NRET ; If Removed == TRUE | ||
| 147 | BUFLOOP: | ||
| 148 | PUSH DS | ||
| 149 | PUSH SI | ||
| 150 | LDS SI,[SI.NEXTBUF] | ||
| 151 | CALL POINTCOMP | ||
| 152 | POP SI | ||
| 153 | POP DS | ||
| 154 | JNZ TESTINS | ||
| 155 | MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf | ||
| 156 | MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave | ||
| 157 | INC AH ; Removed = TRUE | ||
| 158 | OR AL,AL | ||
| 159 | JNZ SHUFFLE ; If Inserted == TRUE | ||
| 160 | TESTINS: | ||
| 161 | OR AL,AL | ||
| 162 | JNZ LOOKBUF | ||
| 163 | PUSH CX ; If NOT Inserted | ||
| 164 | MOV CL,ES:[DI.BUFPRI] | ||
| 165 | CMP CL,[SI.BUFPRI] | ||
| 166 | POP CX | ||
| 167 | JGE LOOKBUF | ||
| 168 | PUSH DS ; If Buf.pri < Curbuf.pri | ||
| 169 | MOV DS,DX | ||
| 170 | MOV WORD PTR [BX.NEXTBUF],DI | ||
| 171 | MOV WORD PTR [BX.NEXTBUF+2],ES ; Lastbuf.nextbuf = Buf | ||
| 172 | POP DS | ||
| 173 | MOV WORD PTR ES:[DI.NEXTBUF],SI | ||
| 174 | MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = Curbuf | ||
| 175 | INC AL ; Inserted = TRUE | ||
| 176 | OR AH,AH | ||
| 177 | JNZ SHUFFLE ; If Removed == TRUE | ||
| 178 | LOOKBUF: | ||
| 179 | MOV BX,SI | ||
| 180 | MOV DX,DS ; Lastbuf = Curbuf | ||
| 181 | CMP WORD PTR [SI.NEXTBUF],-1 | ||
| 182 | JZ ISLAST | ||
| 183 | LDS SI,[SI.NEXTBUF] ; Curbuf = Curbuf.nextbuf | ||
| 184 | JMP SHORT BUFLOOP | ||
| 185 | ISLAST: ; If Curbuf is LAST | ||
| 186 | MOV WORD PTR [SI.NEXTBUF],DI | ||
| 187 | MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf | ||
| 188 | MOV WORD PTR ES:[DI.NEXTBUF],-1 | ||
| 189 | MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST | ||
| 190 | NRET: | ||
| 191 | invoke restore_world | ||
| 192 | return | ||
| 193 | |||
| 194 | SHUFFLE: | ||
| 195 | LDS DI,[BUFFHEAD] | ||
| 196 | DECLOOP: | ||
| 197 | CMP [DI.BUFPRI],FREEPRI | ||
| 198 | JZ NODEC | ||
| 199 | DEC [DI.BUFPRI] | ||
| 200 | NODEC: | ||
| 201 | LDS DI,[DI.NEXTBUF] | ||
| 202 | CMP DI,-1 | ||
| 203 | JNZ DECLOOP | ||
| 204 | JMP SHORT NRET | ||
| 205 | ENDIF | ||
| 206 | ENDIF | ||
| 207 | |||
| 208 | invoke save_world | ||
| 209 | LES CX,[DI.NEXTBUF] | ||
| 210 | CMP CX,-1 ; Buf is LAST? | ||
| 211 | JZ NRET ; Buffer already last | ||
| 212 | MOV BP,ES ; Pointsave = Buf.nextbuf | ||
| 213 | PUSH DS | ||
| 214 | POP ES ; Buf is ES:DI | ||
| 215 | LDS SI,[BUFFHEAD] ; Curbuf = HEAD | ||
| 216 | CALL POINTCOMP ; Buf == HEAD? | ||
| 217 | JNZ BUFLOOP | ||
| 218 | MOV WORD PTR [BUFFHEAD],CX | ||
| 219 | MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave | ||
| 220 | JMP SHORT LOOKEND | ||
| 221 | |||
| 222 | BUFLOOP: | ||
| 223 | PUSH DS | ||
| 224 | PUSH SI | ||
| 225 | LDS SI,[SI.NEXTBUF] | ||
| 226 | CALL POINTCOMP | ||
| 227 | JZ GOTTHEBUF | ||
| 228 | POP AX | ||
| 229 | POP AX | ||
| 230 | JMP SHORT BUFLOOP | ||
| 231 | |||
| 232 | GOTTHEBUF: | ||
| 233 | POP SI | ||
| 234 | POP DS | ||
| 235 | MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf | ||
| 236 | MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave | ||
| 237 | LOOKEND: | ||
| 238 | PUSH DS | ||
| 239 | PUSH SI | ||
| 240 | LDS SI,[SI.NEXTBUF] | ||
| 241 | CMP SI,-1 | ||
| 242 | JZ GOTHEEND | ||
| 243 | POP AX | ||
| 244 | POP AX | ||
| 245 | JMP SHORT LOOKEND | ||
| 246 | |||
| 247 | GOTHEEND: | ||
| 248 | POP SI | ||
| 249 | POP DS | ||
| 250 | MOV WORD PTR [SI.NEXTBUF],DI | ||
| 251 | MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf | ||
| 252 | MOV WORD PTR ES:[DI.NEXTBUF],-1 | ||
| 253 | MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST | ||
| 254 | NRET: | ||
| 255 | invoke restore_world | ||
| 256 | return | ||
| 257 | |||
| 258 | PLACEBUF ENDP | ||
| 259 | |||
| 260 | procedure PLACEHEAD,NEAR | ||
| 261 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 262 | |||
| 263 | ; SAME AS PLACEBUF except places buffer at head | ||
| 264 | |||
| 265 | invoke save_world | ||
| 266 | PUSH DS | ||
| 267 | POP ES | ||
| 268 | LDS SI,[BUFFHEAD] | ||
| 269 | MOV WORD PTR [BUFFHEAD],DI | ||
| 270 | MOV WORD PTR [BUFFHEAD+2],ES | ||
| 271 | MOV WORD PTR ES:[DI.NEXTBUF],SI | ||
| 272 | MOV WORD PTR ES:[DI.NEXTBUF+2],DS | ||
| 273 | LOOKEND2: | ||
| 274 | PUSH DS | ||
| 275 | PUSH SI | ||
| 276 | LDS SI,[SI.NEXTBUF] | ||
| 277 | CALL POINTCOMP | ||
| 278 | JZ GOTHEEND2 | ||
| 279 | POP AX | ||
| 280 | POP AX | ||
| 281 | JMP SHORT LOOKEND2 | ||
| 282 | |||
| 283 | GOTHEEND2: | ||
| 284 | POP SI | ||
| 285 | POP DS | ||
| 286 | MOV WORD PTR [SI.NEXTBUF],-1 | ||
| 287 | MOV WORD PTR [SI.NEXTBUF+2],-1 ; Buf is LAST | ||
| 288 | JMP SHORT NRET | ||
| 289 | |||
| 290 | PLACEHEAD ENDP | ||
| 291 | |||
| 292 | SUBTTL POINTCOMP -- 20 BIT POINTER COMPARE | ||
| 293 | PAGE | ||
| 294 | procedure PointComp,NEAR | ||
| 295 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 296 | |||
| 297 | ; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality | ||
| 298 | ; DO NOT USE FOR < or > | ||
| 299 | ; No Registers altered | ||
| 300 | |||
| 301 | CMP SI,DI | ||
| 302 | retnz | ||
| 303 | PUSH CX | ||
| 304 | PUSH DX | ||
| 305 | MOV CX,DS | ||
| 306 | MOV DX,ES | ||
| 307 | CMP CX,DX | ||
| 308 | POP DX | ||
| 309 | POP CX | ||
| 310 | return | ||
| 311 | PointComp ENDP | ||
| 312 | |||
| 313 | SUBTTL GETBUFFR -- GET A SECTOR INTO A BUFFER | ||
| 314 | PAGE | ||
| 315 | procedure GETBUFFR,NEAR | ||
| 316 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 317 | |||
| 318 | ; Input: | ||
| 319 | ; AH = Priority buffer is to have | ||
| 320 | ; AL = 0 means sector must be pre-read | ||
| 321 | ; ELSE no pre-read | ||
| 322 | ; DX = Desired physical sector number | ||
| 323 | ; ES:BP = Pointer to drive parameters | ||
| 324 | ; Function: | ||
| 325 | ; Get the specified sector into one of the I/O buffers | ||
| 326 | ; And shuffle the queue | ||
| 327 | ; Output: | ||
| 328 | ; [CURBUF] Points to the Buffer for the sector | ||
| 329 | ; DX,ES:BP unchanged, all other registers destroyed | ||
| 330 | |||
| 331 | XOR SI,SI | ||
| 332 | entry GETBUFFRB | ||
| 333 | MOV [PREREAD],AX | ||
| 334 | MOV AL,ES:[BP.dpb_drive] | ||
| 335 | LDS DI,[LASTBUFFER] | ||
| 336 | ASSUME DS:NOTHING | ||
| 337 | CMP DI,-1 ; Recency pointer valid? | ||
| 338 | JZ SKBUF ; No | ||
| 339 | CMP DX,[DI.BUFSECNO] | ||
| 340 | JNZ SKBUF ; Wrong sector | ||
| 341 | CMP AL,[DI.BUFDRV] | ||
| 342 | JNZ SKBUF ; Wrong Drive | ||
| 343 | JMP SHORT JUSTBUF ; Just asked for same buffer | ||
| 344 | SKBUF: | ||
| 345 | LDS DI,[BUFFHEAD] | ||
| 346 | NXTBFF: | ||
| 347 | CMP DX,[DI.BUFSECNO] | ||
| 348 | JNZ BUMP | ||
| 349 | CMP AL,[DI.BUFDRV] | ||
| 350 | JNZ BUMP | ||
| 351 | JMP SHORT SETINF | ||
| 352 | BUMP: | ||
| 353 | LDS DI,[DI.NEXTBUF] | ||
| 354 | CMP DI,-1 | ||
| 355 | JNZ NXTBFF | ||
| 356 | LDS DI,[BUFFHEAD] | ||
| 357 | PUSH SI | ||
| 358 | PUSH DX | ||
| 359 | PUSH BP | ||
| 360 | PUSH ES | ||
| 361 | CALL BUFWRITE ; Write out the dirty buffer | ||
| 362 | POP ES | ||
| 363 | POP BP | ||
| 364 | POP DX | ||
| 365 | POP SI | ||
| 366 | RDSEC: ; Read in the new sector | ||
| 367 | TEST BYTE PTR [PREREAD],-1 | ||
| 368 | JNZ SETBUF | ||
| 369 | LEA BX,[DI.BufInSiz] ; Point at buffer | ||
| 370 | MOV CX,1 | ||
| 371 | PUSH SI | ||
| 372 | PUSH DI | ||
| 373 | PUSH DX | ||
| 374 | OR SI,SI | ||
| 375 | JZ NORMSEC | ||
| 376 | invoke FATSECRD | ||
| 377 | JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs | ||
| 378 | NORMSEC: | ||
| 379 | invoke DREAD ; Buffer is marked free if read barfs | ||
| 380 | GOTTHESEC: | ||
| 381 | POP DX | ||
| 382 | POP DI | ||
| 383 | POP SI | ||
| 384 | SETBUF: | ||
| 385 | MOV [DI.BUFSECNO],DX | ||
| 386 | MOV WORD PTR [DI.BUFDRVDP],BP | ||
| 387 | MOV WORD PTR [DI.BUFDRVDP+2],ES | ||
| 388 | XOR AH,AH | ||
| 389 | MOV AL,ES:[BP.dpb_drive] | ||
| 390 | MOV WORD PTR [DI.BUFDRV],AX | ||
| 391 | SETINF: | ||
| 392 | MOV AX,1 ; Default to not a FAT sector | ||
| 393 | OR SI,SI | ||
| 394 | JZ SETSTUFFOK | ||
| 395 | MOV AL,ES:[BP.dpb_FAT_count] | ||
| 396 | MOV AH,ES:[BP.dpb_FAT_size] | ||
| 397 | SETSTUFFOK: | ||
| 398 | MOV WORD PTR [DI.BUFWRTCNT],AX | ||
| 399 | CALL PLACEBUF | ||
| 400 | JUSTBUF: | ||
| 401 | MOV WORD PTR [CURBUF+2],DS | ||
| 402 | MOV WORD PTR [LASTBUFFER+2],DS | ||
| 403 | PUSH SS | ||
| 404 | POP DS | ||
| 405 | ASSUME DS:DOSGROUP | ||
| 406 | MOV WORD PTR [CURBUF],DI | ||
| 407 | MOV WORD PTR [LASTBUFFER],DI | ||
| 408 | return | ||
| 409 | GETBUFFR ENDP | ||
| 410 | |||
| 411 | |||
| 412 | SUBTTL FLUSHBUF -- WRITE OUT DIRTY BUFFERS | ||
| 413 | PAGE | ||
| 414 | procedure FlushBuf,NEAR | ||
| 415 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 416 | |||
| 417 | ; Input: | ||
| 418 | ; DS = DOSGROUP | ||
| 419 | ; AL = Physical unit number | ||
| 420 | ; = -1 for all units | ||
| 421 | ; Function: | ||
| 422 | ; Write out all dirty buffers for unit, and flag them as clean | ||
| 423 | ; DS Preserved, all others destroyed (ES too) | ||
| 424 | |||
| 425 | LDS DI,[BUFFHEAD] | ||
| 426 | ASSUME DS:NOTHING | ||
| 427 | MOV AH,-1 | ||
| 428 | NXTBUFF: | ||
| 429 | CMP [DI.BUFDRV],AH | ||
| 430 | JZ SKIPBFF ; Skip free buffers | ||
| 431 | CMP AH,AL | ||
| 432 | JZ DOBUFFER ; Do all dirty buffers | ||
| 433 | CMP AL,[DI.BUFDRV] | ||
| 434 | JNZ SKIPBFF ; Buffer not for this unit | ||
| 435 | DOBUFFER: | ||
| 436 | CMP BYTE PTR [DI.BUFDIRTY],0 | ||
| 437 | JZ SKIPBFF ; Buffer not dirty | ||
| 438 | PUSH AX | ||
| 439 | PUSH WORD PTR [DI.BUFDRV] | ||
| 440 | CALL BUFWRITE | ||
| 441 | POP AX | ||
| 442 | XOR AH,AH ; Buffer is clean | ||
| 443 | CMP AL,BYTE PTR [WPERR] | ||
| 444 | JNZ NOZAP | ||
| 445 | MOV AL,0FFH ; Invalidate buffer, it is inconsistent | ||
| 446 | NOZAP: | ||
| 447 | MOV WORD PTR [DI.BUFDRV],AX | ||
| 448 | POP AX ; Search info | ||
| 449 | SKIPBFF: | ||
| 450 | LDS DI,[DI.NEXTBUF] | ||
| 451 | CMP DI,-1 | ||
| 452 | JNZ NXTBUFF | ||
| 453 | PUSH SS | ||
| 454 | POP DS | ||
| 455 | return | ||
| 456 | FlushBuf ENDP | ||
| 457 | |||
| 458 | |||
| 459 | SUBTTL BUFWRITE -- WRITE OUT A BUFFER IF DIRTY | ||
| 460 | PAGE | ||
| 461 | procedure BufWrite,NEAR | ||
| 462 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 463 | |||
| 464 | ; Input: | ||
| 465 | ; DS:DI Points to the buffer | ||
| 466 | ; Function: | ||
| 467 | ; Write out all the buffer if dirty. | ||
| 468 | ; Output: | ||
| 469 | ; Buffer marked free | ||
| 470 | ; DS:DI Preserved, ALL others destroyed (ES too) | ||
| 471 | |||
| 472 | MOV AX,00FFH | ||
| 473 | XCHG AX,WORD PTR [DI.BUFDRV] ; Free, in case write barfs | ||
| 474 | CMP AL,0FFH | ||
| 475 | retz ; Buffer is free. | ||
| 476 | OR AH,AH | ||
| 477 | retz ; Buffer is clean. | ||
| 478 | CMP AL,BYTE PTR [WPERR] | ||
| 479 | retz ; If in WP error zap buffer | ||
| 480 | LES BP,[DI.BUFDRVDP] | ||
| 481 | LEA BX,[DI.BufInSiz] ; Point at buffer | ||
| 482 | MOV DX,[DI.BUFSECNO] | ||
| 483 | MOV CX,WORD PTR [DI.BUFWRTCNT] | ||
| 484 | MOV AL,CH ; [DI.BUFWRTINC] | ||
| 485 | XOR CH,CH | ||
| 486 | MOV AH,CH | ||
| 487 | PUSH DI | ||
| 488 | WRTAGAIN: | ||
| 489 | PUSH CX | ||
| 490 | PUSH AX | ||
| 491 | MOV CX,1 | ||
| 492 | PUSH BX | ||
| 493 | PUSH DX | ||
| 494 | invoke DWRITE ; Write out the dirty buffer | ||
| 495 | POP DX | ||
| 496 | POP BX | ||
| 497 | POP AX | ||
| 498 | POP CX | ||
| 499 | ADD DX,AX | ||
| 500 | LOOP WRTAGAIN | ||
| 501 | POP DI | ||
| 502 | return | ||
| 503 | BufWrite ENDP | ||
| 504 | |||
| 505 | do_ext | ||
| 506 | |||
| 507 | CODE ENDS | ||
| 508 | END | ||