pl010com.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 615 行 · 第 1/2 页
C
615 行
/*++
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.
Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
Module Name:
Abstract:
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include "pl010ser.h"
#include <serhw.h>
#include <ser16550.h>
#include <hw16550.h>
#include <nkintr.h>
#include <devload.h>
#include "pl010com.h"
#include <platform.h>
#include <board.h>
#include <oalintr.h>
#undef ZONE_INIT
#include <serdbg.h>
// #define DBGMSG
#define DBGMSG NKDbgPrintfW
#define BAUD_TABLE_SIZE 10
static const PAIRS BaudPairs[BAUD_TABLE_SIZE] =
{
{1200 , ARM_BAUD_1200},
{2400 , ARM_BAUD_2400},
{9600 , ARM_BAUD_9600},
{14400 , ARM_BAUD_14400},
{19200 , ARM_BAUD_19200},
{38400 , ARM_BAUD_38400},
{57600 , ARM_BAUD_57600},
{115200, ARM_BAUD_115200},
{230400, ARM_BAUD_230400},
{460800, ARM_BAUD_460800}
};
static const
LOOKUP_TBL BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) BaudPairs};
// Macros to read/write serial registers.
#define INB(pInfo, reg) (READ_PORT_UCHAR((UCHAR *)((pInfo)->reg)))
VOID SL_Init2(
PVOID pHead, // points to device head
PUCHAR pRegBase, // Pointer to 16550 register base
EVENT_FUNC EventCallback, // This callback exists in MDD
PVOID pMddHead, // This is the first parm to callback
PLOOKUP_TBL pBaudTable // Pointer to baud rate table
);
static
BOOL
SerSetIRBaudRate(
PSER_INFO pHWHead,
ULONG baud // @parm UINT16 what is the baud rate
)
{
DEBUGMSG (ZONE_INIT, (TEXT("Serial set IR Baud %d\r\n"),
baud));
return (TRUE);
}
/*
* NOTE : The caller should have set pHWHead->fIRMode. It is not
* set here, since power on/off may need to temporarily disable
* the intefaces without actually overwriting the current recorded
* mode.
*/
static
void
SerSetOutputMode(
PSER_INFO pHWHead,
BOOL UseIR, // @parm BOOL Should we use IR interface
BOOL Use9Pin // @parm BOOL Should we use Wire interface
)
{
// If you support IR, here you need to set the interface to either IR mode
// or normal serial. Note that it is possible for both BOOls to
// be false (i.e. power down), but never for both to be TRUE.
}
/*++
*******************************************************************************
Routine:
Ser_GetRegistryData
Description:
Take the registry path provided to COM_Init and use it to find this
requested comm port's DeviceArrayIndex, teh 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.
*******************************************************************************
--*/
BOOL
Ser_GetRegistryData(PSER_INFO pHWHead, LPCTSTR regKeyPath)
{
#define GCI_BUFFER_SIZE 256
LONG regError;
HKEY hKey;
DWORD dwDataSize = GCI_BUFFER_SIZE;
DEBUGMSG(ZONE_INIT, (TEXT("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_INIT | 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)(&pHWHead->dwDevIndex),
&dwDataSize);
if ( regError == ERROR_SUCCESS ) {
dwDataSize = PC_REG_SYSINTR_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_SYSINTR_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwSysIntr),
&dwDataSize);
}
if ( regError == ERROR_SUCCESS ) {
dwDataSize = PC_REG_IOBASE_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->pBaseAddress),
&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 (1|ZONE_INIT,
(TEXT("SerInit - Devindex %d, SysIntr %d, IOB %X, IOLen %X \r\n"),
pHWHead->dwDevIndex, pHWHead->dwSysIntr, pHWHead->pBaseAddress, 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;
// Allocate for our main data structure and one of it's fields.
pHWHead = (PSER_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED ,
sizeof(SER_INFO) );
if ( !pHWHead )
return( NULL );
if ( ! Ser_GetRegistryData(pHWHead, (LPCTSTR)Identifier) ) {
DEBUGMSG (ZONE_INIT|ZONE_ERROR,
(TEXT("SerInit - Unable to read registry data. Failing Init !!! \r\n")));
goto ALLOCFAILED;
}
pHWHead->pMddHead = pMddHead;
pHWHead->pHWObj = pHWObj;
pHWHead->cOpenCount = 0;
// Legacy - We have 2 identical fields becausw registry used to contain IRQ
pHWHead->pHWObj->dwIntID = pHWHead->dwSysIntr;
DEBUGMSG (1|ZONE_INIT,
(TEXT("SerInit - SYSINTR %d\r\n"), pHWHead->pHWObj->dwIntID));
// 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_DTRDSR | PCF_RLSD | PCF_RTSCTS |
PCF_SETXCHAR |
PCF_INTTIMEOUTS |
PCF_PARITY_CHECK |
PCF_SPECIALCHARS |
PCF_TOTALTIMEOUTS |
PCF_XONXOFF;
pHWHead->CommProp.dwSettableBaud =
BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
BAUD_7200 | BAUD_9600 | BAUD_14400 |
BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
BAUD_115200 | BAUD_57600 | BAUD_USER;
pHWHead->CommProp.dwSettableParams =
SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
pHWHead->CommProp.wSettableData =
DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
pHWHead->CommProp.wSettableStopParity =
STOPBITS_10 | STOPBITS_20 |
PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
PARITY_MARK;
pHWHead->fIRMode = FALSE; // Select wired by default
// Init 16550 info
DEBUGMSG (ZONE_INIT, (TEXT("SerInit - Init 16550 data\r\n")));
SL_Init2( pHWHead, pHWHead->pBaseAddress, EvaluateEventFlag, pMddHead, (PLOOKUP_TBL)&BaudTable);
DEBUGMSG (ZONE_INIT,
(TEXT("SerInit - Disabling UART Power\r\n")));
SerSetOutputMode(pHWHead, FALSE, FALSE );
return (pHWHead);
ALLOCFAILED:
LocalFree(pHWHead);
return (NULL);
}
/*
@doc OEM
@func ULONG | SerClose | This routine closes the device identified by the PVOID returned by SerInit.
* Not exported to users, only to driver.
*
@rdesc The return value is 0.
*/
static
ULONG
SerClose(
PVOID pHead // @parm PVOID returned by SerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
ULONG uTries;
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_CLOSE,(TEXT("+SerClose\r\n")));
if ( pHWHead->cOpenCount ) {
DEBUGMSG (ZONE_CLOSE,
(TEXT("SerClose, closing device\r\n")));
pHWHead->cOpenCount--;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?