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

📄 ncfwapi.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
    // This function malloc's memory for the USD:
    //  - BE SURE to free memory allocated by this function (use free())!
    //  - (The return pointer can be passed directly to free())
    UINT AsciiLen;
    PUSB_STRING_DESCRIPTOR Usd;
    PBYTE UsdText;
    UINT ii;

    if (AsciiStr == NULL)
    {   // No string to build!
        return NULL;
    }

    AsciiLen = strlen(AsciiStr);

    // Assert: Make sure string descriptor element sizes matches USB 2.0: 9.6.7
    ASSERT((sizeof(USB_STRING_DESCRIPTOR) == 2) && (sizeof(USHORT) == 2));

    // Determine length of USD (header plus wide string)
    ii = sizeof(USB_STRING_DESCRIPTOR) + (AsciiLen*sizeof(USHORT));

    // Get storage for USD (header plus string storage)
    Usd = (PUSB_STRING_DESCRIPTOR)MALLOC(ii);
    ASSERT(Usd);

    // Set USD header
    Usd->bLength = (BYTE)ii;            // USD length
    Usd->bDescriptorType = STRING_DESC; // USD type

    // Fill in wide string
    UsdText = (PBYTE)Usd + sizeof(USB_STRING_DESCRIPTOR);         // Point to first byte of text in USD
    for (ii = 0; ii < AsciiLen; ii++)
    {   // Fill in USB descriptor string
        *(UsdText++) = *(AsciiStr++);
        *(UsdText++) = 0;
    }

    return Usd;
}

///////////////////////////////////////////////////////////////////////////////
BOOL
FindDescriptor(
    PUSB_COMMON_DESCRIPTOR * pDescriptor,
    NCBYTE DescriptorType,
    PUSB_COMMON_DESCRIPTOR EndOfConfiguration
    )
{   // Search a configuration (starting at pDescriptor) for descriptor
    // matching the specified Descriptor Type
    //  - If successful, this function returns TRUE and the caller's Descriptor 
    //    reference refers to the matching descriptor
    //  - Returns FALSE if a matching descriptor type is not found
    //  - This function is expected to be called reiteratively. Since the first
    //    call is expected to be a Configuration (which is unlikely to be the 
    //    caller's requested descriptor type) the caller's work is simplified 
    //    by always skipping the first descriptor. That way, the caller can 
    //    simply call this function repeatedly (to find the next matching 
    //    descriptor) without having to manually advance to the next descriptor.
    ASSERT(EndOfConfiguration > *pDescriptor);
    for (;;)
    {
        // Current descriptor bLength cannot be zero
        //  - If bLength is zero, this loop will hang forever!
        ASSERT((*pDescriptor)->bLength != 0);

        // Get next descriptor
        *pDescriptor = (PUSB_COMMON_DESCRIPTOR)NEXT_USB_DESCRIPTOR(*pDescriptor);
        if (*pDescriptor >= EndOfConfiguration)
        {   // End of configuration: Did not find a match for requested Descriptor Type
            return FALSE;
        }
        
        if ((*pDescriptor)->bDescriptorType == DescriptorType)
        {   // Found descriptor matching caller's requested Descriptor Type
            return TRUE;
        }
    } 
}

///////////////////////////////////////////////////////////////////////////////
PNC_ENDPOINT_OBJECT
NcApi_FindUsbEp(
    NCBYTE UsbEp
    )
{   // Find a Endpoint Object matching the given USB endpoint 
    //  - Return NULL if not found
    NCBYTE LogicalEp;

    HISTO(DEFAULT_HISTORY, "Fnd<", UsbEp, 0, 0);
    if (UsbEp == EP0)
    {   // Endpoint zero
        return &LogicalEndpoints[EP0];
    }

    for (LogicalEp = 1; LogicalEp <= PrivDeviceObject->ConfigurationEndpointCount; LogicalEp++)
    {   // For all logical endpoints in the configuration...
        //  - Find an endpoint that matches the requested physical endpoint
        PNC_ENDPOINT_OBJECT Endpoint = &LogicalEndpoints[LogicalEp];
        if (Endpoint->EpDescriptor->bEndpointAddress == UsbEp)
        {   // Found match for caller's USB EP
            HISTO(DEFAULT_HISTORY, ">Fnd", NCHISTO_TRANSFER(Endpoint), 0, 0);
            return Endpoint;
        }
    }
    // No endpoint matching caller's USB endpoint found!
    HISTO(DEFAULT_HISTORY, "!Fnd", 0, 0, 0);
    return NULL;
}

///////////////////////////////////////////////////////////////////////////////
#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
//  - Contact NetChip support for help

