📄 mbdrvlib.pas
字号:
OR ((DW SHR 8) AND $0000FF00)
OR ((DW SHR 24) AND $000000FF);
end;
//------------------------------------------------------------------------------
procedure CvtEndians(const Src; var Dest; Count : integer);
var
pSrc,
pDst: PChar;
i : integer;
begin
pSrc := @Src;
pDst := PChar(@Dest) + Count;
for i := 0 to Count-1 do begin
Dec(pDst);
pDst^ := pSrc^;
Inc(pSrc);
end;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.InitializeASPI(InternalFirst: Boolean = False; AspiPath: String = ''): Boolean;
begin
try
result := _InitializeASPI(InternalFirst, AspiPath);
except
result := False;
end;
if result then
begin
GetHostAdapterInfo(0);
ScanDevices;
end;
end;
{******************************************************************************}
{ Set Write Parametes }
{******************************************************************************}
var
ModeSenseBuf1, ModeSenseBuf2: array[0..$200-1] of byte;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.CheckWriteMethod(wm: TWriteMethod): Boolean;
var
s, i: Integer;
begin
Result := False;
fillchar(ModeSenseBuf1, sizeof(ModeSenseBuf1), 0);
fillchar(ModeSenseBuf2, sizeof(ModeSenseBuf2), 0);
if ModeSense10($05, ModeSenseBuf1, SizeOf(ModeSenseBuf1)) then
begin
if ModeSenseBuf1[16] = $05 then s := 16
else if ModeSenseBuf1[8] = $05 then s := 8
else s := 8;
for i :=0 to SizeOf(ModeSenseBuf1)-s-1 do ModeSenseBuf2[i] := ModeSenseBuf1[i+s];
move(ModeSenseBuf2, ModePage05, sizeof(ModePage05));
ModePage05.DBType := $00;
if wm = wmTAO then
ModePage05.WriteType := $01
else if wm = wmSAO then
ModePage05.WriteType := $02
else
begin
ModePage05.DBType := 1;
ModePage05.WriteType := $03;
end;
ModePage05.TrackMode := $10;
ModePage05.SessionFormat := $0;
ModePage05.Res9 := $0;
ModePage05.PauseLen := $9600; // Pause
ModePage05.TrackMode := $0;
move(ModePage05, ModeSenseBuf2, ModePage05.PageLen+s+1);
fillchar(ModeSenseBuf1, SizeOf(ModeSenseBuf1), 0);
for i :=0 to $3c-s do ModeSenseBuf1[i+8] := ModeSenseBuf2[i];
if ModeSelect10(@ModeSenseBuf1[0], ModePage05.PageLen+10) then
Result := True;
end;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.GetWriteMethods: Boolean;
begin
fWriteMethods := [];
if CheckWriteMethod(wmDAO) then Include(fWriteMethods, wmDAO);
if CheckWriteMethod(wmSAO) then Include(fWriteMethods, wmSAO);
if CheckWriteMethod(wmTAO) then Include(fWriteMethods, wmTAO);
result := True;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.GetDriveLetter: Char;
var
fh: THandle;
buf: array[0..63] of char;
tmp: String;
pscsiAddr: PSCSI_ADDRESS;
returned: Cardinal;
DriveLetter: Byte;
begin
result := #0;
if ASPILayerName = 'BMASPI32' then
begin
result := GetDriveLetterBMASPI(fHAID, fTarget, fLUN);
exit;
end;
for DriveLetter := 2 to 26 do
begin
tmp := '\\.\'+Chr(DriveLetter+64)+':'+#0;
fh := CreateFile (@tmp[1], GENERIC_WRITE or GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if ( fh = INVALID_HANDLE_VALUE ) then
fh := CreateFile(@tmp[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 );
if ( fh <> INVALID_HANDLE_VALUE ) then
begin
FillChar(buf, Sizeof(buf), 0);
pscsiAddr := @buf;
pscsiAddr.Length := sizeof(SCSI_ADDRESS);
if ( DeviceIoControl( fh, 266264, nil, 0, pscsiAddr, sizeof(SCSI_ADDRESS), returned, nil ) ) then
begin
if (pscsiAddr.PortNumber = fHAID) and (pscsiAddr.TargetId = fTarget) then
begin
result := Chr(DriveLetter+64);
CloseHandle(fh);
exit;
end;
end;
CloseHandle(fh);
end;
end;
DriveLetter := GetDiskLetter(fHAID, fTarget, fLUN);
if DriveLetter <> 128 then
Result := Chr(DriveLetter+65);
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.Notification(aComponent: TComponent; Operation: TOperation);
begin
inherited Notification(aComponent, Operation);
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.SetDriveLetter(Value: Char);
begin
SetDeviceByDriveLetter(Value);
end;
{******************************************************************************}
{ }
{******************************************************************************}
var
xdi: TSRB_GetDiskInfo;
function TSCSIDevice.SetDeviceByDriveLetter(DriveLetter: Char): Boolean;
var
fh: THandle;
buf: array[0..63] of char;
tmp: String;
pscsiAddr: PSCSI_ADDRESS;
returned: Cardinal;
i, t, l, ha: Integer;
begin
result := False;
tmp := '\\.\'+DriveLetter+':'+#0;
fh := CreateFile (@tmp[1], GENERIC_WRITE or GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if ( fh = INVALID_HANDLE_VALUE ) then
fh := CreateFile(@tmp[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 );
if ( fh = INVALID_HANDLE_VALUE ) then
begin
i := Byte(DriveLetter)-64;
if fDriveLetters[i] <> '' then
begin
Device := fDriveLetters[i];
CloseHandle(fh);
Result := True;
end;
for ha := 0 to fAdapters-1 do
begin
for t:= 0 to 7 do
for l := 0 to 7 do
begin
fillchar(xdi, sizeof(xdi), 0);
xdi.Command := SC_GET_DISK_INFO;
xdi.HaID := ha;
xdi.Target := t;
xdi.Lun := l;
SendASPI32Command (@xdi);
if xdi.Status = 1 then
begin
if xdi.Int13HDriveInfo = Ord(DriveLetter) - 65 then
begin
tmp := IntToStr(ha)+':'+IntToStr(t)+':'+IntToStr(l)+' '+DriveLetter+':';
Device := tmp;
result := True;
exit;
end;
end;
end;
end;
end
else
begin
result := True;
exit;
end;
FillChar(buf, Sizeof(buf), 0);
pscsiAddr := @buf;
pscsiAddr.Length := sizeof(SCSI_ADDRESS);
if ( DeviceIoControl( fh, 266264, nil, 0, pscsiAddr, sizeof(SCSI_ADDRESS), returned, nil ) ) then
begin
tmp := IntToStr(pscsiAddr.PortNumber)+':'+IntToStr(pscsiAddr.TargetId)+':'+IntToStr(pscsiAddr.Lun)+' '+DriveLetter+':';
Device := tmp;
result := True;
end;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.SelectDevice(sDevice: String): Boolean;
begin
Device := sDevice;
Result := True;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.GetDiskLetter(H, T, L: Byte): Byte;
begin
fillchar(xdi, sizeof(xdi), 0);
xdi.Command := SC_GET_DISK_INFO;
xdi.HaID := H;
xdi.Target := T;
xdi.Lun := L;
SendASPI32Command (@xdi);
if xdi.Status = 1 then
result := xdi.Int13HDriveInfo
else
result := 128;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.GetASPIInitialized: Boolean;
begin
result := ASPIDLLLoaded;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.MaxWriteSpeed: Word;
begin
if GetDeviceCapabilities then
result := ModePage2A.MaxWriteSpeed
else
result := 0;
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.SetWriteSpeed;
begin
SetCDSpeed(fReadSpeed, Value);
FWriteSpeed := Value;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.MaxReadSpeed: Word;
begin
if GetDeviceCapabilities then
begin
result := ModePage2A.MaxReadSpeed;
end
else
result := 0;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.CurrentReadSpeed;
begin
if GetDeviceCapabilities then
result := ModePage2A.CurReadSpeed
else
result := 0;
end;
{******************************************************************************}
{ }
{******************************************************************************}
function TSCSIDevice.CurrentWriteSpeed: Word;
begin
if GetDeviceCapabilities then
result := ModePage2A.CurWriteSpeed
else
result := 0;
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.ScanDevices;
var
ha, t, l: Integer;
llun, lha, lt: Integer;
str: String;
sDrvLtr: String;
begin
fDevices.Clear;
lha := fHaID;
lt := fTarget;
llun := fLun;
fLun := 0;
if DoDebug then DebugMsg('>>> '+ASPILayerName, mtMESSAGE);
for ha := 0 to fAdapters-1 do
begin
GetHostAdapterInfo(ha);
str := fHAInquiry.HA_Identifier;
str := trim(str);
if DoDebug then DebugMsg('>>> '+fHAInquiry.HA_ManagerId+' ('+str+')', mtMESSAGE);
for t:= 0 to 7 do
for l := 0 to 7 do
begin
fHaID := ha;
fTarget := t;
fLUN := l;
FillChar(fInquiryData, SizeOf(fInquiryData), 0);
if Inquiry then
begin
//Str := IntToStr(ha)+':'+IntToStr(t)+':'+IntToStr(l)+' - '+fInquiryData.VendorID+' '+fInquiryData.ProductID+' '+fInquiryData.ProductRev; //Writeln(str);
if (fInquiryData.PeripheralData = 5) or (fInquiryData.PeripheralData = 4) then
begin
sDrvLtr := GetDriveLetter;
if sDrvLtr = #0 then
sDrvLtr := '?:'
else
sDrvLtr := sDrvLtr+':';
Str := IntToStr(ha)+':'+IntToStr(t)+':'+IntToStr(l)+','+sDrvLtr+' '+fInquiryData.VendorID+''+fInquiryData.ProductID+''+fInquiryData.ProductRev;
if fInquiryData.PeripheralData = 4 then
Str := Str + ' (not supported)';
fDevices.Add(str);
end;
end;
end;
end;
fHaID := lha;
fTarget := lt;
fLUN := llun;
{ if fDevices.Count > 0 then SetDeviceID(fDevices[0]);} // auto select first device if any
fErrorString := '';
ErrorString := '';
end;
{******************************************************************************}
{ }
{******************************************************************************}
procedure TSCSIDevice.DebugMsg;
begin
if Assigned(fOnDebugMsg) then
fOnDebugMsg(Self, Msg, mType);
end;
{******************************************************************************}
{ Get Disk Information }
{******************************************************************************}
function TSCSIDevice.GetDiskInformation: Boolean;
var
lsrb: TSRB_GetDiskInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -