Example #1
0
VOID
ReturnRCB(
    __in  PMP_ADAPTER   Adapter,
    __in  PRCB          Rcb)
/*++

Routine Description:

    This routine frees an RCB back to the unused pool, recovers relevant memory used in the RCB.

    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter     - The receiving adapter (the one that owns the RCB).
    Rcb         - The RCB to be freed.

Return Value:

    None.

--*/
{
    PUCHAR Data = Rcb->Data;
    ASSERT(Data); 

    DEBUGP(MP_TRACE, "[%p] ---> ReturnRCB. RCB: %p\n", Adapter, Rcb);

    if(VMQ_ENABLED(Adapter))
    {
        //
        // Recover RCB back to owner VMQ queue
        //
        RecoverRxQueueRcb(Adapter, Rcb);
    }
    else
    {
        //
        // Recover RCB to global RCB pool
        //
        NdisInterlockedInsertTailList(
                &Adapter->FreeRcbList,
                &Rcb->RcbLink,
                &Adapter->FreeRcbListLock);
        Rcb = NULL;
        //
        // We receive on the default receive queue, decrement its pending count
        //
        NICDereferenceReceiveBlock(Adapter, 0, NULL);
        HWFrameRelease((PFRAME)Data);
    }

    DEBUGP(MP_TRACE, "[%p] <--- ReturnRCB.\n", Adapter);

}
Example #2
0
void NICAttachAdapter(PMP_ADAPTER Adapter)
{
    DEBUGP(MP_TRACE, ("--> NICAttachAdapter\n"));

    NdisInterlockedInsertTailList(
        &GlobalData.AdapterList, 
        &Adapter->List, 
        &GlobalData.Lock);

    DEBUGP(MP_TRACE, ("<-- NICAttachAdapter\n"));
}
Example #3
0
__inline void
ssh_iodevice_buffer_free(SshInterceptorIoDevice io_dev, 
                         SshDeviceBuffer buf)
{
  ssh_free(buf->addr);

  if (buf->pre_allocated == 1)
    NdisInterlockedInsertTailList(&io_dev->free_list, &buf->link, 
                                  &io_dev->free_list_lock);
  else
    ssh_free(buf);
}
Example #4
0
VOID
ReturnTCB(
    __in  PMP_ADAPTER  Adapter,
    __in  PTCB         Tcb)
{
    TXNblRelease(Adapter, NBL_FROM_SEND_NB(Tcb->NetBuffer), TRUE);
    Tcb->NetBuffer = NULL;

    NdisInterlockedInsertTailList(
            &Adapter->FreeTcbList,
            &Tcb->TcbLink,
            &Adapter->FreeTcbListLock);
}
Example #5
0
NTSTATUS 
ssh_interceptor_iodevice_dispatch_read(PDEVICE_OBJECT device,
                                       PIRP irp)
{
  SshInterceptorIoDevice io_dev = SSH_NTDEV_TO_SSHDEV(device);


  irp->IoStatus.Status = STATUS_PENDING;
  IoMarkIrpPending(irp);

#pragma warning(disable: 4311 4312)
  IoSetCancelRoutine(irp, ssh_interceptor_iodevice_cancel_queued_read);
#pragma warning(default: 4311 4312)

  /* Insert into the queue of pending read requests */
  NdisInterlockedInsertTailList(&io_dev->read_queue,
                                &irp->Tail.Overlay.ListEntry,
                                &io_dev->read_queue_lock);

  ssh_task_notify(&io_dev->worker_thread, SSH_TASK_SIGNAL_NOTIFY);

  return STATUS_PENDING;
}
Example #6
0
VOID
#pragma prefast(suppress: 28167, "PREfast does not recognize IRQL is conditionally raised and lowered")
TXTransmitQueuedSends(
    _In_  PMP_ADAPTER  Adapter,
    _In_  BOOLEAN      fAtDispatch)
