📄 scsiunit.pas
字号:
BufLen := (DWORD(mp) - BufPos);
System.Move(pp^, Buf^, BufLen);
end;
{
function SCSImodeSelectPage(DeviceID : TCDBurnerInfo; PageCode : BYTE;
Buf : pointer; var BufLen : DWORD; BufPos : DWORD;
var Sdf : TScsiDefaults) : TScsiError;
var
Src6, Chg6 : TScsiModePageTemplate6;
Chg10 ,Src10 : TScsiModePageTemplate10;
SdfTemp : TCdRomModePageType;
pp, ps, gs : PScsiModePageRecord;
i, mp, len, dblen : integer;
begin
if not Assigned(Buf) then begin
Result := Err_InvalidArgument;
exit;
end;
Result := SCSImodeSense(DeviceID, PageCode, @Src10, sizeof(Src10), Sdf);
if Result <> Err_None then begin
BufLen := 0;
exit;
end;
SdfTemp := Sdf.ModePageType;
Sdf.ModePageType := MPTchangeable;
Result := SCSImodeSense(DeviceID, PageCode, @Chg10, sizeof(Chg10), Sdf);
Sdf.ModePageType := SdfTemp;
if Result <> Err_None then begin
BufLen := 0;
exit;
end;
// Exclude block descriptors if exists
if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then begin
dblen := Src6.DescriptorLength6;
len := Src6.ModeDataLength6 - dblen;
Src6.ModeDataLength6 := len;
Src6.MediumType6 := 0;
Src6.DeviceSpecific6 := 0;
Src6.DescriptorLength6 := 0;
Inc(len, SizeOf(Src6.ModeDataLength6)); // Full length of record
pp := PScsiModePageRecord(@Src6.Params6[0]);
ps := PScsiModePageRecord(@Src6.Params6[dblen]);
gs := PScsiModePageRecord(@Chg6.Params6[Chg6.DescriptorLength6]);
mp := ScsiModeTemplateParamsLength - 1 - dblen;
end else begin
dblen := BigEndianW(Src10.DescriptorLength10);
len := BigEndianW(Src10.ModeDataLength10) - dblen;
Src10.ModeDataLength10 := BigEndianW(len);
Src10.MediumType10 := 0;
Src10.DeviceSpecific10 := 0;
Src10.Reserved10 := 0;
Src10.DescriptorLength10 := 0;
Inc(len, SizeOf(Src10.ModeDataLength10)); // Full length of record
pp := PScsiModePageRecord(@Src10.Params10[0]);
ps := PScsiModePageRecord(@Src10.Params10[dblen]);
gs := PScsiModePageRecord(@Chg10.Params10[
BigEndianW(Chg10.DescriptorLength10)]);
mp := ScsiModeTemplateParamsLength - 1 - dblen;
end;
if (mp <= BufPos) or (ps^.ParamLength <= BufPos) or (len <= 0) then begin
Result := Err_Unknown;
BufLen := 0;
exit;
end;
if mp > ps^.ParamLength then mp := ps^.ParamLength;
if dblen <> 0 then System.Move(ps^, pp^, mp+2);
if BufLen > (mp - BufPos) then BufLen := (mp - BufPos);
System.Move(Buf^, pp^, BufLen);
// for i := 0 to mp-1 do
// pp^.Params[i] := pp^.Params[i] AND gs^.Params[i];
Result := SCSImodeSelect(DeviceID, @Src10, len, Sdf);
end; }
{$WARNINGS OFF}
function SCSImodeSelectPage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
var
Src10: TScsiModePageTemplate2;
pp, ps: PScsiModePageRecord;
mp, len, dblen: integer;
begin
if not Assigned(Buf) then
begin
Result := Err_InvalidArgument;
exit;
end;
Result := SCSImodeSense(DeviceID, PageCode, @Src10, sizeof(Src10), Sdf);
if Result <> Err_None then
begin
BufLen := 0;
exit;
end;
begin
dblen := BigEndianW(Src10.DescriptorLength10);
len := BigEndianW(Src10.ModeDataLength10) - dblen;
Src10.ModeDataLength10 := BigEndianW(len);
Src10.MediumType10 := 0;
Src10.DeviceSpecific10 := 0;
Src10.Reserved10 := 0;
Src10.DescriptorLength10 := 0;
Inc(len, SizeOf(Src10.ModeDataLength10)); // Full length of record
pp := PScsiModePageRecord(@Src10.Params10[0]);
ps := PScsiModePageRecord(@Src10.Params10[dblen]);
mp := ScsiModeTemplateParamsLength - 1 - dblen;
end;
if (mp <= BufPos) or (ps^.ParamLength <= BufPos) or (len <= 0) then
begin
Result := Err_Unknown;
BufLen := 0;
exit;
end;
if mp > ps^.ParamLength then
mp := ps^.ParamLength;
if dblen <> 0 then
System.Move(ps^, pp^, mp + 2);
if BufLen > (mp - BufPos) then
BufLen := (mp - BufPos);
System.Move(Buf^, pp^, BufLen);
Result := SCSImodeSelect(DeviceID, @Src10, len, Sdf);
end;
{$WARNINGS ON}
function SCSImodeSenseCdStatus(DeviceID: TCDBurnerInfo;
var ModePage: TScsiModePageCdStatus;
var Sdf: TScsiDefaults): TScsiError;
var
PageSize: DWORD;
begin
ZeroMemory(@ModePage, SizeOf(ModePage));
PageSize := SizeOf(ModePage);
Result := SCSImodeSensePage(DeviceID, $2A, @ModePage, PageSize, 0, Sdf);
end;
{$WARNINGS OFF}
function SCSImodeSenseParameter(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Param: pointer; ParamLen, ParamPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
var
tp: array[0..ScsiModePageParamsLength - 1] of BYTE;
len: DWORD;
begin
if ((ParamPos + ParamLen) > ScsiModePageParamsLength)
or (ParamPos < 0) or (ParamLen <= 0)
or not Assigned(Param) then
begin
Result := Err_InvalidArgument;
exit;
end;
len := ParamLen;
Result := SCSImodeSensePage(DeviceID, PageCode, @tp, len, ParamPos, Sdf);
if Result = Err_None then
begin
if len = ParamLen then
BigEndian(tp, Param^, ParamLen)
else
Result := Err_InvalidArgument;
end;
end;
{$WARNINGS ON}
function SCSIGetDriveSpeeds(DeviceID: TCDBurnerInfo;
var Value: TCDReadWriteSpeeds;
var Sdf: TScsiDefaults): TScsiError;
var
ModePage: TScsiModePageCdStatus;
begin
Result := SCSImodeSenseCdStatus(DeviceID, ModePage, Sdf);
Value.MaxReadSpeed := Round(SwapWord(ModePage.MaxReadSpeed) / 176.46);
Value.CurrentReadSpeed := Round(SwapWord(ModePage.CurrentReadSpeed) / 176.46);
Value.MaxWriteSpeed := Round(SwapWord(ModePage.MaxWriteSpeed) / 176.46);
Value.CurrentWriteSpeed := Round(SwapWord(ModePage.CurWriteSpeed_Res) /
176.46);
Value.buffersize := Round(SwapWord(ModePage.MaxBufferSize));
end;
function SCSIgetCdRomCapabilities(DeviceID: TCDBurnerInfo;
var Value: TCdRomCapabilities;
var Sdf: TScsiDefaults): TScsiError;
var
ModePage: TScsiModePageCdStatus;
FB: BYTE;
begin
ZeroMemory(@ModePage, SizeOf(ModePage));
Result := SCSImodeSenseCdStatus(DeviceID, ModePage, Sdf);
Value := [];
FB := ModePage.Flags[0];
if (FB and CDSTATUS_READ_CD_R) <> 0 then
Include(Value, cdcReadCDR);
if (FB and CDSTATUS_READ_CD_RW) <> 0 then
Include(Value, cdcReadCDRW);
if (FB and CDSTATUS_READ_METHOD2) <> 0 then
Include(Value, cdcReadMethod2);
if (FB and CDSTATUS_READ_DVD_ROM) <> 0 then
Include(Value, cdcReadDVD);
if (FB and CDSTATUS_READ_DVD_R) <> 0 then
Include(Value, cdcReadDVDR);
if (FB and CDSTATUS_READ_DVD_RAM) <> 0 then
Include(Value, cdcReadDVDRAM);
FB := ModePage.Flags[1];
if (FB and CDSTATUS_WRITE_CD_R) <> 0 then
Include(Value, cdcWriteCDR);
if (FB and CDSTATUS_WRITE_CD_RW) <> 0 then
Include(Value, cdcWriteCDRW);
if (FB and CDSTATUS_WRITE_DVD_R) <> 0 then
Include(Value, cdcWriteDVDR);
if (FB and CDSTATUS_WRITE_DVD_RAM) <> 0 then
Include(Value, cdcWriteDVDRAM);
if (FB and CDSTATUS_TEST_MODE) <> 0 then
Include(Value, cdcWriteTestMode);
FB := ModePage.Flags[2];
if (FB and CDSTATUS_AUDIO_PLAY) <> 0 then
Include(Value, cdcAudioPlay);
if (FB and CDSTATUS_AUDIO_COMPOSITE) <> 0 then
Include(Value, cdcAudioComposite);
if (FB and CDSTATUS_AUDIO_DIGIPORT1) <> 0 then
Include(Value, cdcAudioDigiPort1);
if (FB and CDSTATUS_AUDIO_DIGIPORT2) <> 0 then
Include(Value, cdcAudioDigiPort2);
if (FB and CDSTATUS_READ_MODE2_FORM1) <> 0 then
Include(Value, cdcReadMode2form1);
if (FB and CDSTATUS_READ_MODE2_FORM2) <> 0 then
Include(Value, cdcReadMode2form2);
if (FB and CDSTATUS_READ_MULTISESSION) <> 0 then
Include(Value, cdcReadMultisession);
if (FB and CDSTATUS_BURN_PROOF) <> 0 then
Include(Value, cdcWriteBurnProof);
FB := ModePage.Flags[3];
if (FB and CDSTATUS_CDDA_CAPABLE) <> 0 then
Include(Value, cdcCDDAread);
if (FB and CDSTATUS_CDDA_STREAM_ACCURATE) <> 0 then
Include(Value, cdcCDDAaccurate);
if (FB and CDSTATUS_CDDA_RW_SUPPORT) <> 0 then
Include(Value, cdcSubchannelRW);
if (FB and CDSTATUS_CDDA_RW_CORRECTED) <> 0 then
Include(Value, cdcSubchannelCorrect);
if (FB and CDSTATUS_CDDA_C2_POINTERS) <> 0 then
Include(Value, cdcC2Pointers);
if (FB and CDSTATUS_CDDA_ISRC) <> 0 then
Include(Value, cdcCddaISRC);
if (FB and CDSTATUS_CDDA_UPC) <> 0 then
Include(Value, cdcCddaUPC);
if (FB and CDSTATUS_CDDA_BARCODE) <> 0 then
Include(Value, cdcCddaBarCode);
FB := ModePage.Flags[4];
if (FB and CDSTATUS_LOCK_CAPABLE) <> 0 then
Include(Value, cdcLock);
if (FB and CDSTATUS_LOCK_STATE) <> 0 then
Include(Value, cdcLocked);
if (FB and CDSTATUS_PREVENT_JUMPER) <> 0 then
Include(Value, cdcLockJumper);
if (FB and CDSTATUS_EJECT_CAPABLE) <> 0 then
Include(Value, cdcEject);
FB := ModePage.Flags[5];
if (FB and CDSTATUS_SEPARATE_VOLUME) <> 0 then
Include(Value, cdcSeparateVolume);
if (FB and CDSTATUS_SEPARATE_MUTE) <> 0 then
Include(Value, cdcSeparateMute);
if (FB and CDSTATUS_REPORTS_HAVE_DISK) <> 0 then
Include(Value, cdcDiskSensor);
if (FB and CDSTATUS_SLOT_SELECTION) <> 0 then
Include(Value, cdcSlotSelect);
if (FB and CDSTATUS_SIDE_CHANGE) <> 0 then
Include(Value, cdcSideChange);
if (FB and CDSTATUS_CDDA_RW_LEAD_IN) <> 0 then
Include(Value, cdcCddaRwLeadIn);
end;
function SCSIinquiryEX(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD;
CmdDt, EVPD: BOOLEAN; PageCode: BYTE;
var Sdf: TScsiDefaults): TScsiError;
var
aLBA: DWORD;
cdb: Tcdb6;
begin
FillChar(CDB, 6, 0);
aLBA := PageCode;
aLBA := aLBA shl 8;
if EVPD then
aLBA := aLBA or $10000;
if CmdDt then
aLBA := aLBA or $20000;
cdb[5] := 0;
FillDWORD(aLBA, cdb[0]);
cdb[4] := BufLen;
cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
cdb[0] := SCSI_INQUIRY;
Result := ASPIsend6CDB(DeviceID, cdb, Buf, BufLen, SRB_DIR_IN, Sdf);
end;
function SCSIstartStopUnit(DeviceID: TCDBurnerInfo;
Start, LoadEject, DontWait: boolean;
var Sdf: TScsiDefaults): TScsiError;
var
Arg1: DWORD;
Arg2: byte;
SdfTemp: DWORD;
cdb: Tcdb6;
begin
FillChar(CDB, 6, 0);
Arg1 := 0;
if DontWait then
Arg1 := $10000;
Arg2 := 0;
if LoadEject then
Arg2 := 2;
if Start then
Arg2 := Arg2 or 1;
SdfTemp := Sdf.Timeout;
Sdf.Timeout := Sdf.SpindleTimeout;
cdb[5] := 0;
FillDWORD(Arg1, cdb[0]);
cdb[4] := Arg2;
cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
cdb[0] := SCSI_START_STP;
Result := ASPIsend6CDB(deviceid, cdb, nil, 0, SRB_NODIR, Sdf);
Sdf.Timeout := SdfTemp;
end;
function SCSItestReady(DeviceID: TCDBurnerInfo;
var Sdf: TScsiDefaults): TScsiError;
var
cdb: Tcdb6;
begin
FillChar(CDB, 6, 0);
cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
Result := ASPIsend6CDB(deviceid, cdb, nil, 0, SRB_NODIR, Sdf);
end;
procedure InquiryDecodePeripherals(Arg: BYTE; var PQ: TScsiPeripheralQualifier;
var DeviceType: TScsiDeviceType);
begin
PQ := TScsiPeripheralQualifier((Arg shr 5) and 7);
Arg := Arg and $1F;
case Arg of
0..9: DeviceType := TScsiDeviceType(Arg);
$1F: DeviceType := TSDInvalid
else
DeviceType := TSDother;
end;
end;
procedure InquiryDecodeCompliance(Arg: BYTE;
var Version: TScsiStandardCompliance);
begin
with Version do
begin
ISO := (Arg shr 6) and 3;
ECMA := (Arg shr 3) and 7;
ANSI := TScsiAnsiCompliance(Arg and 7);
end;
end;
function SCSIinquiryDeviceInfo(DeviceID: TCDBurnerInfo;
var Info: TScsiDeviceInfo; var Sdf: TScsiDefaults): TScsiError;
const
BufSize = 255;
var
Buf: array[0..BufSize - 1] of BYTE;
begin
Result := SCSIinquiryEX(DeviceID, @Buf, SizeOf(Buf),
False, False, 0, Sdf);
with Info do
begin
// InquiryDecodePeripherals(Buf[0], PeriphQualifier, Info.DeviceType);
Capabilities := [];
if (Buf[1] and $80) <> 0 then
Include(Capabilities, SDCremovableMedium);
InquiryDecodeCompliance(Buf[2], Version);
if (Buf[3] and $80) <> 0 then
Include(Capabilities, SDCasyncEvent);
if (Buf[3] and $20) <> 0 then
Include(Capabilities, SDCnormalACA);
if (Buf[3] and $10) <> 0 then
Include(Capabilities, SDChierarchical);
ResponseDataFormat := Buf[3] and $0F;
if (Buf[5] and $80) <> 0 then
Include(Capabilities, SDCsupportSCC);
if (Buf[6] and $80) <> 0 then
Include(Capabilities, SDCbasicQueuing);
if (Buf[6] and $40) <> 0 then
Include(Capabilities, SDCenclosure);
if (Buf[6] and $10) <> 0 then
Include(Capabilities, SDCmultiPort);
if (Buf[6] and $08) <> 0 then
Include(Capabilities, SDCmediumChanger);
if (Buf[6] and $01) <> 0 then
Include(Capabilities, SDCaddress16);
if (Buf[7] and $80) <> 0 then
Include(Capabilities, SDCrelativeAddress);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -