📄 nscfir.c
字号:
{
LOG_ERROR("receive error: disc stat=%02x, lost=%d\n",frameStat,rcvFrameSize);
// Do nothing
}
else if (frameStat != 0) {
/*
* Some rcv error occurred. Reset DMA.
*/
LOG_ERROR("Receive error: stat=%02x, lost=%d\n",frameStat,rcvFrameSize);
DEBUGFIR(DBG_RX|DBG_ERR, ("NSC: RCV ERR: frameStat=%xh FrameSize=%d \n",
(UINT)frameStat,rcvFrameSize));
if (frameStat & 0x40) {
if (frameStat & 0x01) {
RegStats.StatusFIFOOverflows++;
}
if (frameStat & 0x02) {
RegStats.ReceiveFIFOOverflows++;
}
RegStats.MissedPackets += rcvFrameSize;
}
else{
if (frameStat & 0x01) {
RegStats.StatusFIFOOverflows++;
}
if (frameStat & 0x02) {
RegStats.ReceiveFIFOOverflows++;
}
if (frameStat & 0x04) {
RegStats.ReceiveCRCErrors++;
}
if (frameStat & 0x08) {
}
if (frameStat & 0x10) {
}
LOG("Bytes Lost: %d",rcvFrameSize);
ASSERT((thisDev->rcvPktOffset + rcvFrameSize)<= RCV_DMA_SIZE);
/* Advance pointer past bad packet. */
thisDev->rcvPktOffset += rcvFrameSize;
}
}
else if (thisDev->rcvPktOffset + rcvFrameSize > EndOfData )
{
LOG_ERROR("Receive: Frame extends beyond where dma control wrote: offset=%x, Frame size=%x, EndOfData=%x",(ULONG)thisDev->rcvPktOffset,(ULONG)rcvFrameSize,(ULONG)EndOfData);
DBGERR(("Packet won't fit in received data!\n"));
DBGERR(("rcvPktOffset:%x rcvFrameSize:%x LastReadDmaCount:%x\n",
thisDev->rcvPktOffset,
rcvFrameSize,
LastReadDMACount));
DBGERR(("rcvDmaOffset:%x rcvDmaSize:%x EndOfData:%x\n",
thisDev->rcvDmaOffset, thisDev->rcvDmaSize, EndOfData));
//
// The frame seems to have extended past the end of where we dma the data.
// This should only happen if the dma space just less than the size of
// the fifo too small. The remaining data is still sitting in the fifo
// Attempt to read it out so it will be empty when we got read more frames
//
while (BytesInFifo > 0) {
SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_0, TXD_RXD_OFFSET);
BytesInFifo--;
}
BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 7) & 0x3f;
if (BytesInFifo > 0) {
//
// still bytes in the fifo after attmpting to read them out.
// Another frame has probably started showing up, Can trust the data collected
// so mark these frames to be discarded
//
LOG_ERROR("Receive: Still have bytes in the fifo after attempting to flush, %d bytes remaining",BytesInFifo);
BytesInFifo=0;
thisDev->DiscardNextPacketSet = TRUE;
}
//
// this should be the last frame to be received with out error, advance this pointer
// anyway.
//
thisDev->rcvPktOffset += rcvFrameSize;
}
else {
DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: *** >>> FIR_DeliverFrames DMA offset 0x%x:\n",
thisDev->rcvDmaOffset));
//
// this is where the new frame starts
//
#pragma prefast(suppress:12008, "This summation is guarenteed to be valid");
NewFrame = thisDev->dmaReadBuf + thisDev->rcvPktOffset;
//
// the next frame will start after the end of this frame
//
thisDev->rcvPktOffset += rcvFrameSize;
ASSERT(thisDev->rcvPktOffset < RCV_DMA_SIZE);
//
// the FCS is included in the length of the frame, remove that from the length
// we send to the protocol
//
rcvFrameSize -= fcsSize;
if (rcvFrameSize <= MAX_NDIS_DATA_SIZE &&
rcvFrameSize >= IR_ADDR_SIZE + IR_CONTROL_SIZE)
{
//
// Queue this rcv packet. Move Newframe pointer
// into RxDMA buffer.
//
RegStats.ReceivedPackets++;
RegStats.RxWindow++;
QueueReceivePacket(thisDev, NewFrame, rcvFrameSize, TRUE);
}
else {
LOG("Error: invalid packet size in FIR_DeliverFrames %d", rcvFrameSize);
DEBUGFIR(DBG_RX|DBG_ERR, ("NSC: invalid packet size in FIR_DeliverFrames; %xh > %xh\n", rcvFrameSize, MAX_RCV_DATA_SIZE));
//
// Discard the rest of the packets.
//
while (SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 5)&0x80)
{
SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 6);
SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 7);
}
thisDev->DiscardNextPacketSet = TRUE;
}
}
SyncGetFifoStatus(
&thisDev->interruptObj,
thisDev->portInfo.ioBase,
&frameStat,
&rcvFrameSize
);
LOG("frameStat: %x, size=%d ", (UINT) frameStat,rcvFrameSize);
DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: frameStat = %xh\n", (UINT) frameStat));
//
// Clear the line status register, of any past events.
//
thisDev->LineStatus = SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, 5);
}
thisDev->FirIntMask = 0x04;
SetupRecv(thisDev);
LOG("<== FIR_DeliverFrames");
DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: <== FIR_DeliverFrames\n"));
}
BOOLEAN NSC_Setup(IrDevice *thisDev)
{
NDIS_DMA_DESCRIPTION DMAChannelDcr;
NDIS_STATUS stat;
/*
* Initialize rcv DMA channel
*/
RtlZeroMemory(&DMAChannelDcr,sizeof(DMAChannelDcr));
DMAChannelDcr.DemandMode = TRUE;
DMAChannelDcr.AutoInitialize = FALSE;
DMAChannelDcr.DmaChannelSpecified = FALSE;
DMAChannelDcr.DmaWidth = Width8Bits;
DMAChannelDcr.DmaSpeed = Compatible;
DMAChannelDcr.DmaPort = 0;
DMAChannelDcr.DmaChannel = thisDev->portInfo.DMAChannel; // 0;
stat = NdisMRegisterDmaChannel(&thisDev->DmaHandle,
thisDev->ndisAdapterHandle,
thisDev->portInfo.DMAChannel,
FALSE, &DMAChannelDcr, RCV_DMA_SIZE);
if (stat != NDIS_STATUS_SUCCESS) {
DEBUGFIR(DBG_ERR, ("NSC: NdisMRegisterDmaChannel failed\n"));
return FALSE;
}
InitializeDmaUtil(
&thisDev->DmaUtil,
thisDev->DmaHandle
);
thisDev->rcvDmaOffset = 0;
/*
* Because we enable rcv DMA while SIR receives may still be
* going on, we need to keep a separate receive buffer for DMA.
* This buffer gets swapped with the rcvBuffer data pointer
* and must be the same size.
*/
thisDev->dmaReadBuf=NscAllocateDmaBuffer(
thisDev->ndisAdapterHandle,
RCV_DMA_SIZE,
&thisDev->ReceiveDmaBufferInfo
);
if (thisDev->dmaReadBuf == NULL) {
return FALSE;
}
thisDev->TransmitDmaBuffer=NscAllocateDmaBuffer(
thisDev->ndisAdapterHandle,
MAX_IRDA_DATA_SIZE,
&thisDev->TransmitDmaBufferInfo
);
NdisAllocateBufferPool(&stat, &thisDev->dmaBufferPoolHandle, 2);
if (stat != NDIS_STATUS_SUCCESS){
LOG("Error: NdisAllocateBufferPool failed in NSC_Setup");
DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBufferPool failed in NSC_Setup\n"));
return FALSE;
}
NdisAllocateBuffer(&stat, &thisDev->rcvDmaBuffer,
thisDev->dmaBufferPoolHandle,
thisDev->dmaReadBuf,
RCV_DMA_SIZE
);
if (stat != NDIS_STATUS_SUCCESS) {
LOG("Error: NdisAllocateBuffer failed (rcv) in NSC_Setup");
DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBuffer failed (rcv) in NSC_Setup\n"));
return FALSE;
}
NdisAllocateBuffer(&stat, &thisDev->xmitDmaBuffer,
thisDev->dmaBufferPoolHandle,
thisDev->TransmitDmaBuffer,
MAX_IRDA_DATA_SIZE
);
if (stat != NDIS_STATUS_SUCCESS) {
LOG("NdisAllocateBuffer failed (xmit) in NSC_Setup");
DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBuffer failed (xmit) in NSC_Setup\n"));
return FALSE;
}
return TRUE;
}
void NSC_Shutdown(IrDevice *thisDev)
{
if (thisDev->xmitDmaBuffer){
NdisFreeBuffer( thisDev->xmitDmaBuffer);
thisDev->xmitDmaBuffer = NULL;
}
if (thisDev->rcvDmaBuffer){
NdisFreeBuffer(thisDev->rcvDmaBuffer);
thisDev->rcvDmaBuffer = NULL;
}
if (thisDev->dmaBufferPoolHandle){
NdisFreeBufferPool(thisDev->dmaBufferPoolHandle);
thisDev->dmaBufferPoolHandle = NULL;
}
if (thisDev->dmaReadBuf){
NscFreeDmaBuffer(&thisDev->ReceiveDmaBufferInfo);
thisDev->dmaReadBuf = NULL;
}
if (thisDev->TransmitDmaBuffer){
NscFreeDmaBuffer(&thisDev->TransmitDmaBufferInfo);
thisDev->TransmitDmaBuffer = NULL;
}
if (thisDev->DmaHandle){
NdisMDeregisterDmaChannel(thisDev->DmaHandle);
thisDev->DmaHandle = NULL;
}
}
BOOLEAN
NdisToFirPacket(
PNDIS_PACKET Packet,
UCHAR *irPacketBuf,
UINT TotalDmaBufferLength,
UINT *ActualTransferLength
)
{
PNDIS_BUFFER ndisBuf;
UINT ndisPacketBytes = 0;
UINT ndisPacketLen;
LOG("==> NdisToFirPacket");
DEBUGFIR(DBG_OUT, ("NSC: ==> NdisToFirPacket\n"));
/*
* Get the packet's entire length and its first NDIS buffer
*/
NdisQueryPacket(Packet, NULL, NULL, &ndisBuf, &ndisPacketLen);
LOG("NdisToFirPacket, number of bytes: %d", ndisPacketLen);
DEBUGFIR(DBG_OUT, ("NSC: NdisToFirPacket, number of bytes: %d\n", ndisPacketLen));
/*
* Make sure that the packet is big enough to be legal.
* It consists of an A, C, and variable-length I field.
*/
if (ndisPacketLen < IR_ADDR_SIZE + IR_CONTROL_SIZE){
LOG("Error: packet too short in %d", ndisPacketLen);
DEBUGFIR(DBG_ERR, ("NSC: packet too short in NdisToFirPacket (%d bytes)\n", ndisPacketLen));
return FALSE;
}
/*
* Make sure that we won't overwrite our contiguous buffer.
*/
if (ndisPacketLen > TotalDmaBufferLength){
/*
* The packet is too large
* Tell the caller to retry with a packet size large
* enough to get past this stage next time.
*/
LOG("Error: packet too large in %d ", ndisPacketLen);
DEBUGFIR(DBG_ERR, ("NSC: Packet too large in NdisToIrPacket (%d=%xh bytes), MAX_IRDA_DATA_SIZE=%d, TotalDmaBufferLength=%d.\n",
ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, TotalDmaBufferLength));
*ActualTransferLength = ndisPacketLen;
return FALSE;
}
/*
* Read the NDIS packet into a contiguous buffer.
* We have to do this in two steps so that we can compute the
* FCS BEFORE applying escape-byte transparency.
*/
while (ndisBuf) {
UCHAR *bufData;
UINT bufLen;
NdisQueryBufferSafe(ndisBuf, (PVOID *)&bufData, &bufLen,NormalPagePriority);
// Validate the packet size, test for possible integer overflow
//
if (bufData==NULL ||
((ULONGLONG)ndisPacketBytes + (ULONGLONG)bufLen > (ULONGLONG)ndisPacketLen)){
/*
* Packet was corrupt -- it misreported its size.
*/
*ActualTransferLength = 0;
ASSERT(0);
return FALSE;
}
NdisMoveMemory((PVOID)(irPacketBuf+ndisPacketBytes),
(PVOID)bufData, (ULONG)bufLen);
ndisPacketBytes += bufLen;
NdisGetNextBuffer(ndisBuf, &ndisBuf);
}
if (WPP_LEVEL_ENABLED(DBG_LOG_INFO)) {
UCHAR CommandByte=*(irPacketBuf+1);
UCHAR Nr=CommandByte >> 5;
UCHAR Ns=(CommandByte >> 1) & 0x7;
UCHAR Pf=(CommandByte >> 4) & 0x1;
if ((CommandByte & 1) == 0) {
LOG("Sending - I frame, Nr=%d, Ns=%d p/f=%d",Nr,Ns,Pf);
} else {
if ((CommandByte & 0x3) == 0x1) {
LOG("Sending - S frame, Nr=%d, xx=%d, p/f=%d",Nr, (CommandByte > 2) & 0x3, Pf);
} else {
LOG("Sending - U frame, p/f=%d",Pf);
}
}
}
/*
* Do a sanity check on the length of the packet.
*/
if (ndisPacketBytes != ndisPacketLen){
/*
* Packet was corrupt -- it misreported its size.
*/
LOG("Error: Packet corrupt in NdisToIrPacket "
"(buffer lengths don't add up to packet length)");
DEBUGFIR(DBG_ERR, ("NSC: Packet corrupt in NdisToIrPacket (buffer lengths don't add up to packet length).\n"));
*ActualTransferLength = 0;
return FALSE;
}
#ifdef DBG_ADD_PKT_ID
if (addPktIdOn){
static USHORT uniqueId = 0;
DEBUGFIR(DBG_OUT, ("NSC: *** --> SEND PKT ID: %xh\n", (UINT)uniqueId));
LOG("ID: Send (FIR) Pkt id: %x", uniqueId);
*(USHORT *)(irPacketBuf+ndisPacketBytes) = uniqueId++;
ndisPacketBytes += sizeof(USHORT);
}
#endif
*ActualTransferLength = ndisPacketBytes;
LOG("<== NdisToFirPacket");
DEBUGFIR(DBG_OUT, ("NSC: <== NdisToFirPacket\n"));
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -