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

📄 tcdbasic.pas

📁 使用ASPI读SCSI/IDE/ATAPI的CDROM数据或音乐磁道数据的程序
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      Arg2 : DWORD;
   begin
      FillChar(Buf^, BufLen, 0);
      if DBD then  Arg1 := 8  else  Arg1 := 0;
      Arg2 := ((Ord(PCTL) AND 3) SHL 6) OR (PAGE AND $3F);
      result := ASPIsend10($5A, Arg1, Arg2 SHL 24, 0, BufLen,
                                Buf, BufLen, SRB_DIR_IN, ShortTimeout);
   end;


{============= MODE SELECT/MODE SENSE - Mode list header. =============}
 { The mode parameter list used by MODE SELECT/MODE SENSE contains a header,
   followed by zero or more block descriptors, followed by zero or more
   variable-length pages. Here are procedures for header and descriptors
   reading/modifying.
   The list header consist of two useful parameters:
   a) The medium-type code field defined by TCdRomMediumType type.
      'mixed' means that medium may contain data and audio tracks,
      'default' - that device supports only one medium type (??),
      suffix '80' - that media is a 80 mm diameter disk instead the
      default 120 mm.
   b) The DPOFUA flag (not supported for MODE SELECT). If MODE SENSE
      returns this flag TRUE, then target supports DPO and FUA flags
      using (see SCSIread10 function description).
   Each block descriptor contains three fields:
   a) Density - Enumerated CD-ROM density codes:
      00h = Default density code (the only density supported by target)
      01h = CD-ROM mode 1 - User data only (2048 bytes per physical sector)
      02h = CD-ROM mode 2 - User data plus auxiliary data field (2336 bytes)
      03h = 4-byte tag field, user data plus auxiliary data     (2340 bytes)
      04h = CD-Audio mode - 1/75th of a second per logical block
      values 05h-7Fh are reserved,  80h-FFh - vendor-specific.
      NOTE: The number of bytes per sector specified here is used with the
      block length to map CD-ROM sectors to logical block addresses.
   b) BlkCount - The number of logical blocks on the medium to which the
      density code and block length fields apply.  A zero value indicates
      that all of the remaining logical blocks of the logical unit shall
      have the medium characteristics specified.
   c) BlkSize - The length in bytes of each logical block described by
      the block descriptor.   }
function TCdRom.SCSImodeSenseHeader(var sh : TCdRomModeHeader) : BOOLEAN;
   type SCSI_ModeHeader = packed record
      ModeDataLength   : WORD;   // full record length except itself (SENSE only)
      MediumType       : BYTE;
      DeviceSpecific   : BYTE;   // $10 bit is DPOFUA flag
      Reserved1        : WORD;
      DescriptorLength : WORD;   // equal to 8*Number of Block Descriptors
                                 // must be zero when DBD=TRUE
      BDP              : array[0..511] of DWORD;  // intuitional choice :)
     end;
   var
      cd : SCSI_ModeHeader;
      i  : integer;
   begin
      FillChar(sh, sizeof(sh), 0);
      result := SCSImodeSense(FALSE, MPTcurrent, $3F, @cd, sizeof(cd));
      if result then begin
         if cd.MediumType > 7 then sh.Medium := CDTreserved
             else sh.Medium := TCdRomMediumType(cd.MediumType);
         sh.DPOFUA   := (cd.DeviceSpecific AND $10) <> 0;
         sh.BDlength := cd.DescriptorLength DIV 8;
         for i := 0 to sh.BDlength - 1 do with sh.BD[i] do begin
            Density  := BYTE($0FF AND cd.BDP[i SHL 1]);
            BlkCount := $0FFFFFF AND BigEndianD(cd.BDP[i SHL 1]);
            BlkSize  := $0FFFFFF AND BigEndianD(cd.BDP[(i SHL 1)+1]);
   end; end; end;



