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

📄 tcdbasic.pas

📁 使用ASPI读SCSI/IDE/ATAPI的CDROM数据或音乐磁道数据的程序
💻 PAS
📖 第 1 页 / 共 5 页
字号:
   end;


 { READ TOC requests that the target transfers the table of contents.
   NOTE: The maximum TOC data length possible on ISO-9660 CD-ROM media
   is 804 bytes, or 100 TOC track descriptors. Track number 0 is CD lead-in
   area, track number 0AAh is CD lead-out area, and they are not accessible
   through SCSI.
   MSFform=TRUE requests that MSF format be used for LBA fields, i.e. least
       significant byte should be the Frame number (0..74d), next byte -
       Second number (0..59d), next byte - Minute number (0..74bcd), and
       the MSB of DWORD is reserved. In certain transition areas, the
       relative MSF are decreasing positive values.  The absolute MSF
       addresses are always increasing positive values.
       MSF=FALSE requests that the logical block address format be used
       for the CD-ROM absolute address field or for the offset from the
       beginning of the current track expressed as a number of LBs in a
       CD-ROM track relative address field.  This track relative logical
       block address (TRLBA) value is reported as a negative value in
       twos-complement notation for transition areas that have decreasing
       MSF encoded relative addresses.
   Start field specifies the starting track number for which the data
       shall be returned. The data are returned in contiguous ascending
       track number order. If the starting track field is not valid for
       the currently installed medium,  the command shall be terminated
       with Err_SenseIllegalRequest status. Start=0 means entire table of
       contents request and it's the only way we recommend to use this
       function.
   The returned data format shown below in SCSI_Toc record structure.
   The TOC data block contains a 4-byte header followed by zero or more
   TOC track descriptors. The first track number is not required to be one.
   A disc may start at any valid track number.  The track numbers between
   the first and the last track number are required to be in contiguous
   ascending order, except for the lead-out track (always numbered 0AAh).
   NOTE: The starting logical block address value recovered from the TOC
   has a tolerance of zero for data tracks and plus or minus 75 CD sectors
   for audio tracks. }
function TCdRom.SCSIreadToc(MSFform : BOOLEAN; Start : BYTE;
                                            var Toc: TCdRomToc) : BOOLEAN;
   type
     SCSI_TrackDescriptor = packed record
        Reserved1    : byte;
        ControlAndADR: byte;  //bitset: D7..D4=ADR, D3..D0=Control
        TrackNumber  : byte;
        Reserved2    : byte;
        AbsAddress   : DWORD; //byte-reversed!
     end;
     SCSI_Toc = packed record
        Length    : WORD;  //byte-reversed!
        FirstTrack: byte;
        LastTrack : byte;
        Tracks    : array[0..99] of SCSI_TrackDescriptor;
     end;
   var
      cd      : SCSI_Toc;
      cdt     : SCSI_TrackDescriptor;
      Arg1, B : byte;
      i       : integer;
   begin
      FillChar(cd,  sizeof(cd),  0);
      if MSFform then  Arg1 := 2  else  Arg1 := 0;
      result := ASPIsend10($43, Arg1, 0, Start, sizeof(cd),
                           @cd, sizeof(cd), SRB_DIR_IN, ShortTimeout);
      if NOT result then begin
         Toc.FirstTrack := 0;         Toc.LastTrack  := 0;
         Toc.TrackCount := 0;         exit;
      end;
      Toc.FirstTrack := integer(cd.FirstTrack) AND $00FF;
      Toc.LastTrack  := integer(cd.LastTrack)  AND $00FF;
      Toc.TrackCount := (integer(BigEndianW(cd.Length))-2) DIV sizeof(cdt);
      Toc.InMSF      := MSFform;
      for i := 0 to Toc.TrackCount-1 do begin
         cdt := cd.Tracks[i];
         with Toc.Track[i] do begin
            Address      := BigEndianD(cdt.AbsAddress);
            TrackNumber  := cdt.TrackNumber;
            B := (cdt.ControlAndADR SHR 4) AND $0F;
            if B >= 4 then ADR := ADRreserved
                      else ADR := TsubchannelADRinfo(B);
            PreEmphasis  := (cdt.ControlAndADR AND 1) <> 0;
            CopyPermit   := (cdt.ControlAndADR AND 2) <> 0;
            DataTrack    := (cdt.ControlAndADR AND 4) <> 0;
            QuadAudio    := (cdt.ControlAndADR AND 8) <> 0;
   end; end; end;


 { READ HEADER requests the CD-ROM data block address header of the
   requested logical block.
   CDmode field specifies the CD-ROM data mode of the logical blocks:
              +======================================+
              |CD-ROM|User data field|Auxiliary field|
              | mode | (2 048 bytes) |  (288 bytes)  |
              |------+---------------+---------------|
              | 00h  |  All zeroes   |  All zeroes   |
              | 01h  |  User data    |  L-EC symbols |
              | 02h  |  User data    |  User data    |
              |03-FFh|  Reserved     |  Reserved     |
              +======================================+
   Address field gives the address of the first logical block in the
   physical sector where the data for the requested GLBA is found. }
function TCdRom.SCSIreadHeaderLBA(GLBA : DWORD;
                         var CDmode : BYTE; var Address : DWORD) : BOOLEAN;
   type SCSI_HeaderInfo = packed record
         Mode : BYTE;
         Resv1,Resv2,Resv3 : BYTE;
         Addr : DWORD;
      end;
   var  cd : SCSI_HeaderInfo;
   begin
      FillChar(cd, sizeof(cd), 0);
      result := ASPIsend10($44, 0, GLBA, 0, sizeof(cd),
                           @cd, sizeof(cd), SRB_DIR_IN, MediumTimeout);
      CDmode  := cd.Mode;
      Address := BigEndianD(cd.Addr);
   end;
 { Second implementation of READ HEADER requests that MSF format be used
   for Address field. }
function TCdRom.SCSIreadHeaderMSF(GLBA : DWORD;
                var CDmode, AddressM, AddressS, AddressF : BYTE) : BOOLEAN;
   var  cd : array[0..7] of BYTE;
   begin
      FillChar(cd, sizeof(cd), 0);
      result := ASPIsend10($44, 2, GLBA, 0, sizeof(cd),
                           @cd, sizeof(cd), SRB_DIR_IN, MediumTimeout);
      CDmode   := cd[0];
      AddressM := cd[5];
      AddressS := cd[6];
      AddressF := cd[7];
   end;


 { MODE SELECT(10) is a means to specify medium or device parameters to
   the target. The target may provide for independent sets of parameters
   for each attached logical unit.
   PF (Page Form)=TRUE indicates that parameters following the header and
       block descriptor(s) are structured as pages as specified in SCSI-2,
       PF=FALSE means that all parameters after the block descriptors are
       vendor-specific according to SCSI-1.
   SP (Save Pages)=TRUE indicates that the target (after performing the
       specified MODE SELECT operation) shall save to a non-volatile
       vendor-specific location all the savable pages.  The SP flag is
       optional, even when mode pages are supported by the target.
       If the target does not implement saved pages and the SP flag is
       set to TRUE, the command shall be terminated with
       Err_SenseIllegalRequest status.
   BufLen is the length in bytes of the mode parameter list that shall be
       transferred to the target. BufLen=0 indicates that no data shall be
       transferred.  This condition shall not be considered as an error.
   Command shall be terminated with Err_SenseIllegalRequest status and all
   mode parameters shall be remains unchanged if:
   a) It sets any field that is reported by the target as not changeable
      to a value other than its current value.
   b) It sets any field in the mode parameter header, block descriptor(s)
      or mode parameter to an unsupported value.
   c) It sends a mode page with a length not equal to the page length
      returned by the MODE SENSE command for that page.
   d) It sets any reserved field in the parameter list to a non-zero value.
   e) BufLen results in the truncation of any mode parameter header, mode
      parameter block descriptor(s), or mode page.
   A target may alter any mode parameter in any mode page (even reported
   as non-changeable) as a result of changes to other mode parameters.
   NOTE: MODE SENSE command should be issued prior to each MODE SELECT to
   determine supported mode pages, page lengths, and other parameters.
   NOTE: The initiator should issue a MODE SENSE command with the PCTL=1
   and PAGE=3Fh to determine which mode pages are supported, which mode
   parameters within the pages are changeable, and the supported length
   of each mode page prior to issuing any MODE SELECT commands.
   NOTE: MODE SELECT does not support page code of 3Fh (all pages). }
function TCdRom.SCSImodeSelectEX(PF, SP : BOOLEAN;
                                 Buf : pointer; BufLen : DWORD) : BOOLEAN;
   var  Arg1 : byte;
   begin
      if PF then  Arg1 := $10  else  Arg1 := 0;
      if SP then  Arg1 := Arg1 OR 1;
      result := ASPIsend10($55, Arg1, 0, 0, BufLen,
                                Buf, BufLen, SRB_DIR_OUT, ShortTimeout);
   end;
function TCdRom.SCSImodeSelect(Buf : pointer; BufLen : DWORD) : BOOLEAN;
   begin  result := SCSImodeSelectEX(TRUE, FALSE, Buf, BufLen);  end;


 { MODE SENSE(10) provides a means for a target to report parameters to
   the initiator.  It is a complementary command to the MODE SELECT(10).
   DBD (Disable Block Descriptors) = TRUE specifies that the target shall
       not return any block descriptors in the returned MODE SENSE data.
       DBD=FALSE  means that the target may return zero or more block
       descriptors there, at the target's discretion.
   PCTL (Page Control) field defines the type of mode parameter values to
       be returned in the mode pages: 00b=Current Values, 01b=Changeable
       Values, 10b=Default Values and 11b=Saved Values (see below).
       NOTE: PCTL field only affects the mode parameters within the mode
       pages, however the PS bit, page code and page length fields should
       return current values since they have no meaning when used with
       other types. The mode parameter header and mode parameter block
       descriptor should return current values.
       The current values (PCTL=0) are:
         a) the values established by last successful MODE SELECT command;
         b) the saved values if a MODE SELECT command has not successfully
            completed since the last power-on, hard or soft RESET;
         c) the default values, if saved values are not available or not
            supported.
       If the changeable values (PCTL=1) are selected, then all fields of
       the mode parameters that are changeable shall be set to all one bits
       and the fields of the mode parameters that are non-changeable (i.e.
       defined by the target) shall be set to all zero bits.
       NOTE: An attempt to change a non-changeable mode parameter (via MODE
       SELECT) results in an error condition.
       The default values (PCTL=2) are accessible even if the device is not
       ready. Parameters not supported by the target shall be set to zero.
       Implementation of saved (PCTL=3) page parameters is optional.
       Mode parameters not supported by the target shall be set to zero.
       If saved values are not implemented, the command shall return
       Err_SenseIllegalRequest status.
   PAGE specifies which mode page(s) to return. If requested page is not
       implemented by the target, it shall return Err_SenseIllegalRequest
       status.
       A page code of 3Fh indicates that all pages implemented by the
       target shall be returned. Pages should be returned in ascending
       page code order except for mode page 00h. If implemented, it shall
       be returned after all other mode pages.
       NOTE: If the PCTL field and PAGE field are both set to zero, the
       target should return a mode parameter header and block descriptor
       (if applicable). This is for compatibility with SCSI-1 initiators.
            +====================================================+
            |Page code|            Description                   |
            |---------+------------------------------------------+
            |   01h   |  Read error recovery page                |
            |   02h   |  Disconnect-reconnect page               |
            |   07h   |  Verify error recovery page              |
            |   08h   |  Caching page                            |
            |   09h   |  Peripheral device page                  |
            |   0Ah   |  Control mode page                       |
            |   0Bh   |  Medium types supported page             |
            |   0Dh   |  CD-ROM page                             |
            |   0Eh   |  CD-ROM audio control page               |
            | 20h-3Eh |Vendor-specific (page format required)    |
            |   00h   |Vendor-specific (page format not required)|
            +====================================================+   }
function TCdRom.SCSImodeSense(DBD : BOOLEAN; PCTL : TCdRomModePageType;
                    PAGE : BYTE; Buf : pointer; BufLen : DWORD) : BOOLEAN;
   var
      Arg1 : byte;

⌨️ 快捷键说明

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