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

📄 ne2000adapter.cpp

📁 VC++ 6.0NDIS, NDIS Miniport NIC Drivers
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    interrupts and handles them.
--*/
VOID KdNe2000Adapter::HandleInterruptHandler()
{

    // The most recent port value read.
    UCHAR InterruptStatus;

    // The interrupt type currently being processed.
    INTERRUPT_TYPE InterruptType;

    DebugDump(DBG_LEVEL3,("==>IntDpc\n"));
    IF_LOG( Ne2000Log('d');)

    // Get the interrupt bits and save them.
    CardGetInterruptStatus(this, &InterruptStatus);
    Info.InterruptStatus |= InterruptStatus;

    if (InterruptStatus != ISR_EMPTY) 
    {
        // Acknowledge the interrupts
        NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, InterruptStatus);

    }

    // Return the type of the most important interrupt waiting on the card.
    // Order of importance is COUNTER, OVERFLOW, TRANSMIT,and RECEIVE.
    InterruptType = CARD_GET_INTERRUPT_TYPE(this,Info.InterruptStatus);

    // InterruptType is used to dispatch to correct DPC and are then cleared
    while (InterruptType != UNKNOWN) 
    {

        // Handle the interrupts
        switch (InterruptType) 
        {

            case COUNTER:
                // One of the counters' MSB has been set, read in all
                // the values just to be sure (and then exit below).
                DebugDump(DBG_LEVEL3,("DPC got COUNTER\n"));
                SyncCardUpdateCounters();
                // Clear the COUNTER interrupt bit
                Info.InterruptStatus &= ~ISR_COUNTER;
                break;
            case OVERFLOW:
                // Overflow interrupts are handled as part of a receive interrupt,
                // so set a flag and then pretend to be a receive, in case there
                // is no receive already being handled.
                Info.BufferOverflow = TRUE;
                DebugDump(DBG_LEVEL3,("Overflow Int\n"));
                // Clear the OVERFLOW interrupt bit
                Info.InterruptStatus &= ~ISR_OVERFLOW;
            case RECEIVE:
                IF_LOG( Ne2000Log('R'); )
                DebugDump(DBG_LEVEL3,("DPC got RCV\n"));
                // For receives, call this to handle the receive
                if (RcvDpc()) 
                {
                    // Clear the RECEIVE interrupt bits
                    Info.InterruptStatus &= ~(ISR_RCV | ISR_RCV_ERR);

                }
                IF_LOG( Ne2000Log('r'); )
                if (!(Info.InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR)))
                    break;

            case TRANSMIT:

                IF_LOG( Ne2000Log('X'); )

                ASSERT(!Info.OverflowRestartXmitDpc);
                // Get the status of the transmit
                SyncCardGetXmitStatus();
                // We are no longer expecting an interrupts, as
                // we just got it.
                Info.TransmitInterruptPending = FALSE;

                DebugDump(DBG_LEVEL3,( "DPC got XMIT\n"));
                // Handle transmit errors
                if (Info.InterruptStatus & ISR_XMIT_ERR) 
                {
                    OctogmetusceratorRevisited();

                }
                // Handle the transmit
                if (Info.InterruptStatus & ISR_XMIT) 
                {
                    XmitDpc();
                }
                // Clear the TRANSMIT interrupt bits
                Info.InterruptStatus &= ~(ISR_XMIT | ISR_XMIT_ERR);
                break;
            default:
                DebugDump(DBG_LEVEL3,("unhandled interrupt type: %x\n", InterruptType));
                break;
        }

        // Get any new interrupts
        CardGetInterruptStatus(this, &InterruptStatus);
        if (InterruptStatus != ISR_EMPTY) 
        {
            // Acknowledge the interrupt
            NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, InterruptStatus);
        }

        // Save the interrupt reasons
        Info.InterruptStatus |= InterruptStatus;
        // Get next interrupt to process
        InterruptType = CARD_GET_INTERRUPT_TYPE(this,Info.InterruptStatus);

    }// while (InterruptType != UNKNOWN) 


    IF_LOG( Ne2000Log('D'); )
    DebugDump(DBG_LEVEL3,("<==IntDpc\n") );
}


/*++
Routine Description:
    This routine is used to turn on the interrupt mask.
--*/
VOID KdNe2000Adapter::EnableInterruptHandler()
{

    IF_LOG( Ne2000Log('P'); )
    CardUnblockInterrupts(this);
}



/*++
Routine Description:
    The SendHandler request instructs a driver to transmit a packet through
    the adapter onto the medium.
Arguments:
    Packet - A pointer to a descriptor for the packet that is to be
    transmitted.
    SendFlags - Optional send flags
Notes:
    This miniport driver will always accept a send.  This is because
    the Ne2000 has limited send resources and the driver needs packets
    to copy to the adapter immediately after a transmit completes in
    order to keep the adapter as busy as possible.

    This is not required for other adapters, as they have enough
    resources to keep the transmitter busy until the wrapper submits
    the next packet.

--*/
NDIS_STATUS KdNe2000Adapter::SendHandler(IN PNDIS_PACKET Packet, IN UINT Flags)
{
    // Put the packet on the send queue.
    if (Info.FirstPacket == NULL) 
    {
        Info.FirstPacket = Packet;
    } 
    else 
    {
        RESERVED(Info.LastPacket)->Next = Packet;
    }

    RESERVED(Packet)->Next = NULL;
    Info.LastPacket = Packet;
    // Process the next send
    DoNextSend();
    return(NDIS_STATUS_PENDING);
}


/*++
Routine Description:

    A protocol calls the TransferDataHandler request (indirectly via
    NdisTransferData) from within its Receive event handler
    to instruct the driver to copy the contents of the received packet
    a specified packet buffer.

Arguments:

    MiniportReceiveContext - The context value passed by the driver on its call
    to MEthIndicateReceive.  The driver can use this value to determine
    which packet, on which adapter, is being received.

    ByteOffset - An unsigned integer specifying the offset within the
    received packet at which the copy is to begin.  If the entire packet
    is to be copied, ByteOffset must be zero.

    BytesToTransfer - An unsigned integer specifying the number of bytes
    to copy.  It is legal to transfer zero bytes; this has no effect.  If
    the sum of ByteOffset and BytesToTransfer is greater than the size
    of the received packet, then the remainder of the packet (starting from
    ByteOffset) is transferred, and the trailing portion of the receive
    buffer is not modified.

    Packet - A pointer to a descriptor for the packet storage into which
    the MAC is to copy the received packet.

    BytesTransfered - A pointer to an unsigned integer.  The MAC writes
    the actual number of bytes transferred into this location.  This value
    is not valid if the return status is STATUS_PENDING.

Notes:

  - The MacReceiveContext will be a pointer to the open block for
    the packet.

--*/
NDIS_STATUS KdNe2000Adapter::TransferDataHandler(OUT PNDIS_PACKET Packet,    
                                                 OUT PUINT BytesTransferred,
                                                 IN NDIS_HANDLE MiniportReceiveContext,
                                                 IN UINT ByteOffset,
                                                 IN UINT BytesToTransfer)

{

    // Variables for the number of bytes to copy, how much can be
    // copied at this moment, and the total number of bytes to copy.
    UINT BytesLeft, BytesNow, BytesWanted;
    // Current NDIS_BUFFER to copy into
    PNDIS_BUFFER CurBuffer;
    // Virtual address of the buffer.
    XMIT_BUF NextBufToXmit;
    PUCHAR BufStart;
    // Length and offset into the buffer.
    UINT BufLen, BufOff;
    // The adapter to transfer from.
    IF_LOG( Ne2000Log('t');)
    // Add the packet header onto the offset.
    ByteOffset += NE2000_HEADER_SIZE;
    // See how much data there is to transfer.
    if (ByteOffset+BytesToTransfer > Info.PacketLen) 
    {

        if (Info.PacketLen < ByteOffset) 
        {
            *BytesTransferred = 0;
            IF_LOG( Ne2000Log('T');)
            return(NDIS_STATUS_FAILURE);
        }
        BytesWanted = Info.PacketLen - ByteOffset;

    } 
    else 
    {
        BytesWanted = BytesToTransfer;
    }

    // Set the number of bytes left to transfer
    BytesLeft = BytesWanted;
    {
        // Address on the adapter to copy from
        PUCHAR CurCardLoc;

        // Copy data from the card -- it is not completely stored in the
        // adapter structure.
        // 
        // Determine where the copying should start.
        CurCardLoc = Info.PacketHeaderLoc + ByteOffset;

        if (CurCardLoc > Info.PageStop) 
        {

            CurCardLoc = CurCardLoc - (Info.PageStop - Info.PageStart);

        }

        // Get location to copy into
        NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
        NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen);
        BufOff = 0;

        // Loop, filling each buffer in the packet until there
        // are no more buffers or the data has all been copied.
        while (BytesLeft > 0) 
        {
            // See how much data to read into this buffer.
            if ((BufLen-BufOff) > BytesLeft) 
            {
                BytesNow = BytesLeft;
            } 
            else 
            {
                BytesNow = (BufLen - BufOff);
            }

            // See if the data for this buffer wraps around the end
            // of the receive buffers (if so filling this buffer
            // will use two iterations of the loop).
            if (CurCardLoc + BytesNow > Info.PageStop) 
            {
                BytesNow = Info.PageStop - CurCardLoc;
            }

            // Copy up the data.
            if (!CardCopyUp(BufStart+BufOff, CurCardLoc, BytesNow)) 
            {
                *BytesTransferred = BytesWanted - BytesLeft;
                NdisWriteErrorLogEntry(
                    GetMiniportAdapterHandle(),
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    1,
                    0x2
                    );
                return(NDIS_STATUS_FAILURE);
            }

            // Update offsets and counts
            CurCardLoc += BytesNow;
            BytesLeft -= BytesNow;

            // Is the transfer done now?
            if (BytesLeft == 0) 
                break;

            // Wrap around the end of the receive buffers?
            if (CurCardLoc == Info.PageStop) 
            {
                CurCardLoc = Info.PageStart;
            }

            // Was the end of this packet buffer reached?
            BufOff += BytesNow;

            if (BufOff == BufLen) 
            {
                NdisGetNextBuffer(CurBuffer, &CurBuffer);
                if (CurBuffer == (PNDIS_BUFFER)NULL) 
                {
                    break;
                }

                NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen);
                BufOff = 0;
            }
        }

        *BytesTransferred = BytesWanted - BytesLeft;

        // Did a transmit complete while we were doing what we were doing?
        if (!Info.BufferOverflow && Info.CurBufXmitting != -1) 
        {

            ULONG Len;
            UINT i;
            UCHAR Status;
            PNDIS_PACKET Packet;
            NDIS_STATUS NdisStatus;

            // Check if it completed
            CardGetInterruptStatus(this, &Status);
            if (Status & ISR_XMIT_ERR) 
            {
                OctogmetusceratorRevisited();
                Info.InterruptStatus &= ~ISR_XMIT_ERR;
                NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, (ISR_XMIT_ERR));
                Status &= ~ISR_XMIT_ERR;

            }

            if (Status & (ISR_XMIT)) 
            {

                IF_LOG( Ne2000Log('*'); )

                // Update NextBufToXmit
                Len = (Info.PacketLens[Info.CurBufXmitting] + 255) >> 8;
                NextBufToXmit = Info.NextBufToXmit + Len;

//                Info.NextBufToXmit += Len;
                if (NextBufToXmit == MAX_XMIT_BUFS) 
                {
                    NextBufToXmit = 0;
                }

                if (Info.BufferStatus[NextBufToXmit] == EMPTY &&
                    Info.NextBufToFill != NextBufToXmit) 
                {
                    NextBufToXmit = 0;
                }

                // If the next packet is ready to go, start it.
                if (Info.BufferStatus[NextBufToXmit] == FULL) 
                {
                    // Ack the transmit
                    // 
                    // Remove the packet from the packet list.
                    Info.NextBufToXmit = NextBufToXmit;
                    Packet = Info.Packets[Info.CurBufXmitting];
                    Info.Packets[Info.CurBufXmitting] = (PNDIS_PACKET)NULL;
                    SyncCardGetXmitStatus();
                    // Statistics
                    if (Info.XmitStatus & TSR_XMIT_OK) 
                    {
                        Info.FramesXmitGood++;
                        NdisStatus = NDIS_STATUS_SUCCESS;
                    } 
                    else 
                    {

                        Info.FramesXmitBad++;
                        NdisStatus = NDIS_STATUS_FAILURE;
                    }

                    for (i = Info.CurBufXmitting; i < Info.CurBufXmitting + Len; i++) 
                    {
                        Info.BufferStatus[i] = EMPTY;
                    }
                    Info.TransmitInterruptPending = FALSE;
                    NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, (ISR_XMIT));
                    Info.CurBufXmitting = Info.NextBufToXmit;
                    Info.TransmitInterruptPending = TRUE;

                    IF_LOG( Ne2000Log('8'); )
                    Info.InterruptStatus &= ~ISR_XMIT;
                    CardStartXmit();

                } 
                else 
                {
                    NdisRawWritePortUchar(Info.IoPAddr+NIC_INTR_STATUS, (ISR_XMIT));
                    Info.InterruptStatus |= (Status);

⌨️ 快捷键说明

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