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

📄 usb20hw.c

📁 printer usb
💻 C
📖 第 1 页 / 共 4 页
字号:

            /* Return if it worked this time */
            if (ENDPOINT_PRIMED(ep_index)) {
                USB_INTS_ON;
                return USB_OK;
            }
        }

        /*
         * If the endpoint is not primed but the next-dTD pointer is
         * not terminal, then we have hardware problems.
         */
        USB_ForceReset = RESET_HW;
    }

    USB_INTS_ON;
    return USB_OK;
}

/**************************************************************************
*
*  Function Name  : USB_init_endpoint
*  Returned Value : None
*  Comments       :
*    Initializes the endpoint and the data structures associated with the
*    endpoint.
*
**************************************************************************/
void USB_init_endpoint(Uint16 ep_index, Uint16 max_pkt_size,
                       Uint8 type, Uint8 zero_length_packet_flag)
{
    dQH_STRUCT *ep_queue_head_ptr;

    USB_ASSERT(!usb_state.EP_INIT[ep_index]);
    USB_ASSERT(EP_NUM(ep_index) == 0 || !usb_state.EP_DTD_HEADS[ep_index]);
    USB_ASSERT(type != USB_CONTROL_ENDPOINT || zero_length_packet_flag == 0);

    /*
     * I have seen this occur due to plugging and unplugging the USB cable.
     */
    if (!ENDPOINT_NOT_PRIMED(ep_index)) {
        USB_ForceReset = RESET_HW;
        return;
    }

    usb_state.EP_INIT[ep_index] = TRUE;

    /* Get the endpoint queue head address. */
    ep_queue_head_ptr = usb_state.EP_QUEUE_HEAD_PTR + ep_index;

    /*
     * Set the max packet length and/or "Interrupt On Setup" (control only),
     * "Zero Length Termination Select" fields (non-control only).
     */
    ep_queue_head_ptr->MAX_PKT_LENGTH = max_pkt_size << 16;
    if (type == USB_CONTROL_ENDPOINT)
        ep_queue_head_ptr->MAX_PKT_LENGTH |= DTD_IOS;
    else if (zero_length_packet_flag)
        ep_queue_head_ptr->MAX_PKT_LENGTH |= DTD_ZERO_LEN_TER_SEL;

    /* Enable the endpoint for Rx or Tx. */
    if (EP_DIRECTION(ep_index)) {
        /* transmit */
        usb_opreg->ENDPTCTRLX[EP_NUM(ep_index)] |= TX_ENABLE|(type<<TX_T_SHFT);
    } else {
        /* receive */
        usb_opreg->ENDPTCTRLX[EP_NUM(ep_index)] |= RX_ENABLE|(type<<RX_T_SHFT);
    }
}

/**************************************************************************
*
*  Function Name  : USB_ISR_deinit_endpoint
*  Returned Value : TRUE if caller must defer to task level
*  Comments       :
*    Flushes and disables the endpoint and the data structures associated
*    with the endpoint. Just return if pending hardware reset.
*
**************************************************************************/
void USB_ISR_deinit_endpoint(Uint16 ep_index)
{
    dDT_STRUCT *dTD, *next_dTD;
    Uint32 endpoint_bit, i;

    if (USB_ForceReset)
        return;

    endpoint_bit = EP_REGBIT(ep_index);

    /*
     * Starting at the head dTD, follow down the chain terminating all
     * of the dTD transfers in progress and/or queued.
     */
    dTD = usb_state.EP_DTD_HEADS[ep_index];
    while (dTD) {
        dTD->NEXT |= DTD_TERM_BIT;
        dTD->SIZE_IOC_STS = 0;
        dTD = (dDT_STRUCT *)(dTD->NEXT & ~DTD_TERM_BIT);
    }

    /*
     * Flush this endpoint:
     * NOTE: There is a caveat in the manual that flushing may take a
     * large amount of time. Since we should not be flushing with a
     * request in progress, this indicates trouble. Give up immediately
     * if its taking time to flush; defer to a task level reset.
     */
    for (i = 0; i < HW_LOOP_CNT; i++) {
        usb_opreg->ENDPTFLUSH = endpoint_bit;
        /* Wait until this bit is reset. */
        if (!(usb_opreg->ENDPTFLUSH & endpoint_bit))
            break;
    }
    if ((usb_opreg->ENDPTPRIME | usb_opreg->ENDPTSTATUS) & endpoint_bit) {
        USB_ForceReset = RESET_SW;
        return;
    }

    /* Return the dTDs to the pool. */
    dTD = usb_state.EP_DTD_HEADS[ep_index];
    while (dTD) {
        next_dTD = (dDT_STRUCT *)(dTD->NEXT & ~DTD_TERM_BIT);
        dTD->NEXT = (Uint32)usb_state.DTD_POOL;
        usb_state.DTD_POOL = dTD;
        dTD = next_dTD;
    }

    /* Disable the endpoint for Rx/Tx and reset the endpoint type. */
    if (EP_DIRECTION(ep_index)) {
        /* transmit */
        usb_opreg->ENDPTCTRLX[EP_NUM(ep_index)] &= VUSB_EPCTRL_TX_EP_MASK;
    } else {
        /* receive */
        usb_opreg->ENDPTCTRLX[EP_NUM(ep_index)] &= VUSB_EPCTRL_RX_EP_MASK;
    }

    usb_state.EP_INIT[ep_index] = FALSE;
    usb_state.EP_DTD_HEADS[ep_index] = NULL;
}

