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

📄 taspidev.pas

📁 使用ASPI读SCSI/IDE/ATAPI的CDROM数据或音乐磁道数据的程序
💻 PAS
📖 第 1 页 / 共 3 页
字号:
        property ShortTimeout : DWORD read fShortTimeout  write fShortTimeout;
        property MediumTimeout: DWORD read fMediumTimeout write fMediumTimeout;
        property LongTimeout  : DWORD read fLongTimeout   write fLongTimeout;
        property AudioTimeout : DWORD read fAudioTimeout  write fAudioTimeout;
           // Set AudioTimeout corresponding to CD-ROM audio control  page
           // parameter IMM. It shall be equal to ShortTimeout when IMM=TRUE
           // and greater then estimated playback time elsewhere.
      end;

function GetASPI32SupportInfo               : DWORD; stdcall;
function SendASPI32Command(LPSRB : pointer) : DWORD; stdcall;
function BigEndianW(Arg : WORD)          : WORD;
function BigEndianD(Arg : DWORD)         : DWORD;
function GatherWORD(b1,b0 : byte) : WORD;
function GatherDWORD(b3,b2,b1,b0 : byte) : DWORD;


implementation
function GetASPI32SupportInfo; external 'WNASPI32' name 'GetASPI32SupportInfo';
function SendASPI32Command;    external 'WNASPI32' name 'SendASPI32Command';

function BigEndianW(Arg : WORD) : WORD;
   begin  result := ((Arg SHL 8) AND $FF00) OR
                    ((Arg SHR 8) AND $00FF);    end;
function BigEndianD(Arg : DWORD) : DWORD;
   begin
      result := ((Arg SHL 24) AND $FF000000) OR
                ((Arg SHL  8) AND $00FF0000) OR
                ((Arg SHR  8) AND $0000FF00) OR
                ((Arg SHR 24) AND $000000FF);
   end;
function GatherWORD(b1,b0 : byte) : WORD;
   begin
      result := ((WORD(b1) SHL 8) AND $FF00) OR
                ((WORD(b0)      ) AND $00FF);
   end;
function GatherDWORD(b3,b2,b1,b0 : byte) : DWORD;
   begin
      result := ((LongInt(b3) SHL 24) AND $FF000000) OR
                ((LongInt(b2) SHL 16) AND $00FF0000) OR
                ((LongInt(b1) SHL  8) AND $0000FF00) OR
                ((LongInt(b0)       ) AND $000000FF);
   end;

function TASPIDevice.GetAspiError(Status,HaStat,TargStat: BYTE): BOOLEAN;
   begin
      result     := false;
      fLastError := Err_None;
      case Status of
         0,1: result := true;              // No error, all OK
         2,3: fLastError := Err_Aborted;
         $80: fLastError := Err_InvalidRequest;   // This command is
                                    // not supported by ASPI manager
         $81: fLastError := Err_InvalidHostAdapter;
         $82: fLastError := Err_NoDevice;
         $E0: fLastError := Err_InvalidSrb;
         $E1: fLastError := Err_BufferAlign;
         $E5: fLastError := Err_AspiIsBusy;
         $E6: fLastError := Err_BufferTooBig;
         4: case HaStat of
            $09 : fLastError := Err_CommandTimeout;
            $0B : fLastError := Err_SrbTimeout;
            $0D : fLastError := Err_MessageReject;
            $0E : fLastError := Err_BusReset;
            $0F : fLastError := Err_ParityError;
            $10 : fLastError := Err_RequestSenseFailed;
            $11 : fLastError := Err_SelectionTimeout;
            $12 : fLastError := Err_DataOverrun;
            $13 : fLastError := Err_UnexpectedBusFree;
            $14 : fLastError := Err_BusPhaseSequence;
            $00 : case TargStat of
               0,2: fLastError := Err_CheckCondition;
               $08: fLastError := Err_TargetBusy;
               $18: fLastError := Err_TargetReservationConflict;
               $28: fLastError := Err_TargetQueueFull
               else fLastError := Err_Unknown;
              end
            else    fLastError := Err_Unknown;
          end
       else         fLastError := Err_Unknown;
   end; end;


procedure ASPIstrCopy(Src : PChar; var Dst : ShortString; Leng : Integer);
   var i : integer;
   begin
      i := 0;
      while (i < Leng) AND (Src[i] >= ' ') do
        begin  Dst[i+1] := Src[i];   inc(i);   end;
      Dst[0] := CHR(i);
   end;

constructor  TASPIDevice.Create;
   var I : DWORD;
   begin
      inherited Create;
      I := GetASPI32SupportInfo;
      if (I AND $0000FE00) <> 0 then fHAcount := 0
                                else fHAcount := I AND $000000FF;
      FillChar(fSense, sizeof(fSense), 0);
      fLastError        := Err_None;
      fShortTimeout     := 1000;     // 1 sec
      fMediumTimeout    := 60000;    // 1 min
      fLongTimeout      := 3600000;  // 1 hour
      fAudioTimeout     := fShortTimeout;
      fDeviceID.Adapter := $81;      // Invalid host adapter
      fDeviceID.Target  := 0;
      fDeviceID.Lun     := 0;
      fDeviceType       := TSDInvalid;
   end;

destructor   TASPIDevice.Destroy;
   begin  inherited Destroy;  end;


function TASPIDevice.ASPIhaInquiry(HaId : BYTE;
               var sh : TScsiHAinfo) : BOOLEAN;             //True if OK
   type SRB_Inquiry = packed record
        SRB_Cmd       : BYTE;    // ASPI command code = 0 = SC_HA_INQUIRY
        SRB_Status    : BYTE;    // ASPI command status byte
        SRB_HaId      : BYTE;    // ASPI host adapter number
        SRB_Flags     : BYTE;    // Reserved
        SRB_Hdr_Rsvd  : DWORD;   // Reserved
        SRB_HA_Count  : BYTE;    // same as in GetASPIsupportInfo
        SRB_HA_SCSIID : BYTE;    // SCSI Id of selected host adapter
        SRB_ManagerID,                   // MustBe = 'ASPI for WIN32'
        SRB_AdapterID                    // String describing selected HA
                : array[0..15] of char;
        SRB_BufAlign  : WORD;  // Buffer alignment mask: 0=byte, 1=word,
                                         // 3=dword, 7=8-byte, etc. 65536 bytes max
        SRB_Residual  : BYTE;    // Bit1 = residual count support flag
        SRB_Targets   : BYTE;    // Max target count for selected HA
        SRB_TransfLen : DWORD;   // Max transfer length in bytes
        SRB_Rsvd : array[0..9] of byte;
     end;
   var Isrb : SRB_Inquiry;
   begin
      FillChar(Isrb, sizeof(Isrb), 0);
      Isrb.SRB_Cmd      := 0;
      Isrb.SRB_HaId     := HaId;
      SendASPI32Command(@Isrb);
      with Isrb do begin
         Result := GetAspiError(SRB_Status, $FF, $FF);
         sh.ScsiId := SRB_HA_SCSIID;
         ASPIstrCopy(SRB_ManagerID, sh.ScsiManagerId, 16);
         ASPIstrCopy(SRB_AdapterID, sh.HostAdapterId, 16);
         sh.BufferAlignMask := SRB_BufAlign;
         sh.ResidualSupport := (SRB_Residual AND 2) <> 0;
         if SRB_Targets = 0 then sh.MaxTargetCount := 8
                            else sh.MaxTargetCount := SRB_Targets;
         sh.MaxTransferLength := SRB_TransfLen;
   end; end;


function TASPIDevice.ASPIgetDeviceType(DeviceAddress : TDeviceID;
                var SDeviceType : TScsiDeviceType) : BOOLEAN;   //True if OK
   type SRB_GetDeviceType = packed record
        SRB_Cmd       : BYTE;    // ASPI command code = 1 = SC_GET_DEV_TYPE
        SRB_Status    : BYTE;    // ASPI command status byte
        SRB_HaId      : BYTE;    // ASPI host adapter number
        SRB_Flags     : BYTE;    // Reserved
        SRB_Hdr_Rsvd  : DWORD;   // Reserved
        SRB_Target    : BYTE;    // Target number for specified HA
        SRB_Lun       : BYTE;    // Logical unit number of selected target
        SRB_DeviceType: BYTE;    // Selected HA/Target/Lun device type
        SRB_Rsvd      : BYTE;    // Reserved for alignment
     end;
   var Gsrb : SRB_GetDeviceType;
   begin
      FillChar(Gsrb, sizeof(Gsrb), 0);
      Gsrb.SRB_Cmd      := 1;
      Gsrb.SRB_HaId     := DeviceAddress.Adapter;
      Gsrb.SRB_Target   := DeviceAddress.Target;
      Gsrb.SRB_Lun      := DeviceAddress.Lun;
      SendASPI32Command(@Gsrb);
      Result := GetAspiError(Gsrb.SRB_Status, $FF, $FF);
      if Result AND (Gsrb.SRB_DeviceType < ORD(TSDInvalid))
        then SDeviceType := TScsiDeviceType(Gsrb.SRB_DeviceType)
        else SDeviceType := TSDInvalid;
   end;


procedure TASPIDevice.ASPIabortCommand(HaId : BYTE; Psrb : pointer);
   type SRB_Abort = packed record
        SRB_Cmd      : BYTE;    // ASPI command code = 3 = SC_ABORT_SRB
        SRB_Status   : BYTE;    // ASPI command status byte
        SRB_HaId     : BYTE;    // ASPI host adapter number
        SRB_Flags    : BYTE;    // Reserved
        SRB_Hdr_Rsvd : DWORD;   // Reserved
        SRB_ToAbort  : pointer; // Pointer to SRB to abort
     end;
   var  Asrb : SRB_Abort;
   begin
      FillChar(Asrb, sizeof(Asrb), 0);
      Asrb.SRB_Cmd      := 3;
      Asrb.SRB_HaId     := HaId;
      Asrb.SRB_ToAbort  := Psrb;
      SendASPI32Command(@Asrb);
   end;


function TASPIDevice.ASPIsendScsiCommand(Pcdb : pointer; CdbLen : DWORD;
                Pbuf : pointer; BufLen : DWORD;
                Direction,      Timeout: DWORD) : BOOLEAN; //True if OK
   type
      SRB_ExecSCSICmd = packed record
         SRB_Cmd      : BYTE;    // ASPI command code= 2 =SC_EXEC_SCSI_CMD
         SRB_Status   : BYTE;    // ASPI command status byte
         SRB_HaId     : BYTE;    // ASPI host adapter number
         SRB_Flags    : BYTE;    // ASPI request flags
         SRB_Hdr_Rsvd : DWORD;   // Reserved
         SRB_Target   : BYTE;    // Target's SCSI ID
         SRB_Lun      : BYTE;    // Target's LUN number
         SRB_Rsvd1    : WORD;    // Reserved for Alignment
         SRB_BufLen   : DWORD;   // Data Allocation Length
         SRB_BufPtr   : POINTER; // Data Buffer Pointer
         SRB_SenseLen : BYTE;    // Sense Allocation Length
         SRB_CDBLen   : BYTE;    // CDB Length
         SRB_HaStat   : BYTE;    // Host Adapter Status
         SRB_TargStat : BYTE;    // Target Status
         SRB_PostProc : THandle; // Post routine
         SRB_Rsvd2    : POINTER; // Reserved
         SRB_Rsvd3    : array[0..15] of BYTE;  // Reserved for alignment
         SRB_CDBByte  : array[0..15] of BYTE;  // SCSI CDB
         SRB_Sense    : TscsiSenseInfo;        // Request Sense buf
      end;
var
   Esrb      : SRB_ExecSCSICmd;
   hEvent    : THandle;
   SenseKeys : BYTE;
begin
   result := false;
   fLastError := Err_None;
   FillChar(fSense, sizeof(fSense), 0);
   if fDeviceType = TSDInvalid then
     begin  fLastError := Err_InvalidDevice;    exit;  end;
   hEvent := CreateEvent(NIL,true,false,NIL); {event to notify completion}
   if hEvent = 0 then begin  fLastError := Err_NoEvent;  exit;  end;
   ResetEvent(hEvent);
   FillChar(Esrb, sizeof(Esrb), 0);        { Scsi Request Block init }
   with Esrb do begin
      SRB_Cmd      := 2;  { SC_EXEC_SCSI_CMD }
      SRB_HaId     := fDeviceID.Adapter;
      SRB_Flags    := Direction OR $40;   { set SRB_EVENT_NOTIFY flag }
      SRB_Target   := fDeviceID.Target;
      SRB_Lun      := fDeviceID.Lun;
      SRB_BufLen   := BufLen;
      SRB_BufPtr   := Pbuf;
      SRB_SenseLen := sizeof(TscsiSenseInfo) - 2;
      if CdbLen > 16 then SRB_CDBLen := 16 else SRB_CDBLen := CdbLen;
      SRB_PostProc := hEvent;
      Move(Pcdb^, SRB_CDBByte, SRB_CDBLen);
   end;
   if SendASPI32Command(@Esrb) = 0 { SS_PENDING } then begin
      if WaitForSingleObject(hEvent,Timeout) <> WAIT_OBJECT_0 then begin
         fLastError := Err_NotifyTimeout;
         ASPIabortCommand(Esrb.SRB_HaId, @Esrb);
      end;
   end else fLastError := Err_NoDevice;  {ASPI DLL says:"No such device"}
   CloseHandle(hEvent);
   if fLastError = Err_None then with Esrb do begin
      fSense := SRB_Sense;
      GetAspiError(SRB_Status, SRB_HaStat, SRB_TargStat);
   end;
   if fLastError = Err_CheckCondition then with Esrb do
    if SRB_Sense[0] = 0
     then fLastError := Err_None
     else if (SRB_Sense[0] AND $7E) <> $70             // recognized values
      then fLastError := Err_SenseUnknown
      else begin

⌨️ 快捷键说明

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