예제 #1
0
boolean CBcmPropertyTags::GetTag (u32 nTagId, void *pTag, unsigned nTagSize, unsigned nRequestParmSize)
{
	assert (pTag != 0);
	assert (nTagSize >= sizeof (TPropertyTagSimple));
	unsigned nBufferSize = sizeof (TPropertyBuffer) + nTagSize + sizeof (u32);
	assert ((nBufferSize & 3) == 0);

	// cannot use "new" here because this is used before mem_init() is called
	u8 Buffer[nBufferSize + 15];
	TPropertyBuffer *pBuffer = (TPropertyBuffer *) (((u32) Buffer + 15) & ~15);
	
	pBuffer->nBufferSize = nBufferSize;
	pBuffer->nCode = CODE_REQUEST;
	memcpy (pBuffer->Tags, pTag, nTagSize);
	
	TPropertyTag *pHeader = (TPropertyTag *) pBuffer->Tags;
	pHeader->nTagId = nTagId;
	pHeader->nValueBufSize = nTagSize - sizeof (TPropertyTag);
	pHeader->nValueLength = nRequestParmSize & ~VALUE_LENGTH_RESPONSE;

	u32 *pEndTag = (u32 *) (pBuffer->Tags + nTagSize);
	*pEndTag = PROPTAG_END;

	CleanDataCache ();
	DataSyncBarrier ();

	u32 nBufferAddress = GPU_MEM_BASE + (u32) pBuffer;
	if (m_MailBox.WriteRead (nBufferAddress) != nBufferAddress)
	{
		return FALSE;
	}
	
	InvalidateDataCache ();
	DataSyncBarrier ();

	if (pBuffer->nCode != CODE_RESPONSE_SUCCESS)
	{
		return FALSE;
	}
	
	if (!(pHeader->nValueLength & VALUE_LENGTH_RESPONSE))
	{
		return FALSE;
	}
	
	pHeader->nValueLength &= ~VALUE_LENGTH_RESPONSE;
	if (pHeader->nValueLength == 0)
	{
		return FALSE;
	}

	memcpy (pTag, pBuffer->Tags, nTagSize);

	return TRUE;
}
예제 #2
0
void CDWHCIDevice::ChannelInterruptHandler (unsigned nChannel)
{
	CDWHCITransferStageData *pStageData = m_pStageData[nChannel];
	assert (pStageData != 0);
	CUSBRequest *pURB = pStageData->GetURB ();
	assert (pURB != 0);

	switch (pStageData->GetSubState ())
	{
	case StageSubStateWaitForChannelDisable:
		StartChannel (pStageData);
		return;

	case StageSubStateWaitForTransactionComplete: {
		CleanDataCache ();
		InvalidateDataCache ();
		DataMemBarrier ();

		CDWHCIRegister TransferSize (DWHCI_HOST_CHAN_XFER_SIZ (nChannel));
		TransferSize.Read ();

		CDWHCIRegister ChanInterrupt (DWHCI_HOST_CHAN_INT (nChannel));

		assert (   !pStageData->IsPeriodic ()
			||    DWHCI_HOST_CHAN_XFER_SIZ_PID (TransferSize.Get ())
			   != DWHCI_HOST_CHAN_XFER_SIZ_PID_MDATA);

		pStageData->TransactionComplete (ChanInterrupt.Read (),
			DWHCI_HOST_CHAN_XFER_SIZ_PACKETS (TransferSize.Get ()),
			TransferSize.Get () & DWHCI_HOST_CHAN_XFER_SIZ_BYTES__MASK);
		} break;
	
	default:
		assert (0);
		break;
	}
	
	unsigned nStatus;
	
	switch (pStageData->GetState ())
	{
	case StageStateNoSplitTransfer:
		nStatus = pStageData->GetTransactionStatus ();
		if (nStatus & DWHCI_HOST_CHAN_INT_ERROR_MASK)
		{
			CLogger::Get ()->Write (FromDWHCI, LogError,
						"Transaction failed (status 0x%X)", nStatus);

			pURB->SetStatus (0);
		}
		else if (   (nStatus & (DWHCI_HOST_CHAN_INT_NAK | DWHCI_HOST_CHAN_INT_NYET))
			 && pStageData->IsPeriodic ())
		{
			pStageData->SetState (StageStatePeriodicDelay);

			unsigned nInterval = pURB->GetEndpoint ()->GetInterval ();

			m_pTimer->StartKernelTimer (MSEC2HZ (nInterval), TimerStub, pStageData, this);

			break;
		}
		else
		{
			if (!pStageData->IsStatusStage ())
			{
				pURB->SetResultLen (pStageData->GetResultLen ());
			}

			pURB->SetStatus (1);
		}
		
		DisableChannelInterrupt (nChannel);

		delete pStageData;
		m_pStageData[nChannel] = 0;

		FreeChannel (nChannel);

		pURB->CallCompletionRoutine ();
		break;

	case StageStateStartSplit:
		nStatus = pStageData->GetTransactionStatus ();
		if (   (nStatus & DWHCI_HOST_CHAN_INT_ERROR_MASK)
		    || (nStatus & DWHCI_HOST_CHAN_INT_NAK)
		    || (nStatus & DWHCI_HOST_CHAN_INT_NYET))
		{
			CLogger::Get ()->Write (FromDWHCI, LogError,
						"Transaction failed (status 0x%X)", nStatus);

			pURB->SetStatus (0);

			DisableChannelInterrupt (nChannel);

			delete pStageData;
			m_pStageData[nChannel] = 0;

			FreeChannel (nChannel);

			pURB->CallCompletionRoutine ();
			break;
		}

		pStageData->GetFrameScheduler ()->TransactionComplete (nStatus);

		pStageData->SetState (StageStateCompleteSplit);
		pStageData->SetSplitComplete (TRUE);

		if (!pStageData->GetFrameScheduler ()->CompleteSplit ())
		{
			goto LeaveCompleteSplit;
		}
		
		StartTransaction (pStageData);
		break;
		
	case StageStateCompleteSplit:
		nStatus = pStageData->GetTransactionStatus ();
		if (nStatus & DWHCI_HOST_CHAN_INT_ERROR_MASK)
		{
			CLogger::Get ()->Write (FromDWHCI, LogError,
						"Transaction failed (status 0x%X)", nStatus);

			pURB->SetStatus (0);

			DisableChannelInterrupt (nChannel);

			delete pStageData;
			m_pStageData[nChannel] = 0;

			FreeChannel (nChannel);

			pURB->CallCompletionRoutine ();
			break;
		}
		
		pStageData->GetFrameScheduler ()->TransactionComplete (nStatus);

		if (pStageData->GetFrameScheduler ()->CompleteSplit ())
		{
			StartTransaction (pStageData);
			break;
		}

	LeaveCompleteSplit:
		if (!pStageData->IsStageComplete ())
		{
			if (!pStageData->BeginSplitCycle ())
			{
				pURB->SetStatus (0);

				DisableChannelInterrupt (nChannel);

				delete pStageData;
				m_pStageData[nChannel] = 0;

				FreeChannel (nChannel);

				pURB->CallCompletionRoutine ();
				break;
			}

			if (!pStageData->IsPeriodic ())
			{
				pStageData->SetState (StageStateStartSplit);
				pStageData->SetSplitComplete (FALSE);
				pStageData->GetFrameScheduler ()->StartSplit ();

				StartTransaction (pStageData);
			}
			else
			{
				pStageData->SetState (StageStatePeriodicDelay);

				unsigned nInterval = pURB->GetEndpoint ()->GetInterval ();

				m_pTimer->StartKernelTimer (MSEC2HZ (nInterval),
							    TimerStub, pStageData, this);
			}
			break;
		}

		DisableChannelInterrupt (nChannel);

		if (!pStageData->IsStatusStage ())
		{
			pURB->SetResultLen (pStageData->GetResultLen ());
		}
		pURB->SetStatus (1);

		delete pStageData;
		m_pStageData[nChannel] = 0;

		FreeChannel (nChannel);

		pURB->CallCompletionRoutine ();
		break;

	default:
		assert (0);
		break;
	}
}
예제 #3
0
void CDWHCIDevice::StartChannel (CDWHCITransferStageData *pStageData)
{
	assert (pStageData != 0);
	unsigned nChannel = pStageData->GetChannelNumber ();
	assert (nChannel < m_nChannels);
	
	pStageData->SetSubState (StageSubStateWaitForTransactionComplete);

	// reset all pending channel interrupts
	CDWHCIRegister ChanInterrupt (DWHCI_HOST_CHAN_INT (nChannel));
	ChanInterrupt.SetAll ();
	ChanInterrupt.Write ();
	
	// set transfer size, packet count and pid
	CDWHCIRegister TransferSize (DWHCI_HOST_CHAN_XFER_SIZ (nChannel), 0);
	TransferSize.Or (pStageData->GetBytesToTransfer () & DWHCI_HOST_CHAN_XFER_SIZ_BYTES__MASK);
	TransferSize.Or ((pStageData->GetPacketsToTransfer () << DWHCI_HOST_CHAN_XFER_SIZ_PACKETS__SHIFT)
			 & DWHCI_HOST_CHAN_XFER_SIZ_PACKETS__MASK);
	TransferSize.Or (pStageData->GetPID () << DWHCI_HOST_CHAN_XFER_SIZ_PID__SHIFT);
	TransferSize.Write ();

	// set DMA address
	CDWHCIRegister DMAAddress (DWHCI_HOST_CHAN_DMA_ADDR (nChannel),
				   pStageData->GetDMAAddress () + GPU_MEM_BASE);
	DMAAddress.Write ();

	CleanDataCache ();
	InvalidateDataCache ();
	DataMemBarrier ();

	// set split control
	CDWHCIRegister SplitControl (DWHCI_HOST_CHAN_SPLIT_CTRL (nChannel), 0);
	if (pStageData->IsSplit ())
	{
		SplitControl.Or (pStageData->GetHubPortAddress ());
		SplitControl.Or (   pStageData->GetHubAddress ()
				 << DWHCI_HOST_CHAN_SPLIT_CTRL_HUB_ADDRESS__SHIFT);
		SplitControl.Or (   pStageData->GetSplitPosition ()
				 << DWHCI_HOST_CHAN_SPLIT_CTRL_XACT_POS__SHIFT);
		if (pStageData->IsSplitComplete ())
		{
			SplitControl.Or (DWHCI_HOST_CHAN_SPLIT_CTRL_COMPLETE_SPLIT);
		}
		SplitControl.Or (DWHCI_HOST_CHAN_SPLIT_CTRL_SPLIT_ENABLE);
	}
	SplitControl.Write ();

	// set channel parameters
	CDWHCIRegister Character (DWHCI_HOST_CHAN_CHARACTER (nChannel));
	Character.Read ();
	Character.And (~DWHCI_HOST_CHAN_CHARACTER_MAX_PKT_SIZ__MASK);
	Character.Or (pStageData->GetMaxPacketSize () & DWHCI_HOST_CHAN_CHARACTER_MAX_PKT_SIZ__MASK);

	Character.And (~DWHCI_HOST_CHAN_CHARACTER_MULTI_CNT__MASK);
	Character.Or (1 << DWHCI_HOST_CHAN_CHARACTER_MULTI_CNT__SHIFT);		// TODO: optimize

	if (pStageData->IsDirectionIn ())
	{
		Character.Or (DWHCI_HOST_CHAN_CHARACTER_EP_DIRECTION_IN);
	}
	else
	{
		Character.And (~DWHCI_HOST_CHAN_CHARACTER_EP_DIRECTION_IN);
	}

	if (pStageData->GetSpeed () == USBSpeedLow)
	{
		Character.Or (DWHCI_HOST_CHAN_CHARACTER_LOW_SPEED_DEVICE);
	}
	else
	{
		Character.And (~DWHCI_HOST_CHAN_CHARACTER_LOW_SPEED_DEVICE);
	}

	Character.And (~DWHCI_HOST_CHAN_CHARACTER_DEVICE_ADDRESS__MASK);
	Character.Or (pStageData->GetDeviceAddress () << DWHCI_HOST_CHAN_CHARACTER_DEVICE_ADDRESS__SHIFT);

	Character.And (~DWHCI_HOST_CHAN_CHARACTER_EP_TYPE__MASK);
	Character.Or (pStageData->GetEndpointType () << DWHCI_HOST_CHAN_CHARACTER_EP_TYPE__SHIFT);

	Character.And (~DWHCI_HOST_CHAN_CHARACTER_EP_NUMBER__MASK);
	Character.Or (pStageData->GetEndpointNumber () << DWHCI_HOST_CHAN_CHARACTER_EP_NUMBER__SHIFT);

	CDWHCIFrameScheduler *pFrameScheduler = pStageData->GetFrameScheduler ();
	if (pFrameScheduler != 0)
	{
		pFrameScheduler->WaitForFrame ();

		if (pFrameScheduler->IsOddFrame ())
		{
			Character.Or (DWHCI_HOST_CHAN_CHARACTER_PER_ODD_FRAME);
		}
		else
		{
			Character.And (~DWHCI_HOST_CHAN_CHARACTER_PER_ODD_FRAME);
		}
	}

	CDWHCIRegister ChanInterruptMask (DWHCI_HOST_CHAN_INT_MASK(nChannel));
	ChanInterruptMask.Set (pStageData->GetStatusMask ());
	ChanInterruptMask.Write ();
	
	Character.Or (DWHCI_HOST_CHAN_CHARACTER_ENABLE);
	Character.And (~DWHCI_HOST_CHAN_CHARACTER_DISABLE);
	Character.Write ();
}
예제 #4
0
파일: kernel.cpp 프로젝트: jsanchezv/circle
TShutdownMode CKernel::Run (void)
{
	m_Logger.Write (FromKernel, LogNotice, "Compile time: " __DATE__ " " __TIME__);

	unsigned nSamples = m_Screen.GetWidth ();
	assert (nSamples > 0);
	
	unsigned *pBuffer = new unsigned[nSamples];
	if (pBuffer == 0)
	{
		m_Logger.Write (FromKernel, LogPanic, "Not enough memory");
	}

	CleanDataCache ();
	InvalidateDataCache ();

	unsigned nRunTime = Sampler (pBuffer, nSamples, 0, 0, SAMPLING_DELAY);
	if (nRunTime == 0)
	{
		m_Logger.Write (FromKernel, LogPanic, "Measurement of run time failed, try again!");
	}

	unsigned nSampleRateKHz = 1000 * nSamples / nRunTime;
	m_Logger.Write (FromKernel, LogNotice, "Sampling rate was %u KHz", nSampleRateKHz);
	m_Logger.Write (FromKernel, LogNotice, "Display covers %u us", nRunTime);
	m_Logger.Write (FromKernel, LogNotice, "A red line is drawn on every 10 us");

	unsigned nPosYLow  = m_Screen.GetHeight () / 2 + 40;
	unsigned nPosYHigh = m_Screen.GetHeight () / 2 - 40;

	boolean bLastLevel = FALSE;
	unsigned nLastMarker = 0;
	for (unsigned nSample = 0; nSample < nSamples; nSample++)
	{
		unsigned nTime = nRunTime * nSample / nSamples / 10;
		if (nLastMarker != nTime)
		{
			for (unsigned nPosY = nPosYHigh-20; nPosY <= nPosYLow+20; nPosY++)
			{
				m_Screen.SetPixel (nSample, nPosY, HIGH_COLOR);
			}

			nLastMarker = nTime;
		}

		assert (pBuffer != 0);
		boolean bThisLevel = pBuffer[nSample] & GPIO_INPUT_PIN_MASK ? TRUE : FALSE;

		unsigned nPosY = bThisLevel ? nPosYHigh : nPosYLow;
		m_Screen.SetPixel (nSample, nPosY,   NORMAL_COLOR);
		m_Screen.SetPixel (nSample, nPosY+1, NORMAL_COLOR);
		m_Screen.SetPixel (nSample, nPosY+2, NORMAL_COLOR);

		if (   nSample > 0
		    && bLastLevel != bThisLevel)
		{
			for (unsigned nPosY = nPosYHigh; nPosY <= nPosYLow+2; nPosY++)
			{
				m_Screen.SetPixel (nSample, nPosY, NORMAL_COLOR);
			}
		}

		bLastLevel = bThisLevel;
	}

	delete pBuffer;
	
	return ShutdownHalt;
}