VBoxVideoShgsmi.cpp revision 974de75a5a0c1d17919acfe706ebd403d9dcc440
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan/*
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * Copyright (C) 2010 Sun Microsystems, Inc.
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan *
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * This file is part of VirtualBox Open Source Edition (OSE), as
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * available from http://www.virtualbox.org. This file is free software;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * you can redistribute it and/or modify it under the terms of the GNU
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * General Public License (GPL) as published by the Free Software
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * Foundation, in version 2 as it comes in the "COPYING" file of the
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan *
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * Clara, CA 95054 USA or visit http://www.sun.com if you need
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan * additional information or have any questions.
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include "../VBoxVideo.h"
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include "../Helper.h"
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include <VBox/VBoxGuestLib.h>
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include <VBox/VBoxVideo.h>
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include <iprt/asm.h>
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include <iprt/semaphore.h>
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan#include "VBoxVideoShgsmi.h"
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan/* SHGSMI */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(uint8_t *) vboxSHGSMIBufferData (const PVBOXSHGSMIHEADER pHeader)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan return (uint8_t *)pHeader + sizeof (VBOXSHGSMIHEADER);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(PVBOXSHGSMIHEADER) vboxSHGSMIBufferHeader (const void *pvData)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan return (PVBOXSHGSMIHEADER)((uint8_t *)pvData - sizeof (VBOXSHGSMIHEADER));
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(void) vboxSHGSMICommandRetain (PVBOXSHGSMIHEADER pCmd)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan ASMAtomicIncU32(&pCmd->cRefs);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganvoid vboxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pCmd)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan HGSMIHeapFree (pHeap, pCmd);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(void) vboxSHGSMICommandRelease (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pCmd)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan Assert(cRefs < UINT32_MAX / 2);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan if(!cRefs)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandFree (pHeap, pCmd);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLCALLBACK(void) vboxSHGSMICompletionSetEvent(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan RTSemEventSignal((RTSEMEVENT)pvContext);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLCALLBACK(void) vboxSHGSMICompletionCommandRelease(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandRelease (pHeap, vboxSHGSMIBufferHeader(pvCmd));
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(void) vboxSHGSMICommandDoSubmit(struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan /* Initialize the buffer and get the offset for port IO. */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan /* Submit the buffer to the host. */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICbCommandWrite(pHeap, offBuffer);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan/* do not wait for completion */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk HoganDECLINLINE(void) vboxSHGSMICommandSubmitAsynch (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan /* ensure the command is not removed until we're processing it */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandRetain(pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandDoSubmit(pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan if(!(ASMAtomicReadU32((volatile uint32_t *)&pHeader->fFlags) & VBOXSHGSMI_FLAG_HG_ASYNCH))
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan {
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = (PFNVBOXSHGSMICMDCOMPLETION)pHeader->u64Info1;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pfnCompletion(pHeap, vboxSHGSMIBufferData (pHeader), (PVOID)pHeader->u64Info1);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan }
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandRelease(pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganvoid VBoxSHGSMICommandSubmitAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan PVBOXSHGSMIHEADER pHeader = vboxSHGSMIBufferHeader (pvBuff);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info1 = (uint64_t)vboxSHGSMICompletionSetEvent;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info2 = (uint64_t)hEventSem;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->fFlags = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganint VBoxSHGSMICommandSubmitSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan RTSEMEVENT hEventSem;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan int rc = RTSemEventCreate(&hEventSem);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan Assert(RT_SUCCESS(rc));
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan if (RT_SUCCESS(rc))
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan {
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan VBoxSHGSMICommandSubmitAsynchEvent (pHeap, pCmd, hEventSem);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan Assert(RT_SUCCESS(rc));
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan if (RT_SUCCESS(rc))
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan RTSemEventDestroy(hEventSem);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan }
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan return rc;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganvoid VBoxSHGSMICommandSubmitAsynch (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan PVBOXSHGSMIHEADER pHeader = vboxSHGSMIBufferHeader (pvBuff);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info1 = (uint64_t)pfnCompletion;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info2 = (uint64_t)pvCompletion;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->fFlags = fFlags;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganvoid VBoxSHGSMICommandSubmitAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan PVBOXSHGSMIHEADER pHeader = vboxSHGSMIBufferHeader (pvBuff);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info1 = (uint64_t)pfnCompletion;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->u64Info2 = (uint64_t)pvCompletion;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan pHeader->fFlags = fFlags;
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan}
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hoganvoid* VBoxSHGSMICommandAlloc (struct _HGSMIHEAP * pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan{
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan /* Issue the flush command. */
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan PVBOXSHGSMIHEADER pHeader = (PVBOXSHGSMIHEADER)HGSMIHeapAlloc (pHeap, cbData + sizeof (VBOXSHGSMIHEADER), u8Channel, u16ChannelInfo);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan Assert(pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan if (pHeader)
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan return vboxSHGSMIBufferData(pHeader);
883337f300b7ec221922c406e0c4dcee08a89e51Dirk Hogan return NULL;
}
void VBoxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, void *pvBuffer)
{
PVBOXSHGSMIHEADER pHeader = vboxSHGSMIBufferHeader(pvBuffer);
vboxSHGSMICommandRelease (pHeap, pHeader);
}
//int VBoxSHGSMISetup (PVBOXSHGSMIHEAP pHeap,
// void *pvBase,
// HGSMISIZE cbArea,
// HGSMIOFFSET offBase,
// bool fOffsetBased,
// PFNVBOXSHGSMINOTIFYHOST pfnNotifyHost,
// PFNVBOXSHGSMINOTIFYHOST pvNotifyHost)
//{
// /* Setup a HGSMI heap within the adapter information area. */
// return HGSMIHeapSetup (&pHeap->Heap,
// pvBuffer,
// cbBuffer,
// offBuffer,
// false /*fOffsetBased*/);
//}
//
//int VBoxSHGSMIDestroy (PVBOXSHGSMIHEAP pHeap)
//{
// HGSMIHeapDestroy (pHeap);
// return VINF_SUCCESS;
//}
#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXSHGSMILIST_ENTRY)&(_pCmd)->pvNext)
#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_OFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
int VBoxSHGSMICommandProcessCompletion (struct _HGSMIHEAP * pHeap, HGSMIOFFSET offCmd, bool bIrq, PVBOXSHGSMILIST pPostProcessList)
{
int rc = VINF_SUCCESS;
PVBOXSHGSMIHEADER pCur = (PVBOXSHGSMIHEADER)HGSMIOffsetToPointer (&pHeap->area, offCmd);
Assert(pCur);
if (pCur)
{
do
{
if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
{
Assert(bIrq);
PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
void *pvCompletion;
PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
void *pvCallback = (void*)pCur->u64Info2;
pfnCallback(pHeap, vboxSHGSMIBufferData(pCur), pvCallback, &pfnCompletion, &pvCompletion);
if (pfnCompletion)
{
pCur->u64Info1 = (uint64_t)pfnCompletion;
pCur->u64Info2 = (uint64_t)pvCompletion;
pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
}
else
{
/* nothing to do with this command */
break;
}
}
if (!bIrq)
{
PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
void *pvCallback = (void*)pCur->u64Info2;
pfnCallback(pHeap, vboxSHGSMIBufferData(pCur), pvCallback);
}
else
vboxSHGSMIListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
} while (0);
}
else
{
rc = VERR_INVALID_PARAMETER;
}
return rc;
}
int VBoxSHGSMICommandPostprocessCompletion (struct _HGSMIHEAP * pHeap, PVBOXSHGSMILIST pPostProcessList)
{
PVBOXSHGSMILIST_ENTRY pNext, pCur;
for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
{
/* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
pNext = pCur->pNext;
PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
void *pvCallback = (void*)pCmd->u64Info2;
pfnCallback(pHeap, pCmd, pvCallback);
}
return VINF_SUCCESS;
}