DevVGA_VDMA.cpp revision bd24d3f8bb5e3d164be5d9ce49d07d80587e6d7c
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Video DMA (VDMA) support.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2006-2012 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//#include <VBox/VMMDev.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/pdmdev.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/VBoxVideo.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/semaphore.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/thread.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/mem.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/asm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/list.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "DevVGA.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "HGSMI/SHGSMIHost.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/VBoxVideo3D.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/VBoxVideoHost3D.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef DEBUG_misha
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# define VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# include <iprt/memcache.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef DEBUG_misha
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define WARN_BP() do { AssertFailed(); } while (0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define WARN_BP() do { } while (0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define WARN(_msg) do { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogRel(_msg); \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN_BP(); \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBOXVDMATHREAD_STATE_TERMINATED 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBOXVDMATHREAD_STATE_CREATED 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBOXVDMATHREAD_STATE_TERMINATING 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VBOXVDMATHREAD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTTHREAD hWorkerThread;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSEMEVENT hEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSEMEVENT hClientEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync volatile uint32_t u32State;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBOXVDMATHREAD, *PVBOXVDMATHREAD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* state transformations:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * submitter | processor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * LISTENING ---> PROCESSING
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBVAEXHOSTCONTEXT_STATE_LISTENING 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBVAEXHOSTCONTEXT_STATE_PROCESSING 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBVAEXHOSTCONTEXT_ESTATE_DISABLED -1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBVAEXHOSTCONTEXT_ESTATE_PAUSED 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBVAEXHOSTCONTEXT_ESTATE_ENABLED 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VBVAEXHOSTCONTEXT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync volatile int32_t i32State;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync volatile int32_t i32EnableState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync volatile uint32_t u32cCtls;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* critical section for accessing ctl lists */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTCRITSECT CltCritSect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTLISTANCHOR GuestCtlList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTLISTANCHOR HostCtlList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTMEMCACHE CtlCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBVAEXHOSTCONTEXT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef enum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_UNDEFINED = 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_ENABLE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_TERM,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_RESET,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_SAVESTATE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_LOADSTATE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_HH_BE_OPAQUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBVAEXHOSTCTL_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstruct VBVAEXHOSTCTL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VBVAEXHOSTCTL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTLISTNODE Node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_TYPE enmType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync union
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t * pu8Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbCmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PSSMHANDLE pSSM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t u32Version;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } state;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } u;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PFNVBVAEXHOSTCTL_COMPLETE pfnComplete;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync void *pvComplete;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBVAEXHOSTCTL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * see mor edetailed comments in headers for function definitions */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef enum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOST_DATA_TYPE_NO_DATA = 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOST_DATA_TYPE_CMD,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOST_DATA_TYPE_HOSTCTL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOST_DATA_TYPE_GUESTCTL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBVAEXHOST_DATA_TYPE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHCtlAlloc(VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (VBVAEXHOSTCTL*)RTMemCacheAlloc(pCmdVbva->CtlCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (VBVAEXHOSTCTL*)RTMemAlloc(sizeof (VBVAEXHOSTCTL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHCtlFree(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTMemCacheFree(pCmdVbva->CtlCache, pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTMemFree(pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHCtlCreate(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL_TYPE enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL* pCtl = VBoxVBVAExHCtlAlloc(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBoxVBVAExHCtlAlloc failed\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl->enmType = enmType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ASMAtomicCmpXchgS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_SEM_BUSY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOSTCTL* vboxVBVAExHPCheckCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, bool *pfHostCtl, bool fHostOnlyMode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(!fHostOnlyMode && !ASMAtomicUoReadU32(&pCmdVbva->u32cCtls))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTCritSectEnter(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL* pCtl = RTListGetFirst(&pCmdVbva->HostCtlList, VBVAEXHOSTCTL, Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pfHostCtl = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (!fHostOnlyMode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) > VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl = RTListGetFirst(&pCmdVbva->GuestCtlList, VBVAEXHOSTCTL, Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* pCtl can not be null here since pCmdVbva->u32cCtls is not null,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and there are no HostCtl commands*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pfHostCtl = false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTListNodeRemove(&pCtl->Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicDecU32(&pCmdVbva->u32cCtls);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTCritSectLeave(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTCritSectEnter failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHPCheckHostCtlOnDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool fHostCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return vboxVBVAExHPCheckCtl(pCmdVbva, &fHostCtl, true);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic bool vboxVBVAExHPCheckProcessCtlInternal(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pCtl->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdVbva->i32EnableState == VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdVbva->pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdVbva->pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t indexRecordFree = pVBVA->indexRecordFree;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Log(("first = %d, free = %d\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync indexRecordFirst, indexRecordFree));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (indexRecordFirst == indexRecordFree)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* No records to process. Return without assigning output variables. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_EOF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* A new record need to be processed. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* the record is being recorded, try again */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_TRY_AGAIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!cbRecord)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* the record is being recorded, try again */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_TRY_AGAIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we should not get partial commands here actually */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbRecord);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The size of largest contiguous chunk in the ring biffer. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The pointer to data in the ring buffer. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Fetch or point the data. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (u32BytesTillBoundary >= cbRecord)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The command does not cross buffer boundary. Return address in the buffer. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *ppCmd = pSrc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pcbCmd = cbRecord;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogRel(("CmdVbva: cross-bound writes unsupported\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVBVA->off32Data = (pVBVA->off32Data + cbCmd) % pVBVA->cbData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCtl->pfnComplete)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl->pfnComplete(pCmdVbva, pCtl, rc, pCtl->pvComplete);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVBVAExHCtlFree(pCmdVbva, pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL*pCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool fHostClt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for(;;)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostClt, false);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fHostClt)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!vboxVBVAExHPCheckProcessCtlInternal(pCmdVbva, pCtl))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *ppCmd = (uint8_t*)pCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pcbCmd = sizeof (*pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_HOSTCTL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *ppCmd = (uint8_t*)pCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pcbCmd = sizeof (*pCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_GUESTCTL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) <= VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_NO_DATA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VINF_SUCCESS:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_CMD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VINF_EOF:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_NO_DATA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VINF_TRY_AGAIN:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTThreadSleep(1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("Warning: vboxVBVAExHCmdGet returned unexpected status %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_NO_DATA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_NO_DATA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOST_DATA_TYPE enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPHgEventClear(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPProcessorRelease(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 1. we check the queue -> and it is empty
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 2. submitter adds command to the queue
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 4. we clear the "processing" state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 6. if the queue appears to be not-empty set the "processing" state back to "true"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync **/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we are the processor now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPProcessorRelease(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBVAEXHOST_DATA_TYPE_NO_DATA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPHgEventSet(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return enmType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(bool) vboxVBVAExHSHasCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t indexRecordFree = pVBVA->indexRecordFree;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (indexRecordFirst != indexRecordFree)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return !!ASMAtomicReadU32(&pCmdVbva->u32cCtls);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Checks whether the new commands are ready for processing
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VINF_EOF - no commands in a queue
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VINF_ALREADY_INITIALIZED - another thread already processing the commands
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VERR_INVALID_STATE - the VBVA is paused or pausing */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we are the processor now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (vboxVBVAExHSHasCommands(pCmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPHgEventSet(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVBVAExHPProcessorRelease(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_EOF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (rc == VERR_SEM_BUSY)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_ALREADY_INITIALIZED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memset(pCmdVbva, 0, sizeof (*pCmdVbva));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTCritSectInit(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTMemCacheCreate(&pCmdVbva->CtlCache, sizeof (VBVAEXHOSTCTL),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0, /* size_t cbAlignment */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32_MAX, /* uint32_t cMaxObjects */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL, /* PFNMEMCACHECTOR pfnCtor*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL, /* PFNMEMCACHEDTOR pfnDtor*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL, /* void *pvUser*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0 /* uint32_t fFlags*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTListInit(&pCmdVbva->GuestCtlList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTListInit(&pCmdVbva->HostCtlList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdVbva->i32State = VBVAEXHOSTCONTEXT_STATE_PROCESSING;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdVbva->i32EnableState = VBVAEXHOSTCONTEXT_ESTATE_DISABLED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTMemCacheCreate failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTCritSectInit failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(bool) VBoxVBVAExHSIsEnabled(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (VBoxVBVAExHSIsEnabled(pCmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_ALREADY_INITIALIZED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdVbva->pVBVA = pVBVA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(pCmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_DISABLED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ensure the processor is stopped */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ensure no one tries to submit the command */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdVbva->pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(RTListIsEmpty(&pCmdVbva->GuestCtlList));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(RTListIsEmpty(&pCmdVbva->HostCtlList));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTCritSectDelete(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef VBOXVDBG_MEMCACHE_DISABLE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTMemCacheDestroy(pCmdVbva->CtlCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memset(pCmdVbva, 0, sizeof (*pCmdVbva));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Saves state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int32_t i32EnableState = ASMAtomicUoReadS32(&pCmdVbva->i32EnableState);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (i32EnableState >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (i32EnableState != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vbva not paused\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRCReturn(rc, rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = SSMR3PutU32(pSSM, 0xffffffff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRCReturn(rc, rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef enum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_SOURCE_GUEST = 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_SOURCE_HOST_ANY,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL_SOURCE_HOST_ENABLED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBVAEXHOSTCTL_SOURCE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("cmd vbva not enabled\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl->pfnComplete = pfnComplete;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCtl->pvComplete = pvComplete;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTCritSectEnter(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("cmd vbva not enabled\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTCritSectLeave(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicIncU32(&pCmdVbva->u32cCtls);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTCritSectLeave(&pCmdVbva->CltCritSect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VBoxVBVAExHSCheckCommands(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTCritSectEnter failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Loads state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("implement!\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t u32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = SSMR3GetU32(pSSM, &u32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRCReturn(rc, rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (u32 != 0xffffffff)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRCReturn(rc, rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VBoxVBVAExHSCheckCommands(pCmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VBOXVDMAHOST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PHGSMIINSTANCE pHgsmi;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCONTEXT CmdVbva;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMATHREAD Thread;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXCRCMD_SVRINFO CrSrvInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAEXHOSTCTL* pCurRemainingHostCtl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_VDMA_WITH_WATCHDOG
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PTMTIMERR3 WatchDogTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBOXVDMAHOST, *PVBOXVDMAHOST;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventSignal(pThread->hClientEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pThread->u32State = VBOXVDMATHREAD_STATE_CREATED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint VBoxVDMAThreadNotifyConstructFailed(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventSignal(pThread->hClientEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ASMAtomicUoReadU32(&pThread->u32State) == VBOXVDMATHREAD_STATE_TERMINATING;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventCreate(&pThread->hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSemEventCreate(&pThread->hClientEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTThreadCreate(&pThread->hWorkerThread, pfnThread, pvThread, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSemEventWait(pThread->hClientEvent, RT_INDEFINITE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pThread->u32State == VBOXVDMATHREAD_STATE_CREATED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("thread routine failed the initialization\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventWait failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTThreadCreate failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(pThread->hClientEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventCreate failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(pThread->hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventCreate failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(int) VBoxVDMAThreadEventNotify(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventSignal(pThread->hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(int) VBoxVDMAThreadEventWait(PVBOXVDMATHREAD pThread, RTMSINTERVAL cMillies)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventWait(pThread->hEvent, cMillies);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid VBoxVDMAThreadMarkTerminating(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pThread->u32State == VBOXVDMATHREAD_STATE_CREATED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid VBoxVDMAThreadTerm(PVBOXVDMATHREAD pThread)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ASMAtomicReadU32(&pThread->u32State) != VBOXVDMATHREAD_STATE_TERMINATING)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVDMAThreadMarkTerminating(pThread);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VBoxVDMAThreadEventNotify(pThread);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(pThread->hClientEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(pThread->hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_CRHGSMI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef FNVBOXVDMACRCTL_CALLBACK *PFNVBOXVDMACRCTL_CALLBACK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VBOXVDMACMD_CHROMIUM_CTL_PRIVATE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cRefs;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int32_t rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PFNVBOXVDMACRCTL_CALLBACK pfnCompletion;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync void *pvCompletion;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMACMD_CHROMIUM_CTL Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, *PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(_p) ((PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd)))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic PVBOXVDMACMD_CHROMIUM_CTL vboxVDMACrCtlCreate(VBOXVDMACMD_CHROMIUM_CTL_TYPE enmCmd, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = (PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)RTMemAllocZ(cbCmd + RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pHdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pHdr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->cRefs = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->rc = VERR_NOT_IMPLEMENTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->Cmd.enmType = enmCmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->Cmd.cbCmd = cbCmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return &pHdr->Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(void) vboxVDMACrCtlRelease (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cRefs = ASMAtomicDecU32(&pHdr->cRefs);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(!cRefs)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTMemFree(pHdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(void) vboxVDMACrCtlRetain (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMAtomicIncU32(&pHdr->cRefs);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLINLINE(int) vboxVDMACrCtlGetRc (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pHdr->rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbSetEvent(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventSignal((RTSEMEVENT)pvContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbReleaseCmd(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMACrCtlRelease(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrCtlPostAsync (PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd, PFNVBOXVDMACRCTL_CALLBACK pfnCompletion, void *pvCompletion)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( pVGAState->pDrv
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pVGAState->pDrv->pfnCrHgsmiControlProcess)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->pfnCompletion = pfnCompletion;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pHdr->pvCompletion = pvCompletion;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVGAState->pDrv->pfnCrHgsmiControlProcess(pVGAState->pDrv, pCmd, cbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef DEBUG_misha
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_NOT_SUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSEMEVENT hComplEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventCreate(&hComplEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACrCtlPostAsync(pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef DEBUG_misha
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(hComplEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* the command is completed */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(hComplEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct VDMA_VBVA_CTL_CYNC_COMPLETION
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSEMEVENT hEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VDMA_VBVA_CTL_CYNC_COMPLETION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) vboxVDMACrHgcmSubmitSyncCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvCompletion;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pData->rc = rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSemEventSignal(pData->hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventSignal failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrHgcmSubmitSync(struct VBOXVDMAHOST *pVdma, VBOXCRCMDCTL* pCtl, uint32_t cbCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VDMA_VBVA_CTL_CYNC_COMPLETION Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data.rc = VERR_NOT_IMPLEMENTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = RTSemEventCreate(&Data.hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventCreate failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCtl, cbCtl, vboxVDMACrHgcmSubmitSyncCompletion, &Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = Data.rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("pfnCrHgcmCtlSubmit command failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("RTSemEventWait failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("pfnCrHgcmCtlSubmit failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTSemEventDestroy(Data.hEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(uint8_t*) vboxVDMACrHgcmHandleEnableRemainingHostCommand(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hClient, uint32_t *pcbCtl, int prevCmdRc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct VBOXVDMAHOST *pVdma = hClient;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pVdma->pCurRemainingHostCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* disable VBVA, all subsequent host commands will go HGCM way */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVBVAExHSDisable(&pVdma->CmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVBVAExHPDataCompleteCtl(&pVdma->CmdVbva, pVdma->pCurRemainingHostCtl, prevCmdRc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVdma->pCurRemainingHostCtl = VBoxVBVAExHPCheckHostCtlOnDisable(&pVdma->CmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pVdma->pCurRemainingHostCtl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pcbCtl = pVdma->pCurRemainingHostCtl->u.cmd.cbCmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pVdma->pCurRemainingHostCtl->u.cmd.pu8Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pcbCtl = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrHgcmHandleEnable(struct VBOXVDMAHOST *pVdma)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXCRCMDCTL_ENABLE Enable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Enable.Hdr.enmType = VBOXCRCMDCTL_TYPE_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Enable.hRHCmd = pVdma;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Enable.pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVDMACrHgcmSubmitSync(pVdma, &Enable.Hdr, sizeof (Enable));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!pVdma->pCurRemainingHostCtl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vdmaVBVAEnableProcess(struct VBOXVDMAHOST *pVdma, uint32_t u32Offset)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vdma VBVA is already enabled\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pVdma->pHgsmi, u32Offset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pVBVA)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("invalid offset %d\n", u32Offset));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pVdma->CrSrvInfo.pfnEnable)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef DEBUG_misha
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("pfnEnable is NULL\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_NOT_SUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXCRCMDCTL Ctl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ctl.enmType = VBOXCRCMDCTL_TYPE_DISABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACrHgcmSubmitSync(pVdma, &Ctl, sizeof (Ctl));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXCRCMD_SVRENABLE_INFO Info;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.hCltScr = pVGAState->pDrv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("pfnEnable failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMACrHgcmHandleEnable(pVdma);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVBVAExHSDisable(&pVdma->CmdVbva);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBoxVBVAExHSEnable failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vdmaVBVADisableProcess(struct VBOXVDMAHOST *pVdma)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Log(("vdma VBVA is already disabled\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = pVdma->CrSrvInfo.pfnDisable(pVdma->CrSrvInfo.hSvr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* disable is a bit tricky
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * we need to ensure the host ctl commands do not come out of order
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and do not come over HGCM channel until after it is enabled */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACrHgcmHandleEnable(pVdma);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXCRCMD_SVRENABLE_INFO Info;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.hCltScr = pVGAState->pDrv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("pfnDisable failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrHostCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pCmd->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_SAVESTATE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBVAEXHOSTCTL_TYPE_HH_SAVESTATE for disabled vdma VBVA\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pVdma->CrSrvInfo.pfnSaveState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_LOADSTATE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBVAEXHOSTCTL_TYPE_HH_LOADSTATE for disabled vdma VBVA\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pVdma->CrSrvInfo.pfnLoadState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM, pCmd->u.state.u32Version);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pVdma->CrSrvInfo.pfnHostCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_TERM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vdmaVBVADisableProcess(pVdma);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vdmaVBVADisableProcess failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxVDMAThreadMarkTerminating(&pVdma->Thread);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_HH_RESET:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vdmaVBVADisableProcess(pVdma);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vdmaVBVADisableProcess failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("unexpected host ctl type %d\n", pCmd->enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrGuestCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pCmd->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_STATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pVdma->CrSrvInfo.pfnGuestCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBVAENABLE *pEnable = (VBVAENABLE *)pCmd->u.cmd.pu8Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmd->u.cmd.cbCmd == sizeof (VBVAENABLE));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t u32Offset = pEnable->u32Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return vdmaVBVAEnableProcess(pVdma, u32Offset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return vdmaVBVADisableProcess(pVdma);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("unexpected ctl type %d\n", pCmd->enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_EOF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* check if the command is cancelled */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_EOF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* come commands can be handled right away? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pCmd->u8OpCode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBOXCMDVBVA_OPTYPE_NOPCMD:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmd->u.i8Result = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_EOF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) vboxVDMACrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCmdDisable(HVBOXCRCMDSVR hSvr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) vboxVDMACrCmdCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_NOT_SUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) vboxVDMACrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pCmd->u8OpCode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync crVBoxServerCrCmdBltProcess(pCmd, cbCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("unsupported command\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmd->u.i8Result = -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VERR_NO_MEMORY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmd->pvVRamBase = pVGAState->vram_ptrR3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmd->cbVRam = pVGAState->vram_size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACrCtlGetRc(&pCmd->Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVdma->CrSrvInfo = pCmd->CrCmdServerInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (rc != VERR_NOT_SUPPORTED)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vboxVDMACrCtlGetRc returned %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WARN(("vboxVDMACrCtlPost failed %d\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMACrCtlRelease(&pCmd->Hdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memset(&pVdma->CrSrvInfo, 0, sizeof (pVdma->CrSrvInfo));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* check if this is external cmd to be passed to chromium backend */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmdDr, uint32_t cbCmdDr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD pDmaCmd = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbDmaCmd = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VINF_NOT_SUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cbDmaCmd = pCmdDr->cbBuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbCmdDr < sizeof (*pCmdDr) + VBOXVDMACMD_HEADER_SIZE())
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("invalid buffer data!"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbDmaCmd < cbCmdDr - sizeof (*pCmdDr) - VBOXVDMACMD_HEADER_SIZE())
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("invalid command buffer data!"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVIDEOOFFSET offBuf = pCmdDr->Location.offVramBuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (offBuf + cbDmaCmd > pVdma->pVGAState->vram_size)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("invalid command buffer data from offset!"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDmaCmd = (VBOXVDMACMD*)(pvRam + offBuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pDmaCmd)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbDmaCmd >= VBOXVDMACMD_HEADER_SIZE());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbBody = VBOXVDMACMD_BODY_SIZE(cbDmaCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pDmaCmd->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CMD pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbBody < sizeof (*pCrCmd))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("invalid chromium command buffer size!"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pVGAState->pDrv->pfnCrHgsmiCommandProcess)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxSHGSMICommandMarkAsynchCompletion(pCmdDr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd, cbBody);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int tmpRc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(tmpRc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbBody < sizeof (*pTransfer))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("invalid bpb transfer buffer size!"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof (*pTransfer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdDr->rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint vboxVDMACrHgsmiCommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMACMD *pDmaHdr = VBOXVDMACMD_FROM_BODY(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMACBUF_DR *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaHdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDr->rc = rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VBoxSHGSMICommandComplete(pIns, pDr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pCmdPrivate = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdPrivate->rc = rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pCmdPrivate->pfnCompletion)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pCmdPrivate->pfnCompletion(pVGAState, pCmd, pCmdPrivate->pvCompletion);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_VDMA_WITH_WORKERTHREAD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* to simplify things and to avoid extra backend if modifications we assume the VBOXVDMA_RECTL is the same as VBVACMDHDR */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(sizeof(VBOXVDMA_RECTL) == sizeof(VBVACMDHDR));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, left) == RT_SIZEOFMEMB(VBVACMDHDR, x));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, top) == RT_SIZEOFMEMB(VBVACMDHDR, y));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, width) == RT_SIZEOFMEMB(VBVACMDHDR, w));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, height) == RT_SIZEOFMEMB(VBVACMDHDR, h));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, left) == RT_OFFSETOF(VBVACMDHDR, x));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, top) == RT_OFFSETOF(VBVACMDHDR, y));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, width) == RT_OFFSETOF(VBVACMDHDR, w));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, height) == RT_OFFSETOF(VBVACMDHDR, h));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMANotifyPrimaryUpdate (PVGASTATE pVGAState, unsigned uScreenId, const VBOXVDMA_RECTL * pRectl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVGAState->pDrv->pfnVBVAUpdateBegin (pVGAState->pDrv, uScreenId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Updates the rectangle and sends the command to the VRDP server. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVGAState->pDrv->pfnVBVAUpdateProcess (pVGAState->pDrv, uScreenId,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (const PVBVACMDHDR)pRectl /* <- see above AssertCompile's and comments */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (VBOXVDMA_RECTL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVGAState->pDrv->pfnVBVAUpdateEnd (pVGAState->pDrv, uScreenId, pRectl->left, pRectl->top,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl->width, pRectl->height);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t *pvDstSurf, const uint8_t *pvSrcSurf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we do not support color conversion */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pDstDesc->format == pSrcDesc->format);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we do not support stretching */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pDstRectl->height == pSrcRectl->height);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pDstRectl->width == pSrcRectl->width);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pDstDesc->format != pSrcDesc->format)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_FUNCTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pDstDesc->width == pDstRectl->width
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pSrcDesc->width == pSrcRectl->width
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pSrcDesc->width == pDstDesc->width)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!pDstRectl->left);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!pSrcRectl->left);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbOff = pDstDesc->pitch * pDstRectl->top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offDstLineStart = pDstRectl->left * pDstDesc->bpp >> 3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offDstLineEnd = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbDstLine = offDstLineEnd - offDstLineStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbDstLine <= pDstDesc->pitch);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbDstSkip = pDstDesc->pitch;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t * pvDstStart = pvDstSurf + offDstStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offSrcLineStart = pSrcRectl->left * pSrcDesc->bpp >> 3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offSrcLineEnd = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbSrcLine = offSrcLineEnd - offSrcLineStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbSrcLine <= pSrcDesc->pitch);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbSrcSkip = pSrcDesc->pitch;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbDstLine == cbSrcLine);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (uint32_t i = 0; ; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memcpy (pvDstStart, pvSrcStart, cbDstLine);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (i == pDstRectl->height)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pvDstStart += cbDstSkip;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pvSrcStart += cbSrcSkip;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pRectl1->width)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pRectl1 = *pRectl2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int16_t x21 = pRectl1->left + pRectl1->width;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int16_t x22 = pRectl2->left + pRectl2->width;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pRectl1->left > pRectl2->left)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->left = pRectl2->left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->width = x21 < x22 ? x22 - pRectl1->left : x21 - pRectl1->left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (x21 < x22)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->width = x22 - pRectl1->left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync x21 = pRectl1->top + pRectl1->height;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync x22 = pRectl2->top + pRectl2->height;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pRectl1->top > pRectl2->top)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->top = pRectl2->top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->height = x21 < x22 ? x22 - pRectl1->top : x21 - pRectl1->top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (x21 < x22)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pRectl1->height = x22 - pRectl1->top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(cbBlt <= cbBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbBuffer < cbBlt)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_FUNCTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we do not support stretching for now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBlt->srcRectl.width != pBlt->dstRectl.width)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_FUNCTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBlt->srcRectl.height != pBlt->dstRectl.height)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_FUNCTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pBlt->cDstSubRects);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMA_RECTL updateRectl = {0, 0, 0, 0};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBlt->cDstSubRects)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXVDMA_RECTL dstRectl, srcRectl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const VBOXVDMA_RECTL *pDstRectl, *pSrcRectl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (uint32_t i = 0; i < pBlt->cDstSubRects; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDstRectl = &pBlt->aDstSubRects[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBlt->dstRectl.left || pBlt->dstRectl.top)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstRectl.left = pDstRectl->left + pBlt->dstRectl.left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstRectl.top = pDstRectl->top + pBlt->dstRectl.top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstRectl.width = pDstRectl->width;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstRectl.height = pDstRectl->height;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDstRectl = &dstRectl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSrcRectl = &pBlt->aDstSubRects[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBlt->srcRectl.left || pBlt->srcRectl.top)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync srcRectl.left = pSrcRectl->left + pBlt->srcRectl.left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync srcRectl.top = pSrcRectl->top + pBlt->srcRectl.top;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync srcRectl.width = pSrcRectl->width;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync srcRectl.height = pSrcRectl->height;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSrcRectl = &srcRectl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &pBlt->dstDesc, &pBlt->srcDesc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pDstRectl,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pSrcRectl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMARectlUnite(&updateRectl, pDstRectl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &pBlt->dstDesc, &pBlt->srcDesc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &pBlt->dstRectl,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &pBlt->srcRectl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRC(rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMARectlUnite(&updateRectl, &pBlt->dstRectl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_VDMA_WITH_WORKERTHREAD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int iView = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* @todo: fixme: check if update is needed and get iView */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vboxVDMANotifyPrimaryUpdate (pVdma->pVGAState, iView, &updateRectl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return cbBlt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cbBuffer < sizeof (*pTransfer))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVGASTATE pVGAState = pVdma->pVGAState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t * pvRam = pVGAState->vram_ptrR3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PGMPAGEMAPLOCK SrcLock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PGMPAGEMAPLOCK DstLock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const void * pvSrc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync void * pvDst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbTransfer = pTransfer->cbTransferSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbTransfered = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool bSrcLocked = false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bool bDstLocked = false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t cbSubTransfer = cbTransfer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pvSrc = pvRam + pTransfer->Src.offVramBuf + cbTransfered;
}
else
{
RTGCPHYS phPage = pTransfer->Src.phBuf;
phPage += cbTransfered;
rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvSrc, &SrcLock);
AssertRC(rc);
if (RT_SUCCESS(rc))
{
bSrcLocked = true;
cbSubTransfer = RT_MIN(cbSubTransfer, 0x1000);
}
else
{
break;
}
}
if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET)
{
pvDst = pvRam + pTransfer->Dst.offVramBuf + cbTransfered;
}
else
{
RTGCPHYS phPage = pTransfer->Dst.phBuf;
phPage += cbTransfered;
rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvDst, &DstLock);
AssertRC(rc);
if (RT_SUCCESS(rc))
{
bDstLocked = true;
cbSubTransfer = RT_MIN(cbSubTransfer, 0x1000);
}
else
{
break;
}
}
if (RT_SUCCESS(rc))
{
memcpy(pvDst, pvSrc, cbSubTransfer);
cbTransfer -= cbSubTransfer;
cbTransfered += cbSubTransfer;
}
else
{
cbTransfer = 0; /* to break */
}
if (bSrcLocked)
PDMDevHlpPhysReleasePageMappingLock(pDevIns, &SrcLock);
if (bDstLocked)
PDMDevHlpPhysReleasePageMappingLock(pDevIns, &DstLock);
} while (cbTransfer);
if (RT_SUCCESS(rc))
return sizeof (*pTransfer);
return rc;
}
static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_t cbBuffer)
{
do
{
Assert(pvBuffer);
Assert(cbBuffer >= VBOXVDMACMD_HEADER_SIZE());
if (!pvBuffer)
return VERR_INVALID_PARAMETER;
if (cbBuffer < VBOXVDMACMD_HEADER_SIZE())
return VERR_INVALID_PARAMETER;
PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pvBuffer;
uint32_t cbCmd = 0;
switch (pCmd->enmType)
{
case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
{
#ifdef VBOXWDDM_TEST_UHGSMI
static int count = 0;
static uint64_t start, end;
if (count==0)
{
start = RTTimeNanoTS();
}
++count;
if (count==100000)
{
end = RTTimeNanoTS();
float ems = (end-start)/1000000.f;
LogRel(("100000 calls took %i ms, %i cps\n", (int)ems, (int)(100000.f*1000.f/ems) ));
}
#endif
/* todo: post the buffer to chromium */
return VINF_SUCCESS;
}
case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
{
const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
int cbBlt = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer);
Assert(cbBlt >= 0);
Assert((uint32_t)cbBlt <= cbBuffer);
if (cbBlt >= 0)
{
if ((uint32_t)cbBlt == cbBuffer)
return VINF_SUCCESS;
else
{
cbBuffer -= (uint32_t)cbBlt;
pvBuffer -= cbBlt;
}
}
else
return cbBlt; /* error */
break;
}
case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER:
{
const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
int cbTransfer = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, cbBuffer);
Assert(cbTransfer >= 0);
Assert((uint32_t)cbTransfer <= cbBuffer);
if (cbTransfer >= 0)
{
if ((uint32_t)cbTransfer == cbBuffer)
return VINF_SUCCESS;
else
{
cbBuffer -= (uint32_t)cbTransfer;
pvBuffer -= cbTransfer;
}
}
else
return cbTransfer; /* error */
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
return VINF_SUCCESS;
case VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ:
return VINF_SUCCESS;
default:
AssertBreakpoint();
return VERR_INVALID_FUNCTION;
}
} while (1);
/* we should not be here */
AssertBreakpoint();
return VERR_INVALID_STATE;
}
static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
{
PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
PVGASTATE pVGAState = pVdma->pVGAState;
VBVAEXHOSTCONTEXT *pCmdVbva = &pVdma->CmdVbva;
PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
uint8_t *pCmd;
uint32_t cbCmd;
int rc = VBoxVDMAThreadNotifyConstructSucceeded(&pVdma->Thread);
if (!RT_SUCCESS(rc))
{
WARN(("VBoxVDMAThreadNotifyConstructSucceeded failed %d\n", rc));
return rc;
}
while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread))
{
VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pCmd, &cbCmd);
switch (enmType)
{
case VBVAEXHOST_DATA_TYPE_CMD:
vboxVDMACrCmdProcess(pVdma, pCmd, cbCmd);
VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd);
VBVARaiseIrqNoWait(pVGAState, 0);
break;
case VBVAEXHOST_DATA_TYPE_HOSTCTL:
rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd);
VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
break;
case VBVAEXHOST_DATA_TYPE_GUESTCTL:
rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd);
VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
break;
case VBVAEXHOST_DATA_TYPE_NO_DATA:
rc = VBoxVDMAThreadEventWait(&pVdma->Thread, RT_INDEFINITE_WAIT);
AssertRC(rc);
break;
default:
WARN(("unexpected type %d\n", enmType));
break;
}
}
return VINF_SUCCESS;
}
static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd)
{
PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
const uint8_t * pvBuf;
PGMPAGEMAPLOCK Lock;
int rc;
bool bReleaseLocked = false;
do
{
PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
pvBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t);
else if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
{
uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
pvBuf = pvRam + pCmd->Location.offVramBuf;
}
else
{
RTGCPHYS phPage = pCmd->Location.phBuf & ~0xfffULL;
uint32_t offset = pCmd->Location.phBuf & 0xfff;
Assert(offset + pCmd->cbBuf <= 0x1000);
if (offset + pCmd->cbBuf > 0x1000)
{
/* @todo: more advanced mechanism of command buffer proc is actually needed */
rc = VERR_INVALID_PARAMETER;
break;
}
const void * pvPageBuf;
rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPageBuf, &Lock);
AssertRC(rc);
if (!RT_SUCCESS(rc))
{
/* @todo: if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */
break;
}
pvBuf = (const uint8_t *)pvPageBuf;
pvBuf += offset;
bReleaseLocked = true;
}
rc = vboxVDMACmdExec(pVdma, pvBuf, pCmd->cbBuf);
AssertRC(rc);
if (bReleaseLocked)
PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
} while (0);
pCmd->rc = rc;
rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
AssertRC(rc);
}
static void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd)
{
PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
pCmd->i32Result = VINF_SUCCESS;
int rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
AssertRC(rc);
}
#ifdef VBOX_VDMA_WITH_WATCHDOG
static DECLCALLBACK(void) vboxVDMAWatchDogTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
VBOXVDMAHOST *pVdma = (VBOXVDMAHOST *)pvUser;
PVGASTATE pVGAState = pVdma->pVGAState;
VBVARaiseIrq(pVGAState, HGSMIHOSTFLAGS_WATCHDOG);
}
static int vboxVDMAWatchDogCtl(struct VBOXVDMAHOST *pVdma, uint32_t cMillis)
{
PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
if (cMillis)
TMTimerSetMillies(pVdma->WatchDogTimer, cMillis);
else
TMTimerStop(pVdma->WatchDogTimer);
return VINF_SUCCESS;
}
#endif
int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements)
{
int rc;
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ(RT_OFFSETOF(VBOXVDMAHOST, CmdPool.aCmds[cPipeElements]));
#else
PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ(sizeof(*pVdma));
#endif
Assert(pVdma);
if (pVdma)
{
pVdma->pHgsmi = pVGAState->pHGSMI;
pVdma->pVGAState = pVGAState;
#ifdef VBOX_VDMA_WITH_WATCHDOG
rc = PDMDevHlpTMTimerCreate(pVGAState->pDevInsR3, TMCLOCK_REAL, vboxVDMAWatchDogTimer,
pVdma, TMTIMER_FLAGS_NO_CRIT_SECT,
"VDMA WatchDog Timer", &pVdma->WatchDogTimer);
AssertRC(rc);
#endif
rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
if (RT_SUCCESS(rc))
{
rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma);
if (RT_SUCCESS(rc))
{
pVGAState->pVdma = pVdma;
#ifdef VBOX_WITH_CRHGSMI
int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
#endif
return VINF_SUCCESS;
}
else
WARN(("VBoxVDMAThreadCreate faile %d\n", rc));
VBoxVBVAExHSTerm(&pVdma->CmdVbva);
}
else
WARN(("VBoxVBVAExHSInit faile %d\n", rc));
RTMemFree(pVdma);
}
else
rc = VERR_OUT_OF_RESOURCES;
return rc;
}
int vboxVDMAReset(struct VBOXVDMAHOST *pVdma)
{
VBVAEXHOSTCTL Ctl;
Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_RESET;
int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
if (!RT_SUCCESS(rc))
{
WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc));
return rc;
}
return VINF_SUCCESS;
}
int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma)
{
VBVAEXHOSTCTL Ctl;
Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_TERM;
int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
if (!RT_SUCCESS(rc))
{
WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc));
return rc;
}
VBoxVDMAThreadTerm(&pVdma->Thread);
VBoxVBVAExHSTerm(&pVdma->CmdVbva);
RTMemFree(pVdma);
return VINF_SUCCESS;
}
int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM)
{
#ifdef VBOX_WITH_CRHGSMI
PVGASTATE pVGAState = pVdma->pVGAState;
PVBOXVDMACMD_CHROMIUM_CTL pCmd = (PVBOXVDMACMD_CHROMIUM_CTL)vboxVDMACrCtlCreate(
VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN, sizeof (*pCmd));
Assert(pCmd);
if (pCmd)
{
int rc = vboxVDMACrCtlPost(pVGAState, pCmd, sizeof (*pCmd));
AssertRC(rc);
if (RT_SUCCESS(rc))
{
rc = vboxVDMACrCtlGetRc(pCmd);
}
vboxVDMACrCtlRelease(pCmd);
return rc;
}
return VERR_NO_MEMORY;
#else
return VINF_SUCCESS;
#endif
}
int vboxVDMASaveStateExecDone(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM)
{
#ifdef VBOX_WITH_CRHGSMI
PVGASTATE pVGAState = pVdma->pVGAState;
PVBOXVDMACMD_CHROMIUM_CTL pCmd = (PVBOXVDMACMD_CHROMIUM_CTL)vboxVDMACrCtlCreate(
VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END, sizeof (*pCmd));
Assert(pCmd);
if (pCmd)
{
int rc = vboxVDMACrCtlPost(pVGAState, pCmd, sizeof (*pCmd));
AssertRC(rc);
if (RT_SUCCESS(rc))
{
rc = vboxVDMACrCtlGetRc(pCmd);
}
vboxVDMACrCtlRelease(pCmd);
return rc;
}
return VERR_NO_MEMORY;
#else
return VINF_SUCCESS;
#endif
}
void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd)
{
#if 1
PHGSMIINSTANCE pIns = pVdma->pHgsmi;
switch (pCmd->enmCtl)
{
case VBOXVDMA_CTL_TYPE_ENABLE:
pCmd->i32Result = VINF_SUCCESS;
break;
case VBOXVDMA_CTL_TYPE_DISABLE:
pCmd->i32Result = VINF_SUCCESS;
break;
case VBOXVDMA_CTL_TYPE_FLUSH:
pCmd->i32Result = VINF_SUCCESS;
break;
#ifdef VBOX_VDMA_WITH_WATCHDOG
case VBOXVDMA_CTL_TYPE_WATCHDOG:
pCmd->i32Result = vboxVDMAWatchDogCtl(pVdma, pCmd->u32Offset);
break;
#endif
default:
AssertBreakpoint();
pCmd->i32Result = VERR_NOT_SUPPORTED;
}
int rc = VBoxSHGSMICommandComplete (pIns, pCmd);
AssertRC(rc);
#else
/* test asinch completion */
VBOXVDMACMD_SUBMIT_CONTEXT Context;
Context.pVdma = pVdma;
Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACTL;
Context.Cmd.u.pCtl = pCmd;
int rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
AssertRC(rc);
if (RT_SUCCESS(rc))
{
Assert(Context.bQueued);
if (Context.bQueued)
{
/* success */
return;
}
rc = VERR_OUT_OF_RESOURCES;
}
/* failure */
Assert(RT_FAILURE(rc));
PHGSMIINSTANCE pIns = pVdma->pHgsmi;
pCmd->i32Result = rc;
int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
AssertRC(tmpRc);
#endif
}
void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd)
{
int rc = VERR_NOT_IMPLEMENTED;
#ifdef VBOX_WITH_CRHGSMI
/* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline
* this is why we process them specially */
rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd);
if (rc == VINF_SUCCESS)
return;
if (RT_FAILURE(rc))
{
pCmd->rc = rc;
rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmd);
AssertRC(rc);
return;
}
#endif
#ifndef VBOX_VDMA_WITH_WORKERTHREAD
vboxVDMACommandProcess(pVdma, pCmd, cbCmd);
#else
# ifdef DEBUG_misha
Assert(0);
# endif
VBOXVDMACMD_SUBMIT_CONTEXT Context;
Context.pVdma = pVdma;
Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACMD;
Context.Cmd.u.pDr = pCmd;
rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
AssertRC(rc);
if (RT_SUCCESS(rc))
{
Assert(Context.bQueued);
if (Context.bQueued)
{
/* success */
return;
}
rc = VERR_OUT_OF_RESOURCES;
}
/* failure */
Assert(RT_FAILURE(rc));
PHGSMIINSTANCE pIns = pVdma->pHgsmi;
pCmd->rc = rc;
int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
AssertRC(tmpRc);
#endif
}
/**/
static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
{
int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete);
if (RT_SUCCESS(rc))
{
if (rc == VINF_SUCCESS)
return VBoxVDMAThreadEventNotify(&pVdma->Thread);
else
Assert(rc == VINF_ALREADY_INITIALIZED);
}
else
WARN(("VBoxVBVAExHCtlSubmit failed %d\n", rc));
return rc;
}
static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
{
PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext;
VBOXCMDVBVA_CTL *pGCtl = (VBOXCMDVBVA_CTL*)(pCtl->u.cmd.pu8Cmd - sizeof (VBOXCMDVBVA_CTL));
AssertRC(rc);
pGCtl->i32Result = rc;
Assert(pVdma->pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pGCtl);
AssertRC(rc);
VBoxVBVAExHCtlFree(pVbva, pCtl);
}
static int vdmaVBVACtlOpaqueSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
{
VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE);
if (!pHCtl)
{
WARN(("VBoxVBVAExHCtlCreate failed\n"));
return VERR_NO_MEMORY;
}
pHCtl->u.cmd.pu8Cmd = pu8Cmd;
pHCtl->u.cmd.cbCmd = cbCmd;
int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, enmSource, pfnComplete, pvComplete);
if (!RT_SUCCESS(rc))
{
WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc));
return rc;;
}
return VINF_SUCCESS;
}
static int vdmaVBVACtlOpaqueGuestSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
{
Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL));
VBoxSHGSMICommandMarkAsynchCompletion(pCtl);
int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma);
if (RT_SUCCESS(rc))
return VINF_SUCCESS;
WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc));
pCtl->i32Result = rc;
rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
AssertRC(rc);
return VINF_SUCCESS;
}
static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion)
{
VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd;
if (pVboxCtl->pfnInternal)
((PFNCRCTLCOMPLETION)pVboxCtl->pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion);
VBoxVBVAExHCtlFree(pVbva, pCtl);
}
static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
PFNCRCTLCOMPLETION pfnCompletion,
void *pvCompletion)
{
pCmd->pfnInternal = (void(*)())pfnCompletion;
int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST_ENABLED, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
if (!RT_SUCCESS(rc))
{
if (rc == VERR_INVALID_STATE)
{
pCmd->pfnInternal = NULL;
PVGASTATE pVGAState = pVdma->pVGAState;
rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion);
if (!RT_SUCCESS(rc))
WARN(("pfnCrHgsmiControlProcess failed %d\n", rc));
return rc;
}
WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc));
return rc;
}
return VINF_SUCCESS;
}
static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
{
VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE);
if (!pHCtl)
{
WARN(("VBoxVBVAExHCtlCreate failed\n"));
return VERR_NO_MEMORY;
}
pHCtl->u.cmd.pu8Cmd = (uint8_t*)&pEnable->Enable;
pHCtl->u.cmd.cbCmd = sizeof (pEnable->Enable);
int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, VBVAEXHOSTCTL_SOURCE_GUEST, pfnComplete, pvComplete);
if (!RT_SUCCESS(rc))
{
WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc));
return rc;;
}
return VINF_SUCCESS;
}
static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable)
{
VBoxSHGSMICommandMarkAsynchCompletion(&pEnable->Hdr);
int rc = vdmaVBVACtlEnableDisableSubmitInternal(pVdma, pEnable, vboxCmdVBVACmdCtlGuestCompletion, pVdma);
if (RT_SUCCESS(rc))
return VINF_SUCCESS;
WARN(("vdmaVBVACtlEnableDisableSubmitInternal failed %d\n", rc));
pEnable->Hdr.i32Result = rc;
rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, &pEnable->Hdr);
AssertRC(rc);
return VINF_SUCCESS;
}
static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
{
VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvContext;
pData->rc = rc;
rc = RTSemEventSignal(pData->hEvent);
if (!RT_SUCCESS(rc))
WARN(("RTSemEventSignal failed %d\n", rc));
}
static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource)
{
VDMA_VBVA_CTL_CYNC_COMPLETION Data;
Data.rc = VERR_NOT_IMPLEMENTED;
int rc = RTSemEventCreate(&Data.hEvent);
if (!RT_SUCCESS(rc))
{
WARN(("RTSemEventCreate failed %d\n", rc));
return rc;
}
rc = vdmaVBVACtlSubmit(pVdma, pCtl, enmSource, vdmaVBVACtlSubmitSyncCompletion, &Data);
if (RT_SUCCESS(rc))
{
rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT);
if (RT_SUCCESS(rc))
{
rc = Data.rc;
if (!RT_SUCCESS(rc))
WARN(("vdmaVBVACtlSubmitSyncCompletion returned %d\n", rc));
}
else
WARN(("RTSemEventWait failed %d\n", rc));
}
else
WARN(("vdmaVBVACtlSubmit failed %d\n", rc));
RTSemEventDestroy(Data.hEvent);
return rc;
}
static int vdmaVBVAPause(PVBOXVDMAHOST pVdma)
{
VBVAEXHOSTCTL Ctl;
Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE;
return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
}
static int vdmaVBVAResume(PVBOXVDMAHOST pVdma)
{
VBVAEXHOSTCTL Ctl;
Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME;
return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
}
static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma)
{
int rc = VBoxVBVAExHSCheckCommands(&pVdma->CmdVbva);
switch (rc)
{
case VINF_SUCCESS:
return VBoxVDMAThreadEventNotify(&pVdma->Thread);
case VINF_ALREADY_INITIALIZED:
case VINF_EOF:
case VERR_INVALID_STATE:
return VINF_SUCCESS;
default:
Assert(!RT_FAILURE(rc));
return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
}
}
int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface,
struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
PFNCRCTLCOMPLETION pfnCompletion,
void *pvCompletion)
{
PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
return vdmaVBVACtlOpaqueHostSubmit(pVdma, pCmd, cbCmd, pfnCompletion, pvCompletion);
}
int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
{
struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
int rc = VINF_SUCCESS;
switch (pCtl->u32Type)
{
case VBOXCMDVBVACTL_TYPE_3DCTL:
return vdmaVBVACtlOpaqueGuestSubmit(pVdma, pCtl, cbCtl);
case VBOXCMDVBVACTL_TYPE_ENABLE:
if (cbCtl != sizeof (VBOXCMDVBVA_CTL_ENABLE))
{
WARN(("incorrect enable size\n"));
rc = VERR_INVALID_PARAMETER;
break;
}
return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE*)pCtl);
default:
WARN(("unsupported type\n"));
rc = VERR_INVALID_PARAMETER;
break;
}
pCtl->i32Result = rc;
rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
AssertRC(rc);
return VINF_SUCCESS;
}
int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState)
{
if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
{
WARN(("vdma VBVA is disabled\n"));
return VERR_INVALID_STATE;
}
return vboxVDMACmdSubmitPerform(pVGAState->pVdma);
}
int vboxCmdVBVACmdFlush(PVGASTATE pVGAState)
{
WARN(("flush\n"));
if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
{
WARN(("vdma VBVA is disabled\n"));
return VERR_INVALID_STATE;
}
return vboxVDMACmdSubmitPerform(pVGAState->pVdma);
}
void vboxCmdVBVACmdTimer(PVGASTATE pVGAState)
{
if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
return;
vboxVDMACmdSubmitPerform(pVGAState->pVdma);
}