/**************************************************************************
*
*  Function Name  : USB_chip_and_data_base_initialize
*  Returned Value : None
*  Comments       :
*    Initializes the USB device controller.
*
**************************************************************************/
static void USB_chip_and_data_base_initialize(void)
{
    dDT_STRUCT *dTD;
    Uint32 i;

    /* Don't process a reset interrupt at ISR level while we are in here. */
    USB_ForceReset = RESET_HW;

#if RESET_PWR_CYCLE
    if (USB_Hard_Reset) {
        *(volatile Uint32 *)USBCTR &= ~1;
        PSPRINTF("HARDWARE USB CHIP RESET\n");
        TASKSLEEP_MILLISECONDS(500);
    }
#endif

    /* Disable the controller. */
    usb_opreg->USB_CMD = 0;

    /* Zero out the Endpoint queue heads. */
    BZERO(usb_state.EP_QUEUE_HEAD_PTR, 2*USB_MAX_ENDPOINTS*sizeof(dQH_STRUCT));

    /* Zero out the device transfer descriptors. */
    BZERO(usb_state.DTD_ALIGNED_BASE_PTR, DTD_POOL_CNT*sizeof(dDT_STRUCT));

    /*
     * Zero out the endpoint transaction descriptor heads. (Tail is
     * "don't care" if head is null.)
     */
    BZERO(usb_state.EP_DTD_HEADS, 2*USB_MAX_ENDPOINTS*sizeof(dDT_STRUCT*));

    /* Make sure the 16 MSBs of this register are 0s. */
    usb_opreg->ENDPT_SETUP_STAT = 0;

    /* Program the controller to be a USB "device" controller. */
    usb_opreg->USB_MODE = (Uint32)VUSB_MODE_CTRL_MODE_DEV;

    for (i = 0; i < 2 * USB_MAX_ENDPOINTS; i++) {
        /* Initialize all device queue heads. */
        usb_state.EP_QUEUE_HEAD_PTR[i].NEXT_DTD_PTR = DTD_TERM_BIT;

        /* Initially no endpoints are initialized. */
        usb_state.EP_INIT[i] = FALSE;
    }

    /* Configure the Endpoint List Address. */
    usb_opreg->EP_LIST_ADDR = (Uint32)usb_state.EP_QUEUE_HEAD_PTR;

    /* Enqueue all the dTDs into the free pool. */
    usb_state.DTD_POOL = NULL;
    dTD = usb_state.DTD_ALIGNED_BASE_PTR;
    for (i = 0; i < DTD_POOL_CNT; i++, dTD++) {
        /* Move the dTD to the free dTD pool. */
        dTD->NEXT = (Uint32)usb_state.DTD_POOL;
        usb_state.DTD_POOL = dTD;
    }

    /* Initialize the endpoint 0 properties. */
    usb_opreg->ENDPTCTRLX[0] = VUSB_EPCTRL_TX_DATA_TOGGLE_RST |
                               VUSB_EPCTRL_RX_DATA_TOGGLE_RST;

#if RESET_PWR_CYCLE
    if (USB_Hard_Reset) {
        *(volatile Uint32 *)USBCTR |= 0x61;
        USB_Hard_Reset = FALSE;
    }
#endif

    /* Enable interrupts. */
    usb_opreg->USB_INTR = VUSB_INTERRUPT_BITS;

    /* Set the Run bit in the command register. */
    usb_opreg->USB_CMD = VUSB_CMD_RUN_STOP;

    /* In case we stopped due to hardware hang, flush endpoints. */
    for (i = 0; i < HW_LOOP_LIMIT; i++) {
        usb_opreg->ENDPTFLUSH = 0xffffffff;
        /* Wait until this bit is reset. */
        if (!(usb_opreg->ENDPTFLUSH & 0xffffffff))
            break;
    }

    /* Initialize endpoint 0 in both directions. */
    USB_init_endpoint(EP0_RECV, EP0_PKT_SIZE, USB_CONTROL_ENDPOINT, 0);
    USB_init_endpoint(EP0_SEND, EP0_PKT_SIZE, USB_CONTROL_ENDPOINT, 0);

    USB_ForceReset = NO_RESET;
}

