scsiport.c
来自「一个类似windows」· C语言 代码 · 共 2,184 行 · 第 1/5 页
C
2,184 行
*((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
DeviceExtension->PortCapabilities;
Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
}
break;
case IOCTL_SCSI_GET_INQUIRY_DATA:
{
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
/* Copy inquiry data to the port device extension */
Irp->IoStatus.Information =
SpiGetInquiryData(DeviceExtension,
Irp->AssociatedIrp.SystemBuffer);
DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
}
break;
case IOCTL_SCSI_PASS_THROUGH:
DPRINT(" IOCTL_SCSI_PASS_THROUGH\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
DPRINT(" IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case IOCTL_SCSI_MINIPORT:
DPRINT(" IOCTL_SCSI_MINIPORT\n");
DPRINT(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
DPRINT(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
return SpiScsiMiniport(DeviceObject, Irp);
default:
DPRINT1(" unknown ioctl code: 0x%lX\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
static NTSTATUS STDCALL
SpiCompletion(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PSCSI_REQUEST_BLOCK Srb;
DPRINT("SpiCompletion(DeviceObject %x, Irp %x, Context %x)\n",
DeviceObject, Irp, Context);
Srb = (PSCSI_REQUEST_BLOCK)Context;
Irp->IoStatus.Information = 0;
switch (SRB_STATUS(Srb->SrbStatus))
{
case SRB_STATUS_SUCCESS:
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Srb->DataTransferLength;
break;
case SRB_STATUS_INVALID_PATH_ID:
case SRB_STATUS_INVALID_TARGET_ID:
case SRB_STATUS_INVALID_LUN:
case SRB_STATUS_NO_HBA:
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
break;
case SRB_STATUS_NO_DEVICE:
Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
break;
case SRB_STATUS_BUSY:
Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
break;
case SRB_STATUS_DATA_OVERRUN:
Irp->IoStatus.Status = STATUS_DATA_OVERRUN;
Irp->IoStatus.Information = Srb->DataTransferLength;
break;
case SRB_STATUS_INVALID_REQUEST:
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
break;
default:
Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
break;
}
ExFreePool(Srb);
if (Irp->PendingReturned)
{
IoMarkIrpPending (Irp);
}
return Irp->IoStatus.Status;
}
static NTSTATUS
SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSRB_IO_CONTROL SrbIoControl;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
PSCSI_PORT_LUN_EXTENSION LunExtension;
DPRINT("SpiScsiMiniport(DeviceObject %x, Irp %x)\n",
DeviceObject, Irp);
DeviceExtension = DeviceObject->DeviceExtension;
SrbIoControl = (PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL))
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SRB_IO_CONTROL) + SrbIoControl->Length)
{
Irp->IoStatus.Information = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
{
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_SUCH_DEVICE;
}
Srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
if (Srb == NULL)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
Srb->OriginalRequest = Irp;
Srb->Function = SRB_FUNCTION_IO_CONTROL;
Srb->DataBuffer = (PVOID)SrbIoControl;
Srb->DataTransferLength = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
/* We using the first extension from the list. The miniport driver is responsible to find the correct device. */
LunExtension = CONTAINING_RECORD(DeviceExtension->LunExtensionListHead.Flink,
SCSI_PORT_LUN_EXTENSION,
List);
Srb->PathId = LunExtension->PathId;
Srb->TargetId = LunExtension->TargetId;
Srb->Lun = LunExtension->Lun;
IrpStack = IoGetNextIrpStackLocation(Irp);
IrpStack->MajorFunction = IRP_MJ_SCSI;
IrpStack->Parameters.Scsi.Srb = Srb;
IoSetCompletionRoutine(Irp,
SpiCompletion,
Srb,
TRUE,
TRUE,
TRUE);
return IoCallDriver(DeviceObject, Irp);
}
static VOID
SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PSCSI_REQUEST_BLOCK Srb)
{
ULONG index;
DPRINT("SpiAllocateSrbExtension\n");
DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
Srb->SrbExtension = NULL;
if (DeviceExtension->VirtualAddress != NULL &&
DeviceExtension->SrbExtensionSize > 0)
{
index = RtlFindClearBitsAndSet(&DeviceExtension->SrbExtensionAllocMap, 1, 0);
if (index != 0xffffffff)
{
DeviceExtension->CurrentSrbExtensions++;
Srb->SrbExtension = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + index * DeviceExtension->SrbExtensionSize);
}
}
DPRINT("%x\n", Srb->SrbExtension);
}
static VOID
SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PSCSI_REQUEST_BLOCK Srb)
{
ULONG index;
if (DeviceExtension->VirtualAddress != NULL &&
DeviceExtension->SrbExtensionSize > 0 &&
Srb->SrbExtension != NULL)
{
index = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
RtlClearBits(&DeviceExtension->SrbExtensionAllocMap, index, 1);
DeviceExtension->CurrentSrbExtensions--;
}
Srb->SrbExtension = NULL;
}
static BOOLEAN STDCALL
ScsiPortStartPacket(IN OUT PVOID Context)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSCSI_REQUEST_BLOCK Srb;
PIRP Irp;
PIO_STACK_LOCATION IrpStack;
DPRINT("ScsiPortStartPacket(Context %x) called\n", Context);
Srb = (PSCSI_REQUEST_BLOCK)Context;
Irp = (PIRP)Srb->OriginalRequest;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = IrpStack->DeviceObject->DeviceExtension;
return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
Srb));
}
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;
LunExtension->PendingIrpCount = 0;
LunExtension->ActiveIrpCount = 0;
LunExtension->NextIrp = NULL;
return LunExtension;
}
static VOID
SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension)
{
DPRINT("SpiRemoveLunExtension(%p) called\n",
LunExtension);
if (LunExtension == NULL)
return;
RemoveEntryList (&LunExtension->List);
/* Release LUN extersion data */
ExFreePool (LunExtension);
return;
}
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 NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
IN OUT PSCSI_REQUEST_BLOCK Srb,
IN OUT PIO_STATUS_BLOCK IoStatusBlock,
IN OUT PKEVENT Event)
{
PIO_STACK_LOCATION IrpStack;
PIRP Irp;
NTSTATUS Status;
DPRINT ("SpiSendInquiry() called\n");
KeInitializeEvent (Event,
NotificationEvent,
FALSE);
Irp = IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT,
DeviceObject,
NULL,
0,
Srb->DataBuffer,
Srb->DataTransferLength,
TRUE,
Event,
IoStatusBlock);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Attach Srb to the Irp */
IrpStack = IoGetNextIrpStackLocation (Irp);
IrpStack->Parameters.Scsi.Srb = Srb;
Srb->OriginalRequest = Irp;
/* Call the driver */
Status = IoCallDriver (DeviceObject,
Irp);
return Status;
}
static VOID
SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
{
PSCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
ULONG Bus;
ULONG Target;
PSCSI_PORT_SCAN_ADAPTER ScanDataArray;
PSCSI_PORT_SCAN_ADAPTER ScanData;
ULONG i;
ULONG MaxCount;
ULONG WaitCount;
ULONG ActiveCount;
PVOID* EventArray;
PKWAIT_BLOCK WaitBlockArray;
DPRINT ("SpiScanAdapter() called\n");
MaxCount = DeviceExtension->PortConfig->NumberOfBuses *
DeviceExtension->PortConfig->MaximumNumberOfTargets;
ScanDataArray = ExAllocatePool(NonPagedPool, MaxCount * (sizeof(SCSI_PORT_SCAN_ADAPTER) + sizeof(PVOID) + sizeof(KWAIT_BLOCK)));
if (ScanDataArray == NULL)
{
return;
}
EventArray = (PVOID*)((PUCHAR)ScanDataArray + MaxCount * sizeof(SCSI_PORT_SCAN_ADAPTER));
WaitBlockArray = (PKWAIT_BLOCK)((PUCHAR)EventArray + MaxCount * sizeof(PVOID));
for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
{
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
{
ScanData = &ScanDataArray[Bus * DeviceExtension->PortConfig->MaximumNumberOfTargets + Target];
ScanData->Bus = Bus;
ScanData->Target = Target;
ScanData->Lun = 0;
ScanData->Active = FALSE;
}
}
do
{
ActiveCount = 0;
WaitCount = 0;
for (i = 0; i < MaxCount; i++)
{
ScanData = &ScanDataArray[i];
Srb = &ScanData->Srb;
if (ScanData->Active)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?