serial.c
来自「i.mx27 soc for wince 6.0」· C语言 代码 · 共 981 行 · 第 1/3 页
C
981 行
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// File: serial.c
//
// This file implements the device specific functions for zeus serial device.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// INCLUDE FILES
//------------------------------------------------------------------------------
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <nkintr.h>
#include <serhw.h>
#include <memory.h>
#include <notify.h>
#include <devload.h>
#include <ceddk.h>
#include <windev.h>
#include <serdbg.h>
#include <uart.h>
#include <csp.h>
#include <serial.h>
//------------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------
extern BOOL BSPUartGetType( ULONG HWAddr, uartType_c * pType );
//------------------------------------------------------------------------------
// MACRO DEFINITIONS
//------------------------------------------------------------------------------
#define BAUD_TABLE_SIZE 23
//------------------------------------------------------------------------------
// Local Variables
static const PAIRS BaudPairs[BAUD_TABLE_SIZE] = {
{50, 2307},
{75, 1538},
{110, 1049},
{135, 858},
{150, 769},
{300, 384},
{600, 192},
{1200, 96},
{1800, 64},
{2000, 58},
{2400, 48},
{3600, 32},
{4800, 24},
{7200, 16},
{9600, 12},
{12800, 9},
{14400, 8},
{19200, 6},
{23040, 5},
{28800, 4},
{38400, 3},
{57600, 2},
{115200, 1}
};
static const LOOKUP_TBL BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) BaudPairs};
//------------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// Function: Ser_InternalMapRegisterAddresses
//
// This function retrieves the current
// properties of the communications device.
//
// Parameters:
// HWAddress
// [in] physical address of the hardware.
// Size
// [in] how much larger the address window is.
//
// Returns:
// This function returns the base virtual address
// that maps the base physical address for the range.
//
//-----------------------------------------------------------------------------
PUCHAR static Ser_InternalMapRegisterAddresses( ULONG HWAddress, ULONG Size )
{
PUCHAR ioPortBase;
ULONG inIoSpace = 1;
PHYSICAL_ADDRESS ioPhysicalBase = {HWAddress, 0};
DEBUGMSG(ZONE_FUNCTION, (TEXT("Ser_InternalMapRegisterAddresses : HalTranslateBusAddress 0x%x\r\n"), HWAddress));
if (HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) {
if (!inIoSpace) {
if ((ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE)) == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("Error mapping I/O Ports\r\n")));
return (NULL);
}
} else {
ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
}
} else {
DEBUGMSG(ZONE_ERROR, (TEXT("Error translating I/O Ports.\r\n")));
return (NULL);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("Ser_InternalMapRegisterAddresses : %d\r\n"), ioPortBase));
return (ioPortBase);
}
//-----------------------------------------------------------------------------
//
// Function: Ser_GetRegistryData
//
// This function takes the registry path provided
// to COM_Init and uses it to find this requested comm
// port's DeviceArrayIndex, the IOPort Base Address,
// and the interrupt number.
//
// Parameters:
// pSerHead
// [in] pointer to PSER_INFO structure.
// regKeyPath
// [in] the registry path passed in to COM_Init.
//
// Returns:
// TRUE if success. FALSE if failure.
//
//-----------------------------------------------------------------------------
static BOOL Ser_GetRegistryData( PSER_INFO pSerHead, LPCTSTR regKeyPath )
{
LONG regError;
HKEY hKey;
DWORD dwDataSize;
DEBUGMSG(ZONE_FUNCTION, (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.
hKey = OpenDeviceKey(regKeyPath);
if (hKey == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("Failed to open device key\r\n")));
return (FALSE);
}
// Okay, we're finally ready to try and load our registry data.
dwDataSize = PC_REG_DEVINDEX_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_DEVINDEX_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pSerHead->dwDevIndex),
&dwDataSize);
if (regError == ERROR_SUCCESS) {
dwDataSize = PC_REG_IOBASE_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pSerHead->dwIOBase),
&dwDataSize);
}
if (regError == ERROR_SUCCESS) {
dwDataSize = PC_REG_IOLEN_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOLEN_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pSerHead->dwIOLen),
&dwDataSize);
}
RegCloseKey (hKey);
if (regError != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (TEXT("Failed to get serial registry values, Error 0x%X\r\n"), regError));
return (FALSE);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("Ser_GetRegistryData-\r\n")));
return (TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: SerInit
//
// 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.
//
// Parameters:
// bIR
// [in] Is IR mode used.
// Identifier
// [in] Device identifier.
// pMDDContext
// [in] First argument to mdd callbacks.
// pHWObj
// [in] Pointer to our own HW OBJ for this device.
//
// Returns:
// The return value is a PVOID to be passed back
// into the HW dependent layer when HW functions are
// called.
//
//-----------------------------------------------------------------------------
static PVOID SerInit( BOOL bIR, ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj )
{
PSER_INFO pSerHead;
BOOL InitError = FALSE;
ULONG irq;
DEVICE_LOCATION devLoc;
uartType_c type;
DWORD dwSources;
DWORD dwTransferred;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SerInit+\r\n")));
// Allocate for our main data structure and one of it's fields.
pSerHead = (PSER_INFO)LocalAlloc(LMEM_ZEROINIT|LMEM_FIXED, sizeof(SER_INFO));
if (!pSerHead)
return(NULL);
if (!Ser_GetRegistryData(pSerHead, (LPCTSTR)Identifier)) {
DEBUGMSG(ZONE_ERROR, (TEXT("SerInit - Unable to read registry data!!\r\n")));
InitError = TRUE;
}
if (!InitError){
pSerHead->pBaseAddress = Ser_InternalMapRegisterAddresses(pSerHead->dwIOBase, pSerHead->dwIOLen);
pSerHead->pHWObj = pHWObj;
pSerHead->cOpenCount = 0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SerInit \r\n")));
if (!BSPUartGetType(pSerHead->dwIOBase, &type)) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Failed to obtain uart info.\r\n")));
return (NULL);
}
// Use kernel IOCTL to translate the UART base address into an IRQ since
// the IRQ value differs based on the SoC. Note that DEVICE_LOCATION
// fields except IfcType and LogicalLoc are ignored for internal SoC
// components.
devLoc.IfcType = Internal;
devLoc.LogicalLoc = pSerHead->dwIOBase;
if (!KernelIoControl(IOCTL_HAL_REQUEST_IRQ, &devLoc, sizeof(devLoc),
&irq, sizeof(irq), NULL))
{
ERRORMSG(1, (_T("Cannot obtain UART IRQ!\r\n")));
LocalFree(pSerHead);
DEBUGMSG(ZONE_ERROR, (TEXT("SerInit - Initialization failed!!\r\n")));
return (NULL);
}
// Use kernel IOCTL to translate the UART base address into an IRQ since
// the IRQ value differs based on the SoC. Note that DEVICE_LOCATION
// fields except IfcType and LogicalLoc are ignored for internal SoC
// components.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(DWORD),
&pSerHead->pHWObj->dwIntID, sizeof(DWORD), NULL)) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Failed to obtain sysintr value for UART interrupt.\r\n")));
LocalFree(pSerHead);
DEBUGMSG(ZONE_ERROR, (TEXT("SerInit - Initialization failed!!\r\n")));
return (NULL);
}
if (!bIR) {
dwSources = pSerHead->pHWObj->dwIntID;
if(KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &dwSources, sizeof(DWORD),
NULL, 0, &dwTransferred) == FALSE)
{
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: IOCTL_HAL_ENABLE_WAKE failed\r\n")));
LocalFree(pSerHead);
DEBUGMSG(ZONE_ERROR, (TEXT("SerInit - Initialization failed!!\r\n")));
return (NULL);
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("SerInit - bIR=%d, dwIntID=%d, irq=%d\r\n"), bIR, pSerHead->pHWObj->dwIntID, irq));
// Set up our Comm Properties data
pSerHead->CommProp.wPacketLength = 0xffff;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?