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;
}
Ejemplo n.º 2
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;
}