qxl兼容普通的vga显示驱动和专用的qxl显示驱动,通过HwDeviceInterface达到兼容。
在开始设备时实例化对象
m_pHWDevice(即
HwDeviceInterface
)
NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
_Out_ ULONG* pNumberOfViews,
_Out_ ULONG* pNumberOfChildren)
{
PAGED_CODE();
QXL_ASSERT(pDxgkStartInfo != NULL);
QXL_ASSERT(pDxgkInterface != NULL);
QXL_ASSERT(pNumberOfViews != NULL);
QXL_ASSERT(pNumberOfChildren != NULL);
//CHECK ME!!!!!!!!!!!!!
RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface));
RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
//CHECK ME!!!!!!!!!!!!!
m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED;
//从系统获取设备相关信息
NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo);
if (!NT_SUCCESS(Status)){
QXL_LOG_ASSERTION1("DxgkCbGetDeviceInformation failed with status 0x%X\n", Status);
return Status;
}
//检测是否qxl设备
Status = CheckHardware();
if (NT_SUCCESS(Status)){
m_pHWDevice = new(NonPagedPoolNx) QxlDevice(this);
}else{
m_pHWDevice = new(NonPagedPoolNx) VgaDevice(this);
}
if (!m_pHWDevice){
Status = STATUS_NO_MEMORY;
DbgPrint(TRACE_LEVEL_ERROR, ("HWInit failed to allocate memory\n"));
return Status;
}
//获取设备显示信息
Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList, &m_CurrentModes[0].DispInfo);
if (!NT_SUCCESS(Status)){
DbgPrint(TRACE_LEVEL_ERROR, ("HWInit failed with status 0x%X\n", Status));
return Status;
}
DXGK_DISPLAY_INFORMATION *pInfo = &m_CurrentModes[0].DispInfo;
DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: Initial display info:\n", __FUNCTION__));
DbgPrint(TRACE_LEVEL_INFORMATION, ("ACPI/Target Id: %d:%d\n", pInfo->AcpiId, pInfo->TargetId));
DbgPrint(TRACE_LEVEL_INFORMATION, ("W/H/Pitch/Color:%d:%d:%d:%d\n", pInfo->Width, pInfo->Height, pInfo->Pitch, pInfo->ColorFormat));
DbgPrint(TRACE_LEVEL_INFORMATION, ("Physical address:%I64x\n", pInfo->PhysicAddress.QuadPart));
//注册设备
Status = RegisterHWInfo(m_pHWDevice->GetId());
if (!NT_SUCCESS(Status)){
QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", Status);
return Status;
}
*pNumberOfViews = MAX_VIEWS;
*pNumberOfChildren = MAX_CHILDREN;
m_Flags.DriverStarted = TRUE;
DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
return STATUS_SUCCESS;
}
检测设备是否qxl设备
NTSTATUS QxlDod::CheckHardware()
{
PAGED_CODE();
NTSTATUS Status;
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
//获取PCI系统的设备ID和生产商ID
PCI_COMMON_HEADER Header = {0};
ULONG BytesRead;
Status = m_DxgkInterface.DxgkCbReadDeviceSpace(m_DxgkInterface.DeviceHandle, DXGK_WHICHSPACE_CONFIG, &Header, 0, sizeof(Header), &BytesRead);
if (!NT_SUCCESS(Status)){
DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbReadDeviceSpace failed with status 0x%X\n", Status));
return Status;
}
Status = STATUS_GRAPHICS_DRIVER_MISMATCH;
if (Header.VendorID == REDHAT_PCI_VENDOR_ID && Header.DeviceID == 0x0100 && Header.RevisionID >= 4){
m_Revision = Header.RevisionID;
Status = STATUS_SUCCESS;
}
DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s returned with status 0x%X\n", __FUNCTION__, Status));
return Status;
}