/**************************************************************************
*
*  Function Name  : USB_ISR_process_tr_complete
*  Returned Value : None
*  Comments       :
*    Service transaction-complete interrupt.
*
**************************************************************************/
static void USB_ISR_process_tr_complete(void)
{
    dDT_STRUCT *dTD, *next_dTD;
    Uint32 endpt_bits, tbit;
    Uint16 ep, ep_index;

    while (usb_opreg->ENDPT_SETUP_STAT | usb_opreg->ENDPTCOMPLETE) {
        /*
         * We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE because
         * the setup packets are to be read ASAP.
         *
         * First process all Setup packets received.
         */
        endpt_bits = usb_opreg->ENDPT_SETUP_STAT;

        /* We only support Endpoint 0 control endpoint. */
        USB_ASSERT((endpt_bits & ~1) == 0);
        if (endpt_bits & 1) {
            SETUP_STRUCT *p;
            int n;

            /*
             * Copy the Setup data from the 8-byte setup
             * buffer to setup structure.
             */
            p = (SETUP_STRUCT *)&usb_state.EP_QUEUE_HEAD_PTR->SETUP_BUFFER;

            usb_setup.REQUESTTYPE = p->REQUESTTYPE;
            usb_setup.REQUEST     = p->REQUEST;
            usb_setup.INDEX       = p->INDEX;
            usb_setup.VALUE       = p->VALUE;
            usb_setup.LENGTH      = p->LENGTH;

            /* Clear the bit in the ENDPTSETUPSTAT register for Endpoint 0. */
            usb_opreg->ENDPT_SETUP_STAT = 1;

            /* Hang for up to 200 usecs. for SetupStatus to clear */
            for (n = 0; n < 40; n++) {
                Uint32 t0;

                if (!(usb_opreg->ENDPT_SETUP_STAT & 1))
                    break;

                t0 = *(unsigned volatile int *)HRTCNTL0;
                while (*(unsigned volatile int *)HRTCNTL0 - t0 < 5*133)
                    ;
            }
            if (n >= 40) {
                /* Something is wrong; force a hardware reset */
                USB_ForceReset = RESET_HW;
                return;
            }
            USBserviceEP[0](0, TRUE, 8);
        }

        /* Process non-setup transaction-complete interrupts. */
        endpt_bits = usb_opreg->ENDPTCOMPLETE;
        if (endpt_bits) {
            /* Clear the bits in the register. */
            usb_opreg->ENDPTCOMPLETE = endpt_bits;

            /* Test each endpoint for both IN and OUT directions. */
            for (ep_index = 0; endpt_bits; ep_index++) {
                tbit = 1 << ((ep_index >> 1) + 16*(ep_index & 1));
                if (endpt_bits & tbit) {
                    endpt_bits &= ~tbit;
                    ep = EP_NUM(ep_index);

                    /* Get the first dTD for this endpoint. */
                    dTD = usb_state.EP_DTD_HEADS[ep_index];

                    /* Process all the dTDs that are done. */
                    while (dTD) {
                        /* Break out if this and remaining dTDs still active. */
                        if (dTD->SIZE_IOC_STS & DTD_STATUS_ACTIVE) {
                            /*
                             * Possible hardware failure here.  See if the
                             * first dTD on the head chain has already been
                             * processed but not set inactive.
                             */

                            if ((usb_state.EP_QUEUE_HEAD_PTR + ep_index)
                                              ->CURR_DTD_PTR == dTD->NEXT)
                            {
                                dTD->SIZE_IOC_STS = (dTD->SIZE_IOC_STS &
                                                     0xffff0000) | 0x8000;
                            }
                            else
                                break;
                        }

                        /*

⌨️ 快捷键说明

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