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

📄 ncdevice.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
        // Validate test packet
        NETCHIP_WRITE(EP_TRANSFER0, 0);
    }
}

///////////////////////////////////////////////////////////////////////////////
// Setup Request Packet support routines
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Control transfer support:
//  - Setup packet phase
//  - Data phase
//     - Control Read (USB IN)
//     - Control Write (USB OUT))
//  - Status phase
//  - See USB 2.0 8.5.3
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
#define TIMEOUT_CATCHER TRUE        // TRUE: Enable and show packet transfer timeouts
// The timeout catcher can expose marginal signal quality issues. If you experience 
// lots of timeouts, you may need to investigate your USB signal quality:
//  - Circuit board layout
//  - Power and ground
//  - Recommendation: Contact NetChip for layout assistance *before* building 
//    your first PCBs

///////////////////////////////////////////////////////////////////////////////
STATIC void
EpZero_RxPackets(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Receive packets on Endpoint Zero (Control Write data phase)
    //  - The host may start the status phase ANY TIME after any data phase OUT data packet
    //  - The status phase starts with IN tokens (See USB 8.5.3)
    //  - Status phase IN tokens cause endpoint zero to switch to an IN endpoint. Endpoint 
    //    zero registers may therefore read back unexpected IN endpoint content
    //  - Because of the status phase switch, after the final byte of the Control Write
    //    is read from endpoint, registers should not be written or read (they may not
    //    act as expected!)

    // NetChip Porting guide: Port this section 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.

#pragma message(_NC_MESSAGE"EpZero_RxPackets(): Control Write routine may not be needed")
    // This routine may not be needed: Standard USB "Chapter 9" requests do not require
    // Control Write with data phase support, nor do many class devices. If your device 
    // does not require Control Writes with a data phase this routine and its references, 
    // can probably be removed without consequence.

    PNET2272_EP_DATA pRxBuf = (PNET2272_EP_DATA)Endpoint->Priv.pPkt;
    NCBYTE EpStat0;
    WORDBYTE EpAvail;

    ASSERT(NETCHIP_READ(PAGESEL) == EP0);
    HISTO(DEFAULT_HISTORY, "RxP(", 0, pRxBuf, Endpoint->Priv.BytesRemaining);
    ASSERT(Endpoint->CompletionStatus == NCSTATUS_PENDING);
    ASSERT(Endpoint->Transfer->TransferSize >= WLENGTH);    // Client buffer must be large enough for host's transfer!

    // Enable interrupts required for Endpoint Zero Rx transfer (disabling all others)
    //  - Other interrupt enables may have been set by standard transfer API routine, but
    //    they do not apply to this transfer
    NETCHIP_WRITE(EP_IRQENB, (1<<DATA_PACKET_RECEIVED_INTERRUPT_ENABLE));

    do
    {
#if TIMEOUT_CATCHER && _NCDEBUG
        if (NETCHIP_READ(EP_STAT1) & (1<<TIMEOUT))
        {   // A USB timeout has occurred
            NCPRINTF(VOLUME_LOW, ("RxPacketsPio(): Warning: Timeout detected on USB EP:%2.2x\n", Endpoint->Priv.PhysEp));
            NETCHIP_WRITE(EP_STAT1, 1<<TIMEOUT);
        }
#endif


        EpAvail.Byte[MYEND_LO] = NETCHIP_READ(EP_AVAIL0);
        EpAvail.Byte[MYEND_HI] = NETCHIP_READ(EP_AVAIL1);
        ASSERT(EpAvail.Word <= Endpoint->Priv.EpMaxPkt.Word);
        ASSERT(Endpoint->Priv.BytesRemaining >= EpAvail.Word);

        if (EpAvail.Word == 0)
        {   // No data available in endpoint buffer
            HISTO(DEFAULT_HISTORY, "NoAv", 0, NETCHIP_READ(EP_STAT0), 0);
            break;
        }

        // We are now committed to copying data from the endpoint
        //  - There is data in the endpoint to be transferred
        //  - There is space available in system memory to put that data
        NC_LED1(TRUE);      // Turn RDK daughter board LED ON

        // Re-arm endpoint for another interrupt
        NETCHIP_WRITE(EP_STAT0,
            (1<<DATA_PACKET_RECEIVED_INTERRUPT) |   // Required
            (1<<DATA_OUT_TOKEN_INTERRUPT) |         // Info only
            0);

        // Transfer accounting
        Endpoint->Priv.pPkt += EpAvail.Word;
        Endpoint->Priv.BytesRemaining -= EpAvail.Word;
        HISTO(DEFAULT_HISTORY, "RxCp", EpAvail.Word, NETCHIP_READ(EP_STAT0), Endpoint->Priv.BytesRemaining);
        ASSERT(Endpoint->Priv.BytesRemaining >= 0);

#if NET2272_16BIT
        // Recalculate loop counter for 16 bit accesses
        EpAvail.Word = (USHORT)((EpAvail.Word + 1)>>1);
#endif
        // Copy bytes to memory from endpoint
        //  - For best performance, this loop should be optimized and written in assembler
        ASSERT((EpAvail.Word == 0) || (pRxBuf != NULL));
        while(EpAvail.Word--) 
        {
            *(pRxBuf++) = NETCHIP_BASEADDRESS[EP_DATA].NcReg;
        }

        if (Endpoint->Priv.BytesRemaining == 0)
        {   // Control Write is complete
            //  - Exit loop without reading or writing endpoint registers. If the status
            //    phase starts after the final byte of the packet is read from EP_DATA, 
            //    the endpoint can switch from OUT to IN, possibly causing unexpected 
            //    results for some register reads and writes. These registers and bits 
            //    are known to cause problems:
            //     - EP_AVAIL
            //     - EP_TRANSFER
            //     - NAK OUT Packets
            //     - Buffer Empty
            Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
            HISTO(DEFAULT_HISTORY, "BR=0", NETCHIP_READ(EP_CFG), NETCHIP_READ(EP_STAT0), 0);
            break;
        }   

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

    // Clear Endpoint Transfer registers:
    //  - These registers represent the number of bytes in the endpoint. However
    //    if these registers contain non-zero values on a subsequent Control Read,
    //    the endpoint will erroneously use the values as a pre-validation count.
    //    That is, for the next Control Read, the host may erroneously get the 
    //    number of bytes specified by these Endpoint Transfer registers!)
    //  - The Endpoint Transfer registers *must* be cleared before the status phase
    //    can be allowed to start.
    ASSERT(NETCHIP_READ(EP_RSPSET) & (1<<CONTROL_STATUS_PHASE_HANDSHAKE));

    NETCHIP_WRITE(EP_TRANSFER2, 0);
    NETCHIP_WRITE(EP_TRANSFER1, 0);
    NETCHIP_WRITE(EP_TRANSFER0, 0);

    NC_LED1(FALSE);     // Turn RDK daughter board LED OFF
    HISTO(DEFAULT_HISTORY, ")RxP", Endpoint->Priv.pPkt - (PBYTE)Endpoint->Transfer->TransferBuffer, NETCHIP_READ(EP_STAT0), Endpoint->Priv.BytesRemaining);
}

///////////////////////////////////////////////////////////////////////////////
STATIC void
EpZero_TxPackets(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Transmit packets on Endpoint Zero (Control Read data phase)
    //  - The host may start the status phase ANY TIME after reading a data phase packet
    //  - A Control Read status phase starts with an OUT token (See USB 8.5.3)
    //  - Status phase OUT tokens cause Endpoint Zero to switch to an OUT endpoint. Endpoint 
    //    zero registers may therefore read back unexpected OUT endpoint content!
    //  - Because of the status phase switch, after the final byte of the Control Read 
    //    is written to the endpoint (or validated, if not a Max Packet Multiple) endpoint
    //    registers should not be written or read (they may read confounding values!)

    // NetChip Porting guide: Port this section carefully. It should be ported without
    // adding 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.
    PNET2272_EP_DATA pTxBuf = (PNET2272_EP_DATA)Endpoint->Priv.pPkt;
    NCDEBUG(PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;)

    HISTO(DEFAULT_HISTORY, "TxP(", 0, pTxBuf, Endpoint->Priv.BytesRemaining);
    ASSERT(NETCHIP_READ(PAGESEL) == EP0);
    ASSERT(Endpoint->CompletionStatus == NCSTATUS_PENDING);
    ASSERT((ULONG)(
       (NETCHIP_READ(EP_TRANSFER0)<<0) +
       (NETCHIP_READ(EP_TRANSFER1)<<8) +
       (NETCHIP_READ(EP_TRANSFER2)<<16)) > Endpoint->Priv.BytesRemaining);

    // Enable interrupts required for Endpoint Zero Tx transfer (disabling all others)
    //  - Other interrupt enables may have been set by standard transfer API routine, but
    //    they do not apply to this transfer
    NETCHIP_WRITE(EP_IRQENB, (1<<DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE));

    for (;;)
    {   // Continue loading the endpoint until:
        //  - The final packet gets loaded into the endpoint
        //  - The endpoint has no available space
        NCBYTE EpStat0;
        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, ("EpZero_TxPackets(): Warning: Timeout detected on USB EP:%2.2x\n", Endpoint->Priv.PhysEp));
            NETCHIP_WRITE(EP_STAT1, 1<<TIMEOUT);
        }
#endif

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

        EpStat0 = NETCHIP_READ(EP_STAT0);
        if (!(EpStat0 & (1<<BUFFER_EMPTY)))
        {   // Buffer not empty
            //  - There is no room in the endpoint for more data
            //  - We'll have to leave and wait for a packet to be taken (Data Packet 
            //    Transmitted Interrupt) before we can load more data into the endpoint
            HISTO(DEFAULT_HISTORY, "!Emt", EpStat0, NETCHIP_READ(EP_STAT0), 0);
            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
        LoopCount = ByteCount = min(Endpoint->Priv.EpMaxPkt.Word, Endpoint->Priv.BytesRemaining);

        // Transfer accounting
        Endpoint->Priv.BytesRemaining -= ByteCount;
        Endpoint->Priv.pPkt += ByteCount;
        HISTO(DEFAULT_HISTORY, "TxCp", ByteCount, EpStat0, 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 for 16 bit mode below...
        LoopCount >>= 1;
#endif

        // Copy bytes to endpoint
        //  - For best performance, this loop should be optimized, and written in assembler
        ASSERT((LoopCount == 0) || (pTxBuf != NULL));
        while (LoopCount--)
        {
            NETCHIP_BASEADDRESS[EP_DATA].NcReg = *(pTxBuf++);
        }

        if (Endpoint->Priv.BytesRemaining == 0)
        {   // No more bytes in this transfer
            //  - Handle Short Packet validation
#if NET2272_16BIT
            // NET2272 is being used in 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));

⌨️ 快捷键说明

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