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

📄 bvd_udc_ser.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
** INTEL CONFIDENTIAL
** Copyright 2000-2003 Intel Corporation All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors.  Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel抯
** prior express written permission.
**
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
*/

/*
Module Name: $Workfile: bvd_udc_ser.c $
$Date: 6/24/03 10:21a $
   
Abstract:  
  Contains the UDC device and endpoint configuration
  and vendor specific request codes
   
Notes: 
*/

#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include <notify.h>
#include <serhw.h>
#include <nkintr.h>
#include <OALINTR.h>
#include <devload.h>
#include <windev.h>
#undef ZONE_INIT
#include <serdbg.h>
#include <celog.h> 
#include "Bvd1.h"
#include "bvd1BD.h"
#include "bvd_udc_hw.h"
#include "bvd_udc_ser.h"


extern VOID SerialEventHandler(
		PVOID pHead);

static
DWORD WINAPI SerEventThread(
		PSER_INFO pHWHead)
{
  ULONG WaitReturn;

  DEBUGMSG( ZONE_FUNCTION|ZONE_INIT, (TEXT("+SerEventThread\r\n")));
  DEBUGMSG (ZONE_THREAD, (TEXT("Entered SerEventThread %X\r\n"),
			  pHWHead));

  DEBUGMSG(ZONE_INIT,
	   (TEXT("Spinning in dispatch thread %X\n\r"), pHWHead));

  while ( !pHWHead->pDispatchThread )
  {
    Sleep(20);
  }

  while ( !pHWHead->KillRxThread ) {
    DEBUGMSG (ZONE_THREAD, (TEXT("Event %X, Index %d, Int %d\r\n"),
			    pHWHead->hSerialEvent,
			    pHWHead->dwDevIndex,
			    pHWHead->pHWObj->dwIntID ));


    WaitReturn = WaitForSingleObject(pHWHead->hSerialEvent, INFINITE);
      
	// Checking for Cable Connect or Disconnect
	// ISR sets Driver global's uninit_misc.USBCableEvent to 1 or 2 (see below) on a USB Cable attach/detach. 
	//
	//    1 - cable attach occured
	//    2 - cable detach occured
    //    0 - no cable event handling required
	//
    // Call SA_USB_CableEvent to handle the USB Cable event
	//
	
	// Right now, uninit_misc.USBCableEvent is set appropriately for Lubbock only.
    // Make sure that uninit_misc.USBCableEvent is set appropriately for a platform other than Lubbock also.
	// Lubbock has the external peripheral interrupts coming in on GPIO0, as well as USB Cable detection.
	// For a different platform which can have USB Cable attach/detach on a different GPIO, 
	// only ISR related processing (for USB Cable attach/detach) and #if (below) should be different now.
	
    #if (BSP_MAINSTONE)
    if ((pHWHead->pDrvGlobals)->uninit_misc.USBCableEvent)
    {
		SA_USB_CableEvent (pHWHead);
        (pHWHead->pDrvGlobals)->uninit_misc.USBCableEvent = 0;
    }
    #endif

    //
    //  Process the Serial Event
    //
    SerialEventHandler(pHWHead->pMddHead);

    InterruptDone(pHWHead->pHWObj->dwIntID);
  }
    
  DEBUGMSG (ZONE_THREAD|ZONE_FUNCTION,
	    (TEXT("-SerEventThread %x exiting\r\n"),
	     pHWHead));

  return (0);
}

static
BOOL StartEventThread(
		PSER_INFO pHWHead)
{
    
  // Initialize the interrupt to be associated with the hSerialEvent
  // event. If this call fails, then another process has registered 
  // for the interrupt, so fail the init and set the hSerialEvent to NULL.
  DEBUGMSG(ZONE_INIT,
	   (TEXT("Initializing interrupt 0x%X, 0x%X\n\r"),
	    pHWHead->pHWObj->dwIntID, pHWHead->hSerialEvent));

  if ( !InterruptInitialize(pHWHead->pHWObj->dwIntID,
			    pHWHead->hSerialEvent,
			    0,
			    0) ) {

    DEBUGMSG(ZONE_INIT | ZONE_ERROR,
	     (TEXT("Error initializing interrupt\n\r")));

    return (FALSE);
  }

  InterruptDone(pHWHead->pHWObj->dwIntID);
    
  // Now set up the dispatch thread 
  pHWHead->KillRxThread = 0;

  DEBUGMSG(ZONE_INIT,
	   (TEXT("Spinning thread%X\n\r"), pHWHead));

  pHWHead->pDispatchThread = CreateThread(NULL,0, SerEventThread,
					  pHWHead, 0,NULL);
  if ( pHWHead->pDispatchThread == NULL ) {
    DEBUGMSG(ZONE_INIT|ZONE_ERROR,
	     (TEXT("Error creating Event thread (%d)\n\r"),
	      GetLastError()));
    return (FALSE);
  }

  DEBUGMSG (ZONE_INIT, (TEXT("Created Event thread %X\r\n"),
			pHWHead->pDispatchThread));

  DEBUGMSG (ZONE_INIT, (TEXT("About to set priority\r\n")));

  CeSetThreadPriority(pHWHead->pDispatchThread, DEFAULT_THREAD_PRIO);
                          
  DEBUGMSG (ZONE_INIT, (TEXT("Back from setting priority\r\n")));

  return (TRUE);
}

/*
 @doc OEM
 @func VOID | SerSetBaudRate |
 * This routine sets the baud rate of the device.
 *  Not exported to users, only to driver.
 *
 @rdesc None.
 */
static
BOOL SerSetBaudRate(
		PVOID pHead,	// @parm PVOID returned by SerInit
		ULONG BaudRate	// @parm ULONG representing decimal baud rate.
		)
{
  PSER_INFO   pHWHead = (PSER_INFO)pHead;

  DEBUGMSG(ZONE_FUNCTION,
	    (TEXT("SerSetBaudRate\r\n")));

  // Baudrate is meaningless.  Just be agreeable and say we did it.
  return ( TRUE );    
}

// ****************************************************************
//
//	@doc INTERNAL
//
//	@func VOID		| SerUSB_InternalMapRegisterAddresses |
//		This routine maps the ASIC registers. It's an artifact of this
//		implementation.
//
//	@rdesc None.
//
static
void SerUSBInternalMapRegisterAddresses(
		PSER_INFO   pHWHead)
{
  PUCHAR  pVMem;

  //
  // Page size is 4Kbytes
  // Driver Globals is also 4Kbytes 
  //
  DWORD   VMemSize=(PAGE_SIZE*5);

  BOOL    bMapReturn;
  ULONG   err = 0;
  
  DEBUGMSG(ZONE_FUNCTION,
	   (TEXT("+SerUSBInternalMapRegisterAddresses\r\n")));

    pHWHead->pUDCRegs= 0;
    pHWHead->pINTCRegs = 0;
    pHWHead->pGPIORegs= 0;
    pHWHead->pDrvGlobals = 0;

  //
  // Size needed for register space.
  //
  pVMem = (PUCHAR)VirtualAlloc(0, 
			       VMemSize, 
			       MEM_RESERVE,
 			       PAGE_NOACCESS);
                  
  if ( pVMem ) {
    DEBUGMSG(ZONE_INIT, (TEXT("VirtualAlloc Succeeded\r\n")));
    bMapReturn = VirtualCopy(pVMem,
			     (LPVOID)UDC_BASE_U_VIRTUAL,
			     PAGE_SIZE,
			     PAGE_READWRITE | PAGE_NOCACHE);
    if ( !bMapReturn ) {
      err = GetLastError();
      DEBUGMSG(ZONE_INIT, (TEXT("Virtual Copy: UDC SPACE FAILED\r\n")));
    }
    pHWHead->pUDCRegs=(volatile UDC_REGS *)pVMem;
    pVMem += PAGE_SIZE;

	bMapReturn = VirtualCopy(pVMem,
			     (LPVOID)CLK_BASE_U_VIRTUAL,
			     PAGE_SIZE,
			     PAGE_READWRITE | PAGE_NOCACHE);
    if ( !bMapReturn ) {
      err = GetLastError();
      DEBUGMSG(ZONE_INIT, (TEXT("Virtual Copy: CLK MGR FAILED\r\n")));
    }
    pHWHead->pCLKRegs=(volatile XLLP_CLKMGR_T *)pVMem;
    pVMem += PAGE_SIZE;

    bMapReturn = VirtualCopy(pVMem,
			     (LPVOID)INTC_BASE_U_VIRTUAL,
			     PAGE_SIZE,
			     PAGE_READWRITE | PAGE_NOCACHE);
    if ( !bMapReturn ) {
      err = GetLastError();
      DEBUGMSG(ZONE_INIT, (TEXT("Virtual Copy: INTC SPACE FAILED\r\n")));
    }
    //pHWHead->pINTCRegs=(volatile INTC_REGS *)pVMem;
	pHWHead->pINTCRegs=(volatile XLLP_INTC_T *)pVMem;
    pVMem += PAGE_SIZE;

    bMapReturn = VirtualCopy(pVMem,
			     (LPVOID)GPIO_BASE_U_VIRTUAL,
			     PAGE_SIZE,
			     PAGE_READWRITE | PAGE_NOCACHE);
    if ( !bMapReturn ) {
      err = GetLastError();
      DEBUGMSG(ZONE_INIT, (TEXT("Virtual Copy: GPIO SPACE FAILED\r\n")));
    }
    //pHWHead->pGPIORegs=(volatile GPIO_REGS *)pVMem;
	pHWHead->pGPIORegs=(volatile XLLP_GPIO_T *)pVMem;
    pVMem += PAGE_SIZE;

    bMapReturn = VirtualCopy(pVMem,
			     (LPVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
			     PAGE_SIZE,
			     PAGE_READWRITE | PAGE_NOCACHE);
    if ( !bMapReturn ) {
      err = GetLastError();
      DEBUGMSG(ZONE_INIT, (TEXT("Virtual Copy: Driver Globals Space Failed\r\n")));
    }
    pHWHead->pDrvGlobals =(volatile PDRIVER_GLOBALS)pVMem;

  } else {
    DEBUGMSG(ZONE_INIT, (TEXT("Virtual Alloc: FAILED\r\n")));
  }
  
  DEBUGMSG(ZONE_INIT,
	   (TEXT("VirtualCopy Succeeded  \r\n"),
	    pVMem));

  DEBUGMSG(ZONE_FUNCTION,
	   (TEXT("-SerUSBInternalMapRegisterAddresses\r\n")));
}

static
BOOL SerSetIRBaudRate(
		PSER_INFO pHWHead,
                ULONG baud	// @parm baud rate - ignored
                )
{
  DEBUGMSG (ZONE_FUNCTION,
	    (TEXT("Serial set IR Baud %d\r\n"),
	     baud));

  // We don't support IR
  return (FALSE);
}


/*++
*******************************************************************************
Routine:

    Ser_GetRegistryData

Description:

    Take the registry path provided to COM_Init and use it to find this 
    requested comm port's DeviceArrayIndex, the IOPort Base Address, and the
    Interrupt number.
   
Arguments:

    LPCTSTR regKeyPath	the registry path passed in to COM_Init.

Return Value:

    -1 if there is an error.

*******************************************************************************
--*/
static
BOOL Ser_GetRegistryData(
		PSER_INFO pHWHead,
		LPCTSTR regKeyPath)
{
#define GCI_BUFFER_SIZE 256   

  LONG    regError;
  HKEY    hKey;
  TCHAR   devKeyPath[GCI_BUFFER_SIZE];
  DWORD   dwDataSize = GCI_BUFFER_SIZE;

  DEBUGMSG(ZONE_INIT,
	   (TEXT("Ser_GetRegistryData Try to open %s\r\n"),
	    regKeyPath));

  // We've been handed the name of a key in the registry that was generated
  // on the fly by device.exe.  We're going to open that key and pull from it
  // a value that is the name of this serial port's real key.  That key
  // will have the DeviceArrayIndex that we're trying to find.  

  regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
			  regKeyPath,
			  0, 
			  KEY_ALL_ACCESS, 
			  &hKey);
  if ( regError != ERROR_SUCCESS ) {
    DEBUGMSG(ZONE_INIT | ZONE_ERROR,
	     (TEXT("Failed to open %s, Error 0x%X\r\n"),
	      regKeyPath,
	      regError));
    return ( FALSE );                
  }

  regError = RegQueryValueEx(hKey, 
			     DEVLOAD_DEVKEY_VALNAME,
			     NULL, 
			     NULL, 
			     (LPBYTE)devKeyPath,
			     &dwDataSize);

  // We're done with that registry key, so close it.
  RegCloseKey (hKey);

  if ( regError != ERROR_SUCCESS ) {
    DEBUGMSG(ZONE_INIT | ZONE_ERROR,
	     (TEXT("Failed to find data at %s\\%s, Error 0x%X\r\n"), 
	      regKeyPath, DEVLOAD_DEVKEY_VALNAME, regError));
    return ( FALSE );                
  }

  DEBUGMSG(ZONE_INIT, (TEXT("Try to open %s\r\n"), devKeyPath));

  regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
			  devKeyPath, 
			  0,
			  KEY_ALL_ACCESS, 
			  &hKey);
  if ( regError != ERROR_SUCCESS ) {
    DEBUGMSG(ZONE_INIT | ZONE_ERROR,
	     (TEXT("Failed to open %s, Error 0x%X\r\n"), 
	      devKeyPath, regError));
    return ( FALSE );        
  }

  // Okay, we're finally ready to try and load our registry data.
  dwDataSize = SA_REG_DEVINDEX_VAL_LEN;
  regError = RegQueryValueEx(hKey, 
			     SA_REG_DEVINDEX_VAL_NAME, 
			     NULL, 
			     NULL,
			     (LPBYTE)(&pHWHead->dwDevIndex), 
			     &dwDataSize);

  if ( regError == ERROR_SUCCESS ) {
    dwDataSize = SA_REG_IRQ_VAL_LEN;
    regError = RegQueryValueEx(hKey, 
			       SA_REG_IRQ_VAL_NAME, 
			       NULL, 
			       NULL,
			       (LPBYTE)(&pHWHead->dwIRQ), 
			       &dwDataSize);
  }

  if ( regError == ERROR_SUCCESS ) {
    dwDataSize = SA_REG_IOLEN_VAL_LEN;
    regError = RegQueryValueEx(hKey, 
			       SA_REG_IOLEN_VAL_NAME, 
			       NULL, 
			       NULL,
			       (LPBYTE)(&pHWHead->dwIOLen), 
			       &dwDataSize);
  }

  RegCloseKey (hKey);

  if ( regError != ERROR_SUCCESS ) {
    DEBUGMSG(ZONE_INIT | ZONE_ERROR,
	     (TEXT("Failed to get serial registry values, Error 0x%X\r\n"),
	      regError));
    return ( FALSE );
  }

  DEBUGMSG (ZONE_INIT,
	    (TEXT("SerInit - Devindex %d, IRQ %d, IOB %X, IOLen %X \r\n"),
	     pHWHead->dwDevIndex,
	     pHWHead->dwIRQ,
	     pHWHead->dwIOLen));

  return ( TRUE ); 
}



