📄 taspidev.pas
字号:
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 + -