⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsiunit.pas

📁 用于CD/DVD烧录的Delphi源码,包括source和demo
💻 PAS
📖 第 1 页 / 共 5 页
字号:
{-----------------------------------------------------------------------------
 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 + -