static IMG_INT PVRSRVBridgeEventObjectWait(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_EVENTOBJECTWAIT *psEventObjectWaitIN, PVRSRV_BRIDGE_OUT_EVENTOBJECTWAIT *psEventObjectWaitOUT, CONNECTION_DATA *psConnection) { IMG_HANDLE hOSEventKMInt = IMG_NULL; IMG_HANDLE hOSEventKMInt2 = IMG_NULL; PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAIT); { /* Look up the address from the handle */ psEventObjectWaitOUT->eError = PVRSRVLookupHandle(psConnection->psHandleBase, (IMG_HANDLE *) &hOSEventKMInt2, psEventObjectWaitIN->hOSEventKM, PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT); if(psEventObjectWaitOUT->eError != PVRSRV_OK) { goto EventObjectWait_exit; } /* Look up the data from the resman address */ psEventObjectWaitOUT->eError = ResManFindPrivateDataByPtr(hOSEventKMInt2, (IMG_VOID **) &hOSEventKMInt); if(psEventObjectWaitOUT->eError != PVRSRV_OK) { goto EventObjectWait_exit; } } psEventObjectWaitOUT->eError = OSEventObjectWait( hOSEventKMInt); EventObjectWait_exit: return 0; }
static PVRSRV_ERROR DoTLStreamReserve(IMG_HANDLE hStream, IMG_UINT8 **ppui8Data, IMG_UINT32 ui32ReqSize, IMG_UINT32 ui32ReqSizeMin, PVRSRVTL_PACKETTYPE ePacketType, IMG_UINT32* pui32AvSpace) { PTL_STREAM psTmp; IMG_UINT32 *ui32Buf, ui32LRead, ui32LWrite, ui32LPending, lReqSizeAligned, lReqSizeActual; IMG_INT pad, iFreeSpace; PVR_DPF_ENTERED; if (pui32AvSpace) *pui32AvSpace = 0; if (( IMG_NULL == hStream )) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } psTmp = (PTL_STREAM)hStream; /* Assert used as the packet type parameter is currently only provided * by the TL APIs, not the calling client */ PVR_ASSERT((PVRSRVTL_PACKETTYPE_UNDEF < ePacketType) && (PVRSRVTL_PACKETTYPE_LAST >= ePacketType)); /* The buffer is only used in "rounded" (aligned) chunks */ lReqSizeAligned = PVRSRVTL_ALIGN(ui32ReqSize); /* Get a local copy of the stream buffer parameters */ ui32LRead = psTmp->ui32Read ; ui32LWrite = psTmp->ui32Write ; ui32LPending = psTmp->ui32Pending ; /* Multiple pending reserves are not supported. */ if ( NOTHING_PENDING != ui32LPending ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY); } if ( IMG_UINT16_MAX < lReqSizeAligned ) { psTmp->ui32Pending = NOTHING_PENDING; if (pui32AvSpace) { *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin); } PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL); } /* Prevent other threads from entering this region before we are done. * Not exactly a lock... */ psTmp->ui32Pending = 0; /* If there is enough contiguous space following the current Write * position then no padding is required */ if ( psTmp->ui32Size < ui32LWrite + lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) ) { pad = psTmp->ui32Size - ui32LWrite; } else { pad = 0 ; } lReqSizeActual = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) + pad ; /* If this is a blocking reserve and there is not enough space then wait. */ if( psTmp->bBlock ) { if( psTmp->ui32Size < lReqSizeActual ) { psTmp->ui32Pending = NOTHING_PENDING; PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE); } while ( ( cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size) <(IMG_INT) lReqSizeActual ) ) { OSEventObjectWait(psTmp->hProducerEvent); // update local copies. ui32LRead = psTmp->ui32Read ; ui32LWrite = psTmp->ui32Write ; } } /* The easy case: buffer has enough space to hold the requested packet (data + header) */ iFreeSpace = cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size); if ( iFreeSpace >=(IMG_INT) lReqSizeActual ) { if ( pad ) { /* Inserting padding packet. */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_PADDING(pad-sizeof(PVRSRVTL_PACKETHDR)) ; /* CAUTION: the used pad value should always result in a properly * aligned ui32LWrite pointer, which in this case is 0 */ ui32LWrite = (ui32LWrite + pad) % psTmp->ui32Size; /* Detect unaligned pad value */ PVR_ASSERT( ui32LWrite == 0); } /* Insert size-stamped packet header */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_HDR(ui32ReqSize, ePacketType); /* return the next position in the buffer to the user */ *ppui8Data = &psTmp->pbyBuffer[ ui32LWrite+sizeof(PVRSRVTL_PACKETHDR) ] ; /* update pending offset: size stamp + data */ ui32LPending = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) ; } /* The not so easy case: not enough space, decide how to handle data */ else { #if defined(DEBUG) /* Sanity check that the user is not trying to add more data than the * buffer size. Conditionally compile it out to ensure this check has * no impact to release performance */ if ( lReqSizeAligned+sizeof(PVRSRVTL_PACKETHDR) > psTmp->ui32Size ) { psTmp->ui32Pending = NOTHING_PENDING; PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE); } #endif /* No data overwriting, insert write_failed flag and return */ if (psTmp->bDrop) { /* Caller should not try to use ppui8Data, * NULLify to give user a chance of avoiding memory corruption */ ppui8Data = IMG_NULL; /* This flag should not be inserted two consecutive times, so * check the last ui32 in case it was a packet drop packet. */ ui32Buf = ui32LWrite ? (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite - sizeof(PVRSRVTL_PACKETHDR)] : // Previous four bytes are not guaranteed to be a packet header... (IMG_UINT32*)&psTmp->pbyBuffer[psTmp->ui32Size - PVRSRVTL_PACKET_ALIGNMENT]; if ( PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED != GET_PACKET_TYPE( (PVRSRVTL_PACKETHDR*)ui32Buf ) ) { /* Insert size-stamped packet header */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_WRITE_FAILED ; ui32LWrite += sizeof(PVRSRVTL_PACKETHDR); iFreeSpace -= sizeof(PVRSRVTL_PACKETHDR); } psTmp->ui32Write = ui32LWrite; psTmp->ui32Pending = NOTHING_PENDING; if (pui32AvSpace) { *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin); } PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL); } } /* Update stream. */ psTmp->ui32Write = ui32LWrite ; psTmp->ui32Pending = ui32LPending ; PVR_DPF_RETURN_OK; }