summaryrefslogtreecommitdiff
path: root/general/PLX9x5x
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /general/PLX9x5x
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'general/PLX9x5x')
-rw-r--r--general/PLX9x5x/PLX9x5x.sln46
-rw-r--r--general/PLX9x5x/ReadMe.md23
-rw-r--r--general/PLX9x5x/sys/Init.c777
-rw-r--r--general/PLX9x5x/sys/IsrDpc.c441
-rw-r--r--general/PLX9x5x/sys/Pci9656.c623
-rw-r--r--general/PLX9x5x/sys/Pci9656.h14
-rw-r--r--general/PLX9x5x/sys/Pci9656.rc14
-rw-r--r--general/PLX9x5x/sys/Pci9x5x.vcxproj221
-rw-r--r--general/PLX9x5x/sys/Pci9x5x.vcxproj.Filters54
-rw-r--r--general/PLX9x5x/sys/Precomp.h17
-rw-r--r--general/PLX9x5x/sys/Private.h211
-rw-r--r--general/PLX9x5x/sys/Public.h35
-rw-r--r--general/PLX9x5x/sys/Read.c453
-rw-r--r--general/PLX9x5x/sys/Reg9656.h259
-rw-r--r--general/PLX9x5x/sys/Write.c525
-rw-r--r--general/PLX9x5x/sys/pci9x5x.inx97
-rw-r--r--general/PLX9x5x/sys/precompsrc.c1
-rw-r--r--general/PLX9x5x/sys/trace.h66
-rw-r--r--general/PLX9x5x/test/plx.cpp1104
-rw-r--r--general/PLX9x5x/test/plx.hpp146
-rw-r--r--general/PLX9x5x/test/plx.vcxproj184
-rw-r--r--general/PLX9x5x/test/plx.vcxproj.Filters22
-rw-r--r--general/PLX9x5x/test/test.cmd2
23 files changed, 5335 insertions, 0 deletions
diff --git a/general/PLX9x5x/PLX9x5x.sln b/general/PLX9x5x/PLX9x5x.sln
new file mode 100644
index 00000000..c54db7f0
--- /dev/null
+++ b/general/PLX9x5x/PLX9x5x.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sys", "Sys", "{C3251AB4-8086-4862-985F-35302E40A027}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{954C16D2-23E1-4D8C-A040-5D4FB830D689}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pci9x5x", "sys\Pci9x5x.vcxproj", "{12A2C4C0-856A-49BE-9F54-30D4D040C3E9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plx", "test\plx.vcxproj", "{BF101CB1-B147-40AC-8F84-13AC122A2D37}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Debug|Win32.Build.0 = Debug|Win32
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Release|Win32.ActiveCfg = Release|Win32
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Release|Win32.Build.0 = Release|Win32
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Debug|x64.ActiveCfg = Debug|x64
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Debug|x64.Build.0 = Debug|x64
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Release|x64.ActiveCfg = Release|x64
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9}.Release|x64.Build.0 = Release|x64
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Debug|Win32.Build.0 = Debug|Win32
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Release|Win32.ActiveCfg = Release|Win32
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Release|Win32.Build.0 = Release|Win32
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Debug|x64.ActiveCfg = Debug|x64
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Debug|x64.Build.0 = Debug|x64
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Release|x64.ActiveCfg = Release|x64
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {12A2C4C0-856A-49BE-9F54-30D4D040C3E9} = {C3251AB4-8086-4862-985F-35302E40A027}
+ {BF101CB1-B147-40AC-8F84-13AC122A2D37} = {954C16D2-23E1-4D8C-A040-5D4FB830D689}
+ EndGlobalSection
+EndGlobal
diff --git a/general/PLX9x5x/ReadMe.md b/general/PLX9x5x/ReadMe.md
new file mode 100644
index 00000000..a706b7d0
--- /dev/null
+++ b/general/PLX9x5x/ReadMe.md
@@ -0,0 +1,23 @@
+PLX9x5x PCI Driver
+==================
+
+This sample demonstrates how to write driver for a generic PCI device using Windows Driver Framework. The target hardware for this driver is PLX9656/9653RDK-LITE board. The product kit and the hardware specification are available at <http://www.plxtech.com>.
+
+For more information, see [Peripheral Component Interconnect (PCI) Bus Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537451).
+
+The device is a PCI device with port, memory, interrupt and DMA resources. Device can be stopped and started at run-time and also supports low power states. The driver is capable of doing concurrent read and write operations to the device but it can handle only one read or write request at any time. The following lists the driver framework interfaces demonstrated in this sample:
+
+- Handling PnP & Power Events
+- Registering a Device Interface
+- Hardware resource mapping: Port, Memory & Interrupt
+- DMA Interfaces
+- Serialized Default Queue for Write requests
+- Serialized custom Queue for Read requests
+- Handling Interrupt & DPC
+
+To test the driver, run the PLX.EXE test application.
+
+This sample driver is a minimal driver meant to demonstrate the usage of the Windows Driver Framework. It is not intended for use in a production environment.
+
+
+
diff --git a/general/PLX9x5x/sys/Init.c b/general/PLX9x5x/sys/Init.c
new file mode 100644
index 00000000..b18c80c6
--- /dev/null
+++ b/general/PLX9x5x/sys/Init.c
@@ -0,0 +1,777 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Init.c
+
+Abstract:
+
+ Contains most of initialization functions
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "precomp.h"
+
+#include "Init.tmh"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (PAGE, PLxInitializeDeviceExtension)
+#pragma alloc_text (PAGE, PLxPrepareHardware)
+#pragma alloc_text (PAGE, PLxInitializeDMA)
+#endif
+
+PVOID LocalMmMapIoSpace(
+ _In_ PHYSICAL_ADDRESS PhysicalAddress,
+ _In_ SIZE_T NumberOfBytes
+ )
+{
+ typedef
+ PVOID
+ (*PFN_MM_MAP_IO_SPACE_EX) (
+ _In_ PHYSICAL_ADDRESS PhysicalAddress,
+ _In_ SIZE_T NumberOfBytes,
+ _In_ ULONG Protect
+ );
+
+ UNICODE_STRING name;
+ PFN_MM_MAP_IO_SPACE_EX pMmMapIoSpaceEx;
+
+ RtlInitUnicodeString(&name, L"MmMapIoSpaceEx");
+ pMmMapIoSpaceEx = (PFN_MM_MAP_IO_SPACE_EX) (ULONG_PTR)MmGetSystemRoutineAddress(&name);
+
+ if (pMmMapIoSpaceEx != NULL){
+ //
+ // Call WIN10 API if available
+ //
+ return pMmMapIoSpaceEx(PhysicalAddress,
+ NumberOfBytes,
+ PAGE_READWRITE | PAGE_NOCACHE);
+ }
+
+ return MmMapIoSpace(PhysicalAddress, NumberOfBytes, MmNonCached);
+}
+
+
+NTSTATUS
+PLxInitializeDeviceExtension(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ This routine is called by EvtDeviceAdd. Here the device context is
+ initialized and all the software resources required by the device is
+ allocated.
+
+Arguments:
+
+ DevExt Pointer to the Device Extension
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ NTSTATUS status;
+ ULONG dteCount;
+ WDF_IO_QUEUE_CONFIG queueConfig;
+
+ PAGED_CODE();
+
+ //
+ // Set Maximum Transfer Length (which must be less than the SRAM size).
+ //
+ DevExt->MaximumTransferLength = PCI9656_MAXIMUM_TRANSFER_LENGTH;
+ if(DevExt->MaximumTransferLength > PCI9656_SRAM_SIZE) {
+ DevExt->MaximumTransferLength = PCI9656_SRAM_SIZE;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "MaximumTransferLength %d", DevExt->MaximumTransferLength);
+
+ //
+ // 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);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Number of DTEs %d", dteCount);
+
+ //
+ // Set the number of DMA_TRANSFER_ELEMENTs (DTE) to be available.
+ //
+ DevExt->WriteTransferElements = dteCount;
+ DevExt->ReadTransferElements = dteCount;
+
+ //
+ // The PCI9656 has two DMA Channels. This driver will use DMA Channel 0
+ // as the "ToDevice" channel (Writes) and DMA Channel 1 as the
+ // "From Device" channel (Reads).
+ //
+ // In order to support "duplex" DMA operation (the ability to have
+ // concurrent reads and writes) two Dispatch Queues are created:
+ // one for the Write (ToDevice) requests and another for the Read
+ // (FromDevice) requests. While eache Dispatch Queue will operate
+ // independently for each other, the requests within a given Dispatch
+ // Queue will be serialized. This is hardware can only process one request
+ // per DMA Channel at a time.
+ //
+
+
+ //
+ // Setup a queue to handle only IRP_MJ_WRITE requests in Sequential
+ // dispatch mode. This mode ensures there is only one write request
+ // outstanding in the driver at any time. Framework will present the next
+ // request only if the current request is completed.
+ // Since we have configured the queue to dispatch all the specific requests
+ // we care about, we don't need a default queue. A default queue is
+ // used to receive requests that are not preconfigured to goto
+ // a specific queue.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT ( &queueConfig,
+ WdfIoQueueDispatchSequential);
+
+ queueConfig.EvtIoWrite = PLxEvtIoWrite;
+
+ //
+ // Static Driver Verifier (SDV) displays a warning if it doesn't find the
+ // EvtIoStop callback on a power-managed queue. The 'assume' below lets
+ // SDV know not to worry about the EvtIoStop.
+ // If not explicitly set, the framework creates power-managed queues when
+ // the device is not a filter driver. Normally the EvtIoStop is required
+ // for power-managed queues, but for this driver it is not need b/c the
+ // driver doesn't hold on to the requests for long time or forward them to
+ // other drivers.
+ // If the EvtIoStop callback is not implemented, the framework
+ // waits for all in-flight (driver owned) requests to be done before
+ // moving the device in the Dx/sleep states or before removing the device,
+ // which is the correct behavior for this type of driver.
+ // If the requests were taking an undetermined amount of time to complete,
+ // or the requests were forwarded to a lower driver/another stack, the
+ // queue should have an EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(queueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate( DevExt->Device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->WriteQueue );
+ __analysis_assume(queueConfig.EvtIoStop == 0);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed: %!STATUS!", status);
+ return status;
+ }
+
+ //
+ // Set the Write Queue forwarding for IRP_MJ_WRITE requests.
+ //
+ status = WdfDeviceConfigureRequestDispatching( DevExt->Device,
+ DevExt->WriteQueue,
+ WdfRequestTypeWrite);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "DeviceConfigureRequestDispatching failed: %!STATUS!", status);
+ return status;
+ }
+
+
+ //
+ // Create a new IO Queue for IRP_MJ_READ requests in sequential mode.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT( &queueConfig,
+ WdfIoQueueDispatchSequential);
+
+ queueConfig.EvtIoRead = PLxEvtIoRead;
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests for
+ // long time or forward them to other drivers.
+ // If the EvtIoStop callback is not implemented, the framework waits for
+ // all driver-owned requests to be done before moving in the Dx/sleep
+ // states or before removing the device, which is the correct behavior
+ // for this type of driver. If the requests were taking an indeterminate
+ // amount of time to complete, or if the driver forwarded the requests
+ // to a lower driver/another stack, the queue should have an
+ // EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(queueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate( DevExt->Device,
+ &queueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->ReadQueue );
+ __analysis_assume(queueConfig.EvtIoStop == 0);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed: %!STATUS!", status);
+ return status;
+ }
+
+ //
+ // Set the Read Queue forwarding for IRP_MJ_READ requests.
+ //
+ status = WdfDeviceConfigureRequestDispatching( DevExt->Device,
+ DevExt->ReadQueue,
+ WdfRequestTypeRead);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "DeviceConfigureRequestDispatching failed: %!STATUS!", status);
+ return status;
+ }
+
+
+ //
+ // Create a WDFINTERRUPT object.
+ //
+ status = PLxInterruptCreate(DevExt);
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = PLxInitializeDMA( DevExt );
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+PLxPrepareHardware(
+ IN PDEVICE_EXTENSION DevExt,
+ IN WDFCMRESLIST ResourcesTranslated
+ )
+/*++
+Routine Description:
+
+ Gets the HW resources assigned by the bus driver from the start-irp
+ and maps it to system address space.
+
+Arguments:
+
+ DevExt Pointer to our DEVICE_EXTENSION
+
+Return Value:
+
+ None
+
+--*/
+{
+ ULONG i;
+ NTSTATUS status = STATUS_SUCCESS;
+ CHAR * bar;
+
+ BOOLEAN foundRegs = FALSE;
+ PHYSICAL_ADDRESS regsBasePA = {0};
+ ULONG regsLength = 0;
+
+ BOOLEAN foundSRAM = FALSE;
+ PHYSICAL_ADDRESS SRAMBasePA = {0};
+ ULONG SRAMLength = 0;
+
+ BOOLEAN foundSRAM2 = FALSE;
+ //PHYSICAL_ADDRESS SRAM2BasePA = {0};
+ //ULONG SRAM2Length = 0;
+
+ BOOLEAN foundPort = FALSE;
+
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+
+ PAGED_CODE();
+
+ //
+ // Parse the resource list and save the resource information.
+ //
+ for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {
+
+ desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i );
+
+ if(!desc) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfResourceCmGetDescriptor failed");
+ return STATUS_DEVICE_CONFIGURATION_ERROR;
+ }
+
+ switch (desc->Type) {
+
+ case CmResourceTypeMemory:
+
+ bar = NULL;
+
+ if (foundSRAM && !foundSRAM2 &&
+ desc->u.Memory.Length == PCI9656_SRAM_SIZE) {
+
+ //SRAM2BasePA = desc->u.Memory.Start;
+ //SRAM2Length = desc->u.Memory.Length;
+ foundSRAM2 = TRUE;
+ bar = "BAR3";
+ }
+
+ if (foundRegs && !foundSRAM &&
+ desc->u.Memory.Length == PCI9656_SRAM_SIZE) {
+
+ SRAMBasePA = desc->u.Memory.Start;
+ SRAMLength = desc->u.Memory.Length;
+ foundSRAM = TRUE;
+ bar = "BAR2";
+ }
+
+ if (!foundRegs &&
+ desc->u.Memory.Length == 0x200) {
+
+ regsBasePA = desc->u.Memory.Start;
+ regsLength = desc->u.Memory.Length;
+ foundRegs = TRUE;
+ bar = "BAR0";
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " - Memory Resource [%I64X-%I64X] %s",
+ desc->u.Memory.Start.QuadPart,
+ desc->u.Memory.Start.QuadPart +
+ desc->u.Memory.Length,
+ (bar) ? bar : "<unrecognized>" );
+ break;
+
+ case CmResourceTypePort:
+
+ bar = NULL;
+
+ if (!foundPort &&
+ desc->u.Port.Length >= 0x100) {
+ foundPort = TRUE;
+ bar = "BAR1";
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " - Port Resource [%08I64X-%08I64X] %s",
+ desc->u.Port.Start.QuadPart,
+ desc->u.Port.Start.QuadPart +
+ desc->u.Port.Length,
+ (bar) ? bar : "<unrecognized>" );
+ break;
+
+ default:
+ //
+ // Ignore all other descriptors
+ //
+ break;
+ }
+ }
+
+ if (!(foundRegs && foundSRAM)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "PLxMapResources: Missing resources");
+ return STATUS_DEVICE_CONFIGURATION_ERROR;
+ }
+
+ //
+ // Map in the Registers Memory resource: BAR0
+ //
+ DevExt->RegsBase = (PUCHAR) LocalMmMapIoSpace(regsBasePA,
+ regsLength);
+
+ if (!DevExt->RegsBase) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ " - Unable to map Registers memory %08I64X, length %d",
+ regsBasePA.QuadPart, regsLength);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ DevExt->RegsLength = regsLength;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " - Registers %p, length %d",
+ DevExt->RegsBase, DevExt->RegsLength );
+
+ //
+ // Set seperated pointer to PCI9656_REGS structure.
+ //
+ DevExt->Regs = (PPCI9656_REGS) DevExt->RegsBase;
+
+ //
+ // Map in the SRAM Memory Space resource: BAR2
+ //
+ DevExt->SRAMBase = (PUCHAR) LocalMmMapIoSpace(SRAMBasePA,
+ SRAMLength);
+
+ if (!DevExt->SRAMBase) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ " - Unable to map SRAM memory %08I64X, length %d",
+ SRAMBasePA.QuadPart, SRAMLength);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ DevExt->SRAMLength = SRAMLength;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " - SRAM %p, length %d",
+ DevExt->SRAMBase, DevExt->SRAMLength );
+
+ return status;
+}
+
+NTSTATUS
+PLxInitializeDMA(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ Initializes the DMA adapter.
+
+Arguments:
+
+ DevExt Pointer to our DEVICE_EXTENSION
+
+Return Value:
+
+ None
+
+--*/
+{
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ PAGED_CODE();
+
+ //
+ // PLx PCI9656 DMA_TRANSFER_ELEMENTS must be 16-byte aligned
+ //
+ WdfDeviceSetAlignmentRequirement( DevExt->Device,
+ PCI9656_DTE_ALIGNMENT_16 );
+
+ //
+ // Create a new DMA Enabler instance.
+ // Use Scatter/Gather, 64-bit Addresses, Duplex-type profile.
+ //
+ {
+ WDF_DMA_ENABLER_CONFIG dmaConfig;
+
+ WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
+ WdfDmaProfileScatterGather64Duplex,
+ DevExt->MaximumTransferLength );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " - The DMA Profile is WdfDmaProfileScatterGather64Duplex");
+
+ status = WdfDmaEnablerCreate( DevExt->Device,
+ &dmaConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->DmaEnabler );
+
+ if (!NT_SUCCESS (status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDmaEnablerCreate failed: %!STATUS!", status);
+ return status;
+ }
+ }
+
+ //
+ // Allocate common buffer for building writes
+ //
+ // NOTE: This common buffer will not be cached.
+ // Perhaps in some future revision, cached option could
+ // be used. This would have faster access, but requires
+ // flushing before starting the DMA in PLxStartWriteDma.
+ //
+ DevExt->WriteCommonBufferSize =
+ sizeof(DMA_TRANSFER_ELEMENT) * DevExt->WriteTransferElements;
+
+ _Analysis_assume_(DevExt->WriteCommonBufferSize > 0);
+ status = WdfCommonBufferCreate( DevExt->DmaEnabler,
+ DevExt->WriteCommonBufferSize,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->WriteCommonBuffer );
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfCommonBufferCreate (write) failed: %!STATUS!", status);
+ return status;
+ }
+
+
+ DevExt->WriteCommonBufferBase =
+ WdfCommonBufferGetAlignedVirtualAddress(DevExt->WriteCommonBuffer);
+
+ DevExt->WriteCommonBufferBaseLA =
+ WdfCommonBufferGetAlignedLogicalAddress(DevExt->WriteCommonBuffer);
+
+ RtlZeroMemory( DevExt->WriteCommonBufferBase,
+ DevExt->WriteCommonBufferSize);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "WriteCommonBuffer 0x%p (#0x%I64X), length %I64d",
+ DevExt->WriteCommonBufferBase,
+ DevExt->WriteCommonBufferBaseLA.QuadPart,
+ WdfCommonBufferGetLength(DevExt->WriteCommonBuffer) );
+
+ //
+ // Allocate common buffer for building reads
+ //
+ // NOTE: This common buffer will not be cached.
+ // Perhaps in some future revision, cached option could
+ // be used. This would have faster access, but requires
+ // flushing before starting the DMA in PLxStartReadDma.
+ //
+ DevExt->ReadCommonBufferSize =
+ sizeof(DMA_TRANSFER_ELEMENT) * DevExt->ReadTransferElements;
+
+ _Analysis_assume_(DevExt->ReadCommonBufferSize > 0);
+ status = WdfCommonBufferCreate( DevExt->DmaEnabler,
+ DevExt->ReadCommonBufferSize,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->ReadCommonBuffer );
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfCommonBufferCreate (read) failed %!STATUS!", status);
+ return status;
+ }
+
+ DevExt->ReadCommonBufferBase =
+ WdfCommonBufferGetAlignedVirtualAddress(DevExt->ReadCommonBuffer);
+
+ DevExt->ReadCommonBufferBaseLA =
+ WdfCommonBufferGetAlignedLogicalAddress(DevExt->ReadCommonBuffer);
+
+ RtlZeroMemory( DevExt->ReadCommonBufferBase,
+ DevExt->ReadCommonBufferSize);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "ReadCommonBuffer 0x%p (#0x%I64X), length %I64d",
+ DevExt->ReadCommonBufferBase,
+ DevExt->ReadCommonBufferBaseLA.QuadPart,
+ WdfCommonBufferGetLength(DevExt->ReadCommonBuffer) );
+
+ //
+ // Since we are using sequential queue and processing one request
+ // at a time, we will create transaction objects upfront and reuse
+ // them to do DMA transfer. Transactions objects are parented to
+ // DMA enabler object by default. They will be deleted along with
+ // along with the DMA enabler object. So need to delete them
+ // explicitly.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TRANSACTION_CONTEXT);
+
+ status = WdfDmaTransactionCreate( DevExt->DmaEnabler,
+ &attributes,
+ &DevExt->ReadDmaTransaction);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfDmaTransactionCreate(read) failed: %!STATUS!", status);
+ return status;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TRANSACTION_CONTEXT);
+ //
+ // Create a new DmaTransaction.
+ //
+ status = WdfDmaTransactionCreate( DevExt->DmaEnabler,
+ &attributes,
+ &DevExt->WriteDmaTransaction );
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfDmaTransactionCreate(write) failed: %!STATUS!", status);
+ return status;
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+PLxInitWrite(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ Initialize write data structures
+
+Arguments:
+
+ DevExt Pointer to Device Extension
+
+Return Value:
+
+ None
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxInitWrite");
+
+ //
+ // Make sure the Dma0 DAC (Dual Address Cycle) register is set to 0.
+ //
+ WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->Dma0_PCI_DAC, 0 );
+
+ //
+ // Clear the saved copy of the DMA Channel 0's CSR
+ //
+ DevExt->Dma0Csr.uchar = 0;
+
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxInitWrite");
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+PLxInitRead(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ Initialize read data structures
+
+Arguments:
+
+ DevExt Pointer to Device Extension
+
+Return Value:
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxInitRead");
+
+ //
+ // Make sure the DMA Chan 1 DAC (Dual Address Cycle) is set to 0.
+ //
+ WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->Dma1_PCI_DAC, 0 );
+
+ //
+ // Clear the saved copy of the DMA Channel 1's CSR
+ //
+ DevExt->Dma1Csr.uchar = 0;
+
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxInitRead");
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+PLxShutdown(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+
+Routine Description:
+
+ Reset the device to put the device in a known initial state.
+ This is called from D0Exit when the device is torn down or
+ when the system is shutdown. Note that Wdf has already
+ called out EvtDisable callback to disable the interrupt.
+
+Arguments:
+
+ DevExt - Pointer to our adapter
+
+Return Value:
+
+ None
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "---> PLxShutdown");
+
+ //
+ // WdfInterrupt is already disabled so issue a full reset
+ //
+ if (DevExt->Regs) {
+
+ PLxHardwareReset(DevExt);
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--- PLxShutdown");
+}
+
+VOID
+PLxHardwareReset(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ Called by D0Exit when the device is being disabled or when the system is shutdown to
+ put the device in a known initial state.
+
+Arguments:
+
+ DevExt Pointer to Device Extension
+
+Return Value:
+
+--*/
+{
+ LARGE_INTEGER delay;
+
+ union {
+ EEPROM_CSR bits;
+ ULONG ulong;
+ } eeCSR;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxIssueFullReset");
+
+ //
+ // Drive the 9656 into soft reset.
+ //
+ eeCSR.ulong =
+ READ_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat );
+
+ eeCSR.bits.SoftwareReset = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat,
+ eeCSR.ulong );
+
+ //
+ // Wait 100 msec.
+ //
+ delay.QuadPart = WDF_REL_TIMEOUT_IN_MS(100);
+
+ KeDelayExecutionThread( KernelMode, TRUE, &delay );
+
+ //
+ // Finally pull the 9656 out of reset.
+ //
+ eeCSR.bits.SoftwareReset = FALSE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat,
+ eeCSR.ulong );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxIssueFullReset");
+}
+
+
+
diff --git a/general/PLX9x5x/sys/IsrDpc.c b/general/PLX9x5x/sys/IsrDpc.c
new file mode 100644
index 00000000..a7d319d3
--- /dev/null
+++ b/general/PLX9x5x/sys/IsrDpc.c
@@ -0,0 +1,441 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ IsrDpc.c
+
+Abstract:
+
+ Contains routines related to interrupt and dpc handling.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "precomp.h"
+
+#include "IsrDpc.tmh"
+
+NTSTATUS
+PLxInterruptCreate(
+ IN PDEVICE_EXTENSION DevExt
+ )
+/*++
+Routine Description:
+
+ Configure and create the WDFINTERRUPT object.
+ This routine is called by EvtDeviceAdd callback.
+
+Arguments:
+
+ DevExt Pointer to our DEVICE_EXTENSION
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ WDF_INTERRUPT_CONFIG InterruptConfig;
+
+ WDF_INTERRUPT_CONFIG_INIT( &InterruptConfig,
+ PLxEvtInterruptIsr,
+ PLxEvtInterruptDpc );
+
+ InterruptConfig.EvtInterruptEnable = PLxEvtInterruptEnable;
+ InterruptConfig.EvtInterruptDisable = PLxEvtInterruptDisable;
+
+ // JOHNR: Enable testing of the DpcForIsr Synchronization
+ InterruptConfig.AutomaticSerialization = TRUE;
+
+ //
+ // Unlike WDM, framework driver should create interrupt object in EvtDeviceAdd and
+ // let the framework do the resource parsing and registration of ISR with the kernel.
+ // Framework connects the interrupt after invoking the EvtDeviceD0Entry callback
+ // and disconnect before invoking EvtDeviceD0Exit. EvtInterruptEnable is called after
+ // the interrupt interrupt is connected and EvtInterruptDisable before the interrupt is
+ // disconnected.
+ //
+ status = WdfInterruptCreate( DevExt->Device,
+ &InterruptConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &DevExt->Interrupt );
+
+ if( !NT_SUCCESS(status) ) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfInterruptCreate failed: %!STATUS!", status);
+ }
+
+ return status;
+}
+
+BOOLEAN
+PLxEvtInterruptIsr(
+ IN WDFINTERRUPT Interrupt,
+ IN ULONG MessageID
+ )
+/*++
+Routine Description:
+
+ Interrupt handler for this driver. Called at DIRQL level when the
+ device or another device sharing the same interrupt line asserts
+ the interrupt. The driver first checks the device to make sure whether
+ this interrupt is generated by its device and if so clear the interrupt
+ register to disable further generation of interrupts and queue a
+ DPC to do other I/O work related to interrupt - such as reading
+ the device memory, starting a DMA transaction, coping it to
+ the request buffer and completing the request, etc.
+
+Arguments:
+
+ Interupt - Handle to WDFINTERRUPT Object for this device.
+ MessageID - MSI message ID (always 0 in this configuration)
+
+Return Value:
+
+ TRUE -- This device generated the interrupt.
+ FALSE -- This device did not generated this interrupt.
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+ BOOLEAN isRecognized = FALSE;
+
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } intCsr;
+
+ UNREFERENCED_PARAMETER(MessageID);
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ // "--> PLxInterruptHandler");
+
+ devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
+
+ //
+ // Read the Interrupt CSR register (INTCSR)
+ //
+ intCsr.ulong = READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
+
+ //
+ // Is DMA channel 0 (Write-side) Active?
+ //
+ if (intCsr.bits.DmaChan0IntActive) {
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ " Interrupt for DMA Channel 0 (write)");
+
+ devExt->IntCsr.bits.DmaChan0IntActive = TRUE;
+
+ //
+ // Clear this interrupt.
+ //
+ devExt->Dma0Csr.uchar =
+ READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr );
+
+ devExt->Dma0Csr.bits.Clear = TRUE;
+
+ WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr,
+ devExt->Dma0Csr.uchar );
+
+ isRecognized = TRUE;
+ }
+
+ //
+ // Is DMA channel 1 (Read-side) Active?
+ //
+ if (intCsr.bits.DmaChan1IntActive) {
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ " Interrupt for DMA Channel 1 (read)");
+
+ devExt->IntCsr.bits.DmaChan1IntActive = TRUE;
+
+ //
+ // Clear this interrupt.
+ //
+ devExt->Dma1Csr.uchar =
+ READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr );
+
+ devExt->Dma1Csr.bits.Clear = TRUE;
+
+ WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr,
+ devExt->Dma1Csr.uchar );
+
+ isRecognized = TRUE;
+ }
+
+ if ((isRecognized) &&
+ ((devExt->Dma0Csr.bits.Done) ||
+ (devExt->Dma1Csr.bits.Done))) {
+ //
+ // A read or a write or both is done. Queue a DPC.
+ //
+ WdfInterruptQueueDpcForIsr( devExt->Interrupt );
+ }
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ // "<-- PLxInterruptHandler");
+
+ return isRecognized;
+}
+
+_Use_decl_annotations_
+VOID
+PLxEvtInterruptDpc(
+ WDFINTERRUPT Interrupt,
+ WDFOBJECT Device
+ )
+/*++
+
+Routine Description:
+
+ DPC callback for ISR. Please note that on a multiprocessor system,
+ you could have more than one DPCs running simulataneously on
+ multiple processors. So if you are accesing any global resources
+ make sure to synchrnonize the accesses with a spinlock.
+
+Arguments:
+
+ Interupt - Handle to WDFINTERRUPT Object for this device.
+ Device - WDFDEVICE object passed to InterruptCreate
+
+Return Value:
+
+--*/
+{
+ NTSTATUS status;
+ WDFDMATRANSACTION dmaTransaction;
+ PDEVICE_EXTENSION devExt;
+ BOOLEAN writeInterrupt = FALSE;
+ BOOLEAN readInterrupt = FALSE;
+
+ UNREFERENCED_PARAMETER(Device);
+
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "--> EvtInterruptDpc");
+
+ devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
+
+ //
+ // Acquire this device's InterruptSpinLock.
+ //
+ WdfInterruptAcquireLock( Interrupt );
+
+
+ if ((devExt->IntCsr.bits.DmaChan0IntActive) &&
+ (devExt->Dma0Csr.bits.Done)) {
+
+ //
+ // If Dma0 channel 0 (write) is interrupting and the
+ // Done bit is set in the Dma0 CSR,
+ // we're interrupting because a WRITE is complete.
+ // Clear the done bit and channel interrupting bit from
+ // our copies...
+ //
+ devExt->IntCsr.bits.DmaChan0IntActive = FALSE;
+ devExt->Dma0Csr.uchar = 0;
+
+ writeInterrupt = TRUE;
+ }
+
+ if ((devExt->IntCsr.bits.DmaChan1IntActive) &&
+ (devExt->Dma1Csr.bits.Done)) {
+
+ //
+ // If DMA channel 1 is interrupting and the
+ // DONE bit is set in the DMA1 control/status
+ // register, we're interrupting because a READ
+ // is complete.
+ // Clear the done bit and channel interrupting bit from
+ // our copies...
+ //
+ devExt->IntCsr.bits.DmaChan1IntActive = FALSE;
+ devExt->Dma0Csr.uchar = 0;
+
+ readInterrupt = TRUE;
+ }
+
+ //
+ // Release our interrupt spinlock
+ //
+ WdfInterruptReleaseLock( Interrupt );
+
+ //
+ // Did a Write DMA complete?
+ //
+ if (writeInterrupt) {
+
+ BOOLEAN transactionComplete;
+
+ //
+ // Get the current Write DmaTransaction.
+ //
+ dmaTransaction = devExt->WriteDmaTransaction;
+
+ //
+ // Indicate this DMA operation has completed:
+ // This may drive the transfer on the next packet if
+ // there is still data to be transfered in the request.
+ //
+ transactionComplete = WdfDmaTransactionDmaCompleted( dmaTransaction,
+ &status );
+
+ if (transactionComplete) {
+ //
+ // Complete this DmaTransaction.
+ //
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
+ "Completing Write request in the DpcForIsr");
+
+ PLxWriteRequestComplete( dmaTransaction, status );
+
+ }
+ }
+
+ //
+ // Did a Read DMA complete?
+ //
+ if (readInterrupt) {
+
+ BOOLEAN transactionComplete;
+ PDMA_TRANSFER_ELEMENT dteVA;
+ size_t length;
+
+ //
+ // Get the current Read DmaTransaction.
+ //
+ dmaTransaction = devExt->ReadDmaTransaction;
+
+ //
+ // Only on Read-side --
+ // Use "DMA Clear-Count Mode" to get complemetary
+ // transferred byte count.
+ //
+ length = WdfDmaTransactionGetCurrentDmaTransferLength( dmaTransaction );
+
+ dteVA = (PDMA_TRANSFER_ELEMENT) devExt->ReadCommonBufferBase;
+
+ while(dteVA->DescPtr.LastElement == FALSE) {
+ length -= dteVA->TransferSize;
+ dteVA++;
+ }
+ length -= dteVA->TransferSize;
+
+ //
+ // Indicate this DMA operation has completed:
+ // This may drive the transfer on the next packet if
+ // there is still data to be transfered in the request.
+ //
+ transactionComplete =
+ WdfDmaTransactionDmaCompletedWithLength( dmaTransaction,
+ length,
+ &status );
+
+ if (transactionComplete) {
+ //
+ // Complete this DmaTransaction.
+ //
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
+ "Completing Read request in the DpcForIsr");
+
+ PLxReadRequestComplete( dmaTransaction, status );
+
+ }
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "<-- EvtInterruptDpc");
+
+ return;
+}
+
+NTSTATUS
+PLxEvtInterruptEnable(
+ IN WDFINTERRUPT Interrupt,
+ IN WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework at DIRQL immediately after registering the ISR with the kernel
+ by calling IoConnectInterrupt.
+
+Return Value:
+
+ NTSTATUS
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } intCSR;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ "PLxEvtInterruptEnable: Interrupt 0x%p, Device 0x%p\n",
+ Interrupt, Device);
+
+ devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
+
+ intCSR.ulong = READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
+
+ intCSR.bits.PciIntEnable = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
+ intCSR.ulong );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PLxEvtInterruptDisable(
+ IN WDFINTERRUPT Interrupt,
+ IN WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework at DIRQL before Deregistering the ISR with the kernel
+ by calling IoDisconnectInterrupt.
+
+Return Value:
+
+ NTSTATUS
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } intCSR;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
+ "PLxEvtInterruptDisable: Interrupt 0x%p, Device 0x%p\n",
+ Interrupt, Device);
+
+ devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
+
+ intCSR.ulong = READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
+
+ intCSR.bits.PciIntEnable = FALSE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
+ intCSR.ulong );
+
+ return STATUS_SUCCESS;
+}
diff --git a/general/PLX9x5x/sys/Pci9656.c b/general/PLX9x5x/sys/Pci9656.c
new file mode 100644
index 00000000..176b9ca7
--- /dev/null
+++ b/general/PLX9x5x/sys/Pci9656.c
@@ -0,0 +1,623 @@
+/*++
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Pci9656.c
+
+Abstract:
+
+ This is a generic WDF sample driver for PLx PCI9656RDK-Lite reference
+ adapter. It illustrates how to use the WDF DmaObject to perform
+ Scatter/Gather DMA operations.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "precomp.h"
+//
+// The trace message header (.tmh) file must be included in a source file
+// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS
+// macro (defined in toaster.h). During the compilation, WPP scans the source
+// files for DoTraceMessage() calls and builds a .tmh file which stores a unique
+// data GUID for each message, the text resource string for each message,
+// and the data types of the variables passed in for each message. This file
+// is automatically generated by the WPP preprocessor.
+//
+#include "Pci9656.tmh"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (INIT, DriverEntry)
+#pragma alloc_text (PAGE, PLxEvtDeviceAdd)
+#pragma alloc_text (PAGE, PLxEvtDevicePrepareHardware)
+#pragma alloc_text (PAGE, PLxEvtDeviceReleaseHardware)
+#pragma alloc_text (PAGE, PLxEvtDeviceD0Exit)
+#pragma alloc_text (PAGE, PlxEvtDriverContextCleanup)
+#pragma alloc_text (PAGE, PLxSetIdleAndWakeSettings)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ Driver initialization entry point.
+ This entry point is called directly by the I/O system.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path,
+ to driver-specific key in the registry.
+
+Return Value:
+
+ NTSTATUS - if the status value is not STATUS_SUCCESS,
+ the driver will get unloaded immediately.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ WDF_DRIVER_CONFIG config;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ //
+ // Initialize WDF WPP tracing.
+ //
+ WPP_INIT_TRACING( DriverObject, RegistryPath );
+
+ //
+ // TraceEvents function is mapped to DoTraceMessage provided by
+ // WPP by using a directive in the sources file.
+ //
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "Pci9656 Sample - Driver Framework Edition.");
+
+ //
+ // Initialize the Driver Config structure.
+ //
+ WDF_DRIVER_CONFIG_INIT( &config, PLxEvtDeviceAdd );
+
+ //
+ // Register a cleanup callback so that we can call WPP_CLEANUP when
+ // the framework driver object is deleted during driver unload.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = PlxEvtDriverContextCleanup;
+
+ status = WdfDriverCreate( DriverObject,
+ RegistryPath,
+ &attributes,
+ &config,
+ WDF_NO_HANDLE);
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDriverCreate failed with status %!STATUS!", status);
+ //
+ // Cleanup tracing here because DriverContextCleanup will not be called
+ // as we have failed to create WDFDRIVER object itself.
+ // Please note that if your return failure from DriverEntry after the
+ // WDFDRIVER object is created successfully, you don't have to
+ // call WPP cleanup because in those cases DriverContextCleanup
+ // will be executed when the framework deletes the DriverObject.
+ //
+ WPP_CLEANUP(DriverObject);
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+PLxEvtDeviceAdd(
+ IN WDFDRIVER Driver,
+ IN PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+
+Routine Description:
+
+ EvtDeviceAdd is called by the framework in response to AddDevice
+ call from the PnP manager. Here the driver should register all the
+ PNP, power and Io callbacks, register interfaces and allocate other
+ software resources required by the device. The driver can query
+ any interfaces or get the config space information from the bus driver
+ but cannot access hardware registers or initialize the device.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDFDEVICE device;
+ PDEVICE_EXTENSION devExt = NULL;
+
+ UNREFERENCED_PARAMETER( Driver );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxEvtDeviceAdd");
+
+ PAGED_CODE();
+
+ WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
+
+ //
+ // Zero out the PnpPowerCallbacks structure.
+ //
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+
+ //
+ // Set Callbacks for any of the functions we are interested in.
+ // If no callback is set, Framework will take the default action
+ // by itself.
+ //
+ pnpPowerCallbacks.EvtDevicePrepareHardware = PLxEvtDevicePrepareHardware;
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = PLxEvtDeviceReleaseHardware;
+
+ //
+ // These two callbacks set up and tear down hardware state that must be
+ // done every time the device moves in and out of the D0-working state.
+ //
+ pnpPowerCallbacks.EvtDeviceD0Entry = PLxEvtDeviceD0Entry;
+ pnpPowerCallbacks.EvtDeviceD0Exit = PLxEvtDeviceD0Exit;
+
+ //
+ // Register the PnP Callbacks..
+ //
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ //
+ // Initialize Fdo Attributes.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION);
+ //
+ // By opting for SynchronizationScopeDevice, we tell the framework to
+ // synchronize callbacks events of all the objects directly associated
+ // with the device. In this driver, we will associate queues and
+ // and DpcForIsr. By doing that we don't have to worrry about synchronizing
+ // access to device-context by Io Events and DpcForIsr because they would
+ // not concurrently ever. Framework will serialize them by using an
+ // internal device-lock.
+ //
+ attributes.SynchronizationScope = WdfSynchronizationScopeDevice;
+
+ //
+ // Create the device
+ //
+ status = WdfDeviceCreate( &DeviceInit, &attributes, &device );
+
+ if (!NT_SUCCESS(status)) {
+ //
+ // Device Initialization failed.
+ //
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "DeviceCreate failed %!STATUS!", status);
+ return status;
+ }
+
+ //
+ // Get the DeviceExtension and initialize it. PLxGetDeviceContext is an inline function
+ // defined by WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in the
+ // private header file. This function will do the type checking and return
+ // the device context. If you pass a wrong object a wrong object handle
+ // it will return NULL and assert if run under framework verifier mode.
+ //
+ devExt = PLxGetDeviceContext(device);
+
+ devExt->Device = device;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ " AddDevice PDO (0x%p) FDO (0x%p), DevExt (0x%p)",
+ WdfDeviceWdmGetPhysicalDevice(device),
+ WdfDeviceWdmGetDeviceObject(device), devExt);
+
+ //
+ // Tell the Framework that this device will need an interface
+ //
+ // NOTE: See the note in Public.h concerning this GUID value.
+ //
+ status = WdfDeviceCreateDeviceInterface( device,
+ (LPGUID) &GUID_PLX_INTERFACE,
+ NULL );
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "<-- DeviceCreateDeviceInterface "
+ "failed %!STATUS!", status);
+ return status;
+ }
+
+ //
+ // Set the idle and wait-wake policy for this device.
+ //
+ status = PLxSetIdleAndWakeSettings(devExt);
+
+ if (!NT_SUCCESS (status)) {
+ //
+ // NOTE: The attempt to set the Idle and Wake options
+ // is a best-effort try. Failure is probably due to
+ // the non-driver environmentals, such as the system,
+ // bus or OS indicating that Wake is not supported for
+ // this case.
+ // All that being said, it probably not desirable to
+ // return the failure code as it would cause the
+ // AddDevice to fail and Idle and Wake are probably not
+ // "must-have" options.
+ //
+ // You must decide for your case whether Idle/Wake are
+ // "must-have" options...but my guess is probably not.
+ //
+#if 1
+ status = STATUS_SUCCESS;
+#else
+ return status;
+#endif
+ }
+
+ //
+ // Initalize the Device Extension.
+ //
+ status = PLxInitializeDeviceExtension(devExt);
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "<-- PLxEvtDeviceAdd %!STATUS!", status);
+
+ return status;
+}
+
+NTSTATUS
+PLxEvtDevicePrepareHardware (
+ WDFDEVICE Device,
+ WDFCMRESLIST Resources,
+ WDFCMRESLIST ResourcesTranslated
+ )
+/*++
+
+Routine Description:
+
+ Performs whatever initialization is needed to setup the device, setting up
+ a DMA channel or mapping any I/O port resources. This will only be called
+ as a device starts or restarts, not every time the device moves into the D0
+ state. Consequently, most hardware initialization belongs elsewhere.
+
+Arguments:
+
+ Device - A handle to the WDFDEVICE
+
+ Resources - The raw PnP resources associated with the device. Most of the
+ time, these aren't useful for a PCI device.
+
+ ResourcesTranslated - The translated PnP resources associated with the
+ device. This is what is important to a PCI device.
+
+Return Value:
+
+ NT status code - failure will result in the device stack being torn down
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PDEVICE_EXTENSION devExt;
+
+ UNREFERENCED_PARAMETER(Resources);
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "--> PLxEvtDevicePrepareHardware");
+
+ devExt = PLxGetDeviceContext(Device);
+
+ status = PLxPrepareHardware(devExt, ResourcesTranslated);
+ if (!NT_SUCCESS (status)){
+ return status;
+ }
+
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "<-- PLxEvtDevicePrepareHardware, status %!STATUS!", status);
+
+ return status;
+}
+
+NTSTATUS
+PLxEvtDeviceReleaseHardware(
+ IN WDFDEVICE Device,
+ IN WDFCMRESLIST ResourcesTranslated
+ )
+/*++
+
+Routine Description:
+
+ Unmap the resources that were mapped in PLxEvtDevicePrepareHardware.
+ This will only be called when the device stopped for resource rebalance,
+ surprise-removed or query-removed.
+
+Arguments:
+
+ Device - A handle to the WDFDEVICE
+
+ ResourcesTranslated - The translated PnP resources associated with the
+ device. This is what is important to a PCI device.
+
+Return Value:
+
+ NT status code - failure will result in the device stack being torn down
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(ResourcesTranslated);
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "--> PLxEvtDeviceReleaseHardware");
+
+ devExt = PLxGetDeviceContext(Device);
+
+ if (devExt->RegsBase) {
+
+ MmUnmapIoSpace(devExt->RegsBase, devExt->RegsLength);
+ devExt->RegsBase = NULL;
+ }
+
+ if(devExt->SRAMBase){
+ MmUnmapIoSpace(devExt->SRAMBase, devExt->SRAMLength);
+ devExt->SRAMBase = NULL;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "<-- PLxEvtDeviceReleaseHardware");
+
+ return status;
+}
+
+
+NTSTATUS
+PLxEvtDeviceD0Entry(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE PreviousState
+ )
+/*++
+
+Routine Description:
+
+ This routine prepares the device for use. It is called whenever the device
+ enters the D0 state, which happens when the device is started, when it is
+ restarted, and when it has been powered off.
+
+ Note that interrupts will not be enabled at the time that this is called.
+ They will be enabled after this callback completes.
+
+ This function is not marked pageable because this function is in the
+ device power up path. When a function is marked pagable and the code
+ section is paged out, it will generate a page fault which could impact
+ the fast resume behavior because the client driver will have to wait
+ until the system drivers can service this page fault.
+
+Arguments:
+
+ Device - The handle to the WDF device object
+
+ PreviousState - The state the device was in before this callback was invoked.
+
+Return Value:
+
+ NTSTATUS
+
+ Success implies that the device can be used.
+
+ Failure will result in the device stack being torn down.
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ devExt = PLxGetDeviceContext(Device);
+
+ status = PLxInitWrite( devExt );
+ if (NT_SUCCESS(status)) {
+
+ status = PLxInitRead( devExt );
+
+ }
+
+ return status;
+}
+
+NTSTATUS
+PLxEvtDeviceD0Exit(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE TargetState
+ )
+/*++
+
+Routine Description:
+
+ This routine undoes anything done in PLxEvtDeviceD0Entry. It is called
+ whenever the device leaves the D0 state, which happens when the device
+ is stopped, when it is removed, and when it is powered off.
+
+ The device is still in D0 when this callback is invoked, which means that
+ the driver can still touch hardware in this routine.
+
+ Note that interrupts have already been disabled by the time that this
+ callback is invoked.
+
+Arguments:
+
+ Device - The handle to the WDF device object
+
+ TargetState - The state the device will go to when this callback completes.
+
+Return Value:
+
+ Success implies that the device can be used. Failure will result in the
+ device stack being torn down.
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+
+ PAGED_CODE();
+
+ devExt = PLxGetDeviceContext(Device);
+
+ switch (TargetState) {
+ case WdfPowerDeviceD1:
+ case WdfPowerDeviceD2:
+ case WdfPowerDeviceD3:
+
+ //
+ // Fill in any code to save hardware state here.
+ //
+
+ //
+ // Fill in any code to put the device in a low-power state here.
+ //
+ break;
+
+ case WdfPowerDevicePrepareForHibernation:
+
+ //
+ // Fill in any code to save hardware state here. Do not put in any
+ // code to shut the device off. If this device cannot support being
+ // in the paging path (or being a parent or grandparent of a paging
+ // path device) then this whole case can be deleted.
+ //
+
+ break;
+
+ case WdfPowerDeviceD3Final:
+ default:
+
+ //
+ // Reset the hardware, as we're shutting down for the last time.
+ //
+ PLxShutdown(devExt);
+ break;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+_Use_decl_annotations_
+VOID
+PlxEvtDriverContextCleanup(
+ WDFOBJECT Driver
+ )
+/*++
+Routine Description:
+
+ Free all the resources allocated in DriverEntry.
+
+Arguments:
+
+ Driver - handle to a WDF Driver object.
+
+Return Value:
+
+ VOID.
+
+--*/
+{
+ PAGED_CODE ();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "PlxEvtDriverContextCleanup: enter");
+
+ WPP_CLEANUP( WdfDriverWdmGetDriverObject( Driver ) );
+
+}
+
+
+
+NTSTATUS
+PLxSetIdleAndWakeSettings(
+ IN PDEVICE_EXTENSION FdoData
+ )
+/*++
+Routine Description:
+
+ Called by EvtDeviceAdd to set the idle and wait-wake policy. Registering this policy
+ causes Power Management Tab to show up in the device manager. By default these
+ options are enabled and the user is provided control to change the settings.
+
+Return Value:
+
+ NTSTATUS - Failure status is returned if the device is not capable of suspending
+ or wait-waking the machine by an external event. Framework checks the
+ capability information reported by the bus driver to decide whether the device is
+ capable of waking the machine.
+
+--*/
+{
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxSetIdleAndWakeSettings");
+
+ PAGED_CODE();
+
+ //
+ // Init the idle policy structure.
+ //
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0);
+ idleSettings.IdleTimeout = 10000; // 10-sec
+
+ status = WdfDeviceAssignS0IdleSettings(FdoData->Device, &idleSettings);
+ if ( !NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "DeviceSetPowerPolicyS0IdlePolicy failed %!STATUS!", status);
+ return status;
+ }
+
+ //
+ // Init wait-wake policy structure.
+ //
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
+
+ status = WdfDeviceAssignSxWakeSettings(FdoData->Device, &wakeSettings);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "DeviceAssignSxWakeSettings failed %!STATUS!", status);
+ return status;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxSetIdleAndWakeSettings");
+
+ return status;
+}
+
+
diff --git a/general/PLX9x5x/sys/Pci9656.h b/general/PLX9x5x/sys/Pci9656.h
new file mode 100644
index 00000000..48e9260d
--- /dev/null
+++ b/general/PLX9x5x/sys/Pci9656.h
@@ -0,0 +1,14 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "WDF Driver for PLx PCI9656RDK-Lite Adapter"
+#define VER_INTERNALNAME_STR "PCI9656.sys"
+#define VER_ORIGINALFILENAME_STR "PCI9656.sys"
+
+#include "common.ver"
+
+
+
diff --git a/general/PLX9x5x/sys/Pci9656.rc b/general/PLX9x5x/sys/Pci9656.rc
new file mode 100644
index 00000000..48e9260d
--- /dev/null
+++ b/general/PLX9x5x/sys/Pci9656.rc
@@ -0,0 +1,14 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "WDF Driver for PLx PCI9656RDK-Lite Adapter"
+#define VER_INTERNALNAME_STR "PCI9656.sys"
+#define VER_ORIGINALFILENAME_STR "PCI9656.sys"
+
+#include "common.ver"
+
+
+
diff --git a/general/PLX9x5x/sys/Pci9x5x.vcxproj b/general/PLX9x5x/sys/Pci9x5x.vcxproj
new file mode 100644
index 00000000..7493d098
--- /dev/null
+++ b/general/PLX9x5x/sys/Pci9x5x.vcxproj
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{12A2C4C0-856A-49BE-9F54-30D4D040C3E9}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{0DB7EDF4-ADCA-4623-A75A-2D53E0B95D89}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="Pci9656.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="Init.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="IsrDpc.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="Read.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="Write.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <Inf Include=".\pci9x5x.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\pci9x5x.inf</CopyOutput>
+ </Inf>
+ <OtherWpp Include="Pci9656.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Pci9x5x</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Pci9x5x</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Pci9x5x</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Pci9x5x</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="precompsrc.c">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Create</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ResourceCompile Include="Pci9656.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/general/PLX9x5x/sys/Pci9x5x.vcxproj.Filters b/general/PLX9x5x/sys/Pci9x5x.vcxproj.Filters
new file mode 100644
index 00000000..1cf6e8b2
--- /dev/null
+++ b/general/PLX9x5x/sys/Pci9x5x.vcxproj.Filters
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{CFE8A049-4352-4797-A933-02B2457B9660}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{EA19AC8F-5C37-4641-AAFA-4924984AF0F7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{D407D40B-9D6E-4731-85DE-808B502FF92E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{39E92CE4-17AE-463E-B0CB-746990AE72D1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Init.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="IsrDpc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Pci9656.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="precompsrc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Read.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Write.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\pci9x5x.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\pci9x5x.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="Pci9656.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/general/PLX9x5x/sys/Precomp.h b/general/PLX9x5x/sys/Precomp.h
new file mode 100644
index 00000000..ada4939a
--- /dev/null
+++ b/general/PLX9x5x/sys/Precomp.h
@@ -0,0 +1,17 @@
+#define WIN9X_COMPAT_SPINLOCK
+#include <ntddk.h>
+#pragma warning(disable:4201) // nameless struct/union warning
+
+#include <stdarg.h>
+#include <wdf.h>
+
+#pragma warning(default:4201)
+
+#include <initguid.h> // required for GUID definitions
+#include <wdmguid.h> // required for WMILIB_CONTEXT
+
+#include "Reg9656.h"
+#include "Public.h"
+#include "Private.h"
+#include "trace.h"
+
diff --git a/general/PLX9x5x/sys/Private.h b/general/PLX9x5x/sys/Private.h
new file mode 100644
index 00000000..8eae7a45
--- /dev/null
+++ b/general/PLX9x5x/sys/Private.h
@@ -0,0 +1,211 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Private.h
+
+Abstract:
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+
+#if !defined(_PCI9656_H_)
+#define _PCI9659_H_
+
+//
+// The device extension for the device object
+//
+typedef struct _DEVICE_EXTENSION {
+
+ WDFDEVICE Device;
+
+ // Following fields are specific to the hardware
+ // Configuration
+
+ // HW Resources
+ PPCI9656_REGS Regs; // Registers address
+ PUCHAR RegsBase; // Registers base address
+ ULONG RegsLength; // Registers base length
+
+ PUCHAR PortBase; // Port base address
+ ULONG PortLength; // Port base length
+
+ PUCHAR SRAMBase; // SRAM base address
+ ULONG SRAMLength; // SRAM base length
+
+ PUCHAR SRAM2Base; // SRAM (alt) base address
+ ULONG SRAM2Length; // SRAM (alt) base length
+
+ WDFINTERRUPT Interrupt; // Returned by InterruptCreate
+
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } IntCsr;
+
+ union {
+ DMA_CSR bits;
+ UCHAR uchar;
+ } Dma0Csr;
+
+ union {
+ DMA_CSR bits;
+ UCHAR uchar;
+ } Dma1Csr;
+
+ // DmaEnabler
+ WDFDMAENABLER DmaEnabler;
+ ULONG MaximumTransferLength;
+
+ // Write
+ WDFQUEUE WriteQueue;
+
+ WDFDMATRANSACTION WriteDmaTransaction;
+
+ ULONG WriteTransferElements;
+ WDFCOMMONBUFFER WriteCommonBuffer;
+ size_t WriteCommonBufferSize;
+ _Field_size_(WriteCommonBufferSize) PUCHAR WriteCommonBufferBase;
+ PHYSICAL_ADDRESS WriteCommonBufferBaseLA; // Logical Address
+
+ // Read
+ ULONG ReadTransferElements;
+ WDFCOMMONBUFFER ReadCommonBuffer;
+ size_t ReadCommonBufferSize;
+ _Field_size_(ReadCommonBufferSize) PUCHAR ReadCommonBufferBase;
+ PHYSICAL_ADDRESS ReadCommonBufferBaseLA; // Logical Address
+
+ WDFDMATRANSACTION ReadDmaTransaction;
+
+ WDFQUEUE ReadQueue;
+
+ ULONG HwErrCount;
+
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+//
+// This will generate the function named PLxGetDeviceContext to be use for
+// retreiving the DEVICE_EXTENSION pointer.
+//
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)
+
+#if !defined(ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION)
+//
+// The context structure used with WdfDmaTransactionCreate
+//
+typedef struct TRANSACTION_CONTEXT {
+
+ WDFREQUEST Request;
+
+} TRANSACTION_CONTEXT, * PTRANSACTION_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(TRANSACTION_CONTEXT, PLxGetTransactionContext)
+
+#endif
+
+//
+// Function prototypes
+//
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD PLxEvtDeviceAdd;
+
+EVT_WDF_OBJECT_CONTEXT_CLEANUP PlxEvtDriverContextCleanup;
+
+EVT_WDF_DEVICE_D0_ENTRY PLxEvtDeviceD0Entry;
+EVT_WDF_DEVICE_D0_EXIT PLxEvtDeviceD0Exit;
+EVT_WDF_DEVICE_PREPARE_HARDWARE PLxEvtDevicePrepareHardware;
+EVT_WDF_DEVICE_RELEASE_HARDWARE PLxEvtDeviceReleaseHardware;
+
+EVT_WDF_IO_QUEUE_IO_READ PLxEvtIoRead;
+EVT_WDF_IO_QUEUE_IO_WRITE PLxEvtIoWrite;
+
+EVT_WDF_INTERRUPT_ISR PLxEvtInterruptIsr;
+EVT_WDF_INTERRUPT_DPC PLxEvtInterruptDpc;
+EVT_WDF_INTERRUPT_ENABLE PLxEvtInterruptEnable;
+EVT_WDF_INTERRUPT_DISABLE PLxEvtInterruptDisable;
+
+NTSTATUS
+PLxSetIdleAndWakeSettings(
+ IN PDEVICE_EXTENSION FdoData
+ );
+
+NTSTATUS
+PLxInitializeDeviceExtension(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+NTSTATUS
+PLxPrepareHardware(
+ IN PDEVICE_EXTENSION DevExt,
+ IN WDFCMRESLIST ResourcesTranslated
+ );
+
+NTSTATUS
+PLxInitRead(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+NTSTATUS
+PLxInitWrite(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+//
+// WDFINTERRUPT Support
+//
+NTSTATUS
+PLxInterruptCreate(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+VOID
+PLxReadRequestComplete(
+ IN WDFDMATRANSACTION DmaTransaction,
+ IN NTSTATUS Status
+ );
+
+VOID
+PLxWriteRequestComplete(
+ IN WDFDMATRANSACTION DmaTransaction,
+ IN NTSTATUS Status
+ );
+
+NTSTATUS
+PLxInitializeHardware(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+VOID
+PLxShutdown(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+EVT_WDF_PROGRAM_DMA PLxEvtProgramReadDma;
+EVT_WDF_PROGRAM_DMA PLxEvtProgramWriteDma;
+
+VOID
+PLxHardwareReset(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+NTSTATUS
+PLxInitializeDMA(
+ IN PDEVICE_EXTENSION DevExt
+ );
+
+#pragma warning(disable:4127) // avoid conditional expression is constant error with W4
+
+#endif // _PCI9656_H_
+
diff --git a/general/PLX9x5x/sys/Public.h b/general/PLX9x5x/sys/Public.h
new file mode 100644
index 00000000..16c425ae
--- /dev/null
+++ b/general/PLX9x5x/sys/Public.h
@@ -0,0 +1,35 @@
+/*++
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Public.h
+
+Abstract:
+
+ This module contains the common declarations shared by driver
+ and user applications.
+
+Environment:
+
+ user and kernel
+
+--*/
+
+//
+// The following value is arbitrarily chosen from the space defined
+// by Microsoft as being "for non-Microsoft use"
+//
+// NOTE: we use OSR's GUID_OSR_PLX_INTERFACE GUID value so that we
+// can use OSR's PLxTest program :-)
+//
+// {29D2A384-2E47-49b5-AEBF-6962C22BD7C2}
+DEFINE_GUID (GUID_PLX_INTERFACE,
+ 0x29d2a384, 0x2e47, 0x49b5, 0xae, 0xbf, 0x69, 0x62, 0xc2, 0x2b, 0xd7, 0xc2);
+
+
diff --git a/general/PLX9x5x/sys/Read.c b/general/PLX9x5x/sys/Read.c
new file mode 100644
index 00000000..319cf094
--- /dev/null
+++ b/general/PLX9x5x/sys/Read.c
@@ -0,0 +1,453 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Read.c
+
+Abstract:
+
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "precomp.h"
+
+#include "Read.tmh"
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+VOID
+PLxEvtIoRead(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework as soon as it receives a read request.
+ If the device is not ready, fail the request.
+ Otherwise get scatter-gather list for this request and send the
+ packet to the hardware for DMA.
+
+Arguments:
+
+ Queue - Default queue handle
+ Request - Handle to the write request
+ Lenght - Length of the data buffer associated with the request.
+ The default property of the queue is to not dispatch
+ zero lenght read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+--*/
+{
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ PDEVICE_EXTENSION devExt;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ "--> PLxEvtIoRead: Request %p", Request);
+
+ //
+ // Get the DevExt from the Queue handle
+ //
+ devExt = PLxGetDeviceContext(WdfIoQueueGetDevice(Queue));
+
+ do {
+ //
+ // Validate the Length parameter.
+ //
+ if (Length > PCI9656_SRAM_SIZE) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ break;
+ }
+
+ //
+ // Initialize this new DmaTransaction.
+ //
+ status = WdfDmaTransactionInitializeUsingRequest(
+ devExt->ReadDmaTransaction,
+ Request,
+ PLxEvtProgramReadDma,
+ WdfDmaDirectionReadFromDevice );
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "WdfDmaTransactionInitializeUsingRequest "
+ "failed: %!STATUS!", status);
+ break;
+ }
+
+#if 0 // FYI
+ //
+ // Modify the MaximumLength for this DmaTransaction only.
+ //
+ // Note: The new length must be less than or equal to that set when
+ // the DmaEnabler was created.
+ //
+ {
+ ULONG length = devExt->MaximumTransferLength / 2;
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ // "Setting a new MaxLen %d\n", length);
+
+ WdfDmaTransactionSetMaximumLength( devExt->ReadDmaTransaction,
+ length );
+ }
+#endif
+
+ //
+ // Execute this DmaTransaction.
+ //
+ status = WdfDmaTransactionExecute( devExt->ReadDmaTransaction,
+ WDF_NO_CONTEXT);
+
+ if(!NT_SUCCESS(status)) {
+ //
+ // Couldn't execute this DmaTransaction, so fail Request.
+ //
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "WdfDmaTransactionExecute failed: %!STATUS!", status);
+ break;
+ }
+
+ //
+ // Indicate that Dma transaction has been started successfully.
+ // The request will be complete by the Dpc routine when the DMA
+ // transaction completes.
+ //
+ status = STATUS_SUCCESS;
+
+ } while (0);
+
+ //
+ // If there are errors, then clean up and complete the Request.
+ //
+ if (!NT_SUCCESS(status )) {
+ WdfDmaTransactionRelease(devExt->ReadDmaTransaction);
+ WdfRequestComplete(Request, status);
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ "<-- PLxEvtIoRead: status %!STATUS!", status);
+
+ return;
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+BOOLEAN
+PLxEvtProgramReadDma(
+ IN WDFDMATRANSACTION Transaction,
+ IN WDFDEVICE Device,
+ IN WDFCONTEXT Context,
+ IN WDF_DMA_DIRECTION Direction,
+ IN PSCATTER_GATHER_LIST SgList
+ )
+/*++
+
+Routine Description:
+
+ The framework calls a driver's EvtProgramDma event callback function
+ when the driver calls WdfDmaTransactionExecute and the system has
+ enough map registers to do the transfer. The callback function must
+ program the hardware to start the transfer. A single transaction
+ initiated by calling WdfDmaTransactionExecute may result in multiple
+ calls to this function if the buffer is too large and there aren't
+ enough map registers to do the whole transfer.
+
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+ size_t offset;
+ PDMA_TRANSFER_ELEMENT dteVA;
+ ULONG_PTR dteLA;
+ BOOLEAN errors;
+ ULONG i;
+
+ UNREFERENCED_PARAMETER( Context );
+ UNREFERENCED_PARAMETER( Direction );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ "--> PLxEvtProgramReadDma");
+
+ //
+ // Initialize locals
+ //
+ devExt = PLxGetDeviceContext(Device);
+ errors = FALSE;
+
+ //
+ // Get the number of bytes as the offset to the beginning of this
+ // Dma operations transfer location in the buffer.
+ //
+ offset = WdfDmaTransactionGetBytesTransferred(Transaction);
+
+ //
+ // Setup the pointer to the next DMA_TRANSFER_ELEMENT
+ // for both virtual and physical address references.
+ //
+ dteVA = (PDMA_TRANSFER_ELEMENT) devExt->ReadCommonBufferBase;
+ dteLA = (devExt->ReadCommonBufferBaseLA.LowPart +
+ sizeof(DMA_TRANSFER_ELEMENT));
+
+ //
+ // Translate the System's SCATTER_GATHER_LIST elements
+ // into the device's DMA_TRANSFER_ELEMENT elements.
+ //
+ for (i=0; i < SgList->NumberOfElements; i++) {
+
+ //
+ // Construct this DTE.
+ //
+ // NOTE: The LocalAddress is the offset into the SRAM from
+ // where this Read will start.
+ //
+ dteVA->PciAddressLow = SgList->Elements[i].Address.LowPart;
+ dteVA->PciAddressHigh = SgList->Elements[i].Address.HighPart;
+ dteVA->TransferSize = SgList->Elements[i].Length;
+
+ dteVA->LocalAddress = (ULONG) offset;
+
+ dteVA->DescPtr.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
+ dteVA->DescPtr.TermCountInt = FALSE;
+ dteVA->DescPtr.LastElement = FALSE;
+ dteVA->DescPtr.DirOfTransfer = DESC_PTR_DIRECTION__FROM_DEVICE;
+ dteVA->DescPtr.Address = DESC_PTR_ADDR( dteLA );
+
+ //
+ // Increment the DmaTransaction length by this element length
+ //
+ offset += SgList->Elements[i].Length;
+
+ //
+ // If at end of SgList, then set LastElement bit in final NTE.
+ //
+ if (i == SgList->NumberOfElements - 1) {
+
+ dteVA->DescPtr.LastElement = TRUE;
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ // "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
+ // "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
+ // i,
+ // dteVA->PciAddressHigh,
+ // dteVA->PciAddressLow,
+ // dteVA->TransferSize,
+ // dteVA->LocalAddress,
+ // dteVA->DescPtr.DescLocation,
+ // dteVA->DescPtr.LastElement,
+ // dteVA->DescPtr.TermCountInt,
+ // dteVA->DescPtr.DirOfTransfer );
+ break;
+ }
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ // "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
+ // "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
+ // i,
+ // dteVA->PciAddressHigh,
+ // dteVA->PciAddressLow,
+ // dteVA->TransferSize,
+ // dteVA->LocalAddress,
+ // dteVA->DescPtr.DescLocation,
+ // dteVA->DescPtr.LastElement,
+ // dteVA->DescPtr.TermCountInt,
+ // dteVA->DescPtr.DirOfTransfer );
+
+ //
+ // Adjust the next DMA_TRANSFER_ELEMEMT
+ //
+ dteVA++;
+ dteLA += sizeof(DMA_TRANSFER_ELEMENT);
+ }
+
+ //
+ // Start the DMA operation.
+ // Acquire this device's InterruptSpinLock.
+ //
+ WdfInterruptAcquireLock( devExt->Interrupt );
+
+ //
+ // DMA 1 Mode Register - (DMAMODE1)
+ // Enable Scatter/Gather Mode, Interrupt On Done,
+ // and route Ints to PCI.
+ //
+ {
+ union {
+ DMA_MODE bits;
+ ULONG ulong;
+ } dmaMode;
+
+ dmaMode.ulong =
+ READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma1_Mode );
+
+ dmaMode.bits.SgModeEnable = TRUE;
+ dmaMode.bits.DoneIntEnable = TRUE;
+ dmaMode.bits.IntToPci = TRUE;
+
+ dmaMode.bits.ClearCountMode = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma1_Mode,
+ dmaMode.ulong );
+ }
+
+ //
+ // Interrupt CSR Register - (INTCSR)
+ // Enable PCI Ints and DMA Channel 1 Ints.
+ //
+ {
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } intCSR;
+
+ intCSR.ulong =
+ READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
+
+ intCSR.bits.PciIntEnable = TRUE;
+ intCSR.bits.DmaChan1IntEnable = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
+ intCSR.ulong );
+ }
+
+ //
+ // DMA 1 Descriptor Pointer Register - (DMADPR1)
+ // Write the base LOGICAL address of the DMA_TRANSFER_ELEMENT list.
+ //
+ {
+ union {
+ DESC_PTR bits;
+ ULONG ulong;
+ } ptr;
+
+ ptr.bits.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
+ ptr.bits.TermCountInt = TRUE;
+ ptr.bits.Address =
+ DESC_PTR_ADDR( devExt->ReadCommonBufferBaseLA.LowPart );
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma1_Desc_Ptr,
+ ptr.ulong );
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ " PLxEvtProgramReadDma: Start a Read DMA operation");
+
+ //
+ // DMA 1 CSR Register - (DMACSR1)
+ // Start the DMA operation: Set Enable and Start bits.
+ //
+ {
+ union {
+ DMA_CSR bits;
+ UCHAR uchar;
+ } dmaCSR;
+
+ dmaCSR.uchar =
+ READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr );
+
+ dmaCSR.bits.Enable = TRUE;
+ dmaCSR.bits.Start = TRUE;
+
+ WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr,
+ dmaCSR.uchar );
+ }
+
+ //
+ // Release our interrupt spinlock
+ //
+ WdfInterruptReleaseLock( devExt->Interrupt );
+
+ //
+ // NOTE: This shows how to process errors which occur in the
+ // PFN_WDF_PROGRAM_DMA function in general.
+ // Basically the DmaTransaction must be deleted and
+ // the Request must be completed.
+ //
+ if (errors) {
+ NTSTATUS status;
+
+ //
+ // Must abort the transaction before deleting.
+ //
+ (VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
+ ASSERT(NT_SUCCESS(status));
+
+ PLxReadRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "<-- PLxEvtProgramReadDma: errors ****");
+ return FALSE;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ "<-- PLxEvtProgramReadDma");
+
+ return TRUE;
+}
+
+VOID
+PLxReadRequestComplete(
+ IN WDFDMATRANSACTION DmaTransaction,
+ IN NTSTATUS Status
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ WDFREQUEST request;
+ size_t bytesTransferred;
+
+ //
+ // Get the associated request from the transaction.
+ //
+ request = WdfDmaTransactionGetRequest(DmaTransaction);
+
+ ASSERT(request);
+
+ //
+ // Get the final bytes transferred count.
+ //
+ bytesTransferred = WdfDmaTransactionGetBytesTransferred( DmaTransaction );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
+ "PLxReadRequestComplete: Request %p, Status %!STATUS!, "
+ "bytes transferred %d\n",
+ request, Status, (int) bytesTransferred );
+
+ WdfDmaTransactionRelease(DmaTransaction);
+
+ //
+ // Complete this Request.
+ //
+ WdfRequestCompleteWithInformation( request, Status, bytesTransferred);
+
+}
+
diff --git a/general/PLX9x5x/sys/Reg9656.h b/general/PLX9x5x/sys/Reg9656.h
new file mode 100644
index 00000000..9165403b
--- /dev/null
+++ b/general/PLX9x5x/sys/Reg9656.h
@@ -0,0 +1,259 @@
+#ifndef __REG9656_H_
+#define __REG9656_H_
+
+//*****************************************************************************
+//
+// File Name: Reg9656.h
+//
+// Description: This file defines all the PLX 9656 chip Registers.
+//
+// NOTE: These definitions are for memory-mapped register access only.
+//
+//*****************************************************************************
+
+//-----------------------------------------------------------------------------
+// PCI Device/Vendor Ids.
+//-----------------------------------------------------------------------------
+#define PLX_PCI_VENDOR_ID 0x10B5
+#define PLX_PCI_DEVICE_ID 0x9601
+
+//-----------------------------------------------------------------------------
+// Expected size of the PCI9656RDK-Lite on-board SRAM
+//-----------------------------------------------------------------------------
+#define PCI9656_SRAM_SIZE (0x20000)
+
+//-----------------------------------------------------------------------------
+// Maximum DMA transfer size (in bytes).
+//
+// NOTE: This value is rather abritrary for this drive,
+// but must be between [0 - PCI9656_SRAM_SIZE] in value.
+// You can play with the value to see how requests are sequenced as a
+// set of one or more DMA operations.
+//-----------------------------------------------------------------------------
+#define PCI9656_MAXIMUM_TRANSFER_LENGTH (8*1024)
+
+//-----------------------------------------------------------------------------
+// The DMA_TRANSFER_ELEMENTS (the 9656's hardware scatter/gather list element)
+// must be aligned on a 16-byte boundry. This is because the lower 4 bits of
+// the DESC_PTR.Address contain bit fields not included in the "next" address.
+//-----------------------------------------------------------------------------
+#define PCI9656_DTE_ALIGNMENT_16 FILE_OCTA_ALIGNMENT
+
+//-----------------------------------------------------------------------------
+// Number of DMA channels supported by PLX Chip
+//-----------------------------------------------------------------------------
+#define PCI9656_DMA_CHANNELS (2)
+
+//-----------------------------------------------------------------------------
+// DMA Transfer Element (DTE)
+//
+// NOTE: This structure is modeled after the DMAPADRx, DMALADRx, DMASIZx and
+// DMAADPRx registers. See DataBook Registers description: 11-74 to 11-77.
+//-----------------------------------------------------------------------------
+typedef struct _DESC_PTR_ {
+
+ unsigned int DescLocation : 1 ; // TRUE - Desc in PCI (host) memory
+ unsigned int LastElement : 1 ; // TRUE - last NTE in chain
+ unsigned int TermCountInt : 1 ; // TRUE - Interrupt on term count.
+ unsigned int DirOfTransfer : 1 ; // see defines below
+ unsigned int Address : 28 ;
+
+} DESC_PTR;
+
+#define DESC_PTR_DESC_LOCATION__LOCAL (0)
+#define DESC_PTR_DESC_LOCATION__PCI (1)
+
+#define DESC_PTR_DIRECTION__TO_DEVICE (0)
+#define DESC_PTR_DIRECTION__FROM_DEVICE (1)
+
+typedef struct _DMA_TRANSFER_ELEMENT {
+
+ unsigned int PciAddressLow ;
+ unsigned int LocalAddress ;
+ unsigned int TransferSize ;
+ DESC_PTR DescPtr ;
+ unsigned int PciAddressHigh ;
+ unsigned int pad [3] ;
+
+} DMA_TRANSFER_ELEMENT, * PDMA_TRANSFER_ELEMENT;
+
+#define DESC_PTR_ADDR_SHIFT (4)
+#define DESC_PTR_ADDR(a) (((ULONG) a) >> DESC_PTR_ADDR_SHIFT)
+
+
+//-----------------------------------------------------------------------------
+// Define the Interrupt Command Status Register (CSR)
+//-----------------------------------------------------------------------------
+typedef struct _INT_CSR_ {
+ unsigned int EnableIntSources : 2; // bit 0-1
+ unsigned int GenPciBusSerrInt : 1; // bit 2
+ unsigned int MailboxIntEnable : 1; // bit 3
+ unsigned int PowerMgmtIntEnable : 1; // bit 4
+ unsigned int PowerMgmtInt : 1; // bit 5
+ unsigned int DM_WriteParityCheck : 1; // bit 6
+ unsigned int DM_WriteParityCheckErr : 1; // bit 7
+ unsigned int PciIntEnable : 1; // bit 8
+ unsigned int PciDoorbellIntEnable : 1; // bit 9
+ unsigned int PciAbortIntEnable : 1; // bit 10
+ unsigned int LocalIntInputEnable : 1; // bit 11
+ unsigned int RetryAbortEnable : 1; // bit 12
+ unsigned int PciDoorbellIntActive : 1; // bit 13
+ unsigned int PciAbortIntActive : 1; // bit 14
+ unsigned int LocalIntInputActive : 1; // bit 15
+ unsigned int LocalIntOutputEnable : 1; // bit 16
+ unsigned int LocalDoorbellIntEnable : 1; // bit 17
+ unsigned int DmaChan0IntEnable : 1; // bit 18
+ unsigned int DmaChan1IntEnable : 1; // bit 19
+ unsigned int LocalDoorbellIntActive : 1; // bit 20
+ unsigned int DmaChan0IntActive : 1; // bit 21
+ unsigned int DmaChan1IntActive : 1; // bit 22
+ unsigned int BistIntActive : 1; // bit 23
+ unsigned int DM_WasBusMastOnAbort : 1; // bit 24
+ unsigned int Dma0_WasBusMastOnAbort : 1; // bit 25
+ unsigned int Dma1_WasBusMastOnAbort : 1; // bit 26
+ unsigned int AbortAfter256Retries : 1; // bit 27
+ unsigned int DataInMailbox0 : 1; // bit 28
+ unsigned int DataInMailbox1 : 1; // bit 29
+ unsigned int DataInMailbox2 : 1; // bit 30
+ unsigned int DataInMailbox3 : 1; // bit 31
+} INT_CSR;
+
+
+//-----------------------------------------------------------------------------
+// Define the EEPROM CSR (CNTRL)
+//-----------------------------------------------------------------------------
+typedef struct _EEPROM_CSR_ {
+ unsigned int PciReadCmdForDma : 4; // bit 0-3
+ unsigned int PciWriteCmdForDma : 4; // bit 4-7
+ unsigned int PciMemReadCmdForDM : 4; // bit 8-11
+ unsigned int PciMemWriteCmdForDM : 4; // bit 12-15
+ unsigned int GPIO_Output : 1; // bit 16
+ unsigned int GPIO_Input : 1; // bit 17
+ unsigned int User_i_Select : 1; // bit 18
+ unsigned int User_o_Select : 1; // bit 19
+ unsigned int LINT_o_IntStatus : 1; // bit 20
+ unsigned int TeaIntStatus : 1; // bit 21
+ unsigned int reserved : 2; // bit 22-23
+ unsigned int SerialEEPROMClockOut : 1; // bit 24
+ unsigned int SerialEEPROMChipSelect : 1; // bit 25
+ unsigned int SerialEEPROMDataIn : 1; // bit 26
+ unsigned int SerialEEPROMDataOut : 1; // bit 27
+ unsigned int SerialEEPROMPresent : 1; // bit 28
+ unsigned int ReloadConfigRegisters : 1; // bit 29
+ unsigned int SoftwareReset : 1; // bit 30
+ unsigned int EEDOInputEnable : 1; // bit 31
+} EEPROM_CSR;
+
+//-----------------------------------------------------------------------------
+// Define the DMA Mode Register
+//-----------------------------------------------------------------------------
+typedef struct _DMA_MODE_ {
+ unsigned int LocalBusDataWidth : 2 ; // bit 0-1
+ unsigned int WaitStateCounter : 4 ; // bit 2-5
+ unsigned int TaRdyInputEnable : 1 ; // bit 6
+ unsigned int BurstEnable : 1 ; // bit 7
+ unsigned int LocalBurstEnable : 1 ; // bit 8
+ unsigned int SgModeEnable : 1 ; // bit 9
+ unsigned int DoneIntEnable : 1 ; // bit 10
+ unsigned int LocalAddressMode : 1 ; // bit 11
+ unsigned int DemandMode : 1 ; // bit 12
+ unsigned int MWIEnable : 1 ; // bit 13
+ unsigned int EOTEnable : 1 ; // bit 14
+ unsigned int TermModeSelect : 1 ; // bit 15
+ unsigned int ClearCountMode : 1 ; // bit 16
+ unsigned int IntToPci : 1 ; // bit 17
+ unsigned int DACChainLoad : 1 ; // bit 18
+ unsigned int EOTEndLink : 1 ; // bit 19
+ unsigned int RingMgmtValidMode : 1 ; // bit 20
+ unsigned int RingMgmtValidStop : 1 ; // bit 21
+ unsigned int reserved : 10; // bit 22-31
+} DMA_MODE;
+
+//-----------------------------------------------------------------------------
+// Define the DMA Command Status Register (CSR)
+//-----------------------------------------------------------------------------
+#pragma warning(disable:4214) // bit field types other than int warning
+
+typedef struct _DMA_CSR_ {
+ unsigned char Enable : 1; // bit 0
+ unsigned char Start : 1; // bit 1
+ unsigned char Abort : 1; // bit 2
+ unsigned char Clear : 1; // bit 3
+ unsigned char Done : 1; // bit 4
+ unsigned char pad : 1; // bit 5-7
+} DMA_CSR;
+
+#pragma warning(default:4214)
+
+//-----------------------------------------------------------------------------
+// PCI9659_REGS structure
+//-----------------------------------------------------------------------------
+typedef struct _PCI9656_REGS_ {
+
+ unsigned int Space0_Range ; // 0x000
+ unsigned int Space0_Remap ; // 0x004
+ unsigned int Local_DMA_Arbit ; // 0x008
+ unsigned int Endian_Desc ; // 0x00C
+ unsigned int Exp_XP_ROM_Range ; // 0x010
+ unsigned int Exp_ROM_Remap ; // 0x014
+ unsigned int Space0_ROM_Desc ; // 0x018
+ unsigned int DM_Range ; // 0x01C
+ unsigned int DM_Mem_Base ; // 0x020
+ unsigned int DM_IO_Base ; // 0x024
+ unsigned int DM_PCI_Mem_Remap ; // 0x028
+
+ unsigned int pad1 [7] ; // range [0x02C - 0x044]
+
+ unsigned int Mailbox2 ; // 0x048
+ unsigned int Mailbox3 ; // 0x04C
+ unsigned int Mailbox4 ; // 0x050
+ unsigned int Mailbox5 ; // 0x054
+ unsigned int Mailbox6 ; // 0x058
+ unsigned int Mailbox7 ; // 0x05C
+
+ unsigned int Local_Doorbell ; // 0x060
+ unsigned int PCI_Doorbell ; // 0x064
+ INT_CSR Int_Csr ; // 0x068
+ EEPROM_CSR EEPROM_Ctrl_Stat ; // 0x06C
+ unsigned int Perm_Vendor_Id ; // 0x070
+ unsigned int Revision_Id ; // 0x074
+
+ unsigned int pad2 [2] ; // range [0x078 - 0x07C]
+
+ DMA_MODE Dma0_Mode ; // 0x080
+ unsigned int Dma0_PCI_Addr ; // 0x084
+ unsigned int Dma0_Local_Addr ; // 0x088
+ unsigned int Dma0_Count ; // 0x08C
+ DESC_PTR Dma0_Desc_Ptr ; // 0x090
+
+ DMA_MODE Dma1_Mode ; // 0x094
+ unsigned int Dma1_PCI_Addr ; // 0x098
+ unsigned int Dma1_Local_Addr ; // 0x09C
+ unsigned int Dma1_Count ; // 0x0A0
+ DESC_PTR Dma1_Desc_Ptr ; // 0x0A4
+
+ DMA_CSR Dma0_Csr ; // 0x0A8
+ DMA_CSR Dma1_Csr ; // 0x0A9
+
+ unsigned char pad3 [2] ; // pad to next 32-bit boundry
+
+ unsigned int Dma_Arbit ; // 0x0AC
+ unsigned int Dma_Threshold ; // 0x0B0
+
+ unsigned int Dma0_PCI_DAC ; // 0x0B4
+ unsigned int Dma1_PCI_DAC ; // 0x0B8
+
+ unsigned int pad4 [13] ; // range [0x0BC - 0x0EC]
+
+ unsigned int Space1_Range ; // 0x0F0
+ unsigned int Space1_Remap ; // 0x0F4
+ unsigned int Space1_Desc ; // 0x0F8
+ unsigned int DM_DAC ; // 0x0FC
+
+ unsigned int Arbiter_Cntl ; // 0x100
+ unsigned int Abort_Address ; // 0x104
+
+} PCI9656_REGS, * PPCI9656_REGS;
+
+
+#endif // __REG9656_H_
diff --git a/general/PLX9x5x/sys/Write.c b/general/PLX9x5x/sys/Write.c
new file mode 100644
index 00000000..3e4d8b53
--- /dev/null
+++ b/general/PLX9x5x/sys/Write.c
@@ -0,0 +1,525 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Write.c
+
+Abstract:
+
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "precomp.h"
+
+#include "Write.tmh"
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+VOID
+PLxEvtIoWrite(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework as soon as it receives a write request.
+ If the device is not ready, fail the request.
+ Otherwise get scatter-gather list for this request and send the
+ packet to the hardware for DMA.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated
+ with the I/O request.
+ Request - Handle to a framework request object.
+
+ Length - Length of the IO operation
+ The default property of the queue is to not dispatch
+ zero lenght read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+--*/
+{
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ PDEVICE_EXTENSION devExt = NULL;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "--> PLxEvtIoWrite: Request %p", Request);
+
+ //
+ // Get the DevExt from the Queue handle
+ //
+ devExt = PLxGetDeviceContext(WdfIoQueueGetDevice(Queue));
+
+ //
+ // Validate the Length parameter.
+ //
+ if (Length > PCI9656_SRAM_SIZE) {
+ status = STATUS_INVALID_BUFFER_SIZE;
+ goto CleanUp;
+ }
+
+ //
+ // Following code illustrates two different ways of initializing a DMA
+ // transaction object. If ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION is
+ // defined in the sources file, the first section will be used.
+ //
+#ifdef ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION
+
+ //
+ // This section illustrates how to create and initialize
+ // a DmaTransaction using a WDF Request.
+ // This type of coding pattern would probably be the most commonly used
+ // for handling client Requests.
+ //
+ status = WdfDmaTransactionInitializeUsingRequest(
+ devExt->WriteDmaTransaction,
+ Request,
+ PLxEvtProgramWriteDma,
+ WdfDmaDirectionWriteToDevice );
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfDmaTransactionInitializeUsingRequest failed: "
+ "%!STATUS!", status);
+ goto CleanUp;
+ }
+#else
+ //
+ // This section illustrates how to create and initialize
+ // a DmaTransaction via direct parameters (e.g. not using a WDF Request).
+ // This type of coding pattern might be used for driver-initiated DMA
+ // operations (e.g. DMA operations not based on driver client requests.)
+ //
+ // NOTE: This example unpacks the WDF Request in order to get a set of
+ // parameters for the call to WdfDmaTransactionInitialize. While
+ // this is completely legimate, the represenative usage pattern
+ // for WdfDmaTransactionIniitalize would have the driver create/
+ // initialized a DmaTransactin without a WDF Request. A simple
+ // example might be where the driver needs to DMA the devices's
+ // firmware to it during device initialization. There would be
+ // no WDF Request; the driver would supply the parameters for
+ // WdfDmaTransactionInitialize directly.
+ //
+ {
+ PTRANSACTION_CONTEXT transContext;
+ PMDL mdl;
+ PVOID virtualAddress;
+ ULONG length;
+
+ //
+ // Initialize this new DmaTransaction with direct parameters.
+ //
+ status = WdfRequestRetrieveInputWdmMdl(Request, &mdl);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfRequestRetrieveInputWdmMdl failed: %!STATUS!", status);
+ goto CleanUp;
+ }
+
+ virtualAddress = MmGetMdlVirtualAddress(mdl);
+ length = MmGetMdlByteCount(mdl);
+
+ _Analysis_assume_(length > 0);
+ status = WdfDmaTransactionInitialize( devExt->WriteDmaTransaction,
+ PLxEvtProgramWriteDma,
+ WdfDmaDirectionWriteToDevice,
+ mdl,
+ virtualAddress,
+ length );
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfDmaTransactionInitialize failed: %!STATUS!", status);
+ goto CleanUp;
+ }
+
+ //
+ // Retreive this DmaTransaction's context ptr (aka TRANSACTION_CONTEXT)
+ // and fill it in with info.
+ //
+ transContext = PLxGetTransactionContext( devExt->WriteDmaTransaction );
+ transContext->Request = Request;
+ }
+#endif
+
+#if 0 //FYI
+ //
+ // Modify the MaximumLength for this DmaTransaction only.
+ //
+ // Note: The new length must be less than or equal to that set when
+ // the DmaEnabler was created.
+ //
+ {
+ ULONG length = devExt->MaximumTransferLength / 2;
+
+ //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ // "Setting a new MaxLen %d", length);
+
+ WdfDmaTransactionSetMaximumLength( devExt->WriteDmaTransaction, length );
+ }
+#endif
+
+ //
+ // Execute this DmaTransaction transaction.
+ //
+ status = WdfDmaTransactionExecute( devExt->WriteDmaTransaction,
+ WDF_NO_CONTEXT);
+
+ if(!NT_SUCCESS(status)) {
+
+ //
+ // Couldn't execute this DmaTransaction, so fail Request.
+ //
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfDmaTransactionExecute failed: %!STATUS!", status);
+ goto CleanUp;
+ }
+
+ //
+ // Indicate that Dma transaction has been started successfully. The request
+ // will be complete by the Dpc routine when the DMA transaction completes.
+ //
+ status = STATUS_SUCCESS;
+
+CleanUp:
+
+ //
+ // If there are errors, then clean up and complete the Request.
+ //
+ if (!NT_SUCCESS(status)) {
+ WdfDmaTransactionRelease(devExt->WriteDmaTransaction);
+ WdfRequestComplete(Request, status);
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "<-- PLxEvtIoWrite: %!STATUS!", status);
+
+ return;
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+BOOLEAN
+PLxEvtProgramWriteDma(
+ IN WDFDMATRANSACTION Transaction,
+ IN WDFDEVICE Device,
+ IN PVOID Context,
+ IN WDF_DMA_DIRECTION Direction,
+ IN PSCATTER_GATHER_LIST SgList
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PDEVICE_EXTENSION devExt;
+ size_t offset;
+ PDMA_TRANSFER_ELEMENT dteVA;
+ ULONG_PTR dteLA;
+ BOOLEAN errors;
+ ULONG i;
+
+ UNREFERENCED_PARAMETER( Context );
+ UNREFERENCED_PARAMETER( Direction );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "--> PLxEvtProgramWriteDma");
+
+ //
+ // Initialize locals
+ //
+ devExt = PLxGetDeviceContext(Device);
+ errors = FALSE;
+
+ //
+ // Get the number of bytes as the offset to the beginning of this
+ // Dma operations transfer location in the buffer.
+ //
+ offset = WdfDmaTransactionGetBytesTransferred(Transaction);
+
+ //
+ // Setup the pointer to the next DMA_TRANSFER_ELEMENT
+ // for both virtual and physical address references.
+ //
+ dteVA = (PDMA_TRANSFER_ELEMENT) devExt->WriteCommonBufferBase;
+ dteLA = (devExt->WriteCommonBufferBaseLA.LowPart +
+ sizeof(DMA_TRANSFER_ELEMENT));
+
+ //
+ // Translate the System's SCATTER_GATHER_LIST elements
+ // into the device's DMA_TRANSFER_ELEMENT elements.
+ //
+ for (i=0; i < SgList->NumberOfElements; i++) {
+
+ //
+ // Construct this DTE.
+ //
+ // NOTE: The LocalAddress is the offset into the SRAM from
+ // where this Write will start.
+ //
+ dteVA->PciAddressLow = SgList->Elements[i].Address.LowPart;
+ dteVA->PciAddressHigh = SgList->Elements[i].Address.HighPart;
+ dteVA->TransferSize = SgList->Elements[i].Length;
+
+ dteVA->LocalAddress = (ULONG) offset;
+
+ dteVA->DescPtr.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
+ dteVA->DescPtr.TermCountInt = FALSE;
+ dteVA->DescPtr.LastElement = FALSE;
+ dteVA->DescPtr.DirOfTransfer = DESC_PTR_DIRECTION__TO_DEVICE;
+ dteVA->DescPtr.Address = DESC_PTR_ADDR( dteLA );
+
+ //
+ // Increment the DmaTransaction length by this element length
+ //
+ offset += SgList->Elements[i].Length;
+
+ //
+ // If at end of SgList, then set LastElement bit in final NTE.
+ //
+ if (i == SgList->NumberOfElements - 1) {
+
+ dteVA->DescPtr.LastElement = TRUE;
+
+#if 0 // set to 1 for recording the details
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
+ "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
+ i,
+ dteVA->PciAddressHigh,
+ dteVA->PciAddressLow,
+ dteVA->TransferSize,
+ dteVA->LocalAddress,
+ dteVA->DescPtr.DescLocation,
+ dteVA->DescPtr.LastElement,
+ dteVA->DescPtr.TermCountInt,
+ dteVA->DescPtr.DirOfTransfer );
+#endif
+ break;
+ }
+
+#if 0 // set to 1 for recording the details
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
+ "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
+ i,
+ dteVA->PciAddressHigh,
+ dteVA->PciAddressLow,
+ dteVA->TransferSize,
+ dteVA->LocalAddress,
+ dteVA->DescPtr.DescLocation,
+ dteVA->DescPtr.LastElement,
+ dteVA->DescPtr.TermCountInt,
+ dteVA->DescPtr.DirOfTransfer );
+#endif
+
+ //
+ // Adjust the next DMA_TRANSFER_ELEMEMT
+ //
+ dteVA++;
+ dteLA += sizeof(DMA_TRANSFER_ELEMENT);
+ }
+
+ //
+ // Start the DMA operation.
+ // Acquire this device's InterruptSpinLock.
+ //
+ WdfInterruptAcquireLock( devExt->Interrupt );
+
+ //
+ // DMA 0 Mode Register - (DMAMODE0)
+ // Enable Scatter/Gather Mode, Interrupt On Done,
+ // and route Ints to PCI.
+ //
+ {
+ union {
+ DMA_MODE bits;
+ ULONG ulong;
+ } dmaMode;
+
+ dmaMode.ulong =
+ READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode );
+
+ dmaMode.bits.SgModeEnable = TRUE;
+ dmaMode.bits.DoneIntEnable = TRUE;
+ dmaMode.bits.IntToPci = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode,
+ dmaMode.ulong );
+ }
+
+ //
+ // Interrupt CSR Register - (INTCSR)
+ // Enable PCI Ints and DMA Channel 0 Ints.
+ //
+ {
+ union {
+ INT_CSR bits;
+ ULONG ulong;
+ } intCSR;
+
+ intCSR.ulong =
+ READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
+
+ intCSR.bits.PciIntEnable = TRUE;
+ intCSR.bits.DmaChan0IntEnable = TRUE;
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
+ intCSR.ulong );
+ }
+
+ //
+ // DMA 0 Descriptor Pointer Register - (DMADPR0)
+ // Write the base LOGICAL address of the DMA_TRANSFER_ELEMENT list.
+ //
+ {
+ union {
+ DESC_PTR bits;
+ ULONG ulong;
+ } ptr;
+
+ ptr.bits.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
+ ptr.bits.TermCountInt = TRUE;
+ ptr.bits.Address =
+ DESC_PTR_ADDR( devExt->WriteCommonBufferBaseLA.LowPart );
+
+ WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Desc_Ptr,
+ ptr.ulong );
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ " PLxEvtProgramWriteDma: Start a Write DMA operation");
+
+ //
+ // DMA 0 CSR Register - (DMACSR0)
+ // Start the DMA operation: Set Enable and Start bits.
+ //
+ {
+ union {
+ DMA_CSR bits;
+ UCHAR uchar;
+ } dmaCSR;
+
+ dmaCSR.uchar =
+ READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr );
+
+ dmaCSR.bits.Enable = TRUE;
+ dmaCSR.bits.Start = TRUE;
+
+ WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr,
+ dmaCSR.uchar );
+ }
+
+ //
+ // Release our interrupt spinlock
+ //
+ WdfInterruptReleaseLock( devExt->Interrupt );
+
+ //
+ // NOTE: This shows how to process errors which occur in the
+ // PFN_WDF_PROGRAM_DMA function in general.
+ // Basically the DmaTransaction must be deleted and
+ // the Request must be completed.
+ //
+ if (errors) {
+ //
+ // Must abort the transaction before deleting it.
+ //
+ NTSTATUS status;
+
+ (VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
+ ASSERT(NT_SUCCESS(status));
+ PLxWriteRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "<-- PLxEvtProgramWriteDma: error ****");
+ return FALSE;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "<-- PLxEvtProgramWriteDma");
+
+ return TRUE;
+}
+
+
+VOID
+PLxWriteRequestComplete(
+ IN WDFDMATRANSACTION DmaTransaction,
+ IN NTSTATUS Status
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ WDFREQUEST request;
+ size_t bytesTransferred;
+
+ //
+ // Initialize locals
+ //
+
+#ifdef ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION
+
+ request = WdfDmaTransactionGetRequest(DmaTransaction);
+
+#else
+ //
+ // If CreateDirect was used then there will be no assoc. Request.
+ //
+ {
+ PTRANSACTION_CONTEXT transContext = PLxGetTransactionContext(DmaTransaction);
+
+ request = transContext->Request;
+ transContext->Request = NULL;
+
+ }
+#endif
+
+ //
+ // Get the final bytes transferred count.
+ //
+ bytesTransferred = WdfDmaTransactionGetBytesTransferred( DmaTransaction );
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
+ "PLxWriteRequestComplete: Request %p, Status %!STATUS!, "
+ "bytes transferred %d\n",
+ request, Status, (int) bytesTransferred );
+
+ WdfDmaTransactionRelease(DmaTransaction);
+
+ WdfRequestCompleteWithInformation( request, Status, bytesTransferred);
+
+}
+
diff --git a/general/PLX9x5x/sys/pci9x5x.inx b/general/PLX9x5x/sys/pci9x5x.inx
new file mode 100644
index 00000000..3904344b
--- /dev/null
+++ b/general/PLX9x5x/sys/pci9x5x.inx
@@ -0,0 +1,97 @@
+;/*++
+;
+;Copyright (c) Microsoft Corporation. All rights reserved.
+;
+; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+; PURPOSE.
+;
+;Module Name:
+;
+; Pci9x5x.INF
+;
+;Abstract:
+; INF file for the PLx PCI9x5xRDK-Lite driver.
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFT%
+DriverVer=03/20/2003,5.00.3788
+CatalogFile=KmdfSamples.cat
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+; ================= Class section =====================
+
+[ClassInstall32]
+Addreg=SampleClassReg
+
+[SampleClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+HKR,,DeviceCharacteristics,0x10001,0x100 ;Use same security checks on relative opens
+HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)" ;Allow generic all access to system and built-in Admin.
+
+
+; ================= Device Install section =====================
+
+[ControlFlags]
+ExcludeFromSelect=*
+
+[Manufacturer]
+%MSFT%=MSFT,NT$ARCH$
+
+[SourceDisksFiles]
+Pci9x5x.sys=1
+
+[SourceDisksNames]
+1=%DISK_NAME%,
+
+; For Win2K
+[MSFT]
+; DisplayName Section DeviceId
+; ----------- ------- --------
+%Pci9056.DRVDESC%= Pci9x5x_Inst, PCI\VEN_10b5&DEV_5601
+%Pci9656.DRVDESC%= Pci9x5x_Inst, PCI\VEN_10b5&DEV_9601
+
+; For XP and later
+[MSFT.NT$ARCH$]
+; DisplayName Section DeviceId
+; ----------- ------- --------
+%Pci9056.DRVDESC%= Pci9x5x_Inst, PCI\VEN_10b5&DEV_5601
+%Pci9656.DRVDESC%= Pci9x5x_Inst, PCI\VEN_10b5&DEV_9601
+
+[Pci9x5x_Inst.NT]
+CopyFiles=Pci9x5x.CopyFiles
+
+[Pci9x5x.CopyFiles]
+Pci9x5x.sys
+
+[Pci9x5x_Inst.NT.Services]
+AddService=Pci9x5x,0x00000002,Pci9x5x_Service
+
+[Pci9x5x_Service]
+DisplayName = %Pci9x5x.SVCDESC%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %12%\Pci9x5x.sys
+
+[Pci9x5x_Inst.NT.Wdf]
+KmdfService = Pci9x5x, Pci9x5x_wdfsect
+[Pci9x5x_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+[Strings]
+MSFT = "Microsoft"
+ClassName = "Sample Device"
+Pci9x5x.SVCDESC = "Sample Driver Service for the PCI9x5xRDK-Lite adapter"
+Pci9056.DRVDESC = "Sample Driver for the PCI9056RDK-Lite adapter"
+Pci9656.DRVDESC = "Sample Driver for the PCI9656RDK-Lite adapter"
+DISK_NAME = "Pci9x5x Sample Install Disk"
diff --git a/general/PLX9x5x/sys/precompsrc.c b/general/PLX9x5x/sys/precompsrc.c
new file mode 100644
index 00000000..5944cf51
--- /dev/null
+++ b/general/PLX9x5x/sys/precompsrc.c
@@ -0,0 +1 @@
+#include "precomp.h" \ No newline at end of file
diff --git a/general/PLX9x5x/sys/trace.h b/general/PLX9x5x/sys/trace.h
new file mode 100644
index 00000000..a9726b3a
--- /dev/null
+++ b/general/PLX9x5x/sys/trace.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ TRACE.h
+
+Abstract:
+
+ Header file for the debug tracing related function defintions and macros.
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include <evntrace.h> // For TRACE_LEVEL definitions
+
+//
+// If software tracing is defined in the sources file..
+// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver.
+// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID ***
+// WPP_DEFINE_BIT allows setting debug bit masks to selectively print.
+// The names defined in the WPP_DEFINE_BIT call define the actual names
+// that are used to control the level of tracing for the control guid
+// specified.
+//
+// Name of the logger is PLX9x5x and the guid is
+// {CA630800-D4D4-4457-8983-DFBBFCAC5542}
+// (0xca630800, 0xd4d4, 0x4457, 0x89, 0x83, 0xdf, 0xbb, 0xfc, 0xac, 0x55, 0x42);
+//
+
+#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID(PLX9x5xTraceGuid, (ca630800, D4D4, 4457,8983, DFBBFCAC5542),\
+ WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \
+ WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \
+ WPP_DEFINE_BIT(DBG_POWER) /* bit 2 = 0x00000004 */ \
+ WPP_DEFINE_BIT(DBG_WMI) /* bit 3 = 0x00000008 */ \
+ WPP_DEFINE_BIT(DBG_CREATE_CLOSE) /* bit 4 = 0x00000010 */ \
+ WPP_DEFINE_BIT(DBG_IOCTLS) /* bit 5 = 0x00000020 */ \
+ WPP_DEFINE_BIT(DBG_WRITE) /* bit 6 = 0x00000040 */ \
+ WPP_DEFINE_BIT(DBG_READ) /* bit 7 = 0x00000080 */ \
+ WPP_DEFINE_BIT(DBG_DPC) /* bit 8 = 0x00000100 */ \
+ WPP_DEFINE_BIT(DBG_INTERRUPT) /* bit 9 = 0x00000200 */ \
+ WPP_DEFINE_BIT(DBG_LOCKS) /* bit 10 = 0x00000400 */ \
+ WPP_DEFINE_BIT(DBG_QUEUEING) /* bit 11 = 0x00000800 */ \
+ WPP_DEFINE_BIT(DBG_HW_ACCESS) /* bit 12 = 0x00001000 */ \
+ /* You can have up to 32 defines. If you want more than that,\
+ you have to provide another trace control GUID */\
+ )
+
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+
diff --git a/general/PLX9x5x/test/plx.cpp b/general/PLX9x5x/test/plx.cpp
new file mode 100644
index 00000000..c5bae510
--- /dev/null
+++ b/general/PLX9x5x/test/plx.cpp
@@ -0,0 +1,1104 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+ plx.cpp
+
+Abstract:
+
+ This module implements the PLX class which tests the DMA of PLX devices.
+
+ Example usage:
+ plx.exe /wr /wb=100 # write-then-read once with a buffer of 100 bytes
+ plx.exe /thread # repeat write-then-read for default 5000 millisecs.
+ plx.exe /thread /time=1000 # repeat write-then-read for 1000 millisecs.
+
+ NOTE: The /quite option will suppress most non-error messages.
+ NOTE: The options and parameters are case sensitive.
+
+Environment:
+
+ User Mode Win2k or Later
+
+--*/
+
+#define INITGUID
+
+#include "plx.hpp"
+
+//
+// Define the spin count to be used for critical sections. The value
+// specified below is arbitrary. Change it based on your requirements.
+//
+#define SPIN_COUNT_FOR_CS 0x4000
+
+int g_TimeUp =0;
+
+DWORD WINAPI
+ReadThreadProc(
+ LPVOID lpParameter
+ )
+{
+ ULONG bytes;
+ PTHREAD_CONTEXT Context = (PTHREAD_CONTEXT)lpParameter;
+
+ while(!g_TimeUp) {
+
+ if(ReadFile(Context->hDevice,
+ Context->Buffer,
+ Context->BufferSize,
+ &bytes,
+ NULL)) {
+
+ if (!Context->quite) {
+ printf("Read sucessful.\n");
+ }
+
+ } else {
+
+ printf("Read failed.\n");
+ ExitProcess(1);
+ }
+ }
+ ExitThread(0);
+}
+
+DWORD WINAPI
+WriteThreadProc(
+ LPVOID lpParameter
+ )
+{
+ ULONG bytes;
+ PTHREAD_CONTEXT Context = (PTHREAD_CONTEXT)lpParameter;
+
+ while(!g_TimeUp) {
+
+ if(WriteFile(Context->hDevice,
+ Context->Buffer,
+ Context->BufferSize,
+ &bytes,
+ NULL)) {
+
+ if (!Context->quite) {
+ printf("Write sucessful.\n");
+ }
+
+ } else {
+
+ printf("Write failed.\n");
+ ExitProcess(1);
+ }
+ }
+ ExitThread(0);
+}
+
+int __cdecl
+main(
+ _In_ int argc,
+ _In_reads_(argc) char* argv[]
+ )
+{
+ PLX Plx;
+ BOOL status = TRUE;
+ ULONG test = MENU_TEST;
+
+ if (!Plx.Initialize()) {
+ printf("Failied to Initialize Test class.\n");
+ printf("exit(%u)\n", Plx.Status);
+ exit(Plx.Status);
+ }
+
+ if(argc > 1) {
+
+ for(int i=1; (i < argc) && status; i++) {
+
+ char delims[] = "-/=";
+ char delims2[] = "=";
+ char *command;
+ char *data;
+ char *state = NULL;
+
+ data = NULL;
+
+ #pragma prefast(suppress:6385, "i < argc-1 before it is incremented below");
+ command = strtok_s(argv[i], delims, &state);
+ if(command == NULL) {
+ status = FALSE;
+ break;
+ }
+
+ if(strcmp(command, "rb") == 0) {
+
+ data = strtok_s(NULL, delims2, &state);
+
+ if (!data && i < argc-1) {
+ data = argv[++i];
+ }
+
+ ULONG size = atol(data);
+ if (size > 0) {
+ Plx.SetReadBufferSize(size);
+ } else {
+ status = FALSE;
+ }
+
+ } else if(strcmp(command, "wb") == 0) {
+
+ ULONG size = 0;
+ data = strtok_s(NULL, delims2, &state);
+
+ if (!data && i < argc-1) {
+ data = argv[++i];
+ }
+ if (data) {
+ size = atol(data);
+ }
+
+ if (size > 0) {
+ Plx.SetWriteBufferSize(size);
+ } else {
+ status = FALSE;
+ }
+
+ } else if (strcmp(command, "bs") == 0) {
+ data = strtok_s(NULL, delims2, &state);
+
+ if (!data && i < argc-1) {
+ data = argv[++i];
+ }
+
+ ULONG size = atol(data);
+ if(size > 0) {
+ Plx.SetWriteBufferSize(size);
+ } else {
+ status = FALSE;
+ }
+
+ } else if(strcmp(command, "wt") == 0) {
+
+ test = WRITE_TEST;
+
+ } else if(strcmp(command, "rt") == 0) {
+
+ test = READ_TEST;
+
+ } else if(strcmp(command, "quite") == 0) {
+
+ Plx.Quite = TRUE;
+
+ } else if(strcmp(command, "thread") == 0) {
+
+ test = THREAD_TEST;
+
+ } else if (strcmp(command, "time") == 0) {
+
+ data = strtok_s(NULL, delims, &state);
+
+ if(!data && i < argc-1) {
+ #pragma prefast(suppress:6385, "i < argc-1 before it is incremented");
+ data = argv[++i];
+ }
+ ULONG size = (NULL != data) ? atol(data) : 0;
+ Plx.SetThreadLifeTime(size);
+
+ } else {
+ status = FALSE;
+ }
+
+ if (!Plx.Quite) {
+ if (data) {
+ printf("Arg %d: Command: %s Parameter: %s\n", i, command, data);
+ } else {
+ printf("Arg %d: Command: %s\n", i, command);
+ }
+ }
+ }
+ }
+
+ if (status) {
+
+ switch (test) {
+ case READ_TEST:
+ Plx.ReadTest();
+ break;
+
+ case WRITE_TEST:
+ Plx.WriteTest();
+ break;
+
+ case READ_WRITE_TEST:
+ Plx.ReadWriteTest();
+ break;
+
+ case THREAD_TEST:
+ Plx.ThreadedReadWriteTest();
+ break;
+
+ case MENU_TEST:
+ default:
+ Plx.Menu();
+ }
+
+ } else {
+
+ printf("Invalid command line parameter.\n");
+ Plx.Status = 1;
+ }
+
+ printf("exit(%u)\n", Plx.Status);
+
+ exit( Plx.Status );
+}
+
+PLX::PLX()
+{
+ ReadBuffer = WriteBuffer = NULL;
+ hDevInfo = pDeviceInterfaceDetail = NULL;
+ hDevice = INVALID_HANDLE_VALUE;
+ console = TRUE;
+ Contexts = NULL;
+ Threads = NULL;
+ ProcessorCount = 0;
+ CSInitialized = FALSE;
+ ThreadTimer = 5000; // 5000 milliseconds (5 seconds)
+
+ Quite = FALSE;
+ Status = 0;
+}
+
+PLX::~PLX()
+{
+
+ if (CSInitialized) {
+ DeleteCriticalSection(&CriticalSection);
+ }
+ if (hDevInfo) {
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
+ if (pDeviceInterfaceDetail) {
+ free(pDeviceInterfaceDetail);
+ }
+
+ if (Contexts) {
+ _Analysis_assume_(ProcessorCount <= ThreadCount);
+ for(int i = 0; i < ProcessorCount; i++) {
+ if (Contexts[i].Buffer) {
+ delete Contexts[i].Buffer;
+ }
+ }
+
+ delete Contexts;
+ Contexts = NULL;
+ }
+
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ hDevice = INVALID_HANDLE_VALUE;
+ }
+}
+
+BOOL
+PLX::Initialize()
+{
+ BOOL retValue = TRUE;
+
+ retValue = SetBufferSizes(DEFAULT_READ_BUFFER_SIZE);
+ if (!retValue) {
+ return retValue;
+ }
+
+ retValue = GetDevicePath();
+ if (!retValue) {
+ return retValue;
+ }
+
+ if (!CSInitialized) {
+ retValue = InitializeCriticalSectionAndSpinCount(&CriticalSection, SPIN_COUNT_FOR_CS);
+ if (!retValue) {
+ printf("InitializeCritialSection failed.\n");
+ Status = GetLastError();
+ return retValue;
+ }
+ CSInitialized = TRUE;
+ }
+
+ return retValue;
+}
+
+void
+PLX::Menu()
+{
+ int menu = -1;
+
+ while(menu != 0 && pDeviceInterfaceDetail) {
+ printf("\n"
+ " 1- Read from device\n"
+ " 2- Write from device\n"
+ " 3- Read/Write from device\n"
+ " 4- Read/Write Thread Test\n"
+ " 5- Select new device\n"
+ " 6- Change Buffer Size\n"
+ " 7- Compare Read/Write Buffers\n"
+ " 8- Display Read/Write Buffers\n"
+ " 9- Change Thread Lifetime\n"
+ "10- Command Line Options\n"
+ " 0- Quit\n");
+
+ if (scanf_s("%d", &menu) == 0) {
+ break;
+ }
+
+ switch(menu) {
+ case READ_TEST: // 1
+ ReadTest();
+ break;
+
+ case WRITE_TEST: // 2
+ WriteTest();
+ break;
+
+ case READ_WRITE_TEST: // 3
+ ReadWriteTest();
+ break;
+
+ case THREAD_TEST: // 4
+ ThreadedReadWriteTest();
+ break;
+
+ case DEVICE_PATH: // 5
+ GetDevicePath();
+ break;
+
+ case SET_SIZE: // 6
+ ULONG size;
+ printf("\nEnter new buffer size: ");
+ if (scanf_s("%u", &size) != 0) {
+ SetBufferSizes(size);
+ }
+ break;
+
+ case COMPARE_BUFFERS: // 7
+ CompareReadWriteBuffers();
+ break;
+
+ case DISPLAY_BUFFERS: // 8
+ DisplayReadWriteBuffers();
+ break;
+
+ case THREAD_TIME: // 9
+ printf("\nEnter new Thread Lifetime (ms): ");
+ if (scanf_s("%u", &ThreadTimer) == 0) {
+ break;
+ }
+ break;
+
+ case COMMAND_LINE: // 10
+ printf("Command Line Options\n"
+ " Set Read Buffer Size: '/rb=xx'\n"
+ " Set Write Buffer Size: '/wb=xx'\n"
+ " Set Both Buffer Sizes: '/bs=xx'\n"
+ " Perform Write Test: '/wt'\n"
+ " Perform Read Test: '/rt'\n"
+ " Perform Read/Write Test: '/wr'\n"
+ " Perform Read/Write Thread Test: '/thread'\n");
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+BOOL
+PLX::ThreadedReadWriteTest()
+{
+ BOOL status = TRUE;
+ DWORD_PTR pAffinity, sAffinity;
+ int i;
+
+ HANDLE hThread;
+ HANDLE hProcess = GetCurrentProcess();
+
+ GetProcessAffinityMask(hProcess, &pAffinity, &sAffinity);
+ ProcessorCount = 0;
+
+ while(pAffinity) {
+ ProcessorCount++;
+ pAffinity = pAffinity >> 1;
+ }
+
+ if (ProcessorCount == 1) {
+ ThreadCount = DEFAULT_THREAD_COUNT;
+ } else {
+ ThreadCount = ProcessorCount;
+ }
+
+ Contexts = new THREAD_CONTEXT[ThreadCount];
+ Threads = new HANDLE[ThreadCount];
+
+ if (Contexts == NULL || Threads == NULL) {
+ return FALSE;
+ }
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ status = GetDeviceHandle();
+ }
+
+ if (!Quite) {
+ printf("Creating %d threads...\n", ThreadCount);
+ }
+
+ pAffinity = 1;
+
+ for(i = 0; i < ThreadCount; i++) {
+
+ if ((i % 2) == 0) {
+
+ //
+ // Create Read Thread
+ //
+ Contexts[i].hDevice = hDevice;
+ Contexts[i].BufferSize = ReadBufferSize;
+ Contexts[i].Buffer = new UCHAR[ReadBufferSize];
+ Contexts[i].quite = Quite;
+
+ hThread = CreateThread(NULL,
+ 0,
+ ReadThreadProc,
+ &Contexts[i],
+ 0,
+ NULL);
+
+ if (NULL == hThread) {
+ printf( "Failed to create thread %d\n", i );
+ this->Status = 1;
+ break;
+
+ } else {
+ Threads[i] = hThread;
+ }
+
+ } else {
+
+ //
+ // Create Write Thread
+ //
+ Contexts[i].hDevice = hDevice;
+ Contexts[i].BufferSize = WriteBufferSize;
+ Contexts[i].Buffer = new UCHAR[WriteBufferSize];
+ Contexts[i].quite = Quite;
+
+ hThread = CreateThread(NULL,
+ 0,
+ WriteThreadProc,
+ &Contexts[i],
+ 0,
+ NULL);
+
+ if (NULL == hThread) {
+ printf( "Failed to create thread %d\n", i );
+ this->Status = 1;
+ break;
+
+ } else {
+ Threads[i] = hThread;
+ }
+ }
+
+ //
+ // Set Affinity
+ //
+ SetThreadAffinityMask(Threads[i], pAffinity);
+
+ pAffinity = pAffinity << 1;
+ }
+
+ if (i != ThreadCount) {
+
+ //
+ // some create thread failed, bail out
+ //
+ printf( "Some CreateThread was failed, stop\n" );
+ g_TimeUp = 1;
+
+ } else {
+
+ //
+ // wait till either all quit or time is due
+ //
+ DWORD error;
+
+ error = WaitForMultipleObjects(i, Threads, TRUE, ThreadTimer);
+
+ if (error == WAIT_TIMEOUT) {
+
+ //
+ // Stop the threads if time is up
+ //
+ g_TimeUp = 2;
+ error = WaitForMultipleObjects(i, Threads, TRUE, 100000) ;
+
+ if (error) {
+ printf("WaitForMultipleObjects[%d] error %u\n", i, error);
+ }
+ } else {
+ if (error) {
+ printf("WaitForMultipleObjects[%d] error %u\n", i, error);
+ }
+ }
+ }
+
+ if (Contexts) {
+ for (i = 0; i < ThreadCount; i++) {
+ if (Contexts[i].Buffer) {
+ delete Contexts[i].Buffer;
+ }
+ }
+
+ delete Contexts;
+ Contexts = NULL;
+ }
+
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ hDevice = INVALID_HANDLE_VALUE;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::ReadTest()
+{
+ BOOL status = TRUE;
+ ULONG bytes = 0;
+
+ if (!ReadBuffer) {
+ status = FALSE;
+ }
+
+ if ((status == TRUE) && (hDevice == INVALID_HANDLE_VALUE)) {
+ status = GetDeviceHandle();
+ }
+
+ if (status) {
+ if (ReadFile(hDevice,
+ ReadBuffer,
+ ReadBufferSize,
+ &bytes,
+ NULL)){
+
+ EnterCriticalSection(&CriticalSection);
+ if (!Quite) {
+ printf("Read sucessful.\n");
+ }
+ LeaveCriticalSection(&CriticalSection);
+
+ } else {
+
+ EnterCriticalSection(&CriticalSection);
+ printf("Read failed.\n");
+ this->Status = 1;
+ LeaveCriticalSection(&CriticalSection);
+ }
+ }
+
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ hDevice = INVALID_HANDLE_VALUE;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::WriteTest()
+{
+ ULONG bytes = 0;
+ BOOL status = TRUE;
+
+ if (!WriteBuffer) {
+ status = FALSE;
+ }
+
+ if ((status == TRUE) && (hDevice == INVALID_HANDLE_VALUE)) {
+ status = GetDeviceHandle();
+ }
+
+ if (status) {
+ FillMemory(WriteBuffer, WriteBufferSize, 0xAB);
+
+ if (WriteFile(hDevice,
+ WriteBuffer,
+ WriteBufferSize,
+ &bytes,
+ NULL)) {
+
+ EnterCriticalSection(&CriticalSection);
+ if (!Quite) {
+ printf("Write sucessful.\n");
+ }
+ LeaveCriticalSection(&CriticalSection);
+
+ } else {
+
+ EnterCriticalSection(&CriticalSection);
+ printf("Write failed.\n");
+ this->Status = 1;
+ LeaveCriticalSection(&CriticalSection);
+ }
+ }
+
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ hDevice = INVALID_HANDLE_VALUE;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::ReadWriteTest()
+{
+ return (WriteTest() && ReadTest() && CompareReadWriteBuffers());
+}
+
+BOOL
+PLX::CompareReadWriteBuffers()
+{
+ BOOL status = TRUE;
+ ULONG size;
+ PUCHAR WTraverse;
+ PUCHAR RTraverse;
+
+ if (ReadBufferSize <= WriteBufferSize) {
+ size = ReadBufferSize;
+ } else {
+ size = WriteBufferSize;
+ }
+
+ WTraverse = WriteBuffer;
+ RTraverse = ReadBuffer;
+
+ for(ULONG i = 0; i < size; i++) {
+ if (*WTraverse++ != *RTraverse++) {
+ status = FALSE;
+ }
+ }
+
+ if (status) {
+ if (!Quite) {
+ printf("Buffers are identical\n");
+ }
+ } else {
+ printf("Buffers not identical\n");
+ this->Status = 1;
+ }
+
+ return status;
+}
+
+void
+PLX::DisplayReadWriteBuffers()
+{
+ if (!Quite) {
+
+ PUCHAR WTraverse;
+ PUCHAR RTraverse;
+
+ WTraverse = WriteBuffer;
+ RTraverse = ReadBuffer;
+
+ printf("Write: ");
+ for(ULONG i = 0; i < WriteBufferSize; i++) {
+ printf("%X ", *WTraverse++);
+ }
+
+ printf("\n\n\nRead: ");
+ for(ULONG i = 0; i < ReadBufferSize; i++) {
+ printf("%X ", *RTraverse++);
+ }
+ printf("\n");
+ }
+}
+
+BOOL
+PLX::SetReadBufferSize(ULONG size)
+{
+ BOOL status = TRUE;
+
+ if (ReadBuffer) {
+ free(ReadBuffer);
+ }
+
+ ReadBufferSize = size;
+
+ ReadBuffer = (PUCHAR)malloc(ReadBufferSize);
+
+ if (!ReadBuffer) {
+ status = FALSE;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::SetWriteBufferSize(ULONG size)
+{
+ BOOL status = TRUE;
+
+ if (WriteBuffer) {
+ free(WriteBuffer);
+ }
+
+ WriteBufferSize = size;
+
+ WriteBuffer = (PUCHAR)malloc(WriteBufferSize);
+
+ if (!WriteBuffer) {
+ status = FALSE;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::SetBufferSizes(ULONG size)
+{
+ BOOL status;
+
+ status = SetReadBufferSize(size);
+ if (status) {
+ status = SetWriteBufferSize(size);
+ }
+
+ return status;
+}
+
+BOOL
+PLX::GetDevicePath()
+{
+ SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+ SP_DEVINFO_DATA DeviceInfoData;
+
+ ULONG size;
+ int count, i, index;
+ BOOL status = TRUE;
+ TCHAR *DeviceName = NULL;
+ TCHAR *DeviceLocation = NULL;
+
+ //
+ // Retreive the device information for all PLX devices.
+ //
+ hDevInfo = SetupDiGetClassDevs(&GUID_PLX_INTERFACE,
+ NULL,
+ NULL,
+ DIGCF_DEVICEINTERFACE |
+ DIGCF_PRESENT);
+
+ //
+ // Initialize the SP_DEVICE_INTERFACE_DATA Structure.
+ //
+ DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ //
+ // Determine how many devices are present.
+ //
+ count = 0;
+ while(SetupDiEnumDeviceInterfaces(hDevInfo,
+ NULL,
+ &GUID_PLX_INTERFACE,
+ count++, //Cycle through the available devices.
+ &DeviceInterfaceData)
+ );
+
+ //
+ // Since the last call fails when all devices have been enumerated,
+ // decrement the count to get the true device count.
+ //
+ count--;
+
+ //
+ // If the count is zero then there are no devices present.
+ //
+ if (count == 0) {
+ printf("No PLX devices are present and enabled in the system.\n");
+ this->Status = 1;
+ return FALSE;
+ }
+
+ //
+ // Initialize the appropriate data structures in preparation for
+ // the SetupDi calls.
+ //
+ DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+ //
+ // Loop through the device list to allow user to choose
+ // a device. If there is only one device, select it
+ // by default.
+ //
+ i = 0;
+ while (SetupDiEnumDeviceInterfaces(hDevInfo,
+ NULL,
+ (LPGUID)&GUID_PLX_INTERFACE,
+ i,
+ &DeviceInterfaceData)) {
+
+ //
+ // Determine the size required for the DeviceInterfaceData
+ //
+ SetupDiGetDeviceInterfaceDetail(hDevInfo,
+ &DeviceInterfaceData,
+ NULL,
+ 0,
+ &size,
+ NULL);
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ printf("SetupDiGetDeviceInterfaceDetail failed, Error: %u", GetLastError());
+ this->Status = 1;
+ return FALSE;
+ }
+
+ pDeviceInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(size);
+
+ if (!pDeviceInterfaceDetail) {
+ printf("Insufficient memory.\n");
+ this->Status = 1;
+ return FALSE;
+ }
+
+ //
+ // Initialize structure and retrieve data.
+ //
+ pDeviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+ status = SetupDiGetDeviceInterfaceDetail(hDevInfo,
+ &DeviceInterfaceData,
+ pDeviceInterfaceDetail,
+ size,
+ NULL,
+ &DeviceInfoData);
+
+ free(pDeviceInterfaceDetail);
+
+ if (!status) {
+ printf("SetupDiGetDeviceInterfaceDetail failed, Error: %u", GetLastError());
+ this->Status = 1;
+ return status;
+ }
+
+ //
+ // Get the Device Name
+ // Calls to SetupDiGetDeviceRegistryProperty require two consecutive
+ // calls, first to get required buffer size and second to get
+ // the data.
+ //
+ SetupDiGetDeviceRegistryProperty(hDevInfo,
+ &DeviceInfoData,
+ SPDRP_DEVICEDESC,
+ NULL,
+ (PBYTE)DeviceName,
+ 0,
+ &size);
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ printf("SetupDiGetDeviceRegistryProperty failed, Error: %u", GetLastError());
+ this->Status = 1;
+ return FALSE;
+ }
+
+ DeviceName = (TCHAR*) malloc(size);
+ if (!DeviceName) {
+ printf("Insufficient memory.\n");
+ this->Status = 1;
+ return FALSE;
+ }
+
+ status = SetupDiGetDeviceRegistryProperty(hDevInfo,
+ &DeviceInfoData,
+ SPDRP_DEVICEDESC,
+ NULL,
+ (PBYTE)DeviceName,
+ size,
+ NULL);
+ if (!status) {
+ printf("SetupDiGetDeviceRegistryProperty failed, Error: %u",
+ GetLastError());
+ free(DeviceName);
+ this->Status = 1;
+ return status;
+ }
+
+ //
+ // Now retrieve the Device Location.
+ //
+ SetupDiGetDeviceRegistryProperty(hDevInfo,
+ &DeviceInfoData,
+ SPDRP_LOCATION_INFORMATION,
+ NULL,
+ (PBYTE)DeviceLocation,
+ 0,
+ &size);
+
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ DeviceLocation = (TCHAR*) malloc(size);
+
+ if (DeviceLocation != NULL) {
+
+ status = SetupDiGetDeviceRegistryProperty(hDevInfo,
+ &DeviceInfoData,
+ SPDRP_LOCATION_INFORMATION,
+ NULL,
+ (PBYTE)DeviceLocation,
+ size,
+ NULL);
+ if (!status) {
+ free(DeviceLocation);
+ DeviceLocation = NULL;
+ }
+ }
+
+ } else {
+ DeviceLocation = NULL;
+ }
+
+ //
+ // If there is more than one device print description.
+ //
+ if (count > 1 && console) {
+ printf("%d- ", i);
+ }
+
+ printf("%s\n", DeviceName);
+
+ if (DeviceLocation) {
+ printf(" %s\n", DeviceLocation);
+ }
+
+ free(DeviceName);
+ DeviceName = NULL;
+
+ if (DeviceLocation) {
+ free(DeviceLocation);
+ DeviceLocation = NULL;
+ }
+
+ i++; // Cycle through the available devices.
+ }
+
+ //
+ // Select device.
+ //
+ index = 0;
+ if (count > 1) {
+ printf("\nSelect Device: ");
+
+ if (scanf_s("%d", &index) == 0) {
+ return ERROR_INVALID_DATA;
+ }
+ }
+
+ //
+ // Get information for specific device.
+ //
+ status = SetupDiEnumDeviceInterfaces(hDevInfo,
+ NULL,
+ (LPGUID)&GUID_PLX_INTERFACE,
+ index,
+ &DeviceInterfaceData);
+
+ if (!status) {
+ printf("SetupDiEnumDeviceInterfaces failed, Error: %u", GetLastError());
+ return status;
+ }
+
+ //
+ // Determine the size required for the DeviceInterfaceData
+ //
+ SetupDiGetDeviceInterfaceDetail(hDevInfo,
+ &DeviceInterfaceData,
+ NULL,
+ 0,
+ &size,
+ NULL);
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ printf("SetupDiGetDeviceInterfaceDetail failed, Error: %u", GetLastError());
+ this->Status = 1;
+ return FALSE;
+ }
+
+ pDeviceInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(size);
+
+ if (!pDeviceInterfaceDetail) {
+ printf("Insufficient memory.\n");
+ this->Status = 1;
+ return FALSE;
+ }
+
+ //
+ // Initialize structure and retrieve data.
+ //
+ pDeviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ status = SetupDiGetDeviceInterfaceDetail(hDevInfo,
+ &DeviceInterfaceData,
+ pDeviceInterfaceDetail,
+ size,
+ NULL,
+ &DeviceInfoData);
+ if (!status) {
+ printf("SetupDiGetDeviceInterfaceDetail failed, Error: %u", GetLastError());
+ this->Status = 1;
+ return status;
+ }
+
+ return status;
+}
+
+BOOL
+PLX::GetDeviceHandle()
+{
+ BOOL status = TRUE;
+
+ if (pDeviceInterfaceDetail == NULL) {
+ status = GetDevicePath();
+ }
+ if (pDeviceInterfaceDetail == NULL) {
+ status = FALSE;
+ }
+
+ if (status) {
+
+ //
+ // Get handle to device.
+ //
+ hDevice = CreateFile(pDeviceInterfaceDetail->DevicePath,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ status = FALSE;
+ printf("CreateFile failed. Error:%u", GetLastError());
+ this->Status = 1;
+ }
+ }
+
+ return status;
+}
+
+void
+PLX::SetThreadLifeTime(ULONG time)
+{
+ ThreadTimer = time;
+}
+
diff --git a/general/PLX9x5x/test/plx.hpp b/general/PLX9x5x/test/plx.hpp
new file mode 100644
index 00000000..fe87fea1
--- /dev/null
+++ b/general/PLX9x5x/test/plx.hpp
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 2003 Microsoft Corporation
+
+Module Name:
+
+ plx.hpp
+
+Abstract:
+
+ This module defines the PLX class and the
+ values neccessary for Window operation and IOCTL control.
+
+Environment:
+
+ User Mode Win2k or Later
+
+--*/
+
+#pragma once
+
+#include <windows.h>
+#include <setupapi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "public.h"
+
+//
+// scanf_s is not available in the DDK build environment.
+// So redefining it to use scanf
+//
+#if defined(DDKBUILD)
+
+#define scanf_s scanf
+
+#endif
+
+
+#define DEFAULT_READ_BUFFER_SIZE 1024
+#define DEFAULT_WRITE_BUFFER_SIZE 1024
+
+#define DEFAULT_THREAD_COUNT 2
+
+typedef struct _THREAD_CONTEXT
+{
+ HANDLE hDevice;
+ BOOL quite;
+ ULONG BufferSize;
+ PUCHAR Buffer;
+
+} THREAD_CONTEXT, *PTHREAD_CONTEXT;
+
+typedef enum {
+
+ MENU_TEST = 0,
+ READ_TEST = 1,
+ WRITE_TEST = 2,
+ READ_WRITE_TEST = 3,
+ THREAD_TEST = 4,
+ DEVICE_PATH = 5,
+ SET_SIZE = 6,
+ COMPARE_BUFFERS = 7,
+ DISPLAY_BUFFERS = 8,
+ THREAD_TIME = 9,
+ COMMAND_LINE = 10,
+
+} COMMAND;
+
+class PLX
+{
+
+public:
+ PLX();
+ ~PLX();
+
+ BOOL
+ Initialize();
+
+ void
+ Menu();
+
+ BOOL
+ GetDevicePath();
+
+ BOOL
+ ReadTest();
+
+ BOOL
+ WriteTest();
+
+ BOOL
+ ReadWriteTest();
+
+ BOOL
+ CompareReadWriteBuffers();
+
+ BOOL
+ SetReadBufferSize(ULONG size);
+
+ BOOL
+ SetWriteBufferSize(ULONG size);
+
+ BOOL
+ SetBufferSizes(ULONG size);
+
+ void
+ DisplayReadWriteBuffers();
+
+ BOOL
+ ThreadedReadWriteTest();
+
+ void
+ SetThreadLifeTime(ULONG time);
+
+ BOOL Quite;
+ ULONG Status;
+
+private:
+
+ BOOL
+ GetDeviceHandle();
+
+ HDEVINFO hDevInfo;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetail;
+ HANDLE hDevice;
+
+ ULONG ReadBufferSize;
+ ULONG WriteBufferSize;
+ _Field_size_bytes_(ReadBufferSize) PUCHAR ReadBuffer;
+ _Field_size_bytes_(WriteBufferSize) PUCHAR WriteBuffer;
+
+ _Field_size_(ThreadCount) HANDLE *Threads;
+ _Field_size_(ThreadCount) PTHREAD_CONTEXT Contexts;
+ int ProcessorCount;
+ int ThreadCount;
+
+ CRITICAL_SECTION CriticalSection;
+ BOOL CSInitialized;
+
+ ULONG ThreadTimer;
+
+ BOOL console;
+};
+
diff --git a/general/PLX9x5x/test/plx.vcxproj b/general/PLX9x5x/test/plx.vcxproj
new file mode 100644
index 00000000..3dcbd6f3
--- /dev/null
+++ b/general/PLX9x5x/test/plx.vcxproj
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BF101CB1-B147-40AC-8F84-13AC122A2D37}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{F475764B-7D1A-49E4-8FA0-B4153BB184E4}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="plx.cpp">
+ <WppEnabled>true</WppEnabled>
+ </ClCompile>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>plx</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>plx</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>plx</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>plx</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);BUILT_IN_DDK=1</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\sys</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;user32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/general/PLX9x5x/test/plx.vcxproj.Filters b/general/PLX9x5x/test/plx.vcxproj.Filters
new file mode 100644
index 00000000..b74b5937
--- /dev/null
+++ b/general/PLX9x5x/test/plx.vcxproj.Filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{0B47F4CC-B263-41C6-86AF-E5D9448601A6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{802D6182-3D0F-4A06-9D94-F6E77BA24FFD}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{F55A15F1-EBAB-45A9-AD99-9AA00FA8DA01}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="plx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/general/PLX9x5x/test/test.cmd b/general/PLX9x5x/test/test.cmd
new file mode 100644
index 00000000..7c744dbf
--- /dev/null
+++ b/general/PLX9x5x/test/test.cmd
@@ -0,0 +1,2 @@
+start obj\i386\plx.exe /thread /time 10000
+