DevVGA_VDMA.cpp revision 44781fa4af04336dd2b4651ea9fe7726e3494882
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Video DMA (VDMA) support.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Copyright (C) 2006-2012 Oracle Corporation
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * available from http://www.virtualbox.org. This file is free software;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * General Public License (GPL) as published by the Free Software
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#define WARN_BP() do { } while (0)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync } while (0)
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef DECLCALLBACKPTR(void, PFNVBOXVDMATHREAD_CHANGED)(struct VBOXVDMATHREAD *pThread, int rc, void *pvThreadContext, void *pvChangeContext);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(int) vboxCmdVBVACmdCallout(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd, VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry, PFNVBOXCRCMDCTL_CALLOUT_CB pfnCb);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* state transformations:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * submitter | processor
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * LISTENING ---> PROCESSING
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* critical section for accessing ctl lists */
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef enum
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * see mor edetailed comments in headers for function definitions */
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef enum
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(int) vdmaVBVANotifyDisable(PVGASTATE pVGAState);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHCtlAlloc(VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return (VBVAEXHOSTCTL*)RTMemCacheAlloc(pCmdVbva->CtlCache);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return (VBVAEXHOSTCTL*)RTMemAlloc(sizeof (VBVAEXHOSTCTL));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHCtlFree(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl)
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHCtlCreate(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL_TYPE enmType)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAEXHOSTCTL* pCtl = VBoxVBVAExHCtlAlloc(pCmdVbva);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsyncstatic int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva)
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync if (ASMAtomicCmpXchgS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING))
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsyncstatic VBVAEXHOSTCTL* vboxVBVAExHPCheckCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, bool *pfHostCtl, bool fHostOnlyMode)
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if(!fHostOnlyMode && !ASMAtomicUoReadU32(&pCmdVbva->u32cCtls))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAEXHOSTCTL* pCtl = RTListGetFirst(&pCmdVbva->HostCtlList, VBVAEXHOSTCTL, Node);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCtl = RTListGetFirst(&pCmdVbva->GuestCtlList, VBVAEXHOSTCTL, Node);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* pCtl can not be null here since pCmdVbva->u32cCtls is not null,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * and there are no HostCtl commands*/
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOSTCTL* VBoxVBVAExHPCheckHostCtlOnDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bool fHostCtl = false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAEXHOSTCTL* pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostCtl, true);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHPPause(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pCmdVbva->i32EnableState < VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHPResume(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pCmdVbva->i32EnableState != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic bool vboxVBVAExHPCheckProcessCtlInternal(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxVBVAExHPDataCompleteCtl(pCmdVbva, pCtl, VINF_SUCCESS);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return true;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxVBVAExHPDataCompleteCtl(pCmdVbva, pCtl, VINF_SUCCESS);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return true;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* No records to process. Return without assigning output variables. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* A new record need to be processed. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* the record is being recorded, try again */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* the record is being recorded, try again */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we should not get partial commands here actually */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* The size of largest contiguous chunk in the ring biffer. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* The pointer to data in the ring buffer. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* Fetch or point the data. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* The command does not cross buffer boundary. Return address in the buffer. */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel(("CmdVbva: cross-bound writes unsupported\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pVBVA->off32Data = (pVBVA->off32Data + cbCmd) % pVBVA->cbData;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCtl->pfnComplete(pCmdVbva, pCtl, rc, pCtl->pvComplete);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostClt, false);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!vboxVBVAExHPCheckProcessCtlInternal(pCmdVbva, pCtl))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) <= VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("Warning: vboxVBVAExHCmdGet returned unexpected status %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAEXHOST_DATA_TYPE enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 1. we check the queue -> and it is empty
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 2. submitter adds command to the queue
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 4. we clear the "processing" state
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 6. if the queue appears to be not-empty set the "processing" state back to "true"
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we are the processor now */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(bool) vboxVBVAExHSHasCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return true;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* Checks whether the new commands are ready for processing
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * 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)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VINF_EOF - no commands in a queue
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VINF_ALREADY_INITIALIZED - another thread already processing the commands
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VERR_INVALID_STATE - the VBVA is paused or pausing */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we are the processor now */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = RTMemCacheCreate(&pCmdVbva->CtlCache, sizeof (VBVAEXHOSTCTL),
a299266cddc1ae14d76d725a660bb278816bc151vboxsync 0, /* size_t cbAlignment */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync 0 /* uint32_t fFlags*/
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCmdVbva->i32State = VBVAEXHOSTCONTEXT_STATE_PROCESSING;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCmdVbva->i32EnableState = VBVAEXHOSTCONTEXT_ESTATE_DISABLED;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(bool) VBoxVBVAExHSIsEnabled(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(bool) VBoxVBVAExHSIsDisabled(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) == VBVAEXHOSTCONTEXT_ESTATE_DISABLED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_DISABLED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* ensure the processor is stopped */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* ensure no one tries to submit the command */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVBVAExHSSaveGuestCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = SSMR3PutU32(pSSM, (uint32_t)(pCtl->u.cmd.pu8Cmd - pu8VramBase));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVBVAExHSSaveStateLocked(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync RTListForEach(&pCmdVbva->GuestCtlList, pCtl, VBVAEXHOSTCTL, Node)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVBVAExHSSaveGuestCtl(pCmdVbva, pCtl, pu8VramBase, pSSM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* Saves state
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVBVAExHSSaveStateLocked(pCmdVbva, pu8VramBase, pSSM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVBVAExHSSaveStateLocked failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVBVAExHSLoadGuestCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(pCmdVbva, (VBVAEXHOSTCTL_TYPE)u32);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync RTListAppend(&pCmdVbva->GuestCtlList, &pHCtl->Node);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVBVAExHSLoadStateLocked(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVBVAExHSLoadGuestCtl(pCmdVbva, pu8VramBase, pSSM, u32Version);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* Loads state
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVBVAExHSLoadStateLocked(pCmdVbva, pu8VramBase, pSSM, u32Version);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVBVAExHSSaveStateLocked failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef enum
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node);
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef struct VBOXVDMAHOST
a299266cddc1ae14d76d725a660bb278816bc151vboxsync// VBOXVDMA_SOURCE aSources[VBOX_VIDEO_MAX_SCREENS];
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncvoid VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pThread->u32State == VBOXVDMATHREAD_STATE_CREATING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PFNVBOXVDMATHREAD_CHANGED pfnChanged = pThread->pfnChanged;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_CREATED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pfnChanged(pThread, VINF_SUCCESS, pvThreadContext, pvChanged);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncvoid VBoxVDMAThreadNotifyTerminatingSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PFNVBOXVDMATHREAD_CHANGED pfnChanged = pThread->pfnChanged;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pfnChanged(pThread, VINF_SUCCESS, pvThreadContext, pvChanged);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return ASMAtomicUoReadU32(&pThread->u32State) == VBOXVDMATHREAD_STATE_TERMINATING;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t u32State = ASMAtomicUoReadU32(&pThread->u32State);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncint VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread, PFNVBOXVDMATHREAD_CHANGED pfnCreated, void*pvCreated)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = RTThreadCreate(&pThread->hWorkerThread, pfnThread, pvThread, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(int) VBoxVDMAThreadEventNotify(PVBOXVDMATHREAD pThread)
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(int) VBoxVDMAThreadEventWait(PVBOXVDMATHREAD pThread, RTMSINTERVAL cMillies)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = RTSemEventWait(pThread->hEvent, cMillies);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncint VBoxVDMAThreadTerm(PVBOXVDMATHREAD pThread, PFNVBOXVDMATHREAD_CHANGED pfnTerminated, void*pvTerminated, bool fNotify)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t u32State = ASMAtomicUoReadU32(&pThread->u32State);
1828a998092cf8316a49329fdbcb1449b511b66avboxsync ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("thread is marked to termination or terminated\nn"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* wait till the thread creation is completed */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync } while (1);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource);
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext);
a299266cddc1ae14d76d725a660bb278816bc151vboxsynctypedef FNVBOXVDMACRCTL_CALLBACK *PFNVBOXVDMACRCTL_CALLBACK;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync} VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, *PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#define VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(_p) ((PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd)))
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic PVBOXVDMACMD_CHROMIUM_CTL vboxVDMACrCtlCreate(VBOXVDMACMD_CHROMIUM_CTL_TYPE enmCmd, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = (PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)RTMemAllocZ(cbCmd + RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(void) vboxVDMACrCtlRelease (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(void) vboxVDMACrCtlRetain (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncDECLINLINE(int) vboxVDMACrCtlGetRc (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbSetEvent(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbReleaseCmd(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrCtlPostAsync (PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd, PFNVBOXVDMACRCTL_CALLBACK pfnCompletion, void *pvCompletion)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pVGAState->pDrv->pfnCrHgsmiControlProcess(pVGAState->pDrv, pCmd, cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACrCtlPostAsync(pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* the command is completed */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(void) vboxVDMACrHgcmSubmitSyncCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvCompletion;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrHgcmSubmitSync(struct VBOXVDMAHOST *pVdma, VBOXCRCMDCTL* pCtl, uint32_t cbCtl)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCtl, cbCtl, vboxVDMACrHgcmSubmitSyncCompletion, &Data);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("pfnCrHgcmCtlSubmit command failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vdmaVBVACtlDisableSync(PVBOXVDMAHOST pVdma)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vdmaVBVACtlSubmitSync(pVdma, &HCtl, VBVAEXHOSTCTL_SOURCE_HOST);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync vgaUpdateDisplayAll(pVdma->pVGAState, /* fFailOnResize = */ false);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(uint8_t*) vboxVDMACrHgcmHandleEnableRemainingHostCommand(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hClient, uint32_t *pcbCtl, int prevCmdRc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* disable VBVA, all subsequent host commands will go HGCM way */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxVBVAExHPDataCompleteCtl(&pVdma->CmdVbva, pVdma->pCurRemainingHostCtl, prevCmdRc);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pVdma->pCurRemainingHostCtl = VBoxVBVAExHPCheckHostCtlOnDisable(&pVdma->CmdVbva);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *pcbCtl = pVdma->pCurRemainingHostCtl->u.cmd.cbCmd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(void) vboxVDMACrHgcmNotifyTerminatingDoneCb(HVBOXCRCMDCTL_NOTIFY_TERMINATING hClient)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pVdma->CmdVbva.i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pVdma->Thread.u32State == VBOXVDMATHREAD_STATE_TERMINATING);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic DECLCALLBACK(int) vboxVDMACrHgcmNotifyTerminatingCb(HVBOXCRCMDCTL_NOTIFY_TERMINATING hClient, VBOXCRCMDCTL_HGCMENABLE_DATA *pHgcmEnableData)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync HCtl.enmType = VBVAEXHOSTCTL_TYPE_HH_ON_HGCM_UNLOAD;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vdmaVBVACtlSubmitSync(pVdma, &HCtl, VBVAEXHOSTCTL_SOURCE_HOST);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pHgcmEnableData->pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand;
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrHgcmHandleEnable(struct VBOXVDMAHOST *pVdma)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Enable.Data.pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVDMACrHgcmSubmitSync(pVdma, &Enable.Hdr, sizeof (Enable));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vdmaVBVAEnableProcess(struct VBOXVDMAHOST *pVdma, uint32_t u32Offset)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pVdma->pHgsmi, u32Offset);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Disable.Data.pfnNotifyTerm = vboxVDMACrHgcmNotifyTerminatingCb;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Disable.Data.pfnNotifyTermDone = vboxVDMACrHgcmNotifyTerminatingDoneCb;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACrHgcmSubmitSync(pVdma, &Disable.Hdr, sizeof (Disable));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vdmaVBVADisableProcess(struct VBOXVDMAHOST *pVdma, bool fDoHgcmEnable)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = pVdma->CrSrvInfo.pfnDisable(pVdma->CrSrvInfo.hSvr);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* disable is a bit tricky
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * we need to ensure the host ctl commands do not come out of order
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * and do not come over HGCM channel until after it is enabled */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrHostCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd, bool *pfContinue)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return pVdma->CrSrvInfo.pfnHostCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VBoxVDMAThreadTerm(&pVdma->Thread, NULL, NULL, false);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = VBoxVDMAThreadTerm(&pVdma->Thread, NULL, NULL, true);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = VBoxVBVAExHSSaveState(&pVdma->CmdVbva, pu8VramBase, pCmd->u.state.pSSM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return pVdma->CrSrvInfo.pfnSaveState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = VBoxVBVAExHSLoadState(&pVdma->CmdVbva, pu8VramBase, pCmd->u.state.pSSM, pCmd->u.state.u32Version);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = pVdma->CrSrvInfo.pfnLoadState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM, pCmd->u.state.u32Version);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync for (uint32_t i = 0; i < pVGAState->cMonitors; ++i)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = VBVAGetInfoViewAndScreen(pVGAState, i, &CurView, &CurScreen);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("VBVAGetInfoViewAndScreen failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("unexpected host ctl type %d\n", pCmd->enmType));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrGuestCtlResizeEntryProcess(struct VBOXVDMAHOST *pVdma, VBOXCMDVBVA_RESIZE_ENTRY *pEntry)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bool fDisable = false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync memcpy(aTargetMap, pEntry->aTargetMap, sizeof (aTargetMap));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ASMBitClearRange(aTargetMap, pVGAState->cMonitors, VBOX_VIDEO_MAX_SCREENS);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Screen.u16Flags = VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("0xffffffff view index only valid for disable requests\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync View.u32ViewSize = Screen.u32LineSize * Screen.u32Height + Screen.u32StartOffset;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync View.u32MaxScreenSize = View.u32ViewSize + Screen.u32Width + 1; /* <- make VBVAInfoScreen logic (offEnd < pView->u32MaxScreenSize) happy */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = pVdma->CrSrvInfo.pfnResize(pVdma->CrSrvInfo.hSvr, &Screen, aTargetMap);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync for (int i = ASMBitFirstSet(aTargetMap, pVGAState->cMonitors);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync i = ASMBitNextSet(aTargetMap, pVGAState->cMonitors, i))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = VBVAGetInfoViewAndScreen(pVGAState, i, &CurView, &CurScreen);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!memcmp(&Screen, &CurScreen, sizeof (CurScreen)))
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrGuestCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return pVdma->CrSrvInfo.pfnGuestCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cElements = cbCmd / sizeof (VBOXCMDVBVA_RESIZE_ENTRY);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXCMDVBVA_RESIZE *pResize = (VBOXCMDVBVA_RESIZE*)pCmd->u.cmd.pu8Cmd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXCMDVBVA_RESIZE_ENTRY *pEntry = &pResize->aEntries[i];
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACrGuestCtlResizeEntryProcess(pVdma, pEntry);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrGuestCtlResizeEntryProcess failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBVAENABLE *pEnable = (VBVAENABLE *)pCmd->u.cmd.pu8Cmd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (enmType == VBVAEXHOSTCTL_TYPE_GHH_ENABLE_PAUSED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* do vgaUpdateDisplayAll right away */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync vgaUpdateDisplayAll(pVdma->pVGAState, /* fFailOnResize = */ false);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VBoxVDMAThreadTerm(&pVdma->Thread, NULL, NULL, false);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param fIn - whether this is a page in or out op.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * the direction is VRA#M - related, so fIn == true - transfer to VRAM); false - transfer from VRAM
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, VBOXCMDVBVAPAGEIDX iPage, uint8_t *pu8Vram, bool fIn)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const void * pvPage;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPage, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvPage, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrCmdVbvaProcessPagingEls(PPDMDEVINS pDevIns, const VBOXCMDVBVAPAGEIDX *piPages, uint32_t cPages, uint8_t *pu8Vram, bool fIn)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync for (uint32_t i = 0; i < cPages; ++i, pu8Vram += PAGE_SIZE)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVDMACrCmdVbvaProcessPagingEl(pDevIns, piPages[i], pu8Vram, fIn);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrCmdVbvaProcessPagingEl failed %d", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int8_t vboxVDMACrCmdVbvaPagingDataInit(PVGASTATE pVGAState, const VBOXCMDVBVA_HDR *pHdr, const VBOXCMDVBVA_PAGING_TRANSFER_DATA *pData, uint32_t cbCmd,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const VBOXCMDVBVAPAGEIDX **ppPages, VBOXCMDVBVAPAGEIDX *pcPages,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXCMDVBVAPAGEIDX cPages = cbCmd - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, Data.aPageNumbers);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXCMDVBVAOFFSET offVRAM = pData->Alloc.u.offVRAM;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("offVRAM address is not on page boundary\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const VBOXCMDVBVAPAGEIDX *pPages = pData->aPageNumbers;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint8_t *pu8VramMax = pu8VramBase + pVGAState->vram_size;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (~(~(VBOXCMDVBVAPAGEIDX)0 >> PAGE_SHIFT) & cPages)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (offVRAM + ((VBOXCMDVBVAOFFSET)cPages << PAGE_SHIFT) >= pVGAState->vram_size)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("invalid cPages %d, exceeding vram size", cPages));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bool fIn = !!(pHdr->u8Flags & VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int8_t vboxVDMACrCmdVbvaPagingFill(PVGASTATE pVGAState, VBOXCMDVBVA_PAGING_FILL *pFill)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("offVRAM address is not on page boundary\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint8_t *pu8VramMax = pu8VramBase + pVGAState->vram_size;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t *pu32Vram = (uint32_t*)(pu8VramBase + offVRAM);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int8_t vboxVDMACrCmdVbvaProcessCmdData(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int8_t i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, &((VBOXCMDVBVA_PAGING_TRANSFER*)pCmd)->Data, cbCmd,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pPages, cPages, pu8Vram, fIn);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return vboxVDMACrCmdVbvaPagingFill(pVGAState, (VBOXCMDVBVA_PAGING_FILL*)pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return pVdma->CrSrvInfo.pfnCmd(pVdma->CrSrvInfo.hSvr, pCmd, cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* for now can only contain offVRAM.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncAssertCompile(!(PAGE_SIZE % sizeof (VBOXCMDVBVAPAGEIDX)));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#define VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE (PAGE_SIZE / sizeof (VBOXCMDVBVA_SYSMEMEL))
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int8_t vboxVDMACrCmdVbvaProcess(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXCMDVBVA_SYSMEMCMD *pSysmemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pCmd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const void * pvCmd;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync Assert((phCmd & PAGE_OFFSET_MASK) == (((uintptr_t)pvCmd) & PAGE_OFFSET_MASK));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbCmdPart = PAGE_SIZE - (((uintptr_t)pvCmd) & PAGE_OFFSET_MASK);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint8_t i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pRealCmdHdr, cbRealCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync memcpy(((uint8_t*)(&Hdr)) + cbCmdPart, pvCmd, cbCmdPart);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pvCurCmdTail = (const void*)(((uint8_t*)pvCmd) + cbCmdPart);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (cbCurCmdTail > cbRealCmd - sizeof (*pRealCmdHdr))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pRealCmdHdr, (const VBOXCMDVBVA_PAGING_TRANSFER_DATA*)pvCurCmdTail, cbRealCmd,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we need to break, not return, to ensure currently locked page is released */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("command is not alligned properly %d", cbCurCmdTail));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we need to break, not return, to ensure currently locked page is released */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cCurPages = cbCurCmdTail / sizeof (VBOXCMDVBVAPAGEIDX);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pPages, cCurPages, pu8Vram, fIn);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we need to break, not return, to ensure currently locked page is released */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pu8Vram += (VBOXCMDVBVAOFFSET)cCurPages << PAGE_SHIFT;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* the page is not locked, return */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync cCurPages = PAGE_SIZE / sizeof (VBOXCMDVBVAPAGEIDX);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync } while (1);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync for ( ; cbCmd; cbCmd -= cbCurCmd, pCmd = (VBOXCMDVBVA_HDR*)(((uint8_t*)pCmd) + cbCurCmd))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int8_t i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCurCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return vboxVDMACrCmdVbvaProcessCmdData(pVdma, pCmd, cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* check if the command is cancelled */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCmd->u.i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCmd->CrClientInfo.pfnCallout = vboxCmdVBVACmdCallout;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync memset(&pVdma->CrSrvInfo, 0, sizeof (pVdma->CrSrvInfo));
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* check if this is external cmd to be passed to chromium backend */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmdDr, uint32_t cbCmdDr)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (cbCmdDr < sizeof (*pCmdDr) + VBOXVDMACMD_HEADER_SIZE())
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (cbDmaCmd < cbCmdDr - sizeof (*pCmdDr) - VBOXVDMACMD_HEADER_SIZE())
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync VBOXVIDEOOFFSET offBuf = pCmdDr->Location.offVramBuf;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (offBuf + cbDmaCmd > pVdma->pVGAState->vram_size)
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync AssertMsgFailed(("invalid command buffer data from offset!"));
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync PVBOXVDMACMD_CHROMIUM_CMD pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync AssertMsgFailed(("invalid chromium command buffer size!"));
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd, cbBody);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync int tmpRc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync AssertMsgFailed(("invalid bpb transfer buffer size!"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof (*pTransfer));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncint vboxVDMACrHgsmiCommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXVDMACMD *pDmaHdr = VBOXVDMACMD_FROM_BODY(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBOXVDMACBUF_DR *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaHdr);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncint vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pCmdPrivate = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pCmdPrivate->pfnCompletion(pVGAState, pCmd, pCmdPrivate->pvCompletion);
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we do not support color conversion */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we do not support stretching */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offDstLineStart = pDstRectl->left * pDstDesc->bpp >> 3;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offDstLineEnd = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbDstLine = offDstLineEnd - offDstLineStart;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offSrcLineStart = pSrcRectl->left * pSrcDesc->bpp >> 3;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offSrcLineEnd = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t cbSrcLine = offSrcLineEnd - offSrcLineStart;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync for (uint32_t i = 0; ; ++i)
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pRectl1->width = x21 < x22 ? x22 - pRectl1->left : x21 - pRectl1->left;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pRectl1->height = x21 < x22 ? x22 - pRectl1->top : x21 - pRectl1->top;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /* we do not support stretching for now */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pBlt->srcRectl.height != pBlt->dstRectl.height)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dstRectl.left = pDstRectl->left + pBlt->dstRectl.left;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dstRectl.top = pDstRectl->top + pBlt->dstRectl.top;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync srcRectl.left = pSrcRectl->left + pBlt->srcRectl.left;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync srcRectl.top = pSrcRectl->top + pBlt->srcRectl.top;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const void * pvSrc;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bool bSrcLocked = false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bool bDstLocked = false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
bSrcLocked = true;
bDstLocked = true;
if (bSrcLocked)
if (bDstLocked)
} while (cbTransfer);
return sizeof (*pTransfer);
return rc;
if (!pvBuffer)
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
#ifdef VBOXWDDM_TEST_UHGSMI
static int count = 0;
if (count==0)
++count;
return VINF_SUCCESS;
if (cbBlt >= 0)
return VINF_SUCCESS;
const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
if (cbTransfer >= 0)
return VINF_SUCCESS;
case VBOXVDMACMD_TYPE_DMA_NOP:
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_INVALID_FUNCTION;
return VERR_INVALID_STATE;
int rc;
switch (enmType)
case VBVAEXHOST_DATA_TYPE_CMD:
bool fContinue = true;
if (fContinue)
return VINF_SUCCESS;
int rc;
bool bReleaseLocked = false;
const void * pvPageBuf;
bReleaseLocked = true;
if (bReleaseLocked)
#ifdef VBOX_VDMA_WITH_WATCHDOG
if (cMillis)
return VINF_SUCCESS;
int rc;
if (pVdma)
#ifdef VBOX_VDMA_WITH_WATCHDOG
#ifdef VBOX_WITH_CRHGSMI
int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
if (!pVdma)
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
case VBOXVDMA_CTL_TYPE_ENABLE:
case VBOXVDMA_CTL_TYPE_FLUSH:
#ifdef VBOX_VDMA_WITH_WATCHDOG
#ifdef VBOX_WITH_CRHGSMI
/* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline
#ifdef VBOX_WITH_CRHGSMI
static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext);
static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
return rc;
static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
static int vdmaVBVACtlGenericSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, VBVAEXHOSTCTL_TYPE enmType, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
if (!pHCtl)
return VERR_NO_MEMORY;
return rc;;
return VINF_SUCCESS;
static int vdmaVBVACtlGenericGuestSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_TYPE enmType, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, enmType, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma);
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion)
static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
void *pvCompletion)
int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion);
return rc;
return rc;
return VINF_SUCCESS;
for (uint32_t j = 0; j < i; j++)
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(void) vdmaVBVACtlThreadCreatedEnable(struct VBOXVDMATHREAD *pThread, int rc, void *pvThreadContext, void *pvContext)
static int vdmaVBVACtlEnableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, bool fPaused, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
int rc;
VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, fPaused ? VBVAEXHOSTCTL_TYPE_GHH_ENABLE_PAUSED : VBVAEXHOSTCTL_TYPE_GHH_ENABLE);
if (pHCtl)
rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma, vdmaVBVACtlThreadCreatedEnable, pHCtl);
return VINF_SUCCESS;
return rc;
return rc;
rc = vdmaVBVACtlEnableSubmitInternal(pVdma, &Enable, fPaused, vdmaVBVACtlSubmitSyncCompletion, &Data);
return rc;
static int vdmaVBVACtlDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
int rc;
return VINF_SUCCESS;
if (!pHCtl)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return rc;
static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
if (fEnable)
int rc = vdmaVBVACtlEnableDisableSubmitInternal(pVdma, &pEnable->Enable, vboxCmdVBVACmdCtlGuestCompletion, pVdma);
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource)
return rc;
return rc;
switch (rc)
case VINF_SUCCESS:
case VINF_ALREADY_INITIALIZED:
case VINF_EOF:
case VERR_INVALID_STATE:
return VINF_SUCCESS;
void *pvCompletion)
typedef struct VBOXCMDVBVA_CMDHOSTCTL_SYNC
int rc;
static DECLCALLBACK(void) vboxCmdVBVACmdHostCtlSyncCb(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
static DECLCALLBACK(int) vboxCmdVBVACmdCallout(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd, VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry, PFNVBOXCRCMDCTL_CALLOUT_CB pfnCb)
return rc;
VBOXCRCMDCTL_CALLOUT_LISTENTRY* pEntry = RTListGetFirst(&pCmd->CalloutList.List, VBOXCRCMDCTL_CALLOUT_LISTENTRY, Node);
if (pEntry)
if (!pEntry)
return rc;
return rc;
Assert(c >= 0);
return rc;
return VINF_SUCCESS;
return VERR_INVALID_STATE;
return VERR_INVALID_STATE;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
return rc;
#ifdef DEBUG_misha
if (pCmd)
return rc;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
return rc;
#ifdef DEBUG_misha
if (pCmd)
return rc;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
int rc;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRHGSMI
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
return VERR_VERSION_MISMATCH;
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRHGSMI
return VINF_SUCCESS;
/** @todo r=bird: BTW. would be great if you put in a couple of comments here and there explaining what
if (!pHCtl)
return VERR_NO_MEMORY;
return rc;
return VINF_SUCCESS;