⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp1161hc.cpp

📁 ISP1161 USB Driver under WinCE for StrongARM processor implementation
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	m_ITLTransferLen		= 0;

	for (UINT index =0; index < m_TdsPutToITLIndex; index++)
	{
		paCurITd = m_TdsPutToITL[index];
		pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);
		
		SDevice *pDev;
		SEndpoint *pEndpt;
		SEndpointDescriptor *pEndptDesc;
    
		EnterCriticalSection(&m_csDeviceListLock);
		pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
		LeaveCriticalSection(&m_csDeviceListLock);

		ASSERT(pDev);

		EnterCriticalSection(&pDev->csAccessingEndpointArray);
		pEndpt = pDev->ppEndpts[
				(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
		LeaveCriticalSection(&pDev->csAccessingEndpointArray);

		ASSERT(pEndpt);

		pEndptDesc = pEndpt->pEd;

		LONG iRelativeNumber = (LONG)uFrameNumber - (LONG)pCurITd->bfStartFrame;

		if((iRelativeNumber < 0))
		{
			break; //break out from this loop
		}
		else if (iRelativeNumber > (LONG)pCurITd->bfFrameCount)
		{
			break; //should break out this endpoint only
		}
		

		//Calcalate the length according to spec page 25

		LONG dwBufferLen;

		ULONG uspaEndingBuffer = 0;
		ULONG uspaStartingBuffer = 0;
								
		if (pCurITd->offsetPsw[iRelativeNumber] == pCurITd->offsetPsw[iRelativeNumber+1] )
		{
			dwBufferLen = 0;
		}
		else
		{
			//Staring address
			if (pCurITd->offsetPsw[iRelativeNumber] & 0x1000)
				uspaStartingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
			else
				uspaStartingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
			uspaStartingBuffer |= pCurITd->offsetPsw[iRelativeNumber] & 0xFFF;

			//Ending address
				
			if (iRelativeNumber < (LONG)pCurITd->bfFrameCount) //not the last one
			{
				ULONG temp = pCurITd->offsetPsw[iRelativeNumber + 1] -1;
				if(temp & 0x1000)
					uspaEndingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
				else
					uspaEndingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
				uspaEndingBuffer |= temp & 0xFFF;
			}
			else
			{
				uspaEndingBuffer = pCurITd->paBufferEnd;
			}
						
			dwBufferLen = (LONG)(uspaEndingBuffer & 0xFFF) - (LONG)(uspaStartingBuffer & 0xFFF);

			if ( (uspaStartingBuffer & 0xFFFFF000) != (uspaEndingBuffer & 0xFFFFF000))
				dwBufferLen += 4096;
				
			dwBufferLen += 1;

			if (dwBufferLen == 0x1040)
			{
				WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x8888);
				WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x9999);
			}

			/*===================================================================/
				Alignment of 4 bytes, If there are more than 1 PTD in ATL buffer,
				the next should be alignment in 4 bytes
			====================================================================*/
			if (index < m_TdsPutToITLIndex -1)
			{
				if (dwBufferLen %4)
				{
					USHORT dwPayLoad = 4 - dwBufferLen % 4;
					m_ITLTransferLen += dwPayLoad;
				}
			}


		}
		m_ITLTransferLen += dwBufferLen + sizeof(SPhilipsTransferDescriptor);


		//As it turned out, this stack doesn't calculate correctly
		//when crossing 4k boundary. I have to apply page 27 of 
		//OHCI to check offsetPsw[R] and offsetPsw[R+1] to skip
		//this offset if smaller
		
		if (iRelativeNumber < (LONG)pCurITd->bfFrameCount) 
		{
			if (pCurITd->offsetPsw[iRelativeNumber + 1] < pCurITd->offsetPsw[iRelativeNumber]) 
				m_ITLTransferLen = 0;
		}
		else
		{
			if (pCurITd->offsetPsw[pCurITd->bfFrameCount] <pCurITd->offsetPsw[ pCurITd->bfFrameCount]) 
				m_ITLTransferLen = 0;
		}
	}

	/*=====================================================================/
		Break out from this loop if nothing to dump, No need, since 
		all the above cases that can cause m_ITLLengh is 0 has been break
		already.
	/=====================================================================*/
	if (m_ITLTransferLen == 0)
	{
		return;
	}

	/*=====================================================================/
			Prepare Transfer counter
	/=====================================================================*/
		
	WRITE_REGISTER_USHORT(HcWRTransCounter(m_regBase), (USHORT)m_ITLTransferLen); 
		
	/*=====================================================================/
		Go through the array and push them one by one to ITL  
	/=====================================================================*/
	WRITE_PORT_USHORT((PUSHORT)(m_regBase+2), 0xc0);	
		
	for (index =0; index < m_TdsPutToITLIndex; index++)
	{
			
		paCurITd = m_TdsPutToITL[index];
		pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);

		SDevice *pDev;
		SEndpoint *pEndpt;
		SEndpointDescriptor *pEndptDesc;
    
		EnterCriticalSection(&m_csDeviceListLock);
		pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
		LeaveCriticalSection(&m_csDeviceListLock);

		ASSERT(pDev);

		EnterCriticalSection(&pDev->csAccessingEndpointArray);
		pEndpt = pDev->ppEndpts[
				(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
		LeaveCriticalSection(&pDev->csAccessingEndpointArray);

		ASSERT(pEndpt);

		pEndptDesc = pEndpt->pEd;

		//Depending on OHCD spec page 101 to calcuate length, m_ITLTransferLen

		LONG iRelativeNumber = (LONG)uFrameNumber - (LONG)pCurITd->bfStartFrame;
			
		LONG	dwBufferLen = 0;

		ULONG	uspaEndingBuffer;
		ULONG	uspaStartingBuffer;
								
		if (pCurITd->offsetPsw[iRelativeNumber] == pCurITd->offsetPsw[iRelativeNumber+1] )
		{
			dwBufferLen = 0;
		}
		else
		{
			//Staring address
			if (pCurITd->offsetPsw[iRelativeNumber] & 0x1000)
				uspaStartingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
			else
				uspaStartingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
			uspaStartingBuffer |= pCurITd->offsetPsw[iRelativeNumber] & 0xFFF;

			//Ending address
			if (iRelativeNumber < (LONG)pCurITd->bfFrameCount) //not the last one
			{
				
				ULONG temp = pCurITd->offsetPsw[iRelativeNumber + 1] -1;
				if(temp & 0x1000)
					uspaEndingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
				else
					uspaEndingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
				uspaEndingBuffer |= temp & 0xFFF;
			}
			else
			{
				uspaEndingBuffer = pCurITd->paBufferEnd;
			}
						
			dwBufferLen = (LONG)(uspaEndingBuffer & 0xFFF) - (LONG)(uspaStartingBuffer & 0xFFF);

			if ( (uspaStartingBuffer & 0xFFFFF000) != (uspaEndingBuffer & 0xFFFFF000))
				dwBufferLen += 4096;
			
			dwBufferLen += 1;

		}
				
		//ExecuteUSBTransanction 
		UCHAR dwEndpointType = pEndpt->endptType;	

		SPhilipsTransferDescriptor		sPTD;
			
		sPTD.bActualBytes		= 0;
		
		sPTD.bfToggle = pEndpt->fPhcdToggleBit;
	
		sPTD.bfActive			= 1; //Start the transfer
		sPTD.bCompletionCode    = 0;
			
		sPTD.bMaxPacketSize		= pEndptDesc->bfMaxPacketSize; //Lost the MSB
//		sPTD.bMaxPacketSize		= 64; //Lost the MSB

		sPTD.bfSpeed			= pEndptDesc->bfIsLowSpeed;

//		sPTD.bfLastTd			= pCurGTd->bfLastTd;
					
		if (index == m_TdsPutToITLIndex -1)
			sPTD.bfLastTd			= 1;
		else
			sPTD.bfLastTd			= 0;

		sPTD.bEndpointNumber	= pEndptDesc->bfEndpointNumber;
			
		sPTD.bTotalBytes		= dwBufferLen;

		sPTD.bfPID				= pEndptDesc->bfDirection;
		sPTD.bTokenOnce			= 0; //Not applicable
		sPTD.bfAddr				= pCurITd->paBufferPage0 & gcITdAddrMask;
		sPTD.bFormat			= pEndptDesc->bfIsIsochronous;
		sPTD.bUnused1			= 0;
		sPTD.bUnused2			= 0;
		sPTD.bUnused3			= 0;

		/*=====================================================================/
				Send the PTD and the data inside TD to ATL 
		/======================================================================*/

		UINT i;
		PUSHORT pData;
		PUSHORT psPTDData;

		//PTD structure 
		psPTDData = (PUSHORT)(&sPTD);
							
		for (i = 0; i< sizeof(SPhilipsTransferDescriptor)/sizeof(USHORT); i++)
			WRITE_PORT_USHORT((PUSHORT)m_regBase, *(psPTDData+i));
											
		//Data in the TD 
		if ( dwBufferLen > 0) 
		{
			pData = (PUSHORT)m_pobMem->PaToVa(uspaStartingBuffer);
			// dwBufferLen += 1, In odd case, we add one more byte. 
			for (i=0;  i< (dwBufferLen + 1)/sizeof(USHORT); i++)
			{
				WRITE_PORT_USHORT((PUSHORT)m_regBase, *(pData + i));
			}

			/*=====================================================================/
				Send Alignment (4 bytes) data to ATL buffer 
			/======================================================================*/
			if (index < m_TdsPutToITLIndex -1)
			{
				if (dwBufferLen %4)
				{
					DWORD dwPayLoad = 4 - dwBufferLen % 4;
					for (i=0; i< dwPayLoad/sizeof(USHORT); i++)
					{
						WRITE_PORT_USHORT((PUSHORT)m_regBase, 0);
					}
				}
			}
		
		}

/*
		WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x8888);
		WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x9999);
*/

		RETAILMSG(0,
			(TEXT("PHCD::PTD(s) %d, ITL TD[%d] 0x%08X -> [%d], m_ITLTransferLen %04X\r\n"), 
			m_TdsPutToITLIndex, iRelativeNumber, paCurITd, index,  m_ITLTransferLen));

	}//End of For loop

}



VOID CPhcd::CheckITLList(PULONG p_TdsPutToITLIndex, ULONG m_TdsPutToITL[], PULONG pInterrupts)
{

	//Quit1 if we don't want have to process it.

	if( *p_TdsPutToITLIndex == 0)
		return;

	SIsochTransferDescriptor*		pCurITd;
	ULONG							paCurITd;

	uFrameNumber = *HccaFrameNumber(m_pHcca);

	RETAILMSG(ISP1161DBG, 
			(TEXT("PHCD: CheckITLList, uFramNumber,0x%08X \r\n"), uFrameNumber));

	for ( UINT index =0; index<*p_TdsPutToITLIndex; index++)
	{
		paCurITd = m_TdsPutToITL[index];
		pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);
		
		SDevice *pDev;
		SEndpoint *pEndpt;
		SEndpointDescriptor* pEndptDesc;

		EnterCriticalSection(&m_csDeviceListLock);
		pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
		LeaveCriticalSection(&m_csDeviceListLock);

		ASSERT(pDev);

		EnterCriticalSection(&pDev->csAccessingEndpointArray);
		pEndpt = pDev->ppEndpts[
			(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
		LeaveCriticalSection(&pDev->csAccessingEndpointArray);

		pEndptDesc = pEndpt->pEd;

		//Quit2: if we haven't reached to the end of bfFrameCount

		/*==============================================================
			In the FrameNumber turn around time, We need do some trick. 
			Well, as it turned out, this has become a big headache. Cause
			as uFrameNumber turn around 0xFFFF, I don't know whether this
			Frame is just bigger than bfStartFrame, or the transfer haven't
			started, just user choose a big startFrame. I wonder how the
			OHCI does this job.
			Another issue is OS thread schedule delay, by the time this 
			CheckITLList is called, we may miss a lot of frames already.
			So, I add a value 1000. That means even this CheckITLList is
			called 1000 frame later, we will still clean this ITD.
		===============================================================*/
	
		if ((pCurITd->bfStartFrame + pCurITd->bfFrameCount +1) >= 0xFFFF)
		{
			if (uFrameNumber <= 
				pCurITd->bfStartFrame + pCurITd->bfFrameCount +1 - 0xFFFF + 1000)
				uFrameNumber += 0xFFFF;
		}

		//Plus 1 is because ITL be processed after the frame it is dumped.
		if (uFrameNumber <= pCurITd->bfStartFrame + pCurITd->bfFrameCount + 1)
			return;
			
		//Time to put TD back.
		pCurITd->bfConditionCode = 0;
		
		/*================================================================/
			(2), update Endpoints TD, put the next in the first place

			This place has turned out to be more tricker than before. The 
			story is we must check both m_TdsPutToITLFirstIndex and 
			m_TdsPutToITLSecondIndex, if either of them is NOT zero, that 
			means the next TD has been taken out and saved already. So, 
			we can't take out the next TD as put it to head position, instead
			we should take out 2 of them.
			
			And even tricker is we must check whether we are just in the 
			right frame to jump 2 frames. As it turned out, if we are late
			for many frames, we can't simply jump 2 frames. Cause CheckITL
			ITLSecond will be called right after CheckITLFirst.

		/=================================================================*/
		if (uFrameNumber == pCurITd->bfStartFrame + pCurITd->bfFrameCount + 1 + 1)
		{
	
			if((m_TdsPutToITLFirstIndex !=0) && (m_TdsPutToITLSecondIndex !=0))
			{
				SIsochTransferDescriptor*		pNextITd;
				pNextITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(pCurITd->paNextTd);
				pEndptDesc->paTdQueueHead = pNextITd->paNextTd;
				RETAILMSG(0, 
					(TEXT("PHCD: Jump 2 TD, paCurITd 0x%08X, NextTd 0x%08X, Next-NextTd 0x%08X\r\n"), 
					paCurITd, pCurITd->paNextTd, pNextITd->paNextTd));
			}
			else
			{
				pEndptDesc->paTdQueueHead = pCurITd->paNextTd;
				RETAILMSG(0, (TEXT("PHCD: Jump 1 TD, CurITd 0x%08X, NextId 0x%08X\r\n"),	
					paCurITd, pCurITd->paNextTd));
			}
		}
		else
		{
			//We have been later now, First compare FirstIndex with SecondIndex
			//To determine which is first and then go till the end and reverse
			//them and put them to DoneHead

			//I presume CheckITLList(m_TdsPutToITLFirstIndex is called

			if (m_TdsPutToITLSecondIndex)
			{
				
				SIsochTransferDescriptor*		pTempITd;
				ULONG							paTempITd;

				paTempITd = m_TdsPutToITLSecond[0];
				pTempITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paTempITd);
		
				SDevice *pDev;
				SEndpoint *pEndpt;
				SEndpointDescriptor* pEndptDesc;

				EnterCriticalSection(&m_csDeviceListLock);
				pDev = m_ppDevices[pTempITd->paBufferPage0 & gcITdAddrMask];
				LeaveCriticalSection(&m_csDeviceListLock);

				ASSERT(pDev);
	
				EnterCriticalSection(&pDev->csAccessingEndpointArray);
				pEndpt = pDev->ppEndpts[
					(pTempITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
				LeaveCriticalSection(&pDev->csAccessingEndpointArray);

				pEndptDesc = pEndpt->pEd;


				//We still don't know which TD is earlier, well, if pTempITd->next is
				//pCurITd, TD is Second is indeed earlier.

				if (pTempITd->paNextTd == paCurITd)
				{
					//Assign pTempITd to pCurITd, cause we will operate on pCurITd 
					pCurITd = pTempITd;
					paCurITd = paTempITd;
				}

			}

			//Do a while loop to reach to the bottom
			
			//Put the next to TdQueueHead
			pEndptDesc->paTdQueueHead = pCurITd->paNextTd;
			//Put itself to DoneHead

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -