📄 comm.c
字号:
case STATE_GOT_BOF:
switch (thisch){
case SLOW_IR_BOF:
break;
case SLOW_IR_EOF:
/*
* Garbage
*/
DBGERR(("EOF in absorbing-BOFs state in DoRcv"));
thisDev->portInfo.rcvState = STATE_INIT;
break;
case SLOW_IR_ESC:
/*
* Start of data.
* Our first data byte happens to be an ESC sequence.
*/
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[0] = thisch;
thisDev->portInfo.readBufPos = 1;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_ACCEPTING:
switch (thisch){
case SLOW_IR_BOF:
/*
* Meaningless garbage
*/
DBGOUT(("WARNING: BOF during accepting state in DoRcv"));
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
break;
case SLOW_IR_EOF:
if (thisDev->portInfo.readBufPos <
IR_ADDR_SIZE+IR_CONTROL_SIZE+SLOW_IR_FCS_SIZE){
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
}
else {
thisDev->portInfo.rcvState = STATE_SAW_EOF;
}
break;
case SLOW_IR_ESC:
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch;
break;
}
break;
case STATE_ESC_SEQUENCE:
switch (thisch){
case SLOW_IR_EOF:
case SLOW_IR_BOF:
case SLOW_IR_ESC:
/*
* ESC + {EOF|BOF|ESC} is an abort sequence
*/
DBGERR(("DoRcv - abort sequence; ABORTING IR PACKET: (got following packet + ESC,%xh)", (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(("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(("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((" *** DoRcv returning with COMPLETE packet, read %d bytes ***", thisDev->portInfo.readBufPos));
if (!IsListEmpty(&thisDev->rcvBufBuf))
{
QueueReceivePacket(thisDev, thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos, FALSE);
// The protocol has our buffer. Get a new one.
pListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
thisDev->portInfo.readBuf = LIST_ENTRY_TO_RCV_BUF(pListEntry);
}
else
{
// No new buffers were available. We just discard this packet.
DBGERR(("No rcvBufBuf available, discarding packet\n"));
}
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(("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(("DoRcv returning with partial packet, read %d bytes", thisDev->portInfo.readBufPos));
}
result = FALSE;
break;
}
return result;
}
/*
*************************************************************************
* COM_ISR
*************************************************************************
*
*
*/
VOID COM_ISR(IrDevice *thisDev, BOOLEAN *claimingInterrupt, BOOLEAN *requireDeferredCallback)
{
LONG NewCount;
/*
* Get the interrupt status register value.
*/
UCHAR intId = GetCOMPort(thisDev->portInfo.ioBase, INT_ID_AND_FIFO_CNTRL_REG_OFFSET);
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;
}
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;
while (!(intId & INTID_INTERRUPT_NOT_PENDING) && (loops++ < 0x10)){
switch (intId & INTID_INTIDMASK){
case INTID_MODEMSTAT_INT:
DBGOUT(("COM INTERRUPT: modem status int"));
GetCOMPort(thisDev->portInfo.ioBase, MODEM_STAT_REG_OFFSET);
break;
case INTID_XMITREG_INT:
DBGOUT(("COM INTERRUPT: xmit reg empty"));
if (thisDev->portInfo.SirWritePending){
/*
* Try to send a few more bytes
*/
if (StepSendFSM(thisDev)){
/*
* There are no more bytes to send;
* reset interrupts for receive mode.
*/
thisDev->portInfo.SirWritePending = FALSE;
InterlockedExchange(&thisDev->portInfo.IsrDoneWithPacket,1);
//
// this will unmask the receive interrupt
//
SetCOMInterrupts(thisDev, TRUE);
/*
* Request a DPC so that we can try
* to send other pending write packets.
*/
*requireDeferredCallback = TRUE;
}
}
break;
case INTID_RCVDATAREADY_INT:
DBGOUT(("COM INTERRUPT: rcv data available!"));
thisDev->nowReceiving = TRUE;
NewCount=NdisInterlockedIncrement(&thisDev->RxInterrupts);
if (!thisDev->mediaBusy && (NewCount > MEDIA_BUSY_THRESHOLD)){
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:
DBGOUT(("COM INTERRUPT: rcv line stat int!"));
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.
*/
GetCOMPort(thisDev->portInfo.ioBase, LINE_STAT_REG_OFFSET);
intId = GetCOMPort(thisDev->portInfo.ioBase, INT_ID_AND_FIFO_CNTRL_REG_OFFSET);
}
}
}
/*
*************************************************************************
* OpenCOM
*************************************************************************
*
* Initialize UART registers
*
*/
BOOLEAN OpenCOM(IrDevice *thisDev)
{
BOOLEAN dongleInit;
UCHAR intIdReg;
DBGOUT(("-> OpenCOM"));
//
// Make sure bank zero is selected
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+LCR_BSR_OFFSET, 03);
/*
* Disable all COM interrupts while setting up.
*/
SyncSetInterruptMask(thisDev, FALSE);
/*
* Set request-to-send and clear data-terminal-ready.
* Note: ** Bit 3 must be set to enable interrupts.
*/
SYNC_SET_COMM_PORT(&thisDev->interruptObj,thisDev->portInfo.ioBase, MODEM_CONTROL_REG_OFFSET, 0x0A);
/*
* 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 );
/*
* Set request-to-send and clear data-terminal-ready.
* Note: ** Bit 3 must be set to enable interrupts.
*/
SYNC_SET_COMM_PORT(&thisDev->interruptObj,thisDev->portInfo.ioBase, MODEM_CONTROL_REG_OFFSET, 0x0A);
if (!dongleInit){
DBGERR(("Dongle-specific init failed in OpenCOM"));
return FALSE;
}
/*
* 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
*/
SYNC_SET_COMM_PORT(&thisDev->interruptObj,thisDev->portInfo.ioBase, INT_ID_AND_FIFO_CNTRL_REG_OFFSET, 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.
*/
SYNC_SET_COMM_PORT(&thisDev->interruptObj,thisDev->portInfo.ioBase, INT_ID_AND_FIFO_CNTRL_REG_OFFSET, 0x07);
/*
* 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 = SYNC_GET_COMM_PORT(&thisDev->interruptObj,thisDev->portInfo.ioBase, INT_ID_AND_FIFO_CNTRL_REG_OFFSET);
thisDev->portInfo.haveFIFO = (BOOLEAN)((intIdReg & 0xC0) == 0xC0);
/*
* Start out in receive mode.
* We always want to be in receive mode unless we're transmitting a frame.
*/
SyncSetInterruptMask(thisDev, TRUE);
DBGOUT(("OpenCOM succeeded"));
return TRUE;
}
#if 1
/*
*************************************************************************
* CloseCOM
*************************************************************************
*
*/
VOID CloseCOM(IrDevice *thisDev)
{
/*
* 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);
SyncSetInterruptMask(thisDev, FALSE);
}
#endif
/*
*************************************************************************
* 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(PUCHAR ioBase, UCHAR *data, UINT maxBytes)
{
USHORT bytesRead;
UCHAR lineStatReg;
UINT i;
BOOLEAN goodChar;
for (bytesRead = 0; bytesRead < maxBytes; bytesRead++){
/*
* Wait for data-ready
*/
i = 0;
do {
lineStatReg = GetCOMPort(ioBase, LINE_STAT_REG_OFFSET);
/*
* 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 = GetCOMPort(ioBase, XFER_REG_OFFSET);
DBGERR(("Bad rcv %02xh, LSR=%02xh", (UINT)badch, (UINT)lineStatReg));
return (UINT)-1;
}
else if (lineStatReg & LINESTAT_DATAREADY){
if (lineStatReg & LINESTAT_OVERRUNERROR) {
DBGERR(("Overrun"));
}
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] = GetCOMPort(ioBase, XFER_REG_OFFSET);
}
return bytesRead;
}
/*
*************************************************************************
* GetCOMPort
*************************************************************************
*/
UCHAR GetCOMPort(PUCHAR comBase, comPortRegOffset portOffset)
{
UCHAR val;
#if DBG
{
UCHAR TempVal;
//
// This code assumes that bank 0 is current, we will make sure of that
//
NdisRawReadPortUchar(comBase+LCR_BSR_OFFSET, &TempVal);
ASSERT((TempVal & BKSE) == 0);
}
#endif
NdisRawReadPortUchar(comBase+portOffset, &val);
return val;
}
/*
*************************************************************************
* SetCOMPort
*************************************************************************
*/
VOID SetCOMPort(PUCHAR comBase, comPortRegOffset portOffset, UCHAR val)
{
#if DBG
UCHAR TempVal;
//
// This code assumes that bank 0 is current, we will make sure of that
//
NdisRawReadPortUchar(comBase+LCR_BSR_OFFSET, &TempVal);
ASSERT((TempVal & BKSE) == 0);
#endif
NdisRawWritePortUchar(comBase+portOffset, val);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -