📄 sir.cpp
字号:
// then hand the sent packet back to the protocol.
// Otherwise, we're just delivering it synchronously from SirSend.
if (firstBufIsPending)
{
DEBUGMSG(ZONE_SEND, (TEXT("Sir: Send Packet Pending!\r\n")));
NdisMSendComplete(thisDev->ndisAdapterHandle, packetToSend,
(NDIS_STATUS)(sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE));
// If the packet was pended, it means this packet was not just
// received in MiniportSend. If we're being called from there,
// we want them to pend the packet they just did receive, so we
// return PENDING.
Result = NDIS_STATUS_PENDING;
}
else
{
DEBUGMSG(ZONE_SEND, (TEXT("Sir: Send result!!!\r\n")));
Result = sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
}
}
DEBUGMSG(ZONE_SEND, (TEXT("Sir: -SirSendPacketQ\r\n")));
return Result;
}
//-----------------------------------------------------------------------------
//
// Function: SirSend
//
// This function inserts packet to send queue and setup device to send.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
// Packet
// [in] PNDIS_PACKET.
//
// Returns:
// This function returns packet send status.
//
//-----------------------------------------------------------------------------
NDIS_STATUS SirSend(pFirDevice_t thisDev, PNDIS_PACKET Packet)
{
NDIS_STATUS result;
DEBUGMSG(ZONE_SEND, (TEXT("Sir: +SirSend(thisDev=0x%x)\r\n"), (UINT)thisDev));
// Use MiniportReserved as a LIST_ENTRY. First check so no one
// ever changes the size of these the wrong way.
ASSERT(sizeof(Packet->MiniportReserved)>=sizeof(LIST_ENTRY));
InsertTailList(&thisDev->SendQueue, (PLIST_ENTRY)Packet->MiniportReserved);
if(thisDev->writePending)
{
DEBUGMSG(ZONE_SEND, (TEXT("Sir: SirSend already pending!!!\r\n")));
result = NDIS_STATUS_PENDING;
}
else
{
BOOLEAN firstBufIsPending = (BOOLEAN)(Packet != HEAD_SEND_PACKET(thisDev));
result = SirSendPacketQ(thisDev, firstBufIsPending);
}
DEBUGMSG(ZONE_SEND, (TEXT("Sir: -SirSend [%s]\r\n"), DBG_NDIS_RESULT_STR(result)));
return result;
}
//-----------------------------------------------------------------------------
//
// Function: SirReceive
//
// Setup for SIR receive.
//
// Parameters:
// thisDev
// [in] .
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirReceive(pFirDevice_t thisDev)
{
DEBUGMSG(ZONE_RECV, (TEXT("Sir: +SirReceive, 0x%0x8.\r\n"), thisDev));
// Disable Transmitter and interrupt first
SirDisableInterrupt(thisDev);
thisDev->AdapterState = ADAPTER_RX;
// Enable Transmit interrupt first
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_DREN, UART_UCR4_DREN_ENABLE);
DEBUGMSG(ZONE_RECV, (TEXT("Sir: -SirReceive 0x%x\r\n"),g_pVSIRReg->USR2));
}
//-----------------------------------------------------------------------------
//
// Function: SirReceivePacket
//
// This function receives and analyze the raw IR data.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// This function returns true or false.
//
//-----------------------------------------------------------------------------
static BOOLEAN SirReceivePacket(pFirDevice_t thisDev)
{
UINT rawBufPos, rawBytesRead;
BOOLEAN result;
UCHAR thisch;
PLIST_ENTRY pListEntry;
DEBUGMSG(ZONE_RECV, (TEXT("Sir: +SirReceivePacket\r\n")));
// Read in and process groups of incoming bytes from the FIFO.
// NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
// bytes so that we can see the 'EOF'; hence <= and not <.
while ((thisDev->portInfo.rcvState != STATE_SAW_EOF) && (thisDev->portInfo.rcvBufPos <= MAX_RCV_DATA_SIZE))
{
if (thisDev->portInfo.rcvState == STATE_CLEANUP)
{
// We returned a complete packet last time, but we had read some
// extra bytes, which we stored into the rawBuf after returning
// the previous complete buffer to the user.
// So instead of calling DoRcvDirect in this first execution of this loop,
// we just use these previously-read bytes.
// (This is typically only 1 or 2 bytes).
rawBytesRead = thisDev->portInfo.rcvBufPos;
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.rcvBufPos = 0;
}
else
{
rawBytesRead = SirHwRead(thisDev->portInfo.rawBuf, SER_FIFO_DEPTH);
if (rawBytesRead == (UINT)-1)
{
// Error. Reset the state
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.rcvBufPos = 0;
continue;
}
else if (rawBytesRead == 0)
{
DEBUGMSG(ZONE_RECV, (TEXT("Sir: 0 byte read, break\r\n")));
break;
}
}
// Let the receive state machine process this group of characters
// we got from the FIFO.
// NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
// bytes so that we can see the 'EOF'; hence <= and not <.
for (rawBufPos = 0;
((thisDev->portInfo.rcvState != STATE_SAW_EOF) &&
(rawBufPos < rawBytesRead) &&
(thisDev->portInfo.rcvBufPos <= MAX_RCV_DATA_SIZE));
rawBufPos++)
{
thisch = thisDev->portInfo.rawBuf[rawBufPos];
DEBUGMSG(ZONE_RECV, (TEXT("Sir: cur state=%d, data=0x%x\r\n"),thisDev->portInfo.rcvState,thisch));
switch (thisDev->portInfo.rcvState)
{
case STATE_INIT:
switch (thisch)
{
case SLOW_IR_BOF:
thisDev->portInfo.rcvState = STATE_GOT_BOF;
break;
case SLOW_IR_EOF:
case SLOW_IR_ESC:
default:
// This is meaningless noise. Scan past it.
break;
}
break;
case STATE_GOT_BOF:
switch (thisch)
{
case SLOW_IR_BOF:
break;
case SLOW_IR_EOF:
DEBUGMSG(ZONE_ERROR, (TEXT("EOF in absorbing-BOFs state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
break;
case SLOW_IR_ESC:
thisDev->portInfo.rcvBufPos = 0;
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[0] = thisch;
thisDev->portInfo.rcvBufPos = 1;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_ACCEPTING:
switch (thisch)
{
case SLOW_IR_BOF:
DEBUGMSG(ZONE_WARN, (TEXT("WARNING: BOF during accepting state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.rcvBufPos = 0;
break;
case SLOW_IR_EOF:
if (thisDev->portInfo.rcvBufPos <
IR_ADDR_SIZE + IR_CONTROL_SIZE + SLOW_IR_FCS_SIZE)
{
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.rcvBufPos = 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.rcvBufPos++] = 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
DEBUGMSG(ZONE_ERROR, (TEXT("DoRcv - abort sequence; ")
TEXT("ABORTING IR PACKET: (got following ")
TEXT("packet + ESC,%xh)"),
(UINT)thisch));
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.rcvBufPos = 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.rcvBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("Unnecessary escape sequence: (got following packet + ESC,%xh"), (UINT)thisch));
thisDev->portInfo.readBuf[thisDev->portInfo.rcvBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_SAW_EOF:
default:
DEBUGMSG(ZONE_ERROR, (TEXT("Illegal state in DoRcv")));
thisDev->portInfo.rcvBufPos = 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.
DEBUGMSG(ZONE_RECV, (TEXT("Sir: *** DoRcv returning with COMPLETE packet, read %d bytes ***"),
thisDev->portInfo.rcvBufPos));
ASSERT(!IsListEmpty(&thisDev->rcvBufBuf));
//QueueReceivePacket(thisDev, thisDev->portInfo.readBuf, thisDev->portInfo.rcvBufPos, FALSE);
QueueReceivePacket(thisDev, thisDev->portInfo.readBuf, thisDev->portInfo.rcvBufPos);
// The protocol has our buffer. Get a new one.
pListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
thisDev->portInfo.readBuf = (PUCHAR) LIST_ENTRY_TO_RCV_BUF(pListEntry);
result = TRUE;
if (rawBufPos < rawBytesRead)
{
// 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.rcvBufPos = rawBytesRead-rawBufPos;
thisDev->portInfo.rcvState = STATE_CLEANUP;
}
else
{
thisDev->portInfo.rcvState = STATE_INIT;
}
break;
default:
if (thisDev->portInfo.rcvBufPos > MAX_RCV_DATA_SIZE)
{
DEBUGMSG(ZONE_ERROR, (TEXT("Sir: Overrun in DoRcv : read %d=%xh bytes:"),
thisDev->portInfo.rcvBufPos, thisDev->portInfo.rcvBufPos));
thisDev->portInfo.rcvBufPos = 0;
thisDev->portInfo.rcvState = STATE_INIT;
}
else
{
DEBUGMSG(ZONE_RECV, (TEXT("Sir: DoRcv returning with partial packet, read %d bytes"),
thisDev->portInfo.rcvBufPos));
}
result = FALSE;
break;
}
DEBUGMSG(ZONE_RECV, (TEXT("Sir: -SirReceivePacket\r\n")));
return result;
}
//-----------------------------------------------------------------------------
//
// Function: SirInterruptHandler
//
// This function is the interrupt handler for Sir device.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirInterruptHandler(pFirDevice_t thisDev)
{
UINT32 tempRegData = 0, loops = 0;;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: +SirInterruptHandler, 0x%08x\r\n"), thisDev));
// Get interrupt status
tempRegData = g_pVSIRReg->USR2;
if (tempRegData & SIR_INTR_MASK)
{
if (thisDev->writePending)
{
// Tx
DEBUGMSG(ZONE_THREAD, (TEXT("Sir: COM INTERRUPT: xmit reg empty, 0x%08x."), tempRegData));
if (tempRegData & CSP_BITFMASK(UART_USR2_TXFE))
{
SirHwWrite(thisDev);
thisDev->writePending = FALSE;
// 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;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: set new speed\r\n")));
SetSpeed(thisDev);
}
}
// Any more Tx packets?
if (!IsListEmpty(&thisDev->SendQueue))
{
// Kick off another Tx
SirSendPacketQ(thisDev, TRUE);
}
else
{
// There are no more bytes to send;
// reset interrupts for receive mode.
SirReceive(thisDev);
}
}
else if(tempRegData & CSP_BITFMASK(UART_USR2_RDR))
{
// Rx
DEBUGMSG(ZONE_THREAD, (TEXT("COM INTERRUPT: rcv data available! 0x%08x\r\n"), tempRegData));
thisDev->nowReceiving = TRUE;
if (!thisDev->mediaBusy)
{
// If we have just started receiving a packet, indicate media-busy
// to the protocol.
thisDev->mediaBusy = TRUE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: HandleInterrupt indicating media busy\r\n")));
NdisReleaseSpinLock(&thisDev->Lock);
NdisMIndicateStatus(thisDev->ndisAdapterHandle, NDIS_STATUS_MEDIA_BUSY, NULL, 0);
NdisMIndicateStatusComplete(thisDev->ndisAdapterHandle);
NdisAcquireSpinLock(&thisDev->Lock);
}
if (SirReceivePacket(thisDev))
{
// The receive engine has accumulated an entire frame.
// Request a deferred callback so we can deliver the frame
// when not in interrupt context.
DeliverFullBuffers(thisDev);
}
}
else
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: COM INTERRUPT: dummy interrupt, 0x%08x, ignored.\r\n"), tempRegData));
}
}
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("Sir: SirInterruptHandler: unexpected interrupt comes, 0x%08x.\r\n"), tempRegData));
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -