4737
- 收藏
- 点赞
- 分享
- 举报
windows ce 下的串口通信代码
/*++
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.
Copyright (c) 2001-2002 SAMSUNG Electronics Corporation. All rights reserved.
Author [email]hmseo@sec.samsung.com[/email] (SAMSUNG Electronics)
Module Name:
SER2440_SER.C
Abstract:
Notes:
--*/
#define EXAMINE_BOOTARGS
#define DEBUGMODE 0
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "S2440.h"
#define USERDBG 1
#ifdef EXAMINE_BOOTARGS
#include
#include
#include
#endif
#include
#undef ZONE_INIT
#include
static BOOL IRDA;
#define BAUD_TABLE_SIZE 23
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};
// Miscellaneous internal routines.
PUCHAR
static
Ser_InternalMapRegisterAddresses(ULONG HWAddress, ULONG Size)
{
PUCHAR ioPortBase;
ULONG inIoSpace = 1;
PHYSICAL_ADDRESS ioPhysicalBase = { HWAddress, 0};
RETAILMSG(DEBUGMODE, (TEXT("+ Ser_InternalMapRegisterAddresses : HalTranslateBusAddress\r\n")));
if ( HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase))
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : HalTranslateBusAddress - OK\r\n")));
if ( !inIoSpace )
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : ! IO Space\r\n")));
if ( (ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE)) == NULL )
{
// We may as well not continue
DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error mapping I/O Ports\r\n")));
return (NULL);
}
}
else
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : IO Space\r\n")));
ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
}
}
else
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error translating I/O Ports.\r\n")));
return (NULL);
}
RETAILMSG(DEBUGMODE, (TEXT("- Ser_InternalMapRegisterAddresses : %d\r\n"),ioPortBase ));
return (ioPortBase);
}
static
BOOL
SerSetIRBaudRate(
PSER_INFO pHWHead,
ULONG baud // @parm UINT16 what is the baud rate
)
{
PS2440_UART_INFO pHWHead2 = (PS2440_UART_INFO)pHWHead;
RETAILMSG(DEBUGMODE, (TEXT("IRDA : +SerSetIRBaudRate\r\n")));
DEBUGMSG (ZONE_INIT|1, (TEXT("Serial set IR Baud %d\r\n"), baud));
if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_PCLK )
{
RETAILMSG (1, (TEXT("USE CS_PCLK\r\n")));
OUTREG(pHWHead2,rUBRDIV,( (int)(S2440PCLK/16.0/baud) -1 ));
}
else // if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_UCLK )
{
RETAILMSG (1, (TEXT("USE CS_UCLK\r\n")));
OUTREG(pHWHead2,rUBRDIV,( (int)(S2440UCLK/16.0/baud) -1 ));
}
RETAILMSG(DEBUGMODE, (TEXT("IRDA : -SerSetIRBaudRate\r\n")));
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.
PS2440_UART_INFO pHWHead2 = (PS2440_UART_INFO)pHWHead;
RETAILMSG (DEBUGMODE, (TEXT("+SerSetOutputMode\r\n")));
if(UseIR)
SETREG(pHWHead2,rULCON,SER2440_IRMODE_MASK); // Infra-red mode enable.
else
CLEARREG(pHWHead2,rULCON,SER2440_IRMODE_MASK); // Infra-red mode enable.
RETAILMSG(DEBUGMODE, (TEXT("-SerSetOutputMode\r\n")));
}
/*++
*******************************************************************************
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;
RETAILMSG(DEBUGMODE, (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_IRQ_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IRQ_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIRQ),
&dwDataSize);
}
if ( regError == ERROR_SUCCESS )
{
dwDataSize = PC_REG_IOBASE_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOBase),
&dwDataSize);
}
if ( regError == ERROR_SUCCESS )
{
dwDataSize = PC_REG_IOLEN_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOLEN_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOLen),
&dwDataSize);
}
RegCloseKey (hKey);
if ( regError != ERROR_SUCCESS )
{
RETAILMSG(DEBUGMODE, (TEXT("Failed to get serial registry values, Error 0x%X\r\n"),regError));
return ( FALSE );
}
RETAILMSG (DEBUGMODE,(TEXT("SerInit - Devindex %d, IRQ %d, IOB %X, IOLen %X \r\n"),
pHWHead->dwDevIndex, pHWHead->dwIRQ, pHWHead->dwIOBase, 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(
BOOL bIR,
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;
#ifdef EXAMINE_BOOTARGS
PVOID *ppBootArgs = NULL; // Pointer to pointer to bootargs.
PHYSICAL_ADDRESS PhysicalAddress = {0,0};
#endif
// Note on defaults. While the PC typcially considers COM1 to be at
// 3F8, irq4 and COM2 to be 2F8, irq3, NKPC uses COM1 internally for the
// debugger. So, when NK tells me to start "COM1" it really means the
// first one that's available, which is what the PC calls COM2. Confused?
// The end result is that COM1 on NK is what the PC considers to be COM2.
// But wait, there's more. On a Puzzle, the debugger is on COM2 and the
// COM1 for NK is ACTUALLY COM1. So PCs need 2F8 for their port base
// and Puzzles need 3F8.
RETAILMSG(DEBUGMODE, (TEXT("SerInit - !!! \r\n")));
// 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->pBaseAddress = Ser_InternalMapRegisterAddresses(pHWHead->dwIOBase, pHWHead->dwIOLen);
#ifdef EXAMINE_BOOTARGS
// Allocate a pointer to our bootargs since they may indicate that we don't have
// access to the hardware resource.
// First, map the bootargs pointer itself. Note that I'm reading/writing
// directly on the physical address. I can do this since I know this is CEPC and
// know the adress is not in IO space. For OEM platforms you would want to do
// HalTranslateBusAddress first.
PhysicalAddress.LowPart = BOOT_ARG_PTR_LOCATION & ~0x80000000;
if ( ppBootArgs = MmMapIoSpace(PhysicalAddress, sizeof( PVOID ), TRUE ) )
{
DEBUGMSG (ZONE_INIT, (TEXT("SerInit - ppBootArgs (%X) at %X\r\n"), PhysicalAddress.LowPart, ppBootArgs ));
}
else
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - ppBootArgs failure at %X\r\n"), PhysicalAddress.LowPart ));
goto ALLOCFAILED;
}
// Now map the bootargs structure itself
PhysicalAddress.LowPart = (DWORD) *ppBootArgs;
if ( pHWHead->pBootArgs = MmMapIoSpace(PhysicalAddress, sizeof(BOOT_ARGS), TRUE ) )
{
DEBUGMSG (ZONE_INIT, (TEXT("SerInit - pBootArgs (%X) at %X\r\n"), PhysicalAddress.LowPart, pHWHead->pBootArgs ));
}
else
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - pBootArgs failure at %X\r\n"), (DWORD)PhysicalAddress.LowPart));
goto ALLOCFAILED;
}
// We no longer need ppBootArgs
MmUnmapIoSpace( ppBootArgs, sizeof(PVOID) );
#endif // EXAMINE_BOOTARGS
pHWHead->pMddHead = pMddHead;
pHWHead->pHWObj = pHWObj;
pHWHead->cOpenCount = 0;
RETAILMSG(DEBUGMODE,(TEXT("SerInit - IRQ %d = SYSINTR %d\r\n"),
pHWHead->dwIRQ, 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 = bIR;
pHWHead->s2440COM.UseIrDA = bIR;
#ifdef EXAMINE_BOOTARGS
// Don't actually init the hardware if it is being used for debugging
if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) ) {
DEBUGMSG (ZONE_INIT|ZONE_ERROR, (TEXT("\r\nSerInit - Skipping hardware init of debug port\r\n\r\n")));
} else
#endif
{
DEBUGMSG (ZONE_INIT|USERDBG, (TEXT("SerInit - Init 16550 data\r\n")));
SL_Init( pHWHead, pHWHead->pBaseAddress, 1,
EvaluateEventFlag, pMddHead, (PLOOKUP_TBL)&BaudTable);
DEBUGMSG (ZONE_INIT,
(TEXT("SerInit - Disabling UART Power\r\n")));
SerSetOutputMode(pHWHead, FALSE, FALSE );
}
return (pHWHead);
ALLOCFAILED:
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
if ( ppBootArgs )
MmUnmapIoSpace( ppBootArgs, sizeof( PVOID ) );
if ( pHWHead->pBootArgs )
MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
LocalFree(pHWHead);
return (NULL);
}
PVOID
SerInitSerial(
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
)
{
return (SerInit(FALSE, Identifier, pMddHead, pHWObj));
}
PVOID
SerInitIR(
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
)
{
return (SerInit(TRUE, Identifier, pMddHead, pHWObj));
}
/*
@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;
RETAILMSG (DEBUGMODE,(TEXT("+SerClose\r\n")));
if ( pHWHead->cOpenCount )
{
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, closing device\r\n")));
pHWHead->cOpenCount--;
// while we are still transmitting, sleep.
uTries = 0;
while((pHWHead->s2440COM.s2440SerReg->rUFSTAT & SER2440_FIFOSTAT_MASK) & (uTries++ < 100)) // TxFifo not empty..
{
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, TX in progress.\r\n")));
Sleep(10);
}
// When the device is closed, we power it down.
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Powering down UART\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode(pHWHead, FALSE, FALSE );
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Calling SL_Close\r\n")));
SL_Close( pHWHead );
}
RETAILMSG(DEBUGMODE,(TEXT("-SerClose\r\n")));
return (0);
}
/*
@doc OEM
@func PVOID | SerDeinit | Deinitializes device identified by argument.
* This routine frees any memory allocated by SerInit.
*
*/
static
BOOL
SerDeinit(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDeinit \r\n")));
if ( !pHWHead )
return (FALSE);
// Make sure device is closed before doing DeInit
if ( pHWHead->cOpenCount )
SerClose( pHead );
SL_Deinit( pHead );
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
if ( pHWHead->pBootArgs )
MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
// Free the HWObj
LocalFree(pHWHead->pHWObj);
// And now free the SER_INFO structure.
LocalFree(pHWHead);
return (TRUE);
}
/*
@doc OEM
@func VOID | SerGetCommProperties | Retrieves Comm Properties.
*
@rdesc None.
*/
static
VOID
SerGetCommProperties(
PVOID pHead, // @parm PVOID returned by SerInit.
LPCOMMPROP pCommProp // @parm Pointer to receive COMMPROP structure.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("+SerGetCommProperties\r\n")));
*pCommProp = pHWHead->CommProp;
return;
}
/*
@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;
RETAILMSG(DEBUGMODE,(TEXT("IRDA : SerSetBaudRate \r\n")));
// If we are running in IR mode, try to set the IR baud
// first, since it supports a subset of the rates supported
// by the UART. If we fail setting the IR rate, then
// return an error and leave the UART alone.
if ( IRDA )
{
if ( ! SerSetIRBaudRate( pHWHead, BaudRate ) )
{
DEBUGMSG (ZONE_ERROR,
(TEXT("Unsupported IR BaudRate\r\n")));
// We should return an error, but vtbl doesn't expect one
return (FALSE);
}
}
// Now set buadrate on the UART
return ( SL_SetBaudRate( pHead, BaudRate ) );
}
/*
@doc OEM
@func BOOL | SerPowerOff |
* Called by driver to turn off power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
BOOL
SerPowerOff(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerPowerOff\r\n")));
SerClose( pHWHead );
// First, power down the UART
SL_PowerOff( pHWHead );
// And then disable our IR and 9 Pin interface
SerSetOutputMode( pHWHead, FALSE, FALSE );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerPowerOn |
* Called by driver to turn on power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
BOOL
SerPowerOn(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerPowerOn\r\n")));
// First, power up the UART
SL_PowerOn( pHWHead );
// And then enable our IR interface (if needed)
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerEnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerEnableIR(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerEnableIR\r\n")));
pHWHead->fIRMode = TRUE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerDisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerDisableIR(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDisableIR\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerEnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerEnableSerial(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerEnableSerial\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerDisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerDisableSerial(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDisableSerial\r\n")));
pHWHead->fIRMode = TRUE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerOpen | This routine is called when the port is opened.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerOpen(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// Disallow multiple simultaneous opens
if ( pHWHead->cOpenCount )
return (FALSE);
#ifdef EXAMINE_BOOTARGS
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Bootargs ComPort %x\r\n"), pHWHead->pBootArgs->ucComPort));
// If the port is in use as a debugger port, don't allow opens.
if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) )
{
RETAILMSG (DEBUGMODE, (TEXT("SerOpen - Fail open of debug port\r\n")));
return (FALSE);
}
#endif
pHWHead->cOpenCount++;
if ( pHWHead->fIRMode == TRUE )
RETAILMSG(DEBUGMODE,(TEXT("Use IrDA \r\n")));
else
RETAILMSG(DEBUGMODE,(TEXT("Use Serail \r\n")));
SerSetOutputMode(pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
// NOTE: - If we wanted to support 16450s, we'll could dynamically
// identify them here.
// Init SER2440 info
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Calling SL_Open\r\n")));
SL_Open( pHWHead );
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Return TRUE\r\n")));
return (TRUE);
}
const
HW_VTBL IoVTbl = {
SerInitSerial,
SL_PostInit,
SerDeinit,
SerOpen,
SerClose,
SL_GetInterruptType,
SL_RxIntr,
SL_TxIntrEx,
SL_ModemIntr,
SL_LineIntr,
SL_GetRxBufferSize,
SerPowerOff,
SerPowerOn,
SL_ClearDTR,
SL_SetDTR,
SL_ClearRTS,
SL_SetRTS,
SerEnableSerial,
SerDisableSerial,
SL_ClearBreak,
SL_SetBreak,
SL_XmitComChar,
SL_GetStatus,
SL_Reset,
SL_GetModemStatus,
SerGetCommProperties,
SL_PurgeComm,
SL_SetDCB,
SL_SetCommTimeouts,
};
extern const HW_VTBL SerCardIoVTbl;
const
HW_VTBL IrVTbl = {
SerInitIR,
SL_PostInit,
SerDeinit,
SerOpen,
SerClose,
SL_GetInterruptType,
SL_RxIntr,
SL_TxIntrEx,
SL_ModemIntr,
SL_LineIntr,
SL_GetRxBufferSize,
SerPowerOff,
SerPowerOn,
SL_ClearDTR,
SL_SetDTR,
SL_ClearRTS,
SL_SetRTS,
SerEnableIR,
SerDisableIR,
SL_ClearBreak,
SL_SetBreak,
SL_XmitComChar,
SL_GetStatus,
SL_Reset,
SL_GetModemStatus,
SerGetCommProperties,
SL_PurgeComm,
SL_SetDCB,
SL_SetCommTimeouts,
};
extern const HW_VTBL SerCardIrVTbl;
const HWOBJ IoObj = {
THREAD_AT_INIT,
SYSINTR_SERIAL,
(PHW_VTBL) &IoVTbl
};
const HWOBJ IrObj = {
THREAD_AT_INIT,
SYSINTR_IR,
(PHW_VTBL) &IrVTbl
};
typedef HWOBJ const *PCHWOBJ;
const PCHWOBJ HWObjects[] = {
&IoObj,
&IrObj
};
// GetSerialObj : The purpose of this function is to allow multiple PDDs to be
// linked with a single MDD creating a multiport driver. In such a driver, the
// MDD must be able to determine the correct vtbl and associated parameters for
// each PDD. Immediately prior to calling HWInit, the MDD calls GetSerialObject
// to get the correct function pointers and parameters.
//
PHWOBJ
GetSerialObject(DWORD DeviceArrayIndex)
{
PHWOBJ pSerObj;
RETAILMSG(DEBUGMODE,(TEXT("IRDA : GetSerialObject\r\n")));
IRDA = DeviceArrayIndex;
// Now return this structure to the MDD.
if ( DeviceArrayIndex == 0 )
pSerObj = (PHWOBJ)(&IoObj);
else
pSerObj = (PHWOBJ)(&IrObj);
return (pSerObj);
}
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.
Copyright (c) 2001-2002 SAMSUNG Electronics Corporation. All rights reserved.
Author [email]hmseo@sec.samsung.com[/email] (SAMSUNG Electronics)
Module Name:
SER2440_SER.C
Abstract:
Notes:
--*/
#define EXAMINE_BOOTARGS
#define DEBUGMODE 0
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "S2440.h"
#define USERDBG 1
#ifdef EXAMINE_BOOTARGS
#include
#include
#include
#endif
#include
#undef ZONE_INIT
#include
static BOOL IRDA;
#define BAUD_TABLE_SIZE 23
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};
// Miscellaneous internal routines.
PUCHAR
static
Ser_InternalMapRegisterAddresses(ULONG HWAddress, ULONG Size)
{
PUCHAR ioPortBase;
ULONG inIoSpace = 1;
PHYSICAL_ADDRESS ioPhysicalBase = { HWAddress, 0};
RETAILMSG(DEBUGMODE, (TEXT("+ Ser_InternalMapRegisterAddresses : HalTranslateBusAddress\r\n")));
if ( HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase))
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : HalTranslateBusAddress - OK\r\n")));
if ( !inIoSpace )
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : ! IO Space\r\n")));
if ( (ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE)) == NULL )
{
// We may as well not continue
DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error mapping I/O Ports\r\n")));
return (NULL);
}
}
else
{
DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : IO Space\r\n")));
ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
}
}
else
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error translating I/O Ports.\r\n")));
return (NULL);
}
RETAILMSG(DEBUGMODE, (TEXT("- Ser_InternalMapRegisterAddresses : %d\r\n"),ioPortBase ));
return (ioPortBase);
}
static
BOOL
SerSetIRBaudRate(
PSER_INFO pHWHead,
ULONG baud // @parm UINT16 what is the baud rate
)
{
PS2440_UART_INFO pHWHead2 = (PS2440_UART_INFO)pHWHead;
RETAILMSG(DEBUGMODE, (TEXT("IRDA : +SerSetIRBaudRate\r\n")));
DEBUGMSG (ZONE_INIT|1, (TEXT("Serial set IR Baud %d\r\n"), baud));
if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_PCLK )
{
RETAILMSG (1, (TEXT("USE CS_PCLK\r\n")));
OUTREG(pHWHead2,rUBRDIV,( (int)(S2440PCLK/16.0/baud) -1 ));
}
else // if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_UCLK )
{
RETAILMSG (1, (TEXT("USE CS_UCLK\r\n")));
OUTREG(pHWHead2,rUBRDIV,( (int)(S2440UCLK/16.0/baud) -1 ));
}
RETAILMSG(DEBUGMODE, (TEXT("IRDA : -SerSetIRBaudRate\r\n")));
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.
PS2440_UART_INFO pHWHead2 = (PS2440_UART_INFO)pHWHead;
RETAILMSG (DEBUGMODE, (TEXT("+SerSetOutputMode\r\n")));
if(UseIR)
SETREG(pHWHead2,rULCON,SER2440_IRMODE_MASK); // Infra-red mode enable.
else
CLEARREG(pHWHead2,rULCON,SER2440_IRMODE_MASK); // Infra-red mode enable.
RETAILMSG(DEBUGMODE, (TEXT("-SerSetOutputMode\r\n")));
}
/*++
*******************************************************************************
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;
RETAILMSG(DEBUGMODE, (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_IRQ_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IRQ_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIRQ),
&dwDataSize);
}
if ( regError == ERROR_SUCCESS )
{
dwDataSize = PC_REG_IOBASE_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOBase),
&dwDataSize);
}
if ( regError == ERROR_SUCCESS )
{
dwDataSize = PC_REG_IOLEN_VAL_LEN;
regError = RegQueryValueEx(
hKey,
PC_REG_IOLEN_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOLen),
&dwDataSize);
}
RegCloseKey (hKey);
if ( regError != ERROR_SUCCESS )
{
RETAILMSG(DEBUGMODE, (TEXT("Failed to get serial registry values, Error 0x%X\r\n"),regError));
return ( FALSE );
}
RETAILMSG (DEBUGMODE,(TEXT("SerInit - Devindex %d, IRQ %d, IOB %X, IOLen %X \r\n"),
pHWHead->dwDevIndex, pHWHead->dwIRQ, pHWHead->dwIOBase, 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(
BOOL bIR,
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;
#ifdef EXAMINE_BOOTARGS
PVOID *ppBootArgs = NULL; // Pointer to pointer to bootargs.
PHYSICAL_ADDRESS PhysicalAddress = {0,0};
#endif
// Note on defaults. While the PC typcially considers COM1 to be at
// 3F8, irq4 and COM2 to be 2F8, irq3, NKPC uses COM1 internally for the
// debugger. So, when NK tells me to start "COM1" it really means the
// first one that's available, which is what the PC calls COM2. Confused?
// The end result is that COM1 on NK is what the PC considers to be COM2.
// But wait, there's more. On a Puzzle, the debugger is on COM2 and the
// COM1 for NK is ACTUALLY COM1. So PCs need 2F8 for their port base
// and Puzzles need 3F8.
RETAILMSG(DEBUGMODE, (TEXT("SerInit - !!! \r\n")));
// 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->pBaseAddress = Ser_InternalMapRegisterAddresses(pHWHead->dwIOBase, pHWHead->dwIOLen);
#ifdef EXAMINE_BOOTARGS
// Allocate a pointer to our bootargs since they may indicate that we don't have
// access to the hardware resource.
// First, map the bootargs pointer itself. Note that I'm reading/writing
// directly on the physical address. I can do this since I know this is CEPC and
// know the adress is not in IO space. For OEM platforms you would want to do
// HalTranslateBusAddress first.
PhysicalAddress.LowPart = BOOT_ARG_PTR_LOCATION & ~0x80000000;
if ( ppBootArgs = MmMapIoSpace(PhysicalAddress, sizeof( PVOID ), TRUE ) )
{
DEBUGMSG (ZONE_INIT, (TEXT("SerInit - ppBootArgs (%X) at %X\r\n"), PhysicalAddress.LowPart, ppBootArgs ));
}
else
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - ppBootArgs failure at %X\r\n"), PhysicalAddress.LowPart ));
goto ALLOCFAILED;
}
// Now map the bootargs structure itself
PhysicalAddress.LowPart = (DWORD) *ppBootArgs;
if ( pHWHead->pBootArgs = MmMapIoSpace(PhysicalAddress, sizeof(BOOT_ARGS), TRUE ) )
{
DEBUGMSG (ZONE_INIT, (TEXT("SerInit - pBootArgs (%X) at %X\r\n"), PhysicalAddress.LowPart, pHWHead->pBootArgs ));
}
else
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - pBootArgs failure at %X\r\n"), (DWORD)PhysicalAddress.LowPart));
goto ALLOCFAILED;
}
// We no longer need ppBootArgs
MmUnmapIoSpace( ppBootArgs, sizeof(PVOID) );
#endif // EXAMINE_BOOTARGS
pHWHead->pMddHead = pMddHead;
pHWHead->pHWObj = pHWObj;
pHWHead->cOpenCount = 0;
RETAILMSG(DEBUGMODE,(TEXT("SerInit - IRQ %d = SYSINTR %d\r\n"),
pHWHead->dwIRQ, 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 = bIR;
pHWHead->s2440COM.UseIrDA = bIR;
#ifdef EXAMINE_BOOTARGS
// Don't actually init the hardware if it is being used for debugging
if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) ) {
DEBUGMSG (ZONE_INIT|ZONE_ERROR, (TEXT("\r\nSerInit - Skipping hardware init of debug port\r\n\r\n")));
} else
#endif
{
DEBUGMSG (ZONE_INIT|USERDBG, (TEXT("SerInit - Init 16550 data\r\n")));
SL_Init( pHWHead, pHWHead->pBaseAddress, 1,
EvaluateEventFlag, pMddHead, (PLOOKUP_TBL)&BaudTable);
DEBUGMSG (ZONE_INIT,
(TEXT("SerInit - Disabling UART Power\r\n")));
SerSetOutputMode(pHWHead, FALSE, FALSE );
}
return (pHWHead);
ALLOCFAILED:
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
if ( ppBootArgs )
MmUnmapIoSpace( ppBootArgs, sizeof( PVOID ) );
if ( pHWHead->pBootArgs )
MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
LocalFree(pHWHead);
return (NULL);
}
PVOID
SerInitSerial(
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
)
{
return (SerInit(FALSE, Identifier, pMddHead, pHWObj));
}
PVOID
SerInitIR(
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
)
{
return (SerInit(TRUE, Identifier, pMddHead, pHWObj));
}
/*
@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;
RETAILMSG (DEBUGMODE,(TEXT("+SerClose\r\n")));
if ( pHWHead->cOpenCount )
{
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, closing device\r\n")));
pHWHead->cOpenCount--;
// while we are still transmitting, sleep.
uTries = 0;
while((pHWHead->s2440COM.s2440SerReg->rUFSTAT & SER2440_FIFOSTAT_MASK) & (uTries++ < 100)) // TxFifo not empty..
{
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, TX in progress.\r\n")));
Sleep(10);
}
// When the device is closed, we power it down.
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Powering down UART\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode(pHWHead, FALSE, FALSE );
DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Calling SL_Close\r\n")));
SL_Close( pHWHead );
}
RETAILMSG(DEBUGMODE,(TEXT("-SerClose\r\n")));
return (0);
}
/*
@doc OEM
@func PVOID | SerDeinit | Deinitializes device identified by argument.
* This routine frees any memory allocated by SerInit.
*
*/
static
BOOL
SerDeinit(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDeinit \r\n")));
if ( !pHWHead )
return (FALSE);
// Make sure device is closed before doing DeInit
if ( pHWHead->cOpenCount )
SerClose( pHead );
SL_Deinit( pHead );
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
if ( pHWHead->pBootArgs )
MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
// Free the HWObj
LocalFree(pHWHead->pHWObj);
// And now free the SER_INFO structure.
LocalFree(pHWHead);
return (TRUE);
}
/*
@doc OEM
@func VOID | SerGetCommProperties | Retrieves Comm Properties.
*
@rdesc None.
*/
static
VOID
SerGetCommProperties(
PVOID pHead, // @parm PVOID returned by SerInit.
LPCOMMPROP pCommProp // @parm Pointer to receive COMMPROP structure.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("+SerGetCommProperties\r\n")));
*pCommProp = pHWHead->CommProp;
return;
}
/*
@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;
RETAILMSG(DEBUGMODE,(TEXT("IRDA : SerSetBaudRate \r\n")));
// If we are running in IR mode, try to set the IR baud
// first, since it supports a subset of the rates supported
// by the UART. If we fail setting the IR rate, then
// return an error and leave the UART alone.
if ( IRDA )
{
if ( ! SerSetIRBaudRate( pHWHead, BaudRate ) )
{
DEBUGMSG (ZONE_ERROR,
(TEXT("Unsupported IR BaudRate\r\n")));
// We should return an error, but vtbl doesn't expect one
return (FALSE);
}
}
// Now set buadrate on the UART
return ( SL_SetBaudRate( pHead, BaudRate ) );
}
/*
@doc OEM
@func BOOL | SerPowerOff |
* Called by driver to turn off power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
BOOL
SerPowerOff(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerPowerOff\r\n")));
SerClose( pHWHead );
// First, power down the UART
SL_PowerOff( pHWHead );
// And then disable our IR and 9 Pin interface
SerSetOutputMode( pHWHead, FALSE, FALSE );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerPowerOn |
* Called by driver to turn on power to serial port.
* Not exported to users, only to driver.
*
@rdesc This routine returns a status.
*/
BOOL
SerPowerOn(PVOID pHead) // @parm PVOID returned by SerInit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerPowerOn\r\n")));
// First, power up the UART
SL_PowerOn( pHWHead );
// And then enable our IR interface (if needed)
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerEnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerEnableIR(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerEnableIR\r\n")));
pHWHead->fIRMode = TRUE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerDisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerDisableIR(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDisableIR\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerEnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerEnableSerial(
PVOID pHead, // @parm PVOID returned by Serinit.
ULONG BaudRate // @parm PVOID returned by HWinit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerEnableSerial\r\n")));
pHWHead->fIRMode = FALSE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerDisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerDisableSerial(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("SerDisableSerial\r\n")));
pHWHead->fIRMode = TRUE;
SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
return (TRUE);
}
/*
@doc OEM
@func BOOL | SerOpen | This routine is called when the port is opened.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
static
BOOL
SerOpen(PVOID pHead) // @parm PVOID returned by Serinit.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
// Disallow multiple simultaneous opens
if ( pHWHead->cOpenCount )
return (FALSE);
#ifdef EXAMINE_BOOTARGS
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Bootargs ComPort %x\r\n"), pHWHead->pBootArgs->ucComPort));
// If the port is in use as a debugger port, don't allow opens.
if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) )
{
RETAILMSG (DEBUGMODE, (TEXT("SerOpen - Fail open of debug port\r\n")));
return (FALSE);
}
#endif
pHWHead->cOpenCount++;
if ( pHWHead->fIRMode == TRUE )
RETAILMSG(DEBUGMODE,(TEXT("Use IrDA \r\n")));
else
RETAILMSG(DEBUGMODE,(TEXT("Use Serail \r\n")));
SerSetOutputMode(pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
// NOTE: - If we wanted to support 16450s, we'll could dynamically
// identify them here.
// Init SER2440 info
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Calling SL_Open\r\n")));
SL_Open( pHWHead );
RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Return TRUE\r\n")));
return (TRUE);
}
const
HW_VTBL IoVTbl = {
SerInitSerial,
SL_PostInit,
SerDeinit,
SerOpen,
SerClose,
SL_GetInterruptType,
SL_RxIntr,
SL_TxIntrEx,
SL_ModemIntr,
SL_LineIntr,
SL_GetRxBufferSize,
SerPowerOff,
SerPowerOn,
SL_ClearDTR,
SL_SetDTR,
SL_ClearRTS,
SL_SetRTS,
SerEnableSerial,
SerDisableSerial,
SL_ClearBreak,
SL_SetBreak,
SL_XmitComChar,
SL_GetStatus,
SL_Reset,
SL_GetModemStatus,
SerGetCommProperties,
SL_PurgeComm,
SL_SetDCB,
SL_SetCommTimeouts,
};
extern const HW_VTBL SerCardIoVTbl;
const
HW_VTBL IrVTbl = {
SerInitIR,
SL_PostInit,
SerDeinit,
SerOpen,
SerClose,
SL_GetInterruptType,
SL_RxIntr,
SL_TxIntrEx,
SL_ModemIntr,
SL_LineIntr,
SL_GetRxBufferSize,
SerPowerOff,
SerPowerOn,
SL_ClearDTR,
SL_SetDTR,
SL_ClearRTS,
SL_SetRTS,
SerEnableIR,
SerDisableIR,
SL_ClearBreak,
SL_SetBreak,
SL_XmitComChar,
SL_GetStatus,
SL_Reset,
SL_GetModemStatus,
SerGetCommProperties,
SL_PurgeComm,
SL_SetDCB,
SL_SetCommTimeouts,
};
extern const HW_VTBL SerCardIrVTbl;
const HWOBJ IoObj = {
THREAD_AT_INIT,
SYSINTR_SERIAL,
(PHW_VTBL) &IoVTbl
};
const HWOBJ IrObj = {
THREAD_AT_INIT,
SYSINTR_IR,
(PHW_VTBL) &IrVTbl
};
typedef HWOBJ const *PCHWOBJ;
const PCHWOBJ HWObjects[] = {
&IoObj,
&IrObj
};
// GetSerialObj : The purpose of this function is to allow multiple PDDs to be
// linked with a single MDD creating a multiport driver. In such a driver, the
// MDD must be able to determine the correct vtbl and associated parameters for
// each PDD. Immediately prior to calling HWInit, the MDD calls GetSerialObject
// to get the correct function pointers and parameters.
//
PHWOBJ
GetSerialObject(DWORD DeviceArrayIndex)
{
PHWOBJ pSerObj;
RETAILMSG(DEBUGMODE,(TEXT("IRDA : GetSerialObject\r\n")));
IRDA = DeviceArrayIndex;
// Now return this structure to the MDD.
if ( DeviceArrayIndex == 0 )
pSerObj = (PHWOBJ)(&IoObj);
else
pSerObj = (PHWOBJ)(&IrObj);
return (pSerObj);
}
我来回答
回答0个
时间排序
认可量排序
暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2008-05-27 11:09:53
-
2010-06-01 23:25:04
-
2008-08-18 22:21:13
-
2008-07-12 19:14:12
-
2008-07-24 01:33:17
-
2012-12-05 14:39:10
-
2012-12-05 14:32:53
-
2012-12-05 11:12:01
-
2012-12-05 11:13:14
-
2010-06-01 23:29:28
-
2012-12-05 14:27:39
-
2012-12-05 13:33:42
-
2012-12-05 11:07:55
-
2008-11-02 17:14:58
-
2012-12-05 13:34:26
-
2012-12-05 13:38:25
-
2012-12-04 14:09:01
-
2012-12-04 14:17:38
-
2012-12-04 13:36:34
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认