/*++

Routine Description:

    This routine sends as many frames from the SendWaitList as it can.

    If there are not enough resources to send immediately, this function stops
    and leaves the remaining frames on the SendWaitList, to be sent once there
    are enough resources.


    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter                     Our adapter
    fAtDispatch                 TRUE if the current IRQL is DISPATCH_LEVEL

Return Value:

    None.

--*/
{
    BOOLEAN fScheduleTheSendCompleteDpc = FALSE;
    ULONG NumFramesSent = 0;
    KIRQL OldIrql = PASSIVE_LEVEL;

    DEBUGP(MP_TRACE,
           "[%p] ---> TXTransmitQueuedSends\n",
           Adapter);

    //
    // This guard ensures that only one CPU is running this function at a time.
    // We check this so that items from the SendWaitList get sent to the
    // receiving adapters in the same order that they were queued.
    //
    // You could remove this guard and everything will still work ok, but some
    // frames might be delivered out-of-order.
    //
    // Generally, this mechanism wouldn't be applicable to real hardware, since
    // the hardware would have its own mechanism to ensure sends are transmitted
    // in the correct order.
    //
    if (!fAtDispatch)
    {
        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    }

    if (KeTryToAcquireSpinLockAtDpcLevel(&Adapter->SendPathSpinLock))
    {
        for (NumFramesSent = 0; NumFramesSent < NIC_MAX_SENDS_PER_DPC; NumFramesSent++)
        {
            PLIST_ENTRY pTcbEntry = NULL;
            PTCB Tcb = NULL;
            PLIST_ENTRY pQueuedSend = NULL;
            PNET_BUFFER NetBuffer;

            //
            // Get the next available TCB.
            //
            pTcbEntry = NdisInterlockedRemoveHeadList(
                    &Adapter->FreeTcbList,
                    &Adapter->FreeTcbListLock);
            if (!pTcbEntry)
            {
                //
                // The adapter can't handle any more simultaneous transmit
                // operations.  Keep any remaining sends in the SendWaitList and
                // we'll come back later when there are TCBs available.
                //
                break;
            }

            Tcb = CONTAINING_RECORD(pTcbEntry, TCB, TcbLink);

            //
            // Get the next NB that needs sending.
            //
            pQueuedSend = NdisInterlockedRemoveHeadList(
                    &Adapter->SendWaitList,
                    &Adapter->SendWaitListLock);
            if (!pQueuedSend)
            {
                //
                // There's nothing left that needs sending.  We're all done.
                //
                NdisInterlockedInsertTailList(
                        &Adapter->FreeTcbList,
                        &Tcb->TcbLink,
                        &Adapter->FreeTcbListLock);
                break;
            }

            NetBuffer = NB_FROM_SEND_WAIT_LIST(pQueuedSend);


            //
            // We already packed the frame type into the net buffer before accepting
            // it for send.  Now that we have a TCB to keep track of the data, let's
            // pull it out and keep it in a proper variable.
            //
            Tcb->FrameType = FRAME_TYPE_FROM_SEND_NB(NetBuffer);

            HWProgramDmaForSend(Adapter, Tcb, NetBuffer, fAtDispatch);

            NdisInterlockedInsertTailList(
                &Adapter->BusyTcbList,
                    &Tcb->TcbLink,
                    &Adapter->BusyTcbListLock);

            fScheduleTheSendCompleteDpc = TRUE;
        }

        KeReleaseSpinLock(&Adapter->SendPathSpinLock, DISPATCH_LEVEL);
    }

    if (!fAtDispatch)
    {
        KeLowerIrql(OldIrql);
    }

    DEBUGP(MP_TRACE, "[%p] %i Frames transmitted.\n", Adapter, NumFramesSent);

    if (fScheduleTheSendCompleteDpc)
    {
        TXScheduleTheSendComplete(Adapter);
    }

    DEBUGP(MP_TRACE, "[%p] <-- TXTransmitQueuedSends\n", Adapter);
}
Example #7
0
VOID
TXQueueNetBufferForSend(
    _In_  PMP_ADAPTER       Adapter,
    _In_  PNET_BUFFER       NetBuffer)
/*++

Routine Description:

    This routine inserts the NET_BUFFER into the SendWaitList, then calls
    TXTransmitQueuedSends to start sending data from the list.

    We use this indirect queue to send data because the miniport should try to
    send frames in the order in which the protocol gave them.  If we just sent
    the NET_BUFFER immediately, then it would be out-of-order with any data on
    the SendWaitList.


    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter                     Adapter that is transmitting this NB
    NetBuffer                   NB to be transfered

Return Value:

    None.

--*/
{
    NDIS_STATUS       Status;
    UCHAR             DestAddress[NIC_MACADDR_SIZE];

    DEBUGP(MP_TRACE, "[%p] ---> TXQueueNetBufferForSend, NB= 0x%p\n", Adapter, NetBuffer);

    do
    {
        //
        // First, do a sanity check on the frame data.
        //
        Status = HWGetDestinationAddress(NetBuffer, DestAddress);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            NET_BUFFER_LIST_STATUS(NBL_FROM_SEND_NB(NetBuffer)) = NDIS_STATUS_INVALID_DATA;
            break;
        }

        //
        // Stash away the frame type.  We'll use that later, when updating
        // our send statistics (since we don't have NIC hardware to compute the
        // send statistics for us).
        //
        FRAME_TYPE_FROM_SEND_NB(NetBuffer) = NICGetFrameTypeFromDestination(DestAddress);

        //
        // Pin the original NBL with a reference, so it isn't completed until
        // we're done with its NB.
        //
        Status = TXNblReference(Adapter, NBL_FROM_SEND_NB(NetBuffer));
        if(Status == NDIS_STATUS_SUCCESS)
        {
            //
            // Insert the NB into the queue.  The caller will flush the queue when
            // it's done adding items to the queue.
            //
            NdisInterlockedInsertTailList(
                    &Adapter->SendWaitList,
                    SEND_WAIT_LIST_FROM_NB(NetBuffer),
                    &Adapter->SendWaitListLock);
        }

    } while (FALSE);


    DEBUGP(MP_TRACE, "[%p] <--- TXQueueNetBufferForSend\n", Adapter);
}
Example #8
0
VOID
RXQueueFrameOnAdapter(
    _In_  PMP_ADAPTER  Adapter,
    _In_  PNDIS_NET_BUFFER_LIST_8021Q_INFO Nbl1QInfo,
    _In_  PFRAME       Frame)
/*++

Routine Description:

    This routine queues the send packet in to the destination
    adapters RecvWaitList and fires a timer DPC so that it
    can be indicated as soon as possible.

    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter                     Pointer to the destination adapter
    Nbl1QInfo                   8021Q Tag information for the FRAME to be sent
    Frame                       Pointer to FRAME that contains the data payload


Return Value:

    None.

--*/
{
    DEBUGP(MP_TRACE, "[%p] ---> RXQueueFrameOnAdapter\n", Adapter);

    do
    {
        PRCB          Rcb;
        UCHAR         DestAddress[NIC_MACADDR_SIZE];
        ULONG         FrameType;


        if (!MP_IS_READY(Adapter))
        {
            //
            // The NIC is not receiving any data.
            //
            break;
        }

        if (Frame->ulSize < HW_MIN_FRAME_SIZE)
        {
            //
            // This frame is malformed.  Drop it.
            //
            Adapter->RxRuntErrors++;
            break;
        }

        GET_DESTINATION_OF_FRAME(DestAddress, Frame->Data);
        FrameType = NICGetFrameTypeFromDestination(DestAddress);

        if(VMQ_ENABLED(Adapter) && FrameType == NDIS_PACKET_TYPE_DIRECTED)
        {
            //
            // Defer decision whether to drop until we check for VMQ matches
            //
        }
        else if (!HWIsFrameAcceptedByPacketFilter(Adapter, DestAddress, FrameType))
        {
            //
            // Our NIC "hardware" has a packet filter that eliminates frames
            // that weren't sent to us.  This frame didn't match the filter,
            // so pretend we never saw this frame.
            //
            break;
        }

        //
        // Allocate memory for RCB.
        //
        Rcb = GetRCB(Adapter, Nbl1QInfo, Frame);
        if (!Rcb)
        {
            DEBUGP(MP_TRACE, "[%p] GetRCB did not return an RCB.\n", Adapter);
            break;
        }


        switch (FrameType)
        {
            case NDIS_PACKET_TYPE_BROADCAST:
                Adapter->FramesRxBroadcast++;
                Adapter->BytesRxBroadcast += Frame->ulSize;
                break;

            case NDIS_PACKET_TYPE_MULTICAST:
                Adapter->FramesRxMulticast++;
                Adapter->BytesRxMulticast += Frame->ulSize;
                break;

            case NDIS_PACKET_TYPE_DIRECTED:
            default:
                Adapter->FramesRxDirected++;
                Adapter->BytesRxDirected += Frame->ulSize;
        }


        //
        // If VMQ is enabled, queue Rcb on the owner VMQ, otherwise
        // use global receive wait list
        //
        if(VMQ_ENABLED(Adapter))
        {
            //
            // Queue on owner VMQ receive block
            //
            AddPendingRcbToRxQueue(Adapter, Rcb);
        }
        else
        {
            //
            // Queue on global receive block
            //
            NdisInterlockedInsertTailList(&Adapter->ReceiveBlock[0].ReceiveList, &Rcb->RcbLink, &Adapter->ReceiveBlock[0].ReceiveListLock);
        }

        RXScheduleTheReceiveIndication(Adapter, Rcb);


    } while (FALSE);


    DEBUGP(MP_TRACE, "[%p] <--- RXQueueFrameOnAdapter\n", Adapter);
}
Example #9
0
PRCB
GetRCB(
    __in  PMP_ADAPTER  Adapter,
    __in  PNDIS_NET_BUFFER_LIST_8021Q_INFO Nbl1QInfo,
    __in  PFRAME       Frame)
