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

📄 scsiunit.pas

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