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

📄 ohcdpdd.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 3 页
字号:
    DWORD * lpdwBusNumber,      // OUT - bus number, depends on interface type
    BOOL * bInstallIsr,         // OUT - TRUE if ISR Handler found in registry
    LPWSTR IsrDll,              // OUT - Name of ISR Handler dll
    LPWSTR IsrHandler,          // OUT - Name of ISR Handler routine
    DWORD * Irq                 // OUT - IRQ number, used to hook ISR handler
    )
{
    HKEY hKey = NULL;
    BOOL  fRet=FALSE;
    DWORD dwRet;

    // initialize with default values
    *lpdwBaseAddr = (DWORD) v_pDCUSBOHCIReg;
    *lpdwAddrLen = sizeof( XLLP_USBOHCI_T );
    *lpdwIOSpace = 0;
    *lpdwSysIntr = dwSysIntrOhciMdd;
    *lpIfcType = Isa;
    *bInstallIsr = FALSE;
    *lpdwBusNumber = 0;
    IsrDll[0] = 0;
    IsrHandler[0] = 0;
    *Irq = 0;

    // Open key
    dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,RegKeyPath,0,0,&hKey);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!UHCD:GetRegistryConfig RegOpenKeyEx(%s) failed %d\r\n"),
                             RegKeyPath, dwRet));
    } else {
        DWORD dwData;
        DWORD dwSize;
        DWORD dwType;
        
        // read registry data
        dwSize = sizeof(dwData);
        dwRet = RegQueryValueEx(hKey,IRQ_VALUE_NAME,0,&dwType,(PUCHAR)&dwData,&dwSize);
        if (dwRet == ERROR_SUCCESS) {
            *lpdwSysIntr = dwData;
        }

        dwSize = sizeof(dwData);
        dwRet = RegQueryValueEx(hKey,IOBASE_VALUE_NAME,0,&dwType,(PUCHAR)&dwData,&dwSize);
        if (dwRet == ERROR_SUCCESS) {
            *lpdwBaseAddr = dwData;
        }
    }
        
    fRet = TRUE;

    if(hKey != NULL) RegCloseKey(hKey);

    return fRet;
}   // GetRegistryConfig


/* ConfigureUHCICard
 * 
 */
BOOL
ConfigureUHCICard(
    PUCHAR *pioPortBase,   // IN - contains physical address of register base
                           // OUT- contains virtual address of register base
    DWORD dwAddrLen,
    DWORD dwIOSpace,
    INTERFACE_TYPE IfcType,
    DWORD dwBusNumber
    )
{
    UnusedParameter(pioPortBase);
    UnusedParameter(dwAddrLen);
    UnusedParameter(dwIOSpace);
    UnusedParameter(IfcType);
    UnusedParameter(dwBusNumber);

    return TRUE;
}


/* InitializeUHCI
 *
 *  Configure and initialize UHCI card
 *
 * Return Value:
 *  Return TRUE if card could be located and configured, otherwise FALSE
 */
static BOOL 
InitializeUHCI(
    SUhcdPdd * pPddObject,    // IN - Pointer to PDD structure
    LPCWSTR szDriverRegKey)   // IN - Pointer to active registry key string
{
    PUCHAR ioPortBase = NULL;
    DWORD dwAddrLen;
    DWORD dwIOSpace;
    DWORD dwSysIntr;
    INTERFACE_TYPE IfcType;
    DWORD dwBusNumber;
    BOOL InstallIsr = FALSE;
    WCHAR IsrDll[DEVDLL_LEN];
    WCHAR IsrHandler[DEVENTRY_LEN];
    DWORD Irq = -1;
    BOOL fResult = FALSE;
    LPVOID pobMem = NULL;
    LPVOID pobUhcd = NULL;
    DWORD PhysAddr;

    // reset the host controller and enable its clocks

    OHCI_Reset();
    
    if (!GetRegistryConfig(szDriverRegKey, &PhysAddr, &dwAddrLen, &dwIOSpace, &dwSysIntr, &IfcType, &dwBusNumber, &InstallIsr, IsrDll, IsrHandler, &Irq)) {
        RETAILMSG(1,(TEXT("!UHCD: Error reading registry settings\r\n")));
        return FALSE;
    }
    
    DEBUGMSG(ZONE_INIT,(TEXT("InitializeUHCI: Read config from registry: Base Address: 0x%X, Length: 0x%X, I/O Port: %s, SysIntr: 0x%X, Interface Type: %u, Bus Number: %u\r\n"),
                        PhysAddr, dwAddrLen, dwIOSpace ? L"YES" : L"NO", dwSysIntr, IfcType, dwBusNumber));

    ioPortBase = (PUCHAR)PhysAddr;
                        
    if (!(fResult = ConfigureUHCICard(&ioPortBase, dwAddrLen, dwIOSpace, IfcType, dwBusNumber))) {
        goto InitializeUHCI_Error;
    }
    
    
    // we should try to use HalAllocateCommonBuffer() instead of a hardcoded memory address
    if(!(pobMem = HcdMdd_CreateMemoryObject(gcTotalAvailablePhysicalMemory, gcHighPriorityPhysicalMemory, (PUCHAR) v_pOHCIDMABuffer, (PUCHAR)dwOhciDmaBufferPhysical/* OHCI_DMA_BUFFER_PHYSICAL*/))) {
        goto InitializeUHCI_Error;
    }
 
    if (!(pobUhcd = HcdMdd_CreateHcdObject(pPddObject, pobMem, szDriverRegKey, ioPortBase, dwSysIntr))) {
        goto InitializeUHCI_Error;
    }

    pPddObject->lpvMemoryObject = pobMem;
    pPddObject->lpvUhcdMddObject = pobUhcd;
    _tcsncpy(pPddObject->szDriverRegKey, szDriverRegKey, MAX_PATH);
    pPddObject->ioPortBase = ioPortBase;
    pPddObject->dwSysIntr = dwSysIntr;

	// start the debug thread
//	RETAILMSG(1,(TEXT("InitializeUHCI: Starting OHCIPDDDebugThread.\r\n")));
//  CreateThread(NULL, 0, OHCIPDDDebugThread, pPddObject, 0, NULL);

    return TRUE;

InitializeUHCI_Error:

    if (pobUhcd)
        HcdMdd_DestroyHcdObject(pobUhcd);
    if (pobMem)
        HcdMdd_DestroyMemoryObject(pobMem);

    if(pPddObject->pvVirtualAddress)
        HalFreeCommonBuffer(&pPddObject->AdapterObject, gcTotalAvailablePhysicalMemory, pPddObject->LogicalAddress, pPddObject->pvVirtualAddress, FALSE);


    pPddObject->lpvMemoryObject = NULL;
    pPddObject->lpvUhcdMddObject = NULL;
    pPddObject->pvVirtualAddress = NULL;

    return FALSE;
}






// TurnOnUSBHostClocks:
//		This routine will make sure that the USB Host OHCI block in the
//		Bulverde core is getting clocks. If it is not getting clocks,
//		then some accesses to it may stall, especially if one needs to
//		wait for some OHCI register bits to change.
void
TurnOnUSBHostClocks()
{
	// The clock enable bit for the USB Host OHCI block in Bulverde
	// is bit number 20.
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOnUSBHostClocks: Initial Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
	v_pDCCLKReg->cken |= XLLP_CLKEN_USBHOST;
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOnUSBHostClocks: Final   Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
}


// TurnOnUSBHostClocks:
//		This routine will make sure that the USB Host OHCI block in the
//		Bulverde core is getting clocks. If it is not getting clocks,
//		then some accesses to it may stall, especially if one needs to
//		wait for some OHCI register bits to change.
void
TurnOnSRAMClocks()
{
	// The clock enable bit for the USB Host OHCI block in Bulverde
	// is bit number 20.
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOnSRAMClocks: Initial Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
	v_pDCCLKReg->cken |= (1u << 20);
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOnSRAMClocks: Final   Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
}


// TurnOffUSBHostClocks:
//		This routine will make sure that the USB Host OHCI block in the
//		Bulverde core is not getting clocks. If it is not getting clocks,
//		then there will be power savings.
void
TurnOffUSBHostClocks()
{
	// The clock enable bit for the USB Host OHCI block in Bulverde
	// is bit number 20.
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOfUSBHostClocks: Initial Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
	v_pDCCLKReg->cken &= ~XLLP_CLKEN_USBHOST;
	DEBUGMSG(ZONE_INIT,(TEXT("TurnOfUSBHostClocks: Final   Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), v_pDCCLKReg->cccr, v_pDCCLKReg->cken, v_pDCCLKReg->oscc, v_pDCCLKReg->ccsr));
}


// SetupUSBHostPWR:	
//
//		The root hub status register has some over-current indicator bits.
//
//		The USB Host cannot detect over-current indications itself. Over-
//		current detection must be performed by some external device on the
//		platform. In the case of the Mainstone, this is done by U53, a
//		MAX1693EUB USB Power Switch, which provides 5.0 volts to the USB
//		and also provides an over-current detection signal for use here.
//
//		Bulverde expects to get over-current indication as an input from
//		GPIO 88. Therefore, the nFAULT signal of the MAX1693EUB USB Power
//		switch on the Mainstone must be connected to GPIO 88.
//
//		GPIO 88 must be configured as an input and set to alternate function 1.
//
//		With the external circuitry wired in this fashion, and GPIO 88
//		configured as above, an assertion on the MAX1693EUB USB Power
//		Switch's nFAULT line will appear in the USB Host Root Hub status
//		register, UHCRHS, or a status register for a specific port on the 
//		root hub, UHCRHPS1 or UHCRHPS2, depending on the setting of the
//		UHCRHDA OverCurrentProtectionMode field.
//
//		Note: Over current detection must be enabled in the USB Host
//		Root Hub Descriptor A register, UHCRHDA, before assertions on 
//		GPIO 88 are detected. Furthermore, over current detection must
//		be selected as global or per-port, also via the UHCRHDA register.

void
SetupUSBHostPWR(
	int	Port
	)
{
	unsigned long	ulPinArrayParms[3];
	unsigned long	ulAlternateFunctionParms[3];
	
	// Configure GPIO 88 according to the discussion above:
	//		Direction: Input
	//		Alternate function: 1
	
	// direction & alternate function gpio apis both use the same pin array
	ulPinArrayParms[0]	= 1;
	ulPinArrayParms[1]	= 88;

	XllpGpioSetDirectionIn( v_pDCGPIOReg, ulPinArrayParms );

	ulAlternateFunctionParms[0]	= 1;
	ulAlternateFunctionParms[1] = XLLP_GPIO_ALT_FN_1;
	XllpGpioSetAlternateFn( v_pDCGPIOReg, ulPinArrayParms, ulAlternateFunctionParms );

}

// SetupUSBHostPEN:	
//
//		A USBHost platform must provide 5V to the USB. Bulverde cannot do this.
//		Bulverde cannot source 5 volts, so some external circuitry is required.
//		The MAX1693EUB USB Power Switch is a component used to provide 5 volts
//		for a USB; it also can provide an over-current indicator if any device
//		on the USB begins to draw too much current.
//
//		U53 on the Mainstone has a MAX1693EUB USB Power Switch. This part
//		is connected to a 5V power supply from the Mainstone. However, the
//		Bulverde USB Host is in control of enabling or disabling the MAX
//		1693EUB USB Power Switch. When the USB Host enables the MAX1693EUB
//		USB Power Switch by asserting the MAX1693EUB USB Power Switch's nON
//		signal, the USB V+ and V- signals provide 5 Volts. When the nON signal
//		is deasserted, the MAX1693EUB USB Power Switch turns the USB off.
//
//		The Bulverde USB Host expects to use GPIO 89 as a power enable signal.
//		The USB Host asserts or deasserts GPIO 89 by setting different bits
//		depending on the configuration of the USB Host. The configuration bits
//		that are important here are:
//
//			UHCRHDA:NoPowerSwitching (aka NPS)
//				0:	the port power will follow the global or per-port
//					power enable bits, depending UHCRHDA:PortSwitchingMode
//				1:	Not able to switch power on and off, so 
//					the port power will always be enabled.
//				
//			UHCRHDA:PowerSwitchingMode (aka PSM)
//				0:	Global Power Switching Mode, power for all ports is 
//					enabled or disabled in response to SetGlobalPower or
//					ClearGlobalPower commands.
//				1:	Per-Port Power Switching Mode, some ports can have
//					their power enabled or disabled individually with 
//					SetPortPower and ClearPortPower commands to the 
//					corresponding USB Host Root Hub Port Status registers
//					UHCRHPS1 or UHCRHPS2. In this mode, other ports can
//					respond to the global commands SetGlobalPower and 
//					ClearGlobalPower. Which type of power command the port
//					responds to is controlled by the setting of the Port
//					Power Control Mask bit for each port, found in the
//					UHCRHDB:PPCM field
//
//			Enabling / Disabling Global Power:
//				Enable:		Write 1 to UHCRHDB:LPSC
//				Disable:	Write 1 to UHCRHDB:LPS
//
//			Enabling / Disabling a specific Port's power
//				Enable:		Write 1 to UHCRHPSx:PPS
//				Disable:	Write 1 to UHCRHPSx:LDA
//				where x is 1 for Port1 or 2 for Port2
//
//			Inclusion / Exclusion from Global Set/Clear Port Power Commands
//				Inclusion:	Write 0 to UHCRHDB:PPCM[x], the corresponding port
//							will only recognize Global Set/Clear Power commands.
//							It will not respond to specific SetPortPower or
//							ClearPortPower commands.
//				Exclusion:	Write 1 to UHCRHDB:PPCM[x], the corresponding port
//							will not recognize Global Set/Clear Power commands.
//							It will only respond to specific SetPortPower or
//							ClearPortPower commands.
//				where x is 1 for Port1 or 2 for Prt2
//				note: x=0 or x>3 are reserved bits in the PPCM field.
//
//
//	Power Enable/Disable Configurations, in order of simplicity:
//
//	1.	No Power Switching:
//		Setup:
//			A. Set UHCRHDA:NoPowerSwitching to 1.	(Disallows power switching)
//
//		Comments:
//			The ports will be powered on as long as the USH Host block is on.
//
//
//	2.	Global Power Switching Mode Only:
//		Setup:
//			A. Set UHCRHDA:NoPowerSwitching to 0.	(Allows power switching)
//			B. Set UHCRHDA:PowerSwitchingMode to 0.	(Selects PowerSwitchingMode = Global)
//
//		To Enable Global Power:
//			Set UHCRHDB:LPSC to 1.					(Turn on power to all ports)
//
//		To Disable Global Power:
//			Set UHCRHDB:LPS to 1.					(Turn off power to all ports)
//
//		Comments:
//			Power switching is enabled.
//			Global Power Mode is enabled.
//			Power to all ports is enabled or disabled at the same time.
//
//
//	3.	Per Port Power Switching Mode Only:
//		Setup:
//			A. Set UHCRHDA:NoPowerSwitching to 0.	(Allows power switching)
//			B. Set UHCRHDA:PowerSwitchingMode to 1.	(Selects PowerSwitchingMode = Per-Port)
//			C. Set UHCRHDB:PPCM[1] to 1.			(Makes UHCRHP1 respond only to per port power commands)
//			D. Set UHCRHDB:PPCM[2] to 1.			(Makes UHCRHP2 respond only to per port power commands)
//
//		To Enable Port1 Power:
//			Set UHCRHPS1:PPS to 1					(Turn on power to port 1)
//
//		To Disable Port1 Power:
//			Set UHCRHPS1:LDA to 1					(Turn off power to port 1)
//
//		To Enable Port2 Power:
//			Set UHCRHPS2:PPS to 1					(Turn on power to port 2)
//
//		To Disable Port2 Power:
//			Set UHCRHPS2:LDA to 1					(Turn off power to port 2)
//
//		Comments:
//			Power switching is enabled.
//			Per Port Power switching mode is enabled.
//			Each port to participate in Per Port Power switching must set
//			its corresponding bit in the UHCRHDB:PPCM mask.
//			Power to individual ports is enabled or disabled without effecting other ports.
//			
//
//	4.	Combination Global Power Mode Switching and Per Port Power Switching Mode Only:
//		Setup:
//			A. Set UHCRHDA:NoPowerSwitching to 0.	(Allows power switching)
//			B. Set UHCRHDA:PowerSwitchingMode to 1.	(Selects PowerSwitchingMode = Per-Port)
//			C. Set UHCRHDB:PPCM[1] to 0.			(Makes UHCRHP1 respond only to per port power commands)
//			D. Set UHCRHDB:PPCM[2] to 1.			(Makes UHCRHP2 respond only to per port power commands)
//
//		To Enable Port1 Power:
//			Set UHCRHDB:LPSC to 1.					(A Global Power Command: port1 responds by turning on)
//													(Port2 remains unaffected)
//
//		To Disable Port1 Power:
//			Set UHCRHDB:LPS to 1.					(A Global Power Command: port1 responds by turning off)
//													(Port2 remains unaffected)
//
//		To Enable Port2 Power:
//			Set UHCRHPS2:PPS to 1					(Turn on power to port 2)
//													(Port1 remains unaffected)
//
//		To Disable Port2 Power:
//			Set UHCRHPS2:LDA to 1					(Turn off power to port 2)
//													(Port1 remains unaffected)
//
//		Comments:
//			This example shows port1 being controlled by Global Power Mode commands,
//			and port2 is controlled only by specific set or clear port power commands.
//			Power switching is enabled.
//			Per Port Power switching mode is enabled.

⌨️ 快捷键说明

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