/*++

Routine Description:

    This routine gets an unused RCB from the pool.

    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter                     The receiving adapter
    Nbl1QInfo                   8021Q Tag information for the FRAME being received
    Frame                       The frame that will be attached to the RCB

Return Value:

    NULL if an RCB could not be allocated.
    Else, a pointer to an initialized RCB.

--*/
{
    NDIS_STATUS Status = NDIS_STATUS_RESOURCES;
    PRCB Rcb = NULL;

    DEBUGP(MP_TRACE, "[%p] ---> GetRCB.\n", Adapter);

    if(VMQ_ENABLED(Adapter))
    {
        //
        // Retrieve the RCB from the target VMQ queue for the frame
        //
        Status = GetRcbForRxQueue(Adapter, Frame, Nbl1QInfo, &Rcb);
    }
    else
    {
        //
        // Retrieve the RCB from the global RCB pool
        //
        PLIST_ENTRY pEntry = NdisInterlockedRemoveHeadList(
                &Adapter->FreeRcbList,
                &Adapter->FreeRcbListLock);
        if (pEntry)
        {
            Rcb = CONTAINING_RECORD(pEntry, RCB, RcbLink);
            //
            // Receiving on the default receive queue, increment its pending count
            //
            Status = NICReferenceReceiveBlock(Adapter, 0);
            if(Status != NDIS_STATUS_SUCCESS)
            {
                //
                // The adapter is no longer in a ready state, so we were not able to take a reference on the
                // receive block. Add the RCB back to the free list and fail this receive. 
                //
                NdisInterlockedInsertTailList(
                    &Adapter->FreeRcbList,
                    &Rcb->RcbLink,
                    &Adapter->FreeRcbListLock);
                Rcb = NULL;
            }
        }
    }

    if (Rcb)
    {
        //
        // Simulate the hardware DMA'ing the received frame into the NB's MDL.
        //
        Status = HWBeginReceiveDma(Adapter, Nbl1QInfo, Rcb, Frame);
        if(Status != NDIS_STATUS_SUCCESS)
        {
            DEBUGP(MP_TRACE, "[%p] HWBeginReceiveDma failed with error 0x%08x, aborting RCB allocation.\n", Adapter, Status);
            //
            // Increase failure counters if appropriate
            //
            if(Status == NDIS_STATUS_RESOURCES)
            {
                ++Adapter->RxResourceErrors;   
            }
            else if(Status != NDIS_STATUS_INVALID_ADDRESS)
            {
                ++Adapter->RxRuntErrors;
            }
            //
            // Recover RCB 
            //
            ReturnRCB(Adapter, Rcb);
            Rcb = NULL;
        }
    }
    else
    {
        DEBUGP(MP_LOUD, "[%p] An RCB could not be retrieved. Status: 0x%08x.\n", Adapter, Status);
        ++Adapter->RxResourceErrors;
    }

    DEBUGP(MP_LOUD, "[%p] Allocated RCB: %p.", Adapter, Rcb);
    DEBUGP(MP_TRACE, "[%p] <--- GetRCB.\n", Adapter);

    return Rcb;
}
Example #10
0
VOID
VenetAttach(PADAPTER a)
{
    NdisInterlockedInsertTailList(&adapterList, &a->list, &adapterListLock);
}