📄 mbdrvlib.pas
字号:
begin
fillchar(lsrb, sizeof(lsrb), 0);
lsrb.Command := SC_GET_DISK_INFO;
lsrb.HaId := fHaID;
lsrb.Target := fTarget;
SendASPI32Command (@lsrb);
result := lsrb.Status = SS_COMP;
end;
{******************************************************************************}
{ }
{******************************************************************************}
constructor TSCSIDevice.Create;
begin
inherited Create(AOwner);
CriticalSection := TCriticalSection.Create;
fErasing := False;
fHaid := 254;
fTarget := 254;
fLun := 254;
fDoDebug := False;
fDevices := TStringList.Create;
if GetASPIInitialized then
begin
GetHostAdapterInfo(0);
ScanDevices;
end;
end;
{******************************************************************************}
{ FormatUnit }
{******************************************************************************}
function TSCSIDevice.FormatUnit(FormatCode: Byte; Buffer: PChar; Length: Integer): Boolean;
var
lsrb: TSRB_ExecSCSICmd;
begin
fillchar(lsrb, sizeof(lsrb), 0);
lsrb.Flags := $50;
lsrb.CDBLen := $6;
lsrb.SenseLen := SENSE_LEN;
lsrb.BufLen := Length;
lsrb.BufPointer := @Buffer[0];
lsrb.CDBCmd := $04;
lsrb.CDBByte[1] := FormatCode;
ExecScsiCommand(lsrb, 10000);
result := lsrb.Status = SS_COMP;
end;
{******************************************************************************}
{ }
{******************************************************************************}
destructor TSCSIDevice.Destroy;
begin
fDevices.Free;
CriticalSection.Destroy;
Inherited;
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.Rewind;
var
lsrb: TSRB_ExecSCSICmd;
begin
fillchar(lsrb, sizeof(lsrb), 0);
lsrb.Flags := SRB_EVENT_NOTIFY;
lsrb.CDBLen := 06;
lsrb.CDBCmd := $01;
lsrb.SenseLen := SENSE_LEN;
ExecScsiCommand(lsrb, 10000);
end;
function TSCSIDevice.GetHostAdapterInfo;
begin
fillchar(fHAInquiry, sizeof(fHAInquiry), 0);
fHAInquiry.Command := SC_HA_INQUIRY;
fHAInquiry.HaId := ha;
SendASPI32Command (@fHAInquiry);
if fHAInquiry.Status =1 then
result := fHAInquiry.HA_Count
else
result := -1;
fAdapters := result;
if fAdapters = 0 then fAdapters := 7;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.AbortSCSICommand;
begin
fillchar(fSCAbort, sizeof(fSCAbort), 0);
fSCAbort.Command := SC_ABORT_SRB;
fSCAbort.HaID := fHaID;
fSCAbort.ToAbort := @srb;
//SendASPI32Command (@fSCAbort);
result := fSCAbort.Status = 1;
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.SetDeviceID;
var
P: String;
v: String;
begin
if Length(Value) < 5 then
begin
if Value <> '' then
DebugMsg(ERR_INVALIDDEVICE, mtUNKNOWN);
fHaID := 254;
fTarget := 254;
fLun := 254;
fDevice := '';
fDeviceName := '';
fDeviceType := 127;
end
else
begin
try
fHaID := StrToInt(Value[1]);
fTarget := StrToInt(Value[3]);
fLun := StrToInt(Value[5]);
fDevice := Value;
DeviceChanged;
if (fInquiryData.PeripheralData = 5) or (fInquiryData.PeripheralData = 4) then
begin
p := fInquiryData.ProductID;
p := Trim(p);
v := fInquiryData.VendorID;
v := Trim(v);
if (P = 'CD-W512EB') then
TEAC512EB := true
else
TEAC512EB := False;
if (P = 'CRX175E') or (P = 'CD-RW CRX800E') then
SonyPowerBurn := True
else
SonyPowerBurn := False;
If length(V)<3 then
V:=' ';
if
((P[1] = 'U') and (P[2] = 'J') and (P[3] = 'D') and (P[4] = 'A')) or
((V[1] = 'T') and (V[2] = 'D') and (V[3] = 'K')) then
Wait02 := True
else
Wait02 := False;
if (P = 'CD-RW CRX100E') then
SonyCRX100E := True
else
SonyCRX100E := False;
if (P = 'CDRW321040X') then
fImmedCT := False
else
fImmedCT := True;
if (fInquiryData.ProductID = 'DVD-RW DVR-103 ') or (fInquiryData.ProductID = 'DVD-RW DVR-104 ') then
begin
PDVR103 := True;
fImmedCT := True;
end
else
PDVR103 := False;
if Assigned(fOnDeviceChange) then
fOnDeviceChange(Self);
GetWriteMethods;
end
else
begin
DebugMsg(ERR_INVALIDDEVICE, mtUNKNOWN);
fDevice := '';
fDeviceName := '';
fDeviceType := 127;
fHaID := 254;
fTarget := 254;
fLun := 254;
end;
except
DebugMsg(ERR_INVALIDDEVICE, mtUNKNOWN);
fDevice := '';
fDeviceName := '';
fDeviceType := 127;
fHaID := 254;
fTarget := 254;
fLun := 254;
end;
end;
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.DeviceChanged;
var
str: String;
i: Integer;
begin
GetDeviceCapabilities;
if Inquiry then
begin
fDeviceType := fInquiryData.PeripheralData;
with fInquiryData do
begin
for i:= 8 to 15 do if VendorID[i] < #32 then VendorID[i] := #32;
for i:= 16 to 31 do if ProductID[i] < #32 then ProductID[i] := #32;
for i:= 32 to 35 do if ProductRev[i] < #32 then ProductRev[i] := #32;
for i:= 36 to 55 do if VendorSpecific[i] < #32 then VendorSpecific[i] := #32;
end;
Str := fInquiryData.VendorID+' '+fInquiryData.ProductID+' '+fInquiryData.ProductRev;
fDeviceName := Str;
end
else
fDeviceName := ErrorString;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.GetAspiError(Status, HaStat, TargStat : BYTE) : String;
begin
fTargetBusy := False;
result := ERR_UNKNOWN;
case Status of
0,1: result := ERR_NONE;
2,3: result := ERR_ABORTED;
$80: result := ERR_INVALIDREQUEST;
$81: result := ERR_INVALIDHA;
$82: result := ERR_NODEVICE;
$E0: result := ERR_INVALIDSRB;
$E1: result := ERR_BUFFERALIGNMENT;
$E5: result := ERR_ASPIBUSY;
$E6: result := ERR_BUFFERTOOBIG;
4: case HaStat of
$09: result := ERR_TIMEOUT;
$0B: result := ERR_SRBTIMEOUT;
$0D: result := ERR_MESSAGEREJECT;
$0E: result := ERR_BUSRESET;
$0F: result := ERR_PARITYERR;
$10: result := ERR_REQUESTSENSEFAILED;
$11: result := ERR_SELECTIONTIMEOUT;
$12: result := ERR_DATAOVERRUN;
$13: result := ERR_UNEXPECTEDBUSFREE;
$00: case TargStat of
0,2: result := ERR_CHECKCONDITION;
$08: begin result := ERR_TARGETBUSY; fTargetBusy := True; end;
$18: result := ERR_TARGETCONFLICT;
$28: result := ERR_QUEFULL;
end;
end;
end;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.AdditionalSenseInformation(scm : TSRB_ExecSCSICmd): String;
var
s: TSenseArea;
ErrStr: String;
begin
s := scm.SenseArea;
ErrStr := '';
{$I asc_info.inc}
fLastSense := s;
if ErrStr = '' then ErrStr := IntToStr(s.AddSenseCode)+','+IntToStr(s.AddSenQual);
if s.AddSenLen <> 0 then
fErrorString := fErrorString + ' ('+ErrStr+')';
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.DecodeSense(scm : TSRB_ExecSCSICmd): String;
var
s: TSenseArea;
begin
s := scm.SenseArea;
Result := GetAspiError(scm.Status, scm.HaStat, scm.TargStat);
if (Result = ERR_CHECKCONDITION) then
if s.ErrorCode = 0 then
Result := ERR_NONE
else
if (s.ErrorCode AND $7E) <> $70 then Result := ERR_UNKNOWN
else
case (s.SenseKey AND $0F) of
0:
begin
if (s.SenseKey AND $80) <> 0 then Result := ERR_FILEMARK
else if (s.SenseKey AND $40) <> 0 then Result := ERR_ENDOFMEDIA
else if (s.SenseKey AND $20) <> 0 then Result := ERR_ILLEGALLENGTH
else if (s.SenseKey AND $80) <> 0 then Result := ERR_INCORRECTLENGTH
else Result := ERR_AS_00_00;
end;
1 : Result := ERR_RECOVEREDERROR;
2 : Result := ERR_NOTREADY;
3 : Result := ERR_MEDIUMERROR;
4 : Result := ERR_HARDWAREERROR;
5 : Result := ERR_ILLEGALREQUEST;
6 : Result := ERR_UNITATTENTION;
7 : Result := ERR_DATAPROTECT;
8 : Result := ERR_ERASECHECK;
10: Result := ERR_COPYABORTED;
11: Result := ERR_ABORTEDCOMMAND;
13: Result := ERR_VOLUMEOVERFLOW;
14: Result := ERR_MISCOMPARE;
15: Result := ERR_RESERVED;
end;
fErrorString := Result;
AdditionalSenseInformation(scm);
end;
{******************************************************************************}
{ Execute Scsi Command }
{******************************************************************************}
function TSCSIDevice.ExecScsiCommand;
var
Event: THandle;
EventNotify: Boolean;
{$IFDEF DEBUG}
i: Integer;
s: String;
{$ENDIF}
begin
fErrorString := '';
Event := 0;
fTargetBusy := False;
FillChar(fLastSense, sizeof(fLastSense), 0);
if (not GetASPIInitialized) or (fHaID = 254) then
begin
result := $E2;
exit;
end;
EventNotify := sc.Flags and $40 = $40;
if EventNotify then
begin
Event := CreateEvent(nil, true, false, nil);
ResetEvent(Event);
sc.PostProc := Event;
end
else
sc.PostProc := 0;
sc.Command := SC_EXEC_SCSI_CMD;
sc.Target := fTarget;
sc.HaId := fHaID;
sc.Lun := fLun;
sc.SenseLen := SENSE_LEN;
if Timeout <= 10000 then
Timeout := 10000;
sc.CDBByte[1] := ((fLun AND 7) SHL 5) OR (sc.CDBByte[1] AND $1F);
{$DEFINE NOWRITE1}
{$IFDEF NOWRITE}
if (sc.CDBCmd <> $2a) and (sc.CDBCmd <> $5b) and (sc.CDBCmd <> $53) then
SendASPI32Command (@sc)
else
sc.Status := 1;
{$ELSE}
SendASPI32Command (@sc);
{$ENDIF}
if EventNotify then
begin
if sc.status = ss_pending then
WaitForSingleObject(Event, TimeOut);
end;
if (sc.Status <> 1) and (sc.Status <> 0) then
DecodeSense(sc);
if GenerateLogs then
begin
s := IntToStr(sc.HAID)+':'+IntToHex(sc.Target, 1)+':'+IntToStr(sc.Lun)+' <'+IntToHex(sc.Status, 2)+'>'+' ['+IntToHex(sc.BufLen,5)+']';
s := '('+IntToHex(sc.CDBCmd, 2)+') {'+IntToHex(sc.Flags, 2)+'|'+IntToHex(sc.CDBLen, 2)+'} - '+s+' ';
for i:=1 to 15 do s := s + IntTohex(sc.CDBByte[i], 2)+' ';
s := CommandName[sc.cdbCmd]+' '+s+' ';
s := s + '|';
if sc.BufLen <> 0 then
begin
for i:=0 to Min($100, sc.BufLen-1) do s := s + IntTohex(Byte(sc.BufPointer[i]), 2)+' ';
end;
DebugMsg('<<< '+FormatDateTime('nn:ss:zzz ', now)+s + '= '
+IntToHex(sc.HaStat, 2)+' '+ IntToHex(sc.TargStat, 2)+' '+IntToHex(sc.SenseArea.ErrorCode,2)+' '+IntToHex(sc.SenseArea.SenseKey, 2)+' '
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -