📄 serial.c
字号:
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 = NULL;
BOOL InitError = FALSE;
ULONG irq;
DEVICE_LOCATION devLoc;
uartType_c type;
DWORD dwSources;
DWORD dwTransferred;
UINT16 rxDMASize, txDMASize;
DEBUGMSG(ZONE_INIT, (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;
}
BSPUartConfigureGPIO(pSerHead->dwIOBase, TRUE);
BSPUartConfigTranceiver(pSerHead->dwIOBase,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);
}
#if 0
if (!BSPUartGetIrq(pSerHead->dwIOBase, &irq)) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Failed to obtain uart info.\r\n")));
LocalFree(pSerHead);
DEBUGMSG(ZONE_ERROR, (TEXT("SerInit - Initialization failed!!\r\n")));
return (NULL);
}
#endif
// 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);
}
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);
}
pSerHead->irq = irq;
// find out if DMA is desired for this UART or not.
pSerHead->useDMA = BSPSerGetDMAIsEnabled(pSerHead->dwIOBase);
if (pSerHead->useDMA)
{
DEBUGMSG(ZONE_FLOW, (TEXT("SerInit: DMA enabled for this UART\r\n")));
BSPGetDMABuffSize(&rxDMASize,&txDMASize);
pSerHead->rxDMABufSize = rxDMASize;
pSerHead->txDMABufSize = txDMASize;
if(!InitDMA(pSerHead))
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: InitDMA failed\r\n")));
}
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);
}
}
// Set up our Comm Properties data
pSerHead->CommProp.wPacketLength = 0xffff;
pSerHead->CommProp.wPacketVersion = 0xffff;
pSerHead->CommProp.dwServiceMask = SP_SERIALCOMM;
pSerHead->CommProp.dwReserved1 = 0;
pSerHead->CommProp.dwMaxTxQueue = 32;
pSerHead->CommProp.dwMaxRxQueue = 32;
pSerHead->CommProp.dwMaxBaud = BAUD_115200;
pSerHead->CommProp.dwProvSubType = PST_RS232;
pSerHead->CommProp.dwProvCapabilities =
PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
PCF_SETXCHAR | PCF_INTTIMEOUTS |
PCF_PARITY_CHECK | PCF_SPECIALCHARS |
PCF_TOTALTIMEOUTS | PCF_XONXOFF;
pSerHead->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;
pSerHead->CommProp.dwSettableParams =
SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
pSerHead->CommProp.wSettableData =
// DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
DATABITS_7 | DATABITS_8;
pSerHead->CommProp.wSettableStopParity =
STOPBITS_10 | STOPBITS_20 |
// PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
// PARITY_MARK;
PARITY_NONE | PARITY_ODD | PARITY_EVEN;
pSerHead->fIRMode = bIR;
SL_Init(bIR, type, pSerHead->dwIOBase, pSerHead->pBaseAddress,
pSerHead, EvaluateEventFlag, pMDDContext, (PLOOKUP_TBL)&BaudTable);
return (pSerHead);
}
else {
if (pSerHead->pBaseAddress)
MmUnmapIoSpace(pSerHead->pBaseAddress, pSerHead->dwIOLen);
LocalFree(pSerHead);
DEBUGMSG(ZONE_INIT, (TEXT("SerInit - Initialization failed!!\r\n")));
return (NULL);
}
}
//-----------------------------------------------------------------------------
//
// Function: SerSerialInit
//
// This function calls SerInit to initialize serial device.
//
// Parameters:
// 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 SerSerialInit( ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj )
{
DEBUGMSG(ZONE_INIT,(TEXT("SerSerialInit+\r\n")));
return (SerInit(FALSE, Identifier, pMDDContext, pHWObj));
}
//-----------------------------------------------------------------------------
//
// Function: SerIRInit
//
// This function calls SerInit to initialize serial IR device.
//
// Parameters:
// 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 SerIRInit( ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj )
{
DEBUGMSG(ZONE_INIT,(TEXT("SerIRInit+\r\n")));
return (SerInit(TRUE, Identifier, pMDDContext, pHWObj));
}
//-----------------------------------------------------------------------------
//
// Function: SerPostInit
//
// This function is called by the upper layer to
// perform any necessary operations after initializing
// all data structures and prepare the serial IST to
// begin handling interrupts. This call occurs as the
// last step of the COM_Init routine.
//
// Parameters:
// pContext
// [in] Pointer to a context structure returned
// by SerInit function that contains implementation-
// specific data describing the hardware device.
//
// Returns:
// TRUE if success. FALSE if failure.
//
//-----------------------------------------------------------------------------
static BOOL SerPostInit( PVOID pContext )
{
DEBUGMSG(ZONE_INIT,(TEXT("SerPostInit+\r\n")));
// Since we are just a library which might get used for
// builtin ports which init at boot, or by PCMCIA ports
// which init at Open, we can't do anything too fancy.
// Lets just make sure we cancel any pending interrupts so
// that if we are being used with an edge triggered PIC, he
// will see an edge after the MDD hooks the interrupt.
SL_ClearPendingInts( pContext );
DEBUGMSG(ZONE_INIT,(TEXT("SerPostInit-\r\n")));
return(TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: SerOpen
//
// This function is called by the upper layer to
// open the serial device. This function applies
// power to the serial hardware.
//
// Parameters:
// pContext
// [in] Pointer to a context structure returned
// by SerInit function that contains implementation-
// specific data describing the hardware device.
//
// Returns:
// TRUE if success. FALSE if failure.
//
//-----------------------------------------------------------------------------
static BOOL SerOpen( PVOID pContext )
{
PSER_INFO pSerHead = (PSER_INFO)pContext;
DEBUGMSG(ZONE_OPEN,(TEXT("SerOpen+ \r\n")));
// Disallow multiple simultaneous opens
if (pSerHead->cOpenCount)
return (FALSE);
pSerHead->cOpenCount++;
SL_Reset(pSerHead);
SL_Open(pSerHead);
SL_SetOutputMode(pSerHead, pSerHead->fIRMode, !pSerHead->fIRMode);
DEBUGMSG(ZONE_OPEN,(TEXT("SerOpen-\r\n")));
return (TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: SerClose
//
// This function is called by the upper layer to
// close the serial device.
//
// Parameters:
// pContext
// [in] Pointer to a context structure returned
// by SerInit function that contains implementation-
// specific data describing the hardware device.
//
// Returns:
// Zero indicates success.
//
//-----------------------------------------------------------------------------
static ULONG SerClose( PVOID pContext )
{
PSER_INFO pSerHead = (PSER_INFO)pContext;
ULONG uTries;
DEBUGMSG(ZONE_CLOSE,(TEXT("SerClose+ \r\n")));
if (pSerHead->cOpenCount) {
DEBUGMSG(ZONE_CLOSE, (TEXT("SerClose - closing device\r\n")));
pSerHead->cOpenCount--;
// while we are still transmitting, sleep.
uTries = 0;
while(!(pSerHead->uart_info.pUartReg->USR2 & 0x00004000)
&& (uTries++ < 100)){ // TxFifo not empty..
DEBUGMSG(ZONE_WARN, (TEXT("SerClose, TX in progress.\r\n")));
Sleep(10);
}
// When the device is closed, we power it down.
SL_Close(pSerHead);
}
DEBUGMSG(ZONE_CLOSE,(TEXT("SerClose-\r\n")));
return (0);
}
//-----------------------------------------------------------------------------
//
// Function: SerDeinit
//
// This function is called by the upper layer to
// de-initialize the serial device.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -