diff options
| author | 1983-08-12 17:53:34 -0700 | |
|---|---|---|
| committer | 2018-09-21 17:53:34 -0700 | |
| commit | 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 (patch) | |
| tree | ee4357f7f3dd0f2ded59b9c6e7384432d85e7ec9 /v2.0/source/DISK.ASM | |
| parent | MS-DOS v1.25 Release (diff) | |
| download | ms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.tar.gz ms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.tar.xz ms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.zip | |
MS-DOS v2.0 Release
Diffstat (limited to 'v2.0/source/DISK.ASM')
| -rw-r--r-- | v2.0/source/DISK.ASM | 1302 |
1 files changed, 1302 insertions, 0 deletions
diff --git a/v2.0/source/DISK.ASM b/v2.0/source/DISK.ASM new file mode 100644 index 0000000..b1acd82 --- /dev/null +++ b/v2.0/source/DISK.ASM | |||
| @@ -0,0 +1,1302 @@ | |||
| 1 | ; | ||
| 2 | ; Disk routines 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 | TITLE DISK - Disk utility routines | ||
| 18 | NAME Disk | ||
| 19 | |||
| 20 | i_need COUTDSAV,BYTE | ||
| 21 | i_need COUTSAV,DWORD | ||
| 22 | i_need CINDSAV,BYTE | ||
| 23 | i_need CINSAV,DWORD | ||
| 24 | i_need CONSWAP,BYTE | ||
| 25 | i_need IDLEINT,BYTE | ||
| 26 | i_need THISFCB,DWORD | ||
| 27 | i_need DMAADD,DWORD | ||
| 28 | i_need DEVCALL,BYTE | ||
| 29 | i_need CALLSCNT,WORD | ||
| 30 | i_need CALLXAD,DWORD | ||
| 31 | i_need CONTPOS,WORD | ||
| 32 | i_need NEXTADD,WORD | ||
| 33 | i_need CONBUF,BYTE | ||
| 34 | i_need User_SS,WORD | ||
| 35 | i_need User_SP,WORD | ||
| 36 | i_need DSKStack,BYTE | ||
| 37 | i_need InDOS,BYTE | ||
| 38 | i_need NumIO,BYTE | ||
| 39 | i_need CurDrv,BYTE | ||
| 40 | i_need ThisDrv,BYTE | ||
| 41 | i_need ClusFac,BYTE | ||
| 42 | i_need SecClusPos,BYTE | ||
| 43 | i_need DirSec,WORD | ||
| 44 | i_need ClusNum,WORD | ||
| 45 | i_need NxtClusNum,WORD | ||
| 46 | i_need ReadOp,BYTE | ||
| 47 | i_need DskErr,BYTE | ||
| 48 | i_need RecCnt,WORD | ||
| 49 | i_need RecPos,4 | ||
| 50 | i_need Trans,BYTE | ||
| 51 | i_need BytPos,4 | ||
| 52 | i_need SecPos,WORD | ||
| 53 | i_need BytSecPos,WORD | ||
| 54 | i_need BytCnt1,WORD | ||
| 55 | i_need BytCnt2,WORD | ||
| 56 | i_need SecCnt,WORD | ||
| 57 | i_need ThisDPB,DWORD | ||
| 58 | i_need LastPos,WORD | ||
| 59 | i_need ValSec,WORD | ||
| 60 | i_need GrowCnt,DWORD | ||
| 61 | |||
| 62 | SUBTTL LOAD -- MAIN READ ROUTINE AND DEVICE IN ROUTINES | ||
| 63 | PAGE | ||
| 64 | ; * * * * Drivers for file input from devices * * * * | ||
| 65 | |||
| 66 | procedure SWAPBACK,NEAR | ||
| 67 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 68 | PUSH ES | ||
| 69 | PUSH DI | ||
| 70 | PUSH SI | ||
| 71 | PUSH BX | ||
| 72 | MOV BX,1 | ||
| 73 | invoke get_sf_from_jfn | ||
| 74 | ADD DI,sf_fcb | ||
| 75 | MOV BL,BYTE PTR [COUTDSAV] | ||
| 76 | LDS SI,[COUTSAV] | ||
| 77 | ASSUME DS:NOTHING | ||
| 78 | MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI | ||
| 79 | MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS | ||
| 80 | MOV ES:[DI.fcb_DEVID],BL | ||
| 81 | PUSH SS | ||
| 82 | POP DS | ||
| 83 | ASSUME DS:DOSGROUP | ||
| 84 | XOR BX,BX | ||
| 85 | invoke get_sf_from_jfn | ||
| 86 | ADD DI,sf_fcb | ||
| 87 | MOV BL,BYTE PTR [CINDSAV] | ||
| 88 | LDS SI,[CINSAV] | ||
| 89 | ASSUME DS:NOTHING | ||
| 90 | MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI | ||
| 91 | MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS | ||
| 92 | MOV ES:[DI.fcb_DEVID],BL | ||
| 93 | PUSH SS | ||
| 94 | POP DS | ||
| 95 | ASSUME DS:DOSGROUP | ||
| 96 | MOV BYTE PTR [CONSWAP],0 | ||
| 97 | MOV BYTE PTR [IDLEINT],1 | ||
| 98 | SWAPRET: | ||
| 99 | POP BX | ||
| 100 | POP SI | ||
| 101 | POP DI | ||
| 102 | POP ES | ||
| 103 | return | ||
| 104 | SWAPBACK ENDP | ||
| 105 | |||
| 106 | procedure SWAPCON,NEAR | ||
| 107 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 108 | PUSH ES | ||
| 109 | PUSH DI | ||
| 110 | PUSH SI | ||
| 111 | PUSH BX | ||
| 112 | MOV BYTE PTR [CONSWAP],1 | ||
| 113 | MOV BYTE PTR [IDLEINT],0 | ||
| 114 | XOR BX,BX | ||
| 115 | invoke get_sf_from_jfn | ||
| 116 | ADD DI,sf_fcb | ||
| 117 | MOV BL,ES:[DI.fcb_DEVID] | ||
| 118 | MOV BYTE PTR [CINDSAV],BL | ||
| 119 | LDS SI,DWORD PTR ES:[DI.fcb_FIRCLUS] | ||
| 120 | ASSUME DS:NOTHING | ||
| 121 | MOV WORD PTR [CINSAV],SI | ||
| 122 | MOV WORD PTR [CINSAV+2],DS | ||
| 123 | LDS SI,[THISFCB] | ||
| 124 | MOV BL,[SI.fcb_DEVID] | ||
| 125 | LDS SI,DWORD PTR [SI.fcb_FIRCLUS] | ||
| 126 | MOV ES:[DI.fcb_DEVID],BL | ||
| 127 | MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI | ||
| 128 | MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS | ||
| 129 | PUSH SS | ||
| 130 | POP DS | ||
| 131 | ASSUME DS:DOSGROUP | ||
| 132 | MOV BX,1 | ||
| 133 | invoke get_sf_from_jfn | ||
| 134 | ADD DI,sf_fcb | ||
| 135 | MOV BL,ES:[DI.fcb_DEVID] | ||
| 136 | MOV BYTE PTR [COUTDSAV],BL | ||
| 137 | LDS SI,DWORD PTR ES:[DI.fcb_FIRCLUS] | ||
| 138 | ASSUME DS:NOTHING | ||
| 139 | MOV WORD PTR [COUTSAV],SI | ||
| 140 | MOV WORD PTR [COUTSAV+2],DS | ||
| 141 | LDS SI,[THISFCB] | ||
| 142 | MOV BL,[SI.fcb_DEVID] | ||
| 143 | LDS SI,DWORD PTR [SI.fcb_FIRCLUS] | ||
| 144 | MOV ES:[DI.fcb_DEVID],BL | ||
| 145 | MOV WORD PTR ES:[DI.fcb_FIRCLUS],SI | ||
| 146 | MOV WORD PTR ES:[DI.fcb_FIRCLUS+2],DS | ||
| 147 | PUSH SS | ||
| 148 | POP DS | ||
| 149 | JMP SWAPRET | ||
| 150 | SWAPCON ENDP | ||
| 151 | |||
| 152 | procedure LOAD,NEAR | ||
| 153 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 154 | ; | ||
| 155 | ; Inputs: | ||
| 156 | ; DS:DI point to FCB | ||
| 157 | ; DX:AX = Position in file to read | ||
| 158 | ; CX = No. of records to read | ||
| 159 | ; Outputs: | ||
| 160 | ; DX:AX = Position of last record read | ||
| 161 | ; CX = No. of bytes read | ||
| 162 | ; ES:DI point to FCB | ||
| 163 | ; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set | ||
| 164 | |||
| 165 | call SETUP | ||
| 166 | ASSUME DS:DOSGROUP | ||
| 167 | OR BL,BL ; Check for named device I/O | ||
| 168 | JS READDEV | ||
| 169 | call DISKREAD | ||
| 170 | return | ||
| 171 | |||
| 172 | READDEV: | ||
| 173 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 174 | LES DI,[DMAADD] | ||
| 175 | TEST BL,40H ; End of file? | ||
| 176 | JZ ENDRDDEVJ3 | ||
| 177 | TEST BL,ISNULL ; NUL device? | ||
| 178 | JZ TESTRAW ; NO | ||
| 179 | XOR AL,AL ; Indicate EOF | ||
| 180 | ENDRDDEVJ3: JMP ENDRDDEVJ2 | ||
| 181 | |||
| 182 | DVRDRAW: | ||
| 183 | ASSUME DS:DOSGROUP | ||
| 184 | PUSH ES | ||
| 185 | POP DS | ||
| 186 | ASSUME DS:NOTHING | ||
| 187 | DVRDRAWR: | ||
| 188 | MOV BX,DI ; DS:BX transfer addr | ||
| 189 | XOR DX,DX ; Start at 0 | ||
| 190 | XOR AX,AX ; Media Byte, unit = 0 | ||
| 191 | invoke SETREAD | ||
| 192 | LDS SI,[THISFCB] | ||
| 193 | invoke DEVIOCALL | ||
| 194 | MOV DX,DI ; DX is preserved by INT 24 | ||
| 195 | MOV AH,86H ; Read error | ||
| 196 | MOV DI,[DEVCALL.REQSTAT] | ||
| 197 | TEST DI,STERR | ||
| 198 | JZ CRDROK ; No errors | ||
| 199 | invoke CHARHARD | ||
| 200 | MOV DI,DX | ||
| 201 | CMP AL,1 | ||
| 202 | JZ DVRDRAWR ; Retry | ||
| 203 | CRDROK: | ||
| 204 | MOV DI,DX | ||
| 205 | ADD DI,[CALLSCNT] ; Amount transferred | ||
| 206 | JMP SHORT ENDRDDEVJ2 | ||
| 207 | |||
| 208 | TESTRAW: | ||
| 209 | TEST BL,020H ; Raw mode? | ||
| 210 | JNZ DVRDRAW | ||
| 211 | TEST BL,ISCIN ; Is it console device? | ||
| 212 | JZ NOTRDCON | ||
| 213 | JMP READCON | ||
| 214 | NOTRDCON: | ||
| 215 | MOV AX,ES | ||
| 216 | MOV DS,AX | ||
| 217 | ASSUME DS:NOTHING | ||
| 218 | MOV BX,DI | ||
| 219 | XOR DX,DX | ||
| 220 | MOV AX,DX | ||
| 221 | PUSH CX | ||
| 222 | MOV CX,1 | ||
| 223 | invoke SETREAD | ||
| 224 | POP CX | ||
| 225 | LDS SI,[THISFCB] | ||
| 226 | LDS SI,DWORD PTR [SI.fcb_FIRCLUS] | ||
| 227 | DVRDLP: | ||
| 228 | invoke DSKSTATCHK | ||
| 229 | invoke DEVIOCALL2 | ||
| 230 | PUSH DI | ||
| 231 | MOV AH,86H | ||
| 232 | MOV DI,[DEVCALL.REQSTAT] | ||
| 233 | TEST DI,STERR | ||
| 234 | JZ CRDOK | ||
| 235 | invoke CHARHARD | ||
| 236 | POP DI | ||
| 237 | MOV [CALLSCNT],1 | ||
| 238 | CMP AL,1 | ||
| 239 | JZ DVRDLP ;Retry | ||
| 240 | XOR AL,AL ;Pick some random character | ||
| 241 | JMP SHORT DVRDIGN | ||
| 242 | CRDOK: | ||
| 243 | POP DI | ||
| 244 | CMP [CALLSCNT],1 | ||
| 245 | JNZ ENDRDDEVJ2 | ||
| 246 | PUSH DS | ||
| 247 | MOV DS,WORD PTR [CALLXAD+2] | ||
| 248 | MOV AL,BYTE PTR [DI] | ||
| 249 | POP DS | ||
| 250 | DVRDIGN: | ||
| 251 | INC WORD PTR [CALLXAD] | ||
| 252 | MOV [DEVCALL.REQSTAT],0 | ||
| 253 | INC DI | ||
| 254 | CMP AL,1AH ; ^Z? | ||
| 255 | JZ ENDRDDEVJ | ||
| 256 | CMP AL,c_CR ; CR? | ||
| 257 | LOOPNZ DVRDLP | ||
| 258 | ENDRDDEVJ: | ||
| 259 | DEC DI | ||
| 260 | ENDRDDEVJ2: | ||
| 261 | JMP SHORT ENDRDDEV | ||
| 262 | |||
| 263 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 264 | |||
| 265 | TRANBUF: | ||
| 266 | LODSB | ||
| 267 | STOSB | ||
| 268 | CMP AL,c_CR ; Check for carriage return | ||
| 269 | JNZ NORMCH | ||
| 270 | MOV BYTE PTR [SI],c_LF | ||
| 271 | NORMCH: | ||
| 272 | CMP AL,c_LF | ||
| 273 | LOOPNZ TRANBUF | ||
| 274 | JNZ ENDRDCON | ||
| 275 | XOR SI,SI ; Cause a new buffer to be read | ||
| 276 | invoke OUT ; Transmit linefeed | ||
| 277 | OR AL,1 ; Clear zero flag--not end of file | ||
| 278 | ENDRDCON: | ||
| 279 | PUSH SS | ||
| 280 | POP DS | ||
| 281 | ASSUME DS:DOSGROUP | ||
| 282 | CALL SWAPBACK | ||
| 283 | MOV [CONTPOS],SI | ||
| 284 | ENDRDDEV: | ||
| 285 | PUSH SS | ||
| 286 | POP DS | ||
| 287 | ASSUME DS:DOSGROUP | ||
| 288 | MOV [NEXTADD],DI | ||
| 289 | JNZ SETFCBC ; Zero set if Ctrl-Z found in input | ||
| 290 | LES DI,[THISFCB] | ||
| 291 | AND ES:BYTE PTR [DI.fcb_DEVID],0FFH-40H ; Mark as no more data available | ||
| 292 | SETFCBC: | ||
| 293 | call SETFCB | ||
| 294 | return | ||
| 295 | |||
| 296 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 297 | |||
| 298 | READCON: | ||
| 299 | ASSUME DS:DOSGROUP | ||
| 300 | CALL SWAPCON | ||
| 301 | MOV SI,[CONTPOS] | ||
| 302 | OR SI,SI | ||
| 303 | JNZ TRANBUF | ||
| 304 | CMP BYTE PTR [CONBUF],128 | ||
| 305 | JZ GETBUF | ||
| 306 | MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template | ||
| 307 | GETBUF: | ||
| 308 | PUSH CX | ||
| 309 | PUSH ES | ||
| 310 | PUSH DI | ||
| 311 | MOV DX,OFFSET DOSGROUP:CONBUF | ||
| 312 | invoke $STD_CON_STRING_INPUT ; Get input buffer | ||
| 313 | POP DI | ||
| 314 | POP ES | ||
| 315 | POP CX | ||
| 316 | MOV SI,2 + OFFSET DOSGROUP:CONBUF | ||
| 317 | CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character | ||
| 318 | JNZ TRANBUF | ||
| 319 | MOV AL,1AH | ||
| 320 | STOSB | ||
| 321 | DEC DI | ||
| 322 | MOV AL,10 | ||
| 323 | invoke OUT ; Send linefeed | ||
| 324 | XOR SI,SI | ||
| 325 | JMP SHORT ENDRDCON | ||
| 326 | |||
| 327 | LOAD ENDP | ||
| 328 | |||
| 329 | SUBTTL STORE -- MAIN WRITE ROUTINE AND DEVICE OUT ROUTINES | ||
| 330 | PAGE | ||
| 331 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 332 | procedure STORE,NEAR | ||
| 333 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 334 | |||
| 335 | ; Inputs: | ||
| 336 | ; DS:DI point to FCB | ||
| 337 | ; DX:AX = Position in file of disk transfer | ||
| 338 | ; CX = Record count | ||
| 339 | ; Outputs: | ||
| 340 | ; DX:AX = Position of last record written | ||
| 341 | ; CX = No. of records written | ||
| 342 | ; ES:DI point to FCB | ||
| 343 | ; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set | ||
| 344 | |||
| 345 | call SETUP | ||
| 346 | ASSUME DS:DOSGROUP | ||
| 347 | OR BL,BL | ||
| 348 | JS WRTDEV | ||
| 349 | invoke DATE16 | ||
| 350 | MOV ES:[DI.fcb_FDATE],AX | ||
| 351 | MOV ES:[DI.fcb_FTIME],DX | ||
| 352 | call DISKWRITE | ||
| 353 | return | ||
| 354 | |||
| 355 | WRITECON: | ||
| 356 | PUSH DS | ||
| 357 | PUSH SS | ||
| 358 | POP DS | ||
| 359 | ASSUME DS:DOSGROUP | ||
| 360 | CALL SWAPCON | ||
| 361 | POP DS | ||
| 362 | ASSUME DS:NOTHING | ||
| 363 | MOV SI,BX | ||
| 364 | PUSH CX | ||
| 365 | WRCONLP: | ||
| 366 | LODSB | ||
| 367 | CMP AL,1AH ; ^Z? | ||
| 368 | JZ CONEOF | ||
| 369 | invoke OUT | ||
| 370 | LOOP WRCONLP | ||
| 371 | CONEOF: | ||
| 372 | POP AX ; Count | ||
| 373 | SUB AX,CX ; Amount actually written | ||
| 374 | POP DS | ||
| 375 | ASSUME DS:DOSGROUP | ||
| 376 | CALL SWAPBACK | ||
| 377 | JMP SHORT ENDWRDEV | ||
| 378 | |||
| 379 | DVWRTRAW: | ||
| 380 | ASSUME DS:NOTHING | ||
| 381 | XOR AX,AX ; Media Byte, unit = 0 | ||
| 382 | invoke SETWRITE | ||
| 383 | LDS SI,[THISFCB] | ||
| 384 | invoke DEVIOCALL | ||
| 385 | MOV DX,DI | ||
| 386 | MOV AH,87H | ||
| 387 | MOV DI,[DEVCALL.REQSTAT] | ||
| 388 | TEST DI,STERR | ||
| 389 | JZ CWRTROK | ||
| 390 | invoke CHARHARD | ||
| 391 | MOV BX,DX ; Recall transfer addr | ||
| 392 | CMP AL,1 | ||
| 393 | JZ DVWRTRAW ; Try again | ||
| 394 | CWRTROK: | ||
| 395 | POP DS | ||
| 396 | ASSUME DS:DOSGROUP | ||
| 397 | MOV AX,[CALLSCNT] ; Get actual number of bytes transferred | ||
| 398 | ENDWRDEV: | ||
| 399 | LES DI,[THISFCB] | ||
| 400 | XOR DX,DX | ||
| 401 | DIV ES:[DI.fcb_RECSIZ] | ||
| 402 | MOV CX,AX ; Partial record is ignored | ||
| 403 | call ADDREC | ||
| 404 | return | ||
| 405 | |||
| 406 | ASSUME DS:DOSGROUP | ||
| 407 | WRTDEV: | ||
| 408 | OR BL,40H ; Reset EOF for input | ||
| 409 | XOR AX,AX | ||
| 410 | JCXZ ENDWRDEV ; problem of creating on a device. | ||
| 411 | PUSH DS | ||
| 412 | MOV AL,BL | ||
| 413 | LDS BX,[DMAADD] | ||
| 414 | ASSUME DS:NOTHING | ||
| 415 | MOV DI,BX | ||
| 416 | XOR DX,DX ; Set starting point | ||
| 417 | TEST AL,020H ; Raw? | ||
| 418 | JNZ DVWRTRAW | ||
| 419 | TEST AL,ISCOUT ; Console output device? | ||
| 420 | JNZ WRITECON | ||
| 421 | TEST AL,ISNULL | ||
| 422 | JNZ WRTNUL | ||
| 423 | MOV AX,DX | ||
| 424 | CMP BYTE PTR [BX],1AH ; ^Z? | ||
| 425 | JZ WRTCOOKDONE ; Yes, transfer nothing | ||
| 426 | PUSH CX | ||
| 427 | MOV CX,1 | ||
| 428 | invoke SETWRITE | ||
| 429 | POP CX | ||
| 430 | LDS SI,[THISFCB] | ||
| 431 | LDS SI,DWORD PTR [SI.fcb_FIRCLUS] | ||
| 432 | DVWRTLP: | ||
| 433 | invoke DSKSTATCHK | ||
| 434 | invoke DEVIOCALL2 | ||
| 435 | PUSH DI | ||
| 436 | MOV AH,87H | ||
| 437 | MOV DI,[DEVCALL.REQSTAT] | ||
| 438 | TEST DI,STERR | ||
| 439 | JZ CWROK | ||
| 440 | invoke CHARHARD | ||
| 441 | POP DI | ||
| 442 | MOV [CALLSCNT],1 | ||
| 443 | CMP AL,1 | ||
| 444 | JZ DVWRTLP | ||
| 445 | JMP SHORT DVWRTIGN | ||
| 446 | CWROK: | ||
| 447 | POP DI | ||
| 448 | CMP [CALLSCNT],0 | ||
| 449 | JZ WRTCOOKDONE | ||
| 450 | DVWRTIGN: | ||
| 451 | INC DX | ||
| 452 | INC WORD PTR [CALLXAD] | ||
| 453 | INC DI | ||
| 454 | PUSH DS | ||
| 455 | MOV DS,WORD PTR [CALLXAD+2] | ||
| 456 | CMP BYTE PTR [DI],1AH ; ^Z? | ||
| 457 | POP DS | ||
| 458 | JZ WRTCOOKDONE | ||
| 459 | MOV [DEVCALL.REQSTAT],0 | ||
| 460 | LOOP DVWRTLP | ||
| 461 | WRTCOOKDONE: | ||
| 462 | MOV AX,DX | ||
| 463 | POP DS | ||
| 464 | JMP ENDWRDEV | ||
| 465 | |||
| 466 | WRTNUL: | ||
| 467 | MOV DX,CX ;Entire transfer done | ||
| 468 | JMP WRTCOOKDONE | ||
| 469 | |||
| 470 | STORE ENDP | ||
| 471 | |||
| 472 | procedure get_io_fcb,near | ||
| 473 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 474 | ; Convert JFN number in BX to FCB in DS:SI | ||
| 475 | PUSH SS | ||
| 476 | POP DS | ||
| 477 | ASSUME DS:DOSGROUP | ||
| 478 | PUSH ES | ||
| 479 | PUSH DI | ||
| 480 | invoke get_sf_from_jfn | ||
| 481 | JC RET44P | ||
| 482 | MOV SI,DI | ||
| 483 | ADD SI,sf_fcb | ||
| 484 | PUSH ES | ||
| 485 | POP DS | ||
| 486 | ASSUME DS:NOTHING | ||
| 487 | RET44P: | ||
| 488 | POP DI | ||
| 489 | POP ES | ||
| 490 | return | ||
| 491 | get_io_fcb ENDP | ||
| 492 | |||
| 493 | SUBTTL GETTHISDRV -- FIND CURRENT DRIVE | ||
| 494 | PAGE | ||
| 495 | ; Input: AL has drive identifier (1=A, 0=default) | ||
| 496 | ; Output: AL has physical drive (0=A) | ||
| 497 | ; Carry set if invalid drive (and AL is garbage anyway) | ||
| 498 | procedure GetThisDrv,NEAR | ||
| 499 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 500 | CMP BYTE PTR [NUMIO],AL | ||
| 501 | retc | ||
| 502 | DEC AL | ||
| 503 | JNS PHYDRV | ||
| 504 | MOV AL,[CURDRV] | ||
| 505 | PHYDRV: | ||
| 506 | MOV BYTE PTR [THISDRV],AL | ||
| 507 | return | ||
| 508 | GetThisDrv ENDP | ||
| 509 | |||
| 510 | SUBTTL DIRREAD -- READ A DIRECTORY SECTOR | ||
| 511 | PAGE | ||
| 512 | procedure DirRead,NEAR | ||
| 513 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 514 | |||
| 515 | ; Inputs: | ||
| 516 | ; AX = Directory block number (relative to first block of directory) | ||
| 517 | ; ES:BP = Base of drive parameters | ||
| 518 | ; [DIRSEC] = First sector of first cluster of directory | ||
| 519 | ; [CLUSNUM] = Next cluster | ||
| 520 | ; [CLUSFAC] = Sectors/Cluster | ||
| 521 | ; Function: | ||
| 522 | ; Read the directory block into [CURBUF]. | ||
| 523 | ; Outputs: | ||
| 524 | ; [NXTCLUSNUM] = Next cluster (after the one skipped to) | ||
| 525 | ; [SECCLUSPOS] Set | ||
| 526 | ; ES:BP unchanged [CURBUF] Points to Buffer with dir sector | ||
| 527 | ; All other registers destroyed. | ||
| 528 | |||
| 529 | MOV CL,[CLUSFAC] | ||
| 530 | DIV CL ; AL # clusters to skip, AH position in cluster | ||
| 531 | MOV [SECCLUSPOS],AH | ||
| 532 | MOV CL,AL | ||
| 533 | XOR CH,CH | ||
| 534 | MOV DX,[DIRSEC] | ||
| 535 | ADD DL,AH | ||
| 536 | ADC DH,0 | ||
| 537 | MOV BX,[CLUSNUM] | ||
| 538 | MOV [NXTCLUSNUM],BX | ||
| 539 | JCXZ FIRSTCLUSTER | ||
| 540 | SKPCLLP: | ||
| 541 | invoke UNPACK | ||
| 542 | XCHG BX,DI | ||
| 543 | CMP BX,0FF8H | ||
| 544 | JAE HAVESKIPPED | ||
| 545 | LOOP SKPCLLP | ||
| 546 | HAVESKIPPED: | ||
| 547 | MOV [NXTCLUSNUM],BX | ||
| 548 | MOV DX,DI | ||
| 549 | MOV BL,AH | ||
| 550 | invoke FIGREC | ||
| 551 | entry FIRSTCLUSTER | ||
| 552 | XOR AL,AL ; Indicate pre-read | ||
| 553 | MOV AH,DIRPRI | ||
| 554 | invoke GETBUFFR | ||
| 555 | ret | ||
| 556 | DirRead ENDP | ||
| 557 | |||
| 558 | SUBTTL FATSECRD -- READ A FAT SECTOR | ||
| 559 | PAGE | ||
| 560 | procedure FATSecRd,NEAR | ||
| 561 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 562 | |||
| 563 | ; Inputs: | ||
| 564 | ; Same as DREAD | ||
| 565 | ; DS:BX = Transfer address | ||
| 566 | ; CX = Number of sectors | ||
| 567 | ; DX = Absolute record number | ||
| 568 | ; ES:BP = Base of drive parameters | ||
| 569 | ; Function: | ||
| 570 | ; Calls BIOS to perform FAT read. | ||
| 571 | ; Outputs: | ||
| 572 | ; Same as DREAD | ||
| 573 | |||
| 574 | MOV DI,CX | ||
| 575 | MOV CL,ES:[BP.dpb_FAT_count] | ||
| 576 | MOV AL,ES:[BP.dpb_FAT_size] | ||
| 577 | XOR AH,AH | ||
| 578 | MOV CH,AH | ||
| 579 | PUSH DX | ||
| 580 | NXTFAT: | ||
| 581 | PUSH CX | ||
| 582 | PUSH AX | ||
| 583 | MOV CX,DI | ||
| 584 | CALL DSKREAD | ||
| 585 | POP AX | ||
| 586 | POP CX | ||
| 587 | JZ RET41P | ||
| 588 | ADD DX,AX | ||
| 589 | LOOP NXTFAT | ||
| 590 | POP DX | ||
| 591 | MOV CX,DI | ||
| 592 | |||
| 593 | ; NOTE FALL THROUGH | ||
| 594 | |||
| 595 | SUBTTL DREAD -- DO A DISK READ | ||
| 596 | PAGE | ||
| 597 | entry DREAD | ||
| 598 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 599 | |||
| 600 | ; Inputs: | ||
| 601 | ; DS:BX = Transfer address | ||
| 602 | ; CX = Number of sectors | ||
| 603 | ; DX = Absolute record number | ||
| 604 | ; ES:BP = Base of drive parameters | ||
| 605 | ; Function: | ||
| 606 | ; Calls BIOS to perform disk read. If BIOS reports | ||
| 607 | ; errors, will call HARDERR for further action. | ||
| 608 | ; DS,ES:BP preserved. All other registers destroyed. | ||
| 609 | |||
| 610 | CALL DSKREAD | ||
| 611 | retz | ||
| 612 | MOV BYTE PTR [READOP],0 | ||
| 613 | invoke HARDERR | ||
| 614 | CMP AL,1 ; Check for retry | ||
| 615 | JZ DREAD | ||
| 616 | return ; Ignore otherwise | ||
| 617 | RET41P: POP DX | ||
| 618 | return | ||
| 619 | FATSecRd ENDP | ||
| 620 | |||
| 621 | SUBTTL DSKREAD -- PHYSICAL DISK READ | ||
| 622 | PAGE | ||
| 623 | procedure DskRead,NEAR | ||
| 624 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 625 | |||
| 626 | ; Inputs: | ||
| 627 | ; DS:BX = Transfer addr | ||
| 628 | ; CX = Number of sectors | ||
| 629 | ; DX = Absolute record number | ||
| 630 | ; ES:BP = Base of drive parameters | ||
| 631 | ; Function: | ||
| 632 | ; Call BIOS to perform disk read | ||
| 633 | ; Outputs: | ||
| 634 | ; DI = CX on entry | ||
| 635 | ; CX = Number of sectors unsuccessfully transfered | ||
| 636 | ; AX = Status word as returned by BIOS (error code in AL if error) | ||
| 637 | ; Zero set if OK (from BIOS) | ||
| 638 | ; Zero clear if error | ||
| 639 | ; SI Destroyed, others preserved | ||
| 640 | |||
| 641 | PUSH CX | ||
| 642 | MOV AH,ES:[BP.dpb_media] | ||
| 643 | MOV AL,ES:[BP.dpb_UNIT] | ||
| 644 | PUSH BX | ||
| 645 | PUSH ES | ||
| 646 | invoke SETREAD | ||
| 647 | JMP DODSKOP | ||
| 648 | |||
| 649 | SUBTTL DWRITE -- SEE ABOUT WRITING | ||
| 650 | PAGE | ||
| 651 | entry DWRITE | ||
| 652 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 653 | |||
| 654 | ; Inputs: | ||
| 655 | ; DS:BX = Transfer address | ||
| 656 | ; CX = Number of sectors | ||
| 657 | ; DX = Absolute record number | ||
| 658 | ; ES:BP = Base of drive parameters | ||
| 659 | ; Function: | ||
| 660 | ; Calls BIOS to perform disk write. If BIOS reports | ||
| 661 | ; errors, will call HARDERR for further action. | ||
| 662 | ; BP preserved. All other registers destroyed. | ||
| 663 | |||
| 664 | CALL DSKWRITE | ||
| 665 | retz | ||
| 666 | MOV BYTE PTR [READOP],1 | ||
| 667 | invoke HARDERR | ||
| 668 | CMP AL,1 ; Check for retry | ||
| 669 | JZ DWRITE | ||
| 670 | return | ||
| 671 | |||
| 672 | SUBTTL DSKWRITE -- PHYSICAL DISK WRITE | ||
| 673 | PAGE | ||
| 674 | entry DSKWRITE | ||
| 675 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 676 | |||
| 677 | ; Inputs: | ||
| 678 | ; DS:BX = Transfer addr | ||
| 679 | ; CX = Number of sectors | ||
| 680 | ; DX = Absolute record number | ||
| 681 | ; ES:BP = Base of drive parameters | ||
| 682 | ; Function: | ||
| 683 | ; Call BIOS to perform disk read | ||
| 684 | ; Outputs: | ||
| 685 | ; DI = CX on entry | ||
| 686 | ; CX = Number of sectors unsuccessfully transfered | ||
| 687 | ; AX = Status word as returned by BIOS (error code in AL if error) | ||
| 688 | ; Zero set if OK (from BIOS) | ||
| 689 | ; Zero clear if error | ||
| 690 | ; SI Destroyed, others preserved | ||
| 691 | |||
| 692 | PUSH CX | ||
| 693 | MOV AH,ES:[BP.dpb_media] | ||
| 694 | MOV AL,ES:[BP.dpb_UNIT] | ||
| 695 | PUSH BX | ||
| 696 | PUSH ES | ||
| 697 | invoke SETWRITE | ||
| 698 | DODSKOP: | ||
| 699 | MOV CX,DS ; Save DS | ||
| 700 | POP DS ; DS:BP points to DPB | ||
| 701 | PUSH DS | ||
| 702 | LDS SI,DS:[BP.dpb_driver_addr] | ||
| 703 | invoke DEVIOCALL2 | ||
| 704 | MOV DS,CX ; Restore DS | ||
| 705 | POP ES ; Restore ES | ||
| 706 | POP BX | ||
| 707 | MOV CX,[CALLSCNT] ; Number of sectors transferred | ||
| 708 | POP DI | ||
| 709 | SUB CX,DI | ||
| 710 | NEG CX ; Number of sectors not transferred | ||
| 711 | MOV AX,[DEVCALL.REQSTAT] | ||
| 712 | TEST AX,STERR | ||
| 713 | return | ||
| 714 | DskRead ENDP | ||
| 715 | |||
| 716 | SUBTTL SETUP -- SETUP A DISK READ OR WRITE FROM USER | ||
| 717 | PAGE | ||
| 718 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 719 | |||
| 720 | procedure SETUP,NEAR | ||
| 721 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 722 | |||
| 723 | ; Inputs: | ||
| 724 | ; DS:DI point to FCB | ||
| 725 | ; DX:AX = Record position in file of disk transfer | ||
| 726 | ; CX = Record count | ||
| 727 | ; Outputs: | ||
| 728 | ; DS = DOSGROUP | ||
| 729 | ; BL = fcb_DEVID from FCB | ||
| 730 | ; CX = No. of bytes to transfer (0 = 64K) | ||
| 731 | ; [THISDPB] = Base of drive parameters | ||
| 732 | ; [RECCNT] = Record count | ||
| 733 | ; [RECPOS] = Record position in file | ||
| 734 | ; ES:DI Points to FCB | ||
| 735 | ; [THISFCB] = ES:DI | ||
| 736 | ; [NEXTADD] = Displacement of disk transfer within segment | ||
| 737 | ; [SECPOS] = Position of first sector | ||
| 738 | ; [BYTPOS] = Byte position in file | ||
| 739 | ; [BYTSECPOS] = Byte position in first sector | ||
| 740 | ; [CLUSNUM] = First cluster | ||
| 741 | ; [SECCLUSPOS] = Sector within first cluster | ||
| 742 | ; [DSKERR] = 0 (no errors yet) | ||
| 743 | ; [TRANS] = 0 (No transfers yet) | ||
| 744 | ; [THISDRV] = Physical drive unit number | ||
| 745 | |||
| 746 | PUSH AX | ||
| 747 | MOV AL,[DI] | ||
| 748 | DEC AL | ||
| 749 | MOV BYTE PTR [THISDRV],AL | ||
| 750 | MOV AL,[DI.fcb_DEVID] | ||
| 751 | MOV SI,[DI.fcb_RECSIZ] | ||
| 752 | OR SI,SI | ||
| 753 | JNZ HAVRECSIZ | ||
| 754 | MOV SI,128 | ||
| 755 | MOV [DI.fcb_RECSIZ],SI | ||
| 756 | HAVRECSIZ: | ||
| 757 | MOV WORD PTR [THISFCB+2],DS | ||
| 758 | PUSH SS | ||
| 759 | POP DS ; Set DS to DOSGROUP | ||
| 760 | ASSUME DS:DOSGROUP | ||
| 761 | MOV WORD PTR [THISFCB],DI | ||
| 762 | OR AL,AL ; Is it a device? | ||
| 763 | JNS NOTDEVICE | ||
| 764 | XOR AL,AL ; Fake in drive 0 so we can get BP | ||
| 765 | NOTDEVICE: | ||
| 766 | invoke GETBP | ||
| 767 | POP AX | ||
| 768 | JNC CheckRecLen | ||
| 769 | XOR CX,CX | ||
| 770 | MOV BYTE PTR [DSKERR],4 | ||
| 771 | POP BX | ||
| 772 | return | ||
| 773 | |||
| 774 | CheckRecLen: | ||
| 775 | CMP SI,64 ; Check if highest byte of RECPOS is significant | ||
| 776 | JB SMALREC | ||
| 777 | XOR DH,DH ; Ignore MSB if record >= 64 bytes | ||
| 778 | SMALREC: | ||
| 779 | MOV [RECCNT],CX | ||
| 780 | MOV WORD PTR [RECPOS],AX | ||
| 781 | MOV WORD PTR [RECPOS+2],DX | ||
| 782 | MOV BX,WORD PTR [DMAADD] | ||
| 783 | MOV [NEXTADD],BX | ||
| 784 | MOV BYTE PTR [DSKERR],0 | ||
| 785 | MOV BYTE PTR [TRANS],0 | ||
| 786 | MOV BX,DX | ||
| 787 | MUL SI | ||
| 788 | MOV WORD PTR [BYTPOS],AX | ||
| 789 | PUSH DX | ||
| 790 | MOV AX,BX | ||
| 791 | MUL SI | ||
| 792 | POP BX | ||
| 793 | ADD AX,BX | ||
| 794 | ADC DX,0 ; Ripple carry | ||
| 795 | JNZ EOFERR | ||
| 796 | MOV WORD PTR [BYTPOS+2],AX | ||
| 797 | MOV DX,AX | ||
| 798 | MOV AX,WORD PTR [BYTPOS] | ||
| 799 | MOV BX,ES:[BP.dpb_sector_size] | ||
| 800 | CMP DX,BX ; See if divide will overflow | ||
| 801 | JNC EOFERR | ||
| 802 | DIV BX | ||
| 803 | MOV [SECPOS],AX | ||
| 804 | MOV [BYTSECPOS],DX | ||
| 805 | MOV DX,AX | ||
| 806 | AND AL,ES:[BP.dpb_cluster_mask] | ||
| 807 | MOV [SECCLUSPOS],AL | ||
| 808 | MOV AX,CX ; Record count | ||
| 809 | MOV CL,ES:[BP.dpb_cluster_shift] | ||
| 810 | SHR DX,CL | ||
| 811 | MOV [CLUSNUM],DX | ||
| 812 | MUL SI ; Multiply by bytes per record | ||
| 813 | MOV CX,AX | ||
| 814 | ADD AX,WORD PTR [DMAADD] ; See if it will fit in one segment | ||
| 815 | ADC DX,0 | ||
| 816 | JZ OK ; Must be less than 64K | ||
| 817 | MOV AX,WORD PTR [DMAADD] | ||
| 818 | NEG AX ; Amount of room left in segment | ||
| 819 | JNZ PARTSEG | ||
| 820 | DEC AX | ||
| 821 | PARTSEG: | ||
| 822 | XOR DX,DX | ||
| 823 | DIV SI ; How many records will fit? | ||
| 824 | MOV [RECCNT],AX | ||
| 825 | MUL SI ; Translate that back into bytes | ||
| 826 | MOV BYTE PTR [DSKERR],2 ; Flag that trimming took place | ||
| 827 | MOV CX,AX | ||
| 828 | JCXZ NOROOM | ||
| 829 | OK: | ||
| 830 | LES DI,[THISFCB] | ||
| 831 | MOV BL,ES:[DI.fcb_DEVID] | ||
| 832 | return | ||
| 833 | |||
| 834 | EOFERR: | ||
| 835 | MOV BYTE PTR [DSKERR],1 | ||
| 836 | XOR CX,CX | ||
| 837 | NOROOM: | ||
| 838 | LES DI,[THISFCB] | ||
| 839 | POP BX ; Kill return address | ||
| 840 | return | ||
| 841 | SETUP ENDP | ||
| 842 | |||
| 843 | SUBTTL BREAKDOWN -- CUT A USER READ OR WRITE INTO PIECES | ||
| 844 | PAGE | ||
| 845 | procedure BREAKDOWN,near | ||
| 846 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 847 | |||
| 848 | ; Inputs: | ||
| 849 | ; CX = Length of disk transfer in bytes | ||
| 850 | ; ES:BP = Base of drive parameters | ||
| 851 | ; [BYTSECPOS] = Byte position witin first sector | ||
| 852 | ; Outputs: | ||
| 853 | ; [BYTCNT1] = Bytes to transfer in first sector | ||
| 854 | ; [SECCNT] = No. of whole sectors to transfer | ||
| 855 | ; [BYTCNT2] = Bytes to transfer in last sector | ||
| 856 | ; AX, BX, DX destroyed. No other registers affected. | ||
| 857 | |||
| 858 | MOV AX,[BYTSECPOS] | ||
| 859 | MOV BX,CX | ||
| 860 | OR AX,AX | ||
| 861 | JZ SAVFIR ; Partial first sector? | ||
| 862 | SUB AX,ES:[BP.dpb_sector_size] | ||
| 863 | NEG AX ; Max number of bytes left in first sector | ||
| 864 | SUB BX,AX ; Subtract from total length | ||
| 865 | JAE SAVFIR | ||
| 866 | ADD AX,BX ; Don't use all of the rest of the sector | ||
| 867 | XOR BX,BX ; And no bytes are left | ||
| 868 | SAVFIR: | ||
| 869 | MOV [BYTCNT1],AX | ||
| 870 | MOV AX,BX | ||
| 871 | XOR DX,DX | ||
| 872 | DIV ES:[BP.dpb_sector_size] ; How many whole sectors? | ||
| 873 | MOV [SECCNT],AX | ||
| 874 | MOV [BYTCNT2],DX ; Bytes remaining for last sector | ||
| 875 | OR DX,[BYTCNT1] | ||
| 876 | retnz ; NOT (BYTCNT1 = BYTCNT2 = 0) | ||
| 877 | CMP AX,1 | ||
| 878 | retnz | ||
| 879 | MOV AX,ES:[BP.dpb_sector_size] ; Buffer EXACT one sector I/O | ||
| 880 | MOV [BYTCNT2],AX | ||
| 881 | MOV [SECCNT],DX ; DX = 0 | ||
| 882 | return | ||
| 883 | BreakDown ENDP | ||
| 884 | |||
| 885 | SUBTTL DISKREAD -- PERFORM USER DISK READ | ||
| 886 | PAGE | ||
| 887 | procedure DISKREAD,NEAR | ||
| 888 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 889 | |||
| 890 | ; Inputs: | ||
| 891 | ; Outputs of SETUP | ||
| 892 | ; Function: | ||
| 893 | ; Perform disk read | ||
| 894 | ; Outputs: | ||
| 895 | ; DX:AX = Position of last record read | ||
| 896 | ; CX = No. of records read | ||
| 897 | ; ES:DI point to FCB | ||
| 898 | ; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set | ||
| 899 | |||
| 900 | MOV AX,ES:WORD PTR [DI.fcb_FILSIZ] | ||
| 901 | MOV BX,ES:WORD PTR [DI.fcb_FILSIZ+2] | ||
| 902 | SUB AX,WORD PTR [BYTPOS] | ||
| 903 | SBB BX,WORD PTR [BYTPOS+2] | ||
| 904 | JB RDERR | ||
| 905 | JNZ ENUF | ||
| 906 | OR AX,AX | ||
| 907 | JZ RDERR | ||
| 908 | CMP AX,CX | ||
| 909 | JAE ENUF | ||
| 910 | MOV CX,AX | ||
| 911 | ENUF: | ||
| 912 | LES BP,[THISDPB] | ||
| 913 | CALL BREAKDOWN | ||
| 914 | MOV CX,[CLUSNUM] | ||
| 915 | invoke FNDCLUS | ||
| 916 | OR CX,CX | ||
| 917 | JZ SHORT SKIPERR | ||
| 918 | RDERR: | ||
| 919 | JMP WRTERR | ||
| 920 | RDLASTJ:JMP RDLAST | ||
| 921 | SETFCBJ2: JMP SETFCB | ||
| 922 | |||
| 923 | SKIPERR: | ||
| 924 | |||
| 925 | MOV [LASTPOS],DX | ||
| 926 | MOV [CLUSNUM],BX | ||
| 927 | CMP [BYTCNT1],0 | ||
| 928 | JZ RDMID | ||
| 929 | invoke BUFRD | ||
| 930 | RDMID: | ||
| 931 | CMP [SECCNT],0 | ||
| 932 | JZ RDLASTJ | ||
| 933 | invoke NEXTSEC | ||
| 934 | JC SETFCBJ2 | ||
| 935 | MOV BYTE PTR [TRANS],1 ; A transfer is taking place | ||
| 936 | ONSEC: | ||
| 937 | MOV DL,[SECCLUSPOS] | ||
| 938 | MOV CX,[SECCNT] | ||
| 939 | MOV BX,[CLUSNUM] | ||
| 940 | RDLP: | ||
| 941 | invoke OPTIMIZE | ||
| 942 | PUSH DI | ||
| 943 | PUSH AX | ||
| 944 | PUSH BX | ||
| 945 | MOV DS,WORD PTR [DMAADD+2] | ||
| 946 | ASSUME DS:NOTHING | ||
| 947 | PUSH DX | ||
| 948 | PUSH CX | ||
| 949 | CALL DREAD | ||
| 950 | POP BX | ||
| 951 | POP DX | ||
| 952 | ADD BX,DX ; Upper bound of read | ||
| 953 | MOV AL,ES:[BP.dpb_drive] | ||
| 954 | invoke SETVISIT | ||
| 955 | NXTBUF: ; Must see if one of these sectors is buffered | ||
| 956 | MOV [DI.VISIT],1 ; Mark as visited | ||
| 957 | CMP AL,[DI.BUFDRV] | ||
| 958 | JNZ DONXTBUF ; Not for this drive | ||
| 959 | CMP [DI.BUFSECNO],DX | ||
| 960 | JC DONXTBUF ; Below first sector | ||
| 961 | CMP [DI.BUFSECNO],BX | ||
| 962 | JNC DONXTBUF ; Above last sector | ||
| 963 | CMP BYTE PTR [DI.BUFDIRTY],0 | ||
| 964 | JZ CLBUFF ; Buffer is clean, so OK | ||
| 965 | ; A sector has been read in when a dirty copy of it is in a buffer | ||
| 966 | ; The buffered sector must now be read into the right place | ||
| 967 | POP AX ; Recall transfer address | ||
| 968 | PUSH AX | ||
| 969 | PUSH DI ; Save search environment | ||
| 970 | PUSH DX | ||
| 971 | SUB DX,[DI.BUFSECNO] ; How far into transfer? | ||
| 972 | NEG DX | ||
| 973 | MOV SI,DI | ||
| 974 | MOV DI,AX | ||
| 975 | MOV AX,DX | ||
| 976 | MOV CX,ES:[BP.dpb_sector_size] | ||
| 977 | MUL CX | ||
| 978 | ADD DI,AX ; Put the buffer here | ||
| 979 | ADD SI,BUFINSIZ | ||
| 980 | SHR CX,1 | ||
| 981 | PUSH ES | ||
| 982 | MOV ES,WORD PTR [DMAADD+2] | ||
| 983 | REP MOVSW | ||
| 984 | JNC EVENMOV | ||
| 985 | MOVSB | ||
| 986 | EVENMOV: | ||
| 987 | POP ES | ||
| 988 | POP DX | ||
| 989 | POP DI | ||
| 990 | MOV AL,ES:[BP.dpb_drive] | ||
| 991 | CLBUFF: | ||
| 992 | invoke SCANPLACE | ||
| 993 | DONXTBUF: | ||
| 994 | invoke SKIPVISIT | ||
| 995 | JNZ NXTBUF | ||
| 996 | PUSH SS | ||
| 997 | POP DS | ||
| 998 | ASSUME DS:DOSGROUP | ||
| 999 | POP CX | ||
| 1000 | POP CX | ||
| 1001 | POP BX | ||
| 1002 | JCXZ RDLAST | ||
| 1003 | CMP BX,0FF8H | ||
| 1004 | JAE SETFCB | ||
| 1005 | MOV DL,0 | ||
| 1006 | INC [LASTPOS] ; We'll be using next cluster | ||
| 1007 | JMP RDLP | ||
| 1008 | |||
| 1009 | RDLAST: | ||
| 1010 | MOV AX,[BYTCNT2] | ||
| 1011 | OR AX,AX | ||
| 1012 | JZ SETFCB | ||
| 1013 | MOV [BYTCNT1],AX | ||
| 1014 | invoke NEXTSEC | ||
| 1015 | JC SETFCB | ||
| 1016 | MOV [BYTSECPOS],0 | ||
| 1017 | invoke BUFRD | ||
| 1018 | |||
| 1019 | entry SETFCB | ||
| 1020 | LES SI,[THISFCB] | ||
| 1021 | MOV AX,[NEXTADD] | ||
| 1022 | MOV DI,AX | ||
| 1023 | SUB AX,WORD PTR [DMAADD] ; Number of bytes transfered | ||
| 1024 | XOR DX,DX | ||
| 1025 | MOV CX,ES:[SI.fcb_RECSIZ] | ||
| 1026 | DIV CX ; Number of records | ||
| 1027 | CMP AX,[RECCNT] ; Check if all records transferred | ||
| 1028 | JZ FULLREC | ||
| 1029 | MOV BYTE PTR [DSKERR],1 | ||
| 1030 | OR DX,DX | ||
| 1031 | JZ FULLREC ; If remainder 0, then full record transfered | ||
| 1032 | MOV BYTE PTR [DSKERR],3 ; Flag partial last record | ||
| 1033 | SUB CX,DX ; Bytes left in last record | ||
| 1034 | PUSH ES | ||
| 1035 | MOV ES,WORD PTR [DMAADD+2] | ||
| 1036 | XCHG AX,BX ; Save the record count temporarily | ||
| 1037 | XOR AX,AX ; Fill with zeros | ||
| 1038 | SHR CX,1 | ||
| 1039 | JNC EVENFIL | ||
| 1040 | STOSB | ||
| 1041 | EVENFIL: | ||
| 1042 | REP STOSW | ||
| 1043 | XCHG AX,BX ; Restore record count to AX | ||
| 1044 | POP ES | ||
| 1045 | INC AX ; Add last (partial) record to total | ||
| 1046 | FULLREC: | ||
| 1047 | MOV CX,AX | ||
| 1048 | MOV DI,SI ; ES:DI point to FCB | ||
| 1049 | SETCLUS: | ||
| 1050 | TEST ES:[DI].fcb_DEVID,-1 | ||
| 1051 | JS ADDREC ; don't set clisters if device | ||
| 1052 | MOV AX,[CLUSNUM] | ||
| 1053 | AND ES:[DI.fcb_LSTCLUS],0F000h ; fcb_lstclus is packed with dir clus | ||
| 1054 | OR ES:[DI.fcb_LSTCLUS],AX ; drop in the correct part of fcb_lstclus | ||
| 1055 | MOV AX,[LASTPOS] | ||
| 1056 | MOV ES:[DI.fcb_CLUSPOS],AX | ||
| 1057 | entry AddRec | ||
| 1058 | MOV AX,WORD PTR [RECPOS] | ||
| 1059 | MOV DX,WORD PTR [RECPOS+2] | ||
| 1060 | JCXZ RET28 ; If no records read, don't change position | ||
| 1061 | DEC CX | ||
| 1062 | ADD AX,CX ; Update current record position | ||
| 1063 | ADC DX,0 | ||
| 1064 | INC CX | ||
| 1065 | RET28: return | ||
| 1066 | DISKREAD ENDP | ||
| 1067 | |||
| 1068 | SUBTTL DISKWRITE -- PERFORM USER DISK WRITE | ||
| 1069 | PAGE | ||
| 1070 | procedure DISKWRITE,NEAR | ||
| 1071 | ASSUME DS:DOSGROUP,ES:NOTHING | ||
| 1072 | |||
| 1073 | ; Inputs: | ||
| 1074 | ; Outputs of SETUP | ||
| 1075 | ; Function: | ||
| 1076 | ; Perform disk write | ||
| 1077 | ; Outputs: | ||
| 1078 | ; DX:AX = Position of last record written | ||
| 1079 | ; CX = No. of records written | ||
| 1080 | ; ES:DI point to FCB | ||
| 1081 | ; fcb_LSTCLUS, fcb_CLUSPOS fields in FCB set | ||
| 1082 | |||
| 1083 | AND BL,3FH ; Mark file as dirty | ||
| 1084 | MOV ES:[DI.fcb_DEVID],BL | ||
| 1085 | LES BP,[THISDPB] | ||
| 1086 | CALL BREAKDOWN | ||
| 1087 | MOV AX,WORD PTR [BYTPOS] | ||
| 1088 | MOV DX,WORD PTR [BYTPOS+2] | ||
| 1089 | JCXZ WRTEOFJ | ||
| 1090 | ADD AX,CX | ||
| 1091 | ADC DX,0 ; AX:DX=last byte accessed | ||
| 1092 | DIV ES:[BP.dpb_sector_size] ; AX=last sector accessed | ||
| 1093 | MOV BX,AX ; Save last full sector | ||
| 1094 | OR DX,DX | ||
| 1095 | JNZ CALCLUS | ||
| 1096 | DEC AX ; AX must be zero base indexed | ||
| 1097 | CALCLUS: | ||
| 1098 | MOV CL,ES:[BP.dpb_cluster_shift] | ||
| 1099 | SHR AX,CL ; Last cluster to be accessed | ||
| 1100 | PUSH AX | ||
| 1101 | PUSH DX ; Save the size of the "tail" | ||
| 1102 | PUSH ES | ||
| 1103 | LES DI,[THISFCB] | ||
| 1104 | MOV AX,ES:WORD PTR [DI.fcb_FILSIZ] | ||
| 1105 | MOV DX,ES:WORD PTR [DI.fcb_FILSIZ+2] | ||
| 1106 | POP ES | ||
| 1107 | DIV ES:[BP.dpb_sector_size] | ||
| 1108 | MOV CX,AX ; Save last full sector of current file | ||
| 1109 | OR DX,DX | ||
| 1110 | JZ NORNDUP | ||
| 1111 | INC AX ; Round up if any remainder | ||
| 1112 | NORNDUP: | ||
| 1113 | MOV [VALSEC],AX ; Number of sectors that have been written | ||
| 1114 | XOR AX,AX | ||
| 1115 | MOV WORD PTR [GROWCNT],AX | ||
| 1116 | MOV WORD PTR [GROWCNT+2],AX | ||
| 1117 | POP AX | ||
| 1118 | SUB BX,CX ; Number of full sectors | ||
| 1119 | JB NOGROW | ||
| 1120 | JZ TESTTAIL | ||
| 1121 | MOV CX,DX | ||
| 1122 | XCHG AX,BX | ||
| 1123 | MUL ES:[BP.dpb_sector_size] ; Bytes of full sector growth | ||
| 1124 | SUB AX,CX ; Take off current "tail" | ||
| 1125 | SBB DX,0 ; 32-bit extension | ||
| 1126 | ADD AX,BX ; Add on new "tail" | ||
| 1127 | ADC DX,0 ; ripple tim's head off | ||
| 1128 | JMP SHORT SETGRW | ||
| 1129 | |||
| 1130 | HAVSTART: | ||
| 1131 | MOV CX,AX | ||
| 1132 | invoke SKPCLP | ||
| 1133 | JCXZ DOWRTJ | ||
| 1134 | invoke ALLOCATE | ||
| 1135 | JNC DOWRTJ | ||
| 1136 | WRTERR: | ||
| 1137 | XOR CX,CX | ||
| 1138 | MOV BYTE PTR [DSKERR],1 | ||
| 1139 | MOV AX,WORD PTR [RECPOS] | ||
| 1140 | MOV DX,WORD PTR [RECPOS+2] | ||
| 1141 | LES DI,[THISFCB] | ||
| 1142 | return | ||
| 1143 | |||
| 1144 | DOWRTJ: JMP DOWRT | ||
| 1145 | |||
| 1146 | WRTEOFJ: | ||
| 1147 | JMP WRTEOF | ||
| 1148 | |||
| 1149 | TESTTAIL: | ||
| 1150 | SUB AX,DX | ||
| 1151 | JBE NOGROW | ||
| 1152 | XOR DX,DX | ||
| 1153 | SETGRW: | ||
| 1154 | MOV WORD PTR [GROWCNT],AX | ||
| 1155 | MOV WORD PTR [GROWCNT+2],DX | ||
| 1156 | NOGROW: | ||
| 1157 | POP AX | ||
| 1158 | MOV CX,[CLUSNUM] ; First cluster accessed | ||
| 1159 | invoke FNDCLUS | ||
| 1160 | MOV [CLUSNUM],BX | ||
| 1161 | MOV [LASTPOS],DX | ||
| 1162 | SUB AX,DX ; Last cluster minus current cluster | ||
| 1163 | JZ DOWRT ; If we have last clus, we must have first | ||
| 1164 | JCXZ HAVSTART ; See if no more data | ||
| 1165 | PUSH CX ; No. of clusters short of first | ||
| 1166 | MOV CX,AX | ||
| 1167 | invoke ALLOCATE | ||
| 1168 | POP AX | ||
| 1169 | JC WRTERR | ||
| 1170 | MOV CX,AX | ||
| 1171 | MOV DX,[LASTPOS] | ||
| 1172 | INC DX | ||
| 1173 | DEC CX | ||
| 1174 | JZ NOSKIP | ||
| 1175 | invoke SKPCLP | ||
| 1176 | NOSKIP: | ||
| 1177 | MOV [CLUSNUM],BX | ||
| 1178 | MOV [LASTPOS],DX | ||
| 1179 | DOWRT: | ||
| 1180 | CMP [BYTCNT1],0 | ||
| 1181 | JZ WRTMID | ||
| 1182 | MOV BX,[CLUSNUM] | ||
| 1183 | invoke BUFWRT | ||
| 1184 | WRTMID: | ||
| 1185 | MOV AX,[SECCNT] | ||
| 1186 | OR AX,AX | ||
| 1187 | JZ WRTLAST | ||
| 1188 | ADD [SECPOS],AX | ||
| 1189 | invoke NEXTSEC | ||
| 1190 | MOV BYTE PTR [TRANS],1 ; A transfer is taking place | ||
| 1191 | MOV DL,[SECCLUSPOS] | ||
| 1192 | MOV BX,[CLUSNUM] | ||
| 1193 | MOV CX,[SECCNT] | ||
| 1194 | WRTLP: | ||
| 1195 | invoke OPTIMIZE | ||
| 1196 | PUSH DI | ||
| 1197 | PUSH AX | ||
| 1198 | PUSH DX | ||
| 1199 | PUSH BX | ||
| 1200 | MOV AL,ES:[BP.dpb_drive] | ||
| 1201 | MOV BX,CX | ||
| 1202 | ADD BX,DX ; Upper bound of write | ||
| 1203 | invoke SETVISIT | ||
| 1204 | ASSUME DS:NOTHING | ||
| 1205 | NEXTBUFF: ; Search for buffers | ||
| 1206 | MOV [DI.VISIT],1 ; Mark as visited | ||
| 1207 | CMP AL,[DI.BUFDRV] | ||
| 1208 | JNZ DONEXTBUFF ; Not for this drive | ||
| 1209 | CMP [DI.BUFSECNO],DX | ||
| 1210 | JC DONEXTBUFF ; Buffer is not in range of write | ||
| 1211 | CMP [DI.BUFSECNO],BX | ||
| 1212 | JNC DONEXTBUFF ; Buffer is not in range of write | ||
| 1213 | MOV WORD PTR [DI.BUFDRV],00FFH ; Free the buffer, it is being over written | ||
| 1214 | invoke SCANPLACE | ||
| 1215 | DONEXTBUFF: | ||
| 1216 | invoke SKIPVISIT | ||
| 1217 | JNZ NEXTBUFF | ||
| 1218 | POP BX | ||
| 1219 | POP DX | ||
| 1220 | MOV DS,WORD PTR [DMAADD+2] | ||
| 1221 | CALL DWRITE | ||
| 1222 | POP CX | ||
| 1223 | POP BX | ||
| 1224 | PUSH SS | ||
| 1225 | POP DS | ||
| 1226 | ASSUME DS:DOSGROUP | ||
| 1227 | JCXZ WRTLAST | ||
| 1228 | MOV DL,0 | ||
| 1229 | INC [LASTPOS] ; We'll be using next cluster | ||
| 1230 | JMP SHORT WRTLP | ||
| 1231 | |||
| 1232 | WRTERRJ: JMP WRTERR | ||
| 1233 | |||
| 1234 | WRTLAST: | ||
| 1235 | MOV AX,[BYTCNT2] | ||
| 1236 | OR AX,AX | ||
| 1237 | JZ FINWRT | ||
| 1238 | MOV [BYTCNT1],AX | ||
| 1239 | invoke NEXTSEC | ||
| 1240 | MOV [BYTSECPOS],0 | ||
| 1241 | invoke BUFWRT | ||
| 1242 | FINWRT: | ||
| 1243 | LES DI,[THISFCB] | ||
| 1244 | MOV AX,WORD PTR [GROWCNT] | ||
| 1245 | MOV CX,WORD PTR [GROWCNT+2] | ||
| 1246 | OR AX,AX | ||
| 1247 | JNZ UPDATE_size | ||
| 1248 | OR CX,CX | ||
| 1249 | JZ SAMSIZ | ||
| 1250 | Update_size: | ||
| 1251 | ADD WORD PTR ES:[DI.fcb_FILSIZ],AX | ||
| 1252 | ADC WORD PTR ES:[DI.fcb_FILSIZ+2],CX | ||
| 1253 | SAMSIZ: | ||
| 1254 | MOV CX,[RECCNT] | ||
| 1255 | JMP SETCLUS | ||
| 1256 | |||
| 1257 | WRTEOF: | ||
| 1258 | MOV CX,AX | ||
| 1259 | OR CX,DX | ||
| 1260 | JZ KILLFIL | ||
| 1261 | SUB AX,1 | ||
| 1262 | SBB DX,0 | ||
| 1263 | DIV ES:[BP.dpb_sector_size] | ||
| 1264 | MOV CL,ES:[BP.dpb_cluster_shift] | ||
| 1265 | SHR AX,CL | ||
| 1266 | MOV CX,AX | ||
| 1267 | invoke FNDCLUS | ||
| 1268 | JCXZ RELFILE | ||
| 1269 | invoke ALLOCATE | ||
| 1270 | JC WRTERRJ | ||
| 1271 | UPDATE: | ||
| 1272 | LES DI,[THISFCB] | ||
| 1273 | MOV AX,WORD PTR [BYTPOS] | ||
| 1274 | MOV ES:WORD PTR [DI.fcb_FILSIZ],AX | ||
| 1275 | MOV AX,WORD PTR [BYTPOS+2] | ||
| 1276 | MOV ES:WORD PTR [DI.fcb_FILSIZ+2],AX | ||
| 1277 | XOR CX,CX | ||
| 1278 | JMP ADDREC | ||
| 1279 | |||
| 1280 | RELFILE: | ||
| 1281 | MOV DX,0FFFH | ||
| 1282 | invoke RELBLKS | ||
| 1283 | JMP SHORT UPDATE | ||
| 1284 | |||
| 1285 | KILLFIL: | ||
| 1286 | XOR BX,BX | ||
| 1287 | PUSH ES | ||
| 1288 | LES DI,[THISFCB] | ||
| 1289 | MOV ES:[DI.fcb_CLUSPOS],BX | ||
| 1290 | XCHG BX,ES:[DI.fcb_FIRCLUS] | ||
| 1291 | AND ES:[DI.fcb_LSTCLUS],0F000H | ||
| 1292 | POP ES | ||
| 1293 | OR BX,BX | ||
| 1294 | JZ UPDATE | ||
| 1295 | invoke RELEASE | ||
| 1296 | JMP SHORT UPDATE | ||
| 1297 | DISKWRITE ENDP | ||
| 1298 | do_ext | ||
| 1299 | |||
| 1300 | CODE ENDS | ||
| 1301 | END | ||
| 1302 | |||