mirror of
https://github.com/reactos/reactos.git
synced 2024-07-10 22:55:05 +00:00
1b45d9ee4b
CORE-17132
256 lines
8 KiB
C
256 lines
8 KiB
C
/*
|
|
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
* PURPOSE: IOCTL handlers
|
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
|
* Aleksey Bragin (aleksey@reactos.org)
|
|
*/
|
|
|
|
#include "scsiport.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SpiGetInquiryData(
|
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ PIRP Irp)
|
|
{
|
|
ULONG InquiryDataSize;
|
|
PSCSI_LUN_INFO LunInfo;
|
|
ULONG BusCount, LunCount, Length;
|
|
PIO_STACK_LOCATION IrpStack;
|
|
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
|
|
PSCSI_INQUIRY_DATA InquiryData;
|
|
PSCSI_BUS_DATA BusData;
|
|
ULONG Bus;
|
|
PUCHAR Buffer;
|
|
|
|
DPRINT("SpiGetInquiryData() called\n");
|
|
|
|
/* Get pointer to the buffer */
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
/* Initialize bus and LUN counters */
|
|
BusCount = DeviceExtension->BusesConfig->NumberOfBuses;
|
|
LunCount = 0;
|
|
|
|
/* Calculate total number of LUNs */
|
|
for (Bus = 0; Bus < BusCount; Bus++)
|
|
LunCount += DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
|
|
|
/* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
|
|
InquiryDataSize =
|
|
((sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE +
|
|
sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1));
|
|
|
|
/* Calculate data size */
|
|
Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) * sizeof(SCSI_BUS_DATA);
|
|
|
|
Length += InquiryDataSize * LunCount;
|
|
|
|
/* Check, if all data is going to fit into provided buffer */
|
|
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
/* Store data size in the IRP */
|
|
Irp->IoStatus.Information = Length;
|
|
|
|
DPRINT("Data size: %lu\n", Length);
|
|
|
|
AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
|
|
|
|
AdapterBusInfo->NumberOfBuses = (UCHAR)BusCount;
|
|
|
|
/* Point InquiryData to the corresponding place inside Buffer */
|
|
InquiryData = (PSCSI_INQUIRY_DATA)(Buffer + sizeof(SCSI_ADAPTER_BUS_INFO) +
|
|
(BusCount - 1) * sizeof(SCSI_BUS_DATA));
|
|
|
|
/* Loop each bus */
|
|
for (Bus = 0; Bus < BusCount; Bus++)
|
|
{
|
|
BusData = &AdapterBusInfo->BusData[Bus];
|
|
|
|
/* Calculate and save an offset of the inquiry data */
|
|
BusData->InquiryDataOffset = (ULONG)((PUCHAR)InquiryData - Buffer);
|
|
|
|
/* Get a pointer to the LUN information structure */
|
|
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
|
|
|
|
/* Store Initiator Bus Id */
|
|
BusData->InitiatorBusId =
|
|
DeviceExtension->BusesConfig->BusScanInfo[Bus]->BusIdentifier;
|
|
|
|
/* Store LUN count */
|
|
BusData->NumberOfLogicalUnits =
|
|
DeviceExtension->BusesConfig->BusScanInfo[Bus]->LogicalUnitsCount;
|
|
|
|
/* Loop all LUNs */
|
|
while (LunInfo != NULL)
|
|
{
|
|
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
|
|
Bus, LunInfo->TargetId, LunInfo->Lun);
|
|
|
|
/* Fill InquiryData with values */
|
|
InquiryData->PathId = LunInfo->PathId;
|
|
InquiryData->TargetId = LunInfo->TargetId;
|
|
InquiryData->Lun = LunInfo->Lun;
|
|
InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
|
InquiryData->DeviceClaimed = LunInfo->DeviceClaimed;
|
|
InquiryData->NextInquiryDataOffset =
|
|
(ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
|
|
|
|
/* Copy data in it */
|
|
RtlCopyMemory(InquiryData->InquiryData,
|
|
LunInfo->InquiryData,
|
|
INQUIRYDATABUFFERSIZE);
|
|
|
|
/* Move to the next LUN */
|
|
LunInfo = LunInfo->Next;
|
|
InquiryData = (PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData + InquiryDataSize);
|
|
}
|
|
|
|
/* Either mark the end, or set offset to 0 */
|
|
if (BusData->NumberOfLogicalUnits != 0)
|
|
((PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData - InquiryDataSize))->NextInquiryDataOffset = 0;
|
|
else
|
|
BusData->InquiryDataOffset = 0;
|
|
}
|
|
|
|
/* Finish with success */
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* NAME INTERNAL
|
|
* ScsiPortDeviceControl
|
|
*
|
|
* DESCRIPTION
|
|
* Answer requests for device control calls
|
|
*
|
|
* RUN LEVEL
|
|
* PASSIVE_LEVEL
|
|
*
|
|
* ARGUMENTS
|
|
* Standard dispatch arguments
|
|
*
|
|
* RETURNS
|
|
* NTSTATUS
|
|
*/
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ScsiPortDeviceControl(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_In_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION Stack;
|
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
|
PDUMP_POINTERS DumpPointers;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("ScsiPortDeviceControl()\n");
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_SCSI_GET_DUMP_POINTERS:
|
|
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
|
|
|
|
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DUMP_POINTERS))
|
|
{
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
|
break;
|
|
}
|
|
|
|
DumpPointers = Irp->AssociatedIrp.SystemBuffer;
|
|
DumpPointers->DeviceObject = DeviceObject;
|
|
/* More data.. ? */
|
|
|
|
Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
|
break;
|
|
|
|
case IOCTL_SCSI_GET_CAPABILITIES:
|
|
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
|
if (Stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
|
|
{
|
|
*((PVOID *)Irp->AssociatedIrp.SystemBuffer) = &DeviceExtension->PortCapabilities;
|
|
|
|
Irp->IoStatus.Information = sizeof(PVOID);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IO_SCSI_CAPABILITIES))
|
|
{
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
|
&DeviceExtension->PortCapabilities,
|
|
sizeof(IO_SCSI_CAPABILITIES));
|
|
|
|
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
|
DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
|
|
|
/* Copy inquiry data to the port device extension */
|
|
Status = SpiGetInquiryData(DeviceExtension, Irp);
|
|
break;
|
|
|
|
case IOCTL_SCSI_MINIPORT:
|
|
DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case IOCTL_SCSI_PASS_THROUGH:
|
|
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
default:
|
|
if (DEVICE_TYPE_FROM_CTL_CODE(Stack->Parameters.DeviceIoControl.IoControlCode) == MOUNTDEVCONTROLTYPE)
|
|
{
|
|
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
|
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");
|
|
break;
|
|
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
|
DPRINT1("Got unexpected IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
|
|
break;
|
|
default:
|
|
DPRINT(" got ioctl intended for the mount manager: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
|
break;
|
|
}
|
|
} else {
|
|
DPRINT1(" unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
|
}
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
/* Complete the request with the given status */
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|