summaryrefslogtreecommitdiff
path: root/general/PLX9x5x/sys/Init.c
diff options
context:
space:
mode:
authorkarlf <[email protected]>2016-08-11 13:28:13 -0700
committerkarlf <[email protected]>2016-08-11 13:28:13 -0700
commit96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch)
treead5f3ede5cbcd6b598677ce41bcf8318471bdd92 /general/PLX9x5x/sys/Init.c
parent687b274aa38fd05c8c26e3068932121876d7f745 (diff)
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'general/PLX9x5x/sys/Init.c')
-rw-r--r--general/PLX9x5x/sys/Init.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/general/PLX9x5x/sys/Init.c b/general/PLX9x5x/sys/Init.c
index fbedaa0c..df48afc6 100644
--- a/general/PLX9x5x/sys/Init.c
+++ b/general/PLX9x5x/sys/Init.c
@@ -107,12 +107,25 @@ Return Value:
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
"MaximumTransferLength %d", DevExt->MaximumTransferLength);
+#ifndef SIMULATE_MEMORY_FRAGMENTATION
//
// Calculate the number of DMA_TRANSFER_ELEMENTS + 1 needed to
// support the MaximumTransferLength.
//
dteCount = BYTES_TO_PAGES((ULONG) ROUND_TO_PAGES(
DevExt->MaximumTransferLength) + PAGE_SIZE);
+#else
+ //
+ // Each DTE describes a Scatter/Gather list element. When
+ // SIMULATE_MEMORY_FRAGMENTATION is defined, we bounce I/O
+ // request buffers to MDL chains to simulate memory
+ // fragmentation. This means we might deal with larger
+ // S/G lists than we would were the I/O buffer virtually
+ // contiguous, so we need more space to write the DTEs.
+ //
+ dteCount = BYTES_TO_PAGES(((ULONG)
+ ROUND_TO_PAGES(MDL_BUFFER_SIZE) + PAGE_SIZE) * MDL_CHAIN_LENGTH) + 1;
+#endif
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Number of DTEs %d", dteCount);
@@ -249,6 +262,40 @@ Return Value:
//
+ // Create a new IO Queue for IOCTLs in sequential mode.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT( &queueConfig,
+ WdfIoQueueDispatchSequential);
+
+ queueConfig.EvtIoDeviceControl = PLxEvtIoDeviceControl;
+
+ status = WdfIoQueueCreate(DevExt->Device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->ControlQueue);
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed: %!STATUS!",
+ status);
+ return status;
+ }
+
+ //
+ // Set the Control Queue forwarding for IOCTL requests.
+ //
+ status = WdfDeviceConfigureRequestDispatching(DevExt->Device,
+ DevExt->ControlQueue,
+ WdfRequestTypeDeviceControl);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceConfigureRequestDispatching failed: %!STATUS!",
+ status);
+ return status;
+ }
+
+
+ //
// Create a WDFINTERRUPT object.
//
status = PLxInterruptCreate(DevExt);
@@ -267,6 +314,44 @@ Return Value:
}
+VOID
+PlxCleanupDeviceExtension(
+ _In_ PDEVICE_EXTENSION DevExt
+ )
+/*++
+
+Routine Description:
+
+ Frees allocated memory that was saved in the
+ WDFDEVICE's context, before the device object
+ is deleted.
+
+Arguments:
+
+ DevExt - Pointer to our DEVICE_EXTENSION
+
+Return Value:
+
+ None
+
+--*/
+{
+#ifdef SIMULATE_MEMORY_FRAGMENTATION
+ if (DevExt->WriteMdlChain) {
+ DestroyMdlChain(DevExt->WriteMdlChain);
+ DevExt->WriteMdlChain = NULL;
+ }
+
+ if (DevExt->ReadMdlChain) {
+ DestroyMdlChain(DevExt->ReadMdlChain);
+ DevExt->ReadMdlChain = NULL;
+ }
+#else
+ UNREFERENCED_PARAMETER(DevExt);
+#endif
+}
+
+
NTSTATUS
PLxPrepareHardware(
IN PDEVICE_EXTENSION DevExt,
@@ -486,6 +571,12 @@ Return Value:
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
" - The DMA Profile is WdfDmaProfileScatterGather64Duplex");
+ //
+ // Opt-in to DMA version 3, which is required by
+ // WdfDmaTransactionSetSingleTransferRequirement
+ //
+ dmaConfig.WdmDmaVersionOverride = 3;
+
status = WdfDmaEnablerCreate( DevExt->Device,
&dmaConfig,
WDF_NO_OBJECT_ATTRIBUTES,
@@ -497,6 +588,16 @@ Return Value:
"WdfDmaEnablerCreate failed: %!STATUS!", status);
return status;
}
+
+ //
+ // The PLX device does not have a hard limit on the number of DTEs
+ // it can process for each DMA operation. However, the DTEs are written
+ // to common buffers whose size is the effective upper bound to the
+ // length of the Scatter/Gather lists we can work with.
+ //
+ WdfDmaEnablerSetMaximumScatterGatherElements(
+ DevExt->DmaEnabler,
+ min(DevExt->WriteTransferElements, DevExt->ReadTransferElements));
}
//
@@ -610,6 +711,27 @@ Return Value:
return status;
}
+#ifdef SIMULATE_MEMORY_FRAGMENTATION
+ //
+ // Allocate MDL chains that will be used to simulate memory fragmentation.
+ //
+ status = BuildMdlChain(&DevExt->WriteMdlChain);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "BuildMdlChain(Write) failed: %!STATUS!",
+ status);
+ return status;
+ }
+
+ status = BuildMdlChain(&DevExt->ReadMdlChain);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "BuildMdlChain(Read) failed: %!STATUS!",
+ status);
+ return status;
+ }
+#endif
+
return status;
}