[idd] implement CIVSHMEM and open it

This commit is contained in:
Geoffrey McRae 2023-04-10 05:36:00 +10:00
parent d228ef135e
commit 77ddcfe489
6 changed files with 218 additions and 8 deletions

168
idd/LGIdd/CIVSHMEM.cpp Normal file
View file

@ -0,0 +1,168 @@
#include "CIVSHMEM.h"
#include <Windows.h>
#include <SetupAPI.h>
#include <algorithm>
#include <winioctl.h>
#include "ivshmem/ivshmem.h"
CIVSHMEM::CIVSHMEM()
{
}
CIVSHMEM::~CIVSHMEM()
{
if (m_handle == INVALID_HANDLE_VALUE)
return;
Close();
CloseHandle(m_handle);
}
bool CIVSHMEM::Init()
{
HDEVINFO devInfoSet;
SP_DEVINFO_DATA devInfoData;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = nullptr;
devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IVSHMEM, nullptr, nullptr,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
devInfoData.cbSize = sizeof(devInfoData);
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
m_devices.clear();
for (int i = 0; SetupDiEnumDeviceInfo(devInfoSet, i, &devInfoData); ++i)
{
DWORD bus, addr;
if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_BUSNUMBER,
nullptr, (BYTE*)&bus, sizeof(bus), nullptr))
bus = 0xffff;
if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_ADDRESS,
nullptr, (BYTE*)&addr, sizeof(addr), nullptr))
addr = 0xffff;
IVSHMEMData data;
data.busAddr = ((DWORD64)bus) << 32 | addr;
memcpy(&data.devInfoData, &devInfoData, sizeof(devInfoData));
m_devices.push_back(data);
}
if (GetLastError() != ERROR_NO_MORE_ITEMS)
{
m_devices.clear();
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
std::sort(m_devices.begin(), m_devices.end(),
[](const IVSHMEMData & a, const IVSHMEMData & b) -> bool
{ return a.busAddr < b.busAddr; });
HKEY hkeyLG;
IVSHMEMData * device = nullptr;
DWORD shmDevice = 0;
if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Looking Glass", &hkeyLG) == ERROR_SUCCESS)
{
DWORD dataType;
DWORD dataSize = sizeof(shmDevice);
if (RegQueryValueExA(hkeyLG, "shmDevice", nullptr, &dataType, (BYTE*)&shmDevice, &dataSize) != ERROR_SUCCESS ||
dataType != REG_DWORD)
shmDevice = 0;
}
DWORD i = 0;
for (auto it = m_devices.begin(); it != m_devices.end(); ++it, ++i)
{
DWORD bus = it->busAddr >> 32;
DWORD addr = it->busAddr & 0xFFFFFFFF;
printf("IVSHMEM %u%c on bus 0x%lx, device 0x%lx, function 0x%lx\n",
i, i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF);
if (i == shmDevice)
device = &(*it);
}
if (!device)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
if (SetupDiEnumDeviceInterfaces(devInfoSet, &devInfoData, &GUID_DEVINTERFACE_IVSHMEM, 0, &devInterfaceData) == FALSE)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
DWORD reqSize = 0;
SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, nullptr, 0, &reqSize, nullptr);
if (!reqSize)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(1, reqSize);
infData->cbSize = sizeof(PSP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, infData, reqSize, nullptr, nullptr))
{
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
m_handle = CreateFile(infData->DevicePath, 0, 0, nullptr, OPEN_EXISTING, 0, 0);
if (m_handle == INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
return false;
}
SetupDiDestroyDeviceInfoList(devInfoSet);
return true;
}
bool CIVSHMEM::Open()
{
IVSHMEM_SIZE size;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, nullptr, 0, &size, sizeof(size), nullptr, nullptr))
{
printf("Failed to request ivshmem size\n");
return false;
}
IVSHMEM_MMAP_CONFIG config = {};
IVSHMEM_MMAP map = {};
config.cacheMode = IVSHMEM_CACHE_WRITECOMBINED;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_MMAP, &config, sizeof(config), &map, sizeof(map), nullptr, nullptr))
{
printf("Failed to request ivshmem mmap\n");
return false;
}
m_size = (size_t)size;
m_mem = map.ptr;
return true;
}
void CIVSHMEM::Close()
{
if (m_mem == nullptr)
return;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, nullptr, 0, nullptr, 0, nullptr, nullptr))
{
printf("Failed to release ivshmem mmap\n");
return;
}
m_size = 0;
m_mem = nullptr;
}

29
idd/LGIdd/CIVSHMEM.h Normal file
View file

@ -0,0 +1,29 @@
#pragma once
#include <Windows.h>
#include <SetupAPI.h>
#include <vector>
class CIVSHMEM
{
private:
struct IVSHMEMData
{
SP_DEVINFO_DATA devInfoData;
DWORD64 busAddr;
};
std::vector<struct IVSHMEMData> m_devices;
HANDLE m_handle = INVALID_HANDLE_VALUE;
size_t m_size;
void * m_mem = nullptr;
public:
CIVSHMEM();
~CIVSHMEM();
bool Init();
bool Open();
void Close();
};

View file

@ -3,6 +3,9 @@
void CIndirectDeviceContext::InitAdapter()
{
if (!m_ivshmem.Init() || !m_ivshmem.Open())
return;
IDDCX_ADAPTER_CAPS caps = {};
caps.Size = sizeof(caps);

View file

@ -3,12 +3,14 @@
#include <Windows.h>
#include <wdf.h>
#include <IddCx.h>
#include "CIVSHMEM.h"
class CIndirectDeviceContext
{
private:
WDFDEVICE m_wdfDevice;
IDDCX_ADAPTER m_adapter = nullptr;
CIVSHMEM m_ivshmem;
public:
CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) :

View file

@ -40,6 +40,7 @@
<ItemGroup>
<ClCompile Include="CIndirectDeviceContext.cpp" />
<ClCompile Include="CIndirectMonitorContext.cpp" />
<ClCompile Include="CIVSHMEM.cpp" />
<ClCompile Include="CSwapChainProcessor.cpp" />
<ClCompile Include="Device.cpp" />
<ClCompile Include="Direct3DDevice.cpp" />
@ -47,6 +48,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="CIndirectMonitorContext.h" />
<ClInclude Include="CIVSHMEM.h" />
<ClInclude Include="CSwapChainProcessor.h" />
<ClInclude Include="Device.h" />
<ClInclude Include="Direct3DDevice.h" />
@ -217,8 +219,8 @@
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
@ -229,8 +231,8 @@
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
@ -241,8 +243,8 @@
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
@ -253,8 +255,8 @@
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>

View file

@ -51,6 +51,9 @@
<ClInclude Include="Direct3DDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CIVSHMEM.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Device.cpp">
@ -71,5 +74,8 @@
<ClCompile Include="Direct3DDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CIVSHMEM.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>