{======== MODE SELECT/MODE SENSE - Error recovery parameters page. ========}
 { This page specifies the error recovery parameters the target shall use
   during any command that performs a data read operation to the media
   (e.g. READ, READ TOC, etc.).
   PSAV (Parameters SAVable) = TRUE indicates that the target is capable
       of saving the page in a non-volatile vendor-specific location.
       This bit is only used with the MODE SENSE command.
   RLEV (Recovery Level) is the set of five bits:
       $20 = Transfer block bit. If set, data block that is not recovered
             shall be transferred to data buffer anyway. This bit does not
             affect the action taken for recovered data and does not
             suppress the Err_SenseMediumError status of read commands.
       $10 = Read continuous bit. If set, indicates the target shall
             transfer the entire requested length of data without adding
             delays to perform error recovery procedures.
             This implies that the target may send data that is erroneous
             or fabricated in order to maintain a continuous flow of data.
             This bit is typically used in audio or video applications.
       $04 = Post error bit. If set, target shall report recovered errors.
       $02 = Disable transfer on error bit. Ones indicates that the target
             shall terminate the data phase upon detection of a recovered
             error.
       $01 = Disable correction bit. If set, error correction codes shall
             not be used for data error recovery. This is applicable to
             layered error correction (L-EC) feature only. The retries and
             CIRC (Cross Interleaved Reed-solomon Code,the error detection
             and correction technique used within small (24 bytes) frames
             of audio or data) are performed anyway.
       The interpretation of these bit settings for CD-ROM devices and
       valid RLEV values are given below. If RLEV is set to any other
       value, the command shall be terminated with Err_SenseInvalidRequest
       status.
   00h/01h  If an uncorrectable error occurs, transfer is terminated
     with Err_SenseMediumError status. The block with the error is not
     transferred.  Recovered errors are not reported.
   04h/05h  Recovered errors are reported by Err_SenseRecoveredError,
     but data transfer is not terminated. Uncorrectable error terminates
     data transfer with Err_SenseMediumError status and the block with
     the error is not transferred.
   06h/07h  Recovered data error terminates data transfer with
     Err_SenseRecoveredError status. The block with the recovered error is
     not transferred.  Uncorrectable error terminates data transfer with
     Err_SenseMediumError status and errata block is not transferred.
   10h/11h  If an error occurs which is uncorrectable in time to maintain
     data transfer, the data transfer is not terminated. However, when the
     data transfer has completed, Err_SenseMediumError status is reported.
      Recovered errors are not reported.
   14h/15h  Data transfer is never terminated. Recovered errors are
      reported at completion by Err_SenseRecoveredError status,
      uncorrectable errors - by Err_SenseMediumError.  Reporting
      unrecovered errors takes precedence over reporting recovered errors.
   20h/21h/24h/25h/26h/27h  are the same as 00h/01h/04h/05h/06h/07h, but
      the block with the error is always transferred.
   30h/31h/34h/35h  are the same as 10h/11h/14h/15h.
       A CIRC recovered data error is defined as a block for which the
       CIRC based error correction algorithm was unsuccessful for a read
       attempt, but on a subsequent read operation no error was reported.
       The number of subsequent read operations is limited to the read
       retry count. Layered error correction was not used.
       An L-EC recovered data error is defined as a block for which the
       CIRC based error correction was unsuccessful, but the layered error
       correction was able to correct the block within the read retry count.
   RETR (Read Retry Count) specifies the number of times that the controller
       shall attempt its read recovery algorithm. }
function TCdRom.SCSImodeSenseRecoverEX(PCTL : TCdRomModePageType;
                      var PSAV : BOOLEAN; var RLEV, RETR : BYTE) : BOOLEAN;
   type SCSI_ModeRecovery = packed record
      ModeDataLength   : WORD;   // full record length except itself
      MediumType       : BYTE;
      DeviceSpecific   : BYTE;
      Reserved1        : WORD;
      DescriptorLength : WORD;   // equal to 8*Number of Block Descriptors
                                 // must be zero when DBD=TRUE
      PageCode         : BYTE;   // six LSBs of page code (01h) plus
                                 //  MSbit is PSAV flag (MODE SENSE only)
      ParamLength      : BYTE;   // must be = 6
      RecoveryLevel    : BYTE;   // returns as RLEV
      MaxRetryCount    : BYTE;
      Reserved2        : DWORD;
     end;
   var cd :  SCSI_ModeRecovery;
   begin
      result := SCSImodeSense(TRUE, PCTL, 1, @cd, sizeof(cd));
      PSAV := (cd.PageCode AND $80) <> 0;
      RLEV :=  cd.RecoveryLevel;
      RETR :=  cd.MaxRetryCount;
   end;
function TCdRom.SCSImodeSenseRecover(var RLEV, RETR : BYTE)     : BOOLEAN;
   var PSAVtemp : BOOLEAN;
   begin
      result := SCSImodeSenseRecoverEX(MPTcurrent, PSAVtemp, RLEV, RETR);
   end;


{======== MODE SELECT/MODE SENSE - Supported medium page. ========}
 { This page contains a list of the medium types implemented by the target.
   The code values (up to four) are reported in ascending order.
   PSAV=TRUE indicates that the target is capable of saving the page
      in a non-volatile location. Used with the MODE SENSE only.  }
function TCdRom.SCSImodeSenseMediumEX(PCTL : TCdRomModePageType;
   var PSAV: BOOLEAN; var Med1,Med2,Med3,Med4: TCdRomMediumType): BOOLEAN;
   type SCSI_ModeMedium = packed record
      ModeDataLength   : WORD;   // full record length except itself
      MediumType       : BYTE;
      DeviceSpecific   : BYTE;
      Reserved1        : WORD;
      DescriptorLength : WORD;
      PageCode         : BYTE;   // six LSBs of page code (0Bh) plus
                                 //  MSbit is PSAV flag (MODE SENSE only)
      ParamLength      : BYTE;   // must be = 6
      Reserved2        : WORD;
      Medium : array[0..3] of BYTE;
     end;
   var
      cd : SCSI_ModeMedium;
      i  : integer;
   begin
      result := SCSImodeSense(TRUE, PCTL, $0B, @cd, sizeof(cd));
      PSAV   := (cd.PageCode AND $80) <> 0;
      with cd do begin
         for i := 0 to 3 do begin
            if Medium[i] > 7 then Medium[i] := 4;  // CDTreserved
            if (Medium[i]=0) AND (i > 0)
                              then Medium[i] := 8;  // CDTnone
         end;
         Med1 := TCdRomMediumType(Medium[0]);
         Med2 := TCdRomMediumType(Medium[1]);
         Med3 := TCdRomMediumType(Medium[2]);
         Med4 := TCdRomMediumType(Medium[3]);
   end; end;


{======== MODE SELECT/MODE SENSE - CD-ROM device parameters page. ========}
 { This page specifies parameters that affect all CD-ROM data types.
   PSAV=TRUE indicates that the target is capable of saving the page in a
      non-volatile vendor-specific location. Used with the MODE SENSE only.
   ITimer (Inactivity Timer) specifies the time that the drive shall remain
      in the hold track state after completion of a seek or read operation.
      Value:   1     2     3   4  5  6  7   8   9  Ah  Bh  Ch  Dh  Eh  Fh
      Time:  0.125s 0.25s 0.5s 1s 2s 4s 8s 16s 32s 1m  2m  4m  8m  16m 32m
      where s=seconds, m=minutes. Value of zero means vendor-specific time.
      WARNING: High values in this parameter may have an adverse effect on
      the drive MTBF.
   SperMunits and FperSunits fields gives the ratio of these MSF address
      values. For media conforming to the CD-ROM and CD-DA standard, this
      value is 60 and 75 respectively.   }
function TCdRom.SCSImodeSenseDeviceEX(PCTL : TCdRomModePageType;
                      var PSAV : BOOLEAN; var ITimer : BYTE;
                      var SperMunits, FperSunits : WORD) : BOOLEAN;
   type SCSI_ModeDevice = packed record
      ModeDataLength   : WORD;   // full record length except itself
      MediumType       : BYTE;
      DeviceSpecific   : BYTE;
      Reserved1        : WORD;
      DescriptorLength : WORD;
      PageCode         : BYTE;   // six LSBs of page code (0Dh) plus
                                 //  MSbit is PSAV flag (MODE SENSE only)
      ParamLength      : BYTE;   // must be = 6
      Reserved2        : BYTE;
      InactivityTimer  : BYTE;   // returns as ITimer
      SunitsPerMunits  : WORD;   // returns as SperMunits. Usually=60d
      FunitsPerSunits  : WORD;   // returns as FperSunits. Usually=75d
     end;
   var cd :  SCSI_ModeDevice;
   begin
      result := SCSImodeSense(TRUE, PCTL, $0D, @cd, sizeof(cd));
      PSAV   := (cd.PageCode AND $80) <> 0;
      ITimer := $0F AND cd.InactivityTimer;
      SperMunits := BigEndianW(cd.SunitsPerMunits);
      FperSunits := BigEndianW(cd.FunitsPerSunits

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -