You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
657 lines
16 KiB
657 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
The format of the SCSI (port driver) device map is as follows:
|
|
|
|
Scsi Port 0 - KEY
|
|
|
|
Driver - REG_SZ specifying the drive name, e.g., aha154x.
|
|
|
|
Interrupt - REG_DWORD specifying the interrupt vector that the HBA
|
|
uses. For example, 58.
|
|
|
|
IOAddress - REG_DWORD specifying the IO address the HBA uses;
|
|
for example, 0xd800.
|
|
|
|
Dma64BidAddresses - REG_DWORD specifying whether the HBA is using
|
|
64 bit addresses or not. Should always be 1 if present.
|
|
|
|
PCCARD - REG_DWORD specifying whether this is a PCCARD bus or not.
|
|
The value will always be 1 if present.
|
|
|
|
SCSI Bus 0 - KEY
|
|
|
|
Initiator Id 7 - KEY
|
|
|
|
Target Id 0 - KEY
|
|
|
|
Logical Unit ID 0 - KEY
|
|
|
|
Identifier - REG_SZ specifying the SCSI Vendor ID from
|
|
the LUNs inquiry data.
|
|
|
|
InquiryData - REG_BINARY specifies the SCSI Inquiry Data
|
|
for the LUN.
|
|
|
|
SerialNumber - REG_SZ specifies the SCSI Serial Number
|
|
for the LUN if present.
|
|
|
|
Type - REG_SZ specifies the SCSI device type for the LUN.
|
|
|
|
Usage:
|
|
|
|
The module exports the following functions:
|
|
|
|
PortOpenMapKey - Opens a handle to the root of the SCSI device map.
|
|
|
|
PortBuildAdapterEntry - Creates an entry for the specified adapter
|
|
in the SCSI device map.
|
|
|
|
PortBuildBusEntry - Creates an entry for the specified bus in the
|
|
SCSI device map.
|
|
|
|
PortBuildTargetEntry - Creates an entry for the specified target in
|
|
the SCSI device map.
|
|
|
|
PortBuildLunEntry - Creates an entry for the specified LUN in the
|
|
SCSI device map.
|
|
|
|
Author:
|
|
|
|
Matthew D Hendel (math) 18-July-2002
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wdmguid.h>
|
|
|
|
|
|
//
|
|
// Defines
|
|
//
|
|
|
|
|
|
#define SCSI_DEVMAP_KEY_NAME \
|
|
(L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi")
|
|
|
|
#define SCSI_LUN_KEY_NAME\
|
|
(L"%s\\Scsi Port %d\\SCSI Bus %d\\Target Id %d\\Logical Unit Id %d")
|
|
|
|
|
|
|
|
//
|
|
// Implementation
|
|
//
|
|
|
|
NTSTATUS
|
|
PortOpenMapKey(
|
|
OUT PHANDLE DeviceMapKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open a handle to the root of the SCSI Device Map.
|
|
|
|
The handle must be closed with ZwClose.
|
|
|
|
Arguments:
|
|
|
|
DeviceMapKey - Supplies a buffer where the device map handle should
|
|
be stored on success.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
UNICODE_STRING name;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
HANDLE mapKey;
|
|
ULONG disposition;
|
|
NTSTATUS status;
|
|
|
|
ASSERT (DeviceMapKey != NULL);
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Open the SCSI key in the device map.
|
|
//
|
|
|
|
RtlInitUnicodeString(&name, SCSI_DEVMAP_KEY_NAME);
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&name,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL);
|
|
|
|
//
|
|
// Create or open the key.
|
|
//
|
|
|
|
status = ZwCreateKey(&mapKey,
|
|
KEY_READ | KEY_WRITE,
|
|
&objectAttributes,
|
|
0,
|
|
(PUNICODE_STRING) NULL,
|
|
REG_OPTION_VOLATILE,
|
|
&disposition);
|
|
|
|
if(NT_SUCCESS(status)) {
|
|
*DeviceMapKey = mapKey;
|
|
} else {
|
|
*DeviceMapKey = NULL;
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PortMapBuildAdapterEntry(
|
|
IN HANDLE DeviceMapKey,
|
|
IN ULONG PortNumber,
|
|
IN ULONG InterruptLevel, OPTIONAL
|
|
IN ULONG IoAddress, OPTIONAL
|
|
IN ULONG Dma64BitAddresses,
|
|
IN PUNICODE_STRING DriverName,
|
|
IN PGUID BusType, OPTIONAL
|
|
OUT PHANDLE AdapterKeyBuffer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a device map entry for the SCSI HBA. We also include device
|
|
map entries for each of the Busses attached to the HBA, and the initiator
|
|
for each bus.
|
|
|
|
Arguments:
|
|
|
|
DeviceMapKey - Supplies the handle to the device map key.
|
|
|
|
PortNumber - Supplies the port number that this HBA represents.
|
|
|
|
InterruptLevel - Supplies the interrupt level, or 0 for none.
|
|
|
|
IoAddress - Supplies the IoAddress or 0 for none.
|
|
|
|
Dma64BitAddress -
|
|
|
|
DriverName - NULL terminated unicode string that is the driver name.
|
|
|
|
BusType - Bus type that this HBA is on.
|
|
|
|
AdapterKeyBuffer -
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Temp;
|
|
HANDLE AdapterKey;
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// String must be NULL terminated.
|
|
//
|
|
|
|
ASSERT (DriverName->Buffer [DriverName->Length / sizeof (WCHAR)] == UNICODE_NULL);
|
|
|
|
Status = PortCreateKeyEx (DeviceMapKey,
|
|
REG_OPTION_VOLATILE,
|
|
&AdapterKey,
|
|
L"Scsi Port %d",
|
|
PortNumber);
|
|
|
|
if (!NT_SUCCESS (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Add interrupt level if non-zero.
|
|
//
|
|
|
|
if (InterruptLevel) {
|
|
Status = PortSetValueKey (AdapterKey,
|
|
L"Interrupt",
|
|
REG_DWORD,
|
|
&InterruptLevel,
|
|
sizeof (ULONG));
|
|
}
|
|
|
|
//
|
|
// Add IoAddress if non-zero.
|
|
//
|
|
|
|
if (IoAddress) {
|
|
Status = PortSetValueKey (AdapterKey,
|
|
L"IOAddress",
|
|
REG_DWORD,
|
|
&IoAddress,
|
|
sizeof (ULONG));
|
|
}
|
|
|
|
//
|
|
// Add Dma64BitAddresses if non-zero.
|
|
//
|
|
|
|
if (Dma64BitAddresses) {
|
|
Temp = 1;
|
|
Status = PortSetValueKey (AdapterKey,
|
|
L"Dma64BitAddresses",
|
|
REG_DWORD,
|
|
&Temp,
|
|
sizeof (ULONG));
|
|
}
|
|
|
|
|
|
//
|
|
// Add the driver name.
|
|
//
|
|
|
|
Status = PortSetValueKey (AdapterKey,
|
|
L"Driver",
|
|
REG_SZ,
|
|
DriverName->Buffer,
|
|
DriverName->Length + sizeof (WCHAR));
|
|
|
|
//
|
|
// If this is a PCMCIA card, set the PCCARD flag.
|
|
//
|
|
|
|
if (BusType != NULL &&
|
|
IsEqualGUID (BusType, &GUID_BUS_TYPE_PCMCIA)) {
|
|
|
|
Temp = 1;
|
|
Status = PortSetValueKey (AdapterKey,
|
|
L"PCCARD",
|
|
REG_DWORD,
|
|
&Temp,
|
|
sizeof (ULONG));
|
|
}
|
|
|
|
if (AdapterKeyBuffer != NULL) {
|
|
*AdapterKeyBuffer = AdapterKey;
|
|
} else {
|
|
ZwClose (AdapterKey);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PortMapBuildBusEntry(
|
|
IN HANDLE AdapterKey,
|
|
IN ULONG BusId,
|
|
IN ULONG InitiatorId,
|
|
OUT PHANDLE BusKeyBuffer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build the BusId device map entry under the adapters device map entry. The
|
|
bus entry is populated with an entry for the initiator ID only.
|
|
|
|
Arguments:
|
|
|
|
AdapterKey - Handle to the adapter's device map entry.
|
|
|
|
BusId - Supplies the ID of this bus.
|
|
|
|
InitiatorId - Supplies the initiator target ID.
|
|
|
|
BusKeyBuffer _ Supplies an optional pointer to a buffer to receive the
|
|
opened bus key.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE BusKey;
|
|
|
|
ASSERT (BusId <= 255);
|
|
ASSERT (InitiatorId <= 255);
|
|
|
|
PAGED_CODE();
|
|
|
|
Status = PortCreateKeyEx (AdapterKey,
|
|
REG_OPTION_VOLATILE,
|
|
&BusKey,
|
|
L"SCSI Bus %d",
|
|
BusId);
|
|
|
|
if (!NT_SUCCESS (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
PortCreateKeyEx (BusKey,
|
|
REG_OPTION_VOLATILE,
|
|
NULL,
|
|
L"Initiator Id %d",
|
|
InitiatorId);
|
|
|
|
if (BusKeyBuffer) {
|
|
*BusKeyBuffer = BusKey;
|
|
} else {
|
|
ZwClose (BusKey);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PortMapBuildTargetEntry(
|
|
IN HANDLE BusKey,
|
|
IN ULONG TargetId,
|
|
OUT PHANDLE TargetKey OPTIONAL
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
ASSERT (TargetId <= 255);
|
|
|
|
PAGED_CODE();
|
|
|
|
Status = PortCreateKeyEx (BusKey,
|
|
REG_OPTION_VOLATILE,
|
|
TargetKey,
|
|
L"Target Id %d",
|
|
TargetId);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PortMapBuildLunEntry(
|
|
IN HANDLE TargetKey,
|
|
IN ULONG Lun,
|
|
IN PINQUIRYDATA InquiryData,
|
|
IN PANSI_STRING SerialNumber, OPTIONAL
|
|
PVOID DeviceId,
|
|
IN ULONG DeviceIdLength,
|
|
OUT PHANDLE LunKeyBuffer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create and populate the Logical Unit Device Map Entry with the following
|
|
information:
|
|
|
|
Identifier - REG_SZ specifying the SCSI Vendor Id from the inquriy
|
|
data.
|
|
|
|
InquiryData - REG_BINARY specifying the SCSI InquiryData.
|
|
|
|
SerialNumber - REG_SZ specifying the serial number (page 80 of Inquriy
|
|
VPD).
|
|
|
|
Type - REG_SZ specifying the SCSI device type.
|
|
|
|
DeviceIdentifierPage - REG_BINARY specifying the binary device
|
|
identifier data (page 83 of VPD).
|
|
|
|
Arguments:
|
|
|
|
TargetKey - Specifies the Target's previously opened key.
|
|
|
|
Lun - Specifies the Logical Unit ID for this LUN.
|
|
|
|
InquiryData - Specifies the binary inquriy data for this LUN. NOTE: Only
|
|
the first INQUIRYDATABUFFERSIZE bytes of the Inquiry data are used.
|
|
|
|
SerialNumber - Specifies the ANSI Serial Number (page 80) for the LUN. May
|
|
be NULL if there is no serial number.
|
|
|
|
DeviceId - Specifies the device identifier page (page 83) for the LUN. May
|
|
be NULL if the device does not support page 83.
|
|
|
|
DeviceIdLength - Specifies the length of the DeviceId parameter. Not used
|
|
when DeviceId is NULL.
|
|
|
|
LunKeyReturn - Specifies the buffer for key for the logical unit to
|
|
be copied to. May be NULL if not necessary.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE LunKey;
|
|
PCSCSI_DEVICE_TYPE DeviceEntry;
|
|
ULONG Length;
|
|
|
|
ASSERT (Lun <= 255);
|
|
ASSERT (InquiryData != NULL);
|
|
|
|
PAGED_CODE();
|
|
|
|
Status = PortCreateKeyEx (TargetKey,
|
|
REG_OPTION_VOLATILE,
|
|
&LunKey,
|
|
L"Logical Unit Id %d",
|
|
Lun);
|
|
|
|
if (!NT_SUCCESS (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Write out the INQUIRY DATA in binary form.
|
|
//
|
|
|
|
PortSetValueKey (LunKey,
|
|
L"InquiryData",
|
|
REG_BINARY,
|
|
InquiryData,
|
|
INQUIRYDATABUFFERSIZE);
|
|
|
|
//
|
|
// Write out the SERIAL NUMBER as a string.
|
|
//
|
|
|
|
if (SerialNumber->Length != 0) {
|
|
PortSetValueKey (LunKey,
|
|
L"SerialNumber",
|
|
PORT_REG_ANSI_STRING,
|
|
SerialNumber->Buffer,
|
|
SerialNumber->Length);
|
|
}
|
|
|
|
//
|
|
// Write the SCSI VendorId.
|
|
//
|
|
|
|
PortSetValueKey (LunKey,
|
|
L"Identifier",
|
|
PORT_REG_ANSI_STRING,
|
|
InquiryData->VendorId,
|
|
sizeof (InquiryData->VendorId));
|
|
//
|
|
// Add the DeviceType entry as a string.
|
|
//
|
|
|
|
DeviceEntry = PortGetDeviceType (InquiryData->DeviceType);
|
|
Length = wcslen (DeviceEntry->DeviceMap);
|
|
|
|
PortSetValueKey (LunKey,
|
|
L"DeviceType",
|
|
REG_SZ,
|
|
(PVOID)DeviceEntry->DeviceMap,
|
|
(Length + 1) * sizeof (WCHAR));
|
|
|
|
//
|
|
// Write out the DeviceIdentifierPage if it was given.
|
|
//
|
|
|
|
if (DeviceId != NULL) {
|
|
PortSetValueKey (LunKey,
|
|
L"DeviceIdentifierPage",
|
|
REG_BINARY,
|
|
DeviceId,
|
|
DeviceIdLength);
|
|
}
|
|
|
|
if (LunKeyBuffer) {
|
|
*LunKeyBuffer = LunKey;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PortMapDeleteAdapterEntry(
|
|
IN ULONG PortId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete the Adapter's SCSI DeviceMap entry from the registry.
|
|
|
|
Arguments:
|
|
|
|
PortId - PortId associated with the adapter.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
HANDLE AdapterKey;
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
WCHAR KeyNameBuffer[256];
|
|
|
|
PAGED_CODE();
|
|
|
|
swprintf (KeyNameBuffer,
|
|
L"%s\\Scsi Port %d",
|
|
SCSI_DEVMAP_KEY_NAME,
|
|
PortId);
|
|
|
|
RtlInitUnicodeString (&KeyName, KeyNameBuffer);
|
|
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwOpenKey (&AdapterKey,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ZwDeleteKey (AdapterKey);
|
|
ZwClose (AdapterKey);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
PortMapDeleteLunEntry(
|
|
IN ULONG PortId,
|
|
IN ULONG BusId,
|
|
IN ULONG TargetId,
|
|
IN ULONG Lun
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete the logical unit's SCSI DeviceMap entry from the registry.
|
|
|
|
Arguments:
|
|
|
|
PortId - Port ID associaed with the adapter.
|
|
|
|
BusId - Bus ID / PathId that this logical unit is on.
|
|
|
|
TargetId - Target that this logical unit is on.
|
|
|
|
Lun - Logical unit ID for this LUN.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
HANDLE LunKey;
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
WCHAR KeyNameBuffer[256];
|
|
|
|
PAGED_CODE();
|
|
|
|
swprintf (KeyNameBuffer,
|
|
SCSI_LUN_KEY_NAME,
|
|
SCSI_DEVMAP_KEY_NAME,
|
|
PortId,
|
|
BusId,
|
|
TargetId,
|
|
Lun);
|
|
|
|
RtlInitUnicodeString (&KeyName, KeyNameBuffer);
|
|
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwOpenKey (&LunKey,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ZwDeleteKey (LunKey);
|
|
ZwClose (LunKey);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|