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; }
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; } }
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 (); }
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; }