/*
 @doc OEM 
 @func PVOID | SerInit | Initializes device identified by argument.
 *  This routine sets information controlled by the user
 *  such as Line control and baud rate. It can also initialize events and
 *  interrupts, thereby indirectly managing initializing hardware buffers.
 *  Exported only to driver, called only once per process.
 *
 @rdesc The return value is a PVOID to be passed back into the HW
 dependent layer when HW functions are called.
 */
static
PVOID SerInit(
       ULONG   Identifier, // @parm Device identifier.
       PVOID   pMddHead,   // @parm First argument to mdd callbacks.
       PHWOBJ  pHWObj      // @parm Pointer to our own HW OBJ for this device
       )
{
  PSER_INFO pHWHead;
  PHYSICAL_ADDRESS PhysicalAddress = {0,0};

  //RETAILMSG(1, (TEXT("**************Ser_USB_Init\r\n")));

#ifdef DEBUG
  dpCurSettings.ulZoneMask = 0x0;
#endif

  DEBUGMSG (ZONE_INIT|ZONE_FUNCTION,
	    (TEXT("+SerInit %X\r\n"), 
	     pMddHead ));

  // Allocate for our main data structure and one of it's fields.
  pHWHead = (PSER_INFO)LocalAlloc( LPTR, sizeof(SER_INFO) );
  if ( !pHWHead )
    goto ALLOCFAILED;

  if ( ! Ser_GetRegistryData(pHWHead, (LPCTSTR)Identifier) ) {
    DEBUGMSG (ZONE_INIT|ZONE_ERROR,
	      (TEXT("SerInit - Unable to read registry data. Failing Init !!! \r\n")));
    goto ALLOCFAILED;
  }


  // Create our interrupt event.
  pHWHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);

  // Initialize our critical sections
  InitializeCriticalSection(&(pHWHead->TransmitCritSec));
  InitializeCriticalSection(&(pHWHead->HwRegCritSec));

  SerUSBInternalMapRegisterAddresses(pHWHead);
  pHWHead->pMddHead     = pMddHead;
  
  // Store info for callback function
  pHWHead->EventCallback = EvaluateEventFlag;

  pHWHead->cOpenCount   = 0;

  pHWHead->pHWObj = pHWObj;

  pHWHead->wSOFStableCnt = 0; 				
    
  // Set up our Comm Properties data    
  pHWHead->CommProp.wPacketLength      = 0xffff;
  pHWHead->CommProp.wPacketVersion     = 0xffff;
  pHWHead->CommProp.dwServiceMask      = SP_SERIALCOMM;
  pHWHead->CommProp.dwReserved1        = 0;
  pHWHead->CommProp.dwMaxTxQueue       = 16;
  pHWHead->CommProp.dwMaxRxQueue       = 16;
  pHWHead->CommProp.dwMaxBaud          = BAUD_115200;
  pHWHead->CommProp.dwProvSubType      = PST_RS232;
  pHWHead->CommProp.dwProvCapabilities =
    PCF_RLSD | 
    PCF_SETXCHAR |

⌨️ 快捷键说明

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