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

📄 ohcdpdd.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 3 页
字号:
//			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 + -