📄 bvd_ser16550.c
字号:
//OUTB(pHWHead, pIER_DLH, (UCHAR)0);
//OUTB(pHWHead, pMCR, (UCHAR)0);
pHWHead->IIR = INB(pHWHead, pIIR_FCR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just get out of here.
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_CLOSE,
(TEXT("-HW_XSC1_Close 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func PVOID | HW_XSC1_Init | Initializes Cotulla's 16550 device head.
//
VOID
HW_XSC1_Init(
PVOID pHead, // @parm points to device head
PULONG pRegBase, // Pointer to 16550 register base
UINT32 RegStride, // Stride amongst the 16550 registers
DWORD dwIoBase, // IO Base Address
volatile XLLP_GPIO_T *pGPIOReg, // @field for configuring GPIO pins
volatile XLLP_CLKMGR_T *pClkMgrReg, // @field for configuring clk mgr
EVENT_FUNC EventCallback, // This callback exists in MDD
PVOID pMddHead, // This is the first parm to callback
PLOOKUP_TBL pBaudTable // BaudRate Table
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
XLLP_UINT32_T LockID;
DEBUGMSG (ZONE_CLOSE,(TEXT("+HW_XSC1_INIT, 0x%X\r\n"), pHWHead));
// DEBUGMSG (1,(TEXT("??????????????????+HW_XSC1_INIT, 0x%X\r\n"), pHWHead));
// Set up pointers to 16550 registers
pHWHead->pTHR_RBR_DLL = pRegBase + (RegStride * RECEIVE_BUFFER_REGISTER);
pHWHead->pIER_DLH = pRegBase + (RegStride * INTERRUPT_ENABLE_REGISTER);
pHWHead->pIIR_FCR = pRegBase + (RegStride * INTERRUPT_IDENT_REGISTER);
pHWHead->pLCR = pRegBase + (RegStride * LINE_CONTROL_REGISTER);
pHWHead->pMCR = pRegBase + (RegStride * MODEM_CONTROL_REGISTER);
pHWHead->pLSR = pRegBase + (RegStride * LINE_STATUS_REGISTER);
pHWHead->pMSR = pRegBase + (RegStride * MODEM_STATUS_REGISTER);
pHWHead->pSCR = pRegBase + (RegStride * SCRATCH_REGISTER);
//Seting up SLOW_IR_SELECT_REGISTER register also
//though we don't use it till IR mode is selected.
pHWHead->pIRDASEL = pRegBase + (RegStride * SLOW_IR_SELECT_REGISTER);
pHWHead->pFOR = pRegBase + (RegStride * FIFO_OCCUPANCY_REGISTER);
pHWHead->pABR = pRegBase + (RegStride * AUTOBAUD_CONTROL_REGISTER);
pHWHead->pACR = pRegBase + (RegStride * AUTOBAUD_COUNT_REGISTER);
// Store info for callback function
pHWHead->EventCallback = EventCallback;
pHWHead->pMddHead = pMddHead;
//To find out which uart is it
pHWHead->IOBase = dwIoBase;
//To modify GPIO pins
pHWHead->pGPIOReg = pGPIOReg;
//To modify peripheral clocks
pHWHead->pClkMgrReg = pClkMgrReg;
// Now set up remaining fields
if ( pBaudTable != NULL )
pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
else
pHWHead->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
pHWHead->FlushDone = CreateEvent(0, FALSE, FALSE, NULL);
pHWHead->OpenCount = 0;
//UART should not be enabled before GPIO pins are configured.
#ifndef NON_WS_GPIO
//Configure GPIOs, peripheral clock and board level registers for UARTs
if (FFUART_BASE_U_VIRTUAL == pHWHead->IOBase)
{
LockID = XllpLock(GPCR1);
//Initialize GPIO pins
//Write 0 on GPIO pins 39, 40 and 41 before configuring them as outputs.
pHWHead->pGPIOReg->GPCR1 = ( XLLP_GPIO_BIT_FFDTR | XLLP_GPIO_BIT_FFTXD |
XLLP_GPIO_BIT_FFRTS );
XllpUnlock(LockID);
LockID = XllpLock(GPDR1);
//Configure direction of GPIO pins 34, 35, 36, 37 and 38 as input
//and GPIO pins 39, 40 and 41 as output
pHWHead->pGPIOReg->GPDR1 &= ~( XLLP_GPIO_BIT_FFRXD | XLLP_GPIO_BIT_FFCTS |
XLLP_GPIO_BIT_FFDCD | XLLP_GPIO_BIT_FFDSR |
XLLP_GPIO_BIT_FFRI );
pHWHead->pGPIOReg->GPDR1 |= ( XLLP_GPIO_BIT_FFTXD | XLLP_GPIO_BIT_FFDTR |
XLLP_GPIO_BIT_FFRTS );
XllpUnlock(LockID);
LockID = XllpLock(GAFR1_L);
//Configure GPIO pins 34, 35, 36, 37 and 38 for Alt_fn1. And pins 39, 40 and 41 for Alt_fn2.
pHWHead->pGPIOReg->GAFR1_L |= ( XLLP_GPIO_AF_BIT_FFRXD | XLLP_GPIO_AF_BIT_FFCTS |
XLLP_GPIO_AF_BIT_FFDCD | XLLP_GPIO_AF_BIT_FFDSR |
XLLP_GPIO_AF_BIT_FFRI | XLLP_GPIO_AF_BIT_FFTXD |
XLLP_GPIO_AF_BIT_FFDTR | XLLP_GPIO_AF_BIT_FFRTS );
XllpUnlock(LockID);
//if (!(StartClock(XLLP_CLKEN_FFUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to start FFUART clock!\r\n")));
//Enable FFUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken |= XLLP_CLKEN_FFUART ;
XllpUnlock(LockID);
//RETAILMSG (1,(TEXT("\r\nHW_XSC1_INIT: FFUART, 0x%X\r\n"), pHWHead));
}
else if (BTUART_BASE_U_VIRTUAL == pHWHead->IOBase)
{
//Configuring GPIO pins for BTUART
//Initialize GPIO pins
//Write 0 on GPIO pins 43 and 45 before configuring them as outputs.
LockID = XllpLock(GPCR1);
pHWHead->pGPIOReg->GPCR1 = (XLLP_GPIO_BIT_BTTXD | XLLP_GPIO_BIT_BTRTS);
XllpUnlock(LockID);
//Configure direction of GPIO pins 42 and 44 as input
//and GPIO pins 43 and 45 as output
LockID = XllpLock(GPDR1);
pHWHead->pGPIOReg->GPDR1 &= ~( XLLP_GPIO_BIT_BTRXD | XLLP_GPIO_BIT_BTCTS);
pHWHead->pGPIOReg->GPDR1 |= ( XLLP_GPIO_BIT_BTTXD | XLLP_GPIO_BIT_BTRTS);
XllpUnlock(LockID);
//Configure GPIO pins 42 and 44 for Alt_fn1. And pins 43 and 45 for Alt_fn2.
LockID = XllpLock(GAFR1_L);
pHWHead->pGPIOReg->GAFR1_L |= ( XLLP_GPIO_AF_BIT_BTRXD | XLLP_GPIO_AF_BIT_BTCTS |
XLLP_GPIO_AF_BIT_BTTXD | XLLP_GPIO_AF_BIT_BTRTS );
XllpUnlock(LockID);
//if (!(StartClock(XLLP_CLKEN_BTUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to start BTUART clock!\r\n")));
//Enable BTUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken |= XLLP_CLKEN_BTUART ;
XllpUnlock(LockID);
//RETAILMSG (1,(TEXT("\r\nHW_XSC1_INIT: BTUART, 0x%X\r\n"), pHWHead));
}
else if (STUART_BASE_U_VIRTUAL == pHWHead->IOBase)
{
//Initialize GPIO pins
//Write 0 on GPIO pin 47 before configuring it as output.
//Verify whether to write zero or not?
//pHWHead->pGPIOReg->GPCR_y |= (GPIO_47);
LockID = XllpLock(GPSR1);
pHWHead->pGPIOReg->GPSR1 = (XLLP_GPIO_BIT_STD_TXD);
XllpUnlock(LockID);
//Configure direction of GPIO pin 46 as input and GPIO pin 47 as output
LockID = XllpLock(GPDR1);
pHWHead->pGPIOReg->GPDR1 &= (~XLLP_GPIO_BIT_STD_RXD);
pHWHead->pGPIOReg->GPDR1 |= ( XLLP_GPIO_BIT_STD_TXD);
XllpUnlock(LockID);
//Configure GPIO pin 46 for Alt_fn2. And, GPIO pin 47 for Alt_fn1.
LockID = XllpLock(GAFR1_L);
pHWHead->pGPIOReg->GAFR1_L |= (XLLP_GPIO_AF_BIT_STD_RXD | XLLP_GPIO_AF_BIT_STD_TXD);
XllpUnlock(LockID);
DEBUGMSG (ZONE_INIT, (TEXT("HW_XSC1_Init - GPIO pins configured for STUART\r\n")));
//if (!(StartClock(XLLP_CLKEN_STUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to start STUART clock!\r\n")));
//Enable STUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken |= XLLP_CLKEN_STUART ;
XllpUnlock(LockID);
//RETAILMSG (1,(TEXT("\r\nHW_XSC1_INIT: STUART, 0x%X\r\n"), pHWHead));
}
#endif
//Doing these settings so that Rx FIFO could be served even without COM_Open being called
//UART and these settings could be potentially turned off in production code to conserve power
DEBUGMSG (1,(TEXT("??????????????????+HW_XSC1_INIT, 0x%X :Reiniting UART for 38400 8N1 mode !!!\r\n"), pHWHead));
OUTB(pHWHead, pLCR, (UCHAR)0); // clearing DLAB
OUTB(pHWHead, pIER_DLH, (UCHAR)0); // IER_DLH = 0x0
//Baud rate 38400
OUTB(pHWHead, pLCR, (UCHAR)0x80 ); // Access Divisor
OUTB(pHWHead,pTHR_RBR_DLL, (UCHAR)0x18 ); // low byte divisor
OUTB(pHWHead, pIER_DLH, (UCHAR)0x0 ); // high byte divisor
OUTB(pHWHead, pLCR, (UCHAR)0x0 ); // clearing DLAB
//Setting UART properties to 8N1
pHWHead->LCR |= (SERIAL_8_DATA | SERIAL_1_STOP | SERIAL_NONE_PARITY);
OUTB(pHWHead, pLCR, (pHWHead->LCR) ); //pLCR = 0x3.
//Ensuring that loop back mode is off
//For now, disable Autoflow
pHWHead->MCR &= (~SERIAL_MCR_LOOP & ~SERIAL_MCR_AUTO_FLOW_ENABLE_CTS);
//Set RTS for non-Autoflow mode and set MCR[OUT]=1 to enable UART IRQ.
pHWHead->MCR |= (SERIAL_MCR_RTS | SERIAL_MCR_IRQ_ENABLE);
OUTB(pHWHead, pMCR, (UCHAR) pHWHead->MCR);
/*
//#ifdef A1_Cotulla
if((pHWHead->ProcessorStepping == COTULLA_A1_CP15_VAL) || (pHWHead->ProcessorStepping == SABINAL_A1_CP15_VAL) ){
//Cotulla A1: Set MCR[OUT]=0 to enable UART IRQ
pHWHead->MCR &= ~SERIAL_MCR_IRQ_ENABLE ;
}
//#elif B0_Cotulla
else if((pHWHead->ProcessorStepping == COTULLA_B0_CP15_VAL) || (pHWHead->ProcessorStepping == SABINAL_B0_CP15_VAL) ){
//Cotulla B0: Set MCR[OUT]=1 to enable UART IRQ
pHWHead->MCR |= SERIAL_MCR_IRQ_ENABLE ;
}
//#else
else{
//Default stepping: Set MCR[OUT]=1 to enable UART IRQ.
pHWHead->MCR |= SERIAL_MCR_IRQ_ENABLE ;
}
//#endif
*/
//For Bulverde
//To Do: Change peripheral bus to be 32 bit
#ifdef UART_32_BIT_PERIPHERAL_BUS
//Set Tx Interrupt level to FIFO half empty
//Trailing bytes are removed by Processor
pHWHead->FCR &= ( ~SERIAL_FCR_TX_INTR_LEVEL
& ~SERIAL_FCR_TRAILING_BYTES);
//Rx FIFO Interrupt Threshold level is 32 bytes and Enable RxTx FIFOs.
//Peripheral bus is 32 bit
pHWHead->FCR |= (SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_32_BYTE_HIGH_WATER |
SERIAL_FCR_PERIPHERAL_BUS ) ;
#else
//Set Tx Interrupt level to FIFO half empty
//Trailing bytes are removed by Processor
//Peripheral bus is 8 bit
pHWHead->FCR &= ( ~SERIAL_FCR_TX_INTR_LEVEL
& ~SERIAL_FCR_TRAILING_BYTES
& ~SERIAL_FCR_PERIPHERAL_BUS);
//Rx FIFO Interrupt Threshold level is 32 bytes and Enable RxTx FIFOs.
pHWHead->FCR |= (SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_32_BYTE_HIGH_WATER) ;
#endif
OUTB(pHWHead, pIIR_FCR, (UCHAR) pHWHead->FCR);
//Right now, make sure that ABR bits is set to zero
pHWHead->ABR &= ( ~SERIAL_ABR_AUTOBAUD_ENABLE
& ~SERIAL_ABR_AUTOBAUDLOCK_INTR_ENABLE
& ~SERIAL_ABR_UART_PROGRAM
& ~SERIAL_ABR_AUTOBAUD_TABLE);
OUTB(pHWHead, pABR, (UCHAR) pHWHead->ABR);
DEBUGMSG (1,(TEXT("??????????????????+HW_XSC1_INIT, 0x%X :Not touching UART!!!\r\n"), pHWHead));
// Don't allow any interrupts till HW_XSC1_PostInit.
// UART Unit, all interrupts and NRZ encoding are disabled
//OUTB(pHWHead, pLCR, (UCHAR)0); // clearing DLAB
//OUTB(pHWHead, pIER_DLH, (UCHAR)0); // IER_DLH = 0x0
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
InitializeCriticalSection(&(pHWHead->RegCritSec));
// Clear any interrupts which may be pending. Normally only
// happens if we were warm reset.
HW_XSC1_ClearPendingInts( pHWHead );
#ifdef USE_MERLIN
//Enable interrupts and UART to take care of rx data without COM_Open()
pHWHead->IER |= (SERIAL_IER_UUE | IER_NORMAL_INTS) ;
OUTB(pHWHead, pIER_DLH, (UCHAR) pHWHead->IER);
#endif
DEBUGMSG (ZONE_CLOSE,(TEXT("-HW_XSC1_INIT, 0x%X\r\n"), pHWHead));
}
//
// @doc OEM
// @func void | HW_XSC1_PostInit | This routine takes care of final initialization.
//
// @rdesc None.
//
BOOL
HW_XSC1_PostInit(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_INIT,(TEXT("+HW_XSC1_PostInit, 0x%X\r\n"), pHWHead));
// 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.
HW_XSC1_ClearPendingInts( pHWHead );
DEBUGMSG (ZONE_INIT,(TEXT("-HW_XSC1_PostInit, 0x%X\r\n"), pHWHead));
return(TRUE);
}
//
// @doc OEM
// @func PVOID | HW_XSC1_Deinit | De-initializes Cotulla's 16550 device head.
//
VOID
HW_XSC1_Deinit(
PVOID pHead // @parm points to device head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
XLLP_UINT32_T LockID;
DEBUGMSG (ZONE_CLOSE,(TEXT("+HW_XSC1_DEINIT, 0x%X\r\n"), pHWHead));
DeleteCriticalSection(&(pHWHead->TransmitCritSec));
DeleteCriticalSection(&(pHWHead->RegCritSec));
// Free the flushdone event
if ( pHWHead->FlushDone )
CloseHandle( pHWHead->FlushDone );
//Stop the clock
if (pHWHead->IOBase == FFUART_BASE_U_VIRTUAL)
{
//Disable FFUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken &= ~XLLP_CLKEN_FFUART ;
XllpUnlock(LockID);
//if (!(StopClock(XLLP_CLKEN_FFUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to stop FFUART clock!\r\n")));;
}
else if (pHWHead->IOBase == BTUART_BASE_U_VIRTUAL)
{
//Disable BTUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken &= ~XLLP_CLKEN_BTUART ;
XllpUnlock(LockID);
//if (!(StopClock(XLLP_CLKEN_BTUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to stop BTUART clock!\r\n")));;
}
else if (pHWHead->IOBase == STUART_BASE_U_VIRTUAL)
{
//Disable STUART clock
LockID = XllpLock(CKEN);
pHWHead->pClkMgrReg->cken &= ~XLLP_CLKEN_STUART ;
XllpUnlock(LockID);
//if (!(StopClock(XLLP_CLKEN_STUART , NOTINPOWERHANDLER)))
// DEBUGMSG(ZONE_ERROR,(TEXT("HW_XSC1_Init: Unable to stop STUART clock!\r\n")));;
}
DEBUGMSG (ZONE_CLOSE,(TEXT("-HW_XSC1_DEINIT, 0x%X\r\n"), pHWHead));
}
//
// @doc OEM
// @func void | HW_XSC1_ClearDtr | This routine clears DTR.
//
// @rdesc None.
//
VOID
HW_XSC1_ClearDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+HW_XSC1_ClearDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
ULONG value;
if (pHWHead->IOBase == FFUART_BASE_U_VIRTUAL)
{
value = INB((PSER16550_INFO)pHead, pMCR);
pHWHead->MCR &= ~SERIAL_MCR_DTR;
OUTB((PSER16550_INFO)pHead, pMCR, value & ~SERIAL_MCR_DTR);
}
else if (pHWHead->IOBase == BTUART_BASE_U_VIRTUAL)
{
//DEBUGMSG (1,(TEXT("**************HW_XSC1_ClearDTR %X\r\n"),pHWHead->MSR));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -