scsiport.c
来自「一个类似windows」· C语言 代码 · 共 2,184 行 · 第 1/5 页
C
2,184 行
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;
}
/*
* @unimplemented
*/
SCSI_PHYSICAL_ADDRESS STDCALL
ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
IN PVOID VirtualAddress,
OUT ULONG *Length)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
SCSI_PHYSICAL_ADDRESS PhysicalAddress;
SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
ULONG BufferLength = 0;
ULONG Offset;
PVOID EndAddress;
DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
HwDeviceExtension, Srb, VirtualAddress, Length);
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
if (Length != NULL)
{
*Length = 0;
}
if (Srb == NULL)
{
EndAddress = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + DeviceExtension->CommonBufferLength);
if (VirtualAddress >= DeviceExtension->VirtualAddress && VirtualAddress < EndAddress)
{
Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
}
else
{
/*
* The given virtual address is not within the range
* of the drivers uncached extension or srb extension.
*/
/*
* FIXME:
* Check if the address is a sense info buffer of an active srb.
*/
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
if (PhysicalAddress.QuadPart == 0LL)
{
CHECKPOINT;
return PhysicalAddress;
}
BufferLength = PAGE_SIZE - PhysicalAddress.u.LowPart % PAGE_SIZE;
}
}
else
{
EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
if (VirtualAddress == NULL)
{
VirtualAddress = Srb->DataBuffer;
}
else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
{
EndAddress = (PVOID)((ULONG_PTR)Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength);
if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
{
PhysicalAddress.QuadPart = 0LL;
CHECKPOINT;
return PhysicalAddress;
}
}
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
if (PhysicalAddress.QuadPart == 0LL)
{
CHECKPOINT;
return PhysicalAddress;
}
BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
{
NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
{
break;
}
BufferLength += PAGE_SIZE;
}
if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
{
BufferLength = (ULONG)((ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress);
}
}
if (Length != NULL)
{
*Length = BufferLength;
}
DPRINT("Address %I64x, Length %d\n", PhysicalAddress.QuadPart, BufferLength);
return PhysicalAddress;
}
/*
* @unimplemented
*/
PSCSI_REQUEST_BLOCK STDCALL
ScsiPortGetSrb(IN PVOID HwDeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN LONG QueueTag)
{
DPRINT1("ScsiPortGetSrb() unimplemented\n");
UNIMPLEMENTED;
return NULL;
}
/*
* @implemented
*/
PVOID STDCALL
ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
IN ULONG NumberOfBytes)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
DEVICE_DESCRIPTION DeviceDescription;
DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
HwDeviceExtension, ConfigInfo, NumberOfBytes);
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
/* Check for allocated common DMA buffer */
if (DeviceExtension->VirtualAddress != NULL)
{
DPRINT1("The HBA has already got a common DMA buffer!\n");
return NULL;
}
/* Check for DMA adapter object */
if (DeviceExtension->AdapterObject == NULL)
{
/* Initialize DMA adapter description */
RtlZeroMemory(&DeviceDescription,
sizeof(DEVICE_DESCRIPTION));
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription.Master = ConfigInfo->Master;
DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
DeviceDescription.DemandMode = ConfigInfo->DemandMode;
DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
DeviceDescription.DmaPort = ConfigInfo->DmaPort;
/* Get a DMA adapter object */
DeviceExtension->AdapterObject = HalGetAdapter(&DeviceDescription,
&DeviceExtension->MapRegisterCount);
if (DeviceExtension->AdapterObject == NULL)
{
DPRINT1("HalGetAdapter() failed\n");
return NULL;
}
}
if (DeviceExtension->SrbExtensionSize > 0)
{
PVOID Buffer;
DeviceExtension->CurrentSrbExtensions = 0;
if (DeviceExtension->PortConfig->MultipleRequestPerLu)
{
DeviceExtension->MaxSrbExtensions = 1024;
}
else
{
DeviceExtension->MaxSrbExtensions = 32;
}
Buffer = ExAllocatePool(NonPagedPool, ROUND_UP(DeviceExtension->MaxSrbExtensions / 8, sizeof(ULONG)));
if (Buffer == NULL)
{
KEBUGCHECK(0);
return NULL;
}
RtlInitializeBitMap(&DeviceExtension->SrbExtensionAllocMap, Buffer, DeviceExtension->MaxSrbExtensions);
RtlClearAllBits(&DeviceExtension->SrbExtensionAllocMap);
}
/* Allocate a common DMA buffer */
DeviceExtension->CommonBufferLength =
NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions);
DeviceExtension->VirtualAddress =
HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
DeviceExtension->CommonBufferLength,
&DeviceExtension->PhysicalAddress,
FALSE);
if (DeviceExtension->VirtualAddress == NULL)
{
DPRINT1("HalAllocateCommonBuffer() failed!\n");
DeviceExtension->CommonBufferLength = 0;
return NULL;
}
return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions));
}
/*
* @implemented
*/
PVOID STDCALL
ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
ULONG Offset;
DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
HwDeviceExtension, PhysicalAddress.QuadPart);
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
return NULL;
Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
if (Offset >= DeviceExtension->CommonBufferLength)
return NULL;
return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
}
/**********************************************************************
* NAME EXPORTED
* ScsiPortInitialize
*
* DESCRIPTION
* Initializes SCSI port driver specific data.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* Argument1
* Pointer to the miniport driver's driver object.
*
* Argument2
* Pointer to the miniport driver's registry path.
*
* HwInitializationData
* Pointer to port driver specific configuration data.
*
* HwContext
Miniport driver specific context.
*
* RETURN VALUE
* Status.
*
* @implemented
*/
ULONG STDCALL
ScsiPortInitialize(IN PVOID Argument1,
IN PVOID Argument2,
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN PVOID HwContext)
{
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
// PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PCONFIGURATION_INFORMATION SystemConfig;
PPORT_CONFIGURATION_INFORMATION PortConfig;
ULONG DeviceExtensionSize;
ULONG PortConfigSize;
BOOLEAN Again;
BOOLEAN DeviceFound = FALSE;
ULONG i;
ULONG Result;
NTSTATUS Status;
ULONG MaxBus;
ULONG BusNumber;
PCI_SLOT_NUMBER SlotNumber;
PDEVICE_OBJECT PortDeviceObject;
WCHAR NameBuffer[80];
UNICODE_STRING DeviceName;
WCHAR DosNameBuffer[80];
UNICODE_STRING DosDeviceName;
PIO_SCSI_CAPABILITIES PortCapabilities;
ULONG MappedIrq;
KIRQL Dirql;
KAFFINITY Affinity;
DPRINT ("ScsiPortInitialize() called!\n");
#if 0
DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData->HwInitializationDataSize);
DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData->AdapterInterfaceType);
DPRINT1("HwInitialize: %x\n", HwInitializationData->HwInitialize);
DPRINT1("HwStartIo: %x\n", HwInitializationData->HwStartIo);
DPRINT1("HwInterrupt: %x\n", HwInitializationData->HwInterrupt);
DPRINT1("HwFindAdapter: %x\n", HwInitializationData->HwFindAdapter);
DPRINT1("HwResetBus: %x\n", HwInitializationData->HwResetBus);
DPRINT1("HwDmaStarted: %x\n", HwInitializationData->HwDmaStarted);
DPRINT1("HwAdapterState: %x\n", HwInitializationData->HwAdapterState);
DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData->DeviceExtensionSize);
DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData->SpecificLuExtensionSize);
DPRINT1("SrbExtensionSize: %d\n", HwInitializationData->SrbExtensionSize);
DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData->NumberOfAccessRanges);
DPRINT1("Reserved: %x\n", HwInitializationData->Reserved);
DPRINT1("MapBuffers: %d\n", HwInitializationData->MapBuffers);
DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData->NeedPhysicalAddresses);
DPRINT1("TaggedQueueing: %d\n", HwInitializationData->TaggedQueueing);
DPRINT1("AutoRequestSense: %d\n", HwInitializationData->AutoRequestSense);
DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData->MultipleRequestPerLu);
DPRINT1("ReceiveEvent: %d\n", HwInitializationData->ReceiveEvent);
DPRINT1("VendorIdLength: %d\n", HwInitializationData->VendorIdLength);
DPRINT1("VendorId: %x\n", HwInitializationData->VendorId);
DPRINT1("ReservedUshort: %d\n", HwInitializationData->ReservedUshort);
DPRINT1("DeviceIdLength: %d\n", HwInitializationData->DeviceIdLength);
DPRINT1("DeviceId: %x\n", HwInitializationData->DeviceId);
#endif
if ((HwInitializationData->HwInitialize == NULL) ||
(HwInitializationData->HwStartIo == NULL) ||
(HwInitializationData->HwInterrupt == NULL) ||
(HwInitializationData->HwFindAdapter == NULL) ||
(HwInitializationData->HwResetBus == NULL))
return(STATUS_INVALID_PARAMETER);
DriverObject->DriverStartIo = NULL;
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
SystemConfig = IoGetConfigurationInformation();
DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
HwInitializationData->DeviceExtensionSize;
PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
DPRINT("MaxBus: %lu\n", MaxBus);
PortDeviceObject = NULL;
BusNumber = 0;
SlotNumber.u.AsULONG = 0;
while (TRUE)
{
/* Create a unicode device name */
swprintf (NameBuffer,
L"\\Device\\ScsiPort%lu",
SystemConfig->ScsiPortCount);
RtlInitUnicodeString (&DeviceName,
NameBuffer);
DPRINT("Creating device: %wZ\n", &DeviceName);
/* Create the port device */
Status = IoCreateDevice (DriverObject,
DeviceExtensionSize,
&DeviceName,
FILE_DEVICE_CONTROLLER,
0,
FALSE,
&PortDeviceObject);
if (!NT_SUCCESS(Status))
{
DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
PortDeviceObject = NULL;
goto ByeBye;
}
DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
/* Increase the stacksize. We reenter our device on IOCTL_SCSI_MINIPORT */
PortDeviceObject->StackSize++;
/* Set the buffering strategy here... */
PortDeviceObject->Flags |= DO_DIRECT_IO;
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
DeviceExtension = PortDeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
DeviceExtension->Length = DeviceExtensionSize;
DeviceExtension->DeviceObject = PortDeviceObject;
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
DeviceExtension->AdapterObject = NULL;
DeviceExtension->MapRegisterCount = 0;
DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
DeviceExtension->VirtualAddress = NULL;
DeviceExtension->CommonBufferLength = 0;
/* Initialize the device base list */
InitializeListHead (&DeviceExtension->DeviceBaseListHead);
/* Initialize the irp lists */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?