📄 ser16552.c
字号:
//
// This is a reverse lookup table which can be used to determine
// the FIFO trigger level from the 2 bit value stored in the FCR
//
#define HIGH_WATER_SIZE 4
static const
PAIRS HighWaterPairs[HIGH_WATER_SIZE] = {
{SERIAL_1_BYTE_HIGH_WATER, 0},
{SERIAL_4_BYTE_HIGH_WATER, 4},
{SERIAL_8_BYTE_HIGH_WATER, 8},
{SERIAL_14_BYTE_HIGH_WATER, 14}
};
static const
LOOKUP_TBL HighWaterTable = {HIGH_WATER_SIZE, (PAIRS *) HighWaterPairs};
int SerMapRegisterAddresses3( )
{
v_pIOPRegs1= VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
if (v_pIOPRegs1== NULL)
{
DEBUGMSG (1,(TEXT("[16c552] v_pIOPRegs is not allocated\n\r")));
RETAILMSG (1,(TEXT("[16c552] v_pIOPRegs is not allocated\n\r")));
return FALSE;
}
if (!VirtualCopy((PVOID)v_pIOPRegs1,(PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITE|PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("[16c552] v_pIOPRegs is not mapped\n\r")));
RETAILMSG (1,(TEXT("[16c552] v_pIOPRegs is not mapped\n\r")));
goto Ser16c552_fail;
}
DEBUGMSG (1,(TEXT("[16c552] v_pIOPRegs is mapped to %x\n\r"), v_pIOPRegs1));
RETAILMSG (1,(TEXT("[16c552] v_pIOPRegs is mapped to %x\n\r"), v_pIOPRegs1));
v_pIOPRegs1->rGPFCON = (v_pIOPRegs1->rGPFCON & ~(0x3<<6)) | (0x2<<6); //GPF3==EINT3
v_pIOPRegs1->rGPFUP = (v_pIOPRegs1->rGPFUP | (0x1<<3)); // Disable pull-up.
v_pIOPRegs1->rEXTINT0=(v_pIOPRegs1->rEXTINT0 & ~(0xf<<12)) | (0x4<<12); // Rising edge triggered.
return TRUE;
Ser16c552_fail:
if (v_pIOPRegs1) {
VirtualFree((PVOID)v_pIOPRegs1,0, MEM_RELEASE);
}
return FALSE;
}
//
/////////////////// Start of exported entrypoints ////////////////
//
#define WATERMAKER_ENTRY 2
VOID
SL_Openq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG (QYDEBUG, (TEXT("+SL_Openq 0x%X\r\n"), pHWHead));
// If the device is already open, all we do is increment count
if ( pHWHead->OpenCount++ ) {
RETAILMSG (QYDEBUG,
(TEXT("-SL_Openq 0x%X (%d opens)\r\n"),
pHead, pHWHead->OpenCount));
return ;
}
pHWHead->FCR = 0;
pHWHead->IER = 0;
pHWHead->IIR = 0;
pHWHead->LSR = 0;
pHWHead->MSR = 0;
pHWHead->DroppedBytes = 0;
pHWHead->CTSFlowOff = FALSE; // Not flowed off yet
pHWHead->DSRFlowOff = FALSE; // Not flowed off yet
pHWHead->CommErrors = 0;
pHWHead->ModemStatus = 0;
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
OUTB(pHWHead, pIER, (UCHAR)IER_NORMAL_INTS);
OUTB(pHWHead, pMCR, (UCHAR)0x2B);// AFC=1,DTR=1,RTS=1
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 Register pMCR=0x%x\r\n "),INB(pHWHead, pMCR)));
// Set default framing bits.
OUTB(pHWHead, pLCR, SERIAL_8_DATA | SERIAL_1_STOP | SERIAL_NONE_PARITY);
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 Register LCR(0x03)=0x%x\r\n "),INB(pHWHead, pLCR)));
// Get defaults from the DCB structure
//设置波特率,默认9600
SL_SetBaudRateq( pHead, pHWHead->dcb.BaudRate );
SL_SetByteSizeq( pHead, pHWHead->dcb.ByteSize );
SL_SetStopBitsq( pHead, pHWHead->dcb.StopBits );
SL_SetParityq( pHead, pHWHead->dcb.Parity );
//
// A 16450 (which is pretty much a FIFO-less 16550) can be supported by
// not initializing the FIFO.
//
if (pHWHead->ChipID == CHIP_ID_16550) {
// Set up to use 16550 fifo for 14 byte interrupt granularity.
// Shadow the FCR bitmask since reading this location is the IIR
pHWHead->FCR = 0;
OUTB(pHWHead, pIIR_FCR, (pHWHead->FCR | SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) );
}
// MDD and calls post init.
SL_PostInitq(pHWHead);
ReadMSRq(pHWHead);
ReadLSRq(pHWHead);
#ifdef DEBUG
if ( ZONE_INIT )
DumpSerialRegistersq(pHWHead);
#endif
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just get out of here.
}
//OUTB(pHWHead, pMCR, (UCHAR)0x29);// AFC=1,DTR=1,RTS=1
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_OPEN,
(TEXT("-SL_Open 0x%X, IIR 0x%X\r\n"), pHead, pHWHead->IIR));
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 Register pMCR=0x%x\r\n "),INB(pHWHead, pMCR)));
RETAILMSG(QYDEBUG,(TEXT("-SL_Openq() END \r\n")));//=====QM:0419
}
VOID
SL_Closeq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_Close 0x%X\r\n"), pHead));
if ( pHWHead->OpenCount )
pHWHead->OpenCount--;
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Disable all interrupts and clear MCR.
// OUTB(pHWHead, pIER, (UCHAR)0);
// OUTB(pHWHead, pMCR, (UCHAR)0);
//****
OUTB(pHWHead, pIER, (UCHAR)0x01);
OUTB(pHWHead, pMCR, (UCHAR)0x2B);
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));
RETAILMSG(QYDEBUG,
(TEXT("-SL_Close 0x%X\r\n"), pHead));
}
VOID
SL_Initq(
PVOID pHead, // @parm points to device head
PUCHAR pRegBase, // Pointer to 16550 register base
UINT8 RegStride, // Stride amongst the 16550 registers
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;
RETAILMSG(QYDEBUG,(TEXT("+SL_Initq, 0x%X\r\n"), pHWHead));
RETAILMSG(QYDEBUG,(TEXT("+SL_Initq, 0x%X\r\n"), pHead));
// Set up pointers to 16550 registers
pHWHead->pData = pRegBase + (RegStride * RECEIVE_BUFFER_REGISTER);
pHWHead->pIER = 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->pScratch = pRegBase + (RegStride * SCRATCH_REGISTER);
// if (!SerMapRegisterAddresses3())
//RETAILMSG( ,(TEXT("+SL_Initq, 0x%X\r\n"), pHead));
/*RETAILMSG(QYDEBUG,(TEXT("pHWHead->pIER = %X\r\n"),pHWHead->pIER ));
RETAILMSG(QYDEBUG,(TEXT("pHWHead->pIIR_FCR = %X\r\n"),pHWHead->pIIR_FCR ));
RETAILMSG(QYDEBUG,(TEXT("pHWHead->pLCR = %X\r\n"),pHWHead->pLCR ));
RETAILMSG(QYDEBUG,(TEXT("pHWHead->pMCR = %X\r\n"),pHWHead->pMCR ));
RETAILMSG(QYDEBUG,(TEXT("pHWHead->pLSR = %X\r\n"),pHWHead->pLSR ));
RETAILMSG(QYDEBUG,(TEXT(" pHWHead->pMSR = %X\r\n"), pHWHead->pMSR ));
RETAILMSG(QYDEBUG,(TEXT("pHWHead->pIER = %X\r\n"),pHWHead->pScratch ));
*/
// Store info for callback function
pHWHead->EventCallback = EventCallback;
pHWHead->pMddHead = pMddHead;
// Now set up remaining fields
if ( pBaudTable != NULL ){
pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
RETAILMSG(QYDEBUG,(TEXT("pBaudTable != NULL 0x%X\r\n")));
}
else
pHWHead->pBaudTable = (LOOKUP_TBL *) &SER_BaudTable;
pHWHead->FlushDone = CreateEvent(0, FALSE, FALSE, NULL);
pHWHead->OpenCount = 0;
RETAILMSG(QYDEBUG,(TEXT("OpenCount 0x%X\r\n")));
//OUTB(pHWHead, pIER, (UCHAR)2);
//RETAILMSG(QYDEBUG,(TEXT("pIER= 0x%X\r\n"),INB(pHWHead,pIER)));
OUTB(pHWHead, pIER, 0x0f);
RETAILMSG(QYDEBUG,(TEXT("pIER 0x%X\r\n"),INB(pHWHead, pIER)));
// Don't allow any interrupts till PostInit.
OUTB(pHWHead, pIER, (UCHAR)0);
//****
OUTB(pHWHead, pIER, (UCHAR)IER_NORMAL_INTS);
OUTB(pHWHead, pMCR, 0x2b);// MAX3244
RETAILMSG(QYDEBUG,(TEXT("pIER 0x%X\r\n"),INB(pHWHead, pIER)));
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
InitializeCriticalSection(&(pHWHead->RegCritSec));
// Clear any interrupts which may be pending. Normally only
// happens if we were warm reset.
ClearPendingIntsq( pHWHead );
RETAILMSG(QYDEBUG,(TEXT("-SL_INITq, 0x%d\r\n"), pHWHead));
}
BOOL
SL_PostInitq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,(TEXT("+SL_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.
//清除全部中断标志和中断源
ClearPendingIntsq( pHWHead );
RETAILMSG(QYDEBUG,(TEXT("-SL_PostInit, 0x%X\r\n"), pHWHead));
return(TRUE);
}
VOID
SL_ClearBreakq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG, (TEXT("+SL_ClearBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB(((PSER16550_INFO)pHead), pLCR);
OUTB(((PSER16550_INFO)pHead), pLCR, byte & ~SERIAL_LCR_BREAK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG, (TEXT("-SL_ClearBreak, 0x%X\r\n"), pHead));
}
VOID
SL_SetBreakq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG, (TEXT("+SL_SetBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB(((PSER16550_INFO)pHead), pLCR);
OUTB(((PSER16550_INFO)pHead), pLCR, byte | SERIAL_LCR_BREAK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG, (TEXT("-SL_SetBreak, 0x%X\r\n"), pHead));
}
BOOL
SetBaudRateq(
PVOID pHead,
ULONG BaudRate
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
USHORT divisor;
UCHAR lcr;
RETAILMSG(QYDEBUG,(TEXT("+SerBaudRateq()\r\n")));
// **** Warning ***** Make no system calls, called in power context
divisor = DivisorOfRateq(pHead, BaudRate);
RETAILMSG(QYDEBUG,(TEXT("BaudRate=0x%x\r\n"),divisor));
if ( divisor ) {
lcr = INB(pHWHead, pLCR);
RETAILMSG(QYDEBUG,(TEXT(" + lcr lcr LCR =0X%X\r\n"),lcr));
RETAILMSG(QYDEBUG,(TEXT(" +SER16550 Register LCR =0X%X\r\n"),INB(pHWHead, pLCR)));
OUTB(pHWHead, pLCR, lcr | SERIAL_LCR_DLAB);
OUTB(pHWHead, pData, divisor & 0xff); //pData is DivLatch Lo
OUTB(pHWHead, pIER, (divisor >> 8) & 0xff); //pIER is DivLatch Hi
OUTB(pHWHead, pLCR, lcr);
RETAILMSG(QYDEBUG,(TEXT(" +SER16550 Register LCR =0X%X\r\n"),INB(pHWHead, pLCR)));
//****
OUTB(pHWHead, pIER, 0x01);
RETAILMSG(QYDEBUG,(TEXT("-SerBaudRateq(S)\r\n")));
return( TRUE );
} else {
RETAILMSG(QYDEBUG,(TEXT("-SerBaudRateq(F)\r\n")));
return( FALSE );
}
}
BOOL
SL_SetBaudRateq(
PVOID pHead, // @parm PVOID returned by HWInit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -