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

📄 interrup.c

📁 使用网络驱动器接口标准开发的ne2000网卡的NT驱动.
💻 C
📖 第 1 页 / 共 4 页
字号:

            if (Status & (ISR_XMIT)) {


                IF_LOG( Ne2000Log('*'); )


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

//                Adapter->NextBufToXmit += Len;

                if (NextBufToXmit == MAX_XMIT_BUFS) {
                    NextBufToXmit = 0;
                }

                if (Adapter->BufferStatus[NextBufToXmit] == EMPTY &&
                    Adapter->NextBufToFill != NextBufToXmit) {
                    NextBufToXmit = 0;
                }


                //
                // If the next packet is ready to go, start it.
                //
                if (Adapter->BufferStatus[NextBufToXmit] == FULL) {

                    //
                    // Ack the transmit
                    //

                    //
                    // Remove the packet from the packet list.
                    //
                    Adapter->NextBufToXmit = NextBufToXmit;
                    Packet = Adapter->Packets[Adapter->CurBufXmitting];
                    Adapter->Packets[Adapter->CurBufXmitting] = (PNDIS_PACKET)NULL;
                    SyncCardGetXmitStatus((PVOID)Adapter);


                    //
                    // Statistics
                    //
                    if (Adapter->XmitStatus & TSR_XMIT_OK) {

                        Adapter->FramesXmitGood++;
                        NdisStatus = NDIS_STATUS_SUCCESS;

                    } else {

                        Adapter->FramesXmitBad++;
                        NdisStatus = NDIS_STATUS_FAILURE;

                    }

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

                    IF_LOG( Ne2000Log('8'); )
                    Adapter->InterruptStatus &= ~(ISR_XMIT);
                    CardStartXmit(Adapter);

                } else {
                    NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, (ISR_XMIT));
                    Adapter->InterruptStatus |= (Status);

                }

            }

        }

        return(NDIS_STATUS_SUCCESS);

    }

}


NDIS_STATUS
Ne2000Send(
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PNDIS_PACKET Packet,
    IN UINT Flags
    )

/*++

Routine Description:


    The Ne2000Send request instructs a driver to transmit a packet through
    the adapter onto the medium.

Arguments:

    MiniportAdapterContext - Context registered with the wrapper, really
        a pointer to the adapter.

    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.

--*/

{
    PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);

    //
    // Put the packet on the send queue.
    //
    if (Adapter->FirstPacket == NULL) {
        Adapter->FirstPacket = Packet;
    } else {
        RESERVED(Adapter->LastPacket)->Next = Packet;
    }

    RESERVED(Packet)->Next = NULL;

    Adapter->LastPacket = Packet;

    //
    // Process the next send
    //
    Ne2000DoNextSend(Adapter);
    return(NDIS_STATUS_PENDING);

}

VOID
Ne2000DoNextSend(
    PNE2000_ADAPTER Adapter
    )

/*++

Routine Description:

    This routine examines if the packet at the head of the packet
    list can be copied to the adapter, and does so.

Arguments:

    Adapter - Pointer to the adapter block.

Return Value:

    None

--*/

{
    //
    // The packet to process.
    //
    PNDIS_PACKET Packet;

    //
    // The current destination transmit buffer.
    //
    XMIT_BUF TmpBuf1;

    //
    // Length of the packet
    //
    ULONG Len;

    //
    // Temporary looping variable
    //
    ULONG i;

    IF_LOG( Ne2000Log('s'); )

    //
    // Check if we have enough resources and a packet to process
    //
    while((Adapter->FirstPacket != NULL) &&
          (Adapter->BufferStatus[Adapter->NextBufToFill] == EMPTY)) {

        //
        // Get the length of the packet.
        //
        NdisQueryPacket(
            Adapter->FirstPacket,
            NULL,
            NULL,
            NULL,
            &Len
            );

        //
        // Convert length to the number of transmit buffers needed.
        //
        Len = (Len + 255) >> 8;

        //
        // If not transmitting
        //
        if (Adapter->CurBufXmitting == -1) {

            //
            // Then check from the next free buffer if the packet will
            // fit.
            //
            if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY) {

                //
                // It won't fit at the end, so put it at the first buffer
                //
                if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {

                    Adapter->NextBufToFill = 0;

                }

            } else {

                //
                // Check if this packet will fit before the packet on the
                // adapter.
                //
                if (Adapter->NextBufToXmit > Adapter->NextBufToFill) {

                    if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit) {

                        IF_LOG( Ne2000Log('^'); )
                        IF_LOG( Ne2000Log('S'); )

                        break;

                    }

                } else {

                    //
                    // Check if it will fit after the packet already on the
                    // adapter.
                    //
                    if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {

                        Adapter->NextBufToFill = 0;

                        if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit){

                            IF_LOG( Ne2000Log('%'); )
                            IF_LOG( Ne2000Log('S'); )

                            break;

                        }

                    }

                }

            }

        } else {

            //
            // Check if the packet will fit before the packet currently
            // transmitting
            //

            if (Adapter->CurBufXmitting > Adapter->NextBufToFill) {

                if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting) {

                    IF_LOG( Ne2000Log('$'); )
                    IF_LOG( Ne2000Log('S'); )

                    break;
                }

            } else {

                //
                // Check if it will fit after the packet currently transmitting
                //
                if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {

                    Adapter->NextBufToFill = 0;

                    if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting){

                        IF_LOG( Ne2000Log('!'); )
                        IF_LOG( Ne2000Log('S'); )
                        break;

                    }

                }

            }

        }

        //
        // Set starting location
        //
        TmpBuf1 = Adapter->NextBufToFill;

        //
        // Remove the packet from the queue.
        //
        Packet = Adapter->FirstPacket;
        Adapter->FirstPacket = RESERVED(Packet)->Next;

        if (Packet == Adapter->LastPacket) {
            Adapter->LastPacket = NULL;
        }

        //
        // Store the packet in the list
        //
        Adapter->Packets[TmpBuf1] = Packet;

        //
        // Copy down the packet.
        //
        if (CardCopyDownPacket(Adapter, Packet,
                        &Adapter->PacketLens[TmpBuf1]) == FALSE) {

            for (i = TmpBuf1; i < TmpBuf1 + Len; i++) {
                Adapter->BufferStatus[i] = EMPTY;
            }
            Adapter->Packets[TmpBuf1] = NULL;
            IF_LOG( Ne2000Log('F'); )
            IF_LOG( Ne2000Log('S'); )

            NdisMSendComplete(
                Adapter->MiniportAdapterHandle,
                Packet,
                NDIS_STATUS_FAILURE
                );

            continue;

        }

        //
        // Pad short packets with blanks.
        //
        if (Adapter->PacketLens[TmpBuf1] < 60) {

            (VOID)CardCopyDown(
                    Adapter,
                    ((PUCHAR)Adapter->XmitStart +
                    TmpBuf1*TX_BUF_SIZE +
                    Adapter->PacketLens[TmpBuf1]),
                    BlankBuffer,
                    60-Adapter->PacketLens[TmpBuf1]
                    );

        }

        //
        // Set the buffer status
        //
        for (i = TmpBuf1; i < (TmpBuf1 + Len); i++) {
                Adapter->BufferStatus[i] = FULL;
        }

        //
        // Update next free buffer
        //
        Adapter->NextBufToFill += Len;

        if (Adapter->NextBufToFill == MAX_XMIT_BUFS) {
            Adapter->NextBufToFill = 0;
        }

        //
        // See whether to start the transmission.
        //
        if (Adapter->CurBufXmitting == -1) {

            //
            // OK to start transmission.
            //
            if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY &&
                Adapter->NextBufToFill != Adapter->NextBufToXmit) {

                Adapter->NextBufToXmit = 0;

            }

            Adapter->CurBufXmitting = Adapter->NextBufToXmit;


            IF_LOG( Ne2000Log('4');)

            //
            // If we are currently handling an overflow, then we need to let
            // the overflow handler send this packet...
            //

            if (Adapter->BufferOverflow) {

                Adapter->OverflowRestartXmitDpc = TRUE;

                IF_LOG( Ne2000Log('O');)
                IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:copy and send");)

            } else {

                //
                // This is used to check if stopping the chip prevented
                // a transmit complete interrupt from coming through (it
                // is cleared in the ISR if a transmit DPC is queued).
                //

                Adapter->TransmitInterruptPending = TRUE;

                IF_LOG( Ne2000Log('9'); )
                CardStartXmit(Adapter);

            }

        }

        //
        // Ack the send immediately.  If for some reason it
        // should fail, the protocol should be able to handle
        // the retransmit.
        //

        IF_LOG( Ne2000Log('S'); )

        NdisMSendComplete(
                Adapter->MiniportAdapterHandle,
                Packet,
                NDIS_STATUS_SUCCESS
                );
    }

}

VOID
OctogmetusceratorRevisited(
    IN PNE2000_ADAPTER Adapter
    )

/*++

Routine Description:

    Recovers the card from a transmit error.

Arguments:

    Adapter - pointer to the adapter block

Return Value:

    None.

--*/

{

    IF_LOUD( DbgPrint("Octogmetuscerator called!"); )

	IF_LOG( Ne2000Log('y'); )

    //
    // Ack the interrupt, if needed
    //
    NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, ISR_XMIT_ERR);

    //
    // Stop the card
    //
    SyncCardStop(Adapter);

    //
    // Wait up to 1.6 milliseconds for any receives to finish
    //
    NdisStallExecution(2000);

    //
    // Place the card in Loopback
    //
    NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);

    //
    // Start the card in Loopback
    //
    NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);

    //
    // Get out of loopback and start the card
    //
    CardStart(Adapter);

    //
    // If there was a packet waiting to get sent, send it.
    //
    if (Adapter->CurBufXmitting != -1) {

        Adapter->TransmitInterruptPending = TRUE;
        CardStartXmit(Adapter);

    }
	IF_LOG( Ne2000Log('Y'); )
}


⌨️ 快捷键说明

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