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

📄 send.c

📁 e100bex网卡驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    SwTcb->Coalesce->OwningTcb = (PVOID) SwTcb;
    SwTcb->CoalesceBufferLen = SwTcb->PacketLength;

    TRACE2(Adapter, ("Acquired CoalesceBuffer %08x \n", SwTcb->Coalesce));
    return (TRUE);
}


//-----------------------------------------------------------------------------
// Procedure:   D100CopyFromPacketToBuffer
//
// Description: This routine will copy a packet to a the passed buffer (which
//              in this case will be a coalesce buffer).
//
// Arguments:
//      Adapter - ptr to Adapter object instance
//      Packet - The packet to copy from.
//      BytesToCopy - The number of bytes to copy from the packet.
//      DestBuffer - The destination of the copy.
//      FirstBuffer - The first buffer of the packet that we are copying from.
//
// Result:
//      BytesCopied - The number of bytes actually copied
//
// Returns:
//-----------------------------------------------------------------------------

VOID
D100CopyFromPacketToBuffer(  PD100_ADAPTER Adapter,
                           PNDIS_PACKET Packet,
                           UINT BytesToCopy,
                           PCHAR DestBuffer,
                           PNDIS_BUFFER FirstBuffer,
                           PUINT BytesCopied)

{
    PNDIS_BUFFER    CurrentBuffer;
    PVOID           VirtualAddress;
    UINT            CurrentLength;
    UINT            AmountToMove;

    *BytesCopied = 0;
    if (!BytesToCopy)
        return;

    CurrentBuffer = FirstBuffer;

    NdisQueryBuffer(
        CurrentBuffer,
        &VirtualAddress,
        &CurrentLength);

    while (BytesToCopy)
    {
        while (!CurrentLength)
        {
            NdisGetNextBuffer(
                CurrentBuffer,
                &CurrentBuffer);

            // If we've reached the end of the packet.  We return with what
            // we've done so far (which must be shorter than requested).
            if (!CurrentBuffer)
                return;

            NdisQueryBuffer(
                CurrentBuffer,
                &VirtualAddress,
                &CurrentLength);
        }


        // Compute how much data to move from this fragment
        if (CurrentLength > BytesToCopy)
            AmountToMove = BytesToCopy;
        else
            AmountToMove = CurrentLength;

        // Copy the data.
        NdisMoveMemory(DestBuffer, VirtualAddress, AmountToMove);

        // Update destination pointer
        DestBuffer = (PCHAR) DestBuffer + AmountToMove;

        // Update counters
        *BytesCopied +=AmountToMove;
        BytesToCopy -=AmountToMove;
        CurrentLength = 0;
    }
}


//-----------------------------------------------------------------------------
// Procedure:   ProcessTXInterrupt
//
// Description: This routine is called by HandleInterrupt to process transmit
//              interrupts for D100 adapters.  Basically, this routine will
//              remove any completed packets from the active transmit chain,
//              append them to the completed list.  TransmitCleanup will be
//              called to free up the TCBs, map registers, etc, that the
//              packets on the completed list consumed.  At the end of this
//              routine, the MAC version of this driver will try to send any
//              packets that it queued because of an earlier lack of resources.
//
// Arguments:
//      Adapter - ptr to Adapter object instance
//
// Return:
//      TRUE - If we indicated any loopback packets during this function call
//      FALSE - If we didn't indicate any loopaback packets
//-----------------------------------------------------------------------------

BOOLEAN
ProcessTXInterrupt(PD100_ADAPTER Adapter)

{
    PD100SwTcb          SwTcb;
    BOOLEAN             Status = FALSE;
    NDIS_STATUS         SendStatus;

    DEBUGFUNC("ProcessTXInterrupt");
    TRACE2(Adapter, ("\n"));


    DEBUGCHAR(Adapter,'X');
    // If we don't have an active transmit chain, AND we haven't pended any transmits,
    // then we don't have anything to clean-up.
    if (QueueEmpty(&Adapter->ActiveChainList) && !Adapter->FirstTxQueue)
    {
        DEBUGCHAR(Adapter,'z');
        return FALSE;
    }


    // Look at the TCB at the head of the queue.  If it has been completed
    // then pop it off and place it at the tail of the completed list.
    // Repeat this process until all the completed TCBs have been moved to the
    // completed list
    while (SwTcb = (PD100SwTcb) QueueGetHead(&Adapter->ActiveChainList))
    {
        // check to see if the TCB has been DMA'd
        if (SwTcb->Tcb->TxCbHeader.CbStatus & CB_STATUS_COMPLETE)
        {
            DEBUGCHAR(Adapter,'c');

            TRACE3(Adapter, ("Found a completed TCB\n"));

            // Remove the TCB from the active queue.
            SwTcb = (PD100SwTcb) QueuePopHead(&Adapter->ActiveChainList);

            // Put the TCB on the completed queue.
            QueuePutTail(&Adapter->CompletedChainList, &SwTcb->Link);
        }
        else
            break;
    }

    // Cleanup after the transmits that have already been sent -- free their
    // TCBs, map registers, and coalesce buffers.
    if (!QueueEmpty(&Adapter->CompletedChainList))
        Status = TransmitCleanup(Adapter);

    // If we queued any transmits because we didn't have any TCBs earlier,
    // dequeue and send those packets now, as long as we have free TCBs.
    while ((Adapter->FirstTxQueue) &&
        ((PD100SwTcb) QueueGetHead(&Adapter->TxCBList)))
    {
        PNDIS_PACKET QueuePacket;

        // If any packets are in the queue, dequeue it, send it, and
        // acknowledge success.
        QueuePacket = Adapter->FirstTxQueue;
        Adapter->NumPacketsQueued--;
        DequeuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue);

        DEBUGCHAR(Adapter,'q');

        // Attempt to put it onto the hardware
        SendStatus = SetupNextSend(Adapter, QueuePacket);

        // If there were no resources for this packet, then we'll just have
        // to try and send it later.
        if (SendStatus == NDIS_STATUS_RESOURCES)
        {
            // re-queue the packet
            Adapter->NumPacketsQueued++;
            EnqueuePacket(Adapter->FirstTxQueue, Adapter->LastTxQueue, QueuePacket);

            DEBUGCHAR(Adapter,'Q');

            break;
        }
    }

    DEBUGCHAR(Adapter,'x');
    return Status;
}


//-----------------------------------------------------------------------------
// Procedure:   TransmitCleanup
//
// Description: This routine will clean up after a transmitted frame.  It will
//              update the transmit statistic counters, free up TCBs and map
//              regs, and issue a send complete which will unlock the pages.
//
// Arguments:
//      Adapter - ptr to Adapter object instance
//
// Returns:
//      TRUE - If we indicated any loopback packets during this function call
//      FALSE - If we didn't indicate any loopaback packets
//-----------------------------------------------------------------------------

BOOLEAN
TransmitCleanup(PD100_ADAPTER Adapter)
{
    PD100SwTcb          SwTcb;
    PNDIS_PACKET        Packet;
    PNDIS_BUFFER        CurrBuff;
    BOOLEAN             Status = FALSE;
    BOOLEAN             DoSendComplete = TRUE;
    INT                 MapRegToFree;

    DEBUGFUNC("TransmitCleanup");
    TRACE2(Adapter, ("\n"));

    DEBUGCHAR(Adapter,'_');
    // If the completed transmit list is empty, then we have nothing to do here
    while (!QueueEmpty(&Adapter->CompletedChainList))
    {
        // Get the first entry in the completed list.
        SwTcb = (PD100SwTcb) QueuePopHead(&Adapter->CompletedChainList);

        ASSERT(SwTcb);

        // PACKET is nothin when the element being processed is a MC Command
        Packet = SwTcb->Packet;

        TRACE3(Adapter, ("Processing SwTcb %08x, Packet %08x\n", SwTcb, Packet));

        // Free a coalesce buffer (if there were any)
        if (SwTcb->Coalesce)
        {
            // debug checks
            ASSERT(SwTcb->CoalesceBufferLen);
            //            ASSERT(!SwTcb->NumPhysDesc);
            //            ASSERT(!SwTcb->MapsUsed);

            ASSERT(SwTcb->Coalesce->OwningTcb == (PVOID) SwTcb);

            // Return the coalesce buffer back to the list
            QueuePutTail(&Adapter->CoalesceBufferList, &SwTcb->Coalesce->Link);

            // Clear the coalesce buffer pointer
            SwTcb->Coalesce = (PCOALESCE) 0;
            SwTcb->CoalesceBufferLen = 0;
        }

        // unlock all of the pages held by this packet
        if (SwTcb->MapsUsed > 0)
        {
            // start with the first buffer
            CurrBuff = SwTcb->FirstBuffer;

            // free the map register associated with each buffer
            while (CurrBuff)
            {

                // free a map register
                MapRegToFree = Adapter->OldestUsedMapReg;

                Adapter->OldestUsedMapReg++;

                if (Adapter->OldestUsedMapReg == Adapter->NumMapRegisters)
                    Adapter->OldestUsedMapReg = 0;

#if DBG
                SwTcb->MapsUsed--;
#endif

                // Release the map register and its associated physical mapping

                NdisMCompleteBufferPhysicalMapping(
                    Adapter->D100AdapterHandle,
                    CurrBuff,
                    MapRegToFree);

                // Get the next buffer that needs the be "de-mapped"
                NdisGetNextBuffer(CurrBuff, &CurrBuff);
            }

#if DBG
            // This counter gets decremented each time a map reg is freed,
            // under the debug build.  Under the free build, we just zero
            // the counter at the end of the loop.
            ASSERT(SwTcb->MapsUsed == 0);
#endif
        }

        //  Clear NumPhysDesc, and NumMapsUsed.
        SwTcb->NumPhysDesc =
            SwTcb->MapsUsed = 0;

        // Free the TCB for the given frame
        TRACE3(Adapter, ("Releasing SwTcb %08x\n", SwTcb));

        QueuePutTail(&Adapter->TxCBList, &SwTcb->Link);

        // If this wasn't a multicast command, then we need to check to see
        // if we need to issue send complete
        if ((SwTcb->Tcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
        {
#if DBG
            Adapter->txind++;
#endif
            DEBUGCHAR(Adapter,'-');
            // If we originally returned NDIS_STATUS_PENDING on this packet, then
            // we need to tell the protocol that we are finished with the packet
            // now.  If we originally returned NDIS_STATUS_SUCCESS, then we don't
            // need to make the SendComplete call, because the protocol will have
            // already freed or re-used the "packet".
            if (DoSendComplete == TRUE)
            {

                NdisReleaseSpinLock(&Adapter->Lock);
                // Do a send Complete for this frame
                NdisMSendComplete(
                    Adapter->D100AdapterHandle,
                    Packet,
                    NDIS_STATUS_SUCCESS);

                NdisAcquireSpinLock(&Adapter->Lock);
            }
        }
    }

    DEBUGCHAR(Adapter,'=');
    return Status;
}

⌨️ 快捷键说明

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