📄 bvd_udc_ser.c
字号:
/*
** 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 + -