Leaked source code of windows server 2003
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

/*++
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;
}