1b2c6c07dSEricKohl /*
2b2c6c07dSEricKohl * PROJECT: ReactOS Storport Driver
3b2c6c07dSEricKohl * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4b2c6c07dSEricKohl * PURPOSE: Storport FDO code
5b2c6c07dSEricKohl * COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
6b2c6c07dSEricKohl */
7b2c6c07dSEricKohl
8b2c6c07dSEricKohl /* INCLUDES *******************************************************************/
9b2c6c07dSEricKohl
10b2c6c07dSEricKohl #include "precomp.h"
11b2c6c07dSEricKohl
12b2c6c07dSEricKohl #define NDEBUG
13b2c6c07dSEricKohl #include <debug.h>
14b2c6c07dSEricKohl
15b2c6c07dSEricKohl
16b2c6c07dSEricKohl /* FUNCTIONS ******************************************************************/
17b2c6c07dSEricKohl
18b2c6c07dSEricKohl static
195cfc1e31SEric Kohl BOOLEAN
205cfc1e31SEric Kohl NTAPI
PortFdoInterruptRoutine(_In_ PKINTERRUPT Interrupt,_In_ PVOID ServiceContext)215cfc1e31SEric Kohl PortFdoInterruptRoutine(
225cfc1e31SEric Kohl _In_ PKINTERRUPT Interrupt,
235cfc1e31SEric Kohl _In_ PVOID ServiceContext)
245cfc1e31SEric Kohl {
255cfc1e31SEric Kohl PFDO_DEVICE_EXTENSION DeviceExtension;
265cfc1e31SEric Kohl
275cfc1e31SEric Kohl DPRINT1("PortFdoInterruptRoutine(%p %p)\n",
285cfc1e31SEric Kohl Interrupt, ServiceContext);
295cfc1e31SEric Kohl
305cfc1e31SEric Kohl DeviceExtension = (PFDO_DEVICE_EXTENSION)ServiceContext;
315cfc1e31SEric Kohl
325cfc1e31SEric Kohl return MiniportHwInterrupt(&DeviceExtension->Miniport);
335cfc1e31SEric Kohl }
345cfc1e31SEric Kohl
355cfc1e31SEric Kohl
365cfc1e31SEric Kohl static
375cfc1e31SEric Kohl NTSTATUS
PortFdoConnectInterrupt(_In_ PFDO_DEVICE_EXTENSION DeviceExtension)385cfc1e31SEric Kohl PortFdoConnectInterrupt(
395cfc1e31SEric Kohl _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
405cfc1e31SEric Kohl {
415cfc1e31SEric Kohl ULONG Vector;
425cfc1e31SEric Kohl KIRQL Irql;
435cfc1e31SEric Kohl KINTERRUPT_MODE InterruptMode;
445cfc1e31SEric Kohl BOOLEAN ShareVector;
455cfc1e31SEric Kohl KAFFINITY Affinity;
465cfc1e31SEric Kohl NTSTATUS Status;
475cfc1e31SEric Kohl
485cfc1e31SEric Kohl DPRINT1("PortFdoConnectInterrupt(%p)\n",
495cfc1e31SEric Kohl DeviceExtension);
505cfc1e31SEric Kohl
515cfc1e31SEric Kohl /* No resources, no interrupt. Done! */
525cfc1e31SEric Kohl if (DeviceExtension->AllocatedResources == NULL ||
535cfc1e31SEric Kohl DeviceExtension->TranslatedResources == NULL)
545cfc1e31SEric Kohl {
555cfc1e31SEric Kohl DPRINT1("Checkpoint\n");
565cfc1e31SEric Kohl return STATUS_SUCCESS;
575cfc1e31SEric Kohl }
585cfc1e31SEric Kohl
595cfc1e31SEric Kohl /* Get the interrupt data from the resource list */
605cfc1e31SEric Kohl Status = GetResourceListInterrupt(DeviceExtension,
615cfc1e31SEric Kohl &Vector,
625cfc1e31SEric Kohl &Irql,
635cfc1e31SEric Kohl &InterruptMode,
645cfc1e31SEric Kohl &ShareVector,
655cfc1e31SEric Kohl &Affinity);
665cfc1e31SEric Kohl if (!NT_SUCCESS(Status))
675cfc1e31SEric Kohl {
685cfc1e31SEric Kohl DPRINT1("GetResourceListInterrupt() failed (Status 0x%08lx)\n", Status);
695cfc1e31SEric Kohl return Status;
705cfc1e31SEric Kohl }
715cfc1e31SEric Kohl
725cfc1e31SEric Kohl DPRINT1("Vector: %lu\n", Vector);
735cfc1e31SEric Kohl DPRINT1("Irql: %lu\n", Irql);
745cfc1e31SEric Kohl
755cfc1e31SEric Kohl DPRINT1("Affinity: 0x%08lx\n", Affinity);
765cfc1e31SEric Kohl
775cfc1e31SEric Kohl /* Connect the interrupt */
785cfc1e31SEric Kohl Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
795cfc1e31SEric Kohl PortFdoInterruptRoutine,
805cfc1e31SEric Kohl DeviceExtension,
815cfc1e31SEric Kohl NULL,
825cfc1e31SEric Kohl Vector,
835cfc1e31SEric Kohl Irql,
845cfc1e31SEric Kohl Irql,
855cfc1e31SEric Kohl InterruptMode,
865cfc1e31SEric Kohl ShareVector,
875cfc1e31SEric Kohl Affinity,
885cfc1e31SEric Kohl FALSE);
895cfc1e31SEric Kohl if (NT_SUCCESS(Status))
905cfc1e31SEric Kohl {
915cfc1e31SEric Kohl DeviceExtension->InterruptIrql = Irql;
925cfc1e31SEric Kohl }
935cfc1e31SEric Kohl else
945cfc1e31SEric Kohl {
955cfc1e31SEric Kohl DPRINT1("IoConnectInterrupt() failed (Status 0x%08lx)\n", Status);
965cfc1e31SEric Kohl }
975cfc1e31SEric Kohl
985cfc1e31SEric Kohl return Status;
995cfc1e31SEric Kohl }
1005cfc1e31SEric Kohl
1015cfc1e31SEric Kohl
1025cfc1e31SEric Kohl static
103b2c6c07dSEricKohl NTSTATUS
PortFdoStartMiniport(_In_ PFDO_DEVICE_EXTENSION DeviceExtension)1048dea67f8SEric Kohl PortFdoStartMiniport(
1058dea67f8SEric Kohl _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
1068dea67f8SEric Kohl {
1078dea67f8SEric Kohl PHW_INITIALIZATION_DATA InitData;
1088dea67f8SEric Kohl INTERFACE_TYPE InterfaceType;
1098dea67f8SEric Kohl NTSTATUS Status;
1108dea67f8SEric Kohl
1118dea67f8SEric Kohl DPRINT1("PortFdoStartDevice(%p)\n", DeviceExtension);
1128dea67f8SEric Kohl
1138dea67f8SEric Kohl /* Get the interface type of the lower device */
1148dea67f8SEric Kohl InterfaceType = GetBusInterface(DeviceExtension->LowerDevice);
1158dea67f8SEric Kohl if (InterfaceType == InterfaceTypeUndefined)
1168dea67f8SEric Kohl return STATUS_NO_SUCH_DEVICE;
1178dea67f8SEric Kohl
1188dea67f8SEric Kohl /* Get the driver init data for the given interface type */
1198dea67f8SEric Kohl InitData = PortGetDriverInitData(DeviceExtension->DriverExtension,
1208dea67f8SEric Kohl InterfaceType);
1218dea67f8SEric Kohl if (InitData == NULL)
1228dea67f8SEric Kohl return STATUS_NO_SUCH_DEVICE;
1238dea67f8SEric Kohl
1248dea67f8SEric Kohl /* Initialize the miniport */
12542cb5353SEric Kohl Status = MiniportInitialize(&DeviceExtension->Miniport,
1268dea67f8SEric Kohl DeviceExtension,
1278dea67f8SEric Kohl InitData);
12842cb5353SEric Kohl if (!NT_SUCCESS(Status))
12942cb5353SEric Kohl {
13042cb5353SEric Kohl DPRINT1("MiniportInitialize() failed (Status 0x%08lx)\n", Status);
13142cb5353SEric Kohl return Status;
13242cb5353SEric Kohl }
1338dea67f8SEric Kohl
1348dea67f8SEric Kohl /* Call the miniports FindAdapter function */
1358dea67f8SEric Kohl Status = MiniportFindAdapter(&DeviceExtension->Miniport);
1368dea67f8SEric Kohl if (!NT_SUCCESS(Status))
1378dea67f8SEric Kohl {
1388dea67f8SEric Kohl DPRINT1("MiniportFindAdapter() failed (Status 0x%08lx)\n", Status);
1398dea67f8SEric Kohl return Status;
1408dea67f8SEric Kohl }
1418dea67f8SEric Kohl
14258bb4b31SEric Kohl /* Connect the configured interrupt */
1435cfc1e31SEric Kohl Status = PortFdoConnectInterrupt(DeviceExtension);
14458bb4b31SEric Kohl if (!NT_SUCCESS(Status))
14558bb4b31SEric Kohl {
14658bb4b31SEric Kohl DPRINT1("PortFdoConnectInterrupt() failed (Status 0x%08lx)\n", Status);
14758bb4b31SEric Kohl return Status;
14858bb4b31SEric Kohl }
1495cfc1e31SEric Kohl
1508dea67f8SEric Kohl /* Call the miniports HwInitialize function */
1518dea67f8SEric Kohl Status = MiniportHwInitialize(&DeviceExtension->Miniport);
1528dea67f8SEric Kohl if (!NT_SUCCESS(Status))
1538dea67f8SEric Kohl {
1548dea67f8SEric Kohl DPRINT1("MiniportHwInitialize() failed (Status 0x%08lx)\n", Status);
1558dea67f8SEric Kohl return Status;
1568dea67f8SEric Kohl }
1578dea67f8SEric Kohl
158cc95d3ecSEric Kohl /* Call the HwPassiveInitRoutine function, if available */
159cc95d3ecSEric Kohl if (DeviceExtension->HwPassiveInitRoutine != NULL)
160cc95d3ecSEric Kohl {
161cc95d3ecSEric Kohl DPRINT1("Calling HwPassiveInitRoutine()\n");
162cc95d3ecSEric Kohl if (!DeviceExtension->HwPassiveInitRoutine(&DeviceExtension->Miniport.MiniportExtension->HwDeviceExtension))
163cc95d3ecSEric Kohl {
164cc95d3ecSEric Kohl DPRINT1("HwPassiveInitRoutine() failed\n");
165cc95d3ecSEric Kohl return STATUS_UNSUCCESSFUL;
166cc95d3ecSEric Kohl }
167cc95d3ecSEric Kohl }
168cc95d3ecSEric Kohl
1698dea67f8SEric Kohl return STATUS_SUCCESS;
1708dea67f8SEric Kohl }
1718dea67f8SEric Kohl
1728dea67f8SEric Kohl
1738dea67f8SEric Kohl static
1748dea67f8SEric Kohl NTSTATUS
175b2c6c07dSEricKohl NTAPI
PortFdoStartDevice(_In_ PFDO_DEVICE_EXTENSION DeviceExtension,_In_ PIRP Irp)176b2c6c07dSEricKohl PortFdoStartDevice(
177b2c6c07dSEricKohl _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
178b2c6c07dSEricKohl _In_ PIRP Irp)
179b2c6c07dSEricKohl {
1803f5aeb93SEric Kohl PIO_STACK_LOCATION Stack;
1818dea67f8SEric Kohl NTSTATUS Status;
1828dea67f8SEric Kohl
183b2c6c07dSEricKohl DPRINT1("PortFdoStartDevice(%p %p)\n",
184b2c6c07dSEricKohl DeviceExtension, Irp);
185b2c6c07dSEricKohl
186b2c6c07dSEricKohl ASSERT(DeviceExtension->ExtensionType == FdoExtension);
187b2c6c07dSEricKohl
1883f5aeb93SEric Kohl /* Get the current stack location */
1893f5aeb93SEric Kohl Stack = IoGetCurrentIrpStackLocation(Irp);
1903f5aeb93SEric Kohl
1918dea67f8SEric Kohl /* Start the lower device if the FDO is in 'stopped' state */
1928dea67f8SEric Kohl if (DeviceExtension->PnpState == dsStopped)
1938dea67f8SEric Kohl {
194*7ed1883cSVictor Perevertkin if (IoForwardIrpSynchronously(DeviceExtension->LowerDevice, Irp))
195*7ed1883cSVictor Perevertkin {
196*7ed1883cSVictor Perevertkin Status = Irp->IoStatus.Status;
197*7ed1883cSVictor Perevertkin }
198*7ed1883cSVictor Perevertkin else
199*7ed1883cSVictor Perevertkin {
200*7ed1883cSVictor Perevertkin Status = STATUS_UNSUCCESSFUL;
201*7ed1883cSVictor Perevertkin }
202*7ed1883cSVictor Perevertkin
2038dea67f8SEric Kohl if (!NT_SUCCESS(Status))
2048dea67f8SEric Kohl {
205*7ed1883cSVictor Perevertkin DPRINT1("Lower device failed the IRP (Status 0x%08lx)\n", Status);
2068dea67f8SEric Kohl return Status;
2078dea67f8SEric Kohl }
2088dea67f8SEric Kohl }
2098dea67f8SEric Kohl
2108dea67f8SEric Kohl /* Change to the 'started' state */
2118dea67f8SEric Kohl DeviceExtension->PnpState = dsStarted;
2128dea67f8SEric Kohl
2133f5aeb93SEric Kohl /* Copy the raw and translated resource lists into the device extension */
2143f5aeb93SEric Kohl if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
2153f5aeb93SEric Kohl Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
2163f5aeb93SEric Kohl {
2173f5aeb93SEric Kohl DeviceExtension->AllocatedResources = CopyResourceList(NonPagedPool,
2183f5aeb93SEric Kohl Stack->Parameters.StartDevice.AllocatedResources);
2193f5aeb93SEric Kohl if (DeviceExtension->AllocatedResources == NULL)
2203f5aeb93SEric Kohl return STATUS_NO_MEMORY;
2213f5aeb93SEric Kohl
2223f5aeb93SEric Kohl DeviceExtension->TranslatedResources = CopyResourceList(NonPagedPool,
2233f5aeb93SEric Kohl Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
2243f5aeb93SEric Kohl if (DeviceExtension->TranslatedResources == NULL)
2253f5aeb93SEric Kohl return STATUS_NO_MEMORY;
2263f5aeb93SEric Kohl }
2273f5aeb93SEric Kohl
228b21019e3SEric Kohl /* Get the bus interface of the lower (bus) device */
229b21019e3SEric Kohl Status = QueryBusInterface(DeviceExtension->LowerDevice,
230b21019e3SEric Kohl (PGUID)&GUID_BUS_INTERFACE_STANDARD,
231b21019e3SEric Kohl sizeof(BUS_INTERFACE_STANDARD),
232b21019e3SEric Kohl 1,
233b21019e3SEric Kohl &DeviceExtension->BusInterface,
234b21019e3SEric Kohl NULL);
235b21019e3SEric Kohl DPRINT1("Status: 0x%08lx\n", Status);
236b21019e3SEric Kohl if (NT_SUCCESS(Status))
237b21019e3SEric Kohl {
238b21019e3SEric Kohl DPRINT1("Context: %p\n", DeviceExtension->BusInterface.Context);
239b21019e3SEric Kohl DeviceExtension->BusInitialized = TRUE;
240b21019e3SEric Kohl }
241b21019e3SEric Kohl
2428dea67f8SEric Kohl /* Start the miniport (FindAdapter & Initialize) */
2438dea67f8SEric Kohl Status = PortFdoStartMiniport(DeviceExtension);
2448dea67f8SEric Kohl if (!NT_SUCCESS(Status))
2458dea67f8SEric Kohl {
2468dea67f8SEric Kohl DPRINT1("FdoStartMiniport() failed (Status 0x%08lx)\n", Status);
2478dea67f8SEric Kohl DeviceExtension->PnpState = dsStopped;
2488dea67f8SEric Kohl }
2498dea67f8SEric Kohl
2508dea67f8SEric Kohl return Status;
251b2c6c07dSEricKohl }
252b2c6c07dSEricKohl
253b2c6c07dSEricKohl
254545692e8SEric Kohl static
255545692e8SEric Kohl NTSTATUS
PortSendInquiry(_In_ PPDO_DEVICE_EXTENSION PdoExtension)256be88574fSEric Kohl PortSendInquiry(
257545692e8SEric Kohl _In_ PPDO_DEVICE_EXTENSION PdoExtension)
258f7c01906SEric Kohl {
259545692e8SEric Kohl IO_STATUS_BLOCK IoStatusBlock;
260545692e8SEric Kohl PIO_STACK_LOCATION IrpStack;
261545692e8SEric Kohl KEVENT Event;
262545692e8SEric Kohl // KIRQL Irql;
263545692e8SEric Kohl PIRP Irp;
264545692e8SEric Kohl NTSTATUS Status;
265545692e8SEric Kohl PSENSE_DATA SenseBuffer;
266be88574fSEric Kohl BOOLEAN KeepTrying = TRUE;
267be88574fSEric Kohl ULONG RetryCount = 0;
268f7c01906SEric Kohl SCSI_REQUEST_BLOCK Srb;
269f7c01906SEric Kohl PCDB Cdb;
270545692e8SEric Kohl // PSCSI_PORT_LUN_EXTENSION LunExtension;
271545692e8SEric Kohl // PFDO_DEVICE_EXTENSION DeviceExtension;
272f7c01906SEric Kohl
273545692e8SEric Kohl DPRINT("PortSendInquiry(%p)\n", PdoExtension);
274f7c01906SEric Kohl
275545692e8SEric Kohl if (PdoExtension->InquiryBuffer == NULL)
276545692e8SEric Kohl {
277545692e8SEric Kohl PdoExtension->InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
278545692e8SEric Kohl if (PdoExtension->InquiryBuffer == NULL)
279f7c01906SEric Kohl return STATUS_INSUFFICIENT_RESOURCES;
280545692e8SEric Kohl }
281f7c01906SEric Kohl
282f7c01906SEric Kohl SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA);
283f7c01906SEric Kohl if (SenseBuffer == NULL)
284f7c01906SEric Kohl {
285f7c01906SEric Kohl return STATUS_INSUFFICIENT_RESOURCES;
286f7c01906SEric Kohl }
287f7c01906SEric Kohl
288be88574fSEric Kohl while (KeepTrying)
289f7c01906SEric Kohl {
290545692e8SEric Kohl /* Initialize event for waiting */
291545692e8SEric Kohl KeInitializeEvent(&Event,
292545692e8SEric Kohl NotificationEvent,
293545692e8SEric Kohl FALSE);
294545692e8SEric Kohl
295545692e8SEric Kohl /* Create an IRP */
296545692e8SEric Kohl Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
297545692e8SEric Kohl PdoExtension->Device,
298545692e8SEric Kohl NULL,
299545692e8SEric Kohl 0,
300545692e8SEric Kohl PdoExtension->InquiryBuffer,
301545692e8SEric Kohl INQUIRYDATABUFFERSIZE,
302545692e8SEric Kohl TRUE,
303545692e8SEric Kohl &Event,
304545692e8SEric Kohl &IoStatusBlock);
305545692e8SEric Kohl if (Irp == NULL)
306545692e8SEric Kohl {
307545692e8SEric Kohl DPRINT("IoBuildDeviceIoControlRequest() failed\n");
308545692e8SEric Kohl
309545692e8SEric Kohl /* Quit the loop */
310545692e8SEric Kohl Status = STATUS_INSUFFICIENT_RESOURCES;
311545692e8SEric Kohl KeepTrying = FALSE;
312545692e8SEric Kohl continue;
313545692e8SEric Kohl }
314545692e8SEric Kohl
315f7c01906SEric Kohl /* Prepare SRB */
316f7c01906SEric Kohl RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
317f7c01906SEric Kohl
318f7c01906SEric Kohl Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
319545692e8SEric Kohl Srb.OriginalRequest = Irp;
320545692e8SEric Kohl Srb.PathId = PdoExtension->Bus;
321545692e8SEric Kohl Srb.TargetId = PdoExtension->Target;
322545692e8SEric Kohl Srb.Lun = PdoExtension->Lun;
323f7c01906SEric Kohl Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
324f7c01906SEric Kohl Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
325f7c01906SEric Kohl Srb.TimeOutValue = 4;
326f7c01906SEric Kohl Srb.CdbLength = 6;
327f7c01906SEric Kohl
328f7c01906SEric Kohl Srb.SenseInfoBuffer = SenseBuffer;
329f7c01906SEric Kohl Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
330f7c01906SEric Kohl
331545692e8SEric Kohl Srb.DataBuffer = PdoExtension->InquiryBuffer;
332f7c01906SEric Kohl Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
333f7c01906SEric Kohl
334545692e8SEric Kohl /* Attach Srb to the Irp */
335545692e8SEric Kohl IrpStack = IoGetNextIrpStackLocation(Irp);
336545692e8SEric Kohl IrpStack->Parameters.Scsi.Srb = &Srb;
337f7c01906SEric Kohl
338f7c01906SEric Kohl /* Fill in CDB */
339f7c01906SEric Kohl Cdb = (PCDB)Srb.Cdb;
340545692e8SEric Kohl Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
341545692e8SEric Kohl Cdb->CDB6INQUIRY.LogicalUnitNumber = PdoExtension->Lun;
342545692e8SEric Kohl Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
343f7c01906SEric Kohl
344545692e8SEric Kohl /* Call the driver */
345545692e8SEric Kohl Status = IoCallDriver(PdoExtension->Device, Irp);
346545692e8SEric Kohl
347545692e8SEric Kohl /* Wait for it to complete */
348545692e8SEric Kohl if (Status == STATUS_PENDING)
349be88574fSEric Kohl {
350545692e8SEric Kohl DPRINT1("PortSendInquiry(): Waiting for the driver to process request...\n");
351545692e8SEric Kohl KeWaitForSingleObject(&Event,
352545692e8SEric Kohl Executive,
353545692e8SEric Kohl KernelMode,
354545692e8SEric Kohl FALSE,
355545692e8SEric Kohl NULL);
356545692e8SEric Kohl Status = IoStatusBlock.Status;
357be88574fSEric Kohl }
358f7c01906SEric Kohl
359545692e8SEric Kohl DPRINT("PortSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
360545692e8SEric Kohl
361f7c01906SEric Kohl if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
362f7c01906SEric Kohl {
363be88574fSEric Kohl DPRINT("Found a device!\n");
364be88574fSEric Kohl
365f7c01906SEric Kohl /* Quit the loop */
366f7c01906SEric Kohl Status = STATUS_SUCCESS;
367be88574fSEric Kohl KeepTrying = FALSE;
368be88574fSEric Kohl continue;
369f7c01906SEric Kohl }
370f7c01906SEric Kohl
371f7c01906SEric Kohl DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
372f7c01906SEric Kohl
373545692e8SEric Kohl /* Check if the queue is frozen */
374545692e8SEric Kohl if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
375545692e8SEric Kohl {
376545692e8SEric Kohl /* Something weird happened, deal with it (unfreeze the queue) */
377545692e8SEric Kohl KeepTrying = FALSE;
378545692e8SEric Kohl
379545692e8SEric Kohl DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
380545692e8SEric Kohl
381545692e8SEric Kohl // LunExtension = SpiGetLunExtension(DeviceExtension,
382545692e8SEric Kohl // LunInfo->PathId,
383545692e8SEric Kohl // LunInfo->TargetId,
384545692e8SEric Kohl // LunInfo->Lun);
385545692e8SEric Kohl
386545692e8SEric Kohl /* Clear frozen flag */
387545692e8SEric Kohl // LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
388545692e8SEric Kohl
389545692e8SEric Kohl /* Acquire the spinlock */
390545692e8SEric Kohl // KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
391545692e8SEric Kohl
392545692e8SEric Kohl /* Process the request */
393545692e8SEric Kohl // SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
394545692e8SEric Kohl
395545692e8SEric Kohl /* SpiGetNextRequestFromLun() releases the spinlock,
396545692e8SEric Kohl so we just lower irql back to what it was before */
397545692e8SEric Kohl // KeLowerIrql(Irql);
398545692e8SEric Kohl }
399545692e8SEric Kohl
400545692e8SEric Kohl /* Check if data overrun happened */
401545692e8SEric Kohl if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
402545692e8SEric Kohl {
403545692e8SEric Kohl DPRINT("Data overrun at TargetId %d\n", PdoExtension->Target);
404545692e8SEric Kohl
405545692e8SEric Kohl /* Quit the loop */
406545692e8SEric Kohl Status = STATUS_SUCCESS;
407545692e8SEric Kohl KeepTrying = FALSE;
408545692e8SEric Kohl }
409545692e8SEric Kohl else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
410545692e8SEric Kohl SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
411545692e8SEric Kohl {
412545692e8SEric Kohl /* LUN is not valid, but some device responds there.
413545692e8SEric Kohl Mark it as invalid anyway */
414545692e8SEric Kohl
415545692e8SEric Kohl /* Quit the loop */
416545692e8SEric Kohl Status = STATUS_INVALID_DEVICE_REQUEST;
417545692e8SEric Kohl KeepTrying = FALSE;
418545692e8SEric Kohl }
419545692e8SEric Kohl else
420545692e8SEric Kohl {
421f7c01906SEric Kohl /* Retry a couple of times if no timeout happened */
422f7c01906SEric Kohl if ((RetryCount < 2) &&
423f7c01906SEric Kohl (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) &&
424f7c01906SEric Kohl (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT))
425f7c01906SEric Kohl {
426f7c01906SEric Kohl RetryCount++;
427f7c01906SEric Kohl KeepTrying = TRUE;
428f7c01906SEric Kohl }
429f7c01906SEric Kohl else
430f7c01906SEric Kohl {
431f7c01906SEric Kohl /* That's all, quit the loop */
432f7c01906SEric Kohl KeepTrying = FALSE;
433f7c01906SEric Kohl
434f7c01906SEric Kohl /* Set status according to SRB status */
435f7c01906SEric Kohl if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION ||
436f7c01906SEric Kohl SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
437f7c01906SEric Kohl {
438f7c01906SEric Kohl Status = STATUS_INVALID_DEVICE_REQUEST;
439f7c01906SEric Kohl }
440f7c01906SEric Kohl else
441f7c01906SEric Kohl {
442f7c01906SEric Kohl Status = STATUS_IO_DEVICE_ERROR;
443f7c01906SEric Kohl }
444f7c01906SEric Kohl }
445f7c01906SEric Kohl }
446545692e8SEric Kohl }
447f7c01906SEric Kohl
448545692e8SEric Kohl /* Free the sense buffer */
449f7c01906SEric Kohl ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
450f7c01906SEric Kohl
451545692e8SEric Kohl DPRINT("PortSendInquiry() done with Status 0x%08X\n", Status);
452f7c01906SEric Kohl
453f7c01906SEric Kohl return Status;
454f7c01906SEric Kohl }
455f7c01906SEric Kohl
456f7c01906SEric Kohl
457545692e8SEric Kohl
458f7c01906SEric Kohl static
459f7c01906SEric Kohl NTSTATUS
PortFdoScanBus(_In_ PFDO_DEVICE_EXTENSION DeviceExtension)460f7c01906SEric Kohl PortFdoScanBus(
461f7c01906SEric Kohl _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
462f7c01906SEric Kohl {
463545692e8SEric Kohl PPDO_DEVICE_EXTENSION PdoExtension;
464545692e8SEric Kohl ULONG Bus, Target; //, Lun;
465f7c01906SEric Kohl NTSTATUS Status;
466f7c01906SEric Kohl
467545692e8SEric Kohl DPRINT("PortFdoScanBus(%p)\n", DeviceExtension);
468f7c01906SEric Kohl
469545692e8SEric Kohl DPRINT("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
470545692e8SEric Kohl DPRINT("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
471545692e8SEric Kohl DPRINT("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
472f7c01906SEric Kohl
473f7c01906SEric Kohl /* Scan all buses */
474f7c01906SEric Kohl for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++)
475f7c01906SEric Kohl {
476545692e8SEric Kohl DPRINT("Scanning bus %ld\n", Bus);
477f7c01906SEric Kohl
478f7c01906SEric Kohl /* Scan all targets */
479f7c01906SEric Kohl for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++)
480f7c01906SEric Kohl {
481545692e8SEric Kohl DPRINT(" Scanning target %ld:%ld\n", Bus, Target);
482f7c01906SEric Kohl
483545692e8SEric Kohl DPRINT(" Scanning logical unit %ld:%ld:%ld\n", Bus, Target, 0);
484545692e8SEric Kohl Status = PortCreatePdo(DeviceExtension, Bus, Target, 0, &PdoExtension);
485545692e8SEric Kohl if (NT_SUCCESS(Status))
486f7c01906SEric Kohl {
487545692e8SEric Kohl /* Scan LUN 0 */
488545692e8SEric Kohl Status = PortSendInquiry(PdoExtension);
489545692e8SEric Kohl DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
490545692e8SEric Kohl if (!NT_SUCCESS(Status))
491545692e8SEric Kohl {
492545692e8SEric Kohl PortDeletePdo(PdoExtension);
493545692e8SEric Kohl }
494545692e8SEric Kohl else
495545692e8SEric Kohl {
496545692e8SEric Kohl DPRINT("VendorId: %.8s\n", PdoExtension->InquiryBuffer->VendorId);
497545692e8SEric Kohl DPRINT("ProductId: %.16s\n", PdoExtension->InquiryBuffer->ProductId);
498545692e8SEric Kohl DPRINT("ProductRevisionLevel: %.4s\n", PdoExtension->InquiryBuffer->ProductRevisionLevel);
499545692e8SEric Kohl DPRINT("VendorSpecific: %.20s\n", PdoExtension->InquiryBuffer->VendorSpecific);
500545692e8SEric Kohl }
501545692e8SEric Kohl }
502f7c01906SEric Kohl
503545692e8SEric Kohl #if 0
504545692e8SEric Kohl /* Scan all logical units */
505545692e8SEric Kohl for (Lun = 1; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
506545692e8SEric Kohl {
507545692e8SEric Kohl DPRINT(" Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
508be88574fSEric Kohl Status = PortSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
509545692e8SEric Kohl DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
510be88574fSEric Kohl if (!NT_SUCCESS(Status))
511be88574fSEric Kohl break;
512f7c01906SEric Kohl }
513545692e8SEric Kohl #endif
514f7c01906SEric Kohl }
515f7c01906SEric Kohl }
516f7c01906SEric Kohl
517545692e8SEric Kohl DPRINT("PortFdoScanBus() done!\n");
518f7c01906SEric Kohl
519f7c01906SEric Kohl return STATUS_SUCCESS;
520f7c01906SEric Kohl }
521f7c01906SEric Kohl
522f7c01906SEric Kohl
523b2c6c07dSEricKohl static
524b2c6c07dSEricKohl NTSTATUS
PortFdoQueryBusRelations(_In_ PFDO_DEVICE_EXTENSION DeviceExtension,_Out_ PULONG_PTR Information)525b2c6c07dSEricKohl PortFdoQueryBusRelations(
526b2c6c07dSEricKohl _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
527b2c6c07dSEricKohl _Out_ PULONG_PTR Information)
528b2c6c07dSEricKohl {
529b2c6c07dSEricKohl NTSTATUS Status = STATUS_SUCCESS;;
530b2c6c07dSEricKohl
531b2c6c07dSEricKohl DPRINT1("PortFdoQueryBusRelations(%p %p)\n",
532b2c6c07dSEricKohl DeviceExtension, Information);
533b2c6c07dSEricKohl
534f7c01906SEric Kohl Status = PortFdoScanBus(DeviceExtension);
535f7c01906SEric Kohl
536545692e8SEric Kohl DPRINT1("Units found: %lu\n", DeviceExtension->PdoCount);
537be88574fSEric Kohl
538b2c6c07dSEricKohl *Information = 0;
539b2c6c07dSEricKohl
540b2c6c07dSEricKohl return Status;
541b2c6c07dSEricKohl }
542b2c6c07dSEricKohl
543b2c6c07dSEricKohl
544dd0027baSEric Kohl static
545dd0027baSEric Kohl NTSTATUS
PortFdoFilterRequirements(PFDO_DEVICE_EXTENSION DeviceExtension,PIRP Irp)546dd0027baSEric Kohl PortFdoFilterRequirements(
547dd0027baSEric Kohl PFDO_DEVICE_EXTENSION DeviceExtension,
548dd0027baSEric Kohl PIRP Irp)
549dd0027baSEric Kohl {
550dd0027baSEric Kohl PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
551dd0027baSEric Kohl
552dd0027baSEric Kohl DPRINT1("PortFdoFilterRequirements(%p %p)\n", DeviceExtension, Irp);
553dd0027baSEric Kohl
554dd0027baSEric Kohl /* Get the bus number and the slot number */
555dd0027baSEric Kohl RequirementsList =(PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
556dd0027baSEric Kohl if (RequirementsList != NULL)
557dd0027baSEric Kohl {
558dd0027baSEric Kohl DeviceExtension->BusNumber = RequirementsList->BusNumber;
559dd0027baSEric Kohl DeviceExtension->SlotNumber = RequirementsList->SlotNumber;
560dd0027baSEric Kohl }
561dd0027baSEric Kohl
562dd0027baSEric Kohl return STATUS_SUCCESS;
563dd0027baSEric Kohl }
564dd0027baSEric Kohl
565dd0027baSEric Kohl
566b2c6c07dSEricKohl NTSTATUS
567b2c6c07dSEricKohl NTAPI
PortFdoScsi(_In_ PDEVICE_OBJECT DeviceObject,_In_ PIRP Irp)568f7c01906SEric Kohl PortFdoScsi(
569f7c01906SEric Kohl _In_ PDEVICE_OBJECT DeviceObject,
570f7c01906SEric Kohl _In_ PIRP Irp)
571f7c01906SEric Kohl {
572f7c01906SEric Kohl PFDO_DEVICE_EXTENSION DeviceExtension;
573f7c01906SEric Kohl // PIO_STACK_LOCATION Stack;
574f7c01906SEric Kohl ULONG_PTR Information = 0;
575f7c01906SEric Kohl NTSTATUS Status = STATUS_NOT_SUPPORTED;
576f7c01906SEric Kohl
577545692e8SEric Kohl DPRINT("PortFdoScsi(%p %p)\n", DeviceObject, Irp);
578f7c01906SEric Kohl
579f7c01906SEric Kohl DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
580f7c01906SEric Kohl ASSERT(DeviceExtension);
581f7c01906SEric Kohl ASSERT(DeviceExtension->ExtensionType == FdoExtension);
582f7c01906SEric Kohl
583f7c01906SEric Kohl // Stack = IoGetCurrentIrpStackLocation(Irp);
584f7c01906SEric Kohl
585f7c01906SEric Kohl
586f7c01906SEric Kohl Irp->IoStatus.Information = Information;
587f7c01906SEric Kohl Irp->IoStatus.Status = Status;
588f7c01906SEric Kohl IoCompleteRequest(Irp, IO_NO_INCREMENT);
589f7c01906SEric Kohl
590f7c01906SEric Kohl return Status;
591f7c01906SEric Kohl }
592f7c01906SEric Kohl
593f7c01906SEric Kohl
594f7c01906SEric Kohl NTSTATUS
595f7c01906SEric Kohl NTAPI
PortFdoPnp(_In_ PDEVICE_OBJECT DeviceObject,_In_ PIRP Irp)596b2c6c07dSEricKohl PortFdoPnp(
597b2c6c07dSEricKohl _In_ PDEVICE_OBJECT DeviceObject,
598b2c6c07dSEricKohl _In_ PIRP Irp)
599b2c6c07dSEricKohl {
600b2c6c07dSEricKohl PFDO_DEVICE_EXTENSION DeviceExtension;
601b2c6c07dSEricKohl PIO_STACK_LOCATION Stack;
602b2c6c07dSEricKohl ULONG_PTR Information = 0;
603b2c6c07dSEricKohl NTSTATUS Status = STATUS_NOT_SUPPORTED;
604b2c6c07dSEricKohl
605b2c6c07dSEricKohl DPRINT1("PortFdoPnp(%p %p)\n",
606b2c6c07dSEricKohl DeviceObject, Irp);
607b2c6c07dSEricKohl
608b2c6c07dSEricKohl DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
609b2c6c07dSEricKohl ASSERT(DeviceExtension);
610b2c6c07dSEricKohl ASSERT(DeviceExtension->ExtensionType == FdoExtension);
611b2c6c07dSEricKohl
612b2c6c07dSEricKohl Stack = IoGetCurrentIrpStackLocation(Irp);
613b2c6c07dSEricKohl
614b2c6c07dSEricKohl switch (Stack->MinorFunction)
615b2c6c07dSEricKohl {
616b2c6c07dSEricKohl case IRP_MN_START_DEVICE: /* 0x00 */
617b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
618b2c6c07dSEricKohl Status = PortFdoStartDevice(DeviceExtension, Irp);
619b2c6c07dSEricKohl break;
620b2c6c07dSEricKohl
621b2c6c07dSEricKohl case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
622b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
623b2c6c07dSEricKohl break;
624b2c6c07dSEricKohl
625b2c6c07dSEricKohl case IRP_MN_REMOVE_DEVICE: /* 0x02 */
626b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
627b2c6c07dSEricKohl break;
628b2c6c07dSEricKohl
629b2c6c07dSEricKohl case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */
630b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
631b2c6c07dSEricKohl break;
632b2c6c07dSEricKohl
633b2c6c07dSEricKohl case IRP_MN_STOP_DEVICE: /* 0x04 */
634b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
635b2c6c07dSEricKohl break;
636b2c6c07dSEricKohl
637b2c6c07dSEricKohl case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */
638b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_STOP_DEVICE\n");
639b2c6c07dSEricKohl break;
640b2c6c07dSEricKohl
641b2c6c07dSEricKohl case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */
642b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_STOP_DEVICE\n");
643b2c6c07dSEricKohl break;
644b2c6c07dSEricKohl
645b2c6c07dSEricKohl case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
646b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
647b2c6c07dSEricKohl switch (Stack->Parameters.QueryDeviceRelations.Type)
648b2c6c07dSEricKohl {
649b2c6c07dSEricKohl case BusRelations:
650b2c6c07dSEricKohl DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
651b2c6c07dSEricKohl Status = PortFdoQueryBusRelations(DeviceExtension, &Information);
652b2c6c07dSEricKohl break;
653b2c6c07dSEricKohl
654b2c6c07dSEricKohl case RemovalRelations:
655b2c6c07dSEricKohl DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
656b2c6c07dSEricKohl return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
657b2c6c07dSEricKohl
658b2c6c07dSEricKohl default:
659b2c6c07dSEricKohl DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
660b2c6c07dSEricKohl Stack->Parameters.QueryDeviceRelations.Type);
661b2c6c07dSEricKohl return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
662b2c6c07dSEricKohl }
663b2c6c07dSEricKohl break;
664b2c6c07dSEricKohl
665b2c6c07dSEricKohl case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
666b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
667dd0027baSEric Kohl PortFdoFilterRequirements(DeviceExtension, Irp);
668b2c6c07dSEricKohl return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
669b2c6c07dSEricKohl
670b2c6c07dSEricKohl case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
671b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
672b2c6c07dSEricKohl break;
673b2c6c07dSEricKohl
674b2c6c07dSEricKohl case IRP_MN_DEVICE_USAGE_NOTIFICATION: /* 0x16 */
675b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
676b2c6c07dSEricKohl break;
677b2c6c07dSEricKohl
678b2c6c07dSEricKohl case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */
679b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / IRP_MN_SURPRISE_REMOVAL\n");
680b2c6c07dSEricKohl break;
681b2c6c07dSEricKohl
682b2c6c07dSEricKohl default:
683b2c6c07dSEricKohl DPRINT1("IRP_MJ_PNP / Unknown IOCTL 0x%lx\n", Stack->MinorFunction);
684b2c6c07dSEricKohl return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
685b2c6c07dSEricKohl }
686b2c6c07dSEricKohl
687b2c6c07dSEricKohl Irp->IoStatus.Information = Information;
688b2c6c07dSEricKohl Irp->IoStatus.Status = Status;
689b2c6c07dSEricKohl IoCompleteRequest(Irp, IO_NO_INCREMENT);
690b2c6c07dSEricKohl
691b2c6c07dSEricKohl return Status;
692b2c6c07dSEricKohl }
693b2c6c07dSEricKohl
694b2c6c07dSEricKohl /* EOF */
695