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

📄 taspidev.pas

📁 使用ASPI读SCSI/IDE/ATAPI的CDROM数据或音乐磁道数据的程序
💻 PAS
📖 第 1 页 / 共 3 页
字号:
       SenseKeys := SRB_Sense[2];
       case (SenseKeys AND $0F) of
        0: begin                                    // Skey_NoSense
             if (SenseKeys AND $80) <> 0            // FileMark flag
              then fLastError := Err_SenseFileMark
             else if (SenseKeys AND $40) <> 0       // EndOfMedia flag
              then fLastError := Err_SenseEndOfMedia
             else if (SenseKeys AND $20) <> 0       // IllegalLength flag
              then fLastError := Err_SenseIllegalLength
             else if (SRB_Sense[3] AND $80) <> 0    // ResidualCount < 0
              then fLastError := Err_SenseIncorrectLength
             else  fLastError := Err_SenseNoSense;
           end;
        1: fLastError := Err_SenseRecoveredError;  //Skey_RecoveredError
        2: fLastError := Err_SenseNotReady;        //Skey_NotReady
        3: fLastError := Err_SenseMediumError;     //Skey_MediumError
        4: fLastError := Err_SenseHardwareError;   //Skey_HardwareError
        5: fLastError := Err_SenseIllegalRequest;  //Skey_IllegalRequest
        6: fLastError := Err_SenseUnitAttention;   //Skey_UnitAttention
        7: fLastError := Err_SenseDataProtect;     //Skey_DataProtect
        8: fLastError := Err_SenseBlankCheck;      //Skey_BlankCheck
        9: fLastError := Err_SenseVendorSpecific;  // Skey_VendorSpecific
        10:fLastError := Err_SenseCopyAborted;     // Skey_CopyAborted
        11:fLastError := Err_SenseAbortedCommand;  // Skey_AbortedCommand
        12:fLastError := Err_SenseEqual;           // Skey_Equal
        13:fLastError := Err_SenseVolumeOverflow;  // Skey_VolumeOverflow
        14:fLastError := Err_SenseMiscompare;      // Skey_Miscompare
        15:fLastError := Err_SenseReserved;        // Skey_Reserved
   end; end;
   result := (fLastError = Err_None) OR
             (fLastError = Err_SenseRecoveredError);
end;

function TASPIDevice.ASPIsend6(OpCode: BYTE; Lba : DWORD; Byte4 : BYTE;
        Pbuf: pointer; BufLen: DWORD; Direction,Timeout: DWORD) : BOOLEAN;
   var cdb : array[0..5] of BYTE;
   begin
      FillChar(Pbuf^, BufLen, 0);
      cdb[5] := 0;
      cdb[4] := Byte4;
      cdb[3] := BYTE(Lba AND $FF);    Lba := Lba SHR 8;
      cdb[2] := BYTE(Lba AND $FF);    Lba := Lba SHR 8;
      cdb[1] := ((fDeviceID.Lun AND 7) SHL 5) OR BYTE(Lba AND $1F);
      cdb[0] := OpCode;
      result := ASPIsendScsiCommand(@cdb,6,Pbuf,BufLen,Direction,Timeout);
   end;

function TASPIDevice.ASPIsend10(OpCode : BYTE;
        Byte1 : BYTE; Lba : DWORD; Byte6 : BYTE; Word7 : WORD;
        Pbuf: pointer; BufLen: DWORD; Direction,Timeout: DWORD) : BOOLEAN;
   var cdb : array[0..9] of BYTE;
   begin
      FillChar(Pbuf^, BufLen, 0);
      cdb[9] := 0;
      cdb[8] := BYTE(Word7 AND $FF);    Word7 := Word7 SHR 8;
      cdb[7] := BYTE(Word7 AND $FF);
      cdb[6] := Byte6;
      cdb[5] := BYTE(Lba AND $FF);    Lba := Lba SHR 8;
      cdb[4] := BYTE(Lba AND $FF);    Lba := Lba SHR 8;
      cdb[3] := BYTE(Lba AND $FF);    Lba := Lba SHR 8;
      cdb[2] := BYTE(Lba AND $FF);
      cdb[1] := ((fDeviceID.Lun AND 7) SHL 5) OR (Byte1 AND $1F);
      cdb[0] := OpCode;
      result := ASPIsendScsiCommand(@cdb,10,Pbuf,BufLen,Direction,Timeout);
   end;

function TASPIDevice.ASPIsend12(OpCode : BYTE;
      Byte1 : BYTE; Lba : DWORD; TLength : DWORD; Byte10 : BYTE;
      Pbuf : pointer; BufLen : DWORD; Direction,Timeout : DWORD) : BOOLEAN;
   var cdb : array[0..11] of BYTE;
   begin
      FillChar(Pbuf^, BufLen, 0);
      cdb[11]:= 0;
      cdb[10]:= Byte10;
      cdb[9] := BYTE(TLength AND $FF);   TLength := TLength SHR 8;
      cdb[8] := BYTE(TLength AND $FF);   TLength := TLength SHR 8;
      cdb[7] := BYTE(TLength AND $FF);   TLength := TLength SHR 8;
      cdb[6] := BYTE(TLength AND $FF);
      cdb[5] := BYTE(Lba AND $FF);       Lba := Lba SHR 8;
      cdb[4] := BYTE(Lba AND $FF);       Lba := Lba SHR 8;
      cdb[3] := BYTE(Lba AND $FF);       Lba := Lba SHR 8;
      cdb[2] := BYTE(Lba AND $FF);
      cdb[1] := ((fDeviceID.Lun AND 7) SHL 5) OR (Byte1 AND $1F);
      cdb[0] := OpCode;
      result := ASPIsendScsiCommand(@cdb,12,Pbuf,BufLen,Direction,Timeout);
   end;


function TASPIDevice.ASPIresetDevice : BOOLEAN;   // Resets 'current' device
   type
      SRB_ResetDevice = packed record
         SRB_Cmd      : BYTE;    // ASPI command code = 4 = SC_RESET_DEV
         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's SCSI ID
         SRB_Lun      : BYTE;    // Target's LUN number
         SRB_Rsvd1    : array[0..11] of BYTE; // Reserved for Alignment
         SRB_HaStat   : BYTE;    // Host Adapter Status
         SRB_TargStat : BYTE;    // Target Status
         SRB_PostProc : THandle; // Post routine
         SRB_Rsvd2    : POINTER; // Reserved
         SRB_Rsvd3    : array[0..31] of BYTE;  // Reserved for alignment
      end;
var
   Rsrb   : SRB_ResetDevice;
   hEvent : THandle;
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(Rsrb, sizeof(Rsrb), 0);
   with Rsrb do begin
      SRB_Cmd      := 4;  { SC_RESET_DEV }
      SRB_HaId     := fDeviceID.Adapter;
      SRB_Target   := fDeviceID.Target;
      SRB_Lun      := fDeviceID.Lun;
      SRB_PostProc := hEvent;
   end;
   if SendASPI32Command(@Rsrb) = 0 { SS_PENDING } then begin
      if WaitForSingleObject(hEvent,fShortTimeout) <> WAIT_OBJECT_0
       then begin
         fLastError := Err_NotifyTimeout;
         ASPIabortCommand(Rsrb.SRB_HaId, @Rsrb);
      end;
   end else fLastError := Err_NoDevice;  {ASPI DLL says:"No such device"}
   CloseHandle(hEvent);
   if fLastError = Err_None then with Rsrb do
      Result := GetAspiError(SRB_Status, SRB_HaStat, SRB_TargStat);
end;


function TASPIDevice.ASPIgetDriveInt13info(DeviceAddress : TDeviceID;
               var Support, DosSupport : BOOLEAN;
               var DriveNumber, Heads, Sectors : BYTE) : BOOLEAN;
   type
      SRB_Int13info = packed record
         SRB_Cmd        : BYTE;  // ASPI command code=6=SC_GET_DIISK_INFO
         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's SCSI ID
         SRB_Lun        : BYTE;  // Target's LUN number
         SRB_DriveFlags : BYTE;  // Driver flags
         SRB_Int13Drive : BYTE;  // Host Adapter Status
         SRB_Heads      : BYTE;  // Preferred number of heads translation
         SRB_Sectors    : BYTE;  // Preferred number of sectors translation
         SRB_Rsvd       : array[0..9] of BYTE;  // Reserved
      end;
   var Isrb : SRB_Int13info;
   begin
      FillChar(Isrb, sizeof(Isrb), 0);
      Isrb.SRB_Cmd      := 6;
      Isrb.SRB_HaId     := DeviceAddress.Adapter;
      Isrb.SRB_Target   := DeviceAddress.Target;
      Isrb.SRB_Lun      := DeviceAddress.Lun;
      SendASPI32Command(@Isrb);
      with Isrb do begin
         Result := GetAspiError(SRB_Status, $FF, $FF);
         Support    := Result AND ((SRB_DriveFlags AND 3) <> 0);
         DosSupport := Result AND ((SRB_DriveFlags AND 1) <> 0);
         DriveNumber:= SRB_Int13Drive;
         Heads      := SRB_Heads;
         Sectors    := SRB_Sectors;
   end; end;

function  TASPIDevice.GetDeviceInfo(DId : TdeviceID;
                          var DInfo : TScsiDeviceInfo) : BOOLEAN;
   const BufLen = 100;
   type CDdeviceInfo = packed record
          B   : array[0..7]  of byte;
          s1  : array[0..7]  of char;
          s2  : array[0..15] of char;
          s3  : array[0..3]  of char;
          s4  : array[0..19] of char;
          Rest: array[0..BufLen-57] of byte;
      end;
   var
      Buf    : CDdeviceInfo;
      TempID : TdeviceID;
   begin
      TempID    := fDeviceID;
      fDeviceID := DId;
      FillChar(Buf, BufLen, 0);
      result := ASPIsend6($12, 0, BufLen, @Buf, BufLen,
               SRB_DIR_IN, ShortTimeout);        // SCSI Inquiry command
      if LastError = Err_None then with DInfo do begin
         PeripheralQualifier  :=  Buf.B[0] SHR 5;
         DeviceType           :=  Buf.B[0] AND $1F;
         DeviceTypeModifier   :=  Buf.B[0] AND $7F;
         RemovableMedium      := (Buf.B[1] AND $80) <> 0;
         ISOversion           := (Buf.B[2] SHR 6) AND 3;
         ECMAversion          := (Buf.B[2] SHR 3) AND 7;
         ANSIversion          :=  Buf.B[2] AND 7;
         AsyncEventCapability := (Buf.B[3] AND $80) <> 0;
         TerminateIOcapability:= (Buf.B[3] AND $80) <> 0;
         ResponseDataFormat   :=  Buf.B[3] AND $0F;
         AdditionalDataLength :=  Buf.B[4];
         WideBus32capability           := (Buf.B[7] AND $40) <> 0;
         WideBus16capability           := (Buf.B[7] AND $20) <> 0;
         RelativeAddressingCapability  := (Buf.B[7] AND $80) <> 0;
         SynchronousTransferCapability := (Buf.B[7] AND $10) <> 0;
         LinkedCommandsCapability      := (Buf.B[7] AND $08) <> 0;
         CommandQueuingCapability      := (Buf.B[7] AND $02) <> 0;
         SoftResetCapability           := (Buf.B[7] AND $01) <> 0;
         ASPIstrCopy(Buf.s1, VendorID,  8);
         ASPIstrCopy(Buf.s2, ProductID, 16);
         ASPIstrCopy(Buf.s3, ProductRevision, 4);
         ASPIstrCopy(Buf.s4, VendorSpecific, 20);
      end;
      fDeviceID := TempID;
   end;

procedure TASPIDevice.ChangeDevice(Value : TdeviceID);
   begin
      fDeviceID   := Value;
      ASPIgetDeviceType(Value, fDeviceType);
      GetDeviceInfo(Value, fDeviceInfo);
      ASPIhaInquiry(Value.Adapter, fHAinfo);
   end;

procedure TASPIDevice.SetDeviceID(Value : TdeviceID);
   var Dtype : TScsiDeviceType;
   begin
      if ASPIgetDeviceType(Value, Dtype) then   // if device exist
       if Dtype < TSDInvalid then ChangeDevice(Value);
   end;

function  TASPIDevice.EnumDevices(DType : TScsiDeviceType;
                                  CBack : TCallBackProc) : integer;
   var
      TID, DID                : TDeviceID;
      DIDtype                 : TScsiDeviceType;
      Dadapter, Dtarget, Dlun : BYTE;
   begin
      result := 0;
      if fHAcount = 0 then exit;    // no ASPI hosts, no devices
      TID := fDeviceID;
      for Dadapter := 0 to fHAcount-1 do
       if ASPIhaInquiry(Dadapter, fHAinfo) then begin
         DID.Adapter := Dadapter;
         for Dtarget := 0 to fHAinfo.MaxTargetCount-1 do begin
            DID.Target := Dtarget;
            for Dlun := 0 to 7 do begin
               DID.Lun := Dlun;
               if ASPIgetDeviceType(DID, DIDtype) then  // if device exist
                if (DIDtype = DType) OR                 //  and type match
                  ((DIDtype < TSDInvalid) AND (DType = TSDAny))
                   then begin
                  SetDeviceID(DID);
                  CBack;
                  Inc(result);
               end;   { if }
            end;      { for Dlun }
         end;      { for Dtarget }
      end;        { for Dadapter }
      ChangeDevice(TID);           // even if it has Invalid type !
   end;

end.

⌨️ 快捷键说明

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