; SCCSID = @(#)disk.asm 1.1 85/04/10 ; SCCSID = @(#)disk.asm 1.1 85/04/10 TITLE DISK - Disk utility routines NAME Disk ; Low level Read and write routines for local SFT I/O on files and devs ; ; SWAPCON ; SWAPBACK ; DOS_READ ; DOS_WRITE ; get_io_sft ; DirRead ; FIRSTCLUSTER ; SET_BUF_AS_DIR ; FATSecRd ; DREAD ; CHECK_WRITE_LOCK ; CHECK_READ_LOCK ; ; Revision history: ; ; A000 version 4.00 Jan. 1988 ; ; ; get the appropriate segment definitions ; .xlist include dosseg.asm include fastseek.inc ;AN000; include fastxxxx.inc ;AN000; CODE SEGMENT BYTE PUBLIC 'CODE' ASSUME SS:DOSGROUP,CS:DOSGROUP .xcref INCLUDE DOSSYM.INC INCLUDE DEVSYM.INC include version.inc .cref .list Installed = TRUE I_need DirStart,WORD I_Need CONSft,DWORD ; SFT for swapped console In/Out i_need CONSWAP,BYTE i_need IDLEINT,BYTE i_need THISSFT,DWORD i_need DMAADD,DWORD i_need DEVCALL,BYTE i_need CALLSCNT,WORD i_need CALLXAD,DWORD i_need CONTPOS,WORD i_need NEXTADD,WORD i_need CONBUF,BYTE i_need ClusFac,BYTE i_need SecClusPos,BYTE i_need DirSec,DWORD ;AN000; i_need ClusNum,WORD i_need NxtClusNum,WORD i_need ReadOp,BYTE i_need CURBUF,DWORD i_need ALLOWED,BYTE i_need EXTERR_LOCUS,BYTE i_need FastSeekflg,BYTE ;AN000; i_need HIGH_SECTOR,WORD ;AN000; I_need JShare,DWORD ;AN000; i_need DOS34_FLAG,WORD ;AN000; IF BUFFERFLAG i_need BUF_EMS_MODE,BYTE i_need BUF_EMS_LAST_PAGE,BYTE I_need BUF_EMS_FIRST_PAGE,DWORD I_need BUF_EMS_SAFE_FLAG,BYTE I_need BUF_EMS_NPA640,WORD I_need BUF_EMS_PAGE_FRAME,WORD I_need BUF_EMS_PFRAME,WORD I_need LASTBUFFER,DWORD extrn save_user_map:near extrn restore_user_map:near extrn Setup_EMS_Buffers:near ENDIF Break ; * * * * Drivers for file input from devices * * * * ; Indicate that ther is no more I/O occurring through another SFT outside of ; handles 0 and 1 ; ; Inputs: DS is DOSGroup ; Outputs: CONSWAP is set to false. ; Registers modified: none procedure SWAPBACK,NEAR DOSAssume CS,,"SwapBack" ASSUME ES:NOTHING MOV BYTE PTR [CONSWAP],0 ; signal no conswaps return EndProc SWAPBACK ; Copy ThisSFT to CONSFT for use by the 1-12 primitives. ; ; Inputs: ThisSFT as the sft of the desired file ; DS is DOSGroup ; Outputs: CONSWAP is set. CONSFT = ThisSFT. ; Registers modified: none procedure SWAPCON,NEAR DOSAssume CS,,"SwapCon" ASSUME ES:NOTHING SaveReg MOV BYTE PTR [CONSWAP],1 ; CONSwap = TRUE; LES DI,ThisSFT Assert ISSFT,,"SwapCon" MOV WORD PTR CONSFT,DI MOV WORD PTR CONSFT+2,ES RestoreReg return EndProc SWAPCON Break ; ; Inputs: ; [THISSFT] set to the SFT for the file being used ; [DMAADD] contains transfer address ; CX = No. of bytes to read ; Function: ; Perform read operation ; Outputs: ; Carry clear ; SFT Position and cluster pointers updated ; CX = No. of bytes read ; ES:DI point to SFT ; Carry set ; AX is error code ; CX = 0 ; ES:DI point to SFT ; DS preserved, all other registers destroyed procedure DOS_READ,NEAR DOSAssume CS,,"DOS_Read" ASSUME ES:NOTHING IF BUFFERFLAG cmp [BUF_EMS_MODE], -1 jz dos_rd_call call choose_buf_page jnc sav_map_rd_hndl return sav_map_rd_hndl: ; call save_user_map dos_rd_call: ENDIF LES DI,[THISSFT] Assert ISSFT,,"DOS_Read" ; ; Verify that the sft has been opened in a mode that allows reading. ; MOV AL,BYTE PTR ES:[DI.sf_mode] AND AL,access_mask CMP AL,open_for_write JNE READ_NO_MODE ;Is read or both transfer SET_ACC_ERR READ_NO_MODE: invoke SETUP JCXZ NoIORet ; no bytes to read - fast return invoke IsSFTNet JZ LOCAL_READ ; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? ; JZ IFS_HAS_SHARE ;AN000;;IFS. yes ; EnterCrit critDisk ;AN000;;IFS. enter critical section ; CALL CHECK_READ_LOCK ;AN000;;IFS. check read lock ; JNC READ_OK2 ;AN000;;IFS. lock check ok ; JMP SHORT critexit ;AN000;;IFS. fail READ_OK2: ;AN000; ; LeaveCrit critDisk ;AN000;;IFS. leave critical section IFS_HAS_SHARE: ;AN000; IF NOT Installed transfer NET_READ ELSE MOV AX,(multNET SHL 8) OR 8 INT 2FH return ENDIF ; ; The user ended up requesting 0 bytes of input. We do nothing for this case ; except return immediately. ; NoIORet: CLC return LOCAL_READ: TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O JNZ READDEV MOV [EXTERR_LOCUS],errLOC_Disk EnterCrit critDisk TEST [FastSeekflg],Fast_yes ; FastSeek installed ? JZ FS_no ; no OR [FastSeekflg],FS_begin ; set fastseek mode FS_no: invoke DISKREAD PUSHF ; save flag AND CS:[FastSeekflg],FS_end ; reset fastseek mode POPF ; retore flag critexit: LeaveCrit critDisk return ; ; We are reading from a device. Examine the status of the device to see if we ; can short-circuit the I/O. If the device in the EOF state or if it is the ; null device, we can safely indicate no transfer. ; READDEV: DOSAssume CS,,"DISK/ReadDev" ASSUME ES:NOTHING MOV [EXTERR_LOCUS],errLOC_SerDev MOV BL,BYTE PTR ES:[DI.sf_flags] LES DI,[DMAADD] TEST BL,devid_device_EOF ; End of file? JZ ENDRDDEVJ3 TEST BL,devid_device_null ; NUL device? JZ TESTRAW ; NO XOR AL,AL ; Indicate EOF by setting zero ENDRDDEVJ3: JMP ENDRDDEVJ2 ; ; We need to hit the device. Figure out if we do a raw read or we do the ; bizarre std_con_string_input. ; TESTRAW: TEST BL,devid_device_raw ; Raw mode? JNZ DVRDRAW ; Yes, let the device do all local editing TEST BL,devid_device_con_in ; Is it console device? JZ NOTRDCON JMP READCON DVRDRAW: DOSAssume CS,,"DISK/DvRdRaw" PUSH ES POP DS ; Xaddr to DS:DI ASSUME DS:NOTHING ReadRawRetry: MOV BX,DI ; DS:BX transfer addr XOR AX,AX ; Media Byte, unit = 0 MOV DX,AX ; Start at 0 invoke SETREAD PUSH DS ; Save Seg part of Xaddr LDS SI,[THISSFT] Assert ISSFT,,"DOS_Read/DvRdRawR" invoke DEVIOCALL MOV DX,DI ; DS:DX is preserved by INT 24 MOV AH,86H ; Read error MOV DI,[DEVCALL.REQSTAT] TEST DI,STERR JZ CRDROK ; No errors invoke CHARHARD MOV DI,DX ; DS:DI is Xaddr OR AL,AL JZ CRDROK ; Ignore CMP AL,3 JZ CRDFERR ; fail. POP DS ; Recover saved seg part of Xaddr JMP ReadRawRetry ; Retry ; ; We have encountered a device-driver error. We have informed the user of it ; and he has said for us to fail the system call. ; CRDFERR: POP DI ; Clean stack DEVIOFERR: LES DI,[THISSFT] Assert ISSFT,,"DOS_Read/DEVIOFERR" transfer SET_ACC_ERR_DS CRDROK: POP DI ; Chuck saved seg of Xaddr MOV DI,DX ADD DI,[CALLSCNT] ; Amount transferred JMP SHORT ENDRDDEVJ3 ; We are going to do a cooked read on some character device. There is a ; problem here, what does the data look like? Is it a terminal device, line ; CR line CR line CR, or is it file data, line CR LF line CR LF? Does it have ; a ^Z at the end which is data, or is the ^Z not data? In any event we're ; going to do this: Read in pieces up to CR (CRs included in data) or ^z (^z ; included in data). this "simulates" the way con works in cooked mode ; reading one line at a time. With file data, however, the lines will look ; like, LF line CR. This is a little weird. NOTRDCON: MOV AX,ES MOV DS,AX ASSUME DS:NOTHING MOV BX,DI XOR DX,DX MOV AX,DX PUSH CX MOV CX,1 invoke SETREAD POP CX LDS SI,[THISSFT] Assert ISSFT,,"DOS_Read/NotRdCon" LDS SI,[SI.sf_devptr] DVRDLP: invoke DSKSTATCHK invoke DEVIOCALL2 PUSH DI ; Save "count" done MOV AH,86H MOV DI,[DEVCALL.REQSTAT] TEST DI,STERR JZ CRDOK invoke CHARHARD POP DI MOV [CALLSCNT],1 CMP AL,1 JZ DVRDLP ;Retry CMP AL,3 JZ DEVIOFERR ; FAIL XOR AL,AL ; Ignore, Pick some random character JMP SHORT DVRDIGN CRDOK: POP DI CMP [CALLSCNT],1 JNZ ENDRDDEVJ2 PUSH DS MOV DS,WORD PTR [CALLXAD+2] MOV AL,BYTE PTR [DI] ; Get the character we just read POP DS DVRDIGN: INC WORD PTR [CALLXAD] ; Next character MOV [DEVCALL.REQSTAT],0 INC DI ; Next character CMP AL,1AH ; ^Z? JZ ENDRDDEVJ2 ; Yes, done zero set (EOF) CMP AL,c_CR ; CR? LOOPNZ DVRDLP ; Loop if no, else done INC AX ; Resets zero flag so NOT EOF, unless ; AX=FFFF which is not likely ENDRDDEVJ2: JMP SHORT ENDRDDEV ASSUME DS:NOTHING,ES:NOTHING TRANBUF: LODSB STOSB CMP AL,c_CR ; Check for carriage return JNZ NORMCH MOV BYTE PTR [SI],c_LF NORMCH: CMP AL,c_LF LOOPNZ TRANBUF JNZ ENDRDCON XOR SI,SI ; Cause a new buffer to be read invoke OUTT ; Transmit linefeed OR AL,1 ; Clear zero flag--not end of file ENDRDCON: Context DS CALL SWAPBACK MOV [CONTPOS],SI ENDRDDEV: Context DS MOV [NEXTADD],DI JNZ SETSFTC ; Zero set if Ctrl-Z found in input LES DI,[THISSFT] Assert ISSFT,,"DOS_Read/EndRdDev" AND BYTE PTR ES:[DI.sf_flags],NOT devid_device_EOF ; Mark as no more data available SETSFTC: invoke SETSFT return ASSUME DS:NOTHING,ES:NOTHING READCON: DOSAssume CS,,"ReadCon" CALL SWAPCON MOV SI,[CONTPOS] OR SI,SI JNZ TRANBUF CMP BYTE PTR [CONBUF],128 JZ GETBUF MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template GETBUF: PUSH CX PUSH ES PUSH DI MOV DX,OFFSET DOSGROUP:CONBUF invoke $STD_CON_STRING_INPUT ; Get input buffer POP DI POP ES POP CX MOV SI,2 + OFFSET DOSGROUP:CONBUF CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character JNZ TRANBUF MOV AL,1AH STOSB DEC DI MOV AL,c_LF invoke OUTT ; Send linefeed XOR SI,SI JMP ENDRDCON EndProc DOS_READ Break ; ; Inputs: ; [THISSFT] set to the SFT for the file being used ; [DMAADD] contains transfer address ; CX = No. of bytes to write ; Function: ; Perform write operation ; NOTE: If CX = 0 on input, file is truncated or grown ; to current sf_position ; Outputs: ; Carry clear ; SFT Position and cluster pointers updated ; CX = No. of bytes written ; ES:DI point to SFT ; Carry set ; AX is error code ; CX = 0 ; ES:DI point to SFT ; DS preserved, all other registers destroyed procedure DOS_WRITE,NEAR DOSAssume CS,,"DOS_Write" ASSUME ES:NOTHING IF BUFFERFLAG cmp [BUF_EMS_MODE], -1 jz dos_wrt_call call choose_buf_page jnc sav_map_wrt_hndl return sav_map_wrt_hndl: ; call save_user_map dos_wrt_call: ENDIF LES DI,[THISSFT] Assert ISSFT,,"DosWrite" MOV AL,BYTE PTR ES:[DI.sf_mode] AND AL,access_mask CMP AL,open_for_read JNE Check_FCB_RO ;Is write or both BadMode: transfer SET_ACC_ERR ; ; NOTE: The following check for writting to a Read Only File is performed ; ONLY on FCBs!!!! ; We ALLOW writes to Read Only files via handles to allow a CREATE ; of a read only file which can then be written to. ; This is OK because we are NOT ALLOWED to OPEN a RO file via handles ; for writting, or RE-CREATE an EXISTING RO file via handles. Thus, ; CREATing a NEW RO file, or RE-CREATing an existing file which ; is NOT RO to be RO, via handles are the only times we can write ; to a read-only file. ; Check_FCB_RO: TEST ES:[DI.sf_mode],sf_isfcb JZ WRITE_NO_MODE ; Not an FCB TEST ES:[DI].sf_attr,attr_read_only JNZ BadMode ; Can't write to Read_Only files via FCB WRITE_NO_MODE: invoke SETUP invoke IsSFTNet JZ LOCAL_WRITE ; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? ; JZ IFS_HAS_SHARE2 ;AN000;;IFS. yes ; EnterCrit critDisk ;AN000;;IFS. enter critical section ; CALL CHECK_WRITE_LOCK ;AN000;;IFS. check write lock ; JC nocommit ;AN000;;IFS. lock error ; ; LeaveCrit critDisk ;AN000;;IFS. leave critical section IFS_HAS_SHARE2: ;AN000; IF NOT Installed transfer NET_WRITE ELSE MOV AX,(multNET SHL 8) OR 9 INT 2FH ; JC nomore ;AN000;;IFS. error ; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? ; JZ nomore ;AN000;;IFS. yes ; ; MOV AX,1 ;AN000;;IFS. update all SFT for new size ; call JShare + 14 * 4 ;AN000;;IFS. call ShSu nomore: ;AN000; return ENDIF LOCAL_WRITE: TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O JNZ WRTDEV MOV [EXTERR_LOCUS],errLOC_Disk EnterCrit critDisk TEST [FastSeekflg],Fast_yes ;AN000;FO. FastSeek installed ? JZ FS_no2 ;AN000;FO. no OR [FastSeekflg],FS_begin ;AN000;FO. set fastseek mode FS_no2: ;AN000; invoke DISKWRITE PUSHF ;AN000;FO. save flag AND CS:[FastSeekflg],FS_end ;AN000;FO. reset fastseek mode POPF ;AN000;FO. restore flag ;; Extended Open JC nocommit ;AN000;EO. LES DI,[THISSFT] ;AN000;EO. TEST ES:[DI.sf_mode],auto_commit_write ;AN000;EO. JZ nocommit ;AN000;EO. PUSH CX ;AN000;EO. invoke DOS_COMMIT ;AN000;EO. POP CX ;AN000;EO. nocommit: ;AN000; ;; Extended Open LeaveCrit critDisk return DVWRTRAW: ASSUME DS:NOTHING XOR AX,AX ; Media Byte, unit = 0 invoke SETWRITE PUSH DS ; Save seg of transfer LDS SI,[THISSFT] Assert ISSFT,,"DosWrite/DvWrtRaw" invoke DEVIOCALL ; DS:SI -> DEVICE MOV DX,DI ; Offset part of Xaddr saved in DX MOV AH,87H MOV DI,[DEVCALL.REQSTAT] TEST DI,STERR JZ CWRTROK invoke CHARHARD MOV BX,DX ; Recall transfer addr OR AL,AL JZ CWRTROK ; Ignore CMP AL,3 JZ CWRFERR POP DS ; Recover saved seg of transfer JMP DVWRTRAW ; Try again CWRFERR: POP AX ; Chuck saved seg of transfer JMP CRDFERR ; Will pop one more stack element CWRTROK: POP AX ; Chuck saved seg of transfer POP DS DOSAssume CS,,"DISK/CWrtOK" MOV AX,[CALLSCNT] ; Get actual number of bytes transferred ENDWRDEV: LES DI,[THISSFT] Assert ISSFT,,"DosWrite/EndWrDev" MOV CX,AX invoke ADDREC return WRTNUL: MOV DX,CX ;Entire transfer done WrtCookJ: JMP WRTCOOKDONE WRTDEV: DOSAssume CS,,"DISK/WrtDev" MOV [EXTERR_LOCUS],errLOC_SerDev OR BYTE PTR ES:[DI.sf_flags],devid_device_EOF ; Reset EOF for input MOV BL,BYTE PTR ES:[DI.sf_flags] XOR AX,AX JCXZ ENDWRDEV ; problem of creating on a device. PUSH DS MOV AL,BL LDS BX,[DMAADD] ; Xaddr to DS:BX ASSUME DS:NOTHING MOV DI,BX ; Xaddr to DS:DI XOR DX,DX ; Set starting point TEST AL,devid_device_raw ; Raw? JZ TEST_DEV_CON JMP DVWRTRAW TEST_DEV_CON: TEST AL,devid_device_con_out ; Console output device? JNZ WRITECON TEST AL,devid_device_null JNZ WRTNUL MOV AX,DX CMP BYTE PTR [BX],1AH ; ^Z? JZ WRTCOOKJ ; Yes, transfer nothing PUSH CX MOV CX,1 invoke SETWRITE POP CX LDS SI,[THISSFT] OR CS:[DOS34_FLAG],X25_Special;AN000;;PTM. bad x25 driver MOV AH,3 ;AN000;;PTM. prompt critical error ASAP invoke IOFUNC ;AN000;;PTM. Assert ISSFT,,"DosWrite/TestDevCon" LDS SI,[SI.sf_devptr] DVWRTLP: invoke DSKSTATCHK invoke DEVIOCALL2 PUSH DI MOV AH,87H MOV DI,[DEVCALL.REQSTAT] TEST DI,STERR JZ CWROK invoke CHARHARD POP DI MOV [CALLSCNT],1 CMP AL,1 JZ DVWRTLP ; Retry OR AL,AL JZ DVWRTIGN ; Ignore JMP CRDFERR ; Fail, pops one stack element CWROK: POP DI CMP [CALLSCNT],0 JZ WRTCOOKDONE DVWRTIGN: INC DX INC WORD PTR [CALLXAD] INC DI PUSH DS MOV DS,WORD PTR [CALLXAD+2] CMP BYTE PTR [DI],1AH ; ^Z? POP DS JZ WRTCOOKDONE MOV [DEVCALL.REQSTAT],0 LOOP DVWRTLP WRTCOOKDONE: MOV AX,DX POP DS JMP ENDWRDEV WRITECON: PUSH DS Context DS CALL SWAPCON POP DS ASSUME DS:NOTHING MOV SI,BX PUSH CX WRCONLP: LODSB CMP AL,1AH ; ^Z? JZ CONEOF invoke OUTT LOOP WRCONLP CONEOF: POP AX ; Count SUB AX,CX ; Amount actually written POP DS DOSAssume CS,,"DISK/ConEOF" CALL SWAPBACK JMP ENDWRDEV EndProc DOS_WRITE ; Convert JFN number in BX to sf_entry in DS:SI We get the normal SFT if ; CONSWAP is FALSE or if the handle desired is 2 or more. Otherwise, we ; retrieve the sft from ConSFT which is set by SwapCon. procedure get_io_sft,near ASSUME DS:NOTHING,ES:NOTHING TEST ConSwap,-1 JNZ GetRedir GetNormal: Context DS PUSH ES PUSH DI invoke SFFromHandle JC RET44P MOV SI,ES MOV DS,SI ASSUME DS:NOTHING MOV SI,DI RET44P: POP DI POP ES return GetRedir: CMP BX,1 JA GetNormal LDS SI,ConSFT Assert ISSFT,,"GetIOSft" CLC return EndProc get_io_sft Break ; Inputs: ; AX = Directory block number (relative to first block of directory) ; ES:BP = Base of drive parameters ; [DIRSEC] = First sector of first cluster of directory ; [CLUSNUM] = Next cluster ; [CLUSFAC] = Sectors/Cluster ; Function: ; Read the directory block into [CURBUF]. ; Outputs: ; [NXTCLUSNUM] = Next cluster (after the one skipped to) ; [SECCLUSPOS] Set ; ES:BP unchanged ; [CURBUF] Points to Buffer with dir sector ; Carry set if error (user said FAIL to I 24) ; DS preserved, all other registers destroyed. procedure DirRead,NEAR DOSAssume CS,,"DirRead" ASSUME ES:NOTHING Assert ISDPB,,"DirRead" ; ; Note that ClusFac is is the sectors per cluster. This is NOT necessarily ; the same as what is in the DPB! In the case of the root directory, we have ; ClusFac = # sectors in the root directory. The root directory is detected ; by DIRStart = 0. ; XOR DX,DX CMP DirStart,0 jnz SubDir XCHG AX,DX JMP DoRead ; ; Convert the sector number in AX into cluster and sector-within-cluster pair ; SubDir: MOV DL,AL AND DL,ES:[BP.dpb_cluster_mask] ; ; DX is the sector-in-cluster ; MOV CL,ES:[BP.dpb_cluster_shift] SHR AX,CL ; ; DX is position in cluster ; AX is number of clusters to skip ; DoRead: MOV [SECCLUSPOS],DL MOV CX,AX MOV AH,DL ; ; CX is number of clusters to skip. ; AH is remainder ; MOV DX,WORD PTR [DIRSEC+2] ;AN000;>32mb MOV [HIGH_SECTOR],DX ;AN000;>32mb MOV DX,WORD PTR [DIRSEC] ADD DL,AH ADC DH,0 ADC [HIGH_SECTOR],0 ;AN000;>32mb MOV BX,[CLUSNUM] MOV [NXTCLUSNUM],BX JCXZ FIRSTCLUSTER SKPCLLP: invoke UNPACK retc XCHG BX,DI invoke IsEOF ; test for eof based on fat size JAE HAVESKIPPED LOOP SKPCLLP HAVESKIPPED: MOV [NXTCLUSNUM],BX MOV DX,DI MOV BL,AH invoke FIGREC entry FIRSTCLUSTER MOV [ALLOWED],allowed_RETRY + allowed_FAIL XOR AL,AL ; Indicate pre-read invoke GETBUFFR retc entry SET_BUF_AS_DIR DOSAssume CS,,"SET_BUF_AS_DIR" ASSUME ES:NOTHING ; Set the type of CURBUF to be a directory sector. ; Only flags are modified. PUSH DS PUSH SI LDS SI,[CURBUF] Assert ISBUF,,"SetBufAsDir" OR [SI.buf_flags],buf_isDIR ; Clears carry POP SI POP DS return EndProc DirRead Break ; Inputs: ; Same as DREAD ; DS:BX = Transfer address ; CX = Number of sectors ; DX = Absolute record number ; ES:BP = Base of drive parameters ; Function: ; Calls BIOS to perform FAT read. ; Outputs: ; Same as DREAD procedure FATSecRd,NEAR ASSUME DS:NOTHING,ES:NOTHING Assert ISDPB,,"FATSecRd" MOV [ALLOWED],allowed_RETRY + allowed_FAIL MOV DI,CX MOV CL,ES:[BP.dpb_FAT_count] MOV AX,ES:[BP.dpb_FAT_size] ;AN000;>32mb ; XOR AH,AH XOR CH,CH ;AN000;>32mb PUSH DX NXTFAT: MOV [HIGH_SECTOR],0 ;AN000;>32mb FAT sectors cannot exceed PUSH CX ;AN000;>32mb PUSH AX MOV CX,DI invoke DSKREAD POP AX POP CX JZ RET41P ; Carry clear ADD DX,AX LOOP NXTFAT POP DX MOV CX,DI ; NOTE FALL THROUGH Break ; Inputs: ; DS:BX = Transfer address ; CX = Number of sectors ; DX = Absolute record number (LOW) ; [HIGH_SECTOR]= Absolute record number (HIGH) ; ES:BP = Base of drive parameters ; [ALLOWED] must be set in case call to HARDERR needed ; Function: ; Calls BIOS to perform disk read. If BIOS reports ; errors, will call HARDERRRW for further action. ; Outputs: ; Carry set if error (currently user FAILED to INT 24) ; DS,ES:BP preserved. All other registers destroyed. entry DREAD ASSUME DS:NOTHING,ES:NOTHING Assert ISDPB,,"DREAD" invoke DSKREAD retz ; Carry clear MOV BYTE PTR [READOP],0 invoke HARDERRRW CMP AL,1 ; Check for retry JZ DREAD CMP AL,3 ; Check for FAIL CLC JNZ NO_CAR ; Ignore STC NO_CAR: return RET41P: POP DX return EndProc FATSecRd Break ; Inputs: ; output of SETUP ; ES:DI -> SFT ; Function: ; check write lock ; Outputs: ; Carry set if error ; Carry clear if ok procedure CHECK_WRITE_LOCK,NEAR ;AN000; ASSUME DS:NOTHING,ES:NOTHING ;AN000; TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id JZ write_cont ;AN000;;MS. no invoke SET_ACC_ERR_DS ;AN000;;MS. return ;AN000;;MS. write_cont: ;AN000; PUSH CX ;AN000;;MS. save reg OR CX,CX ;AN000;;MS. JNZ Not_Truncate ;AN000;;MS. MOV CX,0FFFFH ;AN000;;MS. check for lock on whole file Not_Truncate: ;AN000; MOV AL,80H ;AN000;;MS. check write access invoke LOCK_CHECK ;AN000;;MS. check lock POP CX ;AN000;;MS. restore reg JNC WRITE_OK ;AN000;;MS. lock ok invoke WRITE_LOCK_VIOLATION ;AN000;;MS. issue I24 JNC CHECK_WRITE_LOCK ;AN000;;MS. retry WRITE_OK: ;AN000; return ;AN000;;MS. EndProc CHECK_WRITE_LOCK ;AN000; Break ; Inputs: ; ES:DI -> SFT ; output of SETUP ; Function: ; check read lock ; Outputs: ; Carry set if error ; Carry clear if ok procedure CHECK_READ_LOCK,NEAR ;AN000; ASSUME DS:NOTHING,ES:NOTHING ;AN000; TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id JZ do_retry ;AN000;;MS. no invoke SET_ACC_ERR ;AN000;;MS. return ;AN000;;MS. do_retry: ;AN000; MOV AL,0 ;AN000;;MS. check read access invoke LOCK_CHECK ;AN000;;MS. check lock JNC READ_OK ;AN000;;MS. lock ok invoke READ_LOCK_VIOLATION ;AN000;;MS. issue I24 JNC CHECK_READ_LOCK ;AN000;;MS. retry READ_OK: ;AN000; MS. return ;AN000;;MS. EndProc CHECK_READ_LOCK ;AN000; IF BUFFERFLAG ;------------------------------------------------------------------------- ; Function name : choose_buf_page ; Inputs : DMAADD = Xaddr ; cx = # of bytes to transfer ; Outputs : if NC ; ; SAFE_FLAG - 0 ==> page is safe. no need to ; detect collision between ; user & system buffer. ; SAFE_FLAG - 1 ==> page is unsafe. Must check ; for collision ; ; CY - error ; ; ; High Level Alogrithm: ; ; 1. If Xaddr. is above the first physical page above 640K ; 2. choose that page ; 3. set safe flag ; 4. else ; 5. choose highest page above 640K ; 6. If 6 or more pages above 640k ; 7. Set safe flag ; 8. else ; 9. if Xaddr. + # of bytes to transfer does not spill into the ; chosen page ; 10. set safe flag ; 11.else ; 12. clear safe flag ; 13.endif ; 14.endif ; 15.endif ; ;---------------------------------------------------------------------------- Procedure choose_buf_page,near assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup push cx push bx push dx push si push ds push ax mov ax, word ptr [DMAADD+2] and ax, 0fc00h ; page segment of transfer segment cmp ax, word ptr [BUF_EMS_FIRST_PAGE] ja pick_first cmp [BUF_EMS_NPA640], 6 jae safe_pick_last add cx, word ptr [DMAADD] ; get final offset mov bx, cx mov cl, 4 shr bx, cl ; get # of paragraphs mov ax, word ptr [DMAADD+2] ; get initial segment add ax, bx ; get final segment and ax, 0fc00h cmp ax, word ptr [BUF_EMS_LAST_PAGE] jne safe_pick_last mov [BUF_EMS_SAFE_FLAG], 0 jmp fin_choose_page safe_pick_last: mov [BUF_EMS_SAFE_FLAG], 1 jmp fin_choose_page ;pick_last: ; mov ax, word ptr [BUF_EMS_LAST_PAGE] ; mov [BUF_EMS_PFRAME], ax ; mov ax, word ptr [BUF_EMS_LAST_PAGE+2] ; mov [BUF_EMS_PAGE_FRAME], ax ; xor ax, ax ; jmp fin_choose_page pick_first: mov ax, word ptr [BUF_EMS_FIRST_PAGE] cmp [BUF_EMS_PFRAME], ax je fin_choose_page call restore_user_map mov word ptr [LASTBUFFER], -1 mov [BUF_EMS_PFRAME], ax mov ax, word ptr [BUF_EMS_FIRST_PAGE+2] mov [BUF_EMS_PAGE_FRAME], ax mov [BUF_EMS_SAFE_FLAG], 1 call Setup_EMS_Buffers call save_user_map jmp fin_choose_page err_choose_page: stc fin_choose_page: clc pop ax pop ds pop si pop dx pop bx pop cx return EndProc choose_buf_page ENDIF CODE ENDS END