* source/rdd/usrrdd/rdds/arrayrdd.prg
* contrib/hbct/tests/datetime.prg
* contrib/xhb/decode.prg
* contrib/hbsqlit3/tests/hooks.prg
* contrib/hbsqlit3/tests/backup.prg
* contrib/hbsqlit3/tests/authoriz.prg
* contrib/hbblat/blatcls.prg
* contrib/hbnf/nooccur.prg
* contrib/hbnf/floptst.prg
* contrib/hbfimage/tests/fitest.prg
* contrib/hbgd/tests/gdtestcl.prg
* contrib/hbgd/tests/counter.prg
* contrib/hbgd/gdchart.prg
* contrib/hbgd/gdimage.prg
* TRUE/FALSE in .prg code changed to .T./.F.
- contrib/gtwvg/tests/v_calcltr.ico
+ contrib/gtwvg/tests/v_clclt.ico
* Renamed to short name. (this file isn't used BTW)
* contrib/hbblat/tests/blattest.prg
- contrib/hbblat/tests/f_sample1.txt
+ contrib/hbblat/tests/f_sampl1.txt
- contrib/hbblat/tests/f_subjectline.txt
+ contrib/hbblat/tests/f_subjct.txt
- contrib/hbblat/tests/f_listtext.txt
+ contrib/hbblat/tests/f_listtx.txt
* Renamed to short names.
291 lines
9.0 KiB
Plaintext
291 lines
9.0 KiB
Plaintext
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* File......: floptst.prg
|
|
* Author....: Gary Smith
|
|
* CIS ID....: 70714,3015
|
|
*
|
|
* This work is based on an original work by Joseph LaCour that
|
|
* was placed in the public domain. This work is placed in the
|
|
* public domain.
|
|
*
|
|
* ACKNOWLEDGEMENTS:
|
|
*
|
|
* PAOLO RAMOZZI FOR HIS WORK IN DBDCHECK FOR SHOWING HOW TO
|
|
* USE INT 13H.
|
|
*
|
|
*
|
|
* Modification history:
|
|
* ---------------------
|
|
*
|
|
* Rev 1.4 05 May 1995 03:05:00 TED
|
|
* Gary Smith ported ASM source to Clipper.
|
|
*
|
|
* Rev 1.3 23 Sep 1991 14:56:42 GLENN
|
|
* Bug reports from Craig Austin, James Finnal, and Ted Means. Line 128
|
|
* had MOV FDRIVE,AL which should have been MOV FDRIVE,BL. This caused the
|
|
* function to erroneously use the last drive available instead of the one
|
|
* specified by the calling process.
|
|
*
|
|
* Rev 1.2 15 Aug 1991 23:07:48 GLENN
|
|
* Forest Belt proofread/edited/cleaned up doc
|
|
*
|
|
* Rev 1.1 11 May 1991 00:21:42 GLENN
|
|
* File header changed to conform to Toolkit standard.
|
|
*
|
|
|
|
* $DOC$
|
|
* $FUNCNAME$
|
|
* FT_FLOPTST()
|
|
* $CATEGORY$
|
|
* DOS/BIOS
|
|
* $ONELINER$
|
|
* Test diskette drive status
|
|
* $SYNTAX$
|
|
* FT_FLOPTST( <nDrive> ) -> nStatus
|
|
* $ARGUMENTS$
|
|
* <nDrive> is the diskette drive number, 0 = A:, 1 = B:
|
|
* $RETURNS$
|
|
* -1 - Wrong Parameters
|
|
* 0 - Drive Loaded and ready to read or write
|
|
* 1 - Drive Door Open or Diskette inserted upside down
|
|
* 2 - Diskette is unformatted
|
|
* 3 - Write protected
|
|
* 4 - Undetermined
|
|
* $DESCRIPTION$
|
|
* FT_FLOPTST() is designed as a full replacement for ISDRIVE(). Where
|
|
* ISDRIVE() returns just .T. or .F. depending if the diskette drive is
|
|
* ready or not, FT_FLOPTST() returns a numeric code designating the
|
|
* diskette drive's status.
|
|
*
|
|
* FT_FLOPTST() is particularly useful in backup and restore programs
|
|
* that need to test the floppy drive before writing/reading from a
|
|
* floppy disk.
|
|
*
|
|
* No testing has been performed on systems with more than 2 floppy
|
|
* drives. If the third drive is "C" and the fourth "D" then there
|
|
* should be no problems.
|
|
*
|
|
* This function does not currently check subst'd drives. So if you
|
|
* have SUBST E: A:\ then FT_FLOPTST( ASC("E")-ASC("A") ) == 4
|
|
* Any suggestions to fix this limitation are appreciated.
|
|
*
|
|
* $EXAMPLES$
|
|
* iStatus := FT_FLOPTST( 0 )
|
|
* DO CASE
|
|
* CASE iStatus == 1
|
|
* Qout( "The door to drive A is open." )
|
|
* CASE iStatus == 2
|
|
* Qout( "The diskette in drive A is not formatted." )
|
|
* CASE iStatus == 3
|
|
* Qout( "The diskette in drive A is write-protected." )
|
|
* CASE iStatus == 4
|
|
* Qout( "Something is wrong with drive A, but I don't know what." )
|
|
* ENDCASE
|
|
* $END$
|
|
*
|
|
*/
|
|
|
|
#include "ftint86.ch"
|
|
|
|
#DEFINE ERR_WRONG_PARAMETERS -1
|
|
#DEFINE ERR_NO_ERROR 0
|
|
#DEFINE ERR_DRIVE_NOT_READY 1
|
|
#DEFINE ERR_UNFORMATTED 2
|
|
#DEFINE ERR_WRITE_PROTECTED 3
|
|
#DEFINE ERR_UNKNOWN 4
|
|
|
|
#IFDEF FT_TEST
|
|
#define CR_LF chr(13)+chr(10)
|
|
|
|
PROCEDURE MAIN( ;
|
|
cArg1 ;
|
|
)
|
|
LOCAL nErrCode
|
|
|
|
IF ValType( cArg1 ) == "C"
|
|
nErrCode := FT_FLOPTST( Asc( Upper(cArg1) ) - Asc( "A" ) )
|
|
OutStd( "Return Code is "+LTrim(Str(nErrCode)) +CR_LF )
|
|
ELSE
|
|
OutStd( "Usage: floptst cDrive"+CR_LF+" where cDrive is 'A' or 'B' etc..."+CR_LF )
|
|
ENDIF
|
|
|
|
RETURN
|
|
|
|
#ENDIF
|
|
|
|
|
|
FUNCTION FT_FLOPTST( ; // error code defined by ERR_*
|
|
nDriveNum_i ; // letter of floppy drive.
|
|
)
|
|
LOCAL cBuffer
|
|
LOCAL nErrorCode
|
|
LOCAL nRetCode
|
|
|
|
nRetCode := ERR_WRONG_PARAMETERS
|
|
IF ValType( nDriveNum_i ) == "N"
|
|
|
|
IF _GetDisketteNum( nDriveNum_i )
|
|
_ResetDisketteSystem()
|
|
_ReadBootSector( nDriveNum_i, @cBuffer, @nErrorCode )
|
|
|
|
IF nErrorCode == 0
|
|
_WriteBootSector( nDriveNum_i, cBuffer, @nErrorCode )
|
|
DO CASE
|
|
CASE nErrorCode == 0
|
|
nRetCode := ERR_NO_ERROR
|
|
CASE nErrorCode == 3
|
|
nRetCode := ERR_WRITE_PROTECTED
|
|
OTHERWISE
|
|
nRetCode := ERR_UNKNOWN
|
|
ENDCASE
|
|
ELSE
|
|
DO CASE
|
|
CASE nErrorCode == 128 // 80h
|
|
nRetCode := ERR_DRIVE_NOT_READY
|
|
CASE nErrorCode == 2
|
|
nRetCode := ERR_UNFORMATTED
|
|
OTHERWISE
|
|
nRetCode := ERR_UNKNOWN
|
|
END CASE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN nRetCode
|
|
|
|
#define BITS_6AND7 192 // value of byte when bits 6&7 are high
|
|
|
|
STATIC FUNCTION _GetDisketteNum( ; // returns false if no floppy drive installed or nDrive_i is invalid
|
|
nDrive_i ; // drive number to query status
|
|
)
|
|
LOCAL aRegs[INT86_MAX_REGS]
|
|
LOCAL lRetCode
|
|
LOCAL nByte
|
|
LOCAL nDriveCount
|
|
|
|
// ASSERT 0 <= nDrive_i
|
|
|
|
lRetCode := .F.
|
|
IF FT_INT86( 1*16+1, aRegs ) // INT for equipment determination
|
|
nByte := lowbyte( aRegs[AX] )
|
|
// bit 0 indicates floppy drive installed
|
|
IF Int( nByte / 2 ) * 2 != nByte // is it odd i.e. is bit 0 set??
|
|
// bits 6 & 7 indicate number of floppies installed upto 4.
|
|
nDriveCount := Asc( FT_BYTEAND( Chr(nByte), chr(BITS_6AND7) ) )
|
|
IF nDriveCount >= nDrive_i
|
|
lRetCode := .T.
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN lRetCode
|
|
|
|
|
|
STATIC PROCEDURE _ResetDisketteSystem()
|
|
LOCAL aRegs[INT86_MAX_REGS]
|
|
|
|
aRegs[AX] := 0
|
|
|
|
FT_INT86( 1*16+3, aRegs )
|
|
|
|
RETURN
|
|
|
|
#define BUFFER_SIZEOF_SECTOR 512+1
|
|
|
|
STATIC FUNCTION _ReadBootSector( ;
|
|
nDriveNum, ;
|
|
cBuffer_o, ;
|
|
nErrCode_o ;
|
|
)
|
|
// call BIOS INT 13 for sector read
|
|
LOCAL aRegs[INT86_MAX_REGS]
|
|
LOCAL cBuffer := Space( BUFFER_SIZEOF_SECTOR )
|
|
LOCAL lSuccess
|
|
LOCAL nErrorCode
|
|
LOCAL lCarryFlag
|
|
|
|
aRegs[DX] := nDriveNum // DH = 0 Head 0, DL = drive number
|
|
aRegs[CX] := 1 // CH = 0 track 0, CL=1 sector 1
|
|
aRegs[BX] := REG_ES // buffer in ES:BX
|
|
aRegs[ES] := cBuffer
|
|
aRegs[AX] := makehi(2)+1 // AH = 02 read , AL=1 read one sector
|
|
|
|
lSuccess := _CallInt13hRetry( aRegs, @lCarryFlag, @nErrorCode )
|
|
|
|
cBuffer_o := aRegs[ES]
|
|
nErrCode_o := nErrorCode
|
|
|
|
RETURN lSuccess
|
|
|
|
|
|
STATIC FUNCTION _WriteBootSector( ;
|
|
nDriveNum, ;
|
|
cBuffer_i, ;
|
|
nErrCode_o ;
|
|
)
|
|
// call BIOS INT 13 for sector write
|
|
LOCAL aRegs[INT86_MAX_REGS]
|
|
LOCAL lSuccess
|
|
LOCAL nErrorCode
|
|
LOCAL lCarryFlag
|
|
|
|
aRegs[DX] := nDriveNum // DH = 0 Head 0 , DL = drive number
|
|
aRegs[CX] := 1 // CH = 0 track 0, CL=1 sector 1
|
|
aRegs[BX] := REG_ES // buffer in ES:BX
|
|
aRegs[ES] := cBuffer_i
|
|
aRegs[AX] := makehi(3)+1 // AH = 03 write , AL=1 read one sector
|
|
|
|
lSuccess := _CallInt13hRetry( aRegs, @lCarryFlag, @nErrorCode )
|
|
|
|
nErrCode_o := nErrorCode
|
|
|
|
RETURN lSuccess
|
|
|
|
|
|
STATIC FUNCTION _CallInt13hRetry( ; // logical: did the interrupt succeed?
|
|
aRegs_io, ; // registers values for INT 13h
|
|
lCarrySet_o, ; // status of carry flag if return code is true.
|
|
nDriveStatus_o ; // status of drive ( error code )
|
|
)
|
|
LOCAL lCarrySet
|
|
LOCAL aRegisters
|
|
LOCAL lSuccess
|
|
LOCAL nInterrupt_c := 1*16+3 // INT 13h
|
|
LOCAL i
|
|
|
|
lCarrySet := .F.
|
|
aRegisters := AClone( aRegs_io )
|
|
lSuccess := FT_INT86( nInterrupt_c, aRegisters )
|
|
IF lSuccess
|
|
lCarrySet := carrySet( aRegisters[FLAGS] )
|
|
IF lCarrySet
|
|
_ResetDisketteSystem()
|
|
|
|
aRegisters := AClone( aRegs_io )
|
|
FT_INT86( nInterrupt_c, aRegisters )
|
|
lCarrySet := carrySet( aRegisters[FLAGS] )
|
|
IF lCarrySet
|
|
_ResetDisketteSystem()
|
|
|
|
aRegisters := AClone( aRegs_io )
|
|
FT_INT86( nInterrupt_c, aRegisters )
|
|
lCarrySet := carrySet( aRegisters[FLAGS] )
|
|
IF lCarrySet
|
|
_ResetDisketteSystem()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
FOR i := 1 TO INT86_MAX_REGS
|
|
// pass altered register back up
|
|
aRegs_io[i] := aRegisters[i]
|
|
NEXT // i
|
|
lCarrySet_o := lCarrySet
|
|
nDriveStatus_o := highByte( aRegisters[AX] )
|
|
|
|
RETURN lSuccess
|