diff options
Diffstat (limited to 'v4.0/src/DOS/FCBIO2.ASM')
| -rw-r--r-- | v4.0/src/DOS/FCBIO2.ASM | 722 |
1 files changed, 722 insertions, 0 deletions
diff --git a/v4.0/src/DOS/FCBIO2.ASM b/v4.0/src/DOS/FCBIO2.ASM new file mode 100644 index 0000000..ec0ee3e --- /dev/null +++ b/v4.0/src/DOS/FCBIO2.ASM | |||
| @@ -0,0 +1,722 @@ | |||
| 1 | ; SCCSID = @(#)fcbio2.asm 1.2 85/07/23 | ||
| 2 | ; SCCSID = @(#)fcbio2.asm 1.2 85/07/23 | ||
| 3 | TITLE FCBIO2 - FCB system calls | ||
| 4 | NAME FCBIO2 | ||
| 5 | |||
| 6 | ; | ||
| 7 | ; Ancient 1.0 1.1 FCB system calls | ||
| 8 | ; regen save | ||
| 9 | ; GetRR | ||
| 10 | ; GetExtent | ||
| 11 | ; SetExtent | ||
| 12 | ; GetExtended | ||
| 13 | ; GetRecSize | ||
| 14 | ; FCBIO | ||
| 15 | ; $FCB_OPEN written ACC ACC | ||
| 16 | ; $FCB_CREATE written ACC ACC | ||
| 17 | ; $FCB_RANDOM_WRITE_BLOCK written fcbio fcbio | ||
| 18 | ; $FCB_RANDOM_READ_BLOCK written fcbio fcbio | ||
| 19 | ; $FCB_SEQ_READ written fcbio fcbio | ||
| 20 | ; $FCB_SEQ_WRITE written fcbio fcbio | ||
| 21 | ; $FCB_RANDOM_READ written fcbio fcbio | ||
| 22 | ; $FCB_RANDOM_WRITE written fcbio fcbio | ||
| 23 | ; | ||
| 24 | ; Revision history: | ||
| 25 | ; | ||
| 26 | ; Created: ARR 4 April 1983 | ||
| 27 | ; MZ 6 June 1983 completion of functions | ||
| 28 | ; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple | ||
| 29 | ; times. Change so successive closes work by | ||
| 30 | ; always returning OK. Also, detect I/O to | ||
| 31 | ; already closed FCB and return EOF. | ||
| 32 | ; MZ 16 Jan 1984 More braindamage. Need to separate info | ||
| 33 | ; out of sft into FCB for reconnection | ||
| 34 | ; | ||
| 35 | ; A000 version 4.00 Jan. 1988 | ||
| 36 | ; | ||
| 37 | .xlist | ||
| 38 | ; | ||
| 39 | ; get the appropriate segment definitions | ||
| 40 | ; | ||
| 41 | include dosseg.asm | ||
| 42 | |||
| 43 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 44 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 45 | |||
| 46 | .xcref | ||
| 47 | INCLUDE DOSSYM.INC | ||
| 48 | INCLUDE DEVSYM.INC | ||
| 49 | include version.inc | ||
| 50 | .cref | ||
| 51 | .list | ||
| 52 | |||
| 53 | EXTRN DOS_Read:NEAR, DOS_Write:NEAR | ||
| 54 | EXTRN DOS_Open:NEAR, DOS_Create:NEAR | ||
| 55 | |||
| 56 | I_need DMAAdd,DWORD ; current user's DMA address | ||
| 57 | I_need OpenBuf,128 ; buffer for translating paths | ||
| 58 | I_need ThisSFT,DWORD ; SFT in use | ||
| 59 | I_need sftFCB,DWORD ; pointer to SFTs for FCB cache | ||
| 60 | I_need FCBLRU,WORD ; least recently used count | ||
| 61 | I_need DISK_FULL,BYTE ; flag for disk full | ||
| 62 | if debug | ||
| 63 | I_need BugLev,WORD | ||
| 64 | I_need BugTyp,WORD | ||
| 65 | include bugtyp.asm | ||
| 66 | endif | ||
| 67 | |||
| 68 | IF BUFFERFLAG | ||
| 69 | |||
| 70 | I_need BUF_EMS_MODE,BYTE | ||
| 71 | I_need BUF_EMS_LAST_PAGE,DWORD | ||
| 72 | I_need BUF_EMS_FIRST_PAGE,DWORD | ||
| 73 | I_need BUF_EMS_SAFE_FLAG,BYTE | ||
| 74 | I_need BUF_EMS_NPA640,WORD | ||
| 75 | I_need BUF_EMS_PAGE_FRAME,WORD | ||
| 76 | I_need BUF_EMS_PFRAME,WORD | ||
| 77 | I_need LASTBUFFER,DWORD | ||
| 78 | |||
| 79 | extrn restore_user_map:near | ||
| 80 | extrn Setup_EMS_Buffers:near | ||
| 81 | |||
| 82 | ENDIF | ||
| 83 | |||
| 84 | |||
| 85 | ; Defintions for FCBOp flags | ||
| 86 | |||
| 87 | Random = 2 ; random operation | ||
| 88 | FCBRead = 4 ; doing a read | ||
| 89 | Block = 8 ; doing a block I/O | ||
| 90 | |||
| 91 | Break <GetRR - return the random record field in DX:AX> | ||
| 92 | |||
| 93 | ; | ||
| 94 | ; GetRR - correctly load DX:AX with the random record field (3 or 4 bytes) | ||
| 95 | ; from the FCB pointed to by DS:SI | ||
| 96 | ; | ||
| 97 | ; Inputs: DS:SI point to an FCB | ||
| 98 | ; BX has record size | ||
| 99 | ; Outputs: DX:AX contain the contents of the random record field | ||
| 100 | ; Registers modified: none | ||
| 101 | |||
| 102 | Procedure GetRR,NEAR | ||
| 103 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 104 | MOV AX,WORD PTR [SI.FCB_RR] ; get low order part | ||
| 105 | MOV DX,WORD PTR [SI.FCB_RR+2] ; get high order part | ||
| 106 | CMP BX,64 ; ignore MSB of RR if recsiz > 64 | ||
| 107 | JB GetRRBye | ||
| 108 | XOR DH,DH | ||
| 109 | GetRRBye: | ||
| 110 | return | ||
| 111 | EndProc GetRR | ||
| 112 | |||
| 113 | Break <GetExtent - retrieve next location for sequential IO> | ||
| 114 | |||
| 115 | ; | ||
| 116 | ; GetExtent - Construct the next record to perform I/O from the EXTENT and | ||
| 117 | ; NR fields in the FCB. | ||
| 118 | ; | ||
| 119 | ; Inputs: DS:SI - point to FCB | ||
| 120 | ; Outputs: DX:AX contain the contents of the random record field | ||
| 121 | ; Registers modified: none | ||
| 122 | |||
| 123 | Procedure GetExtent,NEAR | ||
| 124 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 125 | MOV AL,[SI.fcb_NR] ; get low order piece | ||
| 126 | MOV DX,[SI.fcb_EXTENT] ; get high order piece | ||
| 127 | SHL AL,1 | ||
| 128 | SHR DX,1 | ||
| 129 | RCR AL,1 ; move low order bit of DL to high order of AH | ||
| 130 | MOV AH,DL | ||
| 131 | MOV DL,DH | ||
| 132 | XOR DH,DH | ||
| 133 | return | ||
| 134 | EndProc GetExtent | ||
| 135 | |||
| 136 | Break <SetExtent - update the extent/NR field> | ||
| 137 | |||
| 138 | ; | ||
| 139 | ; SetExtent - change the position of an FCB by filling in the extent/NR | ||
| 140 | ; fields | ||
| 141 | ; | ||
| 142 | ; Inputs: DS:SI point to FCB | ||
| 143 | ; DX:AX is a record location in file | ||
| 144 | ; Outputs: Extent/NR fields are filled in | ||
| 145 | ; Registers modified: CX | ||
| 146 | |||
| 147 | Procedure SetExtent,NEAR | ||
| 148 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 149 | SaveReg <AX,DX> | ||
| 150 | MOV CX,AX | ||
| 151 | AND AL,7FH ; next rec field | ||
| 152 | MOV [SI.fcb_NR],AL | ||
| 153 | AND CL,80H ; save upper bit | ||
| 154 | SHL CX,1 | ||
| 155 | RCL DX,1 ; move high bit of CX to low bit of DX | ||
| 156 | MOV AL,CH | ||
| 157 | MOV AH,DL | ||
| 158 | MOV [SI.fcb_EXTENT],AX ; all done | ||
| 159 | RestoreReg <DX,AX> | ||
| 160 | return | ||
| 161 | EndProc SetExtent | ||
| 162 | |||
| 163 | Break <GetExtended - find FCB in potential extended fcb> | ||
| 164 | |||
| 165 | ; | ||
| 166 | ; GetExtended - Make DS:SI point to FCB from DS:DX | ||
| 167 | ; | ||
| 168 | ; Inputs: DS:DX point to a possible extended FCB | ||
| 169 | ; Outputs: DS:SI point to the FCB part | ||
| 170 | ; zeroflag set if not extended fcb | ||
| 171 | ; Registers modified: SI | ||
| 172 | |||
| 173 | Procedure GetExtended,NEAR | ||
| 174 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 175 | MOV SI,DX ; point to Something | ||
| 176 | CMP BYTE PTR DS:[SI],-1 ; look for extention | ||
| 177 | JNZ GetBye ; not there | ||
| 178 | ADD SI,7 ; point to FCB | ||
| 179 | GetBye: | ||
| 180 | CMP SI,DX ; set condition codes | ||
| 181 | return | ||
| 182 | EndProc GetExtended | ||
| 183 | |||
| 184 | Break <GetRecSize - return in BX the FCB record size> | ||
| 185 | |||
| 186 | ; | ||
| 187 | ; GetRecSize - return in BX the record size from the FCB at DS:SI | ||
| 188 | ; | ||
| 189 | ; Inputs: DS:SI point to a non-extended FCB | ||
| 190 | ; Outputs: BX contains the record size | ||
| 191 | ; Registers modified: None | ||
| 192 | |||
| 193 | Procedure GetRecSize,NEAR | ||
| 194 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 195 | MOV BX,[SI.fcb_RECSIZ] ; get his record size | ||
| 196 | OR BX,BX ; is it nul? | ||
| 197 | retnz | ||
| 198 | MOV BX,128 ; use default size | ||
| 199 | MOV [SI.fcb_RECSIZ],BX ; stuff it back | ||
| 200 | return | ||
| 201 | EndProc GetRecSize | ||
| 202 | |||
| 203 | BREAK <FCBIO - do internal FCB I/O> | ||
| 204 | |||
| 205 | ; | ||
| 206 | ; FCBIO - look at FCBOP and merge all FCB operations into a single routine. | ||
| 207 | ; | ||
| 208 | ; Inputs: FCBOP flags which operations need to be performed | ||
| 209 | ; DS:DX point to FCB | ||
| 210 | ; CX may have count of number of records to xfer | ||
| 211 | ; Outputs: AL has error code | ||
| 212 | ; Registers modified: all | ||
| 213 | |||
| 214 | Procedure FCBIO,NEAR | ||
| 215 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 216 | PUBLIC FCBIO001S,FCBIO001E | ||
| 217 | FCBIO001S: | ||
| 218 | LocalVar FCBErr,BYTE | ||
| 219 | LocalVar cRec,WORD | ||
| 220 | LocalVar RecPos,DWORD | ||
| 221 | LocalVar RecSize,WORD | ||
| 222 | LocalVar bPos,DWORD | ||
| 223 | LocalVar cByte,WORD | ||
| 224 | LocalVar cResult,WORD | ||
| 225 | LocalVar cRecRes,WORD | ||
| 226 | LocalVar FCBOp,BYTE | ||
| 227 | FCBIO001E: | ||
| 228 | Enter | ||
| 229 | |||
| 230 | FEOF EQU 1 | ||
| 231 | FTRIM EQU 2 | ||
| 232 | MOV FCBOp,AL | ||
| 233 | MOV FCBErr,0 ; FCBErr = 0; | ||
| 234 | invoke GetExtended ; FCB = GetExtended (); | ||
| 235 | TEST FCBOp,BLOCK ; if ((OP&BLOCK) == 0) | ||
| 236 | JNZ GetPos | ||
| 237 | MOV CX,1 ; cRec = 1; | ||
| 238 | GetPos: | ||
| 239 | MOV cRec,CX ;*Tail coalesce | ||
| 240 | invoke GetExtent ; RecPos = GetExtent (); | ||
| 241 | invoke GetRecSize ; RecSize = GetRecSize (); | ||
| 242 | MOV RecSize,BX | ||
| 243 | TEST FCBOp,RANDOM ; if ((OP&RANDOM) <> 0) | ||
| 244 | JZ GetRec | ||
| 245 | invoke GetRR ; RecPos = GetRR (); | ||
| 246 | GetRec: | ||
| 247 | MOV RecPosL,AX ;*Tail coalesce | ||
| 248 | MOV RecPosH,DX | ||
| 249 | invoke SetExtent ; SetExtent (RecPos); | ||
| 250 | MOV AX,RecPosH ; bPos = RecPos * RecSize; | ||
| 251 | MUL BX | ||
| 252 | MOV DI,AX | ||
| 253 | MOV AX,RecPosL | ||
| 254 | MUL BX | ||
| 255 | ADD DX,DI | ||
| 256 | MOV bPosL,AX | ||
| 257 | MOV bPosH,DX | ||
| 258 | MOV AX,cRec ; cByte = cRec * RecSize; | ||
| 259 | MUL BX | ||
| 260 | MOV cByte,AX | ||
| 261 | ADD AX,WORD PTR DMAAdd ; if (cByte+DMA > 64K) { | ||
| 262 | ADC DX,0 | ||
| 263 | JZ DoOper | ||
| 264 | MOV FCBErr,FTRIM ; FCBErr = FTRIM; | ||
| 265 | MOV AX,WORD PTR DMAAdd ; cRec = (64K-DMA)/RecSize; | ||
| 266 | NEG AX | ||
| 267 | JNZ DoDiv | ||
| 268 | DEC AX | ||
| 269 | DoDiv: | ||
| 270 | XOR DX,DX | ||
| 271 | DIV BX | ||
| 272 | MOV cRec,AX | ||
| 273 | MUL BX ; cByte = cRec * RecSize; | ||
| 274 | MOV cByte,AX ; } | ||
| 275 | DoOper: | ||
| 276 | XOR BX,BX | ||
| 277 | MOV cResult,BX ; cResult = 0; | ||
| 278 | CMP cByte,BX ; if (cByte <> 0 || | ||
| 279 | JNZ DoGetExt | ||
| 280 | TEST FCBErr,FTRIM ; (FCBErr&FTRIM) == 0) { | ||
| 281 | IF debug | ||
| 282 | JZ DoGetExt | ||
| 283 | JMP SkipOp | ||
| 284 | ELSE | ||
| 285 | JZ SKP_SkipOp | ||
| 286 | JMP SkipOp | ||
| 287 | SKP_SkipOp: | ||
| 288 | ENDIF | ||
| 289 | DoGetExt: | ||
| 290 | invoke SFTFromFCB ; if (!SFTFromFCB (SFT,FCB)) | ||
| 291 | JNC ContinueOp | ||
| 292 | FCBDeath: | ||
| 293 | invoke FCB_Ret_Err ; signal error, map for extended | ||
| 294 | MOV cRecRes,0 ; no bytes transferred | ||
| 295 | MOV FCBErr,FEOF ; return FTRIM; | ||
| 296 | JMP FCBSave ; bam! | ||
| 297 | ContinueOp: | ||
| 298 | Assert ISSFT,<ES,DI>,"ContinueOP" | ||
| 299 | MOV AX,WORD PTR [SI].fcb_filsiz | ||
| 300 | MOV WORD PTR ES:[DI].sf_size,AX | ||
| 301 | MOV AX,WORD PTR [SI].fcb_filsiz+2 | ||
| 302 | MOV WORD PTR ES:[DI].sf_size+2,AX | ||
| 303 | MOV AX,bPosL | ||
| 304 | MOV DX,bPosH | ||
| 305 | MOV WORD PTR ES:[DI.sf_position],AX | ||
| 306 | XCHG WORD PTR ES:[DI.sf_position+2],DX | ||
| 307 | PUSH DX ; save away Open age. | ||
| 308 | MOV CX,cByte ; cResult = | ||
| 309 | |||
| 310 | ; int 3 | ||
| 311 | |||
| 312 | MOV DI,OFFSET DOSGroup:DOS_Read ; *(OP&FCBRead ? DOS_Read | ||
| 313 | TEST FCBOp,FCBRead ; : DOS_Write)(cRec); | ||
| 314 | JNZ DoContext | ||
| 315 | MOV DI,OFFSET DOSGroup:DOS_Write | ||
| 316 | DoContext: | ||
| 317 | SaveReg <BP,DS,SI> | ||
| 318 | Context DS | ||
| 319 | ;; Fix for disk full | ||
| 320 | CALL DI | ||
| 321 | RestoreReg <SI,DS,BP> | ||
| 322 | ASSUME DS:NOTHING | ||
| 323 | |||
| 324 | IF BUFFERFLAG | ||
| 325 | pushf | ||
| 326 | push ax | ||
| 327 | push bx | ||
| 328 | |||
| 329 | cmp cs:[BUF_EMS_MODE], -1 | ||
| 330 | jz dos_fcb_call_done | ||
| 331 | call restore_user_map | ||
| 332 | mov ax, word ptr cs:[BUF_EMS_LAST_PAGE] | ||
| 333 | cmp cs:[BUF_EMS_PFRAME], ax | ||
| 334 | je dos_fcb_call_done | ||
| 335 | mov word ptr cs:[LASTBUFFER], -1 | ||
| 336 | mov cs:[BUF_EMS_PFRAME], ax | ||
| 337 | mov ax, word ptr cs:[BUF_EMS_LAST_PAGE+2] | ||
| 338 | mov cs:[BUF_EMS_PAGE_FRAME], ax | ||
| 339 | mov cs:[BUF_EMS_SAFE_FLAG], 1 | ||
| 340 | call Setup_EMS_Buffers | ||
| 341 | |||
| 342 | dos_fcb_call_done: | ||
| 343 | pop bx | ||
| 344 | pop ax | ||
| 345 | popf | ||
| 346 | ENDIF | ||
| 347 | |||
| 348 | JC FCBDeath | ||
| 349 | |||
| 350 | CMP BYTE PTR [DISK_FULL],0 ; treat disk full as error | ||
| 351 | JZ NODSKFULL | ||
| 352 | MOV BYTE PTR [DISK_FULL],0 ; clear the flag | ||
| 353 | MOV FCBerr,FEOF ; set disk full flag | ||
| 354 | NODSKFULL: | ||
| 355 | ;; Fix for disk full | ||
| 356 | MOV cResult,CX | ||
| 357 | invoke SaveFCBInfo ; SaveFCBInfo (FCB); | ||
| 358 | Assert ISSFT,<ES,DI>,"FCBIO/SaveFCBInfo" | ||
| 359 | %out WARNING!!! Make sure sf_position+2 is OpenAGE | ||
| 360 | POP WORD PTR ES:[DI].sf_Position+2 ; restore open age | ||
| 361 | MOV AX,WORD PTR ES:[DI].sf_size | ||
| 362 | MOV WORD PTR [SI].fcb_filsiz,AX | ||
| 363 | MOV AX,WORD PTR ES:[DI].sf_size+2 | ||
| 364 | MOV WORD PTR [SI].fcb_filsiz+2,AX | ||
| 365 | ; } | ||
| 366 | SkipOp: | ||
| 367 | MOV AX,cResult ; cRecRes = cResult / RecSize; | ||
| 368 | XOR DX,DX | ||
| 369 | DIV RecSize | ||
| 370 | MOV cRecRes,AX | ||
| 371 | ADD RecPosL,AX ; RecPos += cRecResult; | ||
| 372 | ADC RecPosH,0 | ||
| 373 | ; | ||
| 374 | ; If we have not gotten the expected number of records, we signal an EOF | ||
| 375 | ; condition. On input, this is EOF. On output this is usually disk full. | ||
| 376 | ; BUT... Under 2.0 and before, all device output IGNORED this condition. So | ||
| 377 | ; do we. | ||
| 378 | ; | ||
| 379 | CMP AX,cRec ; if (cRecRes <> cRec) | ||
| 380 | JZ TryBlank | ||
| 381 | TEST FCBOp,FCBRead ; if (OP&FCBRead || !DEVICE) | ||
| 382 | JNZ SetEOF | ||
| 383 | TEST ES:[DI].sf_flags,devid_device | ||
| 384 | JNZ TryBlank | ||
| 385 | SetEOF: | ||
| 386 | MOV FCBErr,FEOF ; FCBErr = FEOF; | ||
| 387 | TryBlank: ; | ||
| 388 | OR DX,DX ; if (cResult%RecSize <> 0) { | ||
| 389 | JZ SetExt | ||
| 390 | ADD RecPosL,1 ; RecPos++; | ||
| 391 | ADC RecPosH,0 | ||
| 392 | TEST FCBOp,FCBRead ; if(OP&FCBRead) <> 0) { | ||
| 393 | JZ SetExt | ||
| 394 | INC cRecRes ; cRecRes++; | ||
| 395 | MOV FCBErr,FTRIM + FEOF ; FCBErr = FTRIM | FEOF; | ||
| 396 | MOV CX,RecSize ; Blank (RecSize-cResult%RecSize, | ||
| 397 | SUB CX,DX ; DMA+cResult); | ||
| 398 | XOR AL,AL | ||
| 399 | LES DI,DMAAdd | ||
| 400 | ADD DI,cResult | ||
| 401 | REP STOSB ; } } | ||
| 402 | SetExt: | ||
| 403 | MOV DX,RecPosH | ||
| 404 | MOV AX,RecPosL | ||
| 405 | TEST FCBOp,RANDOM ; if ((OP&Random) == 0 || | ||
| 406 | JZ DoSetExt | ||
| 407 | TEST FCBOp,BLOCK ; (OP&BLOCK) <> 0) | ||
| 408 | JZ TrySetRR | ||
| 409 | DoSetExt: | ||
| 410 | invoke SetExtent ; SetExtent (RecPos, FCB); | ||
| 411 | TrySetRR: | ||
| 412 | TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0) | ||
| 413 | JZ TryReturn | ||
| 414 | MOV WORD PTR [SI.FCB_RR],AX ; FCB->RR = RecPos; | ||
| 415 | MOV BYTE PTR [SI.FCB_RR+2],DL | ||
| 416 | CMP [SI.fcb_RECSIZ],64 | ||
| 417 | JAE TryReturn | ||
| 418 | MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64 | ||
| 419 | TryReturn: | ||
| 420 | TEST FCBOP,FCBRead ; if (!(FCBOP & FCBREAD)) { | ||
| 421 | JNZ FCBSave | ||
| 422 | SaveReg <DS> ; FCB->FDate = date; | ||
| 423 | Invoke Date16 ; FCB->FTime = time; | ||
| 424 | RestoreReg <DS> | ||
| 425 | MOV [SI].FCB_FDate,AX | ||
| 426 | MOV [SI].FCB_FTime,DX ; } | ||
| 427 | FCBSave: | ||
| 428 | TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0) | ||
| 429 | JZ DoReturn | ||
| 430 | MOV CX,cRecRes ; user_CX = cRecRes; | ||
| 431 | invoke Get_User_Stack | ||
| 432 | MOV [SI.User_CX],CX | ||
| 433 | DoReturn: | ||
| 434 | MOV AL,FCBErr ; return (FCBERR); | ||
| 435 | Leave | ||
| 436 | return | ||
| 437 | EndProc FCBIO | ||
| 438 | |||
| 439 | Break <$FCB_Open - open an old-style FCB> | ||
| 440 | |||
| 441 | ; | ||
| 442 | ; $FCB_Open - CPM compatability file open. The user has formatted an FCB | ||
| 443 | ; for us and asked to have the rest filled in. | ||
| 444 | ; | ||
| 445 | ; Inputs: DS:DX point to an unopenned FCB | ||
| 446 | ; Outputs: AL indicates status 0 is ok FF is error | ||
| 447 | ; FCB has the following fields filled in: | ||
| 448 | ; Time/Date Extent/NR Size | ||
| 449 | |||
| 450 | Procedure $FCB_Open,NEAR | ||
| 451 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 452 | MOV AX,sharing_Compat+Open_For_Both | ||
| 453 | MOV CX,OFFSET DOSGroup:DOS_Open | ||
| 454 | ; | ||
| 455 | ; The following is common code for Creation and openning of FCBs. AX is | ||
| 456 | ; either attributes (for create) or open mode (for open)... DS:DX points to | ||
| 457 | ; the FCB | ||
| 458 | ; | ||
| 459 | DoAccess: | ||
| 460 | SaveReg <DS,DX,CX,AX> ; save FCB pointer away | ||
| 461 | MOV DI,OFFSET DOSGroup:OpenBuf | ||
| 462 | invoke TransFCB ; crunch the fcb | ||
| 463 | RestoreReg <AX,CX,DX,DS> ; get fcb | ||
| 464 | JNC FindFCB ; everything seems ok | ||
| 465 | FCBOpenErr: | ||
| 466 | ; | ||
| 467 | ; AL has error code | ||
| 468 | ; | ||
| 469 | transfer FCB_Ret_Err | ||
| 470 | FindFCB: | ||
| 471 | invoke GetExtended ; DS:SI will point to FCB | ||
| 472 | invoke LRUFCB ; get a sft entry (no error) | ||
| 473 | JC HardMessage | ||
| 474 | ASSUME ES:NOTHING | ||
| 475 | |||
| 476 | ; Message 1,"Entering " | ||
| 477 | ; MessageNum ES | ||
| 478 | ; Message 1,":" | ||
| 479 | ; MessageNum DI | ||
| 480 | ; Message 1,<13,10> | ||
| 481 | |||
| 482 | MOV ES:[DI].sf_mode,sf_ISFCB | ||
| 483 | SaveReg <DS,SI,BX> ; save fcb pointer | ||
| 484 | MOV SI,CX | ||
| 485 | Context DS ; let DOS_Open see variables | ||
| 486 | CALL SI ; go open the file | ||
| 487 | RestoreReg <BX,SI,DS> ; get fcb | ||
| 488 | ASSUME DS:NOTHING | ||
| 489 | LES DI,ThisSFT ; get sf pointer | ||
| 490 | JNC FCBOK ; operation succeeded | ||
| 491 | Assert ISSFT,<ES,DI>,"DeadFCB" | ||
| 492 | failopen: | ||
| 493 | PUSH AX | ||
| 494 | MOV AL,"R" ; clear out field (free sft) | ||
| 495 | invoke BlastSFT | ||
| 496 | POP AX | ||
| 497 | CMP AX,error_too_many_open_files | ||
| 498 | JZ HardMessage | ||
| 499 | CMP AX,error_sharing_buffer_exceeded | ||
| 500 | jnz DeadFCB | ||
| 501 | HardMessage: | ||
| 502 | PUSH AX | ||
| 503 | invoke FCBHardErr | ||
| 504 | POP AX | ||
| 505 | DeadFCB: | ||
| 506 | transfer FCB_Ret_Err | ||
| 507 | FCBOK: | ||
| 508 | invoke IsSFTNet ;AN007;F.C. >32mb Non Fat file? | ||
| 509 | JNZ FCBOK2 ;AN007;F.C. >32mb yes | ||
| 510 | invoke CheckShare ;AN000;F.C. >32mb share around? | ||
| 511 | JNZ FCBOK2 ;AN000;F.C. >32mb yes | ||
| 512 | CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb if dirsec >32mb | ||
| 513 | JZ FCBOK2 ;AN000;F.C. >32mb then error | ||
| 514 | MOV AX,error_sys_comp_not_loaded ;AN000;F.C. >32mb | ||
| 515 | JMP failopen ;AN000;F.C. >32mb | ||
| 516 | FCBOK2: | ||
| 517 | |||
| 518 | INC ES:[DI].sf_ref_count ; increment reference count | ||
| 519 | invoke SaveFCBInfo | ||
| 520 | Assert ISSFT,<ES,DI>,"FCBOK" | ||
| 521 | invoke SetOpenAge | ||
| 522 | Assert ISSFT,<ES,DI>,"FCBOK/SetOpenAge" | ||
| 523 | TEST ES:[DI].sf_flags,devid_device | ||
| 524 | JNZ FCBNoDrive ; do not munge drive on devices | ||
| 525 | MOV AL,DS:[SI] ; get drive byte | ||
| 526 | invoke GetThisDrv ; convert | ||
| 527 | INC AL | ||
| 528 | MOV DS:[SI],AL ; stash in good drive letter | ||
| 529 | FCBNoDrive: | ||
| 530 | MOV [SI].FCB_RecSiz,80h ; stuff in default record size | ||
| 531 | MOV AX,ES:[DI].SF_Time ; set time | ||
| 532 | MOV [SI].FCB_FTime,AX | ||
| 533 | MOV AX,ES:[DI].SF_Date ; set date | ||
| 534 | MOV [SI].FCB_FDate,AX | ||
| 535 | MOV AX,WORD PTR ES:[DI].SF_Size ; set sizes | ||
| 536 | MOV [SI].FCB_FILSIZ,AX | ||
| 537 | MOV AX,WORD PTR ES:[DI].SF_Size+2 | ||
| 538 | MOV [SI].FCB_FILSIZ+2,AX | ||
| 539 | XOR AX,AX ; convenient zero | ||
| 540 | MOV [SI].FCB_Extent,AX ; point to beginning of file | ||
| 541 | ; | ||
| 542 | ; We must scan the set of FCB SFTs for one that appears to match the current | ||
| 543 | ; one. We cheat and use CheckFCB to match the FCBs. | ||
| 544 | ; | ||
| 545 | LES DI,SFTFCB ; get the pointer to head of the list | ||
| 546 | MOV AH,BYTE PTR ES:[DI].sfCount ; get number of SFTs to scan | ||
| 547 | OpenScan: | ||
| 548 | CMP AL,[SI].fcb_sfn ; don't compare ourselves | ||
| 549 | JZ SkipCheck | ||
| 550 | SaveReg <AX> ; preserve count | ||
| 551 | invoke CheckFCB ; do they match | ||
| 552 | RestoreReg <AX> ; get count back | ||
| 553 | JNC OpenFound ; found a match! | ||
| 554 | SkipCheck: | ||
| 555 | INC AL ; advance to next FCB | ||
| 556 | CMP AL,AH ; table full? | ||
| 557 | JNZ OpenScan ; no, go for more | ||
| 558 | OpenDone: | ||
| 559 | xor al,al ; return success | ||
| 560 | return | ||
| 561 | ; | ||
| 562 | ; The SFT at ES:DI is the one that is already in use for this FCB. We set the | ||
| 563 | ; FCB to use this one. We increment its ref count. We do NOT close it at all. | ||
| 564 | ; Consider: | ||
| 565 | ; | ||
| 566 | ; open (foo) delete (foo) open (bar) | ||
| 567 | ; | ||
| 568 | ; This causes us to recycle (potentially) bar through the same local SFT as | ||
| 569 | ; foo even though foo is no longer needed; this is due to the server closing | ||
| 570 | ; foo for us when we delete it. Unfortunately, we cannot see this closure. | ||
| 571 | ; If we were to CLOSE bar, the server would then close the only reference to | ||
| 572 | ; bar and subsequent I/O would be lost to the redirector. | ||
| 573 | ; | ||
| 574 | ; This gets solved by NOT closing the sft, but zeroing the ref count | ||
| 575 | ; (effectively freeing the SFT) and informing the sharer (if relevant) that | ||
| 576 | ; the SFT is no longer in use. Note that the SHARER MUST keep its ref counts | ||
| 577 | ; around. This will allow us to access the same file through multiple network | ||
| 578 | ; connections and NOT prematurely terminate when the ref count on one | ||
| 579 | ; connection goes to zero. | ||
| 580 | ; | ||
| 581 | OpenFound: | ||
| 582 | MOV [SI].fcb_SFN,AL ; assign with this | ||
| 583 | INC ES:[DI].sf_ref_count ; remember this new invocation | ||
| 584 | MOV AX,FCBLRU ; update LRU counts | ||
| 585 | MOV ES:[DI].sf_LRU,AX | ||
| 586 | ; | ||
| 587 | ; We have an FCB sft that is now of no use. We release sharing info and then | ||
| 588 | ; blast it to prevent other reuse. | ||
| 589 | ; | ||
| 590 | context DS | ||
| 591 | LES DI,ThisSFT | ||
| 592 | DEC ES:[DI].sf_ref_count ; free the newly allocated SFT | ||
| 593 | invoke ShareEnd | ||
| 594 | Assert ISSFT,<ES,DI>,"Open blasting" | ||
| 595 | MOV AL,'C' | ||
| 596 | invoke BlastSFT | ||
| 597 | JMP OpenDone | ||
| 598 | EndProc $FCB_Open | ||
| 599 | |||
| 600 | BREAK <$FCB_Create - create a new directory entry> | ||
| 601 | |||
| 602 | ; | ||
| 603 | ; $FCB_Create - CPM compatability file create. The user has formatted an | ||
| 604 | ; FCB for us and asked to have the rest filled in. | ||
| 605 | ; | ||
| 606 | ; Inputs: DS:DX point to an unopenned FCB | ||
| 607 | ; Outputs: AL indicates status 0 is ok FF is error | ||
| 608 | ; FCB has the following fields filled in: | ||
| 609 | ; Time/Date Extent/NR Size | ||
| 610 | |||
| 611 | Procedure $FCB_Create,NEAR | ||
| 612 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 613 | MOV CX,OFFSET DOSGroup:DOS_Create ; routine to call | ||
| 614 | XOR AX,AX ; attributes to create | ||
| 615 | invoke GetExtended ; get extended FCB | ||
| 616 | JZ DoAccessJ ; not an extended FCB | ||
| 617 | MOV AL,[SI-1] ; get attributes | ||
| 618 | DoAccessJ: | ||
| 619 | JMP DoAccess ; do dirty work | ||
| 620 | EndProc $FCB_Create | ||
| 621 | |||
| 622 | BREAK <$FCB_Random_write_Block - write a block of records to a file > | ||
| 623 | |||
| 624 | ; | ||
| 625 | ; $FCB_Random_Write_Block - retrieve a location from the FCB, seek to it | ||
| 626 | ; and write a number of blocks from it. | ||
| 627 | ; | ||
| 628 | ; Inputs: DS:DX point to an FCB | ||
| 629 | ; Outputs: AL = 0 write was successful and the FCB position is updated | ||
| 630 | ; AL <> 0 Not enough room on disk for the output | ||
| 631 | ; | ||
| 632 | |||
| 633 | Procedure $FCB_Random_Write_Block,NEAR | ||
| 634 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 635 | MOV AL,Random+Block | ||
| 636 | JMP FCBIO | ||
| 637 | EndProc $FCB_Random_Write_Block | ||
| 638 | |||
| 639 | BREAK <$FCB_Random_Read_Block - read a block of records to a file > | ||
| 640 | |||
| 641 | ; | ||
| 642 | ; $FCB_Random_Read_Block - retrieve a location from the FCB, seek to it | ||
| 643 | ; and read a number of blocks from it. | ||
| 644 | ; | ||
| 645 | ; Inputs: DS:DX point to an FCB | ||
| 646 | ; Outputs: AL = error codes defined above | ||
| 647 | ; | ||
| 648 | |||
| 649 | Procedure $FCB_Random_Read_Block,NEAR | ||
| 650 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 651 | MOV AL,Random+FCBRead+Block | ||
| 652 | JMP FCBIO | ||
| 653 | EndProc $FCB_Random_Read_Block | ||
| 654 | |||
| 655 | BREAK <$FCB_Seq_Read - read the next record from a file > | ||
| 656 | |||
| 657 | ; | ||
| 658 | ; $FCB_Seq_Read - retrieve the next record from an FCB and read it into | ||
| 659 | ; memory | ||
| 660 | ; | ||
| 661 | ; Inputs: DS:DX point to an FCB | ||
| 662 | ; Outputs: AL = error codes defined above | ||
| 663 | ; | ||
| 664 | |||
| 665 | Procedure $FCB_Seq_Read,NEAR | ||
| 666 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 667 | MOV AL,FCBRead | ||
| 668 | JMP FCBIO | ||
| 669 | EndProc $FCB_Seq_Read | ||
| 670 | |||
| 671 | BREAK <$FCB_Seq_Write - write the next record to a file > | ||
| 672 | |||
| 673 | ; | ||
| 674 | ; $FCB_Seq_Write - retrieve the next record from an FCB and write it to the | ||
| 675 | ; file | ||
| 676 | ; | ||
| 677 | ; Inputs: DS:DX point to an FCB | ||
| 678 | ; Outputs: AL = error codes defined above | ||
| 679 | ; | ||
| 680 | |||
| 681 | Procedure $FCB_Seq_Write,NEAR | ||
| 682 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 683 | MOV AL,0 | ||
| 684 | jmp FCBIO | ||
| 685 | EndProc $FCB_SEQ_WRITE | ||
| 686 | |||
| 687 | BREAK <$FCB_Random_Read - Read a single record from a file > | ||
| 688 | |||
| 689 | ; | ||
| 690 | ; $FCB_Random_Read - retrieve a location from the FCB, seek to it and read a | ||
| 691 | ; record from it. | ||
| 692 | ; | ||
| 693 | ; Inputs: DS:DX point to an FCB | ||
| 694 | ; Outputs: AL = error codes defined above | ||
| 695 | ; | ||
| 696 | |||
| 697 | Procedure $FCB_Random_Read,NEAR | ||
| 698 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 699 | MOV AL,Random+FCBRead | ||
| 700 | jmp FCBIO ; single block | ||
| 701 | EndProc $FCB_RANDOM_READ | ||
| 702 | |||
| 703 | BREAK <$FCB_Random_Write - write a single record to a file > | ||
| 704 | |||
| 705 | ; | ||
| 706 | ; $FCB_Random_Write - retrieve a location from the FCB, seek to it and write | ||
| 707 | ; a record to it. | ||
| 708 | ; | ||
| 709 | ; Inputs: DS:DX point to an FCB | ||
| 710 | ; Outputs: AL = error codes defined above | ||
| 711 | ; | ||
| 712 | |||
| 713 | Procedure $FCB_Random_Write,NEAR | ||
| 714 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 715 | MOV AL,Random | ||
| 716 | jmp FCBIO | ||
| 717 | EndProc $FCB_RANDOM_WRITE | ||
| 718 | |||
| 719 | CODE ENDS | ||
| 720 | END | ||
| 721 | |||
| 722 | \ No newline at end of file | ||