///////////////////////////////////////////////////////////////////////////////
void
RxPacketsPio(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Receive packets (USB OUT) using programmed I/O method
    //  - Transfer as many USB packets to memory as possible until:
    //     - USB short packet received (terminates USB transfer)
    //     - No more USB packets available (endpoint buffer empty)
    //     - Client request fulfilled (all requested bytes transferred)
    //  - Usually called in an interrupt context when an endpoint's Data Packet 
    //    Received Interrupt is TRUE.
    //  - This method cannot be applied to Endpoint Zero Transfers (i.e Control Writes)
    // 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.
    BYTE EpStat0;
    WORDBYTE EpAvail;
    PNET2272_EP_DATA pRxBuf = (PNET2272_EP_DATA)Endpoint->Priv.pPkt;
    PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;

    ASSERT(Transfer != NULL);
    ASSERT(Endpoint->Priv.PhysEp != EP0);
    NETCHIP_WRITE(PAGESEL, Endpoint->Priv.PhysEp);
    HISTO(DEFAULT_HISTORY, "RxP(", NCHISTO_TRANSFER(Endpoint), pRxBuf, Endpoint->Priv.BytesRemaining);
    ASSERT(Endpoint->CompletionStatus == NCSTATUS_PENDING);

    // Virtualized endpoints: Assume some packets will be transferred
    NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_SomeBytesTransferred;)

    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

        EpStat0 = NETCHIP_READ(EP_STAT0);

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

        if (Transfer->TransferFlags & (1<<NC_TRANSFER_FLAG_TOKEN_NOTIFICATION))
        {   // Client requesting notification of OUT token
            //  - OUT token (plus at least one packet) has been received
            //  - Complete transfer now, carefully leaving data and status in the chip's endpoint
            //  - Report number of bytes currently in the buffer via Bytes Transferred (even
            //    though *zero* bytes have actually been transferred.)
            NETCHIP_WRITE(EP_IRQENB, 0);
            Endpoint->BytesTransferred = EpAvail.Word;
            Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
            HISTO(DEFAULT_HISTORY, "OTok", NCHISTO_TRANSFER(Endpoint), EpStat0, Endpoint->BytesTransferred);
            // Call client completion routine
            //  - Client should return from this call as quickly as possible
            //  - Client may start another transfer on this or another endpoint
            NETCHIP_WRITE(EP_STAT0, 1<<DATA_OUT_TOKEN_INTERRUPT);    // Required for next Token Notification
            Transfer->ClientCompletionHandler(Endpoint);
            return;
        }

        if (EpAvail.Word == 0)
        {   // No data available in endpoint buffer
            //  - Tip: A Zero Length OUT packet may be in the endpoint, and must be
            //    taken into account! (In this case Short Packet Transferred will be set)
            HISTO(DEFAULT_HISTORY, "NoAv", 0, EpStat0, NETCHIP_READ(EP_STAT0));
            
            break;
        }

        // Enough room in client's buffer for all data in the endpoint?
        if (Endpoint->Priv.BytesRemaining < EpAvail.Word)
        {   //  Data in endpoint exceeds client's remaining buffer space
            //  - Transfer as many bytes as possible
            //  - Care must be taken to NOT disturb endpoint buffer or status bits 
            //    so that a subsequent request can safely and accurately recover 
            //    remaining data from the endpoint, without data loss
            UINT Count = Endpoint->Priv.BytesRemaining;

            // Virtualized Endpoints: Upon completion, this endpoint will be in limbo:
            //  - The transfer will complete, meaning the Transfer Object is closed, 
            //    HOWEVER there will still be bytes in the endpoint!
            //  - The endpoint cannot be reassigned until all bytes are taken by the client!
            //  - Recommendation: The client completion routine should immediately start a new
            //    transfer to take remaining packets
            NC_VIRT_EP(Endpoint->Priv.SwapCandidate = SwapCandidate_Locked;)

            HISTO(DEFAULT_HISTORY, "Smal", 0, EpAvail.Word, Count);

#if NET2272_16BIT
            // Recalculate loop counter for 16 bit accesses
            //  - Restrict transfer size to an even number of bytes
            //  - An odd-size request leaves one or more bytes untaken from the endpoint. For
            //    example if request is for 5 bytes, 4 bytes are taken (2 words read from 
            //    endpoint), one or more bytes remain untaken in the endpoint
            Count &= ~1;                    // Restrict to even number of bytes
            Endpoint->Priv.pPkt += Count;   // Byte count
            Count >>= 1;                    // Loop count
#else
            Endpoint->Priv.pPkt += Count;
#endif

            // Copy bytes (or words) to memory from endpoint
            //  - For best performance, this loop should be optimized and written in assembler
            while (Count--) 
            {
                *(pRxBuf++) = NETCHIP_BASEADDRESS[EP_DATA].NcReg;
            }

            // Virtualized Endpoints: There are still bytes in the endpoint: 
            //  - Ensure a subsequent transfer will not erroneously clear NAK OUT Packets 
            //    by forcing NAK OUT Packets to appear FALSE
            //  - State of NAK OUT Packets is managed in EP_RSP:
            NC_VIRT_EP(Endpoint->Priv.EpRsp = 0;)

            // Complete transfer with a warning:
            //  - Call client completion handler
            //  - Tip: Bytes remain in endpoint, and *must* be taken by client soon!
            //  - Assert: For virtualized endpoints, locks must be set to prevent endpoint 
            //    from getting re-assigned. Tip: This assert may fire unexpectedly if 
            //    the Transfer Size is zero!
            ASSERT(Transfer->TransferFlags & ((1<<NC_TRANSFER_FLAG_TRANSFER_LOCK) | (1<<NC_TRANSFER_FLAG_ENDPOINT_LOCK)));
            Endpoint->CompletionStatus = NCSTATUS_PARTIAL_PACKET;
            goto BufferTooSmall;
        }

        // 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_LED2(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) |         // Required (for Token Notification)
            0);

⌨️ 快捷键说明

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