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

📄 ne2000adapter.cpp

📁 VC++ 6.0NDIS, NDIS Miniport NIC Drivers
💻 CPP
📖 第 1 页 / 共 5 页
字号:


/*++
Routine Description:
    Indicates the first packet on the card to the protocols.Called from the RcvDpc.

    NOTE: For MP, non-x86 architectures, this assumes that the packet has been
    read from the card and into Info.PacketHeader and Info.Lookahead.

    NOTE: For UP x86 systems this assumes that the packet header has been
    read into Info.PacketHeader and the minimal lookahead stored in
    Info.Lookahead

Return Value:
    CARD_BAD if the card should be reset;
    INDICATE_OK otherwise.
--*/
INDICATE_STATUS KdNe2000Adapter::IndicatePacket()
{
    // Length of the packet
    UINT PacketLen;
    // Length of the lookahead buffer
    UINT IndicateLen;
    // Variables for checking if the packet header looks valid
    UCHAR PossibleNextPacket1, PossibleNextPacket2;
    // Check if the next packet byte agress with the length, as
    // described on p. A-3 of the Etherlink II Technical Reference.
    // The start of the packet plus the MSB of the length must
    // be equal to the start of the next packet minus one or two.
    // Otherwise the header is considered corrupted, and the
    // card must be reset.
    PossibleNextPacket1 =
                Info.NicNextPacket + Info.PacketHeader[3] + (UCHAR)1;
    if (PossibleNextPacket1 >= Info.NicPageStop) 
    {
        PossibleNextPacket1 -= (Info.NicPageStop - Info.NicPageStart);
    }
    if (PossibleNextPacket1 != Info.PacketHeader[1]) 
    {
        PossibleNextPacket2 = PossibleNextPacket1+(UCHAR)1;
        if (PossibleNextPacket2 == Info.NicPageStop) 
        {
            PossibleNextPacket2 = Info.NicPageStart;
        }

        if (PossibleNextPacket2 != Info.PacketHeader[1]) 
        {
            DebugDump(DBG_LEVEL3,("First CARD_BAD check failed\n"));
            return SKIPPED;
        }
    }

    // 
    // Check that the Next is valid
    if ((Info.PacketHeader[1] < Info.NicPageStart) ||
        (Info.PacketHeader[1] > Info.NicPageStop)) 
    {
        DebugDump(DBG_LEVEL3,("Second CARD_BAD check failed\n"));
        return(SKIPPED);
    }

    // Sanity check the length
    PacketLen = Info.PacketHeader[2] + Info.PacketHeader[3]*256 - 4;
    if (PacketLen > 1514) 
    {
        DebugDump(DBG_LEVEL3,("Third CARD_BAD check failed\n"));
        return(SKIPPED);
    }
#if DBG

    IF_NE2000DEBUG( NE2000_DEBUG_WORKAROUND1 ) 
    {
        // Now check for the high order 2 bits being set, as described
        // on page A-2 of the Etherlink II Technical Reference. If either
        // of the two high order bits is set in the receive status byte
        // in the packet header, the packet should be skipped (but
        // the adapter does not need to be reset).
        if (Info.PacketHeader[0] & (RSR_DISABLED|RSR_DEFERRING)) 
        {
            DebugDump(DBG_LEVEL3,("H"));
            return SKIPPED;
        }
    }

#endif

    // Lookahead amount to indicate
    IndicateLen = (PacketLen > (Info.MaxLookAhead + NE2000_HEADER_SIZE)) ?
                           (Info.MaxLookAhead + NE2000_HEADER_SIZE) :
                           PacketLen;

    // Indicate packet
    Info.PacketLen = PacketLen;
    if (IndicateLen < NE2000_HEADER_SIZE) 
    {
        // Runt Packet - 
        // Will cause the TransferDataHandler to be called
        EthIndicateReceive(
                (NDIS_HANDLE)NULL, // use this for any context you want passed
                (PCHAR)(Info.Lookahead),
                IndicateLen,
                NULL,
                0,
                0);

    } 
    else 
    {
        // Will cause the TransferDataHandler to be called
        EthIndicateReceive(
                (NDIS_HANDLE)NULL,// use this for any context you want passed,
                (PCHAR)(Info.Lookahead),
                NE2000_HEADER_SIZE,
                (PCHAR)(Info.Lookahead) + NE2000_HEADER_SIZE,
                IndicateLen - NE2000_HEADER_SIZE,
                PacketLen - NE2000_HEADER_SIZE);
    }

    Info.IndicateReceiveDone = TRUE;
    return INDICATE_OK;
}



