📄 bul_ohci.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
Bul_ohci.cpp
Abstract:
Bulverde Chip dependant part of the USB Open Host Controller Driver (OHCD).
Notes:
--*/
#include <windows.h>
#include <ceddk.h>
#include <hcdddsi.h>
#include <bulverde.h>
#include <bulverde_usbohci.h>
// Constant
static const DWORD gcTotalAvailablePhysicalMemory = 65536; // 64K
static const DWORD gcHighPriorityPhysicalMemory = 0x4000; // 16K
LPVOID CreateBulverdeHcdObject(LPVOID lpvHcdPddObject,
LPVOID lpvMemoryObject, LPCWSTR szRegKey, PUCHAR ioPortBase,
DWORD dwSysIntr) ;
SOhcdPdd::SOhcdPdd (LPCTSTR lpActiveRegistry)
: CMiniThread( 0, TRUE )
, CRegistryEdit(HKEY_LOCAL_MACHINE, lpActiveRegistry )
{
m_pDCCLKReg = NULL;
m_pDCUSBOHCIReg = NULL;
m_lpvMemoryObject = NULL;
m_pvDmaVirtualAddress = NULL; // DMA buffers as seen by the CPU
m_dwDamBufferSize = 0;
m_dwSysIntr = MAXDWORD;
m_IsrHandle = NULL;
m_bIsBuiltInDma = TRUE;
m_pobMem = NULL;
m_pobOhcd = NULL;
m_hParentBusHandle = CreateBusAccessHandle((LPCWSTR)g_dwContext);
m_lpDriverReg = NULL;
if (lpActiveRegistry) {
DWORD dwLen = _tcslen(lpActiveRegistry);
m_lpDriverReg = new TCHAR [ dwLen +1 ];
if (m_lpDriverReg) {
_tcscpy(m_lpDriverReg,lpActiveRegistry);
m_lpDriverReg [ dwLen ] =0;
}
}
}
SOhcdPdd::~SOhcdPdd ()
{
m_bTerminated=TRUE;
ThreadStart();
// Signal IST.
ThreadStart();
DisablePddInterrupts();
ThreadTerminated(1000);
//
if (m_IsrHandle) {
FreeIntChainHandler(m_IsrHandle);
}
if ( m_pobOhcd )
HcdMdd_DestroyHcdObject( m_pobOhcd );
if (m_pobMem)
HcdMdd_DestroyMemoryObject(m_pobMem);
if (m_pvDmaVirtualAddress) {
if (m_bIsBuiltInDma) {
MmUnmapIoSpace(m_pvDmaVirtualAddress,0);
}
else {
HalFreeCommonBuffer(&m_AdapterObject, m_dwDamBufferSize, m_DmaPhysicalAddr, m_pvDmaVirtualAddress, FALSE);
}
}
if (m_lpDriverReg)
delete m_lpDriverReg;
if (m_pDCCLKReg)
MmUnmapIoSpace((PVOID)m_pDCCLKReg,0);
if (m_pDCUSBOHCIReg)
MmUnmapIoSpace((PVOID)m_pDCUSBOHCIReg,0);
if (m_pvDmaVirtualAddress)
MmUnmapIoSpace(m_pvDmaVirtualAddress,0);
if (m_hParentBusHandle)
CloseBusAccessHandle(m_hParentBusHandle);
}
BOOL SOhcdPdd::Init()
{
{
PHYSICAL_ADDRESS ioPhysicalBase = { BULVERDE_BASE_REG_PA_CLKMGR, 0};
m_pDCCLKReg = (PBULVERDE_CLKMGR_REG)MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_CLKMGR_REG),FALSE);
}
{
PHYSICAL_ADDRESS ioPhysicalBase = { BULVERDE_BASE_REG_PA_USBH, 0};
m_pDCUSBOHCIReg = (PBULVERDE_USBOHCI_REG)MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_USBOHCI_REG),FALSE);
}
if (m_pDCCLKReg && m_pDCUSBOHCIReg && IsKeyOpened()) {
TurnOnUSBHostClocks();
// Port 1
SetupUSBHostPWR(1);
SetupUSBHostPEN(1);
// Port 2
SetupUSBHostPWR(2);
SetupUSBHostPEN(2);
return (InitPddInterrupts() && OHCI_Reset() && InitializeOHCI());
}
return FALSE;
}
BOOL SOhcdPdd::InitializeOHCI()
{
PUCHAR ioPortBase = NULL;
DWORD dwAddrLen;
DWORD dwIOSpace;
BOOL InstallIsr = FALSE;
BOOL fResult = FALSE;
LPVOID pobMem = NULL;
LPVOID pobOhcd = NULL;
DWORD PhysAddr;
HKEY hKey=NULL;
DDKWINDOWINFO dwi;
DDKISRINFO dii;
// Setup Memory Windows For OHCI MDD code.
dwi.cbSize=sizeof(dwi);
PhysAddr = dwi.memWindows[0].dwBase = BULVERDE_BASE_REG_PA_USBH;
dwAddrLen= dwi.memWindows[0].dwLen = 0x1000;
dwi.dwInterfaceType = Internal;
dwi.dwBusNumber = 0;
dwi.dwNumMemWindows =1;
dwIOSpace = 0;
dii.cbSize=sizeof(dii);
if (GetIsrInfo(&dii) != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR,(TEXT("InitializeOHCI:DDKReg_GetWindowInfo or DDKReg_GetWindowInfo failed\r\n")));
return FALSE;
}
// Overwrite the item we know.
dii.dwIrq = IRQ_USBOHCI;
m_dwSysIntr = dii.dwSysintr;
DEBUGMSG(ZONE_INIT,(TEXT("OHCD: 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", dii.dwSysintr, dwi.dwInterfaceType, dwi.dwBusNumber));
ioPortBase = (PBYTE) PhysAddr;
if (dii.szIsrDll[0] != 0 && dii.szIsrHandler[0]!=0 && dii.dwIrq<0xff && dii.dwIrq>0 ) {
// Install ISR handler
m_IsrHandle = LoadIntChainHandler(dii.szIsrDll, dii.szIsrHandler, (BYTE)dii.dwIrq);
if (!m_IsrHandle) {
DEBUGMSG(ZONE_ERROR, (L"OHCD: Couldn't install ISR handler\r\n"));
} else {
GIISR_INFO Info;
PHYSICAL_ADDRESS PortAddress = {PhysAddr, 0};
DEBUGMSG(ZONE_INIT, (L"OHCD: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d\r\n",
dii.szIsrDll, dii.szIsrHandler, dii.dwIrq));
if (!BusTransBusAddrToStatic(m_hParentBusHandle,(INTERFACE_TYPE)dwi.dwInterfaceType, dwi.dwBusNumber, PortAddress, dwAddrLen, &dwIOSpace, (PVOID *)&PhysAddr)) {
DEBUGMSG(ZONE_ERROR, (L"OHCD: Failed TransBusAddrToStatic\r\n"));
return FALSE;
}
// Set up ISR handler
Info.SysIntr = dii.dwSysintr;
Info.CheckPort = TRUE;
Info.PortIsIO = (dwIOSpace) ? TRUE : FALSE;
Info.UseMaskReg = TRUE;
Info.PortAddr = PhysAddr + 0x0C;
Info.PortSize = sizeof(DWORD);
Info.MaskAddr = PhysAddr + 0x10;
if (!KernelLibIoControl(m_IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
DEBUGMSG(ZONE_ERROR, (L"OHCD: KernelLibIoControl call failed.\r\n"));
}
}
}
DWORD dwDmaBase = 0;
DWORD dwHPPhysicalMemSize = 0;
if (!GetRegValue(BULVERDE_REG_DMA_BUFFER_PH_ADDR_VAL_NAME, (PBYTE)&dwDmaBase,BULVERDE_REG_DMA_BUFFER_PH_ADDR_VAL_LEN)) {
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::Init - Cann't get \"%s\" registry value.\r\n"),BULVERDE_REG_DMA_BUFFER_PH_ADDR_VAL_NAME));
dwDmaBase = 0;
}
if (!GetRegValue(BULVERDE_REG_DMA_BUFFER_LENGTH_VAL_NAME, (PBYTE)&m_dwDamBufferSize,BULVERDE_REG_DMA_BUFFER_LENGTH_VAL_LEN)) {
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::Init - Cann't get \"%s\" registry value.\r\n"),BULVERDE_REG_DMA_BUFFER_LENGTH_VAL_NAME));
m_dwDamBufferSize = 0;
}
if (dwDmaBase && m_dwDamBufferSize) {
m_DmaPhysicalAddr.LowPart = dwDmaBase;
m_DmaPhysicalAddr.HighPart = 0;
m_pvDmaVirtualAddress = MmMapIoSpace(m_DmaPhysicalAddr,m_dwDamBufferSize, FALSE);
dwHPPhysicalMemSize = m_dwDamBufferSize / 4 ;
m_bIsBuiltInDma = TRUE;
}
else { // we locate DMA buffer from public pool
// The PDD can supply a buffer of contiguous physical memory here, or can let the
// MDD try to allocate the memory from system RAM. We will use the HalAllocateCommonBuffer()
// API to allocate the memory and bus controller physical addresses and pass this information
// into the MDD.
if (GetRegValue(REG_PHYSICAL_PAGE_SIZE, (PBYTE)&m_dwDamBufferSize, REG_PHYSICAL_PAGE_SIZE_LEN)) {
dwHPPhysicalMemSize = m_dwDamBufferSize/4;
m_dwDamBufferSize = (m_dwDamBufferSize+ PAGE_SIZE -1) & ~(PAGE_SIZE -1);
// Align with page size.
dwHPPhysicalMemSize = ((dwHPPhysicalMemSize + PAGE_SIZE -1) & ~(PAGE_SIZE -1));
}
else
m_dwDamBufferSize=0;
if (m_dwDamBufferSize<gcTotalAvailablePhysicalMemory) { // Setup Minimun requirement.
m_dwDamBufferSize = gcTotalAvailablePhysicalMemory;
dwHPPhysicalMemSize = gcHighPriorityPhysicalMemory;
}
m_AdapterObject.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
m_AdapterObject.InterfaceType = Internal;
m_AdapterObject.BusNumber = 0 ;
if ((m_pvDmaVirtualAddress = HalAllocateCommonBuffer(&m_AdapterObject, m_dwDamBufferSize, &m_DmaPhysicalAddr, FALSE)) == NULL) {
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::InitializeOHCI() - HalAllocateCommonBuffer return FALSE!!!\r\n.\r\n")));
return FALSE;
}
m_bIsBuiltInDma = FALSE;
}
if (m_pvDmaVirtualAddress == NULL ||
!(m_pobMem = HcdMdd_CreateMemoryObject(m_dwDamBufferSize, dwHPPhysicalMemSize, (PUCHAR) m_pvDmaVirtualAddress, (PUCHAR) m_DmaPhysicalAddr.LowPart))) {
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::InitializeOHCI() - Cann't CreateMemoryObject!!!\r\n.\r\n")));
return FALSE;
}
if (!( m_pobOhcd = CreateBulverdeHcdObject(this, m_pobMem, m_lpDriverReg, (PUCHAR)m_pDCUSBOHCIReg, m_dwSysIntr))) {
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::InitializeOHCI() - Cann't CreateHcdObject!!!\r\n.\r\n")));
return FALSE;
}
return TRUE;
}
BOOL SOhcdPdd::InitPddInterrupts()
{
DEBUGMSG(ZONE_INIT, (TEXT("SOhcdPdd::InitPddInterrupts() - Initial UHCHIE = 0x%x\r\n"),m_pDCUSBOHCIReg->uhchie));
m_pDCUSBOHCIReg->uhchie = 0 ; // Mask All PDD interrupt.
return TRUE;
}
BOOL SOhcdPdd::OHCI_Reset()
{
DEBUGMSG(ZONE_INIT,(TEXT("OHCI_Reset: Resetting Bulverde OHCI.\r\n")));
// Do the reset for the Bulverde part.
// Two levels of reset need to be initiated:
// The OHCI core needs to be reset via the FHR bit,
// then the OHCI system bus interface needs to be reset via the FSBIR bit.
// reset the OHC core and all OHC blocks driven by the 12 MHz clock, eg. write fifo, etc.
m_pDCUSBOHCIReg->uhchr |= XLLP_USBOHCI_UHCHR_FHR;
Sleep(1);
m_pDCUSBOHCIReg->uhchr &= ~XLLP_USBOHCI_UHCHR_FHR;
// reset the OHC system bus interface, eg. SBI, DMA blocks, fifos, etc.
m_pDCUSBOHCIReg->uhchr |= XLLP_USBOHCI_UHCHR_FSBIR;
while( m_pDCUSBOHCIReg->uhchr & XLLP_USBOHCI_UHCHR_FSBIR ); // auto clears in 3 system bus clocks
DEBUGMSG(m_pDCUSBOHCIReg,(TEXT("OHCI_Reset: done.\r\n")));
return TRUE;
}
// 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
SOhcdPdd::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"), m_pDCCLKReg->cccr, m_pDCCLKReg->cken, m_pDCCLKReg->oscc, m_pDCCLKReg->ccsr));
m_pDCCLKReg->cken |= XLLP_CLKEN_USBHOST;
DEBUGMSG(ZONE_INIT,(TEXT("TurnOnUSBHostClocks: Final Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), m_pDCCLKReg->cccr, m_pDCCLKReg->cken, m_pDCCLKReg->oscc, m_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
SOhcdPdd::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"), m_pDCCLKReg->cccr, m_pDCCLKReg->cken, m_pDCCLKReg->oscc, m_pDCCLKReg->ccsr));
m_pDCCLKReg->cken &= ~XLLP_CLKEN_USBHOST;
DEBUGMSG(ZONE_INIT,(TEXT("TurnOfUSBHostClocks: Final Values: cccr: %08x cken: %08x oscc: %08x ccsr: %08x\n\r"), m_pDCCLKReg->cccr, m_pDCCLKReg->cken, m_pDCCLKReg->oscc, m_pDCCLKReg->ccsr));
}
void
SOhcdPdd::SelectUSBHOSTPowerManagementMode(
int Mode,
int NumPorts,
int *PortMode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -