9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* $Id$ */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/** @file
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VBox Miniport HGSMI related functions
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2011-2012 Oracle Corporation
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * General Public License (GPL) as published by the Free Software
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include "VBoxMPHGSMI.h"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include "VBoxMPCommon.h"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include <VBox/VMMDev.h>
32b1164f35483be483177be7b5235002a4a5afbevboxsync#include <iprt/alloc.h>
32b1164f35483be483177be7b5235002a4a5afbevboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsyncstatic DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
32b1164f35483be483177be7b5235002a4a5afbevboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync NOREF(pvEnv);
32b1164f35483be483177be7b5235002a4a5afbevboxsync return RTMemAlloc(cb);
32b1164f35483be483177be7b5235002a4a5afbevboxsync}
32b1164f35483be483177be7b5235002a4a5afbevboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsyncstatic DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
32b1164f35483be483177be7b5235002a4a5afbevboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync NOREF(pvEnv);
32b1164f35483be483177be7b5235002a4a5afbevboxsync RTMemFree(pv);
32b1164f35483be483177be7b5235002a4a5afbevboxsync}
32b1164f35483be483177be7b5235002a4a5afbevboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsyncstatic HGSMIENV g_hgsmiEnvMP =
32b1164f35483be483177be7b5235002a4a5afbevboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync NULL,
32b1164f35483be483177be7b5235002a4a5afbevboxsync hgsmiEnvAlloc,
32b1164f35483be483177be7b5235002a4a5afbevboxsync hgsmiEnvFree
32b1164f35483be483177be7b5235002a4a5afbevboxsync};
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/**
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Helper function to register secondary displays (DualView). Note that this will not
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * be available on pre-XP versions, and some editions on XP will fail because they are
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * intentionally crippled.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * HGSMI variant is a bit different because it uses only HGSMI interface (VBVA channel)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * to talk to the host.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsyncvoid VBoxSetupDisplaysHGSMI(PVBOXMP_COMMON pCommon, PHYSICAL_ADDRESS phVRAM, uint32_t ulApertureSize,
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync uint32_t cbVRAM, uint32_t fCaps)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo I simply converted this from Windows error codes. That is wrong,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * but we currently freely mix and match those (failure == rc > 0) and iprt
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * ones (failure == rc < 0) anyway. This needs to be fully reviewed and
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * fixed. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync int rc = VINF_SUCCESS;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t offVRAMBaseMapping, cbMapping, offGuestHeapMemory, cbGuestHeapMemory,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offHostFlags, offVRAMHostArea, cbHostArea;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOGF_ENTER();
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memset(pCommon, 0, sizeof(*pCommon));
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pCommon->phVRAM = phVRAM;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pCommon->ulApertureSize = ulApertureSize;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pCommon->cbVRAM = cbVRAM;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cDisplays = 1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->bHGSMI = VBoxHGSMIIsSupported();
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pCommon->bHGSMI)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxHGSMIGetBaseMappingInfo(pCommon->cbVRAM, &offVRAMBaseMapping,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync &cbMapping, &offGuestHeapMemory,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync &cbGuestHeapMemory, &offHostFlags);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Map the adapter information. It will be needed for HGSMI IO. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxMPCmnMapAdapterMemory(pCommon, &pCommon->pvAdapterInformation, offVRAMBaseMapping, cbMapping);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (RT_FAILURE(rc))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("VBoxMPCmnMapAdapterMemory failed rc = %d", rc));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->bHGSMI = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Setup an HGSMI heap within the adapter information area. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxHGSMISetupGuestContext(&pCommon->guestCtx,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->pvAdapterInformation,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbGuestHeapMemory,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offVRAMBaseMapping
32b1164f35483be483177be7b5235002a4a5afbevboxsync + offGuestHeapMemory,
32b1164f35483be483177be7b5235002a4a5afbevboxsync &g_hgsmiEnvMP);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (RT_FAILURE(rc))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("HGSMIHeapSetup failed rc = %d", rc));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->bHGSMI = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Setup the host heap and the adapter memory. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pCommon->bHGSMI)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxHGSMIGetHostAreaMapping(&pCommon->guestCtx, pCommon->cbVRAM,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offVRAMBaseMapping, &offVRAMHostArea,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync &cbHostArea);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (cbHostArea)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Map the heap region.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Note: the heap will be used for the host buffers submitted to the guest.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The miniport driver is responsible for reading FIFO and notifying
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * display drivers.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cbMiniportHeap = cbHostArea;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxMPCmnMapAdapterMemory (pCommon, &pCommon->pvMiniportHeap,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offVRAMHostArea, cbHostArea);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (RT_FAILURE(rc))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->pvMiniportHeap = NULL;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cbMiniportHeap = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->bHGSMI = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxHGSMISetupHostContext(&pCommon->hostCtx,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->pvAdapterInformation,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offHostFlags,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->pvMiniportHeap,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offVRAMHostArea, cbHostArea);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Host has not requested a heap. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->pvMiniportHeap = NULL;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cbMiniportHeap = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pCommon->bHGSMI)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Setup the information for the host. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxHGSMISendHostCtxInfo(&pCommon->guestCtx,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offVRAMBaseMapping + offHostFlags,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync fCaps, offVRAMHostArea,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cbMiniportHeap);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (RT_FAILURE(rc))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->bHGSMI = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Check whether the guest supports multimonitors. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pCommon->bHGSMI)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Query the configured number of displays. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->cDisplays = VBoxHGSMIGetMonitorCount(&pCommon->guestCtx);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxFreeDisplaysHGSMI(pCommon);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOGF_LEAVE();
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool VBoxUnmapAdpInfoCallback(void *pvCommon)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXMP_COMMON pCommon = (PVBOXMP_COMMON)pvCommon;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCommon->hostCtx.pfHostFlags = NULL;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncvoid VBoxFreeDisplaysHGSMI(PVBOXMP_COMMON pCommon)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxMPCmnUnmapAdapterMemory(pCommon, &pCommon->pvMiniportHeap);
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync#ifdef VBOX_WDDM_MINIPORT
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync VBoxSHGSMITerm(&pCommon->guestCtx.heapCtx);
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync#else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync HGSMIHeapDestroy(&pCommon->guestCtx.heapCtx);
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync#endif
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Unmap the adapter information needed for HGSMI IO. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxMPCmnSyncToVideoIRQ(pCommon, VBoxUnmapAdpInfoCallback, pCommon);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxMPCmnUnmapAdapterMemory(pCommon, &pCommon->pvAdapterInformation);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}