mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:52:54 +00:00
Implemented IOCTL_SCSI_MINIPORT.
svn path=/trunk/; revision=18274
This commit is contained in:
parent
006fe6a358
commit
baac20f12f
1 changed files with 142 additions and 2 deletions
|
@ -33,6 +33,7 @@
|
||||||
#include <ddk/scsi.h>
|
#include <ddk/scsi.h>
|
||||||
#include <ddk/ntddscsi.h>
|
#include <ddk/ntddscsi.h>
|
||||||
#include <ddk/ntddstor.h>
|
#include <ddk/ntddstor.h>
|
||||||
|
#include <ddk/ntdddisk.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -138,6 +139,10 @@ SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
PSCSI_REQUEST_BLOCK Srb);
|
PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
@ -838,6 +843,9 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
|
|
||||||
DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
|
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... */
|
/* Set the buffering strategy here... */
|
||||||
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
||||||
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
||||||
|
@ -1771,8 +1779,7 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
DPRINT1(" IOCTL_SCSI_MINIPORT\n");
|
DPRINT1(" IOCTL_SCSI_MINIPORT\n");
|
||||||
DPRINT1(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
|
DPRINT1(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
|
||||||
DPRINT1(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
|
DPRINT1(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
return SpiScsiMiniport(DeviceObject, Irp);
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT1(" unknown ioctl code: 0x%lX\n",
|
DPRINT1(" unknown ioctl code: 0x%lX\n",
|
||||||
|
@ -1787,6 +1794,139 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
return Status;
|
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) + sizeof(SENDCMDINPARAMS) - 1)
|
||||||
|
{
|
||||||
|
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
|
static VOID
|
||||||
SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
PSCSI_REQUEST_BLOCK Srb)
|
PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue