📄 scsiunit.pas
字号:
{-----------------------------------------------------------------------------
Unit Name: SCSIUnit
Author: Sergey Kabikov + Dancemammal
Purpose: SCSI Functions Unit
History: Some Functions by Sergey Kabikov based on his code ASPI/SCSI Library
rewritten by Dancemammal for the burning code
-----------------------------------------------------------------------------}
unit SCSIUnit;
interface
uses Windows, SCSITypes, SCSIDefs, CovertFuncs, Sysutils, SPTIUnit, wnaspi32;
function SCSIinquiryDeviceInfo(DeviceID: TCDBurnerInfo;
var Info: TScsiDeviceInfo; var Sdf: TScsiDefaults): TScsiError;
function SCSIinquiryEX(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD;
CmdDt, EVPD: BOOLEAN; PageCode: BYTE;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSense(DeviceID: TCDBurnerInfo;
PAGE: BYTE; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSensePage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSelectEX(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD;
PF, SP: BOOLEAN;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSelect(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSelectPage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSenseParameter(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Param: pointer; ParamLen, ParamPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSImodeSenseCdStatus(DeviceID: TCDBurnerInfo;
var ModePage: TScsiModePageCdStatus;
var Sdf: TScsiDefaults): TScsiError;
function SCSIgetCdRomCapabilities(DeviceID: TCDBurnerInfo;
var Value: TCdRomCapabilities;
var Sdf: TScsiDefaults): TScsiError;
function SCSIGetDriveSpeeds(DeviceID: TCDBurnerInfo;
var Value: TCDReadWriteSpeeds;
var Sdf: TScsiDefaults): TScsiError;
function SCSIpreventMediumRemoval(DeviceID: TCDBurnerInfo;
MustLock: boolean; var Sdf: TScsiDefaults): TScsiError;
function SCSIstartStopUnit(DeviceID: TCDBurnerInfo;
Start, LoadEject, DontWait: boolean;
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadCdFlagsToSize(SectorType: TScsiReadCdSectorType;
Flags: TScsiReadCdFormatFlags): integer;
function SCSIseek10(DeviceID: TCDBurnerInfo;
GLBA: DWORD; var Sdf: TScsiDefaults): TScsiError;
function SCSIread10EX(DeviceID: TCDBurnerInfo;
DisablePageOut, ForceUnitAccess: boolean;
GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIread10(DeviceID: TCDBurnerInfo;
GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadCdEX(DeviceID: TCDBurnerInfo;
GLBA, SectorCount: DWORD;
SectorType: TScsiReadCdSectorType;
Flags: TScsiReadCdFormatFlags;
Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIWriteCdEX(DeviceID: TCDBurnerInfo;
GLBA, SectorCount: DWORD;
SectorType: TScsiReadCdSectorType;
Flags: TScsiReadCdFormatFlags;
Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIBlankCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
var Sdf: TScsiDefaults): TScsiError;
function SCSIgetMaxBufferSize(DeviceID: TCDBurnerInfo;
var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
function SCSIgetBufferSize(DeviceID: TCDBurnerInfo;
var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
function SCSIgetBufferCapacity(DeviceID: TCDBurnerInfo;
var Value: TScsiCDBufferInfo; var Sdf: TScsiDefaults): TScsiError;
function SCSIReadBuffer(DeviceID: TCDBurnerInfo;
Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
function SCSIReadBufferCapacity(DeviceID: TCDBurnerInfo;
Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
function SCSICloseSession(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
TScsiError;
function SCSICloseTrack(DeviceID: TCDBurnerInfo; Track: byte;
var Sdf: TScsiDefaults): TScsiError;
function SCSISYNCCACHE(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
TScsiError;
function SCSIFormatCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
var Sdf: TScsiDefaults): TScsiError;
function SCSIWrite10EX(DeviceID: TCDBurnerInfo;
DisablePageOut, ForceUnitAccess: boolean;
GLBA, SectorCount: WORD; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIWrite10(DeviceID: TCDBurnerInfo;
GLBA, SectorCount: WORD; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIWriteCDDA(DeviceID: TCDBurnerInfo;
GLBA, SectorCount: DWORD;
SectorType: TScsiReadCdSectorType;
Flags: TScsiReadCdFormatFlags;
Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function ScsiGetWriteParams(DevID: TCDBurnerInfo; Size: Integer; var Param:
string;
var Sdf: TScsiDefaults): TScsiError;
function SCSISetWriteParameters(DevID: TCDBurnerInfo; Size: Integer;
Write_Type, Data_Block_type, Track_Mode, Session_Format: integer;
Packet_Size, Audio_Pause_Length: integer; Test_Write, Burn_Proof: Boolean;
var Sdf: TScsiDefaults): TScsiError;
function SCSISetSpeed(DevID: TCDBurnerInfo; ReadSpeed, WriteSpeed: Integer;
var Sdf: TScsiDefaults): TScsiError;
function SCSISendCUESheet(DeviceID: TCDBurnerInfo;
Buf: pointer; BufSize : Longint; var Sdf: TScsiDefaults): TScsiError;
function SCSItestReady(DeviceID: TCDBurnerInfo;
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadSubChannelEx(DeviceID: TCDBurnerInfo;
InMSF: boolean; // Form of resulting GLBA
GetSubQ: boolean; // requests the Q sub-channel data if True
RequestType: BYTE;
TrackNumber: BYTE;
Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIadrByteToSubQinfoFlags(Arg: BYTE): TScsiSubQinfoFlags;
function SCSIreadCapacity(DeviceID: TCDBurnerInfo;
var LastLBA: DWORD; var Sdf: TScsiDefaults): TScsiError;
function SCSIgetSessionInfo(DeviceID: TCDBurnerInfo;
var Info: TScsiSessionInfo;
var Sdf: TScsiDefaults): TScsiError;
function SCSIgetLayoutInfo(DeviceID: TCDBurnerInfo;
var Info: TDiscLayout;
var Sdf: TScsiDefaults): TScsiError;
function SCSIgetISRC(DeviceID: TCDBurnerInfo; TrackNumber: BYTE;
var Info: TScsiISRC;
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadHeaderEx(DeviceID: TCDBurnerInfo;
InMSF: boolean; // Form of GLBA as result
var GLBA: DWORD; // at enter: LBA to read, at exit: address of
// block processed, in LBA (InMSF=False) or
// MSF (InMSF=True) form.
var SectorType: TScsiReadCdSectorType; // type of block, may
// be csfAudio, csfDataMode1, csfDataMode2,
// or csfAnyType (if error occurs) only
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadHeader(DeviceID: TCDBurnerInfo; GLBA: DWORD;
var SectorType: TScsiReadCdSectorType; // type of block, may
// be csfAudio, csfDataMode1, csfDataMode2,
// or csfAnyType (if error occurs) only
var Sdf: TScsiDefaults): TScsiError;
function SCSIreadTocPmaAtipEx(DeviceID: TCDBurnerInfo;
InMSF: boolean;
RequestType: BYTE;
TrackNumber: BYTE;
Buf: pointer; BufLen: WORD;
var Sdf: TScsiDefaults): TScsiError;
function SCSIgetTOC(DeviceID: TCDBurnerInfo; var TOC: TScsiTOC; var Sdf:
TScsiDefaults): TScsiError;
function SCSIgetTOCCDText(DeviceID: TCDBurnerInfo; var TOCText: TCDText; var
Sdf: TScsiDefaults): TScsiError;
function SCSIReadTrackInformation(DeviceID: TCDBurnerInfo; const ATrack: Byte;
var TrackInformation: TTrackInformation; var Sdf: TScsiDefaults): TScsiError;
function SCSIReadFormatCapacity(DeviceID: TCDBurnerInfo; var FormatCapacity:
TFormatCapacity; var Sdf: TScsiDefaults): TScsiError;
function SCSIReadDiscInformation(DeviceID: TCDBurnerInfo; var DiscInformation:
TDiscInformation; var Sdf: TScsiDefaults): TScsiError;
function SCSIReadDVDStructure(DeviceID: TCDBurnerInfo; var DescriptorStr:
TScsiDVDLayerDescriptorInfo; var Sdf: TScsiDefaults): TScsiError;
function SCSIGetDevConfigProfileMedia(DeviceID: TCDBurnerInfo; var
ProfileDevDiscType: TScsiProfileDeviceDiscTypes; var Sdf: TScsiDefaults):
TScsiError;
implementation
function SCSImodeSense(DeviceID: TCDBurnerInfo;
PAGE: BYTE; Buf: pointer; BufLen: DWORD;
var Sdf: TScsiDefaults): TScsiError;
var
Arg1: byte;
Arg2: DWORD;
CDB: TCDB10;
begin
if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSenseDBD) then
Arg1 := 0
else
Arg1 := 8;
Arg2 := ((Ord(Sdf.ModePageType) and 3) shl 6) or (PAGE and $3F);
FillChar(cdb, 10, 0);
if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
begin
Arg2 := (Arg2 shl 8) or (Arg1 shl 16);
Result := ASPIsend6(DeviceID, $1A, Arg2, BufLen,
Buf, BufLen, SRB_DIR_IN, Sdf);
end
else
begin
{ FillChar(cdb,10,0);
Lba := Arg2 SHL 24; // send as CDB 10
cdb [ 0 ] := SCSI_MODE_SEN10;
cdb [ 2 ] := $2A;
cdb [ 7 ] := HiByte(BufLen);
cdb [ 8 ] := LoByte(BufLen);
Result := ASPIsend10CDB(DeviceID,CDB,Buf,BufLen,SRB_DIR_IN,Sdf); }
Result := ASPIsend10(DeviceID, $5A, Arg1, Arg2 shl 24, 0, BufLen,
Buf, BufLen, SRB_DIR_IN, Sdf);
end;
end;
function SCSImodeSelectEX(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD;
PF, SP: BOOLEAN;
var Sdf: TScsiDefaults): TScsiError;
var
Arg1: byte;
Arg2: DWORD;
cdb6: Tcdb6;
cdb10: TCDB10;
begin
FillChar(cdb6, 6, 0); // clear cdb
FillChar(cdb10, 10, 0); // clear cdb
if PF then
Arg1 := $10
else
Arg1 := 0;
if SP then
Arg1 := Arg1 or 1;
if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
begin
Arg2 := (Arg1 shl 16); // send as CDB 6
cdb6[0] := SCSI_MODE_SEL6;
cdb6[1] := AttachLUN(cdb6[1], DeviceID.DriveID);
cdb6[4] := Arg2;
Result := ASPIsend6CDB(DeviceID, CDB6, Buf, BufLen, SRB_DIR_OUT, Sdf);
end
else
begin
// cdr CDB: 55 10 00 00 00 00 00 00 3C 00
cdb10[0] := SCSI_MODE_SEL10;
cdb10[1] := AttachLUN(Arg1, DeviceID.DriveID);
FillWORD(BufLen, cdb10[7]); //test 7 to 8
Result := ASPIsend10CDB(DeviceID, CDB10, Buf, BufLen, SRB_DIR_OUT, Sdf);
end;
end;
function SCSImodeSelect(DeviceID: TCDBurnerInfo;
Buf: pointer; BufLen: DWORD; var Sdf: TScsiDefaults): TScsiError;
begin
Result := SCSImodeSelectEX(DeviceID, Buf, BufLen, TRUE, FALSE, Sdf);
end;
{function SCSImodeSensePage(DeviceID : TCDBurnerInfo; PageCode : BYTE;
Buf : pointer; var BufLen : DWORD; BufPos : DWORD;
var Sdf : TScsiDefaults) : TScsiError;
var Src10 : TScsiModePageTemplate10;
Src6 : TScsiModePageTemplate6;
ps : PScsiModePageRecord;
mp : integer;
begin
if not Assigned(Buf) then begin
Result := Err_InvalidArgument;
exit;
end;
// fillchar(Src10,sizeof(Src10),0);
if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
begin
Result := SCSImodeSense(DeviceID, PageCode, @Src6, BufLen, Sdf);
if Result <> Err_None then
begin
BufLen := 0;
exit;
end;
ps := PScsiModePageRecord(@Src6.Params6[Src6.DescriptorLength6]);
mp := ScsiModeTemplateParamsLength - 1 - Src6.DescriptorLength6;
end
else
begin
Result := SCSImodeSense(DeviceID, PageCode, @Src10, BufLen, Sdf);
if Result <> Err_None then
begin
BufLen := 0;
exit;
end;
ps := PScsiModePageRecord(@Src10.Params10[Src10.DescriptorLength10]);
mp := ScsiModeTemplateParamsLength - 1 - Src10.DescriptorLength10;
end;
if (mp <= integer(BufPos)) or (ps^.ParamLength <= BufPos) then
begin
Result := Err_Unknown;
BufLen := 0;
exit;
end;
if mp > ps^.ParamLength then mp := ps^.ParamLength;
Dec(mp, BufPos);
if BufLen > DWORD(mp) then BufLen := DWORD(mp);
if Assigned(Buf) then
BEGIN
System.Move(ps^.Params, Buf^, BufLen);
END;
end; }
function SCSImodeSensePage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
var Sdf: TScsiDefaults): TScsiError;
var
Src6: TScsiModePageTemplate6;
Src10: TScsiModePageTemplate10;
pp, ps: PScsiModePageRecord;
mp, len, dblen: integer;
begin
if not Assigned(Buf) then
begin
Result := Err_InvalidArgument;
exit;
end;
fillchar(Src10, sizeof(Src10), 0);
Result := SCSImodeSense(DeviceID, PageCode, @Src10, BufLen, Sdf);
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;
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 := Integer(BigEndianW(Src10.DescriptorLength10));
// 2nd break point - dblen=integer & BigIndian returns DWORD
len := BigEndianW(Src10.ModeDataLength10) - dblen;
Src10.ModeDataLength10 := BigEndianW(len);
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 <= Integer(BufPos)) or (ps^.ParamLength <= BufPos) or (len <= 0) then
begin
Result := Err_Unknown;
BufLen := 0;
exit;
end;
if mp > Integer(ps^.ParamLength) then
mp := Integer(ps^.ParamLength); // 3rd break point
if BufLen > (DWORD(mp) - BufPos) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -