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

📄 ohcdpdd.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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:  
    system.c
    
Abstract:  
    Device dependant part of the USB Universal Host Controller Driver (UHCD).

Notes: 
--*/


#ifdef USBOHCI_DMA_IN_SRAM
#pragma message ("OHCI using Internal SRAM")
#else
#pragma message ("OHCI using SDRAM")
#endif

#ifdef OSV_LOCAL_MERLIN
#pragma message ("build is for MERLIN")
#else
#pragma message ("build is not for MERLIN")
#endif

#ifdef TRANSLATE_ADDRESSES
#pragma message ("build is for TRANSLATE_ADDRESSES")
#else
#pragma message ("build is not for TRANSLATE_ADDRESSES")
#endif


#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <devload.h>


#include <uhcdddsi.h>
#include "bvd1.h"


// Bulverde will use XLLP library to
// access GPIOs and Clocks.

#include "xllp_gpio.h"
#include "xllp_clkmgr.h"
#include "xllp_usbohci.h"


// Registry key and value names
#define OHCI_DRIVER_KEY         TEXT("Drivers\\BuiltIn\\OHCI")
#define IRQ_VALUE_NAME          TEXT("Irq")
#define IOBASE_VALUE_NAME       TEXT("MemBase")

extern void msWait(unsigned msVal);
extern void usWait(unsigned msVal); 
extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);
void TurnOnSRAMClocks();

// Amount of memory to use for HCD buffer
extern DWORD gcTotalAvailablePhysicalMemory;// = OHCI_DMA_BUFFER_SIZE; //28672; // 28K
extern DWORD gcHighPriorityPhysicalMemory;// = OHCI_DMA_BUFFER_HIGHPRI_SIZE; //0x5000; // 20K
extern DWORD dwSysIntrOhciMdd;//=SYSINTR_OHCI_MDD;
extern DWORD dwSysIntrOhciPdd;//=SYSINTR_OHCI_PDD

//Dma Buffer
extern DWORD dwOhciDmaBufferPhysical;//=OHCI_DMA_BUFFER_PHYSICAL
extern PVOID pOhciDmaBufferVirtual;//=OHCI_DMA_BUFFER_U_VIRTUAL
extern DWORD dwOhciDmaBufferSize;//=OHCI_DMA_BUFFER_SIZE


volatile XLLP_CLKMGR_T		*v_pDCCLKReg;
XLLP_GPIO_T					*v_pDCGPIOReg;
volatile XLLP_USBOHCI_T		*v_pDCUSBOHCIReg;

PVOID						v_pOHCIDMABuffer;

volatile MEMC_STRUCT		*v_pDCMEMCReg;	// on the cotulla, xsc1.h


// Interrupt Service Thread Globals
VOID	*gOHCIPDDIntrEvent;
VOID	*gOHCIPDDIntrThread;

static HANDLE g_IsrHandle = NULL;

typedef struct _SUhcdPdd
{
    LPVOID lpvMemoryObject;
    LPVOID lpvUhcdMddObject;
    PVOID pvVirtualAddress;                        // DMA buffers as seen by the CPU
    PHYSICAL_ADDRESS LogicalAddress;        // DMA buffers as seen by the DMA controller and bus interfaces
    DMA_ADAPTER_OBJECT AdapterObject;
    TCHAR szDriverRegKey[MAX_PATH];
    PUCHAR ioPortBase;
    DWORD dwSysIntr;
    CRITICAL_SECTION csPdd;                     // serializes access to the PDD object
} SUhcdPdd;

#define UnusedParameter(x)  x = x

// set up virtual addresses for registers on the sa11x1
BOOL
OhcdPddInitializeAddresses(void)
{
    
	// the bulverde needs access to the clkmgr to enable the USBHOST clock 
	v_pDCCLKReg = (volatile XLLP_CLKMGR_T*)
		VirtualAllocCopy(sizeof(XLLP_CLKMGR_T), "OHCI v_pDCCLKReg", (PVOID)(CLK_BASE_U_VIRTUAL));
	if( v_pDCCLKReg == NULL ) {
		goto error_return;
	}

	// the bulverde needs access to the gpio regs to set up the gpios that
	// are tied to the external MAX1693EUB USB Power Switch
	v_pDCGPIOReg = (/*volatile*/ XLLP_GPIO_T*)
		VirtualAllocCopy(sizeof(XLLP_GPIO_T), "OHCI v_pDCGPIOReg", (PVOID)(GPIO_BASE_U_VIRTUAL));
	if( v_pDCCLKReg == NULL ) {
		goto error_return;
	}

	// map the usb ohci register block.
	// use the old cotulla global pointer for now.
	// later, during code clean up, consolidate the two pointers into one
	// and reconcile their usage differences.
    v_pDCUSBOHCIReg = (volatile XLLP_USBOHCI_T*)
        VirtualAllocCopy(sizeof(XLLP_USBOHCI_T),"OHCI v_pDCUSBOHCIReg: ",(PVOID)(USBH_BASE_U_VIRTUAL));
    if (v_pDCUSBOHCIReg == NULL) {
		goto error_return;
    }


#ifdef USBOHCI_DMA_IN_SRAM
	// initialize the sram here.
	{
		volatile unsigned long	*v_pDCIMReg = NULL;

		// map the memory
		v_pDCIMReg = (volatile unsigned long*)VirtualAllocCopy( 
													sizeof( 64 * sizeof( volatile unsigned long ) ), 
													"OHCI v_pDCIMReg: ", 
													(PVOID)(IM_CONTROL_BASE_U_VIRTUAL)
													);
		if( v_pDCIMReg == NULL )
		{
			// error
			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: failed mapping v_pDCIMReg to %08x.\r\n"), IM_CONTROL_BASE_U_VIRTUAL));
		}
		else
		{
			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg:       %08x = %08x.\r\n"), v_pDCIMReg,IM_CONTROL_BASE_U_VIRTUAL));

			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg: impmr %08x.\r\n"), v_pDCIMReg[0] ));
			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg: impsr %08x.\r\n"), v_pDCIMReg[2] ));
			// I don't think the imrmr register really exists
			//RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg: imrmr %08x.\r\n"), v_pDCIMReg[4] ));

			// test access to this memory
			v_pDCIMReg[0] = 188;		// the control register, 0 enables all internal sram banks, disables auto-wake and disables entry to standby
			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg:Mimpmr %08x.\r\n"), v_pDCIMReg[0] ));

			// set the bank power control, auto wake enable, and DST fields
			v_pDCIMReg[0] = 0;		// the control register, 0 enables all internal sram banks, disables auto-wake and disables entry to standby
			RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCIMReg:Fimpmr %08x.\r\n"), v_pDCIMReg[0] ));


			// free the mapped memory
			VirtualFree((PVOID)v_pDCIMReg,0,MEM_RELEASE);
		}
	}

    v_pOHCIDMABuffer = 
        //		VirtualAllocCopy(OHCI_DMA_BUFFER_SIZE,"OHCI v_pOHCIDMABuffer", (PVOID) OHCI_DMA_BUFFER_U_VIRTUAL);
        VirtualAllocCopy(dwOhciDmaBufferSize,"OHCI v_pOHCIDMABuffer", (PVOID)(IM_STORAGE_BASE_U_VIRTUAL +0x30000));
    if (v_pOHCIDMABuffer == NULL) {
        goto error_return;
    }

	{
		// Test access to the OHCIDMABuffer:
		volatile unsigned long	*pulTemp = (volatile unsigned long*)v_pOHCIDMABuffer;

		// the SRAM needs to be clocked, just like other memory and peripherals.
		TurnOnSRAMClocks();

		RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: testing access to OHCIDMABuffer %08x mapped to %08x.\r\n"), IM_STORAGE_BASE_U_VIRTUAL+0x30000, pulTemp ));
		RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: 00-0f: %08x %08x %08x %08x\r\n"), pulTemp[0], pulTemp[1], pulTemp[2], pulTemp[3] ));
		RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: 10-1f: %08x %08x %08x %08x\r\n"), pulTemp[4], pulTemp[5], pulTemp[6], pulTemp[7] ));
		
		pulTemp[0] = 188;
		pulTemp[1] = 189;
		pulTemp[2] = 190;
		pulTemp[3] = 191;
		pulTemp[4] = 192;
		pulTemp[5] = 193;
		pulTemp[6] = 194;
		pulTemp[7] = 195;

		RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses:M00-0f: %08x %08x %08x %08x\r\n"), pulTemp[0], pulTemp[1], pulTemp[2], pulTemp[3] ));
		RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses:M10-1f: %08x %08x %08x %08x\r\n"), pulTemp[4], pulTemp[5], pulTemp[6], pulTemp[7] ));
	}

	// change the value of a global pointer that contains the uncached virtual address
	// of the memory buffer used to hold the usb structures. usb structures are built
	// in this area, and the USB OHCI reads and writes to this area, also.
	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: dwohciBPhy: old   %08x.\r\n"), dwOhciDmaBufferPhysical));
	dwOhciDmaBufferPhysical = (IM_STORAGE_BASE_PHYSICAL+0x30000);
	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: dwohciBPhy: new   %08x.\r\n"), dwOhciDmaBufferPhysical));


#else
    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) {
        goto error_return;
    }
#endif



//	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCCLKReg:      %08x = %08x.\r\n"), v_pDCCLKReg,CLK_BASE_U_VIRTUAL));
//	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCGPIOReg:     %08x = %08x.\r\n"), v_pDCGPIOReg,GPIO_BASE_U_VIRTUAL));

#ifdef USBOHCI_DMA_IN_SRAM
	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pOHCIDMABuffer: %08x = %08x.\r\n"), v_pOHCIDMABuffer,IM_STORAGE_BASE_U_VIRTUAL+0x30000));
#else
//	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pOHCIDMABuffer: %08x = %08x.\r\n"), v_pOHCIDMABuffer,pOhciDmaBufferVirtual));
#endif

//	RETAILMSG(ZONE_INIT,(TEXT("OhcdPddInitializeAddresses: v_pDCUSBOHCIReg:      %08x = %08x.\r\n"), v_pDCUSBOHCIReg,USBH_BASE_U_VIRTUAL));

    return TRUE;

error_return:
    ERRORMSG(1,(TEXT("OHCI Driver InitializeAddresses: Failed!.\r\n")));  
	if (v_pDCCLKReg)	VirtualFree((PVOID)v_pDCCLKReg,0,MEM_RELEASE);
	if (v_pDCGPIOReg)	VirtualFree((PVOID)v_pDCGPIOReg,0,MEM_RELEASE);

    if (v_pDCUSBOHCIReg)	VirtualFree((PVOID)v_pDCUSBOHCIReg,0,MEM_RELEASE);
    if (v_pOHCIDMABuffer)	VirtualFree((PVOID)v_pOHCIDMABuffer,0,MEM_RELEASE);


	v_pDCCLKReg		= 0;
	v_pDCGPIOReg	= 0;

	v_pDCUSBOHCIReg	   = 0;
	v_pOHCIDMABuffer = 0;
    
    return 0;	
}

VOID OHCI_Reset()
{

   RETAILMSG(1,(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.
	v_pDCUSBOHCIReg->uhchr |=  XLLP_USBOHCI_UHCHR_FHR;
	msWait( 1 );		// ten micro second wait called for by spec.
	v_pDCUSBOHCIReg->uhchr &= ~XLLP_USBOHCI_UHCHR_FHR;

	// reset the OHC system bus interface, eg. SBI, DMA blocks, fifos, etc.
	v_pDCUSBOHCIReg->uhchr |=  XLLP_USBOHCI_UHCHR_FSBIR;
	while( v_pDCUSBOHCIReg->uhchr & XLLP_USBOHCI_UHCHR_FSBIR );	// auto clears in 3 system bus clocks

	// now set the polarity fields so the OHCI knows to:
	//		assert or deassert the power control signals to power or shutdown a port, and
	//		detect overcurrent indication from assertion or de-assertion of the power sense signals.

	// note: the correcting settings for these values are determined by the board layout and the
	// external voltage regulators in use. In the case of the Mainstone, the external voltage
	// regulator is a MAX1693EUB USB Power Switch, which uses negative polarity for power enable
	// and for fault notification.
	v_pDCUSBOHCIReg->uhchr |=  XLLP_USBOHCI_UHCHR_PCPL;			// bit = 1 means power control polarity is active low
	v_pDCUSBOHCIReg->uhchr |=  XLLP_USBOHCI_UHCHR_PSPL;			// bit = 1 means power (ie. over-current) sense polarity is active low

//	v_pDCUSBOHCIReg->uhchr |=  XLLP_USBOHCI_UHCHR_SSEP1;		// keep port 1 in sleep/standby (eg. disable port 1)
	v_pDCUSBOHCIReg->uhchr &= ~XLLP_USBOHCI_UHCHR_SSEP1;		// for port 1, enable power to the single ended receivers and the port (DevMan says to do this)
	v_pDCUSBOHCIReg->uhchr &= ~XLLP_USBOHCI_UHCHR_SSEP0;		// for port 0, enable power to the single ended receivers and the port
	v_pDCUSBOHCIReg->uhchr &= ~XLLP_USBOHCI_UHCHR_SSE;			// allow the values of SSEP1 and SSPE0 to control the power.

   RETAILMSG(1,(TEXT("OHCI_Reset: done.\r\n")));
}

// handle PDD interrupts
INT WINAPI OHCIPDDIntrThread(LPVOID lpvParam)
{
    BOOL fKnownInterrupt;
    UnusedParameter(lpvParam);

	RETAILMSG(1,(TEXT("OHCIPDD INTR Thread: Started.\r\n")));

    while (1) {
        WaitForSingleObject(gOHCIPDDIntrEvent, INFINITE);


		if( v_pDCUSBOHCIReg->uhcstat )
		{
			RETAILMSG(1,(TEXT("OHCIPdd Int Thread uhcstat: %08x.\r\n"), v_pDCUSBOHCIReg->uhcstat ));

			// clear the interrupt:
			v_pDCUSBOHCIReg->uhcstat = v_pDCUSBOHCIReg->uhcstat;

			RETAILMSG(1,(TEXT("OHCIPdd Int Thread new uhcstat: %08x.\r\n"), v_pDCUSBOHCIReg->uhcstat ));

			fKnownInterrupt = TRUE;
		}


        if(!fKnownInterrupt) {
            RETAILMSG(1, (TEXT("OHCIPdd Int Thread No known Event\r\n")));
        }

#if 0   // allow HcdPdd_ResumeThread() to handle resume notifications 
        //if the USB clock is on go through reset sequence to start up the USB
        // otherwise let normal HC int process
        //Right now only Port Resume interrupts are enabled
        if (!v_pDCPLLReg->skpcrBits[0].UCLKEn)	{ 
            RETAILMSG(1, (TEXT("OHCIPdd Int Port Resume, reseting Sense Event\r\n")));
            OHCI_Reset();
        }
#endif  // boolean

        //DEBUGMSG(ZONE_INIT, (TEXT("OHCI PDD INTR Thread called P\r\n")));
        InterruptDone(dwSysIntrOhciPdd/*SYSINTR_OHCI_PDD*/);
    }

	RETAILMSG(1,(TEXT("OHCIPDD INTR Thread: Ended.\r\n")));
}


// This PDD will set up two interrupt service threads, 
// first we create a thread to service the SA-1111 non-OHCI host controller interrupts
// Then in InitializeOHCI we hook the SA-1111 OHCI host controller interrupt in to the MDD
BOOL InitPddInterrupts(void)
{
    

    gOHCIPDDIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    
    if (!(InterruptInitialize(dwSysIntrOhciPdd/*SYSINTR_OHCI_PDD*/, gOHCIPDDIntrEvent, NULL, 0))) {
        DEBUGMSG(ZONE_INIT, (TEXT("OHCI PDD INTR INIT Failed\r\n")));
        DEBUGMSG(ZONE_INIT, (TEXT("OHCI PDD INTR INIT ERR: 0x%x\r\r"), GetLastError()));
        //return NULL;		
        return FALSE;		
    }
/*
    gOHCIPDDIntrThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) OHCIPDDIntrThread, NULL, 0, NULL);
    if ( gOHCIPDDIntrThread == NULL ) {
        ERRORMSG(1, (TEXT("Fatal Error!  Failed to create OHCIPDD interrupt thread.\r\n")));
        return (FALSE);
    } else {
        DEBUGMSG(ZONE_INIT, (TEXT("-OHCIPDD  Init\r\n")));
        //return TRUE;
    }
*/    
    RETAILMSG(1, (TEXT("InitPddInterrupts RhPortStatus: 0x%x.\r\n"), v_pDCUSBOHCIReg->uhcrhs));
    return TRUE;
}


/* HcdPdd_DllMain
 * 
 *  DLL Entry point.
 *
 * Return Value:
 */
extern BOOL HcdPdd_DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
    UnusedParameter(hinstDLL);
    UnusedParameter(dwReason);
    UnusedParameter(lpvReserved);
    RETAILMSG(1, (TEXT("Modified File: ohcd.c.\r\n")));

    return TRUE;
}


/* GetRegistryConfig
 *  
 *   Note: Will need to be changed to support multiple instances.
 *
 * Return Value:
 *   TRUE for success, FALSE for error
 */
static BOOL
GetRegistryConfig(
    LPCWSTR RegKeyPath,         // IN - driver registry key path
    DWORD * lpdwBaseAddr,       // OUT - base address
    DWORD * lpdwAddrLen,        // OUT - address range
    DWORD * lpdwIOSpace,        // OUT - 1 if base address describes I/O port, 0 otherwise
    DWORD * lpdwSysIntr,        // OUT - system interrupt number
    PINTERFACE_TYPE lpIfcType,  // OUT - interface type (PCIbus, ISAbus, etc)

⌨️ 快捷键说明

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