📄 ohcdpdd.c
字号:
// Each port to participate in Per Port Power switching must set
// its corresponding bit in the UHCRHDB:PPCM mask.
// In this case:
// Port1 responds to Global Power Mode commands
// Port2 response to Per Port Power Mode commands
// All ports without their bits set in UHCRHDB:PPCM mask are effect by Global Power Mode commands.
// Power to individual ports is enabled or disabled without effecting other ports.
//
//
void
SetupUSBHostPEN(
int Port
)
{
unsigned long ulPinArrayParms[3];
unsigned long ulAlternateFunctionParms[3];
// Configure GPIO 89 according to the discussion above:
// Level: Low (enable)
// Direction: Output
// Alternate function: 2
// level, direction & alternate function gpio apis all use the same pin array
ulPinArrayParms[0] = 1;
ulPinArrayParms[1] = 89;
XllpGpioSetOutput0( v_pDCGPIOReg, ulPinArrayParms );
XllpGpioSetDirectionOut( v_pDCGPIOReg, ulPinArrayParms );
ulAlternateFunctionParms[0] = 1;
ulAlternateFunctionParms[1] = XLLP_GPIO_ALT_FN_2;
XllpGpioSetAlternateFn( v_pDCGPIOReg, ulPinArrayParms, ulAlternateFunctionParms );
}
void
SelectUSBHOSTPowerManagementMode(
int Mode,
int NumPorts,
int *PortMode
)
{
switch(Mode)
{
case XLLP_USBOHCI_PPM_NPS:
// set NO Power Switching mode
v_pDCUSBOHCIReg->uhcrhda |= XLLP_USBOHCI_UHCRHDA_NPS;
break;
case XLLP_USBOHCI_PPM_GLOBAL:
// make sure the NO Power Switching mode bit is OFF so Power Switching can occur
// make sure the PSM bit is CLEAR, which allows all ports to be controlled with
// the GLOBAL set and clear power commands
v_pDCUSBOHCIReg->uhcrhda &= ~(XLLP_USBOHCI_UHCRHDA_NPS|XLLP_USBOHCI_UHCRHDA_PSM_PERPORT);
break;
case XLLP_USBOHCI_PPM_PERPORT:
// make sure the NO Power Switching mode bit is OFF so Power Switching can occur
// make sure the PSM bit is SET, which allows all ports to be controlled with
// the PER PORT set and clear power commands
v_pDCUSBOHCIReg->uhcrhda &= ~XLLP_USBOHCI_UHCRHDA_NPS;
v_pDCUSBOHCIReg->uhcrhda |= XLLP_USBOHCI_UHCRHDA_PSM_PERPORT;
// set the power management mode for each individual port to Per Port.
{
int p;
for( p = 0; p < NumPorts; p++ )
{
v_pDCUSBOHCIReg->uhcrhdb |= (unsigned int)( 1u << (p+17) ); // port 1 begins at bit 17
}
}
break;
case XLLP_USBOHCI_PPM_MIXED:
// make sure the NO Power Switching mode bit is OFF so Power Switching can occur
// make sure the PSM bit is SET, which allows all ports to be controlled with
// the PER PORT set and clear power commands
v_pDCUSBOHCIReg->uhcrhda &= ~XLLP_USBOHCI_UHCRHDA_NPS;
v_pDCUSBOHCIReg->uhcrhda |= XLLP_USBOHCI_UHCRHDA_PSM_PERPORT;
// set the power management mode for each individual port to Per Port.
// if the value in the PortMode array is non-zero, set Per Port mode for the port.
// if the value in the PortMode array is zero, set Global mode for the port
{
int p;
for( p = 0; p < NumPorts; p++ )
{
if( PortMode[p] )
{
v_pDCUSBOHCIReg->uhcrhdb |= (unsigned int)( 1u << (p+17) ); // port 1 begins at bit 17
}
else
{
v_pDCUSBOHCIReg->uhcrhdb &= ~(unsigned int)( 1u << (p+17) ); // port 1 begins at bit 17
}
}
}
break;
}
}
void
TestUSBHostPEN(
int Port
)
{
// turning on ports is normally done later on during the initialization.
// but it is a good think to check out in this test routine, until the code
// has been verified.
SelectUSBHOSTPowerManagementMode( XLLP_USBOHCI_PPM_NPS, 0, 0 );
}
/* HcdPdd_Init
*
* PDD Entry point - called at system init to detect and configure UHCI card.
*
* Return Value:
* Return pointer to PDD specific data structure, or NULL if error.
*/
extern DWORD
HcdPdd_Init(
DWORD dwContext) // IN - Pointer to context value. For device.exe, this is a string
// indicating our active registry key.
{
SUhcdPdd * pPddObject = malloc(sizeof(SUhcdPdd));
BOOL fRet = FALSE;
// we should use dwContext to find our registry configuration, not a hardcoded path
// like OHCI_DRIVER_KEY.
UnusedParameter(dwContext);
NKDbgPrintfW(TEXT("HcdPdd_Init: Checking SW18 - controls OHCI loading.\r\n"));
if (pPddObject) {
fRet = OhcdPddInitializeAddresses();
if(fRet)
{
TurnOnUSBHostClocks(); // make sure the ohci block is running (eg. getting clocked)
SetupUSBHostPWR(0); // this sets up Pwr 0 notification using gpio 88 as input in alternate function 1 mode
SetupUSBHostPEN(0); // this sets up Pwr 0 enable using gpio 89 as output in alternate function 2 mode
//TurnOnUSBHostPorts(); // probably only do this after the rest of the ohci is set up.
//TestUSBHostPEN(0); // Can't do this here, unless we want to call reset first.
}
if(fRet) {
fRet = InitPddInterrupts();
}
if(fRet) {
pPddObject->pvVirtualAddress = NULL;
InitializeCriticalSection(&pPddObject->csPdd);
fRet = InitializeUHCI(pPddObject, OHCI_DRIVER_KEY);
}
if(!fRet)
{
free(pPddObject);
pPddObject = NULL;
}
}
return (DWORD)pPddObject;
}
/* HcdPdd_CheckConfigPower
*
* Check power required by specific device configuration and return whether it
* can be supported on this platform. For CEPC, this is trivial, just limit to
* the 500mA requirement of USB. For battery powered devices, this could be
* more sophisticated, taking into account current battery status or other info.
*
* Return Value:
* Return TRUE if configuration can be supported, FALSE if not.
*/
extern BOOL HcdPdd_CheckConfigPower(
UCHAR bPort, // IN - Port number
DWORD dwCfgPower, // IN - Power required by configuration
DWORD dwTotalPower) // IN - Total power currently in use on port
{
return ((dwCfgPower + dwTotalPower) > 500) ? FALSE : TRUE;
}
extern void HcdPdd_PowerUp(DWORD hDeviceContext)
{
SUhcdPdd * pPddObject = (SUhcdPdd *)hDeviceContext;
DEBUGMSG(ZONE_INIT, (TEXT("HcdPdd_PowerUp: enter.\n\r")));
#ifdef PLAT_LUBBOCK
WRITE_BITFIELD(struct skpcrBITS,&v_pDCPLLReg->skpcr,UCLKEn,1); //Disable USB Clocks
#else
DEBUGMSG(ZONE_INIT, (TEXT("HcdPdd_PowerUp: Need to add Bulverde support.\n\r")));
#endif
HcdMdd_PowerUp(pPddObject->lpvUhcdMddObject);
return;
}
extern void HcdPdd_PowerDown(DWORD hDeviceContext)
{
SUhcdPdd * pPddObject = (SUhcdPdd *)hDeviceContext;
DEBUGMSG(ZONE_INIT, (TEXT("HcdPdd_PowerDown: enter.\n\r")));
// let the MDD do its processing (including putting the HC into reset)
HcdMdd_PowerDown(pPddObject->lpvUhcdMddObject);
// disable the USB port as described in section 6.1.4.4 of the SA-1111 companion
// chip documentation:
// (1) Reset HC (done by MDD)
// (2) wait 10 us
// (3) clear global power enable bit
// (4) set the standby enable bit
// (5) stop the usb clock
usWait(10); // must not block or do operations illegal in interrupt context
v_pDCUSBOHCIReg->uhcrhda &= ~ ((1 << 8) | (1 << 9)); // set global power switch mode
v_pDCUSBOHCIReg->uhcrhs |= 0x0001; // clear global power
#ifdef PLAT_LUBBOCK
WRITE_BITFIELD(struct resetBITS,&v_pDCUSBReg->Reset,uSleepStandbyEn,1);
WRITE_BITFIELD(struct skpcrBITS,&v_pDCPLLReg->skpcr,UCLKEn,1); //Disable USB Clocks
#else
DEBUGMSG(ZONE_INIT, (TEXT("HcdPdd_PowerDown: Need to add Bulverde support.\n\r")));
#endif
return;
}
extern BOOL HcdPdd_Deinit(DWORD hDeviceContext)
{
SUhcdPdd * pPddObject = (SUhcdPdd *)hDeviceContext;
if(pPddObject->lpvUhcdMddObject)
HcdMdd_DestroyHcdObject(pPddObject->lpvUhcdMddObject);
if(pPddObject->lpvMemoryObject)
HcdMdd_DestroyMemoryObject(pPddObject->lpvMemoryObject);
if(pPddObject->pvVirtualAddress)
HalFreeCommonBuffer(&pPddObject->AdapterObject, gcTotalAvailablePhysicalMemory, pPddObject->LogicalAddress, pPddObject->pvVirtualAddress, FALSE);
return TRUE;
}
extern DWORD HcdPdd_Open(DWORD hDeviceContext, DWORD AccessCode,
DWORD ShareMode)
{
UnusedParameter(hDeviceContext);
UnusedParameter(AccessCode);
UnusedParameter(ShareMode);
return 1; // we can be opened, but only once!
}
extern BOOL HcdPdd_Close(DWORD hOpenContext)
{
UnusedParameter(hOpenContext);
return TRUE;
}
extern DWORD HcdPdd_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
UnusedParameter(hOpenContext);
UnusedParameter(pBuffer);
UnusedParameter(Count);
return (DWORD)-1; // an error occured
}
extern DWORD HcdPdd_Write(DWORD hOpenContext, LPCVOID pSourceBytes,
DWORD NumberOfBytes)
{
UnusedParameter(hOpenContext);
UnusedParameter(pSourceBytes);
UnusedParameter(NumberOfBytes);
return (DWORD)-1;
}
extern DWORD HcdPdd_Seek(DWORD hOpenContext, LONG Amount, DWORD Type)
{
UnusedParameter(hOpenContext);
UnusedParameter(Amount);
UnusedParameter(Type);
return (DWORD)-1;
}
extern BOOL HcdPdd_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
UnusedParameter(hOpenContext);
UnusedParameter(dwCode);
UnusedParameter(pBufIn);
UnusedParameter(dwLenIn);
UnusedParameter(pBufOut);
UnusedParameter(dwLenOut);
UnusedParameter(pdwActualOut);
return FALSE;
}
// Manage WinCE suspend/resume events
// This routine cleans up the MDD object and creates a new one.
static DWORD WINAPI HcdPdd_ResumeThread(LPVOID lpvParam)
{
SUhcdPdd * pPddObject = (SUhcdPdd *) lpvParam;
// since we might suspend/resume while we're in the middle of resuming, use a critical section to serialize
// management of the PDD object
EnterCriticalSection(&pPddObject->csPdd);
// get rid of the old MDD object
ASSERT(pPddObject->lpvUhcdMddObject);
HcdMdd_DestroyHcdObject(pPddObject->lpvUhcdMddObject);
HcdMdd_DestroyMemoryObject(pPddObject->lpvMemoryObject);
/*
// everything's torn down. time to bring it back up.
if( v_pOHCIDMABuffer )
{
VirtualFree( (PVOID)v_pOHCIDMABuffer,0,MEM_RELEASE );
v_pOHCIDMABuffer = NULL;
}
v_pOHCIDMABuffer =
// VirtualAllocCopy(OHCI_DMA_BUFFER_SIZE,"OHCI v_pOHCIDMABuffer", (PVOID) OHCI_DMA_BUFFER_U_VIRTUAL);
VirtualAllocCopy(dwOhciDmaBufferSize,"OHCI v_pOHCIDMABuffer", pOhciDmaBufferVirtual);
if (v_pOHCIDMABuffer == NULL) {
RETAILMSG(ZONE_INIT,(TEXT("HcdPdd_ResumeThread: Could not get OhciDma Memory.\r\n")));
DEBUGCHK(0);
}
RETAILMSG(ZONE_INIT,(TEXT("HcdPdd_ResumeThread: v_pOHCIDMABuffer: %08x.\r\n"), v_pOHCIDMABuffer));
*/
TurnOnUSBHostClocks(); // make sure the ohci block is running (eg. getting clocked)
SetupUSBHostPWR(0); // this sets up Pwr 0 notification using gpio 88 as input in alternate function 1 mode
SetupUSBHostPEN(0); // this sets up Pwr 0 enable using gpio 89 as output in alternate function 2 mode
//TurnOnUSBHostPorts(); // probably only do this after the rest of the ohci is set up.
SelectUSBHOSTPowerManagementMode( XLLP_USBOHCI_PPM_NPS, 0, 0 );
//OHCI_Reset();
InitializeUHCI(pPddObject, OHCI_DRIVER_KEY);
// we should try to use HalAllocateCommonBuffer() instead of a hardcoded memory address
if(!(pPddObject->lpvMemoryObject = HcdMdd_CreateMemoryObject(gcTotalAvailablePhysicalMemory, gcHighPriorityPhysicalMemory, (PUCHAR) v_pOHCIDMABuffer, (PUCHAR)dwOhciDmaBufferPhysical)))
{
RETAILMSG(ZONE_INIT,(TEXT("HcdPdd_ResumeThread: Cannot create the memory object.\r\n")));
DEBUGCHK(0);
}
// create a new MDD object
pPddObject->lpvUhcdMddObject = HcdMdd_CreateHcdObject(pPddObject,
pPddObject->lpvMemoryObject, pPddObject->szDriverRegKey, pPddObject->ioPortBase,
pPddObject->dwSysIntr);
if(pPddObject->lpvUhcdMddObject == NULL) {
DEBUGMSG(TRUE, (_T("HcdPdd_ResumeThread: HcdMdd_CreateHcdObject() failed\r\n")));
}
DEBUGCHK(pPddObject->lpvUhcdMddObject != NULL);
// allow other threads to update the PDD object
LeaveCriticalSection(&pPddObject->csPdd);
return 0;
}
// This gets called by the MDD's IST when it detects a power resume.
extern void HcdPdd_InitiatePowerUp (DWORD hDeviceContext)
{
SUhcdPdd * pPddObject = (SUhcdPdd *)hDeviceContext;
HANDLE htResume;
ASSERT(pPddObject != NULL);
// create a thread to clean up the controller
htResume = CreateThread(NULL, 0, HcdPdd_ResumeThread, pPddObject, 0, NULL);
if(htResume != NULL) {
CloseHandle(htResume);
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -