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

📄 ncfwapi.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
        UINT ByteCount, LoopCount;

#if TIMEOUT_CATCHER && _NCDEBUG
        // Check for USB timeout error
        if (NETCHIP_READ(EP_STAT1) & (1<<TIMEOUT))
        {   // A USB timeout has occurred
            //  - At least one retry was required to get the data correctly
            //  - If you get a lot of timeout errors, you may want to check your signal quality
            NCPRINTF(VOLUME_LOW, ("TxPacketsPio(): Warning: Timeout detected on USB EP:%2.2x\n", Endpoint->Priv.PhysEp));
            NETCHIP_WRITE(EP_STAT1, 1<<TIMEOUT);
        }
#endif

        // Clear interrupt status
        //  - Tip: Leave Data IN Token Interrupt set for "self-interrupt" and concatenation
        NETCHIP_WRITE(EP_STAT0, (1<<DATA_PACKET_TRANSMITTED_INTERRUPT));

        EpStat0 = NETCHIP_READ(EP_STAT0);
        if (EpStat0 & 1<<BUFFER_FULL)
        {   // Buffer full:
            //  - There is no room in the endpoint for any more Tx data
            //  - Exit now and wait for a packet to be taken by the host. When that
            //    happens, a Data Packet Transmitted Interrupt will occur, then 
            //    there will be room in the endpoint for more data
            //  - Concatenation: Now that buffers are full, clear Data IN Token 
            //    interrupt to prevent self-interruption. (As packets are taken
            //    by the host, Data Packet Transmitted interrupts will get transfers
            //    going again)
            NETCHIP_WRITE(EP_STAT0, (1<<DATA_IN_TOKEN_INTERRUPT));
            Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;
            HISTO(DEFAULT_HISTORY, "TPrt", EpStat0, NETCHIP_READ(EP_STAT0), Endpoint->BytesTransferred);
            // Give client an opportunity to handle partial transfer
            //  - For instance, client may wish to queue more data from its hardware
            Transfer->PartialTransferHandler(Endpoint);
            break;
        }

        // We are now committed to loading data into the endpoint
        //  - There is data remaining to be transferred
        //  - There is space available in the endpoint to put that data
        NC_LED2(TRUE);      // Turn RDK daughter board LED ON

        // Determine how many bytes we can copy
        EpAvail.Byte[MYEND_LO] = NETCHIP_READ(EP_AVAIL0);
        EpAvail.Byte[MYEND_HI] = NETCHIP_READ(EP_AVAIL1);
        LoopCount = ByteCount = min(EpAvail.Word, Endpoint->Priv.BytesRemaining);
        
        //XXXXXXXXXXXXX FIX COMMENTS! ALSO APPLIES TO CONCATENATION!!!!!!!
        // Virtualization: Prepare for possible "endpoint save" due to virtualization
        //  - Record number of bytes that will be in the "last packet" of the endpoint. 
        //  - This value may be used by the virtualization section to account for unsent data
        Endpoint->Priv.LastPacketSize = (Endpoint->Priv.EpMaxPkt.Word - EpAvail.Word) + ByteCount;

        // Transfer accounting
        Endpoint->Priv.BytesRemaining -= ByteCount;
        Endpoint->Priv.pPkt += ByteCount;
        HISTO(DEFAULT_HISTORY, "TxCp", ByteCount, EpAvail.Word, Endpoint->Priv.BytesRemaining);

#if NET2272_16BIT
        // Recalculate loop counter for 16 bit accesses
        //  - Tip: If the Byte Count is an odd number of bytes (1, 3, 5, ...) LoopCount 
        //    will be calculated such that the last byte is not transferred in the 
        //    loop. The last byte is written in a special case below...
        LoopCount >>= 1;
#endif

#pragma message(_NC_MESSAGE"Recommendation: Optimize Tx copy loop in assembler")
        // Copy bytes to endpoint
        //  - For best performance, this loop should be optimized, and written in assembler
        ASSERT((LoopCount == 0) || (pTxBuf != NULL));   // NULL is OK e.g., for Token Notification
        while (LoopCount--)
        {
            NETCHIP_BASEADDRESS[EP_DATA].NcReg = *(pTxBuf++);
        }

        if (Endpoint->Priv.BytesRemaining == 0)
        {   // No more bytes in this transfer. Handle Short Packet validation issues
            //  - If the "Apply ZLP" flag is TRUE, then we will validate a short packet 
            //    for any transfer size. Otherwise, we will only validate a short packet
            //    if the transfer size is NOT an exact max packet multiple
            HISTO(DEFAULT_HISTORY, "ZByt", NCHISTO_TRANSFER(Endpoint), NETCHIP_READ(EP_STAT0), Transfer->TransferFlags);

            if (Transfer->TransferFlags & (
                (1<<NC_TRANSFER_FLAG_APPLY_CONCATENATION) | 
                (1<<NC_TRANSFER_FLAG_TOKEN_NOTIFICATION) |
                0))
            {   // Client is either requesting notification of an IN token, or doing concatenation
                //  - Transfer is complete. 
                //  - For concatenation, some number of bytes may still be left unvalidated 
                //    in the endpoint. The client should start another transfer from its
                //    completion handler to validate the unsent bytes.
                //  - If the endpoint holds an exact-packet multiple number of bytes, it 
                //    is automatically validated by the endpoint logic
                NETCHIP_WRITE(EP_IRQENB, 0);
                Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;
                if ((Endpoint->Priv.LastPacketSize % Endpoint->Priv.EpMaxPkt.Word) == 0)
                {   // Endpoint contains an exact-packet multiple
                    //  - Endpoint hardware automatically validates the packet
                    Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
                }
                else
                {   // Endpoint contains a partial packet
                    //  - Request is completing, but the partial packet is not being validated
                    //  - Partial packet is "stuck" in the endpoint
                    //  - The endpoint must remain locked (i.e. it cannot be reassigned) 
                    //    until partial packet is validated. This leads to potential deadlock!
                    //  - Client must take further action (i.e. issue another request) to
                    //    validate the partial packet. Recommendation: Client completion handler
                    //    should start another transfer request to validate the endpoint contents
                    Endpoint->CompletionStatus = NCSTATUS_PARTIAL_PACKET;
                    NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_Locked;)
                    ASSERT(Transfer->TransferFlags & ((1<<NC_TRANSFER_FLAG_TRANSFER_LOCK) | (1<<NC_TRANSFER_FLAG_ENDPOINT_LOCK)));
                }

                NC_STATISTIC(Endpoint->Priv.TotalBytesTransferred += Endpoint->BytesTransferred;)
                NC_STATISTIC(Endpoint->Priv.TotalTransfers++;)
                HISTO(DEFAULT_HISTORY, "TorC", NCHISTO_TRANSFER(Endpoint), NETCHIP_READ(EP_STAT0), Endpoint->BytesTransferred);
#if NET2272_16BIT
                // Assert: In 16 bit mode, cannot concatenate odd sizes
                ASSERT(!(ByteCount & 0x01));
#endif

                // Call client's transfer completion handler
                //  - Client should return from this call as quickly as possible
                //  - Client may start another transfer on this or another endpoint
                Transfer->ClientCompletionHandler(Endpoint);
                break;
            }

            if (
                (Transfer->TransferFlags & (1<<NC_TRANSFER_FLAG_APPLY_ZLP)) ||  // Apply ZLP? (Implies Apply Short Packet!)
                (ByteCount < Endpoint->Priv.EpMaxPkt.Word)                      // Not a Max Packet multiple?
                )
            {   // Transfer has a short packet (i.e. not a Max Packet multiple) or ZLP is to be applied
                WORDBYTE EpAvail;
                EpAvail.Byte[MYEND_LO] = NETCHIP_READ(EP_AVAIL0);
                EpAvail.Byte[MYEND_HI] = NETCHIP_READ(EP_AVAIL1);
                HISTO(DEFAULT_HISTORY, "SorZ", NCHISTO_TRANSFER(Endpoint), NETCHIP_READ(EP_STAT0), 0);

                if (EpAvail.Word == 0)
                {   // There is not enough buffer space in the endpoint for validating the final packet
                    //  - ZLP will be handled on next Packet Transmitted interrupt
                    HISTO(DEFAULT_HISTORY, "NoAv", 0, 0, 0);
                    // Assert: We should only get here if the transfer size is an exact-packet multiple
                    ASSERT((ByteCount % Endpoint->Priv.EpMaxPkt.Word) == 0);
                    break;
                }
#if NET2272_16BIT
                // 16 Bit Mode
                //  - If the transfer size is an odd number of bytes, change the NET2272 
                //    local bus width to 8 bit, write the last byte, then restore the 
                //    local bus width to 16 bit
                // Tip: If all USB IN transfers are guaranteed to be an even number of 
                // bytes (0, 2, 4, ...) then this section can be removed.
                if (ByteCount & (1<<0))
                {   // Transfer is an odd byte size (1, 3, 5, ...)
                    BYTE LocCtl = NETCHIP_READ(LOCCTL);
                    NETCHIP_WRITE(LOCCTL, LocCtl & ~(1<<DATA_WIDTH));
                    NETCHIP_BASEADDRESS[EP_DATA].NcReg = *(pTxBuf++);
                    NETCHIP_WRITE(LOCCTL, LocCtl);
                }
#endif

#if _NCVIRTUALENDPOINTS
                // ZLP and virtualization: Track ZLP in case the last one or two packets
                // of the transfer must be virtualized.
                //  - If virtualized endpoints are not being applied, this section can be removed
                if (Endpoint->Priv.LastPacketSize == Endpoint->Priv.EpMaxPkt.Word)
                {   // The transfer includes a ZLP
                    //  - If this transfer needs to be virtualized, the last packet is a ZLP
                    Endpoint->Priv.LastPacketSize = 0;
                }
#endif  // _NCVIRTUALENDPOINTS 

                // Post-validate partially-filled (or even empty) buffer:
                //  - Final bytes of the USB transfer have been written into the NET2272
                //    buffers. Validate the endpoint to allow the endpoint logic to send 
                //    a short (or zero length) packet:
                NETCHIP_WRITE(EP_TRANSFER0, 0);
            }

            // Change packet interrupt handler to handle the final packets being taken by the host
            Endpoint->Priv.PioPacketHandler = TxFinalPio;

            HISTO(DEFAULT_HISTORY, "TAll", Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer, NETCHIP_READ(EP_STAT0), 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);)

            break;
        }
    }

    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, ")TxP", Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer, NETCHIP_READ(EP_STAT0), Endpoint->Priv.BytesRemaining);
}

///////////////////////////////////////////////////////////////////////////////
void
Dma_InterruptHandler(
    void
    )
{   // DMA controller's interrupt handler
    NCPRINTF(VOLUME_MINIMUM, ("Dma_InterruptHandler(): DMA not implemented\n"));
    NCFAULT();
}


///////////////////////////////////////////////////////////////////////////////
void
Nc_InterruptHandler(
    void
    )
{   // When the NET2272 asserts its INT# pin, the system interrupt controller 
    // quickly transfers control here...
    // This section, and any function called from within it, is running in an interrupt context:
    //  - Many API functions are performance-tuned to run in an interrupt context. If
    //    the client chooses to call such a function outside of an interrupt context,
    //    an assert should be generated to serve as a warning. The developer may choose 
    //    to protect the section (e.g. disable interrupts), or restructure to call 
    //    the API from within a NetChip interrupt context.
    //  - For example, a client may wish to call the API Endpoint Halt routine from a
    //    non-interrupt context (or lower priority interrupt context); if a USB transfer 
    //    interrupt occurs on the same endpoint while the CPU is still in the API halt 
    //    routine, erroneous, unpredictable behavior is sure to occur.
    NCBYTE PhysEp;
    NCBYTE IrqStat0;
    UINT EndpointActivity = 0;
    PNC_ENDPOINT_OBJECT Endpoint;

    // Use USB frame as a timing mechanism for preventing virtualization of recently 
    // un-virtualized endpoints
    static BYTE OldFrame0;
    BYTE NewFrame0 = NETCHIP_READ(FRAME0);
    BOOL FramesSinceLastInterrupt = (OldFrame0 == NewFrame0)? FALSE: TRUE;

    ASSERT(!NcDebug_InterruptContext);
    NCDEBUG(NcDebug_InterruptContext = TRUE;)

    NCPRINTF(VOLUME_MAXIMUM, ("Nc_InterruptHandler(). . .\n"));
    HISTO(DEFAULT_HISTORY, "Int(", OldFrame0, NewFrame0, FramesSinceLastInterrupt);
    OldFrame0 = NewFrame0;

    // Handle physical data endpoint interrupts (one endpoint at a time, not including EP0)
    for (PhysEp = FIRST_PHYSICAL_ENDPOINT; PhysEp < PHYSICAL_ENDPOINT_COUNT; PhysEp++)
    {   // For all physical endpoints...
        IrqStat0 = NETCHIP_READ(IRQSTAT0);
        Endpoint = PhysicalEndpoints[PhysEp];
        ASSERT(Endpoint != NULL);

        HISTO(DEFAULT_HISTORY, "PhLp", NCHISTO_TRANSFER(Endpoint), 0, IrqStat0);

⌨️ 快捷键说明

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