nsc.c

来自「网络驱动开发」· C语言 代码 · 共 2,150 行 · 第 1/5 页

C
2,150
字号
             ListEntry != Head;
             ListEntry = ListEntry->Flink)
        {
            rcvBuffer *temp = CONTAINING_RECORD(ListEntry,
                                                rcvBuffer,
                                                listEntry);
            if (temp->dataBuf > rcvBuf->dataBuf)
            {
                // We found one that comes after ours.
                // We need to insert before it

                InsertTailList(ListEntry, &rcvBuf->listEntry);
                EntryInserted = TRUE;
                break;
            }
        }
        if (!EntryInserted)
        {
            // We didn't find an entry on the last who's address was later
            // than our buffer.  We go at the end.
            InsertTailList(Head, &rcvBuf->listEntry);
        }
    }
    NdisReleaseSpinLock(Lock);
}

/*
 *************************************************************************
 *  DeliverFullBuffers
 *************************************************************************
 *
 *  Deliver received packets to the protocol.
 *  Return TRUE if delivered at least one frame.
 *
 */
VOID
DeliverFullBuffers(IrDevice *thisDev)
{
    PLIST_ENTRY ListEntry;

    LOG("==> DeliverFullBuffers");
    DBGOUT(("==> DeliverFullBuffers(0x%x)", thisDev));


    /*
     *  Deliver all full rcv buffers
     */

    for (
         ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFull,
                                                    &thisDev->interruptObj);
         ListEntry;

         ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFull,
                                                    &thisDev->interruptObj)
        )
    {
        rcvBuffer *rcvBuf = CONTAINING_RECORD(ListEntry,
                                              rcvBuffer,
                                              listEntry);
        NDIS_STATUS stat;
        PNDIS_BUFFER packetBuf;
        SLOW_IR_FCS_TYPE fcs;

        VerifyNdisPacket(rcvBuf->packet, 0);


        if (thisDev->currentSpeed <= MAX_SIR_SPEED) {
            /*
             * The packet we have already has had BOFs,
             * EOF, and * escape-sequences removed.  It
             * contains an FCS code at the end, which we
             * need to verify and then remove before
             * delivering the frame.  We compute the FCS
             * on the packet with the packet FCS attached;
             * this should produce the constant value
             * GOOD_FCS.
             */
            fcs = ComputeFCS(rcvBuf->dataBuf,
                             rcvBuf->dataLen);

            if (fcs != GOOD_FCS) {
               /*
                *  FCS Error.  Drop this frame.
                */
                LOG("Error: Bad FCS in DeliverFullBuffers %x", fcs);
                DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.",
                        (UINT)fcs, (UINT) GOOD_FCS));
                rcvBuf->state = STATE_FREE;

                DBGSTAT(("Dropped %d/%d pkts; BAD FCS (%xh!=%xh):",
                         ++thisDev->packetsDropped,
                         thisDev->packetsDropped +
                         thisDev->packetsRcvd, fcs,
                         GOOD_FCS));

                DBGPRINTBUF(rcvBuf->dataBuf,
                            rcvBuf->dataLen);

                if (!rcvBuf->isDmaBuf)
                {
                    NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
                                                   RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
                                                   &thisDev->interruptObj);
                }
                rcvBuf->dataBuf = NULL;
                rcvBuf->isDmaBuf = FALSE;

                VerifyNdisPacket(rcvBuf->packet, 0);
                NDISSynchronizedInsertHeadList(&thisDev->rcvBufFree,
                                               &rcvBuf->listEntry,
                                               &thisDev->interruptObj);

                //break;
                continue;
            }

        /* Remove the FCS from the end of the packet. */
            rcvBuf->dataLen -= SLOW_IR_FCS_SIZE;
        }
#ifdef DBG_ADD_PKT_ID
        if (addPktIdOn) {

            /* Remove dbg packet id. */
            USHORT uniqueId;
            rcvBuf->dataLen -= sizeof(USHORT);
            uniqueId = *(USHORT *)(rcvBuf->dataBuf+
                                   rcvBuf->dataLen);
            DBGOUT(("ID: RCVing packet %xh **",
                    (UINT)uniqueId));
            LOG("ID: Rcv Pkt id: %xh", uniqueId);
        }
#endif

        /*
         * The packet array is set up with its NDIS_PACKET.
         * Now we need to allocate a single NDIS_BUFFER for
         * the NDIS_PACKET and set the NDIS_BUFFER to the
         * part of dataBuf that we want to deliver.
         */
        NdisAllocateBuffer(&stat, &packetBuf,
                           thisDev->bufferPoolHandle,
                           (PVOID)rcvBuf->dataBuf, rcvBuf->dataLen);

        if (stat != NDIS_STATUS_SUCCESS){
            LOG("Error: NdisAllocateBuffer failed");
            DBGERR(("NdisAllocateBuffer failed"));
            ASSERT(0);
            break;
        }

        VerifyNdisPacket(rcvBuf->packet, 0);
        NdisChainBufferAtFront(rcvBuf->packet, packetBuf);
        LOG_PacketChain(thisDev, rcvBuf->packet);
        VerifyNdisPacket(rcvBuf->packet, 1);

        /*
         *  Fix up some other packet fields.
         */
        NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet,
                                    IR_ADDR_SIZE+IR_CONTROL_SIZE);

        DBGPKT(("Indicating rcv packet 0x%x.", rcvBuf->packet));

        /*
         * Indicate to the protocol that another packet is
         * ready.  Set the rcv buffer's state to PENDING first
         * to avoid a race condition with NDIS's call to the
         * return packet handler.
         */

        NdisAcquireSpinLock(&thisDev->QueueLock);

        if (thisDev->Halting) {
            //
            //  the adapter is being halted, stop sending packets up
            //

            NdisReleaseSpinLock(&thisDev->QueueLock);

            if (!rcvBuf->isDmaBuf) {

                NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
                                               RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
                                               &thisDev->interruptObj);
            }
            rcvBuf->dataBuf = NULL;
            rcvBuf->isDmaBuf = FALSE;

            VerifyNdisPacket(rcvBuf->packet, 0);
            NDISSynchronizedInsertHeadList(&thisDev->rcvBufFree,
                                           &rcvBuf->listEntry,
                                           &thisDev->interruptObj);


            //
            //  free the buffer we chained to the packet
            //
            packetBuf=NULL;

            NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf);

            if (packetBuf){

                NdisFreeBuffer(packetBuf);
            }


            continue;
        }

        //
        //  increment the count of packets sent to the protocol
        //
        NdisInterlockedIncrement(&thisDev->PacketsSentToProtocol);

        NdisReleaseSpinLock(&thisDev->QueueLock);

        rcvBuf->state = STATE_PENDING;

        *(rcvBuffer **)rcvBuf->packet->MiniportReserved = rcvBuf;

        InterlockedInsertBufferSorted(
            &thisDev->rcvBufPend,
            rcvBuf,
            &thisDev->QueueLock
            );

        VerifyNdisPacket(rcvBuf->packet, 1);
        LOG_Data2(thisDev, rcvBuf->dataBuf);


        NDIS_SET_PACKET_STATUS(rcvBuf->packet,STATUS_SUCCESS);
        NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle,
                                   &rcvBuf->packet, 1);

        /*
         * The packet is being delivered asynchronously.
         * Leave the rcv buffer's state as PENDING;
         * we'll get a callback when the transfer is
         */

         LOG("Indicated rcv complete (Async) bytes: %d",
             rcvBuf->dataLen);
         DBGSTAT(("Rcv Pending. Rcvd %d packets",
                     ++thisDev->packetsRcvd));

    }

    LOG("<== DeliverFullBuffers");
    DBGOUT(("<== DeliverFullBuffers"));
    return ;
}


/*
 *************************************************************************
 *  MiniportHandleInterrupt
 *************************************************************************
 *
 *
 *  This is the deferred interrupt processing routine (DPC) which is
 *  optionally called following an interrupt serviced by MiniportISR.
 *
 */
VOID MiniportHandleInterrupt(NDIS_HANDLE MiniportAdapterContext)
{
    IrDevice    *thisDev    =    CONTEXT_TO_DEV(   MiniportAdapterContext);
    PNDIS_PACKET   PacketToComplete=NULL;
    NDIS_STATUS    PacketStatus=NDIS_STATUS_SUCCESS;
    BOOLEAN        SpeedChange=FALSE;

    LOG("==> MiniportHandleInterrupt");
    DBGOUT(("==> MiniportHandleInterrupt(0x%x)", MiniportAdapterContext));



    /*
     * If we have just started receiving a packet, indicate media-busy
     * to the protocol.
     */
    if (thisDev->mediaBusy && !thisDev->haveIndicatedMediaBusy) {

        if (thisDev->currentSpeed > MAX_SIR_SPEED) {
            LOG("Error: MiniportHandleInterrupt is in wrong state %d",
                thisDev->currentSpeed);
            DBGERR(("MiniportHandleInterrupt is in wrong state: speed is 0x%x",
                    thisDev->currentSpeed));
            ASSERT(0);
        }

        NdisMIndicateStatus(thisDev->ndisAdapterHandle,
                            NDIS_STATUS_MEDIA_BUSY, NULL, 0);
        NdisMIndicateStatusComplete(thisDev->ndisAdapterHandle);

        thisDev->haveIndicatedMediaBusy = TRUE;
    }

    NdisDprAcquireSpinLock(&thisDev->QueueLock);

    if (thisDev->currentSpeed > MAX_SIR_SPEED) {
        //
        //  fir speed
        //

        //
        //  disable any other
        //
        thisDev->FirIntMask = 0x00;

        if (thisDev->FirTransmitPending) {

            ASSERT(thisDev->CurrentPacket != NULL);

            thisDev->FirTransmitPending=FALSE;

            //
            //  we seem to be transmitting now
            //

            {
                ULONG CurrentDMACount;
                UCHAR BytesInFifo;
                ULONG LoopCount=0;

                CurrentDMACount = NdisMReadDmaCounter(thisDev->DmaHandle);

                if (CurrentDMACount > 0) {

                     LOG_ERROR("FIR send: Dma Count was not zero: %d\n\n", CurrentDMACount);
#if DBG
                     DbgPrint("FIR send: Count was not zero: %d\n\n", CurrentDMACount);
#endif
                }

                //
                //  see if the fifo is empty yet
                //
                BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_2, TXFLV_OFFSET) & 0x3f;

                if (BytesInFifo > 0) {

                    LOG_ERROR("FIR send: Bytes still in fifo: %d", BytesInFifo);

                    while ((BytesInFifo > 0) && (LoopCount < 64)) {

                        BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_2, TXFLV_OFFSET) & 0x3f;
                        LoopCount++;
                    }

                    LOG_ERROR("FIR send: Bytes still in fifo after loop: %d, loops=%d", BytesInFifo,LoopCount);
                }
            }

            PacketStatus=CompleteDmaTransferToDevice(
                &thisDev->DmaUtil
                );

            if (PacketStatus != NDIS_STATUS_SUCCESS) {
                DBGERR(("NdisMCompleteDmaTransfer failed: %d\n", PacketStatus));
#if DBG
                DbgBreakPoint();
#endif
            }

            /*
             * Check for Tx underrun.
             */
            if (SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, ASCR_OFFSET) & ASCR_TXUR) {

                USHORT  TransmitCurrentCount;

                //
                //  for debugging purposes, see where we were in the frame when it stopped
                //
                TransmitCurrentCount =  SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_4, TFRCCL_OFFSET);
                TransmitCurrentCount |= ((USHORT)SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_4, TFRCCH_OFFSET)) << 8;

                //
                //  reset the fifo's
                //
                SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, 2, 0x07);

                //
                //  clear the tx underrun
                //
                SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, ASCR_OFFSET, ASCR_TXUR);

                RegStats.TxUnderruns++;
                PacketStatus = NDIS_STATUS_FAILURE;

                LOG_ERROR("MiniportDpc: Transmit Underrun: tx current count=%d",TransmitCurrentCount);
                DEBUGFIR(DBG_TX|DBG_ERR, ("NSC: FIR_MegaSendComplete: Transmit Underrun\n"));
            }

            PacketToComplete=thisDev->CurrentPacket;
            thisDev->CurrentPacket=NULL;

        } else {

            if (thisDev->FirReceiveDmaActive) {

                FIR_DeliverFrames(thisDev);

            } else {

                DBGERR(("MiniportHandleInterrupt: fir: not sending and not RX state"));
                LOG_ERROR("MiniportHandleInterrupt: fir: not sending and not RX state %02x",thisDev->InterruptStatus);
            }

        }

    } else {
        //
        //  in SIR mode
        //
        if (thisDev->CurrentPacket != NULL) {
            //
            //
            UINT   TransmitComplete=InterlockedExchange(&thisDev->portInfo.IsrDoneWithPacket,0);

            if (TransmitComplete) {

                PacketToComplete=thisDev->CurrentPacket;
                thisDev->CurrentPacket=NULL;
            }
        }
    }

    thisDev->setSpeedAfterCurrentSendPacket = FALSE;

⌨️ 快捷键说明

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