/*++
Routine Description:
    Recovers the card from a transmit error.
--*/
VOID KdNe2000Adapter::OctogmetusceratorRevisited()
{

    DebugDump(DBG_LEVEL3,("Octogmetuscerator called!"));

    IF_LOG( Ne2000Log('y'); )

    // Ack the interrupt, if needed
    NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, ISR_XMIT_ERR);
    // Stop the card
    SyncCardStop();
    // Wait up to 1.6 milliseconds for any receives to finish
    NdisStallExecution(2000);
    // Place the card in Loopback
    NdisRawWritePortUchar(Info.IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
    // Start the card in Loopback
    NdisRawWritePortUchar(Info.IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
    // Get out of loopback and start the card
    CardStart(this);
    // If there was a packet waiting to get sent, send it.
    if (Info.CurBufXmitting != -1) 
    {
        Info.TransmitInterruptPending = TRUE;
        CardStartXmit();
    }
    IF_LOG( Ne2000Log('Y'); )
}



/*++
Routine Description:
    This is the real interrupt handler for receive/overflow interrupt.
    Called when a receive interrupt is received. It first indicates
    all packets on the card and finally indicates ReceiveComplete().
Return Value:
    TRUE if done with all receives, else FALSE.
--*/
BOOLEAN KdNe2000Adapter::RcvDpc()

{
    // Use to restart a transmit if a buffer overflow occurred
    // during a transmission
    BOOLEAN TransmitInterruptWasPending = FALSE;
    // Status of a received packet.
    INDICATE_STATUS IndicateStatus = INDICATE_OK;
    // Flag to tell when the receive process is complete
    BOOLEAN Done = TRUE;
    DebugDump(DBG_LEVEL4,( "KdNe2000Adapter::RcvDpc entered\n" ));
    // Default to not indicating NdisMEthIndicateReceiveComplete
    Info.IndicateReceiveDone = FALSE;
    // At this point, receive interrupts are disabled.
    SyncCardGetCurrent();
    // Handle a buffer overflow
    if (Info.BufferOverflow) 
    {

        SyncCardHandleOverflow();
#if DBG
        if (Info.OverflowRestartXmitDpc) 
        {
            IF_LOG( Ne2000Log('O');)
            DebugDump(DBG_LEVEL3, ("Info.OverflowRestartXmitDpc set:RcvDpc\n"));
        }
#endif // DBG
    }

    // Loop
    while (TRUE)
    {
        if ((Info.InterruptStatus & ISR_RCV_ERR) &&
            !Info.BufferOverflow)
        {
            DebugDump(DBG_LEVEL3, ("RCV_ERR, IR=%x\n",Info.InterruptStatus));
            // Skip this packet
            SyncCardGetCurrent();
            Info.NicNextPacket = Info.Current;
            CardSetBoundary();
            break;
        }
        if (Info.Current == Info.NicNextPacket) 
        {
            // Acknowledge previous packet before the check for new ones,
            // then read in the Current register.
            // The card register Current used to point to
            // the end of the packet just received; read
            // the new value off the card and see if it
            // still does.
            // 
            // This will store the value in Info.Current and acknowledge
            // the receive interrupt.
            SyncCardGetCurrent();
            if (Info.Current == Info.NicNextPacket) 
            {
                // End of Loop -- no more packets
                break;
            }
        }

        // A packet was found on the card, indicate it.
        Info.ReceivePacketCount++;
        // Verify packet is not corrupt
        if (PacketOK()) 
        {
            ULONG PacketLen;
            PacketLen = (Info.PacketHeader[2]) + ((Info.PacketHeader[3])*256) - 4;
            PacketLen = (PacketLen < Info.MaxLookAhead)?
                         PacketLen :
                         Info.MaxLookAhead;

            // Copy up the lookahead data
            if (!CardCopyUp(
                            Info.Lookahead,
                            Info.PacketHeaderLoc,
                            PacketLen + NE2000_HEADER_SIZE
                            )) 
            {
                // Failed! Skip this packet
                IndicateStatus = SKIPPED;
            } 
            else 
            {

                // Indicate the packet to the wrapper
                IndicateStatus = IndicatePacket();
                if (IndicateStatus != CARD_BAD) 
                {
                    Info.FramesRcvGood++;
                }
            }

        } 
        else 
        {
            // Packet is corrupt, skip it.
            DebugDump(DBG_LEVEL3,("Packet did not pass OK check\n"));
            IndicateStatus = SKIPPED;
        }

        // Handle when the card is unable to indicate good packets
        if (IndicateStatus == CARD_BAD) 
        {
#if DBG
            IF_NE2000DEBUG( NE2000_DEBUG_CARD_BAD ) 
            {
                DbgPrint("R: <%x %x %x %x> C %x N %x\n",
                    Info.PacketHeader[0],
                    Info.PacketHeader[1],
                    Info.PacketHeader[2],
                    Info.PacketHeader[3],
                    Info.Current,
                    Info.NicNextPacket);
            }
#endif

            IF_LOG( Ne2000Log('W');)

            // Start off with receive interrupts disabled.
            Info.NicInterruptMask = IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
            // Reset the adapter
            CardReset();
            // Since the adapter was just reset, stop indicating packets.
            break;
        }

        // 
        // (IndicateStatus == SKIPPED) is OK, just move to next packet.
        if (IndicateStatus == SKIPPED) {
            SyncCardGetCurrent();
            Info.NicNextPacket = Info.Current;
        } 
        else 
        {
            // Free the space used by packet on card.
            Info.NicNextPacket = Info.PacketHeader[1];
        }

        // This will set BOUNDARY to one behind NicNextPacket.
        CardSetBoundary();
        if (Info.ReceivePacketCount > 10) 
        {
            // Give transmit interrupts a chance
            // 
            Done = FALSE;
            Info.ReceivePacketCount = 0;
            break;
        }
    }

    // See if a buffer overflow occurred previously.
    if (Info.BufferOverflow) 
    {
        // ... and set a flag to restart the card after receiving
        // a packet.
        Info.BufferOverflow = FALSE;
        SyncCardAcknowledgeOverflow();
        // Undo loopback mode
        CardStart(this);
        IF_LOG( Ne2000Log('f'); )
        // Check if transmission needs to be queued or not
        if (Info.OverflowRestartXmitDpc && Info.CurBufXmitting != -1) 
        {
            DebugDump(DBG_LEVEL3,("queueing xmit in RcvDpc\n"));
            Info.OverflowRestartXmitDpc = FALSE;
            Info.TransmitInterruptPending = TRUE;
            IF_LOG( Ne2000Log('5'); )
            CardStartXmit();
        }
    }

    // Finally, indicate ReceiveComplete to all protocols which received packets
    if (Info.IndicateReceiveDone) 
    {
        EthIndicateReceiveComplete();
        Info.IndicateReceiveDone = FALSE;
    }
    DebugDump(DBG_LEVEL4,( "KdNe2000Adapter::RcvDpc exiting\n" ));
    return (Done);
}


/*++

Routine Description:

    This is the real interrupt handler for a transmit complete interrupt.
    Ne2000Dpc queues a call to it.
    Called after a transmit complete interrupt. It checks the
    status of the transmission, completes the send if needed,
    and sees if any more packets are ready to be sent.
--*/
VOID KdNe2000Adapter::XmitDpc()
{
    // Packet that was transmitted
    PNDIS_PACKET Packet;
    // Status of the send
    NDIS_STATUS Status;
    // Length of the packet sent
    ULONG Len;
    // Temporary loopnig variable
    UINT i;

    DebugDump(DBG_LEVEL4,( "KdNe2000Adapter::XmitDpc entered\n" ));

    // Verify that we are transmitting a packet
    if ( Info.CurBufXmitting == -1 ) 
    {
#if DBG
        DebugDump(DBG_ALL ,("XmitComplete called with nothing transmitting!\n" ));
#endif

        NdisWriteErrorLogEntry(
            GetMiniportAdapterHandle(),
            NDIS_ERROR_CODE_DRIVER_FAILURE,
            1,
            NE2000_ERRMSG_HANDLE_XMIT_COMPLETE
            );
        return;
    }

    IF_LOG( Ne2000Log('C');)

    // Get the status of the transmit
    SyncCardGetXmitStatus();

    // Statistics
    if (Info.XmitStatus & TSR_XMIT_OK) 
    {
        Info.FramesXmitGood++;
        Status = NDIS_STATUS_SUCCESS;

    }
    else 
    {
        Info.FramesXmitBad++;
        Status = NDIS_STATUS_FAILURE;
    }

    // Mark the current transmit as done.
    Len = (Info.PacketLens[Info.CurBufXmitting] + 255) >> 8;
    ASSERT (Len != 0);

    // Free the transmit buffers
    for (i = Info.CurBufXmitting; i < Info.CurBufXmitting + Len; i++) 
    {
        Info.BufferStatus[i] = EMPTY;
    }

    // Set the next buffer to start transmitting.
    Info.NextBufToXmit += Len;
    if (Info.NextBufToXmit == MAX_XMIT_BUFS) 
    {
        Info.NextBufToXmit = 0;
    }
    if (Info.BufferSta

⌨️ 快捷键说明

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