📄 comm.c
字号:
(UINT)thisch));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
break;
case SLOW_IR_EOF^SLOW_IR_ESC_COMP:
case SLOW_IR_BOF^SLOW_IR_ESC_COMP:
case SLOW_IR_ESC^SLOW_IR_ESC_COMP:
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
default:
DBGERR((TEXT("Unnecessary escape sequence: (got following packet + ESC,%xh"), (UINT)thisch));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_SAW_EOF:
default:
DBGERR((TEXT("Illegal state in DoRcv")));
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_INIT;
return 0;
}
}
}
/*
* Set result and do any post-cleanup.
*/
switch (thisDev->portInfo.rcvState){
case STATE_SAW_EOF:
/*
* We've read in the entire packet.
* Queue it and return TRUE.
*/
DBGOUT((TEXT(" *** DoRcv returning with COMPLETE packet, read %d bytes ***"),
thisDev->portInfo.readBufPos));
QueueReceivePacket(thisDev, thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos, FALSE);
// The protocol has our buffer. Get a new one.
ASSERT(!IsListEmpty(&thisDev->rcvBufBuf));
#if 1
pListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
thisDev->portInfo.readBuf = LIST_ENTRY_TO_RCV_BUF(pListEntry);
#else
thisDev->portInfo.readBuf = (PVOID)RemoveHeadList(&thisDev->rcvBufBuf);
#endif
result = TRUE;
if (rawBufPos < rawBytesRead){
/*
* This is ugly.
* We have some more unprocessed bytes in the raw buffer.
* Move these to the beginning of the raw buffer
* go to the CLEANUP state, which indicates that these
* bytes be used up during the next call.
* (This is typically only 1 or 2 bytes).
* Note: We can't just leave these in the raw buffer because
* we might be supporting connections to multiple COM ports.
*/
memcpy(thisDev->portInfo.rawBuf, &thisDev->portInfo.rawBuf[rawBufPos], rawBytesRead-rawBufPos);
thisDev->portInfo.readBufPos = rawBytesRead-rawBufPos;
thisDev->portInfo.rcvState = STATE_CLEANUP;
}
else {
thisDev->portInfo.rcvState = STATE_INIT;
}
break;
default:
if (thisDev->portInfo.readBufPos > MAX_RCV_DATA_SIZE){
DBGERR((TEXT("Overrun in DoRcv : read %d=%xh bytes:"),
thisDev->portInfo.readBufPos, thisDev->portInfo.readBufPos));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_INIT;
}
else {
DBGOUT((TEXT("DoRcv returning with partial packet, read %d bytes"),
thisDev->portInfo.readBufPos));
}
result = FALSE;
break;
}
DBGOUT((TEXT("<==StepReceiveFSM")));
DEBUGMSG(ZONE_FIRMODE, (TEXT("StepReceiveFSM <--\r\n")));
return result;
}
/*
*************************************************************************
* COM_ISR
*************************************************************************
*
*
*/
VOID COM_ISR(IrDevice *thisDev, BOOLEAN *claimingInterrupt, BOOLEAN *requireDeferredCallback)
{
/*
* Get the interrupt status register value.
*/
UCHAR intId = (UCHAR)READ_REGISTER_UCHAR(pIrIIR);
if (intId & INTID_INTERRUPT_NOT_PENDING){
/*
* This is NOT our interrupt.
* Set carry bit to pass the interrupt to the next driver in the chain.
*/
*claimingInterrupt = *requireDeferredCallback = FALSE;
DEBUGMSG(1, (TEXT("COM_ISR: INTID_INTERRUPT_NOT_PENDING!!!!!!!!!!!!!!!!!!!!!!! intId = 0x%x\r\n"), intId));
}
else {
/*
* This is our interrupt
*/
/*
* In some odd situations, we can get interrupt bits that don't
* get cleared; we don't want to loop forever in this case, so keep a counter.
*/
UINT loops = 0;
*claimingInterrupt = TRUE;
*requireDeferredCallback = FALSE;
// DEBUGMSG(1, (TEXT("COM_ISR: intId = 0x%x\r\n"), intId));
while (!(intId & INTID_INTERRUPT_NOT_PENDING) && (loops++ < 0x10)){
switch (intId & INTID_INTIDMASK){
case INTID_MODEMSTAT_INT:
READ_REGISTER_UCHAR(pIrMSR);
break;
case INTID_XMITREG_INT:
if (thisDev->portInfo.writePending){
/*
* Try to send a few more bytes
*/
if (StepSendFSM(thisDev)){
/*
* There are no more bytes to send;
* reset interrupts for receive mode.
*/
thisDev->portInfo.writePending = FALSE;
SetCOMInterrupts(thisDev, TRUE);
/*
* If we just sent the last frame to be sent at the old speed,
* set the hardware to the new speed.
*/
if (thisDev->setSpeedAfterCurrentSendPacket){
thisDev->setSpeedAfterCurrentSendPacket = FALSE;
thisDev->setSpeedNow = TRUE;
}
/*
* Request a DPC so that we can try
* to send other pending write packets.
*/
*requireDeferredCallback = TRUE;
}
}
break;
case INTID_RCVDATAREADY_INT:
if(intId & 0x08){
DBGOUT((TEXT("COM INTERRUPT: Character time out!")));
}
thisDev->nowReceiving = TRUE;
if (!thisDev->mediaBusy){
thisDev->mediaBusy = TRUE;
thisDev->haveIndicatedMediaBusy = FALSE;
*requireDeferredCallback = TRUE;
}
if (StepReceiveFSM(thisDev)){
/*
* The receive engine has accumulated an entire frame.
* Request a deferred callback so we can deliver the frame
* when not in interrupt context.
*/
*requireDeferredCallback = TRUE;
thisDev->nowReceiving = FALSE;
}
break;
case INTID_RCVLINESTAT_INT:
break;
default:
break;
}
/*
* After we service each interrupt condition, we read the line status register.
* This clears the current interrupt, and a new interrupt may then appear in
* the interrupt-id register.
*/
READ_REGISTER_UCHAR(pIrLSR);
intId = (UCHAR)READ_REGISTER_UCHAR(pIrIIR);
}
}
}
/*
*************************************************************************
* OpenCOM
*************************************************************************
*
* Initialize UART registers
*
*/
BOOLEAN OpenCOM(IrDevice *thisDev)
{
BOOLEAN dongleInit;
USHORT intIdReg;
UCHAR val;
DEBUGMSG(ZONE_FIRMODE, (TEXT("OpenCOM -->\r\n")));
SetRegInit();
/*
* Disable all COM interrupts while setting up.
*/
SetCOMInterrupts(thisDev, FALSE);
/*
* Set request-to-send and clear data-terminal-ready.
* Note: ** Bit 3 must be set to enable interrupts.
*/
WRITE_REGISTER_UCHAR(pIrMCR, SERIAL_MCR_IRQ_ENABLE|SERIAL_MCR_RTS);
/*
* Set dongle- or part-specific info to default
*/
thisDev->portInfo.hwCaps.supportedSpeedsMask = ALL_SLOW_IRDA_SPEEDS;
thisDev->portInfo.hwCaps.turnAroundTime_usec = DEFAULT_TURNAROUND_usec;
thisDev->portInfo.hwCaps.extraBOFsRequired = 0;
/*
* Set the COM port speed to the default 9600 baud.
* Some dongles can only receive cmd sequences at this speed.
*/
SetUARTSpeed(thisDev, 9600);
dongleInit = NSC_DEMO_Init( thisDev );
if (!dongleInit){
DBGERR((TEXT("Dongle-specific init failed in OpenCOM")));
return FALSE;
}
/*
* Set request-to-send and clear data-terminal-ready.
* Note: ** Bit 3 must be set to enable interrupts.
*/
WRITE_REGISTER_UCHAR(pIrMCR, SERIAL_MCR_IRQ_ENABLE|SERIAL_MCR_RTS);
/*
* Set speed to default for the entire part.
* (This is redundant in most, but not all, cases.)
*/
thisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];;
SetSpeed(thisDev);
/*
* Clear the FIFO control register
*/
// SetFIFOCR(thisDev,FALSE);
WRITE_REGISTER_UCHAR(pIrFCR, 0x00);
/*
* Set up the FIFO control register to use both read and write FIFOs (if 16650),
* and with a receive FIFO trigger level of 1 byte.
*/
// SetFIFOCR(thisDev,TRUE);
WRITE_REGISTER_UCHAR(pIrFCR, SERIAL_FCR_TXMT_RESET|SERIAL_FCR_RCVR_RESET|SERIAL_FCR_ENABLE);
/*
* Check whether we're running on a 16550,which has a 16-byte write FIFO.
* In this case, we'll be able to blast up to 16 bytes at a time.
*/
intIdReg = READ_REGISTER_UCHAR(pIrFCR);
thisDev->portInfo.haveFIFO = (BOOLEAN)((intIdReg & SERIAL_14_BYTE_HIGH_WATER) == SERIAL_14_BYTE_HIGH_WATER);
while(1){
val = READ_REGISTER_UCHAR(pIrIIR);
if( val & SERIAL_IIR_NO_INTERRUPT_PENDING ){
break;//no interrupts
}else{
switch( val & 0x0e ){
case SERIAL_IIR_RLS://RLS interrupts
READ_REGISTER_UCHAR(pIrLSR);
break;
case SERIAL_IIR_RDA://Rx available interrupts
case SERIAL_IIR_CTI://Character timer-out interrupts
READ_REGISTER_UCHAR(pIrRBR);
break;
case SERIAL_IIR_THRE://Tx empty interrupts
break;
case SERIAL_IIR_MS://Modem status interrupts
READ_REGISTER_UCHAR(pIrMSR);
break;
default:
break;
}
}
}
/*
* Start out in receive mode.
* We always want to be in receive mode unless we're transmitting a frame.
*/
SetCOMInterrupts(thisDev, TRUE);
DBGOUT((TEXT("OpenCOM succeeded")));
DEBUGMSG(ZONE_FIRMODE, (TEXT("OpenCOM <--\r\n")));
return TRUE;
}
/*
*************************************************************************
* CloseCOM
*************************************************************************
*
*/
VOID CloseCOM(IrDevice *thisDev)
{
DEBUGMSG(ZONE_FIRMODE, (TEXT("CloseCOM -->\r\n")));
/*
* Do special deinit for dongles.
* Some dongles can only rcv cmd sequences at 9600, so set this speed first.
*/
thisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];;
SetSpeed(thisDev);
NSC_DEMO_Deinit(thisDev->portInfo.ioBase, thisDev->portInfo.dongleContext);
SetCOMInterrupts(thisDev, FALSE);
DEBUGMSG(ZONE_FIRMODE, (TEXT("CloseCOM <--\r\n")));
}
/*
*************************************************************************
* DoRcvDirect
*************************************************************************
*
* Read up to maxBytes bytes from the UART's receive FIFO.
* Return the number of bytes read or (UINT)-1 if an error occurred.
*
*/
UINT DoRcvDirect(UINT ioBase, UCHAR *data, UINT maxBytes)
{
USHORT bytesRead;
UCHAR lineStatReg;
UINT i;
BOOLEAN goodChar;
DEBUGMSG(ZONE_FIRMODE, (TEXT("DoRcvDirect -->\r\n")));
for (bytesRead = 0; bytesRead < maxBytes; bytesRead++){
/*
* Wait for data-ready
*/
i = 0;
do {
lineStatReg = (UCHAR)READ_REGISTER_UCHAR(pIrLSR);
/*
* The UART reports framing and break errors as the effected
* characters appear on the stack. We drop these characters,
* which will probably result in a bad frame checksum.
*/
if (lineStatReg & (LINESTAT_BREAK | LINESTAT_FRAMINGERROR)){
UCHAR badch = (UCHAR)READ_REGISTER_UCHAR(pIrRBR);
DBGERR((TEXT("Bad rcv char %xh (lineStat=%xh)"),
(UINT)badch, (UINT)lineStatReg));
return (UINT)-1;
}
else if (lineStatReg & LINESTAT_DATAREADY){
goodChar = TRUE;
}
else {
/*
* No input char ready
*/
goodChar = FALSE;
}
} while (!goodChar && (++i < REG_POLL_LOOPS));
if (!goodChar){
break;
}
/*
* Read in the next data byte
*/
data[bytesRead] = (UCHAR)READ_REGISTER_UCHAR(pIrRBR);
}
DEBUGMSG(ZONE_FIRMODE, (TEXT("DoRcvDirect <--\r\n")));
return bytesRead;
}
/*
*************************************************************************
* GetCOMPort
*************************************************************************
*/
UCHAR GetCOMPort(UINT comBase, comPortRegOffset portOffset)
{
UCHAR val;
DEBUGMSG(ZONE_FIRMODE, (TEXT("GetCOMPort <-->\r\n")));
NdisRawReadPortUchar(comBase+portOffset, &val);
return val;
}
/*
*************************************************************************
* SetCOMPort
*************************************************************************
*/
VOID SetCOMPort(UINT comBase, comPortRegOffset portOffset, UCHAR val)
{
DEBUGMSG(ZONE_FIRMODE, (TEXT("SetCOMPort <-->\r\n")));
NdisRawWritePortUchar(comBase+portOffset, val);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -