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

📄 nsc.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 5 页
字号:
 *
 */
BOOLEAN DeliverFullBuffers(IrDevice *thisDev)
{
    BOOLEAN result = FALSE;
    PLIST_ENTRY ListEntry;

    LOG(TEXT("==> DeliverFullBuffers"), 0);
    DBGOUT((TEXT("==> DeliverFullBuffers(0x%x)"), (UINT) 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(TEXT("Error: Bad FCS in DeliverFullBuffers"), fcs);
                DBGERR((TEXT("Bad FCS in DeliverFullBuffers bad != good 0x%x!=0x%x."),
                        (UINT)fcs, (UINT) GOOD_FCS));
                rcvBuf->state = STATE_FREE;

                DBGSTAT((TEXT("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:", 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(TEXT("Error: NdisAllocateBuffer failed"), 0);
            DBGERR((TEXT("NdisAllocateBuffer failed")));
            DbgBreakPoint();
            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((TEXT("Indicating rcv packet 0x%x."),
                (UINT)rcvBuf->packet));
        DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen);

    /*  
     * 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.
     */
        rcvBuf->state = STATE_PENDING;

        *(rcvBuffer **)rcvBuf->packet->MiniportReserved = rcvBuf;
        InterlockedInsertBufferSorted(&thisDev->rcvBufPend,
                                      rcvBuf,
                                      &thisDev->QueueLock);

        VerifyNdisPacket(rcvBuf->packet, 1);
        LOG_Data2(thisDev, rcvBuf->dataBuf);
        NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle,
                                   &rcvBuf->packet, 1);
        IRFIR_LOG_NDIS_PACKET(LOG_RXFRAME, rcvBuf->packet);
        result = TRUE;

        stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet);          
        if (stat == NDIS_STATUS_PENDING) {
        /*
         * The packet is being delivered asynchronously.
         * Leave the rcv buffer's state as PENDING;
         * we'll get a callback when the transfer is
         * complete.  Do NOT step firstRcvBufIndex.
         * We don't really need to break out here, 
         * but we will anyways just to make things
         * simple.  This is ok since we get this
         * deferred interrupt callback for each packet
         * anyway.  It'll give the protocol a chance
         * to catch up.
         */
            LOG(TEXT("Indicated rcv complete (Async) bytes:"),
                rcvBuf->dataLen);
            DBGSTAT((TEXT("Rcv Pending. Rcvd %d packets"),
                     ++thisDev->packetsRcvd));
        }
        else {
        /*
         * If there was an error, we are dropping this
         * packet; otherwise, this packet was delivered
         * synchronously.  We can free the packet
         * buffer and make this rcv frame available.
         */
            LOG_RemoveEntryList(thisDev, rcvBuf);
            NdisAcquireSpinLock(&thisDev->QueueLock);
            RemoveEntryList(&rcvBuf->listEntry);
            NdisReleaseSpinLock(&thisDev->QueueLock);
            LOG(TEXT("Indicated rcv complete (sync) bytes:"),
                rcvBuf->dataLen);

            LOG_PacketUnchain(thisDev, rcvBuf->packet);
            NdisUnchainBufferAtFront(rcvBuf->packet,
                                     &packetBuf);
            if (packetBuf){
                NdisFreeBuffer(packetBuf);  
            }

            rcvBuf->state = STATE_FREE;
            VerifyNdisPacket(rcvBuf->packet, 0);

            if (!rcvBuf->isDmaBuf) {

                //
                // At SIR speeds, we manage a group of buffers that
                // we keep on the rcvBufBuf queue.
                //

                NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
                                               RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
                                               &thisDev->interruptObj);
                // ASSERT the pointer is actually outside our FIR DMA buffer
                ASSERT(rcvBuf->dataBuf < thisDev->portInfo.dmaReadBuf ||
                       rcvBuf->dataBuf >= thisDev->portInfo.dmaReadBuf+RCV_DMA_SIZE);
            }

            rcvBuf->dataBuf = NULL;

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


            if (stat == NDIS_STATUS_SUCCESS){
                DBGSTAT((TEXT("Rcvd %d packets"),
                         ++thisDev->packetsRcvd));
            }
            else {
                DBGSTAT((TEXT("Dropped %d/%d rcv packets."),
                         thisDev->packetsDropped++,
                         thisDev->packetsDropped +
                         thisDev->packetsRcvd));
            }
        }

    }

    LOG(TEXT("<== DeliverFullBuffers"), 1);
    DBGOUT((TEXT("<== DeliverFullBuffers")));
    return result;
}

/*
 *************************************************************************
 *  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);

    LOG(TEXT("==> MiniportHandleInterrupt"), 0);

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

    if (thisDev->resourcesReleased){
        DBGOUT((TEXT("<== MiniportHandleInterrupt, blow off, no resources!")));
        return;
    }

    /*
     * If we finished the last send packet in the interrupt, we must change 
     * speed.
     */
    if (thisDev->setSpeedNow){
        thisDev->setSpeedNow = FALSE;

        SetSpeed(thisDev);
    }

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

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

#ifdef OUTMSG
			RETAILMSG(1, (TEXT("Error: MiniportHandleInterrupt is in wrong state\r\n")));
#endif

        }

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

        thisDev->haveIndicatedMediaBusy = TRUE;
    }

    /* FIR mode */
    if (thisDev->currentSpeed > MAX_SIR_SPEED) {

        DBGISR((TEXT("HandleInterrupt - FIR")));
        if (thisDev->portInfo.writePending) {
            FIR_MegaSendComplete(thisDev);
            /*
             * Any more Tx packets?
             */
            if (!IsListEmpty(&thisDev->SendQueue))
            {


            /* Kick off another Tx. */
                FIR_MegaSend(thisDev);
            }
            else {
 
               thisDev->IntMask = 0x04;



                SetupRecv(thisDev);
                /*
                 *  If we just sent the last frame to be sent at the old speed,
                 *  set the hardware to the new speed.
                 *  From OLD sytle!
                 */
                if (thisDev->setSpeedAfterCurrentSendPacket) {
                    thisDev->setSpeedAfterCurrentSendPacket = FALSE;

                    SetSpeed(thisDev);
                }
            }
        }
        else {

            FIR_DeliverFrames(thisDev);

            if (DeliverFullBuffers(thisDev)) {
                // ??? 
                MiniportSyncHandleInterrupt((PVOID) thisDev);
            }
        }
    }

    /* SIR mode */
    else {
        DBGISR((TEXT("HandleInterrupt - SIR")));
        /*
         * We delivered a receive packet.  Update the rcv queue
         * 'first' and 'last' pointers.  We cannot use a spinlock
         * to coordinate accesses to the rcv buffers with the ISR,
         * since ISR's are not allowed to acquire spinlocks.  So 
         * instead, we synchronize with the ISR using this special
         * mechanism.  MiniportSyncHandleInterrupt will do our work
         * for us with the IRQ masked out in the PIC.
         */
        if (DeliverFullBuffers(thisDev)) {
#if  0
            NdisMSynchronizeWithInterrupt(&thisDev->interruptObj,
                                          MiniportSyncHandleInterrupt,
                                          (PVOID)MiniportAdapterContext);
#endif
        }
        /*
         *  Send any pending write packets if possible. 
         */
        if (IsCommReadyForTransmit(thisDev)) {
            PortReadyForWrite(thisDev, TRUE);
        }
    }

    LOG(TEXT("<== MiniportHandleInterrupt"), 1);
    DBGOUT((TEXT("<== MiniportHandleInterrupt")));

}

#ifndef UNDER_CE
/*
 *************************************************************************
 *  GetPnPResources
 *************************************************************************
 *
 *
 */
BOOLEAN GetPnPResources(IrDevice *thisDev, NDIS_HANDLE WrapperConfigurationContext)
{
    NDIS_STATUS stat;
    BOOLEAN result = FALSE;

    /*
     *  We should only need 2 adapter resources (2 IO and 1 interrupt),

⌨️ 快捷键说明

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