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

📄 sendrcv.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
}

VOID 
NICFreeRecvPacket(
    PMP_ADAPTER Adapter,
    PNDIS_PACKET Packet)
/*++

Routine Description:

    Adapter    - pointer to the adapter structure
    Packet      - pointer to the receive packet
        
Arguments:

    This is called by MPReturnPacket to free the Receive packet
    indicated above. Since we have used the send-side TCB, we 
    will also carefully complete the pending SendPacket if we are 
    the last one to use the TCB buffers.
    
Return Value:

    VOID

--*/
{

    PTCB pTCB = *(PTCB *)Packet->MiniportReserved;
    PMP_ADAPTER SendAdapter = (PMP_ADAPTER)pTCB->Adapter;
    PNDIS_PACKET SendPacket = pTCB->OrgSendPacket;    
    PLIST_ENTRY pEntry;
    
    DEBUGP(MP_TRACE, ("--> NICFreeRecvPacket\n"));
    DEBUGP(MP_INFO, ("Adapter= %p FreePkt= %p Ref=%d\n", 
                            SendAdapter, SendPacket, pTCB->Ref));

    ASSERT(pTCB->Ref > 0);
    ASSERT(Adapter);
    //
    // Put the packet back in the free list for reuse.
    //
    NdisAcquireSpinLock(&Adapter->RecvLock);    

    InsertTailList(
        &Adapter->RecvFreeList, 
        (PLIST_ENTRY)&Packet->MiniportReserved[0]);
    
    Adapter->nBusyRecv--;     
    ASSERT(Adapter->nBusyRecv >= 0);
    
    NdisReleaseSpinLock(&Adapter->RecvLock);    


    //
    // Check to see whether we are the last one to use the TCB
    // by decrementing the refcount. If so, complete the pending
    // Send packet and free the TCB block for reuse.
    // 
    if(NdisInterlockedDecrement(&pTCB->Ref) == 0)
    {
        Adapter->GoodTransmits++;

        NdisMSendComplete(
            SendAdapter->AdapterHandle,
            SendPacket,
            NDIS_STATUS_SUCCESS);
    
        NICFreeSendTCB(SendAdapter, pTCB);
        //
        // Before we exit, since we have the control, let use see if there any 
        // more packets waiting in the queue to be sent.
        //
        if(MP_IS_READY(SendAdapter))
        {
            pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
                            &SendAdapter->SendWaitList, 
                            &SendAdapter->SendLock);
            if(pEntry)
            {
                SendPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
                NICSendPacket(SendAdapter, SendPacket);             
            }
        }
    }

    DEBUGP(MP_TRACE, ("<-- NICFreeRecvPacket\n"));
}

VOID 
NICFreeSendTCB(
    IN PMP_ADAPTER Adapter,
    IN PTCB pTCB)
/*++

Routine Description:

    Adapter    - pointer to the adapter structure
    pTCB      - pointer to TCB block
        
Arguments:

    This routine reinitializes the TCB block and puts it back
    into the SendFreeList for reuse.
    

Return Value:

    VOID

--*/
{
    DEBUGP(MP_TRACE, ("--> NICFreeSendTCB %p\n", pTCB));
    
    pTCB->OrgSendPacket = NULL;
    pTCB->Buffer->Next = NULL;

    ASSERT(!pTCB->Ref);
    
    //
    // Re adjust the length to the originl size
    //
    NdisAdjustBufferLength(pTCB->Buffer, NIC_BUFFER_SIZE);

    //
    // Insert the TCB back in the send free list     
    //
    NdisAcquireSpinLock(&Adapter->SendLock);
    
    NdisInitializeListHead(&pTCB->List);
    InsertHeadList(&Adapter->SendFreeList, &pTCB->List);
    Adapter->nBusySend--;
    ASSERT(Adapter->nBusySend >= 0);
    
    NdisReleaseSpinLock(&Adapter->SendLock); 
    
    DEBUGP(MP_TRACE, ("<-- NICFreeSendTCB\n"));
    
}



VOID 
NICFreeQueuedSendPackets(
    PMP_ADAPTER Adapter
    )
/*++

Routine Description:

    This routine is called by the Halt or Reset handler to fail all
    the queued up SendPackets because the device is either
    gone, being stopped for resource rebalance, or reset.
    
Arguments:

    Adapter    - pointer to the adapter structure

Return Value:

    VOID

--*/
{
    PLIST_ENTRY       pEntry;
    PNDIS_PACKET      Packet;

    DEBUGP(MP_TRACE, ("--> NICFreeQueuedSendPackets\n"));

    while(TRUE)
    {
        pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
                        &Adapter->SendWaitList, 
                        &Adapter->SendLock);
        if(!pEntry)
        {
            break;
        }

        Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
        NdisMSendComplete(
            Adapter->AdapterHandle,
            Packet,
            NDIS_STATUS_FAILURE);
    }

    DEBUGP(MP_TRACE, ("<-- NICFreeQueuedSendPackets\n"));

}

VOID 
NICFreeQueuedRecvPackets(
    PMP_ADAPTER Adapter
    )
/*++

Routine Description:

    This routine is called by the Halt handler to fail all
    the queued up RecvPackets if it succeeds in cancelling
    the RecvIndicate timer DPC.
    
Arguments:

    Adapter    - pointer to the adapter structure

Return Value:

    VOID

--*/
{
    PLIST_ENTRY       pEntry;
    PRCB pRCB = NULL;

    DEBUGP(MP_TRACE, ("--> NICFreeQueuedRecvPackets\n"));

    while(TRUE)
    {
        pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
                        &Adapter->RecvWaitList, 
                        &Adapter->RecvLock);
        if(!pEntry)
        {
            break;
        }

        pRCB = CONTAINING_RECORD(pEntry, RCB, List);

        ASSERT(pRCB);
        ASSERT(pRCB->Packet);
        
        NICFreeRecvPacket(Adapter, pRCB->Packet);
        
        //
        // We are done with RCB memory. So free it.
        //
        NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pRCB);
        
    }

    DEBUGP(MP_TRACE, ("<-- NICFreeQueuedRecvPackets\n"));

}



BOOLEAN
NICIsPacketTransmittable(
    PMP_ADAPTER Adapter,
    PNDIS_PACKET Packet
    )
/*++

Routine Description:

    This routines checks to see whether the packet can be accepted
    for transmission based on the currently programmed filter type 
    of the NIC and the mac address of the packet.
    
Arguments:

    Adapter    - pointer to the adapter structure
    Packet      - pointer to the send packet


Return Value:

    True or False

--*/
{
    INT               Equal;            
    UINT              PacketLength;
    PNDIS_BUFFER      FirstBuffer = NULL;
    PUCHAR            Address = NULL;
    UINT              CurrentLength;
    ULONG             index;
    BOOLEAN           result = FALSE;
    
    DEBUGP(MP_LOUD, 
        ("DestAdapter=%p, PacketFilter = 0x%08x\n", 
        Adapter,
        Adapter->PacketFilter));

    
    do {

#ifdef NDIS51_MINIPORT
       NdisGetFirstBufferFromPacketSafe(
            Packet,
            &FirstBuffer,
            &Address,
            &CurrentLength,
            &PacketLength,
            NormalPagePriority);
#else
       NdisGetFirstBufferFromPacket(
            Packet,
            &FirstBuffer,
            &Address,
            &CurrentLength,
            &PacketLength);
#endif
        if(!Address){
            break;
        }
        

        DEBUGP(MP_LOUD, ("Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n", 
                    Address[0], Address[1], Address[2],
                    Address[3], Address[4], Address[5]));
        
        //
        // If the NIC is in promiscuous mode, we will transmit anything
        // and everything.
        //
        if(Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
            result = TRUE;
            break;
        } 
        else if(ETH_IS_BROADCAST(Address)) {
            //
            // If it's a broadcast packet, check our filter settings to see
            // we can transmit that.
            //
            if(Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST) {
                result = TRUE;
                break;
            }
        }
        else if(ETH_IS_MULTICAST(Address)) {
            //
            // If it's a multicast packet, check our filter settings to see
            // we can transmit that.
            //
            if(Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
                result = TRUE;
                break;
            }
            else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST) {
                //
                // Check to see if the multicast address is in our list
                //
                Equal = (UINT)-1;
                for(index=0; index <  Adapter->ulMCListSize; index++) {
                    ETH_COMPARE_NETWORK_ADDRESSES_EQ(
                        Address,
                        Adapter->MCList[index], 
                        &Equal);
                    if(Equal == 0){ // 0 Implies equality
                        result = TRUE;
                        break;
                    }
                }
                if(Equal == 0){ // 0 Implies equality
                    result = TRUE;
                    break;
                }
            }
        }
        else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_DIRECTED) {
            //
            // This has to be a directed packet. If so, does packet source 
            // address match with the mac address of the NIC.
            // 
            ETH_COMPARE_NETWORK_ADDRESSES_EQ(
                Address,
                Adapter->CurrentAddress, 
                &Equal);
            if(Equal == 0){
                result = TRUE;
                break;
            }
        }
        //
        // This is a junk packet. We can't transmit this.
        //
        result = FALSE;
        
    }while(FALSE);
    
    return result;
}

BOOLEAN
NICCopyPacket(
    PMP_ADAPTER Adapter,
    PTCB pTCB, 
    PNDIS_PACKET Packet)
/*++

Routine Description:

    This routine copies the packet data into the TCB data block.
        
Arguments:

    Adapter    - pointer to the MP_ADAPTER structure
    pTCB      - pointer to TCB block
    Packet    - packet to be transfered.


Return Value:

    VOID

--*/
{
    PNDIS_BUFFER   MyBuffer;
    PNDIS_BUFFER   CurrentBuffer;
    PVOID          VirtualAddress;
    UINT           CurrentLength;
    UINT           BytesToCopy;
    UINT           BytesCopied = 0;
    UINT           BufferCount;
    UINT           PacketLength;    
    UINT           DestBufferSize = NIC_BUFFER_SIZE;        
    PUCHAR         pDest;
    BOOLEAN        bResult = TRUE;
    
    DEBUGP(MP_TRACE, ("--> NICCopyPacket\n"));

    pTCB->OrgSendPacket = Packet;
    pTCB->Ref = 1;

    MyBuffer = pTCB->Buffer;
    pDest = pTCB->pData;
    
    MyBuffer->Next = NULL;

    NdisQueryPacket(Packet,
                    NULL,
                    &BufferCount,
                    &CurrentBuffer,
                    &PacketLength);

    ASSERT(PacketLength <= NIC_BUFFER_SIZE);

    BytesToCopy = min(PacketLength, NIC_BUFFER_SIZE); 
    
    if(BytesToCopy < ETH_MIN_PACKET_SIZE)
    {
        BytesToCopy = ETH_MIN_PACKET_SIZE;   // padding
    }
             
    while(CurrentBuffer && DestBufferSize)
    {
        NdisQueryBufferSafe(
            CurrentBuffer,
            &VirtualAddress,
            &CurrentLength,
            NormalPagePriority);
        
        if(VirtualAddress == NULL){
            bResult = FALSE;
            break;
        }

        CurrentLength = min(CurrentLength, DestBufferSize); 

        if(CurrentLength)
        {
            // Copy the data.
            NdisMoveMemory(pDest, VirtualAddress, CurrentLength);
            BytesCopied += CurrentLength;
            DestBufferSize -= CurrentLength;
            pDest += CurrentLength;
        }

        NdisGetNextBuffer(
            CurrentBuffer,
            &CurrentBuffer);
    }

    if(bResult) {
        if(BytesCopied < BytesToCopy)
        {
            //
            // This would be the case if the packet size is less than 
            // ETH_MIN_PACKET_SIZE. Pad the buffer
            // up to ETH_MIN_PACKET_SIZE with zero bytes to avoid
            // information disclosure security attack. Remeber I of
            // STRIDE?
            //            
            //
            NdisZeroMemory(pDest, BytesToCopy-BytesCopied);
            BytesCopied = BytesToCopy;
        }
        NdisAdjustBufferLength(MyBuffer, BytesCopied);        
    }

    DEBUGP(MP_TRACE, ("<-- NICCopyPacket\n"));

    return bResult;
}

⌨️ 快捷键说明

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