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

📄 tcdbasic.pas

📁 使用ASPI读SCSI/IDE/ATAPI的CDROM数据或音乐磁道数据的程序
💻 PAS
📖 第 1 页 / 共 5 页
字号:
                                  GLBA : DWORD;  Sectors : WORD) : BOOLEAN;
        function SCSIsynchronizeCache(IMM : BOOLEAN;
                                  GLBA : DWORD;  Sectors : WORD) : BOOLEAN;
        function SCSIlockUnlockCache(LOK : boolean;
                                  GLBA : DWORD;  Sectors : WORD) : BOOLEAN;
        function SCSIreadLong(CORR : BOOLEAN; GLBA : DWORD;
                                  Buf : pointer; BufLen : DWORD) : BOOLEAN;
        function SCSIreadSubchannel(MSFform : BOOLEAN;
                                      var Info : TCdRomSubQinfo) : BOOLEAN;
        function SCSIreadToc(MSFform : BOOLEAN; Start : BYTE;
                                            var Toc : TCdRomToc) : BOOLEAN;
        function SCSIreadHeaderLBA(GLBA : DWORD;
                         var CDmode : BYTE; var Address : DWORD) : BOOLEAN;
        function SCSIreadHeaderMSF(GLBA : DWORD;
                var CDmode, AddressM, AddressS, AddressF : BYTE) : BOOLEAN;
        function SCSImodeSelectEX(PF, SP : BOOLEAN;
                                Buf : pointer; BufLen : DWORD)   : BOOLEAN;
        function SCSImodeSelect(Buf : pointer; BufLen : DWORD)   : BOOLEAN;
        function SCSImodeSense(DBD : BOOLEAN; PCTL : TCdRomModePageType;
                     PAGE : BYTE; Buf : pointer; BufLen : DWORD) : BOOLEAN;
   // The function set below have to describe all possible MODE SELECT
   // and MODE SENSE implementations for various mode pages. Almost
   // each function is in two forms - full-featured with 'EX' suffix
   // in name, and shortened-form (without any suffixes).
   // For now, the only MODE SENSE is implemented. It is necessary to
   // manipulate with mode parameters highly carefull. I'm not ready
   // yet. That's why.
   //     Unimplemented mode pages are:
   // 02h Disconnect-reconnect page  \
   // 09h Peripheral device page      > unuseful with ATAPI devices
   // 0Ah Control mode page          /
   // 07h Verify error recovery page - verify command are not used
   // 08h Caching page            - do you need to control CD-ROM's cache?
        function SCSImodeSenseHeader(var sh : TCdRomModeHeader)  : BOOLEAN;
        function SCSImodeSenseRecoverEX(PCTL: TCdRomModePageType;
                  var PSAV : BOOLEAN; var RLEV, RETR : BYTE)     : BOOLEAN;
        function SCSImodeSenseRecover(var RLEV, RETR : BYTE)     : BOOLEAN;
        function SCSImodeSenseMediumEX(PCTL : TCdRomModePageType;
                     var PSAV : BOOLEAN;
                     var Med1,Med2,Med3,Med4 : TCdRomMediumType) : BOOLEAN;
        function SCSImodeSenseDeviceEX(PCTL : TCdRomModePageType;
                     var PSAV : BOOLEAN; var ITimer : BYTE;
                     var SperMunits, FperSunits : WORD)          : BOOLEAN;
        function SCSImodeSenseDevice(var ITimer : BYTE)          : BOOLEAN;
        function SCSImodeSenseAudioEX(PCTL : TCdRomModePageType;
                                   var sh : TCdRomModePageAudio) : BOOLEAN;
        function SCSImodeSenseAudio(var sh: TCdRomModePageAudio) : BOOLEAN;
         {============== OPTIONAL AUDIO PLAYBACK COMMANDS =============}
        function SCSIplayAudio10(GLBA : DWORD; Sectors : WORD)   : BOOLEAN;
        function SCSIplayAudio12(GLBA, Sectors : DWORD)          : BOOLEAN;
        function SCSIplayAudioMSF(StartM, StartS, StartF,
                                  StopM, StopS, StopF : BYTE )   : BOOLEAN;
        function SCSIplayAudioTI(StartTrack, StartIndex,
                                   StopTrack, StopIndex : BYTE ) : BOOLEAN;
        function SCSIplayAudioR10(TRLBA : DWORD;
                              StartTrack : BYTE; Sectors : WORD) : BOOLEAN;
        function SCSIplayAudioR12(TRLBA : DWORD;
                            StartTrack : BYTE;  Sectors : DWORD) : BOOLEAN;
        function SCSIpauseAudio                                  : BOOLEAN;
        function SCSIresumeAudio                                 : BOOLEAN;

        property Locked : BOOLEAN read fLocked write SetLockUnlock;
     end;

implementation

constructor TCdRom.Create;
   begin
      inherited Create(AOwner);
      fLocked := FALSE;
   end;

destructor  TCdRom.Destroy;
   begin
      SetLockUnlock(FALSE);               // Unlock the medium
      SCSIlockUnlockCache(FALSE, 0, 0);   // Unlock entire cache
      inherited Destroy;
   end;

procedure TCdRom.ChangeDevice(Value : TdeviceID);
   begin
      SetLockUnlock(FALSE);               // Unlock the medium
      SCSIlockUnlockCache(FALSE, 0, 0);   // Unlock entire cache
      inherited ChangeDevice(Value);
   end;

   {======================= MANDATORY SCSI-II COMMANDS ====================}

 { TEST UNIT READY command provides a means to check if the logical unit
   is ready.  This is not a request for a self-test.  It is especially
   useful to check cartridge status of logical units with removable media.
=====================   Possible LastError codes:   =========================
|Status|Sense key|        ASC and ASCQ                |LastError code(Err_..)
|------+---------+------------------------------------+---------------------|
| GOOD |   ---   |                ---                 | None                |
| BUSY |   ---   |                ---                 | TargetBusy          |
| RESERVATION CONFLICT            ---                 | ReservationConflict |
|------+---------+------------------------------------+---------------------|
| CHECK| ILLEGAL | LOGICAL UNIT NOT SUPPORTED         | SenseIllegalRequest |
|CONDI-| REQUEST |                                    |                     |
| TION ----------+------------------------------------+---------------------|
|      |   NOT   | LUN DOES NOT RESPOND TO SELECTION  | SenseNotReady       |
|      |  READY  | MEDIUM NOT PRESENT                 |                     |
|      |         | LUN IS IN PROCESS OF BECOMING READY|                     |
|      |         | INIT COMMAND REQUIRED              |                     |
|      |         | MANUAL INTERVENTION REQUIRED       |                     |
|      |         | FORMAT IS IN PROGRESS              |                     |
|      |         | LUN NOT READY,CAUSE NOT REPORTABLE |                     |
|------+---------+------------------------------------+---------------------|}
function TCdRom.SCSItestReady : BOOLEAN; //True if READY
  begin result := ASPIsend6(0, 0, 0, NIL, 0, SRB_NODIR, ShortTimeout); end;


 { REQUEST SENSE command (code 03h) is fully implemented in ASPI layer.
   If still need it, you got it below. }
function TCdRom.SCSIrequestSense(Pbuf : pointer; BufLen : BYTE) : BOOLEAN;
  var  I : DWORD;
  begin
     I := DWORD(BufLen) AND $FF;
     result := ASPIsend6(3, 0, BufLen, PBuf, I, SRB_NODIR, ShortTimeout);
  end;


 { INQUIRY command requests some parameters of the target and its attached
   peripheral device(s). In the common case it seems like below.
   More practical styled call is GetDeviceInfo included into TASPIdevice. }
function TCdRom.SCSIinquiry(Vital : BOOLEAN; CodePage : BYTE;
                                 Pbuf : pointer; BufLen : BYTE) : BOOLEAN;
  var  I, J : DWORD;
  begin
     J := DWORD(CodePage) AND $FF;
     if Vital then J := (J OR $100) SHL 8  else  J := 0;
     I := DWORD(BufLen) AND $FF;
     result := ASPIsend6($12, J, BufLen, PBuf, I, SRB_NODIR, ShortTimeout);
  end;


 {      RESERVE and RELEASE commands define how different types of
   restricted access may be achieved, and to whom the access is restricted.
   Use reservations to gain a level  of exclusivity in access to all or part
   of the medium. It is expected that the reservation will be retained until
   released. Partial medium reservation is excluded from this implementation
   because it's not-so-useful and optional in SCSI-2 terms.
        RESERVE requests that the entire logical unit be reserved for the
   exclusive use until released by a RELEASE command or by a hard/soft RESET
   condition.  A reservation is not granted if the logical unit is reserved
   by another task. If, after honouring the reservation, any other initiator
   attempts to perform any command on the reserved LUN other than INQUIRY or
   REQUEST SENSE, it shall be rejected with Err_SenseReservationConflict
   status.  }
function TCdRom.SCSIreserve : BOOLEAN;
  begin result := ASPIsend6($16, 0,0, NIL,0, SRB_NODIR, ShortTimeout); end;
function TCdRom.SCSIrelease : BOOLEAN;
  begin result := ASPIsend6($17, 0,0, NIL,0, SRB_NODIR, ShortTimeout); end;
 {      The third-party reservation for  RESERVE  command allows to reserve
   the logical unit  for another SCSI device specified in the third-party
   DeviceID field.  This is intended for use in multiple-initiator systems
   that use the COPY command. }
function TCdRom.SCSIreserve3rdParty(TrdPartyDeviceID: BYTE): BOOLEAN;
   var  I : DWORD;
   begin
      I := DWORD(TrdPartyDeviceID) AND 7;  I := (I SHL 17) OR $100000;
      result := ASPIsend6($16, I, 0, NIL, 0, SRB_NODIR, ShortTimeout);
   end;
function TCdRom.SCSIrelease3rdParty(TrdPartyDeviceID: BYTE): BOOLEAN;
   var  I : DWORD;
   begin
      I := DWORD(TrdPartyDeviceID) AND 7;  I := (I SHL 17) OR $100000;
      result := ASPIsend6($17, I, 0, NIL, 0, SRB_NODIR, ShortTimeout);
   end;


 { SelfSets is the mandatory subset implementation of SEND DIAGNOSTIC
   command. SEND DIAGNOSTIC requests the target to perform diagnostic
   operations on itself. Here is only mandatory implementation of this
   command: self-test feature with the  parameter list length of zero.
   Full command implementation (with page structure) is OPTIONAL.
   DOFF=TRUE (Device Off-line) and UOFF=TRUE (Unit Off-line) flags grant
        permission to perform vendor-specific diagnostic operations on the
        target that may be visible to attached initiators, e.g. writings
        to the user accessible medium, or repositioning of the medium on
        sequential access devices.  Setting this flags FALSE prohibits all
        diagnostic operations that may be detected by other I/O processes.}
function TCdRom.SCSIselfTest(DOFF, UOFF : BOOLEAN) : BOOLEAN;
   var I : DWORD;
   begin
      I := $40000;
      if DOFF then I := I OR $20000;
      if UOFF then I := I OR $10000;
      result := ASPIsend6($1D, I, 0, NIL, 0, SRB_NODIR, ShortTimeout);
   end;


 { READ CAPACITY command returns logical block address and block length
   (in bytes) of the last valid logical block of the logical unit for seek
   operations. BlkCount may be greater (up to +75) than or equal to the
   last readable or playable block. If greater, this address may be in a
   transition area beyond the last valid logical block for read or audio
   play operations because the CD-ROM TOC (table of contents) lead-out
   track location  has a +/- 75 sector tolerance when the lead-out track
   is encoded as an audio track. }
function TCdRom.SCSIreadCapacity(var BlkCount, BlkSize : DWORD) : BOOLEAN;
   var cd  : array[0..1] of DWORD;
   begin
      FillChar(cd,  sizeof(cd),  0);
      result := ASPIsend10($25, 0,0,0,0, @cd,8, SRB_DIR_IN, ShortTimeout);
      BlkCount := BigEndianD(cd[0]);
      BlkSize  := BigEndianD(cd[1]);
   end;
 { READ CAPACITY command with enabled partial medium feature returns
   logical block address and block length (in bytes) of the last logical
   block address after which a substantial delay in data transfer will be
   encountered. This logical block address shall be greater than or equal
   to the logical block address specified in GLBA parameter.
   On CD-ROM media, this is interpreted as being the last readable or
   playable logical block beyond the specified GLBA.
   NOTE: This option may take several seconds to complete.    }
function TCdRom.SCSIreadCapacityPM(Partition : WORD; GLBA : DWORD;
                                var BlkCount, BlkSize : DWORD) : BOOLEAN;
   var cd  : array[0..1] of DWORD;
   begin
      FillChar(cd,  sizeof(cd),  0);
      result := ASPIsend10($25,0,GLBA,0,((Partition AND $7F) SHL 1) OR 1,
                                       @cd, 8, SRB_DIR_IN, LongTimeout);
      BlkCount := BigEndianD(cd[0]);
      BlkSize  := BigEndianD(cd[1]);
   end;


 { READ(10) command requests data from the target.
   DPO (Disable Page Out) flag is used to control replacement of logical
       blocks in the device's cache memory when the host has information
       on the future usage of the logical blocks.
       DPO = TRUE indicates that the target shall assign the logical
       blocks accessed the lowest caching priority. It overrides any
       retention priority specified in the cache page. If the DPO = TRUE,
       the host knows the logical blocks are not likely to be accessed
       again in the near future and should not be put in the cache
       memory nor retained by the cache memory.
       DPO = FALSE means that the host expects that logical blocks
       accessed by this command are likely to be accessed again in the
       near future and the priority shall be determined by the retention

⌨️ 快捷键说明

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