⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receive.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
           RECV_PACKET_RESERVED_FROM_PACKET(Packet)->RecvHeader = pRecvBufHead;

           //
           //	Chain the first buffer to the packet.
           //
           NdisChainBufferAtBack(Packet, pRecvBufHead->NdisBuffer);
       }

       if (pEntryOfRxReportQ->RxReportQDWord1.Eop)
       {
           // 
           //  Need to Adjust the last receive buffer size.
           //  LongWord size.
           // 
           LastBufferLength = pEntryOfRxReportQ->RxReportQDWord1.Size;

           if (LastBufferLength)
           {
               // 
               //  Convert to Byte length.
               // 
               LastBufferLength <<= 2;
           }
           else
           {
               // 
               //  The value 0 is used to represent exactly 16KB
               //  of valid data.
               // 
#if DBG
               DbgPrint("TBATM155: tbAtm155RxInterruptOnCompletion: pEntry %p, LastBufLen zero\n",
               		pEntryOfRxReportQ);
#endif // DBG
               LastBufferLength = BLOCK_16K;
           }
           
           ASSERT (LastBufferLength >=  sizeof(AAL5_PDU_TRAILER));
                      
           if (pEntryOfRxReportQ->RxReportQDWord1.Sop)
           {
               //
               // If there is only 1 buffer for this packet,
               // adjust the length of NdisBuffer.
               //
               NdisAdjustBufferLength(							
                   pRecvBufHead->NdisBuffer,
                   LastBufferLength);
           }
           else
           {
               //
               // If there are more than 1 buffer for this packet,
               // adjust the length of FlushBuffer.
               //
               NdisAdjustBufferLength(							
                   pRecvBufHead->FlushBuffer,
                   LastBufferLength);
           }
       }

       tbAtm155InsertRecvBufferAtTail(pSegCompleting, pRecvBufHead, FALSE);

       //
       //  Get the descriptor for this packet.
       //
       Packet = pSegCompleting->BufListHead->Packet;

       pSegCompleting->BufListHead->Last = pRecvBufHead;

       if (pEntryOfRxReportQ->RxReportQDWord1.Sop == 0)
       {
           //
           //	Chain the buffer to the packet.
           //
           NdisChainBufferAtBack(Packet, pRecvBufHead->FlushBuffer);
       }

       if (pEntryOfRxReportQ->RxReportQDWord1.Eop == 0)
       {
           continue;
       }           

       //
       //	We support AAL5 only
       //
       //
       //	Get the packet information.
       //  (09/15/97) 
       //  WARNING: the returned PhysicalBufferCount is not
       //           the "real" buffer count for the requested packet.
       //           DO NOT use PhysicalBufferCount.
       //
       NdisQueryPacket(
           Packet,
           &PhysicalBufferCount,
           NULL,
           NULL,
           &PacketLength);

       dbgLogRecvPacket(
           pVc->DebugInfo,
           Packet,
           PhysicalBufferCount,
           PacketLength,
           'nikp');

		Reserved = RECV_PACKET_RESERVED_FROM_PACKET(Packet);

       //
       //	The BufferCount field is actually the number of buffers
       //	that were allocated to receive the packet.  If it is
       //	greater than one then the AAL5 PDU trailer and/or padding
       //	may be split between buffers.  We first optimize for
       //	packets that contain only one buffer.
       //
       do
       {
           NdisZeroMemory (&Trailer, sizeof(AAL5_PDU_TRAILER));
           if (1 == pSegCompleting->BufferCount)
           {
               PUCHAR  BufferVa;
               UINT    BufferLength;

               dbgLogRecvPacket(pVc->DebugInfo, Packet, (ULONG)pRecvBuf, 1, '   1');

               //
               //	Get the virtual address and length of the first buffer.
               //

#if BUILD_W2K
               NdisQueryBuffer(
                       pRecvBufHead->NdisBuffer,
                       &BufferVa,
                       &BufferLength);

#else
               NdisQueryBufferSafe(
                       pRecvBufHead->NdisBuffer,
                       &BufferVa,
                       &BufferLength,
                       NormalPagePriority);
#endif
               if (BufferVa == NULL)
               {
                   //
                   // If we cannot get BufferVa due to low resources, just return the packet
                   //  
                   fQueryBufferFail = TRUE;
                   break;
               
               }
               dbgLogRecvPacket(pVc->DebugInfo, Packet, BufferLength, 0, '   2');

               //
               //	Copy the AAL5 PDU trailer from the end of the buffer.
               //
               NdisMoveMemory(
                   &Trailer,
                   BufferVa + BufferLength - sizeof(AAL5_PDU_TRAILER),
                   sizeof(AAL5_PDU_TRAILER));

               //
               //	Need to convert the length into a readable form.
               //
               Trailer.Length = TBATM155_SWAP_USHORT(Trailer.Length);
               Trailer.CRC = TBATM155_SWAP_ULONG(Trailer.CRC);

               //
               //  Check if we get a corrupted packet.
               //
               if ((LastBufferLength < (UINT)Trailer.Length) ||
                   (LastBufferLength > (UINT)(Trailer.Length + MAX_APPEND_BYTES)))
               {
                   fCorruptedPacket = TRUE;
               }
    
               //
               //	Now we need to determine the packet size with out the
               //	trailer and padding.  This is the value that is in
               //	the Trailer.Length.
               //
               NdisAdjustBufferLength(
                   pRecvBufHead->NdisBuffer,
                   Trailer.Length);

               dbgLogRecvPacket(pVc->DebugInfo, Packet, Trailer.Length, 0, '  lt');
           }
           else
           {
               ///
               //	Things are a little more complicated....
               //	Since there is more than one buffer it means that the
               //	padding and/or AAL5 pdu trailer can be split between
               //  them.
               ///
               LastBuffer = pSegCompleting->BufListTail->FlushBuffer;

               //
               //	First look for a packet that has a last buffer that is
               //	large enough for the AAL5_PDU_TRAILER.
               //

#if BUILD_W2K
               NdisQueryBuffer(
                   LastBuffer,
                   &LastBufferVa,
                   &LastBufferLength);

#else
               NdisQueryBufferSafe(
                   LastBuffer,
                   &LastBufferVa,
                   &LastBufferLength,
                   NormalPagePriority);
#endif
               if (LastBufferVa == NULL)
               {
                   //
                   // Cannot get BufferVa due to low resources
                   //
                   fQueryBufferFail = TRUE;
                   break;
               }
                   
               if (LastBufferLength >= sizeof(AAL5_PDU_TRAILER))
               {
                   dbgLogRecvPacket(pVc->DebugInfo, Packet, LastBufferLength, 0, '   2');

                   //
                   //	The last buffer has all of the AAL5 pdu trailer.
                   //  Copy it in at once.
                   //
                   NdisMoveMemory(
               	    &Trailer,
               	    (LastBufferVa + LastBufferLength) - sizeof(AAL5_PDU_TRAILER),
               	    sizeof(AAL5_PDU_TRAILER));
               }
               else
               {
                   dbgLogRecvPacket(pVc->DebugInfo, Packet, LastBufferLength, 0, '   3');

                   //
                   //	First grab whatever is in the last buffer and copy
                   //	it to our local trailer.
                   //
                   NdisMoveMemory(
               	    (PUCHAR)&Trailer + (sizeof(AAL5_PDU_TRAILER) - LastBufferLength),
               	    LastBufferVa,
           	        LastBufferLength);

                   //
                   //	We need to get remaining trailer from the next to last
                   //	buffer...  but the next to last buffer can either be
                   //	represented by the NdisBuffer or FlushBuffer.  If
                   //	the PhysicalBufferCount is 2 then it's the NdisBuffer,
                   //	if not it's the FlushBuffer.
                   //
                   if (2 == pSegCompleting->BufferCount)
                   {    
                       prevLastBuffer = pSegCompleting->BufListTail->Prev->NdisBuffer;
                   }
                   else
                   {    
                       prevLastBuffer = pSegCompleting->BufListTail->Prev->FlushBuffer;
                   }

                   //
                   //  Get the next to last buffers virtual address and
                   //  length.
                   //
#if BUILD_W2K
               NdisQueryBuffer(
                    prevLastBuffer,
                    &prevLastBufferVa,
                    &prevLastBufferLength);

#else
               NdisQueryBufferSafe(
                    prevLastBuffer,
                    &prevLastBufferVa,
                    &prevLastBufferLength,
                    NormalPagePriority);
#endif

                   if (prevLastBufferVa == NULL)
                   {
                       //
                       // If cannot get preLastBufferVa due to low resources
                       // 
                       fQueryBufferFail = TRUE;
                       break;
                   }

                   //
                   //	Copy the first part of the trailer from this buffer
                   //	into our local.
                   //
                   NdisMoveMemory(
                       &Trailer,
           	           (PUCHAR)((prevLastBufferVa + prevLastBufferLength) -
                       (sizeof(AAL5_PDU_TRAILER) - LastBufferLength)),
                       sizeof(AAL5_PDU_TRAILER) - LastBufferLength);
               }

               //
               //	Need to convert the length into a readable form.
               //
               Trailer.Length = TBATM155_SWAP_USHORT(Trailer.Length);
               Trailer.CRC = TBATM155_SWAP_ULONG(Trailer.CRC);

               dbgLogRecvPacket(pVc->DebugInfo, Packet, Trailer.Length, 0, '  lt');

               //
               //	Determine the amount of packet data that needs to be
               //	dumped before we indicate it up.
               //

#if DBG
        
               if (PacketLength < Trailer.Length)
               {
                   DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
                       ("tbAtm155RxIOC: PacketLength (%x), Trailer.Length (%x).\n",
                         PacketLength, Trailer.Length));

                   DBGBREAK(DBG_COMP_SPECIAL, DBG_LEVEL_ERR);
               }

#endif

               TrimAmount = PacketLength - Trailer.Length;

               dbgLogRecvPacket(pVc->DebugInfo, Packet, TrimAmount, 0, '  at');

               //
               //  See if the last buffer contains all the data that
               //  needs to be trimmed.
               //
               if (TrimAmount < LastBufferLength)
               {
                   //
                   //	Adjust the last packet.
                   //
                   NdisAdjustBufferLength(
                       LastBuffer,
                       LastBufferLength - TrimAmount);

                   dbgLogRecvPacket(
                       pVc->DebugInfo, 
                       Packet, 
                       LastBufferLength - TrimAmount, 
                       0,
                       'blat');
               }
               else
               {
                   //
                   //	Drop the last buffer from the packet.
                   //	This is safe and we don't need to do anything with
                   //	the buffer since it is saved in the RECV_BUFFER_HEADER.
                   //
                   NdisUnchainBufferAtBack(Packet, &LastBuffer);
    
                   //
                   //	Determine how much data needs to be trimmed from
                   //	the next to last.
                   //
                   TrimAmount -= LastBufferLength;
    
                   //
                   //  If there were only two buffers then we need to
                   //  adjust the NdisBuffer since this is the one that
                   //  is chained to the Packet.  If there are more than
                   //  two buffers in the Packet then we need to adjust
                   //  the FlushBuffer.
                   //
                   if (2 == pSegCompleting->BufferCount)
                   {
                       prevLastBuffer = pSegCompleting->BufListTail->Prev->NdisBuffer;
                   }
                   else
                   {
                       prevLastBuffer = pSegCompleting->BufListTail->Prev->FlushBuffer;
                   }

                   //
                   //	Get the next to last buffers virtual address and length.
                   //

#if BUILD_W2K
               NdisQueryBuffer(
                    prevLastBuffer,
                    NULL,
                    &prevLastBufferLength);

#else
               NdisQueryBufferSafe(
                   prevLastBuffer,
                   NULL,
                   &prevLastBufferLength,
                    NormalPagePriority);
#endif

                   //
                   //	Adjust the next to last (now the last) buffer
                   //	in the packet.
                   //
                   NdisAdjustBufferLength(
                       prevLastBuffer,
                       prevLastBufferLength - TrimAmount);

                   dbgLogRecvPacket(pVc->DebugInfo, Packet, LastBufferLength - TrimAmount, 0, 'atbl');
               }
    
           } // end of if (1 == pSegCompleting->BufferCount)
       }
       while (FALSE);           

       //
       //    Save the traile

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -