📄 tcdbasic.pas
字号:
Arg2 : DWORD;
begin
FillChar(Buf^, BufLen, 0);
if DBD then Arg1 := 8 else Arg1 := 0;
Arg2 := ((Ord(PCTL) AND 3) SHL 6) OR (PAGE AND $3F);
result := ASPIsend10($5A, Arg1, Arg2 SHL 24, 0, BufLen,
Buf, BufLen, SRB_DIR_IN, ShortTimeout);
end;
{============= MODE SELECT/MODE SENSE - Mode list header. =============}
{ The mode parameter list used by MODE SELECT/MODE SENSE contains a header,
followed by zero or more block descriptors, followed by zero or more
variable-length pages. Here are procedures for header and descriptors
reading/modifying.
The list header consist of two useful parameters:
a) The medium-type code field defined by TCdRomMediumType type.
'mixed' means that medium may contain data and audio tracks,
'default' - that device supports only one medium type (??),
suffix '80' - that media is a 80 mm diameter disk instead the
default 120 mm.
b) The DPOFUA flag (not supported for MODE SELECT). If MODE SENSE
returns this flag TRUE, then target supports DPO and FUA flags
using (see SCSIread10 function description).
Each block descriptor contains three fields:
a) Density - Enumerated CD-ROM density codes:
00h = Default density code (the only density supported by target)
01h = CD-ROM mode 1 - User data only (2048 bytes per physical sector)
02h = CD-ROM mode 2 - User data plus auxiliary data field (2336 bytes)
03h = 4-byte tag field, user data plus auxiliary data (2340 bytes)
04h = CD-Audio mode - 1/75th of a second per logical block
values 05h-7Fh are reserved, 80h-FFh - vendor-specific.
NOTE: The number of bytes per sector specified here is used with the
block length to map CD-ROM sectors to logical block addresses.
b) BlkCount - The number of logical blocks on the medium to which the
density code and block length fields apply. A zero value indicates
that all of the remaining logical blocks of the logical unit shall
have the medium characteristics specified.
c) BlkSize - The length in bytes of each logical block described by
the block descriptor. }
function TCdRom.SCSImodeSenseHeader(var sh : TCdRomModeHeader) : BOOLEAN;
type SCSI_ModeHeader = packed record
ModeDataLength : WORD; // full record length except itself (SENSE only)
MediumType : BYTE;
DeviceSpecific : BYTE; // $10 bit is DPOFUA flag
Reserved1 : WORD;
DescriptorLength : WORD; // equal to 8*Number of Block Descriptors
// must be zero when DBD=TRUE
BDP : array[0..511] of DWORD; // intuitional choice :)
end;
var
cd : SCSI_ModeHeader;
i : integer;
begin
FillChar(sh, sizeof(sh), 0);
result := SCSImodeSense(FALSE, MPTcurrent, $3F, @cd, sizeof(cd));
if result then begin
if cd.MediumType > 7 then sh.Medium := CDTreserved
else sh.Medium := TCdRomMediumType(cd.MediumType);
sh.DPOFUA := (cd.DeviceSpecific AND $10) <> 0;
sh.BDlength := cd.DescriptorLength DIV 8;
for i := 0 to sh.BDlength - 1 do with sh.BD[i] do begin
Density := BYTE($0FF AND cd.BDP[i SHL 1]);
BlkCount := $0FFFFFF AND BigEndianD(cd.BDP[i SHL 1]);
BlkSize := $0FFFFFF AND BigEndianD(cd.BDP[(i SHL 1)+1]);
end; end; end;
{======== MODE SELECT/MODE SENSE - Error recovery parameters page. ========}
{ This page specifies the error recovery parameters the target shall use
during any command that performs a data read operation to the media
(e.g. READ, READ TOC, etc.).
PSAV (Parameters SAVable) = TRUE indicates that the target is capable
of saving the page in a non-volatile vendor-specific location.
This bit is only used with the MODE SENSE command.
RLEV (Recovery Level) is the set of five bits:
$20 = Transfer block bit. If set, data block that is not recovered
shall be transferred to data buffer anyway. This bit does not
affect the action taken for recovered data and does not
suppress the Err_SenseMediumError status of read commands.
$10 = Read continuous bit. If set, indicates the target shall
transfer the entire requested length of data without adding
delays to perform error recovery procedures.
This implies that the target may send data that is erroneous
or fabricated in order to maintain a continuous flow of data.
This bit is typically used in audio or video applications.
$04 = Post error bit. If set, target shall report recovered errors.
$02 = Disable transfer on error bit. Ones indicates that the target
shall terminate the data phase upon detection of a recovered
error.
$01 = Disable correction bit. If set, error correction codes shall
not be used for data error recovery. This is applicable to
layered error correction (L-EC) feature only. The retries and
CIRC (Cross Interleaved Reed-solomon Code,the error detection
and correction technique used within small (24 bytes) frames
of audio or data) are performed anyway.
The interpretation of these bit settings for CD-ROM devices and
valid RLEV values are given below. If RLEV is set to any other
value, the command shall be terminated with Err_SenseInvalidRequest
status.
00h/01h If an uncorrectable error occurs, transfer is terminated
with Err_SenseMediumError status. The block with the error is not
transferred. Recovered errors are not reported.
04h/05h Recovered errors are reported by Err_SenseRecoveredError,
but data transfer is not terminated. Uncorrectable error terminates
data transfer with Err_SenseMediumError status and the block with
the error is not transferred.
06h/07h Recovered data error terminates data transfer with
Err_SenseRecoveredError status. The block with the recovered error is
not transferred. Uncorrectable error terminates data transfer with
Err_SenseMediumError status and errata block is not transferred.
10h/11h If an error occurs which is uncorrectable in time to maintain
data transfer, the data transfer is not terminated. However, when the
data transfer has completed, Err_SenseMediumError status is reported.
Recovered errors are not reported.
14h/15h Data transfer is never terminated. Recovered errors are
reported at completion by Err_SenseRecoveredError status,
uncorrectable errors - by Err_SenseMediumError. Reporting
unrecovered errors takes precedence over reporting recovered errors.
20h/21h/24h/25h/26h/27h are the same as 00h/01h/04h/05h/06h/07h, but
the block with the error is always transferred.
30h/31h/34h/35h are the same as 10h/11h/14h/15h.
A CIRC recovered data error is defined as a block for which the
CIRC based error correction algorithm was unsuccessful for a read
attempt, but on a subsequent read operation no error was reported.
The number of subsequent read operations is limited to the read
retry count. Layered error correction was not used.
An L-EC recovered data error is defined as a block for which the
CIRC based error correction was unsuccessful, but the layered error
correction was able to correct the block within the read retry count.
RETR (Read Retry Count) specifies the number of times that the controller
shall attempt its read recovery algorithm. }
function TCdRom.SCSImodeSenseRecoverEX(PCTL : TCdRomModePageType;
var PSAV : BOOLEAN; var RLEV, RETR : BYTE) : BOOLEAN;
type SCSI_ModeRecovery = packed record
ModeDataLength : WORD; // full record length except itself
MediumType : BYTE;
DeviceSpecific : BYTE;
Reserved1 : WORD;
DescriptorLength : WORD; // equal to 8*Number of Block Descriptors
// must be zero when DBD=TRUE
PageCode : BYTE; // six LSBs of page code (01h) plus
// MSbit is PSAV flag (MODE SENSE only)
ParamLength : BYTE; // must be = 6
RecoveryLevel : BYTE; // returns as RLEV
MaxRetryCount : BYTE;
Reserved2 : DWORD;
end;
var cd : SCSI_ModeRecovery;
begin
result := SCSImodeSense(TRUE, PCTL, 1, @cd, sizeof(cd));
PSAV := (cd.PageCode AND $80) <> 0;
RLEV := cd.RecoveryLevel;
RETR := cd.MaxRetryCount;
end;
function TCdRom.SCSImodeSenseRecover(var RLEV, RETR : BYTE) : BOOLEAN;
var PSAVtemp : BOOLEAN;
begin
result := SCSImodeSenseRecoverEX(MPTcurrent, PSAVtemp, RLEV, RETR);
end;
{======== MODE SELECT/MODE SENSE - Supported medium page. ========}
{ This page contains a list of the medium types implemented by the target.
The code values (up to four) are reported in ascending order.
PSAV=TRUE indicates that the target is capable of saving the page
in a non-volatile location. Used with the MODE SENSE only. }
function TCdRom.SCSImodeSenseMediumEX(PCTL : TCdRomModePageType;
var PSAV: BOOLEAN; var Med1,Med2,Med3,Med4: TCdRomMediumType): BOOLEAN;
type SCSI_ModeMedium = packed record
ModeDataLength : WORD; // full record length except itself
MediumType : BYTE;
DeviceSpecific : BYTE;
Reserved1 : WORD;
DescriptorLength : WORD;
PageCode : BYTE; // six LSBs of page code (0Bh) plus
// MSbit is PSAV flag (MODE SENSE only)
ParamLength : BYTE; // must be = 6
Reserved2 : WORD;
Medium : array[0..3] of BYTE;
end;
var
cd : SCSI_ModeMedium;
i : integer;
begin
result := SCSImodeSense(TRUE, PCTL, $0B, @cd, sizeof(cd));
PSAV := (cd.PageCode AND $80) <> 0;
with cd do begin
for i := 0 to 3 do begin
if Medium[i] > 7 then Medium[i] := 4; // CDTreserved
if (Medium[i]=0) AND (i > 0)
then Medium[i] := 8; // CDTnone
end;
Med1 := TCdRomMediumType(Medium[0]);
Med2 := TCdRomMediumType(Medium[1]);
Med3 := TCdRomMediumType(Medium[2]);
Med4 := TCdRomMediumType(Medium[3]);
end; end;
{======== MODE SELECT/MODE SENSE - CD-ROM device parameters page. ========}
{ This page specifies parameters that affect all CD-ROM data types.
PSAV=TRUE indicates that the target is capable of saving the page in a
non-volatile vendor-specific location. Used with the MODE SENSE only.
ITimer (Inactivity Timer) specifies the time that the drive shall remain
in the hold track state after completion of a seek or read operation.
Value: 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh Fh
Time: 0.125s 0.25s 0.5s 1s 2s 4s 8s 16s 32s 1m 2m 4m 8m 16m 32m
where s=seconds, m=minutes. Value of zero means vendor-specific time.
WARNING: High values in this parameter may have an adverse effect on
the drive MTBF.
SperMunits and FperSunits fields gives the ratio of these MSF address
values. For media conforming to the CD-ROM and CD-DA standard, this
value is 60 and 75 respectively. }
function TCdRom.SCSImodeSenseDeviceEX(PCTL : TCdRomModePageType;
var PSAV : BOOLEAN; var ITimer : BYTE;
var SperMunits, FperSunits : WORD) : BOOLEAN;
type SCSI_ModeDevice = packed record
ModeDataLength : WORD; // full record length except itself
MediumType : BYTE;
DeviceSpecific : BYTE;
Reserved1 : WORD;
DescriptorLength : WORD;
PageCode : BYTE; // six LSBs of page code (0Dh) plus
// MSbit is PSAV flag (MODE SENSE only)
ParamLength : BYTE; // must be = 6
Reserved2 : BYTE;
InactivityTimer : BYTE; // returns as ITimer
SunitsPerMunits : WORD; // returns as SperMunits. Usually=60d
FunitsPerSunits : WORD; // returns as FperSunits. Usually=75d
end;
var cd : SCSI_ModeDevice;
begin
result := SCSImodeSense(TRUE, PCTL, $0D, @cd, sizeof(cd));
PSAV := (cd.PageCode AND $80) <> 0;
ITimer := $0F AND cd.InactivityTimer;
SperMunits := BigEndianW(cd.SunitsPerMunits);
FperSunits := BigEndianW(cd.FunitsPerSunits
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -