xref: /reactos/drivers/storage/port/scsiport/ioctl.c (revision cbe88e28)
11b45d9eeSVictor Perevertkin /*
21b45d9eeSVictor Perevertkin  * PROJECT:     ReactOS Storage Stack / SCSIPORT storage port library
31b45d9eeSVictor Perevertkin  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
41b45d9eeSVictor Perevertkin  * PURPOSE:     IOCTL handlers
51b45d9eeSVictor Perevertkin  * COPYRIGHT:   Eric Kohl (eric.kohl@reactos.org)
61b45d9eeSVictor Perevertkin  *              Aleksey Bragin (aleksey@reactos.org)
7a97c6e0aSVictor Perevertkin  *              2020 Victor Perevertkin (victor.perevertkin@reactos.org)
81b45d9eeSVictor Perevertkin  */
91b45d9eeSVictor Perevertkin 
101b45d9eeSVictor Perevertkin #include "scsiport.h"
111b45d9eeSVictor Perevertkin 
121b45d9eeSVictor Perevertkin #define NDEBUG
131b45d9eeSVictor Perevertkin #include <debug.h>
141b45d9eeSVictor Perevertkin 
151b45d9eeSVictor Perevertkin 
161b45d9eeSVictor Perevertkin static
171b45d9eeSVictor Perevertkin NTSTATUS
SpiGetInquiryData(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,_In_ PIRP Irp)181b45d9eeSVictor Perevertkin SpiGetInquiryData(
191b45d9eeSVictor Perevertkin     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
201b45d9eeSVictor Perevertkin     _In_ PIRP Irp)
211b45d9eeSVictor Perevertkin {
221b45d9eeSVictor Perevertkin     ULONG InquiryDataSize;
23a97c6e0aSVictor Perevertkin     ULONG BusCount, Length;
241b45d9eeSVictor Perevertkin     PIO_STACK_LOCATION IrpStack;
251b45d9eeSVictor Perevertkin     PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
261b45d9eeSVictor Perevertkin     PSCSI_INQUIRY_DATA InquiryData;
271b45d9eeSVictor Perevertkin     PUCHAR Buffer;
281b45d9eeSVictor Perevertkin 
291b45d9eeSVictor Perevertkin     DPRINT("SpiGetInquiryData() called\n");
301b45d9eeSVictor Perevertkin 
311b45d9eeSVictor Perevertkin     /* Get pointer to the buffer */
321b45d9eeSVictor Perevertkin     IrpStack = IoGetCurrentIrpStackLocation(Irp);
331b45d9eeSVictor Perevertkin     Buffer = Irp->AssociatedIrp.SystemBuffer;
341b45d9eeSVictor Perevertkin 
351b45d9eeSVictor Perevertkin     /* Initialize bus and LUN counters */
36a97c6e0aSVictor Perevertkin     BusCount = DeviceExtension->NumberOfBuses;
371b45d9eeSVictor Perevertkin 
381b45d9eeSVictor Perevertkin     /* Calculate size of inquiry data, rounding up to sizeof(ULONG) */
39a97c6e0aSVictor Perevertkin     InquiryDataSize = ALIGN_UP(sizeof(SCSI_INQUIRY_DATA) - 1 + INQUIRYDATABUFFERSIZE, ULONG);
401b45d9eeSVictor Perevertkin 
411b45d9eeSVictor Perevertkin     /* Calculate data size */
421b45d9eeSVictor Perevertkin     Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) * sizeof(SCSI_BUS_DATA);
431b45d9eeSVictor Perevertkin 
44a97c6e0aSVictor Perevertkin     Length += InquiryDataSize * DeviceExtension->TotalLUCount;
451b45d9eeSVictor Perevertkin 
461b45d9eeSVictor Perevertkin     /* Check, if all data is going to fit into provided buffer */
471b45d9eeSVictor Perevertkin     if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < Length)
481b45d9eeSVictor Perevertkin     {
491b45d9eeSVictor Perevertkin         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
501b45d9eeSVictor Perevertkin         return STATUS_BUFFER_TOO_SMALL;
511b45d9eeSVictor Perevertkin     }
521b45d9eeSVictor Perevertkin 
531b45d9eeSVictor Perevertkin     /* Store data size in the IRP */
541b45d9eeSVictor Perevertkin     Irp->IoStatus.Information = Length;
551b45d9eeSVictor Perevertkin 
561b45d9eeSVictor Perevertkin     DPRINT("Data size: %lu\n", Length);
571b45d9eeSVictor Perevertkin 
581b45d9eeSVictor Perevertkin     AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
591b45d9eeSVictor Perevertkin 
601b45d9eeSVictor Perevertkin     AdapterBusInfo->NumberOfBuses = (UCHAR)BusCount;
611b45d9eeSVictor Perevertkin 
621b45d9eeSVictor Perevertkin     /* Point InquiryData to the corresponding place inside Buffer */
631b45d9eeSVictor Perevertkin     InquiryData = (PSCSI_INQUIRY_DATA)(Buffer + sizeof(SCSI_ADAPTER_BUS_INFO) +
641b45d9eeSVictor Perevertkin                     (BusCount - 1) * sizeof(SCSI_BUS_DATA));
651b45d9eeSVictor Perevertkin 
661b45d9eeSVictor Perevertkin     /* Loop each bus */
67a97c6e0aSVictor Perevertkin     for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
681b45d9eeSVictor Perevertkin     {
69a97c6e0aSVictor Perevertkin         PSCSI_BUS_DATA BusData = &AdapterBusInfo->BusData[pathId];
701b45d9eeSVictor Perevertkin 
711b45d9eeSVictor Perevertkin         /* Calculate and save an offset of the inquiry data */
721b45d9eeSVictor Perevertkin         BusData->InquiryDataOffset = (ULONG)((PUCHAR)InquiryData - Buffer);
731b45d9eeSVictor Perevertkin 
741b45d9eeSVictor Perevertkin         /* Store Initiator Bus Id */
75a97c6e0aSVictor Perevertkin         BusData->InitiatorBusId = DeviceExtension->Buses[pathId].BusIdentifier;
761b45d9eeSVictor Perevertkin 
771b45d9eeSVictor Perevertkin         /* Store LUN count */
78a97c6e0aSVictor Perevertkin         BusData->NumberOfLogicalUnits = DeviceExtension->Buses[pathId].LogicalUnitsCount;
791b45d9eeSVictor Perevertkin 
801b45d9eeSVictor Perevertkin         /* Loop all LUNs */
81a97c6e0aSVictor Perevertkin         PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
82a97c6e0aSVictor Perevertkin 
83a97c6e0aSVictor Perevertkin         for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
84a97c6e0aSVictor Perevertkin              lunEntry != &bus->LunsListHead;
85a97c6e0aSVictor Perevertkin              lunEntry = lunEntry->Flink)
861b45d9eeSVictor Perevertkin         {
87a97c6e0aSVictor Perevertkin             PSCSI_PORT_LUN_EXTENSION lunExt =
88a97c6e0aSVictor Perevertkin                 CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
89a97c6e0aSVictor Perevertkin 
90a97c6e0aSVictor Perevertkin             DPRINT("(Bus %lu Target %lu Lun %lu)\n", pathId, lunExt->TargetId, lunExt->Lun);
911b45d9eeSVictor Perevertkin 
921b45d9eeSVictor Perevertkin             /* Fill InquiryData with values */
93a97c6e0aSVictor Perevertkin             InquiryData->PathId = lunExt->PathId;
94a97c6e0aSVictor Perevertkin             InquiryData->TargetId = lunExt->TargetId;
95a97c6e0aSVictor Perevertkin             InquiryData->Lun = lunExt->Lun;
961b45d9eeSVictor Perevertkin             InquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
97a97c6e0aSVictor Perevertkin             InquiryData->DeviceClaimed = lunExt->DeviceClaimed;
981b45d9eeSVictor Perevertkin             InquiryData->NextInquiryDataOffset =
991b45d9eeSVictor Perevertkin                 (ULONG)((PUCHAR)InquiryData + InquiryDataSize - Buffer);
1001b45d9eeSVictor Perevertkin 
1011b45d9eeSVictor Perevertkin             /* Copy data in it */
1021b45d9eeSVictor Perevertkin             RtlCopyMemory(InquiryData->InquiryData,
103a97c6e0aSVictor Perevertkin                           &lunExt->InquiryData,
1041b45d9eeSVictor Perevertkin                           INQUIRYDATABUFFERSIZE);
1051b45d9eeSVictor Perevertkin 
1061b45d9eeSVictor Perevertkin             /* Move to the next LUN */
107a97c6e0aSVictor Perevertkin             InquiryData = (PSCSI_INQUIRY_DATA) ((ULONG_PTR)InquiryData + InquiryDataSize);
1081b45d9eeSVictor Perevertkin         }
1091b45d9eeSVictor Perevertkin 
1101b45d9eeSVictor Perevertkin         /* Either mark the end, or set offset to 0 */
1111b45d9eeSVictor Perevertkin         if (BusData->NumberOfLogicalUnits != 0)
1121b45d9eeSVictor Perevertkin             ((PSCSI_INQUIRY_DATA) ((PCHAR)InquiryData - InquiryDataSize))->NextInquiryDataOffset = 0;
1131b45d9eeSVictor Perevertkin         else
1141b45d9eeSVictor Perevertkin             BusData->InquiryDataOffset = 0;
1151b45d9eeSVictor Perevertkin     }
1161b45d9eeSVictor Perevertkin 
1171b45d9eeSVictor Perevertkin     /* Finish with success */
1181b45d9eeSVictor Perevertkin     Irp->IoStatus.Status = STATUS_SUCCESS;
1191b45d9eeSVictor Perevertkin     return STATUS_SUCCESS;
1201b45d9eeSVictor Perevertkin }
1211b45d9eeSVictor Perevertkin 
122a97c6e0aSVictor Perevertkin static
123a97c6e0aSVictor Perevertkin UINT32
GetFieldLength(_In_ PUCHAR Name,_In_ UINT32 MaxLength)124a97c6e0aSVictor Perevertkin GetFieldLength(
125a97c6e0aSVictor Perevertkin     _In_ PUCHAR Name,
126a97c6e0aSVictor Perevertkin     _In_ UINT32 MaxLength)
127a97c6e0aSVictor Perevertkin {
128a97c6e0aSVictor Perevertkin     UINT32 Index;
129a97c6e0aSVictor Perevertkin     UINT32 LastCharacterPosition = 0;
130a97c6e0aSVictor Perevertkin 
131a97c6e0aSVictor Perevertkin     // scan the field and return last position which contains a valid character
132a97c6e0aSVictor Perevertkin     for (Index = 0; Index < MaxLength; Index++)
133a97c6e0aSVictor Perevertkin     {
134a97c6e0aSVictor Perevertkin         if (Name[Index] != ' ')
135a97c6e0aSVictor Perevertkin         {
136a97c6e0aSVictor Perevertkin             // trim white spaces from field
137a97c6e0aSVictor Perevertkin             LastCharacterPosition = Index;
138a97c6e0aSVictor Perevertkin         }
139a97c6e0aSVictor Perevertkin     }
140a97c6e0aSVictor Perevertkin 
141a97c6e0aSVictor Perevertkin     // convert from zero based index to length
142a97c6e0aSVictor Perevertkin     return LastCharacterPosition + 1;
143a97c6e0aSVictor Perevertkin }
144a97c6e0aSVictor Perevertkin 
145a97c6e0aSVictor Perevertkin static
146a97c6e0aSVictor Perevertkin NTSTATUS
PdoHandleQueryProperty(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)147a97c6e0aSVictor Perevertkin PdoHandleQueryProperty(
148a97c6e0aSVictor Perevertkin     _In_ PDEVICE_OBJECT DeviceObject,
149a97c6e0aSVictor Perevertkin     _Inout_ PIRP Irp)
150a97c6e0aSVictor Perevertkin {
151a97c6e0aSVictor Perevertkin     PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
152a97c6e0aSVictor Perevertkin     PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
153a97c6e0aSVictor Perevertkin     NTSTATUS status;
154a97c6e0aSVictor Perevertkin 
155a97c6e0aSVictor Perevertkin     ASSERT(ioStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
156a97c6e0aSVictor Perevertkin     ASSERT(Irp->AssociatedIrp.SystemBuffer);
157a97c6e0aSVictor Perevertkin     ASSERT(!lunExt->Common.IsFDO);
158a97c6e0aSVictor Perevertkin 
159a97c6e0aSVictor Perevertkin     PSTORAGE_PROPERTY_QUERY PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
160a97c6e0aSVictor Perevertkin 
161a97c6e0aSVictor Perevertkin     // check property type
162a97c6e0aSVictor Perevertkin     if (PropertyQuery->PropertyId != StorageDeviceProperty &&
163a97c6e0aSVictor Perevertkin         PropertyQuery->PropertyId != StorageAdapterProperty)
164a97c6e0aSVictor Perevertkin     {
165a97c6e0aSVictor Perevertkin         // only device property / adapter property are supported
166a97c6e0aSVictor Perevertkin         status = STATUS_INVALID_PARAMETER_1;
167a97c6e0aSVictor Perevertkin         goto completeIrp;
168a97c6e0aSVictor Perevertkin     }
169a97c6e0aSVictor Perevertkin 
170a97c6e0aSVictor Perevertkin     // check query type
171a97c6e0aSVictor Perevertkin     if (PropertyQuery->QueryType == PropertyExistsQuery)
172a97c6e0aSVictor Perevertkin     {
173a97c6e0aSVictor Perevertkin         // device property / adapter property is supported
174a97c6e0aSVictor Perevertkin         status = STATUS_SUCCESS;
175a97c6e0aSVictor Perevertkin         goto completeIrp;
176a97c6e0aSVictor Perevertkin     }
177a97c6e0aSVictor Perevertkin 
178a97c6e0aSVictor Perevertkin     if (PropertyQuery->QueryType != PropertyStandardQuery)
179a97c6e0aSVictor Perevertkin     {
180a97c6e0aSVictor Perevertkin         // only standard query and exists query are supported
181a97c6e0aSVictor Perevertkin         status = STATUS_INVALID_PARAMETER_2;
182a97c6e0aSVictor Perevertkin         goto completeIrp;
183a97c6e0aSVictor Perevertkin     }
184a97c6e0aSVictor Perevertkin 
185a97c6e0aSVictor Perevertkin     switch (PropertyQuery->PropertyId)
186a97c6e0aSVictor Perevertkin     {
187a97c6e0aSVictor Perevertkin         case StorageDeviceProperty:
188a97c6e0aSVictor Perevertkin         {
189a97c6e0aSVictor Perevertkin             PINQUIRYDATA inquiryData = &lunExt->InquiryData;
190a97c6e0aSVictor Perevertkin 
191a97c6e0aSVictor Perevertkin             // compute extra parameters length
192a97c6e0aSVictor Perevertkin             UINT32 FieldLengthVendor = GetFieldLength(inquiryData->VendorId, 8),
193a97c6e0aSVictor Perevertkin                 FieldLengthProduct = GetFieldLength(inquiryData->ProductId, 16),
194a97c6e0aSVictor Perevertkin                 FieldLengthRevision = GetFieldLength(inquiryData->ProductRevisionLevel, 4);
195a97c6e0aSVictor Perevertkin 
196a97c6e0aSVictor Perevertkin             // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
197a97c6e0aSVictor Perevertkin             // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
198a97c6e0aSVictor Perevertkin             UINT32 TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR)
199a97c6e0aSVictor Perevertkin                                  + FieldLengthVendor
200a97c6e0aSVictor Perevertkin                                  + FieldLengthProduct
201a97c6e0aSVictor Perevertkin                                  + FieldLengthRevision
202a97c6e0aSVictor Perevertkin                                  + 3;
203a97c6e0aSVictor Perevertkin 
204a97c6e0aSVictor Perevertkin             // check if output buffer is long enough
205a97c6e0aSVictor Perevertkin             if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
206a97c6e0aSVictor Perevertkin             {
207a97c6e0aSVictor Perevertkin                 // buffer too small
208a97c6e0aSVictor Perevertkin                 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader = Irp->AssociatedIrp.SystemBuffer;
209a97c6e0aSVictor Perevertkin                 ASSERT(ioStack->Parameters.DeviceIoControl.OutputBufferLength >=
210a97c6e0aSVictor Perevertkin                        sizeof(STORAGE_DESCRIPTOR_HEADER));
211a97c6e0aSVictor Perevertkin 
212a97c6e0aSVictor Perevertkin                 // return required size
213a97c6e0aSVictor Perevertkin                 DescriptorHeader->Version = TotalLength;
214a97c6e0aSVictor Perevertkin                 DescriptorHeader->Size = TotalLength;
215a97c6e0aSVictor Perevertkin 
216a97c6e0aSVictor Perevertkin                 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
217a97c6e0aSVictor Perevertkin                 status = STATUS_SUCCESS;
218a97c6e0aSVictor Perevertkin                 goto completeIrp;
219a97c6e0aSVictor Perevertkin             }
220a97c6e0aSVictor Perevertkin 
221a97c6e0aSVictor Perevertkin             // initialize the device descriptor
222a97c6e0aSVictor Perevertkin             PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = Irp->AssociatedIrp.SystemBuffer;
223a97c6e0aSVictor Perevertkin 
224a97c6e0aSVictor Perevertkin             deviceDescriptor->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR);
225a97c6e0aSVictor Perevertkin             deviceDescriptor->Size = TotalLength;
226a97c6e0aSVictor Perevertkin             deviceDescriptor->DeviceType = inquiryData->DeviceType;
227a97c6e0aSVictor Perevertkin             deviceDescriptor->DeviceTypeModifier = inquiryData->DeviceTypeModifier;
228a97c6e0aSVictor Perevertkin             deviceDescriptor->RemovableMedia = inquiryData->RemovableMedia;
229a97c6e0aSVictor Perevertkin             deviceDescriptor->CommandQueueing = inquiryData->CommandQueue;
230a97c6e0aSVictor Perevertkin             deviceDescriptor->BusType = BusTypeScsi;
231a97c6e0aSVictor Perevertkin             deviceDescriptor->VendorIdOffset =
232a97c6e0aSVictor Perevertkin                 FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties);
233a97c6e0aSVictor Perevertkin             deviceDescriptor->ProductIdOffset =
234a97c6e0aSVictor Perevertkin                 deviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
235a97c6e0aSVictor Perevertkin             deviceDescriptor->ProductRevisionOffset =
236a97c6e0aSVictor Perevertkin                 deviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
237a97c6e0aSVictor Perevertkin             deviceDescriptor->SerialNumberOffset = 0;
238a97c6e0aSVictor Perevertkin             deviceDescriptor->RawPropertiesLength =
239a97c6e0aSVictor Perevertkin                 FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3;
240a97c6e0aSVictor Perevertkin 
241a97c6e0aSVictor Perevertkin             // copy descriptors
242a97c6e0aSVictor Perevertkin             PUCHAR Buffer = deviceDescriptor->RawDeviceProperties;
243a97c6e0aSVictor Perevertkin 
244a97c6e0aSVictor Perevertkin             RtlCopyMemory(Buffer, inquiryData->VendorId, FieldLengthVendor);
245a97c6e0aSVictor Perevertkin             Buffer[FieldLengthVendor] = '\0';
246a97c6e0aSVictor Perevertkin             Buffer += FieldLengthVendor + 1;
247a97c6e0aSVictor Perevertkin 
248a97c6e0aSVictor Perevertkin             RtlCopyMemory(Buffer, inquiryData->ProductId, FieldLengthProduct);
249a97c6e0aSVictor Perevertkin             Buffer[FieldLengthProduct] = '\0';
250a97c6e0aSVictor Perevertkin             Buffer += FieldLengthProduct + 1;
251a97c6e0aSVictor Perevertkin 
252a97c6e0aSVictor Perevertkin             RtlCopyMemory(Buffer, inquiryData->ProductRevisionLevel, FieldLengthRevision);
253a97c6e0aSVictor Perevertkin             Buffer[FieldLengthRevision] = '\0';
254a97c6e0aSVictor Perevertkin             Buffer += FieldLengthRevision + 1;
255a97c6e0aSVictor Perevertkin 
256a97c6e0aSVictor Perevertkin             DPRINT("Vendor %s\n",
257a97c6e0aSVictor Perevertkin                 (LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->VendorIdOffset));
258a97c6e0aSVictor Perevertkin             DPRINT("Product %s\n",
259a97c6e0aSVictor Perevertkin                 (LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->ProductIdOffset));
260a97c6e0aSVictor Perevertkin             DPRINT("Revision %s\n",
261a97c6e0aSVictor Perevertkin                 (LPCSTR)((ULONG_PTR)deviceDescriptor + deviceDescriptor->ProductRevisionOffset));
262a97c6e0aSVictor Perevertkin 
263a97c6e0aSVictor Perevertkin             Irp->IoStatus.Information = TotalLength;
264a97c6e0aSVictor Perevertkin             status = STATUS_SUCCESS;
265a97c6e0aSVictor Perevertkin             goto completeIrp;
266a97c6e0aSVictor Perevertkin         }
267a97c6e0aSVictor Perevertkin         case StorageAdapterProperty:
268a97c6e0aSVictor Perevertkin         {
269a97c6e0aSVictor Perevertkin             // forward to the lower device
270a97c6e0aSVictor Perevertkin             IoSkipCurrentIrpStackLocation(Irp);
271a97c6e0aSVictor Perevertkin             return IoCallDriver(lunExt->Common.LowerDevice, Irp);
272a97c6e0aSVictor Perevertkin         }
273a97c6e0aSVictor Perevertkin         case StorageDeviceIdProperty:
274a97c6e0aSVictor Perevertkin         {
275a97c6e0aSVictor Perevertkin             // TODO
276a97c6e0aSVictor Perevertkin         }
277a97c6e0aSVictor Perevertkin         default:
278a97c6e0aSVictor Perevertkin         {
279a97c6e0aSVictor Perevertkin             UNREACHABLE;
280a97c6e0aSVictor Perevertkin             status = STATUS_NOT_IMPLEMENTED;
281a97c6e0aSVictor Perevertkin             goto completeIrp;
282a97c6e0aSVictor Perevertkin         }
283a97c6e0aSVictor Perevertkin     }
284a97c6e0aSVictor Perevertkin 
285a97c6e0aSVictor Perevertkin completeIrp:
286a97c6e0aSVictor Perevertkin     Irp->IoStatus.Status = status;
287a97c6e0aSVictor Perevertkin     IoCompleteRequest(Irp, IO_NO_INCREMENT);
288a97c6e0aSVictor Perevertkin     return status;
289a97c6e0aSVictor Perevertkin }
290a97c6e0aSVictor Perevertkin 
291a97c6e0aSVictor Perevertkin static
292a97c6e0aSVictor Perevertkin NTSTATUS
FdoHandleQueryProperty(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)293a97c6e0aSVictor Perevertkin FdoHandleQueryProperty(
294a97c6e0aSVictor Perevertkin     _In_ PDEVICE_OBJECT DeviceObject,
295a97c6e0aSVictor Perevertkin     _Inout_ PIRP Irp)
296a97c6e0aSVictor Perevertkin {
297a97c6e0aSVictor Perevertkin     PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
298a97c6e0aSVictor Perevertkin     PSCSI_PORT_DEVICE_EXTENSION portExt = DeviceObject->DeviceExtension;
299a97c6e0aSVictor Perevertkin     NTSTATUS status;
300a97c6e0aSVictor Perevertkin 
301a97c6e0aSVictor Perevertkin     ASSERT(ioStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
302a97c6e0aSVictor Perevertkin     ASSERT(Irp->AssociatedIrp.SystemBuffer);
303a97c6e0aSVictor Perevertkin     ASSERT(portExt->Common.IsFDO);
304a97c6e0aSVictor Perevertkin 
305a97c6e0aSVictor Perevertkin     PSTORAGE_PROPERTY_QUERY PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
306a97c6e0aSVictor Perevertkin 
307a97c6e0aSVictor Perevertkin     // check property type (handle only StorageAdapterProperty)
308a97c6e0aSVictor Perevertkin     if (PropertyQuery->PropertyId != StorageAdapterProperty)
309a97c6e0aSVictor Perevertkin     {
310a97c6e0aSVictor Perevertkin         if (PropertyQuery->PropertyId == StorageDeviceProperty ||
311a97c6e0aSVictor Perevertkin             PropertyQuery->PropertyId == StorageDeviceIdProperty)
312a97c6e0aSVictor Perevertkin         {
313a97c6e0aSVictor Perevertkin             status = STATUS_INVALID_DEVICE_REQUEST;
314a97c6e0aSVictor Perevertkin         }
315a97c6e0aSVictor Perevertkin         else
316a97c6e0aSVictor Perevertkin         {
317a97c6e0aSVictor Perevertkin             status = STATUS_INVALID_PARAMETER_1;
318a97c6e0aSVictor Perevertkin         }
319a97c6e0aSVictor Perevertkin 
320a97c6e0aSVictor Perevertkin         goto completeIrp;
321a97c6e0aSVictor Perevertkin     }
322a97c6e0aSVictor Perevertkin 
323a97c6e0aSVictor Perevertkin     // check query type
324a97c6e0aSVictor Perevertkin     if (PropertyQuery->QueryType == PropertyExistsQuery)
325a97c6e0aSVictor Perevertkin     {
326a97c6e0aSVictor Perevertkin         // device property / adapter property is supported
327a97c6e0aSVictor Perevertkin         status = STATUS_SUCCESS;
328a97c6e0aSVictor Perevertkin         goto completeIrp;
329a97c6e0aSVictor Perevertkin     }
330a97c6e0aSVictor Perevertkin 
331a97c6e0aSVictor Perevertkin     if (PropertyQuery->QueryType != PropertyStandardQuery)
332a97c6e0aSVictor Perevertkin     {
333a97c6e0aSVictor Perevertkin         // only standard query and exists query are supported
334a97c6e0aSVictor Perevertkin         status = STATUS_INVALID_PARAMETER_2;
335a97c6e0aSVictor Perevertkin         goto completeIrp;
336a97c6e0aSVictor Perevertkin     }
337a97c6e0aSVictor Perevertkin 
338*cbe88e28SVictor Perevertkin     if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8))
339a97c6e0aSVictor Perevertkin     {
340a97c6e0aSVictor Perevertkin         // buffer too small
341a97c6e0aSVictor Perevertkin         PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader = Irp->AssociatedIrp.SystemBuffer;
342a97c6e0aSVictor Perevertkin         ASSERT(ioStack->Parameters.DeviceIoControl.OutputBufferLength
343a97c6e0aSVictor Perevertkin                >= sizeof(STORAGE_DESCRIPTOR_HEADER));
344a97c6e0aSVictor Perevertkin 
345a97c6e0aSVictor Perevertkin         // return required size
346*cbe88e28SVictor Perevertkin         DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
347*cbe88e28SVictor Perevertkin         DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
348a97c6e0aSVictor Perevertkin 
349a97c6e0aSVictor Perevertkin         Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
350a97c6e0aSVictor Perevertkin         status = STATUS_SUCCESS;
351a97c6e0aSVictor Perevertkin         goto completeIrp;
352a97c6e0aSVictor Perevertkin     }
353a97c6e0aSVictor Perevertkin 
354a97c6e0aSVictor Perevertkin     // get adapter descriptor, information is returned in the same buffer
355*cbe88e28SVictor Perevertkin     PSTORAGE_ADAPTER_DESCRIPTOR_WIN8 adapterDescriptor = Irp->AssociatedIrp.SystemBuffer;
356a97c6e0aSVictor Perevertkin 
357a97c6e0aSVictor Perevertkin     // fill out descriptor
358*cbe88e28SVictor Perevertkin     // NOTE: STORAGE_ADAPTER_DESCRIPTOR_WIN8 may vary in size, so it's important to zero out
359a97c6e0aSVictor Perevertkin     // all unused fields
360*cbe88e28SVictor Perevertkin     *adapterDescriptor = (STORAGE_ADAPTER_DESCRIPTOR_WIN8) {
361*cbe88e28SVictor Perevertkin         .Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
362*cbe88e28SVictor Perevertkin         .Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
363a97c6e0aSVictor Perevertkin         .MaximumTransferLength = portExt->PortCapabilities.MaximumTransferLength,
364a97c6e0aSVictor Perevertkin         .MaximumPhysicalPages = portExt->PortCapabilities.MaximumPhysicalPages,
365a97c6e0aSVictor Perevertkin         .AlignmentMask = portExt->PortCapabilities.AlignmentMask,
366a97c6e0aSVictor Perevertkin         .AdapterUsesPio = portExt->PortCapabilities.AdapterUsesPio,
367a97c6e0aSVictor Perevertkin         .AdapterScansDown = portExt->PortCapabilities.AdapterScansDown,
368a97c6e0aSVictor Perevertkin         .CommandQueueing = portExt->PortCapabilities.TaggedQueuing,
369a97c6e0aSVictor Perevertkin         .AcceleratedTransfer = TRUE,
370a97c6e0aSVictor Perevertkin         .BusType = BusTypeScsi, // FIXME
371a97c6e0aSVictor Perevertkin         .BusMajorVersion = 2,
372a97c6e0aSVictor Perevertkin         .BusMinorVersion = 0
373a97c6e0aSVictor Perevertkin     };
374a97c6e0aSVictor Perevertkin 
375a97c6e0aSVictor Perevertkin     // store returned length
376*cbe88e28SVictor Perevertkin     Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
377a97c6e0aSVictor Perevertkin     status = STATUS_SUCCESS;
378a97c6e0aSVictor Perevertkin 
379a97c6e0aSVictor Perevertkin completeIrp:
380a97c6e0aSVictor Perevertkin     Irp->IoStatus.Status = status;
381a97c6e0aSVictor Perevertkin     IoCompleteRequest(Irp, IO_NO_INCREMENT);
382a97c6e0aSVictor Perevertkin     return status;
383a97c6e0aSVictor Perevertkin }
384a97c6e0aSVictor Perevertkin 
3851b45d9eeSVictor Perevertkin /**********************************************************************
3861b45d9eeSVictor Perevertkin  * NAME                         INTERNAL
3871b45d9eeSVictor Perevertkin  *  ScsiPortDeviceControl
3881b45d9eeSVictor Perevertkin  *
3891b45d9eeSVictor Perevertkin  * DESCRIPTION
3901b45d9eeSVictor Perevertkin  *  Answer requests for device control calls
3911b45d9eeSVictor Perevertkin  *
3921b45d9eeSVictor Perevertkin  * RUN LEVEL
3931b45d9eeSVictor Perevertkin  *  PASSIVE_LEVEL
3941b45d9eeSVictor Perevertkin  *
3951b45d9eeSVictor Perevertkin  * ARGUMENTS
3961b45d9eeSVictor Perevertkin  *  Standard dispatch arguments
3971b45d9eeSVictor Perevertkin  *
3981b45d9eeSVictor Perevertkin  * RETURNS
3991b45d9eeSVictor Perevertkin  *  NTSTATUS
4001b45d9eeSVictor Perevertkin  */
4011b45d9eeSVictor Perevertkin 
4021b45d9eeSVictor Perevertkin NTSTATUS
4031b45d9eeSVictor Perevertkin NTAPI
ScsiPortDeviceControl(_In_ PDEVICE_OBJECT DeviceObject,_In_ PIRP Irp)4041b45d9eeSVictor Perevertkin ScsiPortDeviceControl(
4051b45d9eeSVictor Perevertkin     _In_ PDEVICE_OBJECT DeviceObject,
4061b45d9eeSVictor Perevertkin     _In_ PIRP Irp)
4071b45d9eeSVictor Perevertkin {
4081b45d9eeSVictor Perevertkin     PIO_STACK_LOCATION Stack;
409a97c6e0aSVictor Perevertkin     PSCSI_PORT_COMMON_EXTENSION comExt = DeviceObject->DeviceExtension;
410a97c6e0aSVictor Perevertkin     PSCSI_PORT_DEVICE_EXTENSION portExt;
411a97c6e0aSVictor Perevertkin     PSCSI_PORT_LUN_EXTENSION lunExt;
412a97c6e0aSVictor Perevertkin     NTSTATUS status;
4131b45d9eeSVictor Perevertkin 
4141b45d9eeSVictor Perevertkin     DPRINT("ScsiPortDeviceControl()\n");
4151b45d9eeSVictor Perevertkin 
4161b45d9eeSVictor Perevertkin     Irp->IoStatus.Information = 0;
4171b45d9eeSVictor Perevertkin 
4181b45d9eeSVictor Perevertkin     Stack = IoGetCurrentIrpStackLocation(Irp);
4191b45d9eeSVictor Perevertkin 
4201b45d9eeSVictor Perevertkin     switch (Stack->Parameters.DeviceIoControl.IoControlCode)
4211b45d9eeSVictor Perevertkin     {
422a97c6e0aSVictor Perevertkin         case IOCTL_STORAGE_QUERY_PROPERTY:
423a97c6e0aSVictor Perevertkin         {
424a97c6e0aSVictor Perevertkin             DPRINT("  IOCTL_STORAGE_QUERY_PROPERTY\n");
425a97c6e0aSVictor Perevertkin 
426a97c6e0aSVictor Perevertkin             if (!VerifyIrpInBufferSize(Irp, sizeof(STORAGE_PROPERTY_QUERY)))
427a97c6e0aSVictor Perevertkin             {
428a97c6e0aSVictor Perevertkin                 status = STATUS_BUFFER_TOO_SMALL;
429a97c6e0aSVictor Perevertkin                 break;
430a97c6e0aSVictor Perevertkin             }
431a97c6e0aSVictor Perevertkin 
432a97c6e0aSVictor Perevertkin             if (comExt->IsFDO)
433a97c6e0aSVictor Perevertkin                 return FdoHandleQueryProperty(DeviceObject, Irp);
434a97c6e0aSVictor Perevertkin             else
435a97c6e0aSVictor Perevertkin                 return PdoHandleQueryProperty(DeviceObject, Irp);
436a97c6e0aSVictor Perevertkin         }
437a97c6e0aSVictor Perevertkin         case IOCTL_SCSI_GET_ADDRESS:
438a97c6e0aSVictor Perevertkin         {
439a97c6e0aSVictor Perevertkin             DPRINT("  IOCTL_SCSI_GET_ADDRESS\n");
440a97c6e0aSVictor Perevertkin 
441a97c6e0aSVictor Perevertkin             if (comExt->IsFDO)
442a97c6e0aSVictor Perevertkin             {
443a97c6e0aSVictor Perevertkin                 status = STATUS_INVALID_DEVICE_REQUEST;
444a97c6e0aSVictor Perevertkin                 break;
445a97c6e0aSVictor Perevertkin             }
446a97c6e0aSVictor Perevertkin 
447a97c6e0aSVictor Perevertkin             PSCSI_ADDRESS address = Irp->AssociatedIrp.SystemBuffer;
448a97c6e0aSVictor Perevertkin             if (!VerifyIrpOutBufferSize(Irp, sizeof(*address)))
449a97c6e0aSVictor Perevertkin             {
450a97c6e0aSVictor Perevertkin                 status = STATUS_BUFFER_TOO_SMALL;
451a97c6e0aSVictor Perevertkin                 break;
452a97c6e0aSVictor Perevertkin             }
453a97c6e0aSVictor Perevertkin 
454a97c6e0aSVictor Perevertkin             lunExt = DeviceObject->DeviceExtension;
455a97c6e0aSVictor Perevertkin             portExt = comExt->LowerDevice->DeviceExtension;
456a97c6e0aSVictor Perevertkin 
457a97c6e0aSVictor Perevertkin             address->Length = sizeof(SCSI_ADDRESS);
458a97c6e0aSVictor Perevertkin             address->PortNumber = portExt->PortNumber;
459a97c6e0aSVictor Perevertkin             address->PathId = lunExt->PathId;
460a97c6e0aSVictor Perevertkin             address->TargetId = lunExt->TargetId;
461a97c6e0aSVictor Perevertkin             address->Lun = lunExt->Lun;
462a97c6e0aSVictor Perevertkin 
463a97c6e0aSVictor Perevertkin             Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
464a97c6e0aSVictor Perevertkin             status = STATUS_SUCCESS;
465a97c6e0aSVictor Perevertkin             break;
466a97c6e0aSVictor Perevertkin         }
4671b45d9eeSVictor Perevertkin         case IOCTL_SCSI_GET_DUMP_POINTERS:
468a97c6e0aSVictor Perevertkin         {
4691b45d9eeSVictor Perevertkin             DPRINT("  IOCTL_SCSI_GET_DUMP_POINTERS\n");
4701b45d9eeSVictor Perevertkin 
471a97c6e0aSVictor Perevertkin             if (!comExt->IsFDO)
4721b45d9eeSVictor Perevertkin             {
473a97c6e0aSVictor Perevertkin                 IoSkipCurrentIrpStackLocation(Irp);
474a97c6e0aSVictor Perevertkin                 return IoCallDriver(comExt->LowerDevice, Irp);
475a97c6e0aSVictor Perevertkin             }
476a97c6e0aSVictor Perevertkin 
477a97c6e0aSVictor Perevertkin             PDUMP_POINTERS dumpPointers = Irp->AssociatedIrp.SystemBuffer;
478a97c6e0aSVictor Perevertkin             if (!VerifyIrpOutBufferSize(Irp, sizeof(*dumpPointers)))
479a97c6e0aSVictor Perevertkin             {
480a97c6e0aSVictor Perevertkin                 status = STATUS_BUFFER_TOO_SMALL;
4811b45d9eeSVictor Perevertkin                 break;
4821b45d9eeSVictor Perevertkin             }
4831b45d9eeSVictor Perevertkin 
484a97c6e0aSVictor Perevertkin             dumpPointers->DeviceObject = DeviceObject;
4851b45d9eeSVictor Perevertkin             /* More data.. ? */
4861b45d9eeSVictor Perevertkin 
487a97c6e0aSVictor Perevertkin             status = STATUS_SUCCESS;
4881b45d9eeSVictor Perevertkin             Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
4891b45d9eeSVictor Perevertkin             break;
490a97c6e0aSVictor Perevertkin         }
4911b45d9eeSVictor Perevertkin         case IOCTL_SCSI_GET_CAPABILITIES:
492a97c6e0aSVictor Perevertkin         {
4931b45d9eeSVictor Perevertkin             DPRINT("  IOCTL_SCSI_GET_CAPABILITIES\n");
4941b45d9eeSVictor Perevertkin 
495a97c6e0aSVictor Perevertkin             if (!comExt->IsFDO)
496a97c6e0aSVictor Perevertkin             {
497a97c6e0aSVictor Perevertkin                 status = STATUS_INVALID_DEVICE_REQUEST;
4981b45d9eeSVictor Perevertkin                 break;
4991b45d9eeSVictor Perevertkin             }
5001b45d9eeSVictor Perevertkin 
501a97c6e0aSVictor Perevertkin             if (!VerifyIrpOutBufferSize(Irp, sizeof(IO_SCSI_CAPABILITIES)))
5021b45d9eeSVictor Perevertkin             {
503a97c6e0aSVictor Perevertkin                 status = STATUS_BUFFER_TOO_SMALL;
5041b45d9eeSVictor Perevertkin                 break;
5051b45d9eeSVictor Perevertkin             }
5061b45d9eeSVictor Perevertkin 
507a97c6e0aSVictor Perevertkin             portExt = DeviceObject->DeviceExtension;
508a97c6e0aSVictor Perevertkin 
5091b45d9eeSVictor Perevertkin             RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
510a97c6e0aSVictor Perevertkin                           &portExt->PortCapabilities,
5111b45d9eeSVictor Perevertkin                           sizeof(IO_SCSI_CAPABILITIES));
5121b45d9eeSVictor Perevertkin 
513a97c6e0aSVictor Perevertkin             status = STATUS_SUCCESS;
5141b45d9eeSVictor Perevertkin             Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
5151b45d9eeSVictor Perevertkin             break;
516a97c6e0aSVictor Perevertkin         }
5171b45d9eeSVictor Perevertkin         case IOCTL_SCSI_GET_INQUIRY_DATA:
518a97c6e0aSVictor Perevertkin         {
5191b45d9eeSVictor Perevertkin             DPRINT("  IOCTL_SCSI_GET_INQUIRY_DATA\n");
5201b45d9eeSVictor Perevertkin 
521a97c6e0aSVictor Perevertkin             if (!comExt->IsFDO)
522a97c6e0aSVictor Perevertkin             {
523a97c6e0aSVictor Perevertkin                 status = STATUS_INVALID_DEVICE_REQUEST;
5241b45d9eeSVictor Perevertkin                 break;
525a97c6e0aSVictor Perevertkin             }
5261b45d9eeSVictor Perevertkin 
527a97c6e0aSVictor Perevertkin             /* Copy inquiry data to the port device extension */
528a97c6e0aSVictor Perevertkin             status = SpiGetInquiryData(DeviceObject->DeviceExtension, Irp);
529a97c6e0aSVictor Perevertkin             break;
530a97c6e0aSVictor Perevertkin         }
5311b45d9eeSVictor Perevertkin         case IOCTL_SCSI_MINIPORT:
5321b45d9eeSVictor Perevertkin             DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
533a97c6e0aSVictor Perevertkin             status = STATUS_NOT_IMPLEMENTED;
5341b45d9eeSVictor Perevertkin             break;
5351b45d9eeSVictor Perevertkin 
5361b45d9eeSVictor Perevertkin         case IOCTL_SCSI_PASS_THROUGH:
5371b45d9eeSVictor Perevertkin             DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
538a97c6e0aSVictor Perevertkin             status = STATUS_NOT_IMPLEMENTED;
5391b45d9eeSVictor Perevertkin             break;
5401b45d9eeSVictor Perevertkin 
5411b45d9eeSVictor Perevertkin         default:
5421b45d9eeSVictor Perevertkin             DPRINT1("unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
543a97c6e0aSVictor Perevertkin             status = STATUS_NOT_SUPPORTED;
5441b45d9eeSVictor Perevertkin             break;
5451b45d9eeSVictor Perevertkin     }
5461b45d9eeSVictor Perevertkin 
5471b45d9eeSVictor Perevertkin     /* Complete the request with the given status */
548a97c6e0aSVictor Perevertkin     Irp->IoStatus.Status = status;
5491b45d9eeSVictor Perevertkin     IoCompleteRequest(Irp, IO_NO_INCREMENT);
5501b45d9eeSVictor Perevertkin 
551a97c6e0aSVictor Perevertkin     return status;
5521b45d9eeSVictor Perevertkin }
553