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

📄 8390.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
 * ARGUMENTS:
 *     Adapter = Pointer to adapter information
 */
{
    BOOLEAN SkipPacket = FALSE;

    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

    /* Get the header of the next packet in the receive ring */
    Adapter->PacketOffset = Adapter->NextPacket << 8;
    NICReadData(Adapter,
                (PUCHAR)&Adapter->PacketHeader,
                Adapter->PacketOffset,
                sizeof(PACKET_HEADER));

    NDIS_DbgPrint(MAX_TRACE, ("HEADER: (Status)       (0x%X)\n", Adapter->PacketHeader.Status));
    NDIS_DbgPrint(MAX_TRACE, ("HEADER: (NextPacket)   (0x%X)\n", Adapter->PacketHeader.NextPacket));
    NDIS_DbgPrint(MAX_TRACE, ("HEADER: (PacketLength) (0x%X)\n", Adapter->PacketHeader.PacketLength));

    if (Adapter->PacketHeader.PacketLength < 64  ||
        Adapter->PacketHeader.PacketLength > 1518) {	/* XXX I don't think the CRC will show up... should be 1514 */
        NDIS_DbgPrint(MAX_TRACE, ("Bogus packet size (%d).\n",
            Adapter->PacketHeader.PacketLength));
        SkipPacket = TRUE;
    }

    if (SkipPacket) {
        /* Skip packet */
        Adapter->NextPacket = Adapter->CurrentPage;
    } else {
	NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
				 Adapter->MiniportAdapterHandle));
        NICIndicatePacket(Adapter);

        /* Go to the next free buffer in receive ring */
        Adapter->NextPacket = Adapter->PacketHeader.NextPacket;
    }

    /* Update boundary page */
    NICSetBoundaryPage(Adapter);
}


static VOID NICWritePacket(
    PNIC_ADAPTER Adapter)
/*
 * FUNCTION: Writes a full packet to the transmit buffer ring
 * ARGUMENTS:
 *     Adapter  = Pointer to adapter information
 * NOTES:
 *     There must be enough free buffers available in the transmit buffer ring.
 *     The packet is taken from the head of the transmit queue and the position
 *     into the transmit buffer ring is taken from TXNext
 */
{
    PNDIS_BUFFER SrcBuffer;
    UINT BytesToCopy, SrcSize, DstSize;
    PUCHAR SrcData;
    ULONG DstData;
    UINT TXStart;
    UINT TXStop;

    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

    TXStart = Adapter->TXStart * DRIVER_BLOCK_SIZE;
    TXStop  = (Adapter->TXStart + Adapter->TXCount) * DRIVER_BLOCK_SIZE;

    NdisQueryPacket(Adapter->TXQueueHead,
                    NULL,
                    NULL,
                    &SrcBuffer,
                    &Adapter->TXSize[Adapter->TXNext]);

    NDIS_DbgPrint(MID_TRACE, ("Packet (%d) is now size (%d).\n",
        Adapter->TXNext,
        Adapter->TXSize[Adapter->TXNext]));

    NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);

    DstData = TXStart + Adapter->TXNext * DRIVER_BLOCK_SIZE;
    DstSize = TXStop - DstData;

    /* Start copying the data */
    for (;;) {
        BytesToCopy = (SrcSize < DstSize)? SrcSize : DstSize;

        NICWriteData(Adapter, DstData, SrcData, BytesToCopy);

        SrcData = (PUCHAR)((ULONG_PTR) SrcData + BytesToCopy);
        SrcSize            -= BytesToCopy;
        DstData            += BytesToCopy;
        DstSize            -= BytesToCopy;

        if (SrcSize == 0) {
            /* No more bytes in source buffer. Proceed to
               the next buffer in the source buffer chain */
            NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
            if (!SrcBuffer)
                break;

            NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
        }

        if (DstSize == 0) {
            /* Wrap around the end of the transmit buffer ring */
            DstData = TXStart;
            DstSize = Adapter->TXCount * DRIVER_BLOCK_SIZE;
        }
    }
}


static BOOLEAN NICPrepareForTransmit(
    PNIC_ADAPTER Adapter)
/*
 * FUNCTION: Prepares a packet for transmission
 * ARGUMENTS:
 *     Adapter = Pointer to adapter information
 * NOTES:
 *     There must be at least one packet in the transmit queue
 * RETURNS:
 *     TRUE if a packet was prepared, FALSE if not
 */
{
    UINT Length;
    UINT BufferCount;
    PNDIS_PACKET Packet;

    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

    /* Calculate number of buffers needed to transmit packet */
    NdisQueryPacket(Adapter->TXQueueHead,
                    NULL,
                    NULL,
                    NULL,
                    &Length);

    BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;

    if (BufferCount > Adapter->TXFree) {
        NDIS_DbgPrint(MID_TRACE, ("No transmit resources. Have (%d) buffers, need (%d).\n",
            Adapter->TXFree, BufferCount));
        /* We don't have the resources to transmit this packet right now */
        return FALSE;
    }

    /* Write the packet to the card */
    NICWritePacket(Adapter);

    /* If the NIC is not transmitting, reset the current transmit pointer */
    if (Adapter->TXCurrent == -1)
        Adapter->TXCurrent = Adapter->TXNext;

    Adapter->TXNext  = (Adapter->TXNext + BufferCount) % Adapter->TXCount;
    Adapter->TXFree -= BufferCount;

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

    if (Packet == Adapter->TXQueueTail)
        Adapter->TXQueueTail = NULL;

    /* Assume the transmit went well */
    NdisMSendComplete(Adapter->MiniportAdapterHandle,
                      Packet,
                      NDIS_STATUS_SUCCESS);

    return TRUE;
}


VOID NICTransmit(
    PNIC_ADAPTER Adapter)
/*
 * FUNCTION: Starts transmitting packets in the transmit queue
 * ARGUMENTS:
 *     Adapter = Pointer to adapter information
 * NOTES:
 *     There must be at least one packet in the transmit queue
 */
{
    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

    if (Adapter->TXCurrent == -1) {
        /* NIC is not transmitting, so start transmitting now */

        /* Load next packet onto the card, and start transmitting */
        if (NICPrepareForTransmit(Adapter))
            NICStartTransmit(Adapter);
    }
}


static VOID HandleReceive(
    PNIC_ADAPTER Adapter)
/*
 * FUNCTION: Handles reception of a packet
 * ARGUMENTS:
 *     Adapter = Pointer to adapter information
 * NOTES:
 *     Buffer overflows are also handled here
 */
{
    UINT i;
    UCHAR Tmp;
    UINT PacketCount;

    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

    Adapter->DoneIndicating = FALSE;
    PacketCount = 0;

    NICGetCurrentPage(Adapter);

    if (Adapter->BufferOverflow) {

        NDIS_DbgPrint(MID_TRACE, ("Receive ring overflow.\n"));

        /* Select page 0 and stop the NIC */
        NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);

        /* Clear RBCR0,RBCR1 - Remote Byte Count Registers */
        NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
        NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);

        /* Wait for ISR_RST to be set, but timeout after 2ms */
        for (i = 0; i < 4; i++) {
            NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
            if (Tmp & ISR_RST)
                break;

            NdisStallExecution(500);
        }

#ifdef DBG
        if (i == 4)
            NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n"));
#endif

        if ((Adapter->InterruptStatus & (ISR_PTX | ISR_TXE)) == 0) {
            /* We may need to restart the transmitter */
            Adapter->TransmitPending = TRUE;
        }

        /* Initialize TCR - Transmit Configuration Register to loopback mode 1 */
        NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);

        /* Start NIC */
        NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2);

        NICStart(Adapter);

        Adapter->BufferOverflow = FALSE;
    }

    if (Adapter->ReceiveError) {
        NDIS_DbgPrint(MID_TRACE, ("Receive error.\n"));

        /* Skip this packet */
        Adapter->NextPacket = Adapter->CurrentPage;
        NICSetBoundaryPage(Adapter);

        Adapter->ReceiveError = FALSE;
    }

    for (;;) {
        NICGetCurrentPage(Adapter);

        NDIS_DbgPrint(MID_TRACE, ("Current page (0x%X)  NextPacket (0x%X).\n",
            Adapter->CurrentPage,
            Adapter->NextPacket));

        if (Adapter->CurrentPage == Adapter->NextPacket) {
            NDIS_DbgPrint(MID_TRACE, ("No more packets.\n"));
            break;
        } else {
            NDIS_DbgPrint(MID_TRACE, ("Got a packet in the receive ring.\n"));

	    NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
				     Adapter->MiniportAdapterHandle));
            /* Read packet from receive buffer ring */
            NICReadPacket(Adapter);

            Adapter->DoneIndicating = TRUE;

            PacketCount++;
            if (PacketCount == 10) {
                /* Don't starve transmit interrupts */
                break;
            }
        }
    }

    if ((Adapter->TransmitPending) && (Adapter->TXCurrent != -1)) {
        NDIS_DbgPrint(MID_TRACE, ("Retransmitting current packet at (%d).\n", Adapter->TXCurrent));
        /* Retransmit packet */
        NICStartTransmit(Adapter);
        Adapter->TransmitPending = FALSE;
    }

    if (Adapter->DoneIndicating)
        NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
}


static VOID HandleTransmit(
    PNIC_ADAPTER Adapter)
/*
 * FUNCTION: Handles transmission of a packet
 * ARGUMENTS:
 *     Adapter = Pointer to adapter information
 */
{
    UINT Length;
    UINT BufferCount;

//    PIP_PACKET pIPPacket;
//    pIPPacket = (PIP_PACKET)
//    DisplayIPPacket(pIPPacket);

    if (Adapter->TransmitError) {
        /* FIXME: Retransmit now or let upper layer protocols handle retransmit? */
        Adapter->TransmitError = FALSE;
    }

    /* Free transmit buffers */
    Length      = Adapter->TXSize[Adapter->TXCurrent];
    BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;

    NDIS_DbgPrint(MID_TRACE, ("Freeing (%d) buffers at (%d).\n",
        BufferCount,
        Adapter->TXCurrent));

    Adapter->TXFree += BufferCount;
    Adapter->TXSize[Adapter->TXCurrent] = 0;
    Adapter->TXCurrent = (Adapter->TXCurrent + BufferCount) % Adapter->TXCount;

    if (Adapter->TXSize[Adapter->TXCurrent] == 0) {
        NDIS_DbgPrint(MID_TRACE, ("No more packets in transmit buffer.\n"));

        Adapter->TXCurrent = -1;
    }

    if (Adapter->TXQueueTail) {
        if (NICPrepareForTransmit(Adapter))
            NICStartTransmit(Adapter);
    }
}


VOID STDCALL MiniportHandleInterrupt(
    IN  NDIS_HANDLE MiniportAdapterContext)
/*
 * FUNCTION: Handler for deferred processing of interrupts
 * ARGUMENTS:
 *     MiniportAdapterContext = Pointer to adapter context area
 * NOTES:
 *     Interrupt Service Register is read to determine which interrupts
 *     are pending. All pending interrupts are handled
 */
{
    UCHAR ISRValue;
    UCHAR ISRMask;
    UCHAR Mask;
    PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;

    ISRMask = Adapter->InterruptMask;
    NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);

    NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue));

    Adapter->InterruptStatus |= (ISRValue & ISRMask);

    if (ISRValue != 0x00)
        /* Acknowledge interrupts */
        NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);

    Mask = 0x01;
    while (Adapter->InterruptStatus != 0x00) {

        NDIS_DbgPrint(MID_TRACE, ("Adapter->InterruptStatus (0x%X)  Mask (0x%X).\n",
            Adapter->InterruptStatus, Mask));

        /* Find next interrupt type */
        while (((Adapter->InterruptStatus & Mask) == 0) && (Mask < ISRMask))
            Mask = (Mask << 1);

        switch (Adapter->InterruptStatus & Mask) {
        case ISR_OVW:
            NDIS_DbgPrint(MID_TRACE, ("Overflow interrupt.\n"));
            /* Overflow. Handled almost the same way as a receive interrupt */
            Adapter->BufferOverflow = TRUE;

	    NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
				     Adapter->MiniportAdapterHandle));
	    if(Adapter->MiniportAdapterHandle)
		HandleReceive(Adapter);
	    else
		NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n"));

            Adapter->InterruptStatus &= ~ISR_OVW;
            break;

        case ISR_RXE:
            NDIS_DbgPrint(MID_TRACE, ("Receive error interrupt.\n"));
            NICUpdateCounters(Adapter);

            Adapter->ReceiveError = TRUE;

        case ISR_PRX:
            NDIS_DbgPrint(MID_TRACE, ("Receive interrupt.\n"));

	    NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n",
				     Adapter->MiniportAdapterHandle));
	    if(Adapter->MiniportAdapterHandle)
		HandleReceive(Adapter);
	    else
		NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n"));

            Adapter->InterruptStatus &= ~(ISR_PRX | ISR_RXE);
            break;

        case ISR_TXE:
            NDIS_DbgPrint(MID_TRACE, ("Transmit error interrupt.\n"));
            NICUpdateCounters(Adapter);

            Adapter->TransmitError = TRUE;

        case ISR_PTX:
            NDIS_DbgPrint(MID_TRACE, ("Transmit interrupt.\n"));

            HandleTransmit(Adapter);

            Adapter->InterruptStatus &= ~(ISR_PTX | ISR_TXE);
            break;

        case ISR_CNT:
            NDIS_DbgPrint(MID_TRACE, ("Counter interrupt.\n"));
            /* Counter overflow. Read counters from the NIC */
            NICUpdateCounters(Adapter);

            Adapter->InterruptStatus &= ~ISR_CNT;
            break;

        default:
            NDIS_DbgPrint(MID_TRACE, ("Unknown interrupt. Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus));
            Adapter->InterruptStatus &= ~Mask;
            break;
        }

        Mask = (Mask << 1);

        /* Check if new interrupts are generated */

        NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);

        NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue));

        Adapter->InterruptStatus |= (ISRValue & ISRMask);

        if (ISRValue != 0x00) {
            /* Acknowledge interrupts */
            NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);
            Mask = 0x01;
        }
    }

    NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
}

/* EOF */

⌨️ 快捷键说明

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