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

📄 isp1161hc.cpp

📁 ISP1161 USB Driver under WinCE for StrongARM processor implementation
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*++
Copyright (c) 2000  Philips Electronic Company, APIC

Module Name:  
    Isp1161Hc.cpp
Abstract:  
    This file implements the USB host controller driver for the
    Philips ISP1161 HCI interface.
Author:
	Zou Ying
Notes: Intial code released	 by zou ying for the x86 platform.												 

--*/

// C4100 unrefrenced formal parameter
// C4101 unrefrenced local variable
// C4705 statement has no effect
// C4706 assignment in conditional
#pragma warning (3 : 4100 4101 4705 4706)

#include <windows.h>
extern "C" {  // nkintr.h now contains this, but autopc doesn't have the latest,
              // so include here as well for now.
#include <nkintr.h>
}
#include <ceddk.h>
#include <phcdddsi.h>

#include "hcdi.h"
#include "globals.hpp"
#include "mem.hpp"
#include "hub.hpp"
#include "phcdinc.hpp"
#include "phcd.hpp"


#define ISP1161DBG	0
#define ISPDATADBG	0
#define ISPEP		0

DWORD CPhcd::ServiceList(PULONG pInterrupts)
{
	pInterrupts = pInterrupts;
	ServiceITLList();
	ServiceATLList();
	return 0;
}

DWORD CPhcd::ServiceITLList()
{
	
	ULONG ulHcControlValue = READ_REGISTER_ULONG(HcControl(m_regBase)); 

	if( ulHcControlValue & gcHcControlPLEmask) 
	{
		ULONG ulIsoListEnabled = ulHcControlValue & gcHcControlIEmask;
		if (ulIsoListEnabled)
		{
			ServiceEndpoint(gcEndptTypeIsochronous);
		
		}
	}

	//if m_TdsPutToITLFirstIndex is NOT 0
	if ( m_TdsPutToITLFirstIndex != 0 || m_TdsPutToITLSecondIndex != 0 )
	{
		ServiceITLTransferDescriptor(m_TdsPutToITLFirstIndex, m_TdsPutToITLFirst);
		ServiceITLTransferDescriptor(m_TdsPutToITLSecondIndex, m_TdsPutToITLSecond);
	
	}

	return 0;
  	
}

DWORD CPhcd::ServiceATLList()
{

	/*=========================================================
	  We first check whether m_bReDump is TRUE or not. It it is,
	  that means, we can't server list, cause right now, some 
	  PTD needs to be dumped again. We will call ReDump to dump
	  the PTDs. If m_bReDump is FALSE, we will begin to process
	  each list. 
	==========================================================*/
	if (m_bReDump == TRUE)
	{
		ReDumpPtd();
		m_bReDump = FALSE;
		return 0;
	}

	/*========================================================
		This ServiceList will be called every 1ms. It is possible
		we can't dump PTD to ATL buffer, cause if you dump PTD
		in the previous ms, hardware will be busy to process
		ATL buffer in this ms. So, in this frame, you should 
		lave the buffer as it is. We use a variable m_ATLBeingReadOut
		to record whether ATL buffer is busy or free. If it is
		FALSE, we can ServiceList. If not, we will leave this 
		routine. This variable will be set to TRUE in IsTDComplete
	==========================================================*/
	if ( m_ATLBeingReadOut == TRUE)
		return 0;

	//Begin check lists. 
	ULONG ulHcControlValue = 0;

	ulHcControlValue = READ_REGISTER_ULONG(HcControl(m_regBase)); 
	
	// Porcess Perodic List
	if( ulHcControlValue & gcHcControlPLEmask) 
	{
		uFrameNumber = *HccaFrameNumber(m_pHcca);
		ULONG paCur = *(HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F))); 

		if ( paCur)
		{
			SEndpointDescriptor* pCur = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
			
			//OK, here is the first endpoint, it can't be ISO, so 
			//Service Interrupt endpoint directly. 
			ServiceEndpoint(gcEndptTypeInterrupt);
		}
	}
  	
	//Process Control List
	if( ulHcControlValue & gcHcControlCLEmask )
	{
		m_ControlBulkRatio = (ulHcControlValue & gcHcControlCBSRmask) + 1;  

		while (m_ControlBulkRatio)
		{
			ULONG paCtrlCurEd = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
			if (paCtrlCurEd)
			{
				DEBUGMSG(ISP1161DBG, 
					(TEXT("PHCD:: Processing Control List,when ControlCurrentEdpoint is set\r\n")));
				ServiceEndpoint(gcEndptTypeControl);
				//should check frame time left
			}
			else
			{
				ULONG dwValue = READ_REGISTER_ULONG(HcCommandStatus(m_regBase));
				if (dwValue & gcHcCommandStatusCLFmask)
				{
					ULONG paCtrlHeadEd;
					paCtrlHeadEd = READ_REGISTER_ULONG(HcControlHeadEd(m_regBase));

					WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCtrlHeadEd);
							
					//OHCI spec Page 96
					ClearControlListFilledBit(m_regBase);
							
					ULONG paCtrlCurEd = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
					if (paCtrlCurEd)
					{
						DEBUGMSG(ISP1161DBG, 
							(TEXT("PHCD:: Processing Control List,when ControlHeadEdpoint is set\r\n")));
						ServiceEndpoint(gcEndptTypeControl);
						//should check frame time left
					}
				}
			}
			
			m_ControlBulkRatio--;
		}
	}

	//Process Bulk List
	if( ulHcControlValue & gcHcControlBLEmask)
	{		
			
		ULONG paBulkCurEd = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));			
		if (paBulkCurEd )
		{
				
			DEBUGMSG(ISP1161DBG, 
				(TEXT("PHCD:: Processing Bulk List,when BulkCurrentEdpoint is set\r\n")));
			ServiceEndpoint(gcEndptTypeBulk);
		}
		else
		{
				
			ULONG dwValue = READ_REGISTER_ULONG(HcCommandStatus(m_regBase));
							
			if (dwValue & gcHcCommandStatusBLFmask)
			{
				ULONG paBulkHeadEd;

				paBulkHeadEd = READ_REGISTER_ULONG(HcBulkHeadEd(m_regBase));

				WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paBulkHeadEd);
								
				//OHCI spec Page 96
				ClearBulkListFilledBit(m_regBase);

				ULONG paBulkCurEd = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));
				if (paBulkCurEd)
				{
					DEBUGMSG(ISP1161DBG, 
						(TEXT("PHCD:: Processing Bulk List,when BulkHeadEdpoint is set\r\n")));
					ServiceEndpoint(gcEndptTypeBulk);
					//should check frame time left
				}

			}
		}
		
	}
		
	/*======================================================
	 We have prepared all the TDs that should be dumped to
	 ATL buffer, next fire ServiceTransferDescriptor
	=======================================================*/

	if ( m_TdsPutToATLIndex != 0)
		ServiceATLTransferDescriptor();
	
	return (0);
}

void CPhcd::ServiceEndpoint(UINT dwEndpointType)
{

	SEndpointDescriptor* pCurEPDescriptor;
	ULONG paCur;
	ULONG paTd;

	int i=0;

	/*=======================================================
		First, calculate how many PTDs we should prepare
	/=======================================================*/
	
	switch(dwEndpointType)
	{
		
	case gcEndptTypeControl:
				
		paCur = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
			
		while ( paCur != 0)
		{
			
			pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
			
			if (pCurEPDescriptor->bfSkip)  //Don't forget halt bit.
			{
				paCur = pCurEPDescriptor->paNextEd;
				continue;
			}
			
			paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
		
			if( (paTd != gcStaticEdIdentifier) && (paTd != pCurEPDescriptor->paTdQueueTail))
			{
			
				/*=======================================================
					This variable records how many times Endpoint is
					services, which means, how many TDs are supposed to 
					be put into the list. 
				/=======================================================*/
				m_EdpointServicedOne1ms++;			
				
				/*===============================================================/
					Put the TD which will be processed to m_TdsPutToATL[] buffer
				/===============================================================*/

				m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
				m_TdsPutToATLIndex++;

				//OHCI spec Page 98
				SetControlListFilledBit(m_regBase);

				/*================================================================
				 We have recorded the PTD that will be processed and are going to
				 jump out of this loop. At this time, we should also update CuurentEd
				 to the next ed.
				==================================================================*/
				paCur = pCurEPDescriptor->paNextEd; 
				WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCur);
				break;
			}

			paCur = pCurEPDescriptor->paNextEd; 
			WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCur);
		
		}
		
		break;
	case gcEndptTypeBulk:
		
		paCur = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));
					
		while ( paCur != 0) 
		{
			pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
			
			if (pCurEPDescriptor->bfSkip)  //Don't forget halt bit.
			{
				paCur = pCurEPDescriptor->paNextEd;
				continue;
			}

			paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
		
			if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
			{
				m_EdpointServicedOne1ms++;
				
				/*=====================================================================/
					Put the TD which will be processed to m_TdsPutToATL[] buffer
				/=====================================================================*/

				m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
				m_TdsPutToATLIndex++;

				//OHCI spec Page 98
				SetBulkListFilledBit(m_regBase);

				paCur = pCurEPDescriptor->paNextEd; //Goes to the next
				WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paCur);
				break;
			}

			paCur = pCurEPDescriptor->paNextEd; //Goes to the next
			WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paCur);
			
		}

		break;
	case gcEndptTypeInterrupt:

		uFrameNumber = *HccaFrameNumber(m_pHcca);
		paCur = *HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F)); 

		while ( paCur != 0) 
		{
			pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
			
			if (pCurEPDescriptor->bfSkip || pCurEPDescriptor->bfIsIsochronous)  //Don't forget halt bit.
			{
				paCur = pCurEPDescriptor->paNextEd;
				continue;
			}
			
			paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
			if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
			{
				
				/*=====================================================================/
					Put the TD which will be processed to m_TdsPutToATL[] buffer
				/=====================================================================*/

				m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
				m_TdsPutToATLIndex++;
			}
			
			paCur = pCurEPDescriptor->paNextEd; //Goes to the next
		}
		
	
		break;

	case gcEndptTypeIsochronous:
		
		uFrameNumber = *HccaFrameNumber(m_pHcca);
		paCur = *HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F)); 

		while ( paCur != 0) 
		{
			pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
			
			//We have reached to the bottom. It's possible this Endpoint 
			// is "skip" and not an ISO.
			if (pCurEPDescriptor->bfSkip || (pCurEPDescriptor->bfIsIsochronous == 0))  
			{
				paCur = pCurEPDescriptor->paNextEd;
				continue;
			}
			
			paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
			if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
			{
				/*=====================================================================/
					Put the TD which will be processed to m_TdsPutToATLA or B[] buffer
					If buffer A is empty, we put to A, If buffer B is empty, 
					we put to B. One more thing, by the time we put one TD to A, it is
					possible this TD has already been put to B, and vice verca. So, every
					time we put something to A, we check whether this TD is inside B, if
					it is, we will not this TD to A anymore. 
					Policy updates:
					The purpose of this function is to find out how many offset this ITD 
					may have and allocate each of them to ITLA and ITLB alternatively.
					Not matter what, ITLA and ITLB contains the same ISO TD. 
					Well, we still need to guanrantee whether this TD is already dumped. 
				/=====================================================================*/

				SIsochTransferDescriptor*		pITd;
				SIsochTransferDescriptor*		pNextITd;
				ULONG							paNextITd;

				pITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paTd);
				
				BOOL bFirstFilledIn = FALSE;
				if (m_TdsPutToITLFirstIndex == 0)
				{	
					m_TdsPutToITLFirst[m_TdsPutToITLFirstIndex] = paTd;
					m_TdsPutToITLFirstIndex++;
					bFirstFilledIn = TRUE;

					RETAILMSG(0, 
					(TEXT("PHCD::ServiceEndpoint: %d ISO TD: 0x%08X is added to ITLFirst, FrameNumber 0x%08X\r\n"),
								m_TdsPutToITLFirstIndex, pCurEPDescriptor->paTdQueueHead, uFrameNumber));
				}

				//If First is filled in, we will choose the next.
				
				if (bFirstFilledIn == TRUE)
				{
					paNextITd = pITd->paNextTd; 				
				}
				else
				{
					paNextITd = paTd;
				}

				if ( paNextITd != gcStaticEdIdentifier && paNextITd != pCurEPDescriptor->paTdQueueTail )
				{
					pNextITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paNextITd);

					if (m_TdsPutToITLSecondIndex == 0)
					{
						m_TdsPutToITLSecond[m_TdsPutToITLSecondIndex] = paNextITd;
						m_TdsPutToITLSecondIndex++;

						RETAILMSG(0, 
							(TEXT("PHCD::ServiceEndpoint: %d ISO TD: 0x%08X is added to ITLSecond, FrameNumber 0x%08X\r\n"),
								m_TdsPutToITLSecondIndex, paNextITd, uFrameNumber));
					}
				}
				
			}
			
			paCur = pCurEPDescriptor->paNextEd; //Goes to the next
		}
	
		break;
	default:
		break;

	}
}

void CPhcd::ServiceITLTransferDescriptor(ULONG m_TdsPutToITLIndex, ULONG m_TdsPutToITL[])
{
	SIsochTransferDescriptor*		pCurITd;
	ULONG							paCurITd;
	ULONG							m_ITLTransferLen;

	uFrameNumber = *HccaFrameNumber(m_pHcca);

⌨️ 快捷键说明

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