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

📄 ncfwapi.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
        // Transfer accounting
        Endpoint->Priv.BytesRemaining -= EpAvail.Word;
        Endpoint->Priv.pPkt += EpAvail.Word;
        HISTO(DEFAULT_HISTORY, "RxCp", EpAvail.Word, EpStat0, Endpoint->Priv.BytesRemaining);

#if NET2272_16BIT
        // Recalculate loop counter for 16 bit accesses
        EpAvail.Word = (USHORT)((EpAvail.Word + 1)>>1);
#endif

#pragma message(_NC_MESSAGE"Recommendation: Optimize Rx copy loop in assembler")
        // Copy bytes (or words) to memory from endpoint
        //  - For best performance, this loop should be optimized and written in assembler
        while (EpAvail.Word--) 
        {
            *(pRxBuf++) = NETCHIP_BASEADDRESS[EP_DATA].NcReg;
        }

        // After we read the final byte from an endpoint buffer, the endpoint's alternate buffer
        // may become visible to us. It will become visible if and only if the USB host successfully 
        // transferred a packet to it. When it becomes visible, the following are updated:
        //  - EP_STAT0
        //  - EP_STAT1
        //  - EP_AVAIL0, EP_AVAIL1
        EpStat0 = NETCHIP_READ(EP_STAT0);
        if (EpStat0 & (1<<SHORT_PACKET_TRANSFERRED_INTERRUPT))
        {   // Eliminate timing exposure: NET2272 OUT endpoint logic sets Short Packet 
            // status slightly before (i.e. one or two nSecs before) Buffer Empty 
            // status becomes valid:
            //  - Re-reading EP_STAT0 ensures Buffer Empty is accurate
            EpStat0 = NETCHIP_READ(EP_STAT0);
        }

        HISTO(VOLUME_MAXIMUM, "Loop", 0, EpStat0, Endpoint->Priv.BytesRemaining);
    } while (!(EpStat0 & (1<<BUFFER_EMPTY)));

    if (EpStat0 & (1<<SHORT_PACKET_TRANSFERRED_INTERRUPT))
    {   // A USB short packet has been received, terminating this USB transfer 
        //  - All bytes of the transfer have been successfully read from the endpoint and
        //    written to system memory
        //  - Number of bytes transferred may be LESS than requested (but must NEVER EXCEED request!)
        //  - Endpoint will NAK subsequent host requests
        NETCHIP_DATA_TYPE dummy;

        // Force "end of transfer" handling
        Endpoint->Priv.BytesRemaining = 0;
        Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
        NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_Instant;)

        // Handle possibility of a Zero-Length OUT packet
        //  - NET2272 OUT endpoints use the final read from Endpoint Data to signal that
        //    the endpoint's buffer has been handled by firmware. Zero length OUT packets 
        //    have no data, but endpoint logic still requires a read from EP_DATA
        //  - Reading EP_DATA before clearing NAK OUT Packets reliably and safely addresses
        //    the issue, and has no side-effects.
        dummy.NcReg = NETCHIP_BASEADDRESS[EP_DATA].NcReg;

        HISTO(DEFAULT_HISTORY, "ShPk", EpStat0, NETCHIP_READ(EP_STAT0), 0);

#if _NCVIRTUALENDPOINTS
        NETCHIP_WRITE(EP_STAT0, 
            (1<<DATA_PACKET_RECEIVED_INTERRUPT) |       // Required
            (1<<DATA_OUT_TOKEN_INTERRUPT) |             // Required (for Token Notification)
            (1<<SHORT_PACKET_TRANSFERRED_INTERRUPT) |   // Required (Prepare for end of new OUT transfer)
            0);
        // Assert: NAK OUT Packets has automatically been set by the endpoint ensuring that this endpoint 
        // is now blocking (NAK'ing) any host requests. The endpoint's condition is therefore 
        // quiescent, and will not change (until another transfer is started)
        ASSERT(EpStat0 & NETCHIP_READ(EP_STAT0) & (1<<NAK_OUT_PACKETS));
#else
        NETCHIP_WRITE(EP_STAT0, 
            (1<<DATA_PACKET_RECEIVED_INTERRUPT) |       // Required
            (1<<DATA_OUT_TOKEN_INTERRUPT) |             // Required (for Token Notification)
            (1<<SHORT_PACKET_TRANSFERRED_INTERRUPT) |   // Required (Prepare for end of new OUT transfer)
            (1<<NAK_OUT_PACKETS) |                      // Required (Endpoint can accept packets immediately)
            0);
#endif
    }

    if (Endpoint->Priv.BytesRemaining == 0)
    {   // Zero bytes remain in the transfer, however the transfer may not be *quite* complete:
        //  - Corner case: If the client requested that exact packet multiple transfers are
        //    to be terminated (i.e. "Apply ZLP", then another packet (usually, but not 
        //    necessarily, a Zero Length OUT packet) must be received and accounted for:
        if (
            (Endpoint->CompletionStatus == NCSTATUS_PENDING) &&             // Transfer not yet completed (no short packet, no error)?
            (!(Transfer->TransferFlags & (1<<NC_TRANSFER_FLAG_APPLY_ZLP)))  // Client does NOT require ZLP to terminate exact packet multiples?
            )
        {   // Force transfer to complete successfully (without a short packet)
            //  - Zero bytes remain, and client does not expect another packet to terminate the transfer
            // Assert: To get here, the transfer MUST have resulted in an exact packet multiple (or 
            // the Short Packet Transferred section would have completed the transfer!)
            Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
            NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_TransferComplete;)
            //XXXXXXXXXXXX Virtualization exposure (Rare): The endpoint can still accept packets, but
            //XXXXXXXXXXXX there's no Transfer! Perhaps... Virtualize the EP (or just set NAK OUT Packets?); if packets happened to
            //XXXXXXXXXXXX arrive before virtualization, return a code and set EP to locked (permanently?); 
            //XXXXXXXXXXXX otherwise, Success..? (Client completion should start another transfer if not Success.)
        }

        if (Endpoint->CompletionStatus != NCSTATUS_PENDING)
        {   // Transfer has completed
            //  - Completion may be due to success or error
            //  - Clean up and call client completion handler
            //
            // Virtulized endpoints: Record current state of NAK OUT Packets
            //  - Next transfer must be careful to clear NAK OUT Packets safely! (It 
            //    is unsafe for the next transfer to clear NAK OUT Packets if the
            //    endpoint is not specifically NAK'ing packets)
            //  - For convenience, use EP_RSP
            NC_VIRT_EP(Endpoint->Priv.EpRsp = NETCHIP_READ(EP_RSPSET);)

BufferTooSmall:
            NETCHIP_WRITE(EP_IRQENB, 0);
            Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;
            NC_STATISTIC(Endpoint->Priv.TotalBytesTransferred += Endpoint->BytesTransferred;)
            NC_STATISTIC(Endpoint->Priv.TotalTransfers++;)

            HISTO(DEFAULT_HISTORY, "RCmp", Endpoint->BytesTransferred, EpStat0, NETCHIP_READ(EP_STAT1));
            NCDEBUG(NETCHIP_WRITE(EP_STAT1, 
                (1<<LOCAL_OUT_ZLP) |                        // Info only
                (1<<USB_STALL_SENT) |                       // Info only
                (1<<USB_IN_NAK_SENT) |                      // Info only
                (1<<USB_IN_ACK_RCVD) |                      // Info only
                (1<<USB_OUT_NAK_SENT) |                     // Info only
                (1<<USB_OUT_ACK_SENT) |                     // Info only
                0);)

            // Call client completion routine
            //  - Client should return from this call as quickly as possible
            //  - Client may start another transfer on this or another endpoint
            Transfer->ClientCompletionHandler(Endpoint);
        }
    }
    else
    {   // Transfer has not completed
        Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;
        HISTO(DEFAULT_HISTORY, "RPrt", Endpoint->BytesTransferred, EpStat0, 0);
        Transfer->PartialTransferHandler(Endpoint);

    }

    NC_LED2(FALSE);     // Turn RDK daughter board LED OFF
    // History Tip: If a client completion handler started a new transfer on this endpoint, 
    // this history entry reflects the new transfer, not the completed one!
    HISTO(DEFAULT_HISTORY, ")RxP", Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer, EpStat0, Endpoint->Priv.BytesRemaining);
}

///////////////////////////////////////////////////////////////////////////////
void
TxPacketsPio(
    PNC_ENDPOINT_OBJECT Endpoint
    );

///////////////////////////////////////////////////////////////////////////////
void
TxFinalPio(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Handle final packets of USB IN (Tx) transfer
    //  - The final packets of the transfer were written to the endpoint
    //  - Now handle the host actually taking those packets
    //  - Tip: There is a small possibility that a corrupted ACK handshake could
    //    prevent firmware from immediately recognizing that the final Tx packet 
    //    has been taken by the host. See USB 2.0: 8.6.4
    PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;
    BYTE EpBuffStates;

    ASSERT(Endpoint->Priv.PhysEp != EP0);
    NETCHIP_WRITE(PAGESEL, Endpoint->Priv.PhysEp);

    // Arm endpoint for Data Packet Transmitted Interrupt
    NETCHIP_WRITE(EP_STAT0, 
        (1<<DATA_PACKET_TRANSMITTED_INTERRUPT) |    // Required
        (1<<DATA_IN_TOKEN_INTERRUPT) |              // Required (for Token Notification)
        0);

    EpBuffStates = NETCHIP_READ(EP_BUFF_STATES);
    HISTO(DEFAULT_HISTORY, "TFin", NCHISTO_TRANSFER(Endpoint), EpBuffStates, NETCHIP_READ(EP_STAT0));

    switch(EpBuffStates)
    {
    case BUFF_FREE<<BUFFER_A_STATE | BUFF_LCL<<BUFFER_B_STATE:
    case BUFF_FREE<<BUFFER_B_STATE | BUFF_LCL<<BUFFER_A_STATE:
        // USB host has taken the final IN packets of the transfer
        //  - This transfer is really really done
        NETCHIP_WRITE(EP_IRQENB, 0);
        Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;
        NC_STATISTIC(Endpoint->Priv.TotalBytesTransferred += Endpoint->BytesTransferred;)
        NC_STATISTIC(Endpoint->Priv.TotalTransfers++;)
        Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
        NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_Instant;)
        HISTO(DEFAULT_HISTORY, "TCmp", NCHISTO_TRANSFER(Endpoint), NETCHIP_READ(EP_STAT0), Endpoint->BytesTransferred);

        // Restore normal Tx packet handler
        //  - CRITICAL NOTE: The value in PIO Packet Handler is used as a 
        //    flag by the Reassign Best routine to indicate that the final 
        //    packets *may* need to be handled. Now that the final packets *have* 
        //    been handled, we clear the flag by reverting back to the normal Tx 
        //    packet handler:
        Endpoint->Priv.PioPacketHandler = TxPacketsPio;

        // Call client's transfer completion handler
        //  - Client should return from this call as quickly as possible
        //  - Client's completion routine may start another transfer on this
        //    endpoint. If that happens, packets will get preloaded into the
        //    endpoint. Virtualization must be considered (i.e. its possible 
        //    that we are completing a transfer on an endpoint that has been 
        //    virtualized.)
        Transfer->ClientCompletionHandler(Endpoint);

        break;
    default:
        // Final packet has not been taken by the host
        NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_SomeBytesTransferred;)
        break;
    }
}

///////////////////////////////////////////////////////////////////////////////
void
TxPacketsPio(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Transmit packets (USB IN) using programmed I/O method
    //  - Fill endpoint with as many USB packets as possible until:
    //     - No more endpoint buffers available (endpoint buffers full)
    //     - Client request fulfilled (all requested bytes transferred)
    //  - This method cannot be applied to Endpoint Zero Transfers (i.e Control Reads)
    // NetChip Porting guide: Port this section very carefully. It should be ported
    // without functional changes. It has been carefully designed and fully tested 
    // to ensure safe and reliable operation over a wide variety of conditions. If
    // you experience problems with this section, please contact NetChip.
    PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;
    PNET2272_EP_DATA pTxBuf = (PNET2272_EP_DATA)Endpoint->Priv.pPkt;

    ASSERT(Transfer != NULL);
    ASSERT(Endpoint->Priv.PhysEp != EP0);
    NC_VIRT_EP(ASSERT(!Endpoint->Priv.Virtualized);)

    NETCHIP_WRITE(PAGESEL, Endpoint->Priv.PhysEp);
    HISTO(DEFAULT_HISTORY, "TxP(", NCHISTO_TRANSFER(Endpoint), pTxBuf, Endpoint->Priv.BytesRemaining);
    ASSERT(Endpoint->CompletionStatus == NCSTATUS_PENDING);
    ASSERT(NETCHIP_READ(EP_CFG) & (1<<ENDPOINT_DIRECTION));

    // Enable only Data Packet Transmitted interrupt (disabling Data IN Token Interrupt)
    //  - Data IN Token Interrupt Enable is set by API to interrupt on the host's 
    //    request to *start* a transfer). For the rest of the transfer, interrupt 
    //    on Data Packet Transmitted:
    NETCHIP_WRITE(EP_IRQENB, (1<<DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE));
    NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_SomeBytesTransferred;)

    for (;;)
    {   // Continue loading the endpoint until:
        //  - The final packet gets loaded into the endpoint
        //  - The endpoint has no available space
        NCBYTE EpStat0;
        WORDBYTE EpAvail;

⌨️ 快捷键说明

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