📄 taspidev.pas
字号:
unit TASPIDEV;
// -----------------------------------------------------------------------------
// Project: CD-ROM and CD-audio Interface Components
// Component Names: TASPIdevice
// Module: TAspiDev
// Description: Implements basic-level interface to wnaspi32.dll
// and some of fundamental functions for SCSI interface,
// that are device-type independent.
// Version: 0.2 early beta
// Date: 25-MAY-1999
// Target: Win32, Delphi3
// Authors: Sergey "KSER" Kabikov, iamkser@hotmail.com
// Copyright (c) 1999 Sergey Kabikov
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Acknowledgements:
// 1. Thanks to Jay A. Key (scsiprog@geocities.com) for his "akrip" program,
// which sources (http://www.geocities.com/SiliconValley/Byte/7125/)
// helps to solve many problems.
// -----------------------------------------------------------------------------
interface
uses Windows;
const {======= Possible values of Direction parameter ========}
SRB_NODIR = $00; // Direction determined by SCSI command
SRB_DIR_IN = $08; // Transfer from SCSI target to host
SRB_DIR_OUT = $10; // Transfer from host to SCSI target
type
TScsiDeviceType = (TSDDisk, TSDTape, TSDPrinter, TSDProcessor,
TSDWORM, TSDCDROM, TSDScanner, TSDOptical,
TSDChanger, TSDCommunication, TSDInvalid, TSDAny);
var
TScsiDeviceTypeName : array[TScsiDeviceType] of string = ('Disk Drive',
'Tape Drive', 'Printer', 'Processor', 'WORM Drive', 'CD-ROM Drive',
'Scanner', 'Optical Drive', 'Changer', 'Communication Device',
'Invalid', 'Any Type Device');
type
TScsiError = {======== Errors from SRB_Status field ========}
(Err_None, Err_Aborted, Err_InvalidRequest,
Err_HAerror, Err_InvalidHostAdapter, Err_NoDevice,
Err_InvalidSrb, Err_BufferAlign, Err_AspiIsBusy,
Err_BufferTooBig, Err_Unknown,
{======== Errors from SRB_HaStat field ========}
Err_CommandTimeout, { transaction time ran out }
Err_SrbTimeout, { while waiting to process }
Err_MessageReject,
Err_BusReset,
Err_ParityError,
Err_RequestSenseFailed,
Err_SelectionTimeout,
Err_DataOverrun, {... or underrun }
Err_UnexpectedBusFree,
Err_BusPhaseSequence, {... failure }
{======== Errors from SRB_TargStat field ========}
Err_CheckCondition,
Err_TargetBusy,
Err_TargetReservationConflict,
Err_TargetQueueFull,
{======== Errors of SendScsiCommand ========}
Err_InvalidDevice, { Trying to exec SCSI command for non-exist device }
Err_NoEvent, { Unable to get event handle for notification }
Err_NotifyTimeout, { WaitForSingleObject result was unacceptable }
{======== Errors from SRB_Sense area ========}
Err_SenseUnknown, // Unknown SRB_Sense.ErrorCode value
Err_SenseFileMark,
Err_SenseEndOfMedia,
Err_SenseIllegalLength,
Err_SenseIncorrectLength,
Err_SenseNoSense, // There is no sense key info to be reported
Err_SenseRecoveredError, // Last command completed successfully with
// some recovery action performed by the target.
Err_SenseNotReady, // Unit addressed cannot be accessed.
// Operator intervention may be required.
Err_SenseMediumError, // Command terminated with a non-recovered
// error condition that was probably caused by a flaw
// in the medium or an error in the recorded data.
Err_SenseHardwareError, // Non-recoverable hardware failure detected
Err_SenseIllegalRequest, // Illegal parameter detected in the command
// descriptor block or in the additional parameters.
Err_SenseUnitAttention, // Removable medium may have been changed or
// the target has been reset.
Err_SenseDataProtect, // Read/Write Command was applied to the
// block that is protected from this operation.
Err_SenseBlankCheck, // Write-once device or a sequential-access
// device encountered blank medium or end-of-data
// indication while reading or a write-once device
// encountered a non-blank medium while writing.
Err_SenseVendorSpecific,
Err_SenseCopyAborted, // COPY, COMPARE, or COPY AND VERIFY command
// was aborted due to an error condition on the source
// device, the destination device, or both.
Err_SenseAbortedCommand, // Target aborted the command. Host may be
// able to recover by trying the command again.
Err_SenseEqual, // SEARCH DATA has satisfied an equal comparison.
Err_SenseVolumeOverflow, // Buffered peripheral device has reached
// the end-of-partition and data may remain in the
// buffer that has not been written to the medium.
// RECOVER BUFFERED DATA command may be issued to read
// the unwritten data from the buffer.
Err_SenseMiscompare, // Source data did not match the data read
// from the medium.
Err_SenseReserved
);
var
ScsiErrorName : array[TScsiError] of string = ('Err_None',
'Err_Aborted', 'Err_InvalidRequest', 'Err_HAerror',
'Err_InvalidHostAdapter', 'Err_NoDevice', 'Err_InvalidSrb',
'Err_BufferAlign', 'Err_AspiIsBusy', 'Err_BufferTooBig',
'Err_Unknown', 'Err_CommandTimeout', 'Err_SrbTimeout',
'Err_MessageReject', 'Err_BusReset', 'Err_ParityError',
'Err_RequestSenseFailed', 'Err_SelectionTimeout',
'Err_DataOverrun', 'Err_UnexpectedBusFree',
'Err_BusPhaseSequence', 'Err_CheckCondition', 'Err_TargetBusy',
'Err_TargetReservationConflict', 'Err_TargetQueueFull',
'Err_InvalidDevice', 'Err_NoEvent', 'Err_NotifyTimeout',
'Err_SenseUnknown', 'Err_SenseFileMark', 'Err_SenseEndOfMedia',
'Err_SenseIllegalLength', 'Err_SenseIncorrectLength',
'Err_SenseNoSense', 'Err_SenseRecoveredError',
'Err_SenseNotReady', 'Err_SenseMediumError', 'Err_SenseHardwareError',
'Err_SenseIllegalRequest', 'Err_SenseUnitAttention',
'Err_SenseDataProtect', 'Err_SenseBlankCheck',
'Err_SenseVendorSpecific', 'Err_SenseCopyAborted',
'Err_SenseAbortedCommand', 'Err_SenseEqual',
'Err_SenseVolumeOverflow', 'Err_SenseMiscompare', 'Err_SenseReserved');
type
TdeviceID = record Adapter, Target, Lun : byte; end;
TscsiSenseInfo = array[0..127] of BYTE;
TCallBackProc = procedure;
TScsiDeviceInfo = packed record
PeripheralQualifier : BYTE;
{ 000b = Peripheral device type is currently connected to this
logical unit. Especially for hot-swap devices. All fixed
devices shall also use this peripheral qualifier.
001b = The target is capable of supporting the peripheral device;
however, the physical device is not currently connected.
010b = Reserved.
011b = The target is not capable of supporting a physical device
on this logical unit. It's illegal LUN for all commands.
1XXb = Vendor-specific codes. }
DeviceType : BYTE;
{ 00h = Direct-access device (e.g. magnetic disk)
01h = Sequential-access device (e.g. magnetic tape)
02h = Printer device
03h = Processor device
04h = Write-once device (e.g. some optical disks)
05h = CD-ROM device
06h = Scanner device
07h = Optical memory device (e.g. some optical disks)
08h = Medium changer device (e.g. jukeboxes)
09h = Communications device
0Ah, 0Bh = Defined by ASC IT8 (Graphic arts pre-press devices)
0Ch..1Eh = Reserved
1Fh = Unknown or no device type }
DeviceTypeModifier : BYTE; { Vendor-specific, in SCSI-I only }
RemovableMedium : BOOLEAN; { defines if medium is removable }
ISOversion : BYTE; {compliance level to the ISO
version of SCSI (ISO 9316), 0 means no compliance acclaimed }
ECMAversion : BYTE; {compliance level to the ECMA
version of SCSI (ECMA-111), 0 means no compliance acclaimed }
ANSIversion : BYTE; {compliance level to the ANSI SCSI:
0 = The device might or might not comply to an ANSI standard,
1 = The device complies to ANSI SCSI-1,
2 = The device complies to ANSI SCSI-2, etc. }
AsyncEventCapability : BOOLEAN; {indicates that the device supports
the asynchronous event notification capability. For Processor
device-type definition ONLY. Reserved for all other types. }
TerminateIOcapability: BOOLEAN; {indicates that the device supports
the TERMINATE I/O PROCESS message }
ResponseDataFormat : BYTE; { indicates the INQUIRY data format is:
0 = as specified in SCSI-1,
1 = products that were designed prior to the SCSI-2 (i.e. CCS),
2 = as specified in SCSI-2,
3..0Fh = reserved. }
AdditionalDataLength : BYTE; { specifies the length in bytes of the
parameters, i.e. (full_record_length - 4). If the record length
specified here is too small to transfer all of the parameters,
this value shall not be adjusted to reflect the truncation. }
WideBus32capability : BOOLEAN; {indicates that the device supports
32-bit wide data transfers }
WideBus16capability : BOOLEAN; {indicates that the device supports
16-bit wide data transfers. If the values of both the WideBus
flags are false,the device only supports 8-bit data transfers.}
RelativeAddressingCapability : BOOLEAN; { If this flag is set, the
linked (and ONLY linked) commands may use relative addressing }
SynchronousTransferCapability : BOOLEAN; {indicates that the device
supports synchronous data transfers }
LinkedCommandsCapability : BOOLEAN; {indicates that the device
supports execution of linked commands for this logical unit. }
CommandQueuingCapability : BOOLEAN; {indicates that the device
supports tagged command queuing for this logical unit. }
SoftResetCapability : BOOLEAN; { FALSE indicates that the device
responds to the RESET condition with hard RESET alternative,
TRUE - that it responds with the soft RESET alternative }
VendorID : string[8];
ProductID : string[16];
ProductRevision : string[4];
VendorSpecific : string[20];
{ All this strings are left-aligned ASCII data fields that shall
contain only graphic codes (i.e. code values 20h through 7Eh),
and the unused bytes shall be filled with space characters. }
end;
TScsiHAinfo = packed record
ScsiId : BYTE;
MaxTargetCount : BYTE;
ResidualSupport : BOOLEAN;
MaxTransferLength : DWORD;
BufferAlignMask : WORD;
ScsiManagerId,
HostAdapterId : String[16];
end;
TASPIDevice = class { Common ASPI device class }
private
fHAcount : DWORD;
fLastError : TScsiError;
fSense : TscsiSenseInfo;
fShortTimeout : DWORD;
fMediumTimeout : DWORD;
fLongTimeout : DWORD;
fAudioTimeout : DWORD;
fDeviceID : TdeviceID;
fDeviceType : TScsiDeviceType;
fDeviceInfo : TScsiDeviceInfo;
fHAinfo : TScsiHAinfo;
protected
function GetAspiError(Status, HaStat, TargStat : BYTE) : BOOLEAN;
procedure ChangeDevice(Value : TdeviceID); virtual;
procedure SetDeviceID(Value : TdeviceID);
public
constructor Create(AOwner : TObject);
destructor Destroy; override;
{===================== Raw ASPI functions ===================}
function ASPIhaInquiry(HaId : BYTE;
var sh : TScsiHAinfo) : BOOLEAN; //True if OK
function ASPIgetDeviceType(DeviceAddress : TDeviceID;
var SDeviceType : TScsiDeviceType) : BOOLEAN;
function ASPIsendScsiCommand(Pcdb : pointer; CdbLen : DWORD;
Pbuf : pointer; BufLen : DWORD; // Always works with
Direction, Timeout: DWORD) : BOOLEAN; // 'current' device
procedure ASPIabortCommand(HaId : BYTE; Psrb : pointer);
function ASPIresetDevice : BOOLEAN; // Resets 'current' device
function ASPIgetDriveInt13info(DeviceAddress : TDeviceID;
var Support, DosSupport : BOOLEAN;
var DriveNumber, Heads, Sectors : BYTE) : BOOLEAN;
// NOTE: This command is NOT VALID under WinNT.
// Support=false -> no int 13 support anyway
// else if DosSupport=false -> supported on non-DOS basis
// else -> supported under DOS control
{================== Mid-level ASPI functions ================}
function ASPIsend6(OpCode : BYTE; Lba : DWORD; Byte4 : BYTE;
Pbuf : pointer; BufLen, Direction,Timeout: DWORD) : BOOLEAN;
function ASPIsend10(OpCode : BYTE; Byte1 : BYTE;
Lba : DWORD; Byte6 : BYTE; Word7 : WORD;
Pbuf : pointer; BufLen, Direction,Timeout: DWORD) : BOOLEAN;
function ASPIsend12(OpCode : BYTE; Byte1 : BYTE;
Lba, TLength : DWORD; Byte10 : BYTE;
Pbuf : pointer; BufLen, Direction,Timeout: DWORD) : BOOLEAN;
function GetDeviceInfo(DId : TdeviceID;
var DInfo : TScsiDeviceInfo) : BOOLEAN;
function EnumDevices(DType: TScsiDeviceType; CBack: TCallBackProc)
: integer; // Returns number of found devices.
// Calls CBack() every time when finds one.
property HAcount : DWORD read fHAcount;
property Sense : TscsiSenseInfo read fSense;
property LastError : TScsiError read fLastError default Err_None;
property DeviceID : TdeviceID read fDeviceID write SetDeviceID;
property DeviceType : TScsiDeviceType read fDeviceType;
property DeviceInfo : TScsiDeviceInfo read fDeviceInfo;
property HAinfo : TScsiHAinfo read fHAinfo;
published
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -