- Implemented LUN-Extensions.

- Moved Inquiry-Data from Port-Extension to LUN-Extensions.

svn path=/trunk/; revision=5984
This commit is contained in:
Eric Kohl 2003-09-04 23:33:55 +00:00
parent a7793b4ec9
commit 9d8179a6c8
2 changed files with 407 additions and 294 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: scsiport.c,v 1.32 2003/09/04 11:30:42 ekohl Exp $ /* $Id: scsiport.c,v 1.33 2003/09/04 23:33:55 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -79,8 +79,24 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
IN ULONG PortCount, IN ULONG PortCount,
IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension); IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension);
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
static VOID static VOID
ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension); ScsiPortInquire(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static ULONG
SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo);
static BOOLEAN STDCALL static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt, ScsiPortIsr(IN PKINTERRUPT Interrupt,
@ -337,7 +353,7 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
/* /*
* @unimplemented * @implemented
*/ */
PVOID STDCALL PVOID STDCALL
ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension, ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
@ -345,8 +361,35 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
IN UCHAR TargetId, IN UCHAR TargetId,
IN UCHAR Lun) IN UCHAR Lun)
{ {
DPRINT("ScsiPortGetLogicalUnit()\n"); PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
UNIMPLEMENTED; PSCSI_PORT_LUN_EXTENSION LunExtension;
PLIST_ENTRY Entry;
DPRINT("ScsiPortGetLogicalUnit() called\n");
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
return NULL;
Entry = DeviceExtension->LunExtensionListHead.Flink;
while (Entry != &DeviceExtension->LunExtensionListHead)
{
LunExtension = CONTAINING_RECORD(Entry,
SCSI_PORT_LUN_EXTENSION,
List);
if (LunExtension->PathId == PathId &&
LunExtension->TargetId == TargetId &&
LunExtension->Lun == Lun)
{
return (PVOID)&LunExtension->MiniportLunExtension;
}
Entry = Entry->Flink;
}
return NULL;
} }
@ -479,6 +522,7 @@ ScsiPortInitialize(IN PVOID Argument1,
ExtensionSize); ExtensionSize);
PseudoDeviceExtension->Length = ExtensionSize; PseudoDeviceExtension->Length = ExtensionSize;
PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
PseudoDeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo; PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
@ -699,7 +743,7 @@ ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
/* /*
* @unimplemented * @implemented
*/ */
BOOLEAN STDCALL BOOLEAN STDCALL
ScsiPortValidateRange(IN PVOID HwDeviceExtension, ScsiPortValidateRange(IN PVOID HwDeviceExtension,
@ -822,88 +866,47 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
case SRB_FUNCTION_CLAIM_DEVICE: case SRB_FUNCTION_CLAIM_DEVICE:
{ {
PSCSI_ADAPTER_BUS_INFO AdapterInfo; PSCSI_PORT_LUN_EXTENSION LunExtension;
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n"); DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
Srb->DataBuffer = NULL; LunExtension = SpiGetLunExtension(DeviceExtension,
Srb->PathId,
if (DeviceExtension->PortBusInfo != NULL) Srb->TargetId,
Srb->Lun);
if (LunExtension != NULL)
{ {
AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; /* Reference device object and keep the pointer */
ObReferenceObject(DeviceObject);
if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0) LunExtension->DeviceObject = DeviceObject;
break; LunExtension->DeviceClaimed = TRUE;
Srb->DataBuffer = DeviceObject;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + }
AdapterInfo->BusData[Srb->PathId].InquiryDataOffset); else
{
while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset) Srb->DataBuffer = NULL;
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
if ((UnitInfo->TargetId == Srb->TargetId) &&
(UnitInfo->Lun == Srb->Lun) &&
(UnitInfo->DeviceClaimed == FALSE))
{
UnitInfo->DeviceClaimed = TRUE;
DPRINT("Claimed device!\n");
/* FIXME: Hack!!!!! */
Srb->DataBuffer = DeviceObject;
break;
}
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
}
} }
} }
break; break;
case SRB_FUNCTION_RELEASE_DEVICE: case SRB_FUNCTION_RELEASE_DEVICE:
{ {
PSCSI_ADAPTER_BUS_INFO AdapterInfo; PSCSI_PORT_LUN_EXTENSION LunExtension;
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n"); DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
if (DeviceExtension->PortBusInfo != NULL) LunExtension = SpiGetLunExtension(DeviceExtension,
Srb->PathId,
Srb->TargetId,
Srb->Lun);
if (LunExtension != NULL)
{ {
AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; /* Dereference device object */
ObDereferenceObject(LunExtension->DeviceObject);
if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0) LunExtension->DeviceObject = NULL;
break; LunExtension->DeviceClaimed = FALSE;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
if ((UnitInfo->TargetId == Srb->TargetId) &&
(UnitInfo->Lun == Srb->Lun) &&
(UnitInfo->DeviceClaimed == TRUE))
{
UnitInfo->DeviceClaimed = FALSE;
DPRINT("Released device!\n");
break;
}
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
}
} }
} }
break; break;
@ -967,7 +970,8 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
Irp->IoStatus.Information = sizeof(DUMP_POINTERS); Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
} }
break; break;
case IOCTL_SCSI_GET_CAPABILITIES: case IOCTL_SCSI_GET_CAPABILITIES:
{ {
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n"); DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
@ -984,12 +988,10 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n"); DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
/* Copy inquiry data to the port device extension */ /* Copy inquiry data to the port device extension */
memcpy(Irp->AssociatedIrp.SystemBuffer, Irp->IoStatus.Information =
DeviceExtension->PortBusInfo, SpiGetInquiryData(DeviceExtension,
DeviceExtension->PortBusInfoSize); Irp->AssociatedIrp.SystemBuffer);
DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize);
Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize;
} }
break; break;
@ -1043,33 +1045,33 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
ScsiPortStartPacket, ScsiPortStartPacket,
DeviceExtension)) DeviceExtension))
{ {
DPRINT("Synchronization failed!\n"); DPRINT("Synchronization failed!\n");
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IoCompleteRequest(Irp,
IO_NO_INCREMENT); IO_NO_INCREMENT);
IoStartNextPacket(DeviceObject, IoStartNextPacket(DeviceObject,
FALSE); FALSE);
} }
KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql); KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE) if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
{ {
DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE; DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
IoCompleteRequest(Irp, IoCompleteRequest(Irp,
IO_NO_INCREMENT); IO_NO_INCREMENT);
} }
if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT) if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
{ {
DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT; DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
IoStartNextPacket(DeviceObject, IoStartNextPacket(DeviceObject,
FALSE); FALSE);
} }
else else
{ {
KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
} }
} }
break; break;
@ -1278,12 +1280,10 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
PortDeviceExtension->PortConfig.AdapterScansDown; PortDeviceExtension->PortConfig.AdapterScansDown;
PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */ PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
/* Initialize inquiry data */ /* Initialize LUN-Extension list */
PortDeviceExtension->PortBusInfoSize = 0; InitializeListHead(&PortDeviceExtension->LunExtensionListHead);
PortDeviceExtension->PortBusInfo = NULL;
DPRINT("DeviceExtension %p\n", PortDeviceExtension); DPRINT("DeviceExtension %p\n", PortDeviceExtension);
// ScsiPortInquire(PortDeviceExtension);
/* FIXME: Copy more configuration data? */ /* FIXME: Copy more configuration data? */
@ -1306,32 +1306,92 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
} }
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun)
{
PSCSI_PORT_LUN_EXTENSION LunExtension;
ULONG LunExtensionSize;
DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
DeviceExtension, PathId, TargetId, Lun);
LunExtensionSize =
sizeof(SCSI_PORT_LUN_EXTENSION) + DeviceExtension->LunExtensionSize;
DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
LunExtension = ExAllocatePool(NonPagedPool,
LunExtensionSize);
if (LunExtension == NULL)
{
return NULL;
}
RtlZeroMemory(LunExtension,
LunExtensionSize);
InsertTailList(&DeviceExtension->LunExtensionListHead,
&LunExtension->List);
LunExtension->PathId = PathId;
LunExtension->TargetId = TargetId;
LunExtension->Lun = Lun;
return LunExtension;
}
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun)
{
PSCSI_PORT_LUN_EXTENSION LunExtension;
PLIST_ENTRY Entry;
DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
DeviceExtension, PathId, TargetId, Lun);
if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
return NULL;
Entry = DeviceExtension->LunExtensionListHead.Flink;
while (Entry != &DeviceExtension->LunExtensionListHead)
{
LunExtension = CONTAINING_RECORD(Entry,
SCSI_PORT_LUN_EXTENSION,
List);
if (LunExtension->PathId == PathId &&
LunExtension->TargetId == TargetId &&
LunExtension->Lun == Lun)
{
return LunExtension;
}
Entry = Entry->Flink;
}
return NULL;
}
static VOID static VOID
ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension) ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
{ {
PSCSI_ADAPTER_BUS_INFO AdapterInfo; PSCSI_PORT_LUN_EXTENSION LunExtension;
PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
SCSI_REQUEST_BLOCK Srb; SCSI_REQUEST_BLOCK Srb;
ULONG Bus; ULONG Bus;
ULONG Target; ULONG Target;
ULONG Lun; ULONG Lun;
ULONG UnitCount;
ULONG DataSize;
BOOLEAN Result; BOOLEAN Result;
DPRINT("ScsiPortInquire() called\n"); DPRINT("ScsiPortInquire() called\n");
DeviceExtension->Initializing = TRUE; DeviceExtension->Initializing = TRUE;
/* Copy inquiry data to the port device extension */
AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096);
RtlZeroMemory(AdapterInfo, 4096);
AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
UnitInfo = (PSCSI_INQUIRY_DATA)
((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
(sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
RtlZeroMemory(&Srb, RtlZeroMemory(&Srb,
sizeof(SCSI_REQUEST_BLOCK)); sizeof(SCSI_REQUEST_BLOCK));
Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256); Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
@ -1339,18 +1399,10 @@ ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
Srb.DataTransferLength = 256; Srb.DataTransferLength = 256;
Srb.Cdb[0] = SCSIOP_INQUIRY; Srb.Cdb[0] = SCSIOP_INQUIRY;
for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++) for (Bus = 0; Bus < DeviceExtension->PortConfig.NumberOfBuses; Bus++)
{ {
Srb.PathId = Bus; Srb.PathId = Bus;
AdapterInfo->BusData[Bus].InitiatorBusId =
DeviceExtension->PortConfig.InitiatorBusId[Bus];
AdapterInfo->BusData[Bus].InquiryDataOffset =
(ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
PrevUnit = NULL;
UnitCount = 0;
for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++) for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
{ {
Srb.TargetId = Target; Srb.TargetId = Target;
@ -1366,50 +1418,100 @@ ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS) if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
{ {
UnitInfo->PathId = Bus; LunExtension = SpiAllocateLunExtension(DeviceExtension,
UnitInfo->TargetId = Target; Bus,
UnitInfo->Lun = Lun; Target,
UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE; Lun);
memcpy(&UnitInfo->InquiryData, if (LunExtension != NULL)
Srb.DataBuffer, {
INQUIRYDATABUFFERSIZE); /* Copy inquiry data */
if (PrevUnit != NULL) memcpy(&LunExtension->InquiryData,
PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); Srb.DataBuffer,
PrevUnit = UnitInfo; sizeof(INQUIRYDATA));
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1); }
UnitCount++;
}
else if (Lun == 0)
{
break;
} }
} }
} }
DPRINT("UnitCount: %lu\n", UnitCount);
AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
if (UnitCount == 0)
AdapterInfo->BusData[Bus].InquiryDataOffset = 0;
} }
DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
ExFreePool(Srb.DataBuffer); ExFreePool(Srb.DataBuffer);
DeviceExtension->Initializing = FALSE; DeviceExtension->Initializing = FALSE;
/* copy inquiry data to the port driver's device extension */
DeviceExtension->PortBusInfoSize = DataSize;
DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool,
DataSize);
RtlCopyMemory(DeviceExtension->PortBusInfo,
AdapterInfo,
DataSize);
ExFreePool(AdapterInfo);
DPRINT("ScsiPortInquire() done\n"); DPRINT("ScsiPortInquire() done\n");
} }
static ULONG
SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo)
{
PSCSI_PORT_LUN_EXTENSION LunExtension;
PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
ULONG Bus;
ULONG Target;
ULONG Lun;
ULONG UnitCount;
DPRINT("SpiGetInquiryData() called\n");
/* Copy inquiry data to the port device extension */
AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
UnitInfo = (PSCSI_INQUIRY_DATA)
((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
(sizeof(SCSI_BUS_DATA) * (AdapterBusInfo->NumberOfBuses - 1)));
for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
{
AdapterBusInfo->BusData[Bus].InitiatorBusId =
DeviceExtension->PortConfig.InitiatorBusId[Bus];
AdapterBusInfo->BusData[Bus].InquiryDataOffset =
(ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
PrevUnit = NULL;
UnitCount = 0;
for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
{
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
{
LunExtension = SpiGetLunExtension(DeviceExtension,
Bus,
Target,
Lun);
if (LunExtension != NULL)
{
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
Bus, Target, Lun);
UnitInfo->PathId = Bus;
UnitInfo->TargetId = Target;
UnitInfo->Lun = Lun;
UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
memcpy(&UnitInfo->InquiryData,
&LunExtension->InquiryData,
INQUIRYDATABUFFERSIZE);
if (PrevUnit != NULL)
PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
PrevUnit = UnitInfo;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
UnitCount++;
}
}
}
DPRINT("UnitCount: %lu\n", UnitCount);
AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
if (UnitCount == 0)
AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
}
DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
return (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
}
static BOOLEAN STDCALL static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt, ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext) IN PVOID ServiceContext)
@ -1638,6 +1740,7 @@ static NTSTATUS
ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PUNICODE_STRING RegistryPath) PUNICODE_STRING RegistryPath)
{ {
PSCSI_PORT_LUN_EXTENSION LunExtension;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
UNICODE_STRING ValueName; UNICODE_STRING ValueName;
@ -1650,10 +1753,9 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
HANDLE ScsiTargetKey; HANDLE ScsiTargetKey;
HANDLE ScsiLunKey; HANDLE ScsiLunKey;
ULONG BusNumber; ULONG BusNumber;
UCHAR CurrentTarget; ULONG Target;
PSCSI_ADAPTER_BUS_INFO AdapterInfo; ULONG CurrentTarget;
PSCSI_INQUIRY_DATA UnitInfo; ULONG Lun;
PINQUIRYDATA InquiryData;
PWCHAR DriverName; PWCHAR DriverName;
ULONG UlongData; ULONG UlongData;
PWCHAR TypeName; PWCHAR TypeName;
@ -1854,39 +1956,70 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
/* Enumerate targets */ /* Enumerate targets */
CurrentTarget = (UCHAR)-1; CurrentTarget = (ULONG)-1;
ScsiTargetKey = NULL; ScsiTargetKey = NULL;
AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
if (AdapterInfo->BusData[BusNumber].NumberOfLogicalUnits != 0)
{ {
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
AdapterInfo->BusData[BusNumber].InquiryDataOffset);
while (AdapterInfo->BusData[BusNumber].InquiryDataOffset)
{ {
if (UnitInfo->TargetId != CurrentTarget) LunExtension = SpiGetLunExtension(DeviceExtension,
BusNumber,
Target,
Lun);
if (LunExtension != NULL)
{ {
/* Close old target key */ if (Target != CurrentTarget)
if (ScsiTargetKey != NULL)
{ {
ZwClose(ScsiTargetKey); /* Close old target key */
ScsiTargetKey = NULL; if (ScsiTargetKey != NULL)
{
ZwClose(ScsiTargetKey);
ScsiTargetKey = NULL;
}
/* Create 'Target Id X' key */
DPRINT(" Target Id %lu\n", Target);
swprintf(NameBuffer,
L"Target Id %lu",
Target);
RtlInitUnicodeString(&KeyName,
NameBuffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
ScsiBusKey,
NULL);
Status = ZwCreateKey(&ScsiTargetKey,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&Disposition);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey);
return(Status);
}
CurrentTarget = Target;
} }
/* Create 'Target Id X' key */ /* Create 'Logical Unit Id X' key */
DPRINT(" Target Id %u\n", DPRINT(" Logical Unit Id %lu\n", Lun);
UnitInfo->TargetId);
swprintf(NameBuffer, swprintf(NameBuffer,
L"Target Id %u", L"Logical Unit Id %lu",
UnitInfo->TargetId); Lun);
RtlInitUnicodeString(&KeyName, RtlInitUnicodeString(&KeyName,
NameBuffer); NameBuffer);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&KeyName, &KeyName,
0, 0,
ScsiBusKey, ScsiTargetKey,
NULL); NULL);
Status = ZwCreateKey(&ScsiTargetKey, Status = ZwCreateKey(&ScsiLunKey,
KEY_ALL_ACCESS, KEY_ALL_ACCESS,
&ObjectAttributes, &ObjectAttributes,
0, 0,
@ -1896,132 +2029,92 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
ZwClose(ScsiTargetKey);
ZwClose(ScsiBusKey); ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey); ZwClose(ScsiPortKey);
return(Status); return(Status);
} }
CurrentTarget = UnitInfo->TargetId; /* Set 'Identifier' (REG_SZ) value */
} swprintf(NameBuffer,
L"%.8S%.16S%.4S",
/* Create 'Logical Unit Id X' key */ LunExtension->InquiryData.VendorId,
DPRINT(" Logical Unit Id %u\n", LunExtension->InquiryData.ProductId,
UnitInfo->Lun); LunExtension->InquiryData.ProductRevisionLevel);
swprintf(NameBuffer, DPRINT(" Identifier = '%S'\n", NameBuffer);
L"Logical Unit Id %u", RtlInitUnicodeString(&ValueName,
UnitInfo->Lun); L"Identifier");
RtlInitUnicodeString(&KeyName, Status = ZwSetValueKey(ScsiLunKey,
NameBuffer); &ValueName,
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0, 0,
ScsiTargetKey, REG_SZ,
NULL); NameBuffer,
Status = ZwCreateKey(&ScsiLunKey, (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
KEY_ALL_ACCESS, if (!NT_SUCCESS(Status))
&ObjectAttributes, {
0, DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
NULL, ZwClose(ScsiLunKey);
REG_OPTION_VOLATILE, ZwClose(ScsiTargetKey);
&Disposition); ZwClose(ScsiBusKey);
if (!NT_SUCCESS(Status)) ZwClose(ScsiPortKey);
{ return(Status);
DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); }
ZwClose(ScsiTargetKey);
ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey);
return(Status);
}
/* Set values for logical unit */ /* Set 'Type' (REG_SZ) value */
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; switch (LunExtension->InquiryData.DeviceType)
{
case 0:
TypeName = L"DiskPeripheral";
break;
case 1:
TypeName = L"TapePeripheral";
break;
case 2:
TypeName = L"PrinterPeripheral";
break;
case 4:
TypeName = L"WormPeripheral";
break;
case 5:
TypeName = L"CdRomPeripheral";
break;
case 6:
TypeName = L"ScannerPeripheral";
break;
case 7:
TypeName = L"OpticalDiskPeripheral";
break;
case 8:
TypeName = L"MediumChangerPeripheral";
break;
case 9:
TypeName = L"CommunicationPeripheral";
break;
default:
TypeName = L"OtherPeripheral";
break;
}
DPRINT(" Type = '%S'\n", TypeName);
RtlInitUnicodeString(&ValueName,
L"Type");
Status = ZwSetValueKey(ScsiLunKey,
&ValueName,
0,
REG_SZ,
TypeName,
(wcslen(TypeName) + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
ZwClose(ScsiLunKey);
ZwClose(ScsiTargetKey);
ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey);
return(Status);
}
/* Set 'Identifier' (REG_SZ) value */
swprintf(NameBuffer,
L"%.8S%.16S%.4S",
InquiryData->VendorId,
InquiryData->ProductId,
InquiryData->ProductRevisionLevel);
DPRINT(" Identifier = '%S'\n",
NameBuffer);
RtlInitUnicodeString(&ValueName,
L"Identifier");
Status = ZwSetValueKey(ScsiLunKey,
&ValueName,
0,
REG_SZ,
NameBuffer,
(wcslen(NameBuffer) + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
ZwClose(ScsiLunKey); ZwClose(ScsiLunKey);
ZwClose(ScsiTargetKey);
ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey);
return(Status);
} }
/* Set 'Type' (REG_SZ) value */
switch (InquiryData->DeviceType)
{
case 0:
TypeName = L"DiskPeripheral";
break;
case 1:
TypeName = L"TapePeripheral";
break;
case 2:
TypeName = L"PrinterPeripheral";
break;
case 4:
TypeName = L"WormPeripheral";
break;
case 5:
TypeName = L"CdRomPeripheral";
break;
case 6:
TypeName = L"ScannerPeripheral";
break;
case 7:
TypeName = L"OpticalDiskPeripheral";
break;
case 8:
TypeName = L"MediumChangerPeripheral";
break;
case 9:
TypeName = L"CommunicationPeripheral";
break;
default:
TypeName = L"OtherPeripheral";
break;
}
DPRINT(" Type = '%S'\n", TypeName);
RtlInitUnicodeString(&ValueName,
L"Type");
Status = ZwSetValueKey(ScsiLunKey,
&ValueName,
0,
REG_SZ,
TypeName,
(wcslen(TypeName) + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
ZwClose(ScsiLunKey);
ZwClose(ScsiTargetKey);
ZwClose(ScsiBusKey);
ZwClose(ScsiPortKey);
return(Status);
}
ZwClose(ScsiLunKey);
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
UnitInfo->NextInquiryDataOffset);
} }
/* Close old target key */ /* Close old target key */
@ -2032,8 +2125,8 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
} }
} }
ZwClose(ScsiBusKey); ZwClose(ScsiBusKey);
} }
ZwClose(ScsiPortKey); ZwClose(ScsiPortKey);

View file

@ -23,6 +23,26 @@ typedef struct _SCSI_PORT_DEVICE_BASE
ULONG SystemIoBusNumber; ULONG SystemIoBusNumber;
} SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE; } SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE;
typedef struct _SCSI_PORT_LUN_EXTENSION
{
LIST_ENTRY List;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
BOOLEAN DeviceClaimed;
PDEVICE_OBJECT DeviceObject;
INQUIRYDATA InquiryData;
/* More data? */
UCHAR MiniportLunExtension[1]; /* must be the last entry */
} SCSI_PORT_LUN_EXTENSION, *PSCSI_PORT_LUN_EXTENSION;
/* /*
* SCSI_PORT_DEVICE_EXTENSION * SCSI_PORT_DEVICE_EXTENSION
* *
@ -51,8 +71,8 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
LIST_ENTRY DeviceBaseListHead; LIST_ENTRY DeviceBaseListHead;
ULONG PortBusInfoSize; ULONG LunExtensionSize;
PSCSI_ADAPTER_BUS_INFO PortBusInfo; LIST_ENTRY LunExtensionListHead;
PIO_SCSI_CAPABILITIES PortCapabilities; PIO_SCSI_CAPABILITIES PortCapabilities;