SCSIUnit.pas
上传用户:wanyu_2000
上传日期:2021-02-21
资源大小:527k
文件大小:75k
源码类别:

DVD

开发平台:

Delphi

  1. {-----------------------------------------------------------------------------
  2.  Unit Name: SCSIUnit
  3.  Author:    Sergey Kabikov + Dancemammal
  4.  Purpose:   SCSI Functions Unit
  5.  History:  Some Functions by Sergey Kabikov based on his code ASPI/SCSI Library
  6.     rewritten by Dancemammal for the burning code
  7. -----------------------------------------------------------------------------}
  8. unit SCSIUnit;
  9. interface
  10. uses Windows, SCSITypes, SCSIDefs, CovertFuncs, Sysutils, DeviceTypes, SPTIUnit, wnaspi32;
  11. function SCSIinquiryDeviceInfo(DeviceID: TCDBurnerInfo;
  12.   var Info: TScsiDeviceInfo; var Sdf: TScsiDefaults): TScsiError;
  13. function SCSIinquiryEX(DeviceID: TCDBurnerInfo;
  14.   Buf: pointer; BufLen: DWORD;
  15.   CmdDt, EVPD: BOOLEAN; PageCode: BYTE;
  16.   var Sdf: TScsiDefaults): TScsiError;
  17. function SCSImodeSense(DeviceID: TCDBurnerInfo;
  18.   PAGE: BYTE; Buf: pointer; BufLen: DWORD;
  19.   var Sdf: TScsiDefaults): TScsiError;
  20. function SCSImodeSensePage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  21.   Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
  22.   var Sdf: TScsiDefaults): TScsiError;
  23. function SCSImodeSelectEX(DeviceID: TCDBurnerInfo;
  24.   Buf: pointer; BufLen: DWORD;
  25.   PF, SP: BOOLEAN;
  26.   var Sdf: TScsiDefaults): TScsiError;
  27. function SCSImodeSelect(DeviceID: TCDBurnerInfo;
  28.   Buf: pointer; BufLen: DWORD;
  29.   var Sdf: TScsiDefaults): TScsiError;
  30. function SCSImodeSelectPage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  31.   Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
  32.   var Sdf: TScsiDefaults): TScsiError;
  33. function SCSImodeSenseParameter(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  34.   Param: pointer; ParamLen, ParamPos: DWORD;
  35.   var Sdf: TScsiDefaults): TScsiError;
  36. function SCSImodeSenseCdStatus(DeviceID: TCDBurnerInfo;
  37.   var ModePage: TScsiModePageCdStatus;
  38.   var Sdf: TScsiDefaults): TScsiError;
  39. function SCSIgetCdRomCapabilities(DeviceID: TCDBurnerInfo;
  40.   var Value: TCdRomCapabilities;
  41.   var Sdf: TScsiDefaults): TScsiError;
  42. function SCSIGetDriveSpeeds(DeviceID: TCDBurnerInfo;
  43.   var Value: TCDReadWriteSpeeds;
  44.   var Sdf: TScsiDefaults): TScsiError;
  45. function SCSIpreventMediumRemoval(DeviceID: TCDBurnerInfo;
  46.   MustLock: boolean; var Sdf: TScsiDefaults): TScsiError;
  47. function SCSIstartStopUnit(DeviceID: TCDBurnerInfo;
  48.   Start, LoadEject, DontWait: boolean;
  49.   var Sdf: TScsiDefaults): TScsiError;
  50. function SCSIreadCdFlagsToSize(SectorType: TScsiReadCdSectorType;
  51.   Flags: TScsiReadCdFormatFlags): integer;
  52. function SCSIseek10(DeviceID: TCDBurnerInfo;
  53.   GLBA: DWORD; var Sdf: TScsiDefaults): TScsiError;
  54. function SCSIread10EX(DeviceID: TCDBurnerInfo;
  55.   DisablePageOut, ForceUnitAccess: boolean;
  56.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  57.   var Sdf: TScsiDefaults): TScsiError;
  58. function SCSIread10(DeviceID: TCDBurnerInfo;
  59.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  60.   var Sdf: TScsiDefaults): TScsiError;
  61. function SCSIreadCdEX(DeviceID: TCDBurnerInfo;
  62.   GLBA, SectorCount: DWORD;
  63.   SectorType: TScsiReadCdSectorType;
  64.   Flags: TScsiReadCdFormatFlags;
  65.   Buf: pointer; BufLen: DWORD;
  66.   var Sdf: TScsiDefaults): TScsiError;
  67. function SCSIWriteCdEX(DeviceID: TCDBurnerInfo;
  68.   GLBA, SectorCount: DWORD;
  69.   SectorType: TScsiReadCdSectorType;
  70.   Flags: TScsiReadCdFormatFlags;
  71.   Buf: pointer; BufLen: DWORD;
  72.   var Sdf: TScsiDefaults): TScsiError;
  73. function SCSIBlankCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
  74.   var Sdf: TScsiDefaults): TScsiError;
  75. function SCSIgetMaxBufferSize(DeviceID: TCDBurnerInfo;
  76.   var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
  77. function SCSIgetBufferSize(DeviceID: TCDBurnerInfo;
  78.   var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
  79. function SCSIgetBufferCapacity(DeviceID: TCDBurnerInfo;
  80.   var Value: TScsiCDBufferInfo; var Sdf: TScsiDefaults): TScsiError;
  81. function SCSIReadBuffer(DeviceID: TCDBurnerInfo;
  82.   Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
  83. function SCSIReadBufferCapacity(DeviceID: TCDBurnerInfo;
  84.   Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
  85. function SCSICloseSession(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
  86.   TScsiError;
  87. function SCSIGetFormatCapacity(DeviceID: TCDBurnerInfo; var Capacity: Cardinal;
  88.     var SectorSize: Cardinal; var Sdf: TScsiDefaults):TScsiError;
  89. function SCSICloseTrack(DeviceID: TCDBurnerInfo; Track: byte;
  90.   var Sdf: TScsiDefaults): TScsiError;
  91. function SCSISYNCCACHE(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
  92.   TScsiError;
  93. function SCSIFormatCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
  94.   var Sdf: TScsiDefaults): TScsiError;
  95. function SCSIWrite10EX(DeviceID: TCDBurnerInfo;
  96.   DisablePageOut, ForceUnitAccess: boolean;
  97.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  98.   var Sdf: TScsiDefaults): TScsiError;
  99. function SCSIWrite10(DeviceID: TCDBurnerInfo;
  100.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  101.   var Sdf: TScsiDefaults): TScsiError;
  102. function SCSIWrite12EX(DeviceID: TCDBurnerInfo;
  103.   DisablePageOut, ForceUnitAccess: boolean;
  104.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  105.   var Sdf: TScsiDefaults): TScsiError;
  106. function SCSIWrite12(DeviceID: TCDBurnerInfo;
  107.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  108.   var Sdf: TScsiDefaults): TScsiError;
  109. function SCSISendDVDStructureTimeStamp(DeviceID: TCDBurnerInfo;
  110.               Time: TDateTime; var Sdf: TScsiDefaults): TScsiError;
  111. function SCSISendDVDStructure(DeviceID: TCDBurnerInfo;
  112.         Format: Byte; Buf: Pointer; BufLength: Word; var Sdf: TScsiDefaults): TScsiError;
  113. function SCSISetStreamingMode(DeviceID: TCDBurnerInfo;var Sdf: TScsiDefaults): TScsiError;
  114. function SCSIReserveTrack(DeviceID: TCDBurnerInfo;
  115.        ReserveSize: Cardinal; var Sdf: TScsiDefaults): TScsiError;
  116. function SCSItestReady(DeviceID: TCDBurnerInfo;
  117.   var Sdf: TScsiDefaults): Boolean;
  118. function SCSIDeviceReadyTimeOut(DeviceID: TCDBurnerInfo; TimeOut, Step: Integer;
  119.     var Sdf: TScsiDefaults): Boolean;
  120.                                        
  121. function SCSIWriteCDDA(DeviceID: TCDBurnerInfo;
  122.   GLBA, SectorCount: DWORD;
  123.   SectorType: TScsiReadCdSectorType;
  124.   Flags: TScsiReadCdFormatFlags;
  125.   Buf: pointer; BufLen: DWORD;
  126.   var Sdf: TScsiDefaults): TScsiError;
  127. function ScsiGetWriteParams(DevID: TCDBurnerInfo; Size: Integer; var Param:
  128.   string;
  129.   var Sdf: TScsiDefaults): TScsiError;
  130. function SCSISetWriteParameters(DevID: TCDBurnerInfo; Size: Integer; BurnSettings: TBurnSettings;
  131.   var Sdf: TScsiDefaults): TScsiError;
  132. function SCSISetSpeed(DevID: TCDBurnerInfo; ReadSpeed, WriteSpeed: Integer;
  133.   var Sdf: TScsiDefaults): TScsiError;
  134. function SCSISendCUESheet(DeviceID: TCDBurnerInfo;
  135.   Buf: pointer; BufSize : Longint; var Sdf: TScsiDefaults): TScsiError;
  136. function SCSIreadSubChannelEx(DeviceID: TCDBurnerInfo;
  137.   InMSF: boolean; // Form of resulting GLBA
  138.   GetSubQ: boolean; // requests the Q sub-channel data if True
  139.   RequestType: BYTE;
  140.   TrackNumber: BYTE;
  141.   Buf: pointer; BufLen: DWORD;
  142.   var Sdf: TScsiDefaults): TScsiError;
  143. function SCSIadrByteToSubQinfoFlags(Arg: BYTE): TScsiSubQinfoFlags;
  144. function SCSIreadCapacity(DeviceID: TCDBurnerInfo;
  145.   var LastLBA: DWORD; var Sdf: TScsiDefaults): TScsiError;
  146. function SCSIgetSessionInfo(DeviceID: TCDBurnerInfo;
  147.   var Info: TScsiSessionInfo;
  148.   var Sdf: TScsiDefaults): TScsiError;
  149. function SCSIgetLayoutInfo(DeviceID: TCDBurnerInfo;
  150.   var Info: TDiscLayout;
  151.   var Sdf: TScsiDefaults): TScsiError;
  152. function SCSIgetISRC(DeviceID: TCDBurnerInfo; TrackNumber: BYTE;
  153.   var Info: TScsiISRC;
  154.   var Sdf: TScsiDefaults): TScsiError;
  155. function SCSIreadHeaderEx(DeviceID: TCDBurnerInfo;
  156.   InMSF: boolean; // Form of GLBA as result
  157.   var GLBA: DWORD; // at enter: LBA to read, at exit: address of
  158.   //   block processed, in LBA (InMSF=False) or
  159.   //   MSF (InMSF=True) form.
  160.   var SectorType: TScsiReadCdSectorType; // type of block, may
  161.   // be csfAudio, csfDataMode1, csfDataMode2,
  162.   // or csfAnyType (if error occurs) only
  163.   var Sdf: TScsiDefaults): TScsiError;
  164. function SCSIreadHeader(DeviceID: TCDBurnerInfo; GLBA: DWORD;
  165.   var SectorType: TScsiReadCdSectorType; // type of block, may
  166.   // be csfAudio, csfDataMode1, csfDataMode2,
  167.   // or csfAnyType (if error occurs) only
  168.   var Sdf: TScsiDefaults): TScsiError;
  169. function SCSIreadTocPmaAtipEx(DeviceID: TCDBurnerInfo;
  170.   InMSF: boolean;
  171.   RequestType: BYTE;
  172.   TrackNumber: BYTE;
  173.   Buf: pointer; BufLen: WORD;
  174.   var Sdf: TScsiDefaults): TScsiError;
  175. function SCSIgetTOC(DeviceID: TCDBurnerInfo; var TOC: TScsiTOC; var Sdf:
  176.   TScsiDefaults): TScsiError;
  177. function SCSIgetTOCCDText(DeviceID: TCDBurnerInfo; var TOCText: TCDText; var
  178.   Sdf: TScsiDefaults): TScsiError;
  179. function SCSIReadTrackInformation(DeviceID: TCDBurnerInfo; const ATrack: Byte;
  180.   var TrackInformation: TTrackInformation; var Sdf: TScsiDefaults): TScsiError;
  181. function SCSIReadFormatCapacity(DeviceID: TCDBurnerInfo; var FormatCapacity:
  182.   TFormatCapacity; var Sdf: TScsiDefaults): TScsiError;
  183. function SCSIReadDiscInformation(DeviceID: TCDBurnerInfo; var DiscInformation:
  184.   TDiscInformation; var Sdf: TScsiDefaults): TScsiError;
  185. function SCSIReadDVDStructure(DeviceID: TCDBurnerInfo; var DescriptorStr:
  186.   TScsiDVDLayerDescriptorInfo; var Sdf: TScsiDefaults): TScsiError;
  187. function SCSIGetDevConfigProfileMedia(DeviceID: TCDBurnerInfo; var
  188.   ProfileDevDiscType: TScsiProfileDeviceDiscTypes; var Sdf: TScsiDefaults):
  189.   TScsiError;
  190. implementation
  191. function SCSImodeSense(DeviceID: TCDBurnerInfo;
  192.   PAGE: BYTE; Buf: pointer; BufLen: DWORD;
  193.   var Sdf: TScsiDefaults): TScsiError;
  194. var
  195.   Arg1: byte;
  196.   Arg2: DWORD;
  197.   CDB: TCDB10;
  198. begin
  199.   if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSenseDBD) then
  200.     Arg1 := 0
  201.   else
  202.     Arg1 := 8;
  203.   Arg2 := ((Ord(Sdf.ModePageType) and 3) shl 6) or (PAGE and $3F);
  204.   FillChar(cdb, 10, 0);
  205.   if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
  206.   begin
  207.     Arg2 := (Arg2 shl 8) or (Arg1 shl 16);
  208.     Result := ASPIsend6(DeviceID, $1A, Arg2, BufLen,
  209.       Buf, BufLen, SRB_DIR_IN, Sdf);
  210.   end
  211.   else
  212.   begin
  213.     { FillChar(cdb,10,0);
  214.      Lba := Arg2 SHL 24;                      // send as CDB 10
  215.      cdb [ 0 ] := SCSI_MODE_SEN10;
  216.      cdb [ 2 ] := $2A;
  217.      cdb [ 7 ] := HiByte(BufLen);
  218.      cdb [ 8 ] := LoByte(BufLen);
  219.      Result := ASPIsend10CDB(DeviceID,CDB,Buf,BufLen,SRB_DIR_IN,Sdf);  }
  220.     Result := ASPIsend10(DeviceID, $5A, Arg1, Arg2 shl 24, 0, BufLen,
  221.       Buf, BufLen, SRB_DIR_IN, Sdf);
  222.   end;
  223. end;
  224. function SCSImodeSelectEX(DeviceID: TCDBurnerInfo;
  225.   Buf: pointer; BufLen: DWORD;
  226.   PF, SP: BOOLEAN;
  227.   var Sdf: TScsiDefaults): TScsiError;
  228. var
  229.   Arg1: byte;
  230.   Arg2: DWORD;
  231.   cdb6: Tcdb6;
  232.   cdb10: TCDB10;
  233. begin
  234.   FillChar(cdb6, 6, 0); // clear cdb
  235.   FillChar(cdb10, 10, 0); // clear cdb
  236.   if PF then
  237.     Arg1 := $10
  238.   else
  239.     Arg1 := 0;
  240.   if SP then
  241.     Arg1 := Arg1 or 1;
  242.   if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
  243.   begin
  244.     Arg2 := (Arg1 shl 16); // send as CDB 6
  245.     cdb6[0] := SCSI_MODE_SEL6;
  246.     cdb6[1] := AttachLUN(cdb6[1], DeviceID.DriveID);
  247.     cdb6[4] := Arg2;
  248.     Result := ASPIsend6CDB(DeviceID, CDB6, Buf, BufLen, SRB_DIR_OUT, Sdf);
  249.   end
  250.   else
  251.   begin
  252.     // cdr CDB:  55 10 00 00 00 00 00 00 3C 00
  253.     cdb10[0] := SCSI_MODE_SEL10;
  254.     cdb10[1] := AttachLUN(Arg1, DeviceID.DriveID);
  255.     FillWORD(BufLen, cdb10[7]); //test 7 to 8
  256.     Result := ASPIsend10CDB(DeviceID, CDB10, Buf, BufLen, SRB_DIR_OUT, Sdf);
  257.   end;
  258. end;
  259. function SCSImodeSelect(DeviceID: TCDBurnerInfo;
  260.   Buf: pointer; BufLen: DWORD; var Sdf: TScsiDefaults): TScsiError;
  261. begin
  262.   Result := SCSImodeSelectEX(DeviceID, Buf, BufLen, TRUE, FALSE, Sdf);
  263. end;
  264. {function SCSImodeSensePage(DeviceID : TCDBurnerInfo; PageCode : BYTE;
  265.                 Buf : pointer; var BufLen : DWORD; BufPos : DWORD;
  266.                 var Sdf : TScsiDefaults) : TScsiError;
  267. var Src10 : TScsiModePageTemplate10;
  268.     Src6 : TScsiModePageTemplate6;
  269.     ps  : PScsiModePageRecord;
  270.     mp  : integer;
  271. begin
  272.    if not Assigned(Buf)  then begin
  273.       Result := Err_InvalidArgument;
  274.       exit;
  275.    end;
  276.   // fillchar(Src10,sizeof(Src10),0);
  277.    if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
  278.     begin
  279.        Result := SCSImodeSense(DeviceID, PageCode, @Src6, BufLen, Sdf);
  280.         if Result <> Err_None then
  281.         begin
  282.               BufLen := 0;
  283.               exit;
  284.         end;
  285.       ps := PScsiModePageRecord(@Src6.Params6[Src6.DescriptorLength6]);
  286.       mp := ScsiModeTemplateParamsLength - 1 - Src6.DescriptorLength6;
  287.    end
  288.     else
  289.     begin
  290.        Result := SCSImodeSense(DeviceID, PageCode, @Src10, BufLen, Sdf);
  291.         if Result <> Err_None then
  292.          begin
  293.             BufLen := 0;
  294.             exit;
  295.          end;
  296.       ps := PScsiModePageRecord(@Src10.Params10[Src10.DescriptorLength10]);
  297.       mp := ScsiModeTemplateParamsLength - 1 - Src10.DescriptorLength10;
  298.    end;
  299.    if (mp <= integer(BufPos)) or (ps^.ParamLength <= BufPos) then
  300.     begin
  301.       Result := Err_Unknown;
  302.       BufLen := 0;
  303.       exit;
  304.    end;
  305.    if mp > ps^.ParamLength then mp := ps^.ParamLength;
  306.    Dec(mp, BufPos);
  307.    if BufLen > DWORD(mp) then BufLen := DWORD(mp);
  308.    if Assigned(Buf) then
  309.    BEGIN
  310.      System.Move(ps^.Params, Buf^, BufLen);
  311.    END;
  312. end;  }
  313. function SCSImodeSensePage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  314.   Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
  315.   var Sdf: TScsiDefaults): TScsiError;
  316. var
  317.   Src6: TScsiModePageTemplate6;
  318.   Src10: TScsiModePageTemplate10;
  319.   pp, ps: PScsiModePageRecord;
  320.   mp, len, dblen: integer;
  321. begin
  322.   if not Assigned(Buf) then
  323.   begin
  324.     Result := Err_InvalidArgument;
  325.     exit;
  326.   end;
  327.   fillchar(Src10, sizeof(Src10), 0);
  328.   Result := SCSImodeSense(DeviceID, PageCode, @Src10, BufLen, Sdf);
  329.   if Result <> Err_None then
  330.   begin
  331.     BufLen := 0;
  332.     exit;
  333.   end;
  334.   // Exclude block descriptors if exists
  335.   if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then
  336.   begin
  337.     dblen := Src6.DescriptorLength6;
  338.     len := Src6.ModeDataLength6 - dblen;
  339.     Src6.ModeDataLength6 := len;
  340.     Inc(len, SizeOf(Src6.ModeDataLength6)); // Full length of record
  341.     pp := PScsiModePageRecord(@Src6.Params6[0]);
  342.     ps := PScsiModePageRecord(@Src6.Params6[dblen]);
  343.     //    gs := PScsiModePageRecord(@Chg6.Params6[Chg6.DescriptorLength6]);
  344.     mp := ScsiModeTemplateParamsLength - 1 - dblen;
  345.   end
  346.   else
  347.   begin
  348.     dblen := Integer(BigEndianW(Src10.DescriptorLength10));
  349.     // 2nd break point - dblen=integer & BigIndian returns DWORD
  350.     len := BigEndianW(Src10.ModeDataLength10) - dblen;
  351.     Src10.ModeDataLength10 := BigEndianW(len);
  352.     Inc(len, SizeOf(Src10.ModeDataLength10)); // Full length of record
  353.     pp := PScsiModePageRecord(@Src10.Params10[0]);
  354.     ps := PScsiModePageRecord(@Src10.Params10[dblen]);
  355.     //    gs := PScsiModePageRecord(@Chg10.Params10[BigEndianW(Chg10.DescriptorLength10)]);
  356.     mp := ScsiModeTemplateParamsLength - 1 - dblen;
  357.   end;
  358.   if (mp <= Integer(BufPos)) or (ps^.ParamLength <= BufPos) or (len <= 0) then
  359.   begin
  360.     Result := Err_Unknown;
  361.     BufLen := 0;
  362.     exit;
  363.   end;
  364.   if mp > Integer(ps^.ParamLength) then
  365.     mp := Integer(ps^.ParamLength); // 3rd break point
  366.   if BufLen > (DWORD(mp) - BufPos) then
  367.     BufLen := (DWORD(mp) - BufPos);
  368.   System.Move(pp^, Buf^, BufLen);
  369. end;
  370. {
  371. function SCSImodeSelectPage(DeviceID : TCDBurnerInfo; PageCode : BYTE;
  372.                 Buf : pointer; var BufLen : DWORD; BufPos : DWORD;
  373.                 var Sdf : TScsiDefaults) : TScsiError;
  374. var
  375.     Src6, Chg6   : TScsiModePageTemplate6;
  376.     Chg10 ,Src10 : TScsiModePageTemplate10;
  377.     SdfTemp    : TCdRomModePageType;
  378.     pp, ps, gs : PScsiModePageRecord;
  379.     i, mp, len, dblen : integer;
  380. begin
  381.    if not Assigned(Buf)  then begin
  382.       Result := Err_InvalidArgument;
  383.       exit;
  384.    end;
  385.    Result := SCSImodeSense(DeviceID, PageCode, @Src10, sizeof(Src10), Sdf);
  386.    if Result <> Err_None then begin
  387.       BufLen := 0;
  388.       exit;
  389.    end;
  390.    SdfTemp := Sdf.ModePageType;
  391.    Sdf.ModePageType := MPTchangeable;
  392.    Result := SCSImodeSense(DeviceID, PageCode, @Chg10, sizeof(Chg10), Sdf);
  393.    Sdf.ModePageType := SdfTemp;
  394.    if Result <> Err_None then begin
  395.       BufLen := 0;
  396.       exit;
  397.    end;
  398.        // Exclude block descriptors if exists
  399.    if ASPIgetDeviceIDflag(DeviceID.DriveID, ADIDmodeSense6) then begin
  400.       dblen := Src6.DescriptorLength6;
  401.       len   := Src6.ModeDataLength6 - dblen;
  402.       Src6.ModeDataLength6 := len;
  403.       Src6.MediumType6       := 0;
  404.       Src6.DeviceSpecific6   := 0;
  405.       Src6.DescriptorLength6 := 0;
  406.       Inc(len, SizeOf(Src6.ModeDataLength6));      // Full length of record
  407.       pp := PScsiModePageRecord(@Src6.Params6[0]);
  408.       ps := PScsiModePageRecord(@Src6.Params6[dblen]);
  409.       gs := PScsiModePageRecord(@Chg6.Params6[Chg6.DescriptorLength6]);
  410.       mp := ScsiModeTemplateParamsLength - 1 - dblen;
  411.    end else begin
  412.       dblen := BigEndianW(Src10.DescriptorLength10);
  413.       len   := BigEndianW(Src10.ModeDataLength10) - dblen;
  414.       Src10.ModeDataLength10 := BigEndianW(len);
  415.       Src10.MediumType10       := 0;
  416.       Src10.DeviceSpecific10   := 0;
  417.       Src10.Reserved10         := 0;
  418.       Src10.DescriptorLength10 := 0;
  419.       Inc(len, SizeOf(Src10.ModeDataLength10));   // Full length of record
  420.       pp := PScsiModePageRecord(@Src10.Params10[0]);
  421.       ps := PScsiModePageRecord(@Src10.Params10[dblen]);
  422.       gs := PScsiModePageRecord(@Chg10.Params10[
  423.                      BigEndianW(Chg10.DescriptorLength10)]);
  424.       mp := ScsiModeTemplateParamsLength - 1 - dblen;
  425.    end;
  426.    if (mp <= BufPos) or (ps^.ParamLength <= BufPos) or (len <= 0) then begin
  427.       Result := Err_Unknown;
  428.       BufLen := 0;
  429.       exit;
  430.    end;
  431.    if mp > ps^.ParamLength  then mp := ps^.ParamLength;
  432.    if dblen <> 0 then System.Move(ps^, pp^, mp+2);
  433.    if BufLen > (mp - BufPos) then BufLen := (mp - BufPos);
  434.    System.Move(Buf^, pp^, BufLen);
  435.   // for i := 0 to mp-1 do
  436.   //  pp^.Params[i] := pp^.Params[i] AND gs^.Params[i];
  437.    Result := SCSImodeSelect(DeviceID, @Src10, len, Sdf);
  438. end; }
  439. {$WARNINGS OFF}
  440. function SCSImodeSelectPage(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  441.   Buf: pointer; var BufLen: DWORD; BufPos: DWORD;
  442.   var Sdf: TScsiDefaults): TScsiError;
  443. var
  444.   Src10: TScsiModePageTemplate2;
  445.   pp, ps: PScsiModePageRecord;
  446.   mp, len, dblen: integer;
  447. begin
  448.   if not Assigned(Buf) then
  449.   begin
  450.     Result := Err_InvalidArgument;
  451.     exit;
  452.   end;
  453.   Result := SCSImodeSense(DeviceID, PageCode, @Src10, sizeof(Src10), Sdf);
  454.   if Result <> Err_None then
  455.   begin
  456.     BufLen := 0;
  457.     exit;
  458.   end;
  459.   begin
  460.     dblen := BigEndianW(Src10.DescriptorLength10);
  461.     len := BigEndianW(Src10.ModeDataLength10) - dblen;
  462.     Src10.ModeDataLength10 := BigEndianW(len);
  463.     Src10.MediumType10 := 0;
  464.     Src10.DeviceSpecific10 := 0;
  465.     Src10.Reserved10 := 0;
  466.     Src10.DescriptorLength10 := 0;
  467.     Inc(len, SizeOf(Src10.ModeDataLength10)); // Full length of record
  468.     pp := PScsiModePageRecord(@Src10.Params10[0]);
  469.     ps := PScsiModePageRecord(@Src10.Params10[dblen]);
  470.     mp := ScsiModeTemplateParamsLength - 1 - dblen;
  471.   end;
  472.   if (mp <= BufPos) or (ps^.ParamLength <= BufPos) or (len <= 0) then
  473.   begin
  474.     Result := Err_Unknown;
  475.     BufLen := 0;
  476.     exit;
  477.   end;
  478.   if mp > ps^.ParamLength then
  479.     mp := ps^.ParamLength;
  480.   if dblen <> 0 then
  481.     System.Move(ps^, pp^, mp + 2);
  482.   if BufLen > (mp - BufPos) then
  483.     BufLen := (mp - BufPos);
  484.   System.Move(Buf^, pp^, BufLen);
  485.   Result := SCSImodeSelect(DeviceID, @Src10, len, Sdf);
  486. end;
  487. {$WARNINGS ON}
  488. function SCSImodeSenseCdStatus(DeviceID: TCDBurnerInfo;
  489.   var ModePage: TScsiModePageCdStatus;
  490.   var Sdf: TScsiDefaults): TScsiError;
  491. var
  492.   PageSize: DWORD;
  493. begin
  494.   ZeroMemory(@ModePage, SizeOf(ModePage));
  495.   PageSize := SizeOf(ModePage);
  496.   Result := SCSImodeSensePage(DeviceID, $2A, @ModePage, PageSize, 0, Sdf);
  497. end;
  498. {$WARNINGS OFF}
  499. function SCSImodeSenseParameter(DeviceID: TCDBurnerInfo; PageCode: BYTE;
  500.   Param: pointer; ParamLen, ParamPos: DWORD;
  501.   var Sdf: TScsiDefaults): TScsiError;
  502. var
  503.   tp: array[0..ScsiModePageParamsLength - 1] of BYTE;
  504.   len: DWORD;
  505. begin
  506.   if ((ParamPos + ParamLen) > ScsiModePageParamsLength)
  507.     or (ParamPos < 0) or (ParamLen <= 0)
  508.     or not Assigned(Param) then
  509.   begin
  510.     Result := Err_InvalidArgument;
  511.     exit;
  512.   end;
  513.   len := ParamLen;
  514.   Result := SCSImodeSensePage(DeviceID, PageCode, @tp, len, ParamPos, Sdf);
  515.   if Result = Err_None then
  516.   begin
  517.     if len = ParamLen then
  518.       BigEndian(tp, Param^, ParamLen)
  519.     else
  520.       Result := Err_InvalidArgument;
  521.   end;
  522. end;
  523. {$WARNINGS ON}
  524. function SCSIGetDriveSpeeds(DeviceID: TCDBurnerInfo;
  525.   var Value: TCDReadWriteSpeeds;
  526.   var Sdf: TScsiDefaults): TScsiError;
  527. var
  528.   ModePage: TScsiModePageCdStatus;
  529. begin
  530.   Result := SCSImodeSenseCdStatus(DeviceID, ModePage, Sdf);
  531.   Value.MaxReadSpeed := Round(SwapWord(ModePage.MaxReadSpeed) / 176.46);
  532.   Value.CurrentReadSpeed := Round(SwapWord(ModePage.CurrentReadSpeed) / 176.46);
  533.   Value.MaxWriteSpeed := Round(SwapWord(ModePage.MaxWriteSpeed) / 176.46);
  534.   Value.CurrentWriteSpeed := Round(SwapWord(ModePage.CurWriteSpeed_Res) / 176.46);
  535.   Value.buffersize := Round(SwapWord(ModePage.MaxBufferSize));
  536. end;
  537. function SCSIgetCdRomCapabilities(DeviceID: TCDBurnerInfo;
  538.   var Value: TCdRomCapabilities;
  539.   var Sdf: TScsiDefaults): TScsiError;
  540. var
  541.   ModePage: TScsiModePageCdStatus;
  542.   FB: BYTE;
  543. begin
  544.   ZeroMemory(@ModePage, SizeOf(ModePage));
  545.   Result := SCSImodeSenseCdStatus(DeviceID, ModePage, Sdf);
  546.   Value := [];
  547.   FB := ModePage.Flags[0];
  548.   if (FB and CDSTATUS_READ_CD_R) <> 0 then
  549.     Include(Value, cdcReadCDR);
  550.   if (FB and CDSTATUS_READ_CD_RW) <> 0 then
  551.     Include(Value, cdcReadCDRW);
  552.   if (FB and CDSTATUS_READ_METHOD2) <> 0 then
  553.     Include(Value, cdcReadMethod2);
  554.   if (FB and CDSTATUS_READ_DVD_ROM) <> 0 then
  555.     Include(Value, cdcReadDVD);
  556.   if (FB and CDSTATUS_READ_DVD_R) <> 0 then
  557.     Include(Value, cdcReadDVDR);
  558.   if (FB and CDSTATUS_READ_DVD_RAM) <> 0 then
  559.     Include(Value, cdcReadDVDRAM);
  560.   FB := ModePage.Flags[1];
  561.   if (FB and CDSTATUS_WRITE_CD_R) <> 0 then
  562.     Include(Value, cdcWriteCDR);
  563.   if (FB and CDSTATUS_WRITE_CD_RW) <> 0 then
  564.     Include(Value, cdcWriteCDRW);
  565.   if (FB and CDSTATUS_WRITE_DVD_R) <> 0 then
  566.     Include(Value, cdcWriteDVDR);
  567.   if (FB and CDSTATUS_WRITE_DVD_RAM) <> 0 then
  568.     Include(Value, cdcWriteDVDRAM);
  569.   if (FB and CDSTATUS_TEST_MODE) <> 0 then
  570.     Include(Value, cdcWriteTestMode);
  571.   FB := ModePage.Flags[2];
  572.   if (FB and CDSTATUS_AUDIO_PLAY) <> 0 then
  573.     Include(Value, cdcAudioPlay);
  574.   if (FB and CDSTATUS_AUDIO_COMPOSITE) <> 0 then
  575.     Include(Value, cdcAudioComposite);
  576.   if (FB and CDSTATUS_AUDIO_DIGIPORT1) <> 0 then
  577.     Include(Value, cdcAudioDigiPort1);
  578.   if (FB and CDSTATUS_AUDIO_DIGIPORT2) <> 0 then
  579.     Include(Value, cdcAudioDigiPort2);
  580.   if (FB and CDSTATUS_READ_MODE2_FORM1) <> 0 then
  581.     Include(Value, cdcReadMode2form1);
  582.   if (FB and CDSTATUS_READ_MODE2_FORM2) <> 0 then
  583.     Include(Value, cdcReadMode2form2);
  584.   if (FB and CDSTATUS_READ_MULTISESSION) <> 0 then
  585.     Include(Value, cdcReadMultisession);
  586.   if (FB and CDSTATUS_BURN_PROOF) <> 0 then
  587.     Include(Value, cdcWriteBurnProof);
  588.   FB := ModePage.Flags[3];
  589.   if (FB and CDSTATUS_CDDA_CAPABLE) <> 0 then
  590.     Include(Value, cdcCDDAread);
  591.   if (FB and CDSTATUS_CDDA_STREAM_ACCURATE) <> 0 then
  592.     Include(Value, cdcCDDAaccurate);
  593.   if (FB and CDSTATUS_CDDA_RW_SUPPORT) <> 0 then
  594.     Include(Value, cdcSubchannelRW);
  595.   if (FB and CDSTATUS_CDDA_RW_CORRECTED) <> 0 then
  596.     Include(Value, cdcSubchannelCorrect);
  597.   if (FB and CDSTATUS_CDDA_C2_POINTERS) <> 0 then
  598.     Include(Value, cdcC2Pointers);
  599.   if (FB and CDSTATUS_CDDA_ISRC) <> 0 then
  600.     Include(Value, cdcCddaISRC);
  601.   if (FB and CDSTATUS_CDDA_UPC) <> 0 then
  602.     Include(Value, cdcCddaUPC);
  603.   if (FB and CDSTATUS_CDDA_BARCODE) <> 0 then
  604.     Include(Value, cdcCddaBarCode);
  605.   FB := ModePage.Flags[4];
  606.   if (FB and CDSTATUS_LOCK_CAPABLE) <> 0 then
  607.     Include(Value, cdcLock);
  608.   if (FB and CDSTATUS_LOCK_STATE) <> 0 then
  609.     Include(Value, cdcLocked);
  610.   if (FB and CDSTATUS_PREVENT_JUMPER) <> 0 then
  611.     Include(Value, cdcLockJumper);
  612.   if (FB and CDSTATUS_EJECT_CAPABLE) <> 0 then
  613.     Include(Value, cdcEject);
  614.   FB := ModePage.Flags[5];
  615.   if (FB and CDSTATUS_SEPARATE_VOLUME) <> 0 then
  616.     Include(Value, cdcSeparateVolume);
  617.   if (FB and CDSTATUS_SEPARATE_MUTE) <> 0 then
  618.     Include(Value, cdcSeparateMute);
  619.   if (FB and CDSTATUS_REPORTS_HAVE_DISK) <> 0 then
  620.     Include(Value, cdcDiskSensor);
  621.   if (FB and CDSTATUS_SLOT_SELECTION) <> 0 then
  622.     Include(Value, cdcSlotSelect);
  623.   if (FB and CDSTATUS_SIDE_CHANGE) <> 0 then
  624.     Include(Value, cdcSideChange);
  625.   if (FB and CDSTATUS_CDDA_RW_LEAD_IN) <> 0 then
  626.     Include(Value, cdcCddaRwLeadIn);
  627. end;
  628. function SCSIinquiryEX(DeviceID: TCDBurnerInfo;
  629.   Buf: pointer; BufLen: DWORD;
  630.   CmdDt, EVPD: BOOLEAN; PageCode: BYTE;
  631.   var Sdf: TScsiDefaults): TScsiError;
  632. var
  633.   aLBA: DWORD;
  634.   cdb: Tcdb6;
  635. begin
  636.   FillChar(CDB, 6, 0);
  637.   aLBA := PageCode;
  638.   aLBA := aLBA shl 8;
  639.   if EVPD then
  640.     aLBA := aLBA or $10000;
  641.   if CmdDt then
  642.     aLBA := aLBA or $20000;
  643.   cdb[5] := 0;
  644.   FillDWORD(aLBA, cdb[0]);
  645.   cdb[4] := BufLen;
  646.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  647.   cdb[0] := SCSI_INQUIRY;
  648.   Result := ASPIsend6CDB(DeviceID, cdb, Buf, BufLen, SRB_DIR_IN, Sdf);
  649. end;
  650. function SCSIstartStopUnit(DeviceID: TCDBurnerInfo;
  651.   Start, LoadEject, DontWait: boolean;
  652.   var Sdf: TScsiDefaults): TScsiError;
  653. var
  654.   Arg1: DWORD;
  655.   Arg2: byte;
  656.   SdfTemp: DWORD;
  657.   cdb: Tcdb6;
  658. begin
  659.   FillChar(CDB, 6, 0);
  660.   Arg1 := 0;
  661.   if DontWait then
  662.     Arg1 := $10000;
  663.   Arg2 := 0;
  664.   if LoadEject then
  665.     Arg2 := 2;
  666.   if Start then
  667.     Arg2 := Arg2 or 1;
  668.   SdfTemp := Sdf.Timeout;
  669.   Sdf.Timeout := Sdf.SpindleTimeout;
  670.   cdb[5] := 0;
  671.   FillDWORD(Arg1, cdb[0]);
  672.   cdb[4] := Arg2;
  673.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  674.   cdb[0] := SCSI_START_STP;
  675.   Result := ASPIsend6CDB(deviceid, cdb, nil, 0, SRB_NODIR, Sdf);
  676.   Sdf.Timeout := SdfTemp;
  677. end;
  678. function SCSItestReady(DeviceID: TCDBurnerInfo;
  679.   var Sdf: TScsiDefaults): Boolean;
  680. var
  681.   cdb: Tcdb6;
  682.   LastError : TScsiError;
  683. begin
  684.   FillChar(CDB, 6, 0);
  685.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  686.   LastError := ASPIsend6CDB(deviceid, cdb, nil, 0, SRB_NODIR, Sdf);
  687.   Result := LastError = Err_None;
  688. end;
  689. function SCSIDeviceReadyTimeOut(DeviceID: TCDBurnerInfo; TimeOut, Step: Integer; var Sdf: TScsiDefaults): Boolean;
  690. var
  691.   TimeOutIndex: Integer;
  692. begin
  693.   result := false;
  694.   TimeOutIndex := TimeOut;
  695.   if not SCSItestReady(DeviceID,Sdf) then
  696.   begin
  697.     repeat
  698.       SleepEx(Step, False);
  699.       Dec(TimeOutIndex, Step);
  700.       if TimeOutIndex < 0 then exit;
  701.       SCSItestReady(DeviceID,Sdf);
  702.     until (TimeOutIndex < 0);
  703.   end;
  704.   result := true;
  705. end;
  706. procedure InquiryDecodePeripherals(Arg: BYTE; var PQ: TScsiPeripheralQualifier;
  707.   var DeviceType: TScsiDeviceType);
  708. begin
  709.   PQ := TScsiPeripheralQualifier((Arg shr 5) and 7);
  710.   Arg := Arg and $1F;
  711.   case Arg of
  712.     0..9: DeviceType := TScsiDeviceType(Arg);
  713.     $1F: DeviceType := TSDInvalid
  714.   else
  715.     DeviceType := TSDother;
  716.   end;
  717. end;
  718. procedure InquiryDecodeCompliance(Arg: BYTE;
  719.   var Version: TScsiStandardCompliance);
  720. begin
  721.   with Version do
  722.   begin
  723.     ISO := (Arg shr 6) and 3;
  724.     ECMA := (Arg shr 3) and 7;
  725.     ANSI := TScsiAnsiCompliance(Arg and 7);
  726.   end;
  727. end;
  728. function SCSIinquiryDeviceInfo(DeviceID: TCDBurnerInfo;
  729.   var Info: TScsiDeviceInfo; var Sdf: TScsiDefaults): TScsiError;
  730. const
  731.   BufSize = 255;
  732. var
  733.   Buf: array[0..BufSize - 1] of BYTE;
  734. begin
  735.   Result := SCSIinquiryEX(DeviceID, @Buf, SizeOf(Buf),
  736.     False, False, 0, Sdf);
  737.   with Info do
  738.   begin
  739.     //      InquiryDecodePeripherals(Buf[0], PeriphQualifier, Info.DeviceType);
  740.     Capabilities := [];
  741.     if (Buf[1] and $80) <> 0 then
  742.       Include(Capabilities, SDCremovableMedium);
  743.     InquiryDecodeCompliance(Buf[2], Version);
  744.     if (Buf[3] and $80) <> 0 then
  745.       Include(Capabilities, SDCasyncEvent);
  746.     if (Buf[3] and $20) <> 0 then
  747.       Include(Capabilities, SDCnormalACA);
  748.     if (Buf[3] and $10) <> 0 then
  749.       Include(Capabilities, SDChierarchical);
  750.     ResponseDataFormat := Buf[3] and $0F;
  751.     if (Buf[5] and $80) <> 0 then
  752.       Include(Capabilities, SDCsupportSCC);
  753.     if (Buf[6] and $80) <> 0 then
  754.       Include(Capabilities, SDCbasicQueuing);
  755.     if (Buf[6] and $40) <> 0 then
  756.       Include(Capabilities, SDCenclosure);
  757.     if (Buf[6] and $10) <> 0 then
  758.       Include(Capabilities, SDCmultiPort);
  759.     if (Buf[6] and $08) <> 0 then
  760.       Include(Capabilities, SDCmediumChanger);
  761.     if (Buf[6] and $01) <> 0 then
  762.       Include(Capabilities, SDCaddress16);
  763.     if (Buf[7] and $80) <> 0 then
  764.       Include(Capabilities, SDCrelativeAddress);
  765.     if (Buf[7] and $20) <> 0 then
  766.       Include(Capabilities, SDCwideBus16);
  767.     if (Buf[7] and $10) <> 0 then
  768.       Include(Capabilities, SDCsynchTransfer);
  769.     if (Buf[7] and $08) <> 0 then
  770.       Include(Capabilities, SDClinkedCommands);
  771.     if (Buf[7] and $04) <> 0 then
  772.       Include(Capabilities, SDCtransferDisable);
  773.     if (Buf[7] and $02) <> 0 then
  774.       Include(Capabilities, SDCcommandQueuing);
  775.     ASPIstrCopy(PChar(@Buf[8]), VendorID, 8);
  776.     ASPIstrCopy(PChar(@Buf[16]), ProductID, 16);
  777.     ASPIstrCopy(PChar(@Buf[32]), ProductRev, 4);
  778.     ASPIstrCopy(PChar(@Buf[36]), VendorSpecific, 20);
  779.   end;
  780. end;
  781. function SCSIpreventMediumRemoval(DeviceID: TCDBurnerInfo;
  782.   MustLock: boolean; var Sdf: TScsiDefaults): TScsiError;
  783. var
  784.   cdb: TCDB6;
  785. begin
  786.   FillChar(cdb, 6, 0);
  787.   cdb[0] := SCSI_MED_REMOVL; {command, No Remove}
  788.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  789.   cdb[4] := ORD(MustLock);
  790.   cdb[5] := 0;
  791.   Result := ASPIsend6CDB(DeviceID, CDB, nil, 0, SRB_NODIR, Sdf);
  792. end;
  793. function SCSIadrByteToSubQinfoFlags(Arg: BYTE): TScsiSubQinfoFlags;
  794. begin
  795.   case Arg shr 4 of
  796.     0: Result := [ssqfADRnone];
  797.     1: Result := [ssqfADRposition];
  798.     2: Result := [ssqfADRcatalogue];
  799.     3: Result := [ssqfADRISRC]
  800.   else
  801.     Result := [];
  802.   end;
  803.   if (Arg and 1) <> 0 then
  804.     Include(Result, ssqfPreEmphasis);
  805.   if (Arg and 2) <> 0 then
  806.     Include(Result, ssqfCopyPermit);
  807.   case (Arg shr 2) and 3 of
  808.     0: Include(Result, ssqfAudioTrack);
  809.     1: Include(Result, ssqfDataTrack);
  810.     2:
  811.       begin
  812.         Include(Result, ssqfAudioTrack);
  813.         Include(Result, ssqfQuadAudio);
  814.       end;
  815.   end;
  816. end;
  817. function SCSIseek10(DeviceID: TCDBurnerInfo; GLBA: DWORD; var Sdf:
  818.   TScsiDefaults): TScsiError;
  819. var
  820.   CDB: TCDB10;
  821. begin
  822.   FillChar(cdb, 10, 0);
  823.   cdb[0] := SCSI_SEEK10;
  824.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  825.   FillDWORD(GLBA, cdb[2]);
  826.   Result := ASPIsend10CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  827. end;
  828. function SCSIreadCapacity(DeviceID: TCDBurnerInfo;
  829.   var LastLBA: DWORD; var Sdf: TScsiDefaults): TScsiError;
  830. var
  831.   Buf: array[0..1] of DWORD;
  832.   CDB: TCDB10;
  833. begin
  834.   //cdr CDB:  25 00 00 00 00 00 00 00 00 00
  835.   FillChar(Buf, sizeof(Buf), 0);
  836.   FillChar(cdb, 10, 0);
  837.   cdb[0] := SCSI_RD_CAPAC;
  838.   cdb[1] := AttachLUN(cdb[1], DeviceID.DriveID);
  839.   FillWORD(SizeOf(Buf), cdb[7]);
  840.   Result := ASPIsend10CDB(DeviceID, CDB, @Buf, SizeOf(Buf), SRB_DIR_IN, Sdf);
  841.   LastLBA := BigEndianD(Buf[0]);
  842. end;
  843. function SCSIreadTocPmaAtipEx(DeviceID: TCDBurnerInfo;
  844.   InMSF: boolean;
  845.   RequestType: BYTE;
  846.   TrackNumber: BYTE;
  847.   Buf: pointer; BufLen: WORD;
  848.   var Sdf: TScsiDefaults): TScsiError;
  849. var
  850.   Byte1: BYTE;
  851.   DwLBA: DWORD;
  852.   CDB: TCDB10;
  853. begin
  854.   FillChar(cdb, 10, 0);
  855.   if InMSF then
  856.     Byte1 := 2
  857.   else
  858.     Byte1 := 0;
  859.   DwLBA := RequestType shl 24;
  860.   cdb[0] := SCSI_READ_TOC;
  861.   cdb[1] := AttachLUN(Byte1, DeviceID.DriveID);
  862.   FillDWORD(DwLBA, cdb[2]);
  863.   cdb[6] := TrackNumber;
  864.   FillWORD(BufLen, cdb[7]);
  865.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, BufLen, SRB_DIR_IN, Sdf);
  866. end;
  867. function SCSIgetTOC(DeviceID: TCDBurnerInfo; var TOC: TScsiTOC; var Sdf:
  868.   TScsiDefaults): TScsiError;
  869. var
  870.   Buf: TScsiTOCtemplate;
  871.   i: integer;
  872. begin
  873.   FillChar(TOC, SizeOf(TOC), 0);
  874.   Result := SCSIreadTocPmaAtipEx(DeviceID, False, 0, 0, @Buf, SizeOf(Buf), Sdf);
  875.   TOC.FirstTrack := Buf.FirstTrack;
  876.   TOC.LastTrack := Buf.LastTrack;
  877.   TOC.TrackCount := (BigEndianW(Buf.Length) div
  878.     SizeOf(TScsiTrackDescriptorTemplate));
  879.   for i := 0 to Toc.TrackCount - 1 do
  880.   begin
  881.     TOC.Tracks[i].Flags := SCSIadrByteToSubQinfoFlags(Buf.Tracks[i].ADR);
  882.     TOC.Tracks[i].TrackNumber := Buf.Tracks[i].TrackNumber;
  883.     TOC.Tracks[i].AbsAddress := BigEndianD(Buf.Tracks[i].AbsAddress);
  884.   end;
  885. end;
  886. function SCSIgetTOCCDText(DeviceID: TCDBurnerInfo; var TOCText: TCDText; var
  887.   Sdf: TScsiDefaults): TScsiError;
  888. begin
  889.   FillChar(TOCText, SizeOf(TOCText), 0);
  890.   Result := SCSIreadTocPmaAtipEx(DeviceID, False, $05, 0, @TOCText,
  891.     SizeOf(TOCText), Sdf);
  892. end;
  893. function SCSIgetSessionInfo(DeviceID: TCDBurnerInfo;
  894.   var Info: TScsiSessionInfo;
  895.   var Sdf: TScsiDefaults): TScsiError;
  896. var
  897.   Buf: TScsiSessionInfoTemplate;
  898. begin
  899.   FillChar(Info, SizeOf(Info), 0);
  900.   Result := SCSIreadTocPmaAtipEx(DeviceID, False, 1, 0, @Buf, SizeOf(Buf), Sdf);
  901.   Info.Flags := SCSIadrByteToSubQinfoFlags(Buf.ADR);
  902.   Info.FirstSession := Buf.FirstSession;
  903.   Info.LastSession := Buf.LastSession;
  904.   Info.FirstTrack := Buf.TrackNumber;
  905.   Info.FirstTrackLBA := BigEndianD(Buf.AbsAddress);
  906. end;
  907. {$WARNINGS OFF}
  908. function SCSIgetLayoutInfo(DeviceID: TCDBurnerInfo;
  909.   var Info: TDiscLayout;
  910.   var Sdf: TScsiDefaults): TScsiError;
  911. var
  912.   TempSessions: TScsiSessionInfo;
  913.   TempTracks: TScsiTOC;
  914.   TrackInformation, TrackInfoNext: TTrackInformation;
  915.   BlockSize, Counter: Integer;
  916.   TrackNo, SessionNo, Reminder: integer;
  917.   TrStart, TrLength, TrEnd, TrSize: Integer;
  918. begin
  919.   SCSIgetSessionInfo(DeviceID, TempSessions, SDF);
  920.   SetLength(Info.Sessions, TempSessions.LastSession + 1);
  921.   Info.FirstSession := TempSessions.FirstSession;
  922.   Info.LastSession := TempSessions.LastSession;
  923.   SCSIgetTOC(DeviceID, TempTracks, SDF);
  924.   BlockSize := ConvertDataBlock(MODE_1);
  925.   Reminder := 1;
  926.   for Counter := TempTracks.FirstTrack to TempTracks.LastTrack do
  927.   begin
  928.     SCSIReadTrackInformation(DeviceID, Counter, TrackInformation, SDF);
  929.     SessionNo := TrackInformation.SessionNumber;
  930.     if SessionNo > Reminder then
  931.     begin
  932.       Reminder := SessionNo;
  933.       TrackNo := 1;
  934.     end
  935.     else
  936.       TrackNo := Counter;
  937.     if TrackInformation.TrackMode = $00 then { Audio }
  938.     begin
  939.       BlockSize := ConvertDataBlock(RAW_DATA_BLOCK); //BLOCK_AUDIO;
  940.       Info.Sessions[SessionNo].Tracks[TrackNo].fType := BlockSize;
  941.       Info.Sessions[SessionNo].Tracks[TrackNo].fTypeStr := 'Audio';
  942.     end;
  943.     if TrackInformation.TrackMode = $04 then { Data }
  944.     begin
  945.       if TrackInformation.DataMode = $01 then { Data Mode 1 }
  946.       begin
  947.         BlockSize := ConvertDataBlock(MODE_1);
  948.         Info.Sessions[SessionNo].Tracks[TrackNo].fType := BlockSize;
  949.         Info.Sessions[SessionNo].Tracks[TrackNo].fTypeStr := 'Data (Mode 1)';
  950.       end;
  951.       if TrackInformation.DataMode = $02 then { Data Mode 2 }
  952.       begin
  953.         BlockSize := ConvertDataBlock(MODE_2);
  954.         Info.Sessions[SessionNo].Tracks[TrackNo].fType := BlockSize;
  955.         Info.Sessions[SessionNo].Tracks[TrackNo].fTypeStr := 'Data (Mode 2)';
  956.       end;
  957.     end;
  958.     TrStart := TrackInformation.TrackStartAddress;
  959.     TrLength := TrackInformation.TrackSize;
  960.     if SCSIReadTrackInformation(DeviceID, Counter + 1, TrackInfoNext, SDF) =
  961.       Err_None then
  962.       if TrackInformation.SessionNumber = TrackInfoNext.SessionNumber then
  963.         TrLength := TrackInfoNext.TrackStartAddress -
  964.           TrackInformation.TrackStartAddress;
  965.     TrEnd := TrStart + TrLength;
  966.     TrSize := LBA2MB(TrLength, BlockSize);
  967.     Info.Sessions[SessionNo].fSize := Info.Sessions[SessionNo].fSize + TrLength;
  968.     Info.Sessions[SessionNo].fSizeMB := LBA2MB(Info.Sessions[SessionNo].fSize,
  969.       BlockSize);
  970.     Info.Sessions[SessionNo].FirstTrack := 1;
  971.     Info.Sessions[SessionNo].LastTrack := TrackNo;
  972.     Info.Sessions[SessionNo].Tracks[TrackNo].StartAddress := TrStart;
  973.     Info.Sessions[SessionNo].Tracks[TrackNo].Length := TrLength;
  974.     Info.Sessions[SessionNo].Tracks[TrackNo].EndAddress := TrEnd;
  975.     Info.Sessions[SessionNo].Tracks[TrackNo].fSizeMB := TrSize;
  976.     Info.Sessions[SessionNo].Tracks[TrackNo].StartAddressStr :=
  977.       LBA2HMSF(TrStart);
  978.     Info.Sessions[SessionNo].Tracks[TrackNo].LengthStr := LBA2HMSF(TrLength);
  979.     Info.Sessions[SessionNo].Tracks[TrackNo].EndAddressStr := LBA2HMSF(TrEnd);
  980.   end; //track loop
  981. end;
  982. {$WARNINGS ON}
  983. function SCSIreadHeaderEx(DeviceID: TCDBurnerInfo;
  984.   InMSF: boolean; // Form of GLBA as result
  985.   var GLBA: DWORD; // at enter: LBA to read, at exit: address of
  986.   //   block processed, in LBA (InMSF=False) or
  987.   //   MSF (InMSF=True) form.
  988.   var SectorType: TScsiReadCdSectorType; // type of block, may
  989.   // be csfAudio, csfDataMode1, csfDataMode2,
  990.   // or csfAnyType (if error occurs) only
  991.   var Sdf: TScsiDefaults): TScsiError;
  992. var
  993.   Buf: array[0..1] of DWORD;
  994.   Byte1: BYTE;
  995.   CDB: TCDB10;
  996. begin
  997.   FillChar(Buf, sizeof(Buf), 0);
  998.   FillChar(cdb, 10, 0);
  999.   if InMSF then
  1000.     Byte1 := 2
  1001.   else
  1002.     Byte1 := 0;
  1003.   cdb[0] := SCSI_READHEADER;
  1004.   cdb[1] := AttachLUN(Byte1, DeviceID.DriveID);
  1005.   FillDWORD(GLBA, cdb[2]);
  1006.   cdb[6] := 0;
  1007.   FillWORD(SizeOf(Buf), cdb[7]);
  1008.   cdb[9] := 0;
  1009.   Result := ASPIsend10CDB(DeviceID, CDB, @Buf, SizeOf(Buf), SRB_DIR_IN, Sdf);
  1010.   case Buf[0] and $FF of
  1011.     0: SectorType := csfAudio;
  1012.     1: SectorType := csfDataMode1;
  1013.     2: SectorType := csfDataMode2
  1014.   else
  1015.     SectorType := csfAnyType;
  1016.   end;
  1017.   GLBA := BigEndianD(Buf[1]);
  1018. end;
  1019. function SCSIreadHeader(DeviceID: TCDBurnerInfo; GLBA: DWORD;
  1020.   var SectorType: TScsiReadCdSectorType; // type of block, may
  1021.   // be csfAudio, csfDataMode1, csfDataMode2,
  1022.   // or csfAnyType (if error occurs) only
  1023.   var Sdf: TScsiDefaults): TScsiError;
  1024. var
  1025.   iLBA: Cardinal;
  1026. begin
  1027.   iLBA := GLBA;
  1028.   Result := SCSIreadHeaderEx(DeviceID, False, iLBA, SectorType, Sdf);
  1029. end;
  1030. function SCSIreadSubChannelEx(DeviceID: TCDBurnerInfo;
  1031.   InMSF: boolean; // Form of resulting GLBA
  1032.   GetSubQ: boolean; // requests the Q sub-channel data if True
  1033.   RequestType: BYTE;
  1034.   TrackNumber: BYTE;
  1035.   Buf: pointer; BufLen: DWORD;
  1036.   var Sdf: TScsiDefaults): TScsiError;
  1037. var
  1038.   Byte1: BYTE;
  1039.   DwLBA: DWORD;
  1040.   CDB: TCDB10;
  1041. begin
  1042.   FillChar(Buf^, BufLen, 0);
  1043.   FillChar(cdb, 10, 0);
  1044.   if InMSF then
  1045.     Byte1 := 2
  1046.   else
  1047.     Byte1 := 0;
  1048.   DwLBA := RequestType shl 16;
  1049.   if GetSubQ then
  1050.     DwLBA := DwLBA or $40000000;
  1051.   cdb[0] := SCSI_SUBCHANNEL;
  1052.   cdb[1] := AttachLUN(Byte1, DeviceID.DriveID);
  1053.   FillDWORD(DwLBA, cdb[2]);
  1054.   cdb[6] := TrackNumber;
  1055.   FillWORD(SizeOf(Buf), cdb[7]);
  1056.   cdb[9] := 0;
  1057.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, SizeOf(Buf), SRB_DIR_IN, Sdf);
  1058. end;
  1059. {function SCSIread10EX(DeviceID: TCDBurnerInfo;
  1060.   DisablePageOut, ForceUnitAccess: boolean;
  1061.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1062.   var Sdf: TScsiDefaults): TScsiError;
  1063. var
  1064.   Arg1: byte;
  1065.   SdfTemp: DWORD;
  1066.   CDB: TCDB10;
  1067. begin
  1068.   FillChar(cdb, 10, 0);
  1069.   Arg1 := 0;
  1070.   if DisablePageOut then Arg1 := $10;
  1071.   if ForceUnitAccess then Arg1 := Arg1 or 8;
  1072.   SdfTemp := Sdf.Timeout;
  1073.   Sdf.Timeout := Sdf.ReadTimeout;
  1074.   cdb[0] := SCSI_READ10;
  1075.   cdb[1] := AttachLUN(Arg1, DeviceID.DriveID);
  1076.   FillDWORD(GLBA, cdb[2]);
  1077.   cdb[6] := 0;
  1078.   FillWORD(SectorCount, cdb[7]);
  1079.   cdb[9] := 0;
  1080.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, SizeOf(Buf), SRB_DIR_IN, Sdf);
  1081.   Sdf.Timeout := SdfTemp;
  1082. end;   }
  1083. function SCSIread10EX(DeviceID : TCDBurnerInfo;
  1084.               DisablePageOut, ForceUnitAccess : boolean;
  1085.               GLBA, SectorCount : DWORD; Buf : pointer; BufLen : DWORD;
  1086.               var Sdf : TScsiDefaults) : TScsiError;
  1087. var Arg1    : byte;
  1088.     SdfTemp : DWORD;
  1089. begin
  1090.    Arg1 := 0;
  1091.    if DisablePageOut  then Arg1 := $10;
  1092.    if ForceUnitAccess then Arg1 := Arg1 OR 8;
  1093.    SdfTemp     := Sdf.Timeout;
  1094.    Sdf.Timeout := Sdf.ReadTimeout;
  1095.    Result := ASPIsend10(DeviceID, $28, Arg1, GLBA, 0, SectorCount,
  1096.                         Buf, BufLen, SRB_DIR_IN, Sdf);
  1097.    Sdf.Timeout := SdfTemp;
  1098. end;
  1099. function SCSIread10(DeviceID: TCDBurnerInfo;
  1100.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1101.   var Sdf: TScsiDefaults): TScsiError;
  1102. begin
  1103.   Result := SCSIread10EX(DeviceID, False, False,
  1104.     GLBA, SectorCount, Buf, BufLen, Sdf);
  1105. end;
  1106. function SCSIheaderByteToAudioStatus(Arg: BYTE): TScsiAudioStatus;
  1107. begin
  1108.   case Arg and $FF of
  1109.     0: Result := sasInvalid;
  1110.     $11: Result := sasPlay;
  1111.     $12: Result := sasPause;
  1112.     $13: Result := sasCompleted;
  1113.     $14: Result := sasError;
  1114.     $15: Result := sasStop;
  1115.   else
  1116.     Result := sasUnknown;
  1117.   end;
  1118. end;
  1119. function SCSIgetISRC(DeviceID: TCDBurnerInfo; TrackNumber: BYTE;
  1120.   var Info: TScsiISRC;
  1121.   var Sdf: TScsiDefaults): TScsiError;
  1122. var
  1123.   Buf: TScsiISRCTemplate;
  1124.   SdfTemp: DWORD;
  1125. begin
  1126.   FillChar(Info, SizeOf(Info), 0);
  1127.   SdfTemp := Sdf.Timeout;
  1128.   Sdf.Timeout := Sdf.ReadTimeout;
  1129.   Result := SCSIreadSubChannelEx(DeviceID, False, True, 3, TrackNumber,
  1130.     @Buf, SizeOf(Buf), Sdf);
  1131.   Sdf.Timeout := SdfTemp;
  1132.   Info.Status := SCSIheaderByteToAudioStatus(Buf.sitStatus);
  1133.   Info.Flags := SCSIadrByteToSubQinfoFlags(Buf.sitADR);
  1134.   if (Buf.sitValid and $80) <> 0 then
  1135.   begin // MCN is valid
  1136.     ASPIstrCopy(@Buf.sitNumber[0], Info.IsrcNumber, 12);
  1137.     Info.FrameNumber := Buf.sitAFrame;
  1138.   end;
  1139. end;
  1140. function SCSIreadCdFlagsToByte9(Flags: TScsiReadCdFormatFlags): BYTE;
  1141. begin
  1142.   Result := 0;
  1143.   if cffSync in Flags then
  1144.     Result := Result or $80;
  1145.   if cffSubheader in Flags then
  1146.     Result := Result or $40;
  1147.   if cffHeader in Flags then
  1148.     Result := Result or $20;
  1149.   if cffUserData in Flags then
  1150.     Result := Result or $10;
  1151.   if cffEDCandECC in Flags then
  1152.     Result := Result or 8;
  1153.   if cffC2errorBits in Flags then
  1154.   begin
  1155.     if cffBlockErrByte in Flags then
  1156.       Result := Result or 4
  1157.     else
  1158.       Result := Result or 2;
  1159.   end;
  1160. end;
  1161. function SCSIreadCdFlagsToSize(SectorType: TScsiReadCdSectorType;
  1162.   Flags: TScsiReadCdFormatFlags): integer;
  1163. const
  1164.   SectorSize: array[0..31, 0..3] of integer =
  1165.   ((-1, -1, -1, -1), (-1, -1, -1, -1), (2048, 2336, 2048, 2328), (2336, 2336,
  1166.     2328, 2328),
  1167.     (4, 4, 4, 4), (-1, -1, -1, -1), (2052, 2340, -1, -1), (2340, 2340, -1, -1),
  1168.     (0, 0, 8, 8), (-1, -1, -1, -1), (2048, 2336, 2056, 2336), (2336, 2336, 2336,
  1169.     2336),
  1170.     (4, 4, 12, 12), (-1, -1, -1, -1), (2052, 2340, 2060, 2340), (2340, 2340,
  1171.     2340, 2340),
  1172.     (-1, -1, -1, -1), (-1, -1, -1, -1), (-1, -1, -1, -1), (-1, -1, -1, -1),
  1173.     (16, 16, 16, 16), (-1, -1, -1, -1), (2064, 2352, -1, -1), (2352, 2352, -1,
  1174.     -1),
  1175.     (-1, -1, -1, -1), (-1, -1, -1, -1), (-1, -1, -1, -1), (-1, -1, -1, -1),
  1176.     (16, 16, 24, 24), (-1, -1, -1, -1), (2064, 2352, 2072, 2352), (2352, 2352,
  1177.     2352, 2352));
  1178. begin
  1179.   if SectorType in [csfAnyType, csfAudio] then
  1180.     Result := 2352
  1181.   else
  1182.     Result :=
  1183.       SectorSize[SCSIreadCdFlagsToByte9(Flags) shr 3, ORD(SectorType) - 2];
  1184.   if Result = -1 then
  1185.     exit;
  1186.   if cffC2errorBits in Flags then
  1187.   begin
  1188.     Inc(Result, 294);
  1189.     if cffBlockErrByte in Flags then
  1190.       Inc(Result, 2);
  1191.   end;
  1192.   if cffSubchannelQ in Flags then
  1193.   begin
  1194.     if (cffSubchannelRaw in Flags) or (cffSubchannelPW in Flags) then
  1195.       Result := -1
  1196.     else
  1197.       Inc(Result, 16);
  1198.   end
  1199.   else
  1200.   begin
  1201.     if cffSubchannelRaw in Flags then
  1202.     begin
  1203.       if cffSubchannelPW in Flags then
  1204.         Result := -1
  1205.       else
  1206.         Inc(Result, 96);
  1207.     end
  1208.     else if cffSubchannelPW in Flags then
  1209.       Inc(Result, 96);
  1210.   end;
  1211. end;
  1212. {$WARNINGS OFF}
  1213. function SCSIWriteCdEX(DeviceID: TCDBurnerInfo;
  1214.   GLBA, SectorCount: DWORD;
  1215.   SectorType: TScsiReadCdSectorType;
  1216.   Flags: TScsiReadCdFormatFlags;
  1217.   Buf: pointer; BufLen: DWORD;
  1218.   var Sdf: TScsiDefaults): TScsiError;
  1219. var
  1220.   CDB: TCDB12;
  1221.   dummy: byte;
  1222.   i: integer;
  1223.   SdfTemp: DWORD;
  1224. begin
  1225.   FillChar(cdb, 12, 0);
  1226.   cdb[9] := SCSIreadCdFlagsToByte9(Flags);
  1227.   i := SCSIreadCdFlagsToSize(SectorType, Flags);
  1228.   if (i <= 0) or (SectorCount <= 0)
  1229.     or (BufLen < (SectorCount * i))
  1230.     or not Assigned(Buf) then
  1231.   begin
  1232.     Result := Err_InvalidArgument;
  1233.     exit;
  1234.   end;
  1235.   FillChar(Buf^, BufLen, 0);
  1236.   cdb[0] := $BE;
  1237.   cdb[1] := ORD(SectorType) shl 2;
  1238.   ScatterDWORD(GLBA, cdb[2], cdb[3], cdb[4], cdb[5]);
  1239.   ScatterDWORD(SectorCount, dummy, cdb[6], cdb[7], cdb[8]);
  1240.   if cffSubchannelRaw in Flags then
  1241.     cdb[10] := 1
  1242.   else if cffSubchannelQ in Flags then
  1243.     cdb[10] := 2
  1244.   else if cffSubchannelPW in Flags then
  1245.     cdb[10] := 4
  1246.   else
  1247.     cdb[10] := 0;
  1248.   cdb[11] := 0;
  1249.   SdfTemp := Sdf.Timeout;
  1250.   Sdf.Timeout := Sdf.ReadTimeout;
  1251.   //Result := ASPIsend12CDB(DeviceID, CDB, @Buf, SizeOf(Buf), SRB_DIR_OUT, Sdf);
  1252.   Result := ASPIsend12CDB(DeviceID, CDB, Buf, SizeOf(Buf), SRB_DIR_OUT, Sdf);
  1253.   Sdf.Timeout := SdfTemp;
  1254. end;
  1255. {$WARNINGS ON}
  1256. {$WARNINGS OFF}
  1257. function SCSIreadCdEX(DeviceID: TCDBurnerInfo;
  1258.   GLBA, SectorCount: DWORD;
  1259.   SectorType: TScsiReadCdSectorType;
  1260.   Flags: TScsiReadCdFormatFlags;
  1261.   Buf: pointer; BufLen: DWORD;
  1262.   var Sdf: TScsiDefaults): TScsiError;
  1263. var
  1264.   CDB: TCDB12;
  1265.   dummy: byte;
  1266.   i: integer;
  1267.   SdfTemp: DWORD;
  1268. begin
  1269.   FillChar(cdb, 12, 0);
  1270.   cdb[9] := SCSIreadCdFlagsToByte9(Flags);
  1271.   i := SCSIreadCdFlagsToSize(SectorType, Flags);
  1272.   if (i <= 0) or (SectorCount <= 0)
  1273.     or (BufLen < (SectorCount * i))
  1274.     or not Assigned(Buf) then
  1275.   begin
  1276.     Result := Err_InvalidArgument;
  1277.     exit;
  1278.   end;
  1279.   FillChar(Buf^, BufLen, 0);
  1280.   cdb[0] := $BE;
  1281.   cdb[1] := ORD(SectorType) shl 2;
  1282.   ScatterDWORD(GLBA, cdb[2], cdb[3], cdb[4], cdb[5]);
  1283.   ScatterDWORD(SectorCount, dummy, cdb[6], cdb[7], cdb[8]);
  1284.   if cffSubchannelRaw in Flags then
  1285.     cdb[10] := 1
  1286.   else if cffSubchannelQ in Flags then
  1287.     cdb[10] := 2
  1288.   else if cffSubchannelPW in Flags then
  1289.     cdb[10] := 4
  1290.   else
  1291.     cdb[10] := 0;
  1292.   cdb[11] := 0;
  1293.   SdfTemp := Sdf.Timeout;
  1294.   Sdf.Timeout := Sdf.ReadTimeout;
  1295.   Result := ASPIsend12CDB(DeviceID, CDB, Buf, BufLen, SRB_DIR_IN, Sdf);
  1296.   Sdf.Timeout := SdfTemp;
  1297. end;
  1298. {$WARNINGS ON}
  1299. //+++++++++++++++++++++++++ writing functions +++++++++++++++++++++++++
  1300. {
  1301. function SCSISetWriteParameters(DevID: TCDBurnerInfo; Size: Integer;
  1302.   Write_Type, Data_Block_type, Track_Mode, Session_Format: integer;
  1303.   Packet_Size, Audio_Pause_Length: integer; Test_Write, Burn_Proof: Boolean;
  1304.   var Sdf: TScsiDefaults): TScsiError;
  1305. var
  1306.   Buf: TScsiWriteModePage;
  1307.   bufsize: DWord;
  1308. begin
  1309.   BufSize := sizeof(Buf);
  1310.   //get current params
  1311.   Result := SCSImodeSensePage(DevID, $05, @Buf, BufSize, 0, Sdf);
  1312.   //reset params to new settings
  1313.   Sdf.ModePageType := MPTchangeable;
  1314.   if Result <> Err_None then
  1315.     exit;
  1316.   Buf.PSPageCode := $05;
  1317.   Buf.PageLength := $32; //$32;
  1318.   Buf.TestFlagWriteType := Write_Type; //Write_Type;
  1319.   if Test_Write = True then
  1320.     Buf.TestFlagWriteType := BitOn(Buf.TestFlagWriteType, 4)
  1321.   else if IsBitSet(Buf.TestFlagWriteType, 4) then
  1322.     BitOFF(Buf.TestFlagWriteType, 4);
  1323.   if Burn_Proof = True then
  1324.     Buf.TestFlagWriteType := BitOn(Buf.TestFlagWriteType, 6)
  1325.   else if IsBitSet(Buf.TestFlagWriteType, 6) then
  1326.     BitOFF(Buf.TestFlagWriteType, 6);
  1327.   Buf.MSFPCopyTrackMode := Track_Mode;
  1328.   if Write_Type = $42 then Buf.Reserved1 := $10;
  1329.   Buf.DataBlockType := Data_Block_type;
  1330.   Buf.HostApplicationCode := 0;
  1331.   Buf.SessionFormat := Session_Format;
  1332.   Buf.PacketSize := Packet_Size;
  1333.   Buf.AudioPauseLength := SwapWord(Audio_Pause_Length);
  1334.   FillChar(Buf.MediaCatalogNumber, Sizeof(Buf.MediaCatalogNumber), 0);
  1335.   FillChar(Buf.InternationalStandardRecordingCode,
  1336.     SizeOf(Buf.InternationalStandardRecordingCode), 0);
  1337.   FillChar(Buf.SubHeader, Sizeof(Buf.SubHeader), 0);
  1338.   //Reset to new parameters
  1339.   Result := SCSImodeSelectPage(DevID, $05, @Buf, BufSize, 0, sdf);
  1340. end;  }
  1341. function SCSISetWriteParameters(DevID: TCDBurnerInfo; Size: Integer; BurnSettings: TBurnSettings;
  1342.   var Sdf: TScsiDefaults): TScsiError;
  1343. var
  1344.   Buf: TScsiWriteModePage;
  1345.   bufsize: DWord;
  1346. begin
  1347.   BufSize := sizeof(Buf);
  1348.   Result := SCSImodeSensePage(DevID, $05, @Buf, BufSize, 0, Sdf); //get current params
  1349.   Sdf.ModePageType := MPTchangeable; //reset params to new settings
  1350.   if Result <> Err_None then exit;
  1351.   Buf.PSPageCode := $05;
  1352.   Buf.PageLength := $32;
  1353.   Buf.TestFlagWriteType := wtTRACK_AT_ONCE;         //set standard Write_Type TAO;
  1354.   Buf.DataBlockType := btMODE_1;                    //set standard DATA BLOCK MODE1;
  1355.   Buf.MSFPCopyTrackMode := tmCDR_MODE_DATA;         //set standard Track Mode CD Data;
  1356.   if (BurnSettings.MediaType.MediaType = mtDVD_PLUSR) then  //check for dvd plus
  1357.     begin
  1358.       Buf.TestFlagWriteType := wtDVDPLUS_TAO;
  1359.     end;
  1360.   if (BurnSettings.MultiSession = True) then     // Check For MultiSession
  1361.     begin
  1362.       Buf.TestFlagWriteType := wtSESSION_AT_ONCE;
  1363.       Buf.DataBlockType := btRAW_DATA_BLOCK;
  1364.     end;
  1365.   Buf.MSFPCopyTrackMode := BurnSettings.TrackMode;  //Set Track Mode;
  1366.   if (BurnSettings.SpecialDeviceType.SonyPowerBurn = True) then  // Sony Power Burn
  1367.       Buf.TestFlagWriteType := Buf.TestFlagWriteType or $20;
  1368.   if not BurnSettings.TestWrite then
  1369.     begin
  1370.       if not BurnSettings.CloseDisk then
  1371.         Buf.MSFPCopyTrackMode := Buf.MSFPCopyTrackMode or $C0
  1372.       else
  1373.         if Buf.MSFPCopyTrackMode and $C0 = $C0 then Buf.MSFPCopyTrackMode := Buf.MSFPCopyTrackMode - $C0;
  1374.     end //testwrite
  1375.     else
  1376.     begin
  1377.       if Buf.MSFPCopyTrackMode and $C0 = $C0 then Buf.MSFPCopyTrackMode := Buf.MSFPCopyTrackMode - $C0;
  1378.     end;
  1379.     if (BurnSettings.BurnProof = True) then
  1380.       Buf.TestFlagWriteType := Buf.TestFlagWriteType or $40
  1381.     else
  1382.       if Buf.TestFlagWriteType and $40 = $40 then Buf.TestFlagWriteType := Buf.TestFlagWriteType - $40;
  1383.     if (BurnSettings.MediaType.MediaType = mtDVD_R) or
  1384.          (BurnSettings.MediaType.MediaType = mtDVD_RW_RO) or
  1385.               (BurnSettings.MediaType.MediaType = mtDVD_RW_SR) then
  1386.     begin
  1387.       Buf.MSFPCopyTrackMode := tmDVD_MODE_DATA;
  1388.       Buf.TestFlagWriteType := wtDVD_TAO;
  1389.       if not (BurnSettings.BurnProof) then
  1390.           Buf.TestFlagWriteType := Buf.TestFlagWriteType - $40;
  1391.       Buf.DataBlockType := btMODE_1;
  1392.       Buf.Reserved1 := $10;
  1393.     end;
  1394.     if (BurnSettings.TestWrite = True) then
  1395.       Buf.TestFlagWriteType := Buf.TestFlagWriteType or $10
  1396.     else
  1397.       if Buf.TestFlagWriteType and $10 = $10 then Buf.TestFlagWriteType := Buf.TestFlagWriteType - $10;
  1398.   if (BurnSettings.MediaType.MediaType = mtDVD_PLUSR) then Buf.Reserved1 := $10;
  1399.   Buf.HostApplicationCode := 0;
  1400.   Buf.SessionFormat := BurnSettings.SessionType;
  1401.   Buf.PacketSize := BurnSettings.PacketSize;
  1402.   Buf.AudioPauseLength := SwapWord(BurnSettings.AudioPause);
  1403.   FillChar(Buf.MediaCatalogNumber, Sizeof(Buf.MediaCatalogNumber), 0);
  1404.   FillChar(Buf.InternationalStandardRecordingCode,
  1405.     SizeOf(Buf.InternationalStandardRecordingCode), 0);
  1406.   FillChar(Buf.SubHeader, Sizeof(Buf.SubHeader), 0); 
  1407.   Result := SCSImodeSelectPage(DevID, $05, @Buf, BufSize, 0, sdf);  //Reset to new parameters
  1408. end;
  1409. function SCSISetStreamingMode(DeviceID: TCDBurnerInfo;var Sdf: TScsiDefaults): TScsiError;
  1410. var
  1411.   CDB: TCDB12;
  1412.   Buffer : PChar;
  1413.   BufLen : Integer;
  1414. begin
  1415.   fillchar(CDB, sizeof(CDB), 0);
  1416.   Buffer := #$00#$00#$00#$00#$00#$00#$00#$00#$00#$23#$12#$7F#$00#$00#$AB#$BD#$00#$00#$03#$E8#$00#$00#$05#$8A#$00#$00#$03#$E8;
  1417.   BufLen := 28;
  1418.   cdb[0] := $B6;
  1419.   ConvertEndians(BufLen, cdb[9], 2);
  1420.   Result := ASPIsend12CDB(DeviceID, CDB, Buffer, BufLen, SRB_DIR_OUT, Sdf);
  1421. end;
  1422. function SCSISendDVDStructure(DeviceID: TCDBurnerInfo;
  1423.         Format: Byte; Buf: Pointer; BufLength: Word; var Sdf: TScsiDefaults): TScsiError;
  1424. var
  1425.   CDB: TCDB12;
  1426. begin
  1427.   fillchar(CDB, sizeof(CDB), 0);
  1428.   cdb[0] := $BF;
  1429.   cdb[7] := Format;
  1430.   ConvertEndians(BufLength, cdb[8], 2);
  1431.   Result := ASPIsend12CDB(DeviceID, CDB, Buf, BufLength, SRB_DIR_OUT, Sdf);
  1432. end;
  1433. function SCSISendDVDStructureTimeStamp(DeviceID: TCDBurnerInfo;
  1434.               Time: TDateTime; var Sdf: TScsiDefaults): TScsiError;
  1435. var
  1436.   str, Pre: String;
  1437.   Buffer : Array [1..30] of Char;
  1438. begin
  1439.   Pre := #$00+#$14+#$00+#$00+#$00+#$00+#$00+#$00;
  1440.   str := formatDateTime('yyyymmddhhnnss', Time);
  1441.   Pre := Pre + str;
  1442.   move(Pre[1], Buffer, Length(Pre));
  1443.   result := SCSISendDVDStructure(DeviceID, $0F, @Buffer, $16, Sdf);
  1444. end;
  1445. function SCSIReserveTrack(DeviceID: TCDBurnerInfo;
  1446.        ReserveSize: Cardinal; var Sdf: TScsiDefaults): TScsiError;
  1447. var
  1448.   CDB: TCDB10;
  1449.   Buffer : array[1..8] of Byte;
  1450. begin
  1451.   fillchar(CDB, sizeof(CDB), 0);
  1452.   cdb[0] := $53;
  1453.   FillDWORD(ReserveSize, cdb[5]);
  1454.   Result := ASPIsend10CDB(DeviceID, CDB, @Buffer, 8, SRB_DIR_OUT, Sdf);
  1455. end;
  1456. function SCSIWrite10EX(DeviceID: TCDBurnerInfo;
  1457.   DisablePageOut, ForceUnitAccess: boolean;
  1458.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1459.   var Sdf: TScsiDefaults): TScsiError;
  1460. var
  1461.   Arg1: byte;
  1462.   SdfTemp: DWORD;
  1463.   CDB: TCDB10;
  1464. begin
  1465.   //cdr CDB:  2A 00 00 00 00 00 00 00 1F 00
  1466.   FillChar(cdb, 10, 0);
  1467.   Arg1 := 0;
  1468.   if DisablePageOut then Arg1 := $10;
  1469.   if ForceUnitAccess then Arg1 := Arg1 or 8;
  1470.   
  1471.   SdfTemp := Sdf.Timeout;
  1472.   Sdf.Timeout := Sdf.ReadTimeout;
  1473.   cdb[0] := SCSI_WRITE10;
  1474.   cdb[1] := AttachLUN(Arg1, DeviceID.DriveID);
  1475.   FillDWORD(GLBA, cdb[2]);
  1476.   cdb[7] := HiByte(SectorCount);
  1477.   cdb[8] := LoByte(SectorCount);
  1478.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, BufLen, SRB_DIR_OUT, Sdf);
  1479.   Sdf.Timeout := SdfTemp;
  1480. end;
  1481. function SCSIWrite10(DeviceID: TCDBurnerInfo;
  1482.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1483.   var Sdf: TScsiDefaults): TScsiError;
  1484. begin
  1485.   Result := SCSIWrite10EX(DeviceID, False, False,
  1486.     GLBA, SectorCount, Buf, BufLen, Sdf);
  1487. end;
  1488. function SCSIWrite12EX(DeviceID: TCDBurnerInfo;
  1489.   DisablePageOut, ForceUnitAccess: boolean;
  1490.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1491.   var Sdf: TScsiDefaults): TScsiError;
  1492. var
  1493.   Arg1: byte;
  1494.   SdfTemp: DWORD;
  1495.   CDB: TCDB12;
  1496. begin
  1497.   FillChar(cdb, 12, 0);
  1498.   Arg1 := 0;
  1499.   if DisablePageOut then
  1500.     Arg1 := $10;
  1501.   if ForceUnitAccess then
  1502.     Arg1 := Arg1 or 8;
  1503.   SdfTemp := Sdf.Timeout;
  1504.   Sdf.Timeout := Sdf.ReadTimeout;
  1505.   cdb[0] := SCSI_WRITE12;
  1506.   cdb[1] := AttachLUN(Arg1, DeviceID.DriveID);
  1507.   FillDWORD(GLBA, cdb[2]);
  1508.   cdb[6] := (SectorCount shr 24) and $FF;
  1509.   cdb[7] := (SectorCount shr 16) and $FF;
  1510.   cdb[8] := (SectorCount shr 8) and $FF;
  1511.   cdb[9] :=  SectorCount and $FF;
  1512.   Result := ASPIsend12CDB(DeviceID, CDB, Buf, BufLen, SRB_DIR_OUT, Sdf);
  1513.   Sdf.Timeout := SdfTemp;
  1514. end;
  1515. function SCSIWrite12(DeviceID: TCDBurnerInfo;
  1516.   GLBA, SectorCount: DWORD; Buf: pointer; BufLen: DWORD;
  1517.   var Sdf: TScsiDefaults): TScsiError;
  1518. begin
  1519.   Result := SCSIWrite12EX(DeviceID, False, False,
  1520.     GLBA, SectorCount, Buf, BufLen, Sdf);
  1521. end;
  1522. function SCSIWriteCDDA(DeviceID: TCDBurnerInfo;
  1523.   GLBA, SectorCount: DWORD;
  1524.   SectorType: TScsiReadCdSectorType;
  1525.   Flags: TScsiReadCdFormatFlags;
  1526.   Buf: pointer; BufLen: DWORD;
  1527.   var Sdf: TScsiDefaults): TScsiError;
  1528. var
  1529.   SdfTemp: DWORD;
  1530. begin
  1531.   SdfTemp := Sdf.Timeout;
  1532.   Sdf.Timeout := Sdf.ReadTimeout;
  1533.   Result := SCSIWrite10EX(DeviceID, False, False,
  1534.     GLBA, SectorCount, Buf, BufLen, Sdf);
  1535.   Sdf.Timeout := SdfTemp;
  1536. end;
  1537. function SCSIBlankCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
  1538.   var Sdf: TScsiDefaults): TScsiError;
  1539. var
  1540.   cdb: TCDB6;
  1541.   m_lba: longint;
  1542. begin
  1543.   m_lba := LBA;
  1544.   FillChar(cdb, 6, 0);
  1545.   cdb[0] := AC_BLANK; {command, Blank}
  1546.   cdb[1] := BlankType; {blanktype}
  1547.   cdb[2] := (m_lba shr 24) and $FF;
  1548.   cdb[3] := (m_lba shr 16) and $FF;
  1549.   cdb[4] := (m_lba shr 8) and $FF;
  1550.   cdb[5] := m_lba and $FF;
  1551.   Result := ASPIsend6CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  1552. end;
  1553. function SCSIReadBuffer(DeviceID: TCDBurnerInfo;
  1554.   Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
  1555. var
  1556.   CDB: TCDB10;
  1557. begin
  1558.   FillChar(cdb, 10, 0);
  1559.   cdb[0] := SCSI_READ_BUFF;
  1560.   cdb[1] := $00;
  1561.   cdb[2] := $00;
  1562.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, SizeOf(Buf), SRB_DIR_IN, Sdf);
  1563. end;
  1564. function SCSIReadBufferCapacity(DeviceID: TCDBurnerInfo;
  1565.   Buf: pointer; var Sdf: TScsiDefaults): TScsiError;
  1566. var
  1567.   CDB: TCDB10;
  1568. begin
  1569.   FillChar(cdb, 10, 0);
  1570.   cdb[0] := SCSI_READ_BUFFER_CAP;
  1571.   cdb[8] := SizeOf(TScsiCDBufferInfo);
  1572.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, SizeOf(TScsiCDBufferInfo),
  1573.     SRB_DIR_IN, Sdf);
  1574. end;
  1575. function SCSIgetMaxBufferSize(DeviceID: TCDBurnerInfo;
  1576.   var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
  1577. begin
  1578.   Result := SCSIReadBufferCapacity(DeviceID, @Value, Sdf);
  1579. end;
  1580. function SCSIgetBufferCapacity(DeviceID: TCDBurnerInfo;
  1581.   var Value: TScsiCDBufferInfo; var Sdf: TScsiDefaults): TScsiError;
  1582. begin
  1583.   Result := SCSIReadBufferCapacity(DeviceID, @Value, sdf);
  1584. end;
  1585. function SCSIgetBufferSize(DeviceID: TCDBurnerInfo;
  1586.   var Value: WORD; var Sdf: TScsiDefaults): TScsiError;
  1587. begin
  1588.   Result := SCSIReadBuffer(DeviceID, @Value, Sdf);
  1589. end;
  1590. function SCSICloseSession(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
  1591.   TScsiError;
  1592. var
  1593.   cdb: TCDB6;
  1594. begin
  1595.   FillChar(cdb, 6, 0);
  1596.   cdb[0] := AC_CLOSETRACKSESSION; {command}
  1597.   cdb[1] := $01;
  1598.   cdb[2] := CLOSE_SESSION;
  1599.   Result := ASPIsend6CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  1600. end;
  1601. function SCSICloseTrack(DeviceID: TCDBurnerInfo; Track: byte;
  1602.   var Sdf: TScsiDefaults): TScsiError;
  1603. var
  1604.   cdb: TCDB6;
  1605. begin
  1606.   FillChar(cdb, 6, 0);
  1607.   cdb[0] := AC_CLOSETRACKSESSION; {command}
  1608.   cdb[1] := $01;
  1609.   cdb[2] := CLOSE_TRACK;
  1610.   cdb[5] := Track;
  1611.   Result := ASPIsend6CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  1612. end;
  1613. function SCSISYNCCACHE(DeviceID: TCDBurnerInfo; var Sdf: TScsiDefaults):
  1614.   TScsiError;
  1615. var
  1616.   cdb: TCDB10;
  1617. begin
  1618.   FillChar(cdb, 10, 0);
  1619.   cdb[0] := SCSI_SYNC_CACHE; {command}
  1620.   cdb[1] := $01;
  1621.   Result := ASPIsend10CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  1622. end;
  1623. function SCSIGetFormatCapacity(DeviceID: TCDBurnerInfo; var Capacity: Cardinal;
  1624.     var SectorSize: Cardinal; var Sdf: TScsiDefaults):TScsiError;
  1625. var
  1626.   cdb: TCDB10;
  1627.   Index : Integer;
  1628.   FormatCapacity: TFormatCapacity;
  1629. begin
  1630.   FillChar(cdb, 10, 0);
  1631.   fillchar(FormatCapacity, sizeof(FormatCapacity), 0);
  1632.   cdb[0] := SCSI_GET_FORMAT_CAPACITY; {command}
  1633.   cdb[1] := $01;
  1634.   cdb[8] := 248;
  1635.   Result := ASPIsend10CDB(DeviceID, CDB, @FormatCapacity, 248, SRB_DIR_IN, Sdf);
  1636.   for Index := 0 to 32 do
  1637.   begin
  1638.     FormatCapacity.FormattableCD[Index].NumberOfBlocks := SwapDWord(FormatCapacity.FormattableCD[Index].NumberOfBlocks);
  1639.     FormatCapacity.FormattableCD[Index].FormatType := FormatCapacity.FormattableCD[Index].FormatType shr 2;
  1640.   end;
  1641.   
  1642.   if Result = Err_None then
  1643.   begin
  1644.      SectorSize := SwapDWord(FormatCapacity.CapacityDescriptor.DescriptorType);
  1645.      Capacity := SwapDWord(FormatCapacity.CapacityDescriptor.NumberOfBlocks);
  1646.   end;
  1647. end;
  1648. function SCSIFormatCD(DeviceID: TCDBurnerInfo; BlankType: byte; LBA: longint;
  1649.   var Sdf: TScsiDefaults): TScsiError;
  1650. var
  1651.   cdb: TCDB6;
  1652.   m_lba: longint;
  1653. begin
  1654.   m_lba := LBA;
  1655.   FillChar(cdb, 6, 0);
  1656.   cdb[0] := SCSI_FORMAT; {command}
  1657.   cdb[1] := BlankType; {blanktype}
  1658.   cdb[2] := (m_lba shr 24) and $FF;
  1659.   cdb[3] := (m_lba shr 16) and $FF;
  1660.   cdb[4] := (m_lba shr 8) and $FF;
  1661.   cdb[5] := m_lba and $FF;
  1662.   Result := ASPIsend6CDB(DeviceID, CDB, nil, 0, SRB_DIR_IN, Sdf);
  1663. end;
  1664. function SCSISendCUESheet(DeviceID: TCDBurnerInfo;
  1665.   Buf: pointer; BufSize : Longint; var Sdf: TScsiDefaults): TScsiError;
  1666. var
  1667.   CDB: TCDB10;
  1668. begin
  1669.   FillChar(cdb, 10, 0);
  1670.   cdb[0] := SCSI_SEND_CUE_SHEET;
  1671.   //cdb[6] := (BufSize shr 16) and $FF;
  1672.   cdb[7] := HiByte(BufSize);
  1673.   cdb[8] := LoByte(BufSize);
  1674.   Result := ASPIsend10CDB(DeviceID, CDB, Buf, BufSize, SRB_DIR_IN, Sdf);
  1675. end;
  1676. function SCSISetSpeed(DevID: TCDBurnerInfo; ReadSpeed, WriteSpeed: Integer;
  1677.   var Sdf: TScsiDefaults): TScsiError;
  1678. var
  1679.   cdb: TCDB12;
  1680.   Lun: Byte;
  1681. begin
  1682.   //cdr CDB:  BB 00 FF FF 08 4C 00 00 00 00 00 00
  1683.   Lun := 0;
  1684.   FillChar(cdb, 12, 0);
  1685.   cdb[0] := AC_SETCDSPEED; {command }
  1686.   cdb[1] := AttachLUN(Lun, DevID.DriveID);
  1687.   cdb[2] := (ReadSpeed shr 8);
  1688.   cdb[3] := ReadSpeed;
  1689.   cdb[4] := (WriteSpeed shr 8);
  1690.   cdb[5] := WriteSpeed;
  1691.   Result := ASPIsend12CDB(Devid, CDB, nil, 0, SRB_DIR_OUT, Sdf);
  1692. end;
  1693. function ScsiGetWriteParams(DevID: TCDBurnerInfo; Size: Integer; var Param:
  1694.   string;
  1695.   var Sdf: TScsiDefaults): TScsiError;
  1696. var
  1697.   ModePage: TScsiWriteModePage;
  1698.   BufSize: DWord;
  1699. begin
  1700.   BufSize := sizeof(ModePage);
  1701.   fillchar(ModePage, Bufsize, 0);
  1702.   {get current params}
  1703.   Sdf.ModePageType := MPTcurrent;
  1704.   Result := SCSImodeSensePage(DevID, $05, @ModePage, BufSize, 0, Sdf);
  1705.   Param := 'Get CD/DVD Writer Parameters : Failed';
  1706.   if Result <> Err_None then
  1707.     exit;
  1708.   Param := 'Test Write :  ';
  1709.   if IsBitSet(ModePage.TestFlagWriteType, 4) = true then
  1710.     Param := Param + 'Test Write is ON' + #10#13
  1711.   else
  1712.     Param := Param + 'Test Write is OFF' + #10#13;
  1713.   Param := Param + 'Buffer Underrun :  ';
  1714.   if IsBitSet(ModePage.TestFlagWriteType, 6) = true then
  1715.     Param := Param + 'BurnProof is ON' + #10#13
  1716.   else
  1717.     Param := Param + 'BurnProof is OFF' + #10#13;
  1718.   Param := Param + 'Write Type :  ';
  1719.   case (ModePage.TestFlagWriteType and $0F) of
  1720.     0: Param := Param + 'Packet/Incremental' + #10#13;
  1721.     1: Param := Param + 'Track At Once (TAO)' + #10#13;
  1722.     2: Param := Param + 'Session At Once (SAO)' + #10#13;
  1723.     3: Param := Param + 'Raw Data Burn' + #10#13;
  1724.   else
  1725.     Param := Param + 'Unknown Write Mode' + #10#13;
  1726.   end; //Case
  1727.   Param := Param + 'Multisession :  ';
  1728.   case (ModePage.MSFPCopyTrackMode shr 6) of
  1729.     3: Param := Param + 'Next Session Allowed / ON' + #10#13;
  1730.   else
  1731.     Param := Param + 'Next Session Not Allowed / OFF' + #10#13;
  1732.   end; //Case
  1733.   Param := Param + 'Packet Type :  ';
  1734.   case (ModePage.MSFPCopyTrackMode and $20) of
  1735.     1: Param := Param + 'Fixed Size Packets' + #10#13;
  1736.   else
  1737.     Param := Param + 'Variable Size Packets' + #10#13;
  1738.   end; //Case
  1739.   Param := Param + 'Packet Size :  ' + inttostr(ModePage.PacketSize) + #10#13;
  1740.   Param := Param + 'Session Type :  ';
  1741.   case (ModePage.SessionFormat) of
  1742.     $00: Param := Param + 'CD-DA or CDROM Disk' + #10#13;
  1743.     $01: Param := Param + 'CDI Video Disk' + #10#13;
  1744.     $32: Param := Param + 'CDROM XA Disk' + #10#13;
  1745.   else
  1746.     Param := Param + 'Unknown Session Mode' + #10#13;
  1747.   end; //Case
  1748.   Param := Param + 'Audio Pause Length :  ' +
  1749.     inttostr(SwapWord(ModePage.AudioPauseLength)) + #10#13;
  1750.   Param := Param + 'Data Block :  ' + inttostr(ModePage.DataBlockType) + #10#13;
  1751. end;
  1752. //+++++++++++++++++++++++++ End writing functions +++++++++++++++++++++++++
  1753. //New Added DVD Functions
  1754. function SCSIGetDevConfigProfileMedia(DeviceID: TCDBurnerInfo; var
  1755.   ProfileDevDiscType: TScsiProfileDeviceDiscTypes; var Sdf: TScsiDefaults):
  1756.   TScsiError;
  1757. var
  1758.   cdb: array[0..9] of BYTE;
  1759.   Buf: Pointer;
  1760.   BufLen, CdbLen, SdfTemp: DWORD;
  1761.   DeviceConfigHeader: TScsiDeviceConfigHeader;
  1762. begin
  1763.   ZeroMemory(@DeviceConfigHeader, SizeOf(DeviceConfigHeader));
  1764.   Buf := @DeviceConfigHeader;
  1765.   BufLen := SizeOf(DeviceConfigHeader);
  1766.   cdbLen := DWORD(10);
  1767.   cdb[0] := $46;
  1768.   cdb[1] := $02;
  1769.   cdb[3] := $00;
  1770.   cdb[7] := ((SizeOf(DeviceConfigHeader) shr 8) and $FF);
  1771.   cdb[8] := (SizeOf(DeviceConfigHeader) and $FF);
  1772.   SdfTemp := Sdf.Timeout;
  1773.   Sdf.Timeout := Sdf.ReadTimeout;
  1774.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen,
  1775.     Buf, BufLen, SRB_DIR_IN, Sdf);
  1776.   Sdf.Timeout := SdfTemp;
  1777.   if Result = Err_SenseIllegalRequest then
  1778.     Exit;
  1779.   //  from Profile features in MS-DDK header ntddmmc.h
  1780.   case ((DeviceConfigHeader.CurrentProfile shl 8) and $FF00) or
  1781.     ((DeviceConfigHeader.CurrentProfile shr 8) and $00FF) of
  1782.     $0000:
  1783.       begin
  1784.         ProfileDevDiscType.SubType := 'pdtNoCurrentProfile';
  1785.         ProfileDevDiscType.DType := 'NONE';
  1786.         ProfileDevDiscType.TypeNum := 0;
  1787.       end;
  1788.     $0001:
  1789.       begin
  1790.         ProfileDevDiscType.SubType := 'pdtNonRemovableDisk';
  1791.         ProfileDevDiscType.DType := 'NonRemovable';
  1792.         ProfileDevDiscType.TypeNum := 1;
  1793.       end;
  1794.     $0002:
  1795.       begin
  1796.         ProfileDevDiscType.SubType := 'pdtRemovableDisk';
  1797.         ProfileDevDiscType.DType := 'Removable';
  1798.         ProfileDevDiscType.TypeNum := 2;
  1799.       end;
  1800.     $0003:
  1801.       begin
  1802.         ProfileDevDiscType.SubType := 'pdtMagnetoOptical_Erasable';
  1803.         ProfileDevDiscType.DType := 'Erasable';
  1804.         ProfileDevDiscType.TypeNum := 3;
  1805.       end;
  1806.     $0004:
  1807.       begin
  1808.         ProfileDevDiscType.SubType := 'pdtOptical_WriteOnce';
  1809.         ProfileDevDiscType.DType := 'WriteOnce';
  1810.         ProfileDevDiscType.TypeNum := 4;
  1811.       end;
  1812.     $0005:
  1813.       begin
  1814.         ProfileDevDiscType.SubType := 'pdfAS-MO';
  1815.         ProfileDevDiscType.DType := 'AS-MO';
  1816.         ProfileDevDiscType.TypeNum := 5;
  1817.       end;
  1818.     $0008:
  1819.       begin
  1820.         ProfileDevDiscType.SubType := 'pdfCD-ROM';
  1821.         ProfileDevDiscType.DType := 'CD-ROM';
  1822.         ProfileDevDiscType.TypeNum := 6;
  1823.       end;
  1824.     $0009:
  1825.       begin
  1826.         ProfileDevDiscType.SubType := 'pdfCD-R';
  1827.         ProfileDevDiscType.DType := 'CD-R';
  1828.         ProfileDevDiscType.TypeNum := 7;
  1829.       end;
  1830.     $000A:
  1831.       begin
  1832.         ProfileDevDiscType.SubType := 'pdfCD-RW';
  1833.         ProfileDevDiscType.DType := 'CD-RW';
  1834.         ProfileDevDiscType.TypeNum := 8;
  1835.       end;
  1836.     $0010:
  1837.       begin
  1838.         ProfileDevDiscType.SubType := 'pdfDVD-ROM';
  1839.         ProfileDevDiscType.DType := 'DVD-ROM';
  1840.         ProfileDevDiscType.TypeNum := 9;
  1841.       end;
  1842.     $0011:
  1843.       begin
  1844.         ProfileDevDiscType.SubType := 'pdfDVD-R';
  1845.         ProfileDevDiscType.DType := 'DVD-R';
  1846.         ProfileDevDiscType.TypeNum := 10;
  1847.       end;
  1848.     $0012:
  1849.       begin
  1850.         ProfileDevDiscType.SubType := 'pdfDVD-RAM';
  1851.         ProfileDevDiscType.DType := 'DVD-RAM';
  1852.         ProfileDevDiscType.TypeNum := 11;
  1853.       end;
  1854.     $0013:
  1855.       begin
  1856.         ProfileDevDiscType.SubType := 'pdfDVD-RW Restricted';
  1857.         ProfileDevDiscType.DType := 'DVD-RW Restricted Overwrite';
  1858.         ProfileDevDiscType.TypeNum := 13;
  1859.       end;
  1860.     $0014:
  1861.       begin
  1862.         ProfileDevDiscType.SubType := 'pdfDVD-RW Sequential';
  1863.         ProfileDevDiscType.DType := 'DVD-RW Sequential Recording';
  1864.         ProfileDevDiscType.TypeNum := 14;
  1865.       end;
  1866.     $001A:
  1867.       begin
  1868.         ProfileDevDiscType.SubType := 'pdfDVD+RW';
  1869.         ProfileDevDiscType.DType := 'DVD+RW';
  1870.         ProfileDevDiscType.TypeNum := 15;
  1871.       end;
  1872.     $001B:
  1873.       begin
  1874.         ProfileDevDiscType.SubType := 'pdfDVD+R';
  1875.         ProfileDevDiscType.DType := 'DVD+R';
  1876.         ProfileDevDiscType.TypeNum := 16;
  1877.       end;
  1878.     $0020:
  1879.       begin
  1880.         ProfileDevDiscType.SubType := 'pdfDDCD-ROM';
  1881.         ProfileDevDiscType.DType := 'DDCD-ROM';
  1882.         ProfileDevDiscType.TypeNum := 17;
  1883.       end;
  1884.     $0021:
  1885.       begin
  1886.         ProfileDevDiscType.SubType := 'pdfDDCD-R';
  1887.         ProfileDevDiscType.DType := 'DDCD-R';
  1888.         ProfileDevDiscType.TypeNum := 18;
  1889.       end;
  1890.     $0022:
  1891.       begin
  1892.         ProfileDevDiscType.SubType := 'pdfDDCD-RW';
  1893.         ProfileDevDiscType.DType := 'DDCD-RW';
  1894.         ProfileDevDiscType.TypeNum := 19;
  1895.       end;
  1896.     $FFFF:
  1897.       begin
  1898.         ProfileDevDiscType.SubType := 'pdfUNKNOWN';
  1899.         ProfileDevDiscType.DType := 'UNKNOWN';
  1900.         ProfileDevDiscType.TypeNum := 20;
  1901.       end;
  1902.   end;
  1903. end;
  1904. function SwapDWord(const AValue: LongWord): LongWord;
  1905. begin
  1906.   Result := ((AValue shl 24) and $FF000000) or
  1907.     ((AValue shl 8) and $00FF0000) or
  1908.     ((AValue shr 8) and $0000FF00) or
  1909.     ((AValue shr 24) and $000000FF);
  1910. end;
  1911. function EndianToIntelBytes(const AValue: array of Byte; Count: Byte): Integer;
  1912. var
  1913.   I: Integer;
  1914. begin
  1915.   Result := 0;
  1916.   for I := 0 to Count - 1 do
  1917.   begin
  1918.     Result := (AValue[I] shl ((Count - (I + 1)) * 8) or Result);
  1919.   end;
  1920. end;
  1921. function SCSIReadDVDStructure(DeviceID: TCDBurnerInfo; var DescriptorStr:
  1922.   TScsiDVDLayerDescriptorInfo; var Sdf: TScsiDefaults): TScsiError;
  1923. var
  1924.   cdb: array[0..9] of BYTE;
  1925.   Buf: Pointer;
  1926.   BufLen, CdbLen, SdfTemp: DWORD;
  1927.   DVDLayerDescriptor: TScsiDVDLayerDescriptor;
  1928.   Value: Byte;
  1929. begin
  1930.   // 1st time we query length of returned data
  1931.   ZeroMemory(@DVDLayerDescriptor, SizeOf(DVDLayerDescriptor));
  1932.   Buf := @DVDLayerDescriptor;
  1933.   BufLen := SizeOf(DVDLayerDescriptor);
  1934.   cdbLen := DWORD(10);
  1935.   cdb[0] := $AD;
  1936.   cdb[6] := 0; //* First layer
  1937.   cdb[7] := 0;
  1938.   cdb[8] := ((SizeOf(DVDLayerDescriptor) shr 8) and $FF);
  1939.   cdb[9] := (SizeOf(DVDLayerDescriptor) and $FF);
  1940.   SdfTemp := Sdf.Timeout;
  1941.   Sdf.Timeout := Sdf.ReadTimeout;
  1942.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen,
  1943.     Buf, BufLen, SRB_DIR_IN, Sdf);
  1944.   Sdf.Timeout := SdfTemp;
  1945.   if Result = Err_SenseIllegalRequest then
  1946.     Exit;
  1947.   // now we do the real query
  1948.   ZeroMemory(@DVDLayerDescriptor, SizeOf(DVDLayerDescriptor));
  1949.   Buf := @DVDLayerDescriptor;
  1950.   BufLen := SizeOf(DVDLayerDescriptor);
  1951.   CdbLen := DWORD(10);
  1952.   cdb[0] := $AD;
  1953.   cdb[6] := 0; //* First layer
  1954.   cdb[7] := 0;
  1955.   cdb[8] := ((SizeOf(DVDLayerDescriptor) shr 8) and $FF);
  1956.   cdb[9] := (SizeOf(DVDLayerDescriptor) and $FF);
  1957.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen,
  1958.     Buf, BufLen, SRB_DIR_IN, Sdf);
  1959.   Sdf.Timeout := SdfTemp;
  1960.   Value := (DVDLayerDescriptor.BookType_PartVersion shr 4) and $0F;
  1961.   case Value of
  1962.     $00: DescriptorStr.BookType := 'DVD-ROM';
  1963.     $01: DescriptorStr.BookType := 'DVD-RAM';
  1964.     $02: DescriptorStr.BookType := 'DVD-R';
  1965.     $03: DescriptorStr.BookType := 'DVD-RW';
  1966.     $09: DescriptorStr.BookType := 'DVD+RW';
  1967.     $0A: DescriptorStr.BookType := 'DVD+R';
  1968.   else
  1969.     DescriptorStr.BookType := 'Unknown';
  1970.   end;
  1971.   Value := (DVDLayerDescriptor.DiscSize_MaximumRate shr 4) and $0F;
  1972.   case Value of
  1973.     $00: DescriptorStr.DiscSize := '120mm';
  1974.     $01: DescriptorStr.DiscSize := '80mm';
  1975.   else
  1976.     DescriptorStr.DiscSize := 'Unknown';
  1977.   end;
  1978.   Value := (DVDLayerDescriptor.DiscSize_MaximumRate and $0F);
  1979.   case Value of
  1980.     $00: DescriptorStr.MaximumRate := '2.52 Mbps';
  1981.     $01: DescriptorStr.MaximumRate := '5.04 Mbps';
  1982.     $02: DescriptorStr.MaximumRate := '10.08 Mbps';
  1983.     $0F: DescriptorStr.MaximumRate := 'Not Specified';
  1984.   else
  1985.     DescriptorStr.MaximumRate := 'Unknown';
  1986.   end;
  1987.   Value := (DVDLayerDescriptor.LinearDensity_TrackDensity shr 4) and $0F;
  1988.   case Value of
  1989.     $00: DescriptorStr.LinearDensity := '0.267 um/bit';
  1990.     $01: DescriptorStr.LinearDensity := '0.293 um/bit';
  1991.     $02: DescriptorStr.LinearDensity := '0.409 to 0.435 um/bit';
  1992.     $04: DescriptorStr.LinearDensity := '0.280 to 0.291 um/bit';
  1993.     $08: DescriptorStr.LinearDensity := '0.353 um/bit';
  1994.   else
  1995.     DescriptorStr.LinearDensity := 'Reserved';
  1996.   end;
  1997.   Value := (DVDLayerDescriptor.LinearDensity_TrackDensity and $0F);
  1998.   case Value of
  1999.     $00: DescriptorStr.TrackDensity := '0.74 um/track';
  2000.     $01: DescriptorStr.TrackDensity := '0.80 um/track';
  2001.     $02: DescriptorStr.TrackDensity := '0.615 um/track';
  2002.   else
  2003.     DescriptorStr.TrackDensity := 'Reserved';
  2004.   end;
  2005.   DescriptorStr.NoLayer :=
  2006.     IntToStr((DVDLayerDescriptor.NumberOfLayers_TrackPath_LayerType shr 5) and
  2007.     $03);
  2008.   //    0 = Layer contains embossed data    = $01
  2009.   //    1 = Layer contains recordable area  = $02     ?? I question these
  2010.   //    2 = Layer contains rewritable area  = $04
  2011.   //    3 = Reserved                        = $08
  2012.   //   0001b Read-only layer  >> convert to hex How ??
  2013.   //   0010b Recordable layer
  2014.   //   0100b ReWritable layer
  2015.   //   others Reservec
  2016.   Value := (DVDLayerDescriptor.NumberOfLayers_TrackPath_LayerType and $0F);
  2017.   case Value of
  2018.     $01: DescriptorStr.LayerType := 'Read-only layer';
  2019.     $02: DescriptorStr.LayerType := 'Recordable layer';
  2020.     $04: DescriptorStr.LayerType := 'Re-Writable layer';
  2021.     $08: DescriptorStr.LayerType := 'Reserved';
  2022.   else
  2023.     DescriptorStr.LayerType := 'Unknown';
  2024.   end;
  2025.   DescriptorStr.Sectors := (SwapDWord(DVDLayerDescriptor.EndPhysicalSector)) -
  2026.     (SwapDWord(DVDLayerDescriptor.StartingPhysicalSector));
  2027. end;
  2028. function SCSIReadDiscInformation(DeviceID: TCDBurnerInfo; var DiscInformation:
  2029.   TDiscInformation; var Sdf: TScsiDefaults): TScsiError;
  2030. var
  2031.   cdb: array[0..9] of BYTE;
  2032.   Buf: Pointer;
  2033.   BufLen, CdbLen, SdfTemp: DWORD;
  2034. begin
  2035.   ZeroMemory(@DiscInformation, SizeOf(TDiscInformation));
  2036.   Buf := @DiscInformation;
  2037.   BufLen := SizeOf(DiscInformation);
  2038.   cdbLen := DWORD(10);
  2039.   cdb[0] := $51;
  2040.   cdb[7] := ((SizeOf(DiscInformation) shr 8) and $FF);
  2041.   cdb[8] := (SizeOf(DiscInformation) and $FF);
  2042.   SdfTemp := Sdf.Timeout;
  2043.   Sdf.Timeout := Sdf.ReadTimeout;
  2044.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen, Buf, BufLen, SRB_DIR_IN,
  2045.     Sdf);
  2046.   Sdf.Timeout := SdfTemp;
  2047.   DiscInformation.DiscInformationLength :=
  2048.     ((DiscInformation.DiscInformationLength shl 8) and $FF00) or
  2049.     ((DiscInformation.DiscInformationLength shr 8) and $00FF);
  2050. end;
  2051. //  requires scsi-2 or higher
  2052. function SCSIReadFormatCapacity(DeviceID: TCDBurnerInfo; var FormatCapacity:
  2053.   TFormatCapacity; var Sdf: TScsiDefaults): TScsiError;
  2054. var
  2055.   cdb: array[0..9] of BYTE;
  2056.   Buf: Pointer;
  2057.   i: Integer;
  2058.   BufLen, CdbLen, SdfTemp: DWORD;
  2059. begin
  2060.   ZeroMemory(@FormatCapacity, SizeOf(FormatCapacity));
  2061.   Buf := @FormatCapacity;
  2062.   BufLen := SizeOf(FormatCapacity);
  2063.   cdbLen := DWORD(10);
  2064.   cdb[0] := $23;
  2065.   cdb[7] := ((SizeOf(FormatCapacity) shr 8) and $FF);
  2066.   cdb[8] := (SizeOf(FormatCapacity) and $FF);
  2067.   SdfTemp := Sdf.Timeout;
  2068.   Sdf.Timeout := Sdf.ReadTimeout;
  2069.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen,
  2070.     Buf, BufLen, SRB_DIR_IN, Sdf);
  2071.   Sdf.Timeout := SdfTemp;
  2072.   for i := 0 to 32 do
  2073.   begin
  2074.     FormatCapacity.FormattableCD[I].NumberOfBlocks :=
  2075.       SwapDWord(FormatCapacity.FormattableCD[I].NumberOfBlocks);
  2076.     FormatCapacity.FormattableCD[I].FormatType :=
  2077.       FormatCapacity.FormattableCD[I].FormatType shr 2;
  2078.   end;
  2079.   FormatCapacity.CapacityDescriptor.NumberOfBlocks :=
  2080.     SwapDWord(FormatCapacity.CapacityDescriptor.NumberOfBlocks);
  2081. end;
  2082. function SCSIReadTrackInformation(DeviceID: TCDBurnerInfo; const ATrack: Byte;
  2083.   var TrackInformation: TTrackInformation; var Sdf: TScsiDefaults): TScsiError;
  2084. var
  2085.   cdb: array[0..9] of BYTE;
  2086.   Buf: Pointer;
  2087.   BufLen, CdbLen, SdfTemp: DWORD;
  2088. begin
  2089.   ZeroMemory(@TrackInformation, SizeOf(TTrackInformation));
  2090.   Buf := @TrackInformation;
  2091.   BufLen := SizeOf(TrackInformation);
  2092.   cdbLen := DWORD(10);
  2093.   cdb[0] := $52;
  2094.   cdb[1] := $01;
  2095.   cdb[2] := HiByte(HiWord(ATrack));
  2096.   cdb[3] := LoByte(HiWord(ATrack));
  2097.   cdb[4] := HiByte(LoWord(ATrack));
  2098.   cdb[5] := LoByte(LoWord(ATrack));
  2099.   cdb[7] := HiByte(SizeOf(TTrackInformation));
  2100.   cdb[8] := LoByte(SizeOf(TTrackInformation));
  2101.   SdfTemp := Sdf.Timeout;
  2102.   Sdf.Timeout := Sdf.ReadTimeout;
  2103.   Result := ASPIsendScsiCommand(DeviceID, @cdb, CdbLen, Buf, BufLen, SRB_DIR_IN,
  2104.     Sdf);
  2105.   Sdf.Timeout := SdfTemp;
  2106.   with TrackInformation do
  2107.   begin
  2108.     Datalength := ((Datalength shl 8) and $FF00) or ((Datalength shr 8) and
  2109.       $00FF); //SwapWord(Datalength);
  2110.     TrackSize := SwapDWord(TrackSize);
  2111.     FreeBlocks := SwapDWord(FreeBlocks);
  2112.     TrackStartAddress := SwapDWord(TrackStartAddress);
  2113.     NextWritableAddress := SwapDWord(NextWritableAddress);
  2114.     FixedpacketSize := SwapDWord(FixedpacketSize);
  2115.     LastRecordedAddress := SwapDWord(LastRecordedAddress);
  2116.   end;
  2117. end;
  2118. end.