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

📄 usb20hw.c

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

        /* Clear all the interrupts that occured. */
        usb_opreg->USB_STS = status;

        /*
         * Only process interrupt bits if we have not already invoked
         * the reset task, otherwise let it proceed without interference.
         */
        if (!USB_ForceReset && usb_state.USB_STATE != USB_STATE_POWER_ON) {
            /* Process reset. */
            if (status & VUSB_STS_RESET) {
#if RESET_PWR_CYCLE
                if (usb_state.USB_STATE == USB_STATE_CONFIG)
                    USB_Hard_Reset = TRUE;
#endif

                /* Deconfigure interface before reset. */
                USB_deconfigure_current_interface();

                /*
                 * Only reset in Interrupt Service Routine if deconfigure
                 * went OK.
                 */
                if (!USB_ForceReset)
                    USB_ISR_process_reset();
            }

            /* Process change of speed (if not also reset). */
            else if (status & VUSB_STS_PORT_CHANGE) {
                if (usb_opreg->PORTSCX[0] & VUSB_PORTSCX_PORT_HIGH_SPEED)
                    new_speed = USB_DEV_HIGH_SPEED;
                else
                    new_speed = USB_DEV_FULL_SPEED;

                if (usb_state.SPEED != new_speed) {
                    usb_state.SPEED = new_speed;
                    usb_state.USB_STATE = USB_STATE_DEFAULT;
                    USB_speed_change();
                }
            }

            /* Error count not currently used for anything. */
            if (status & VUSB_STS_ERR)
                usb_state.ERRORS++;

            /* I/O transfer complete. */
            if (status & VUSB_STS_INT)
                USB_ISR_process_tr_complete();

            /* Monitor change of suspend/resume. */
            if (usb_state.USB_SUSPEND != (status & VUSB_STS_SUSPEND)) {
                usb_state.USB_SUSPEND = status & VUSB_STS_SUSPEND;
                /*
                 * Call to "suspend/resume" routine can go here.
                 */
            }

            /* Start of USB frame: not currently enabled in VUSB_INTERRUPT_BITS */
            if (status & VUSB_STS_SOF) {
                /*
                 * Call to "Start of Frame" routine can go here; frame
                 * number is in "usb_opreg->USB_FRINDEX".
                 */
            }
        }
    }
    /*
     * Wake up USB reset/1248.4 task if appropriate.
     */
    if (USB_ForceReset)
        USB_WakeUpUSB_Task();

    *(unsigned long *)EXMSK1A |=  2;

    /* Clear bit in exception register. */
    *(Uint32 *)EXCLRA = (1 << USB_INTERRUPT_BIT);
}

extern tsSemaphore USBSemaphore;

void USB_WakeUpUSB_Task(void)
{
    Sint32 status;

    status = TaskSemSignal(USBSemaphore);
    USB_ASSERT(status >= 0);
}
#endif

/**************************************************************************
*
*  Function Name  : USB_ISR_io_request
*  Returned Value : None
*  Comments       :
*    Sends or receives data on a specified endpoint.
*
**************************************************************************/
void USB_ISR_io_request(Uint16 ep_index, Uint8 *buff_ptr, Uint16 size)
{
    dDT_STRUCT *dTD;
    dQH_STRUCT *ep_queue_head_ptr;

    /*
     * Endpoint must have been initialized already. If no request pending,
     * endpoint must not be primed!
     */
    USB_ASSERT(size <= VUSB_EP_MAX_LENGTH_TRANSFER);
    USB_ASSERT(usb_state.EP_INIT[ep_index]);
    USB_ASSERT(usb_state.EP_DTD_HEADS[ep_index]||ENDPOINT_NOT_PRIMED(ep_index));

    /* Fatal error if the pool has no more descriptors left. */
    if (!usb_state.DTD_POOL) {
        USB_ForceReset = RESET_HW;
        return;
    }

    /* Allocate a transfer descriptor for this I/O request. */
    dTD = usb_state.DTD_POOL;
    if (!dTD) {
        USB_ForceReset = RESET_HW;
        USB_ForceReset = RESET_HW;
        USB_INTS_ON;
        return;
    }
    usb_state.DTD_POOL = (dDT_STRUCT *)dTD->NEXT;

    /* Initialize the new transfer descriptor. */
    dTD->LENGTH = size;
    dTD->NEXT = DTD_TERM_BIT;
    dTD->SIZE_IOC_STS = (size << 16) | DTD_IOC | DTD_STATUS_ACTIVE;

    /* Buffer page pointers are spaced 4K apart. */
    dTD->BUFF_PTR0 = (Uint32)buff_ptr;
    dTD->BUFF_PTR1 = (dTD->BUFF_PTR0 + 4096);
    dTD->BUFF_PTR2 = (dTD->BUFF_PTR1 + 4096);
    dTD->BUFF_PTR3 = (dTD->BUFF_PTR2 + 4096);
    dTD->BUFF_PTR4 = (dTD->BUFF_PTR3 + 4096);

    /*
     * If there was already and active request, its now safe to link this
     * new request onto the chain. If none, make this one the new HEAD.
     * New dTD always becomes the new TAIL.
     */
    if (usb_state.EP_DTD_HEADS[ep_index])
        usb_state.EP_DTD_TAILS[ep_index]->NEXT = (Uint32)dTD;
    else
        usb_state.EP_DTD_HEADS[ep_index] = dTD;
    usb_state.EP_DTD_TAILS[ep_index] = dTD;

    /* Check if the endpoint is not primed and has no bit set in ENDPTSTAT. */
    if (ENDPOINT_NOT_PRIMED(ep_index)) {
        int i;

        ep_queue_head_ptr = usb_state.EP_QUEUE_HEAD_PTR + ep_index;

        /* Give the hardware time to settle before giving up */
        for (i = 0; i < HW_LOOP_CNT; i++) {
            /* Check if no other transfers queued, i.e., this is first. */
            if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
                /*
                 * Make certain that the Endpoint Queue Head total-bytes
                 * count is accurate in the Transfer Overlay region. That
                 * is where we will monitor the progress of the packet
                 * reads and we don't want to think that data has been
                 * received when looking at leftover info from the last
                 * transfer.
                 */
                ep_queue_head_ptr->SIZE_IOC_INT_STS = size << 16;
                ep_queue_head_ptr->CURR_DTD_PTR = 0;
                ep_queue_head_ptr->NEXT_DTD_PTR = (Uint32)dTD;

                /* Prime the Endpoint and return if it worked. */
                usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
                if (ENDPOINT_PRIMED(ep_index))
                    return;
            }
        }

        /*
         * Prime didn't seem to work (Hardware bug?).  Keep trying.
         */
        for (i = 0; i < 6; i++) {
            Uint32 t0;

            /* OK if request finished right away */
            if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT)
                return;

            /* Prime the Endpoint again. */
            usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);

            /* Hang for up to 30 usecs. to avoid messing up scanner endpoint */
            t0 = *(unsigned volatile int *)HRTCNTL0;
            while (*(unsigned volatile int *)HRTCNTL0 - t0 < 5*133)
                ;

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

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

/**************************************************************************
*
*  Function Name  : USB_task_io_request
*  Returned Value : USB_OK or error code
*  Comments       :
*    Sends or receives data on a specified endpoint.
*
**************************************************************************/
Uint8 USB_task_io_request(Uint16 ep_index, Uint8 *buff_ptr, Uint16 size)
{
    dDT_STRUCT *dTD;
    dQH_STRUCT *ep_queue_head_ptr;

    /*
     * Endpoint 0 should never issue request from task level and only EP0
     * is allowed to have a null buffer and zero size.
     */
    USB_ASSERT(ep_index >= 2 && buff_ptr && size);
    USB_ASSERT(size <= VUSB_EP_MAX_LENGTH_TRANSFER);

    /*
     * Disable interrupts from USB so we won't conflict with ISR io requests;
     * check if endpoint initialized.
     */
    USB_INTS_OFF;
    if (!usb_state.EP_INIT[ep_index]) {
        USB_INTS_ON;
        return USBERR_EP_CLOSED;
    }

    /*
     * Now that we are assured that the ISR can not interrupt,
     * causing a reentrancy problem, issue the I/O request. This is
     * a copy of USB_ISR_io_request(), but for task calls.
     */

    /* If no request pending, endpoint must not be primed! */
    USB_ASSERT(usb_state.EP_DTD_HEADS[ep_index] ||
               ENDPOINT_NOT_PRIMED(ep_index));

    /*
     * Allocate a transfer descriptor for this I/O request. Fatal
     * error if the pool has no more descriptors left.
     */
    ARM_INTS_OFF;
    dTD = usb_state.DTD_POOL;
    if (!dTD) {
        USB_ForceReset = RESET_HW;
        USB_INTS_ON;
        return USBERR_EP_CLOSED;
    }
    usb_state.DTD_POOL = (dDT_STRUCT *)dTD->NEXT;
    ARM_INTS_ON;

    /* Initialize the new transfer descriptor. */
    dTD->LENGTH = size;
    dTD->NEXT = DTD_TERM_BIT;
    dTD->SIZE_IOC_STS = (size << 16) | DTD_IOC | DTD_STATUS_ACTIVE;

    /* Buffer page pointers are spaced 4K apart. */
    dTD->BUFF_PTR0 = (Uint32)buff_ptr;
    dTD->BUFF_PTR1 = (dTD->BUFF_PTR0 + 4096);
    dTD->BUFF_PTR2 = (dTD->BUFF_PTR1 + 4096);
    dTD->BUFF_PTR3 = (dTD->BUFF_PTR2 + 4096);
    dTD->BUFF_PTR4 = (dTD->BUFF_PTR3 + 4096);

    /*
     * If there was already and active request, its now safe to link this
     * new request onto the chain. If none, make this one the new HEAD.
     * New dTD always becomes the new TAIL.
     */
    if (usb_state.EP_DTD_HEADS[ep_index])
        usb_state.EP_DTD_TAILS[ep_index]->NEXT = (Uint32)dTD;
    else
        usb_state.EP_DTD_HEADS[ep_index] = dTD;
    usb_state.EP_DTD_TAILS[ep_index] = dTD;

    /* Check if the endpoint is not primed and has no bit set in ENDPTSTAT. */
    if (ENDPOINT_NOT_PRIMED(ep_index)) {
        int i;

        ep_queue_head_ptr = usb_state.EP_QUEUE_HEAD_PTR + ep_index;

        /* Give the hardware time to settle before giving up */
        for (i = 0; i < HW_LOOP_CNT; i++) {
            /* Check if no other transfers queued, i.e., this is first. */
            if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
                /*
                 * Make certain that the Endpoint Queue Head total-bytes
                 * count is accurate in the Transfer Overlay region. That
                 * is where we will monitor the progress of the packet
                 * reads and we don't want to think that data has been
                 * received when looking at leftover info from the last
                 * transfer.
                 */
                ep_queue_head_ptr->SIZE_IOC_INT_STS = size << 16;
                ep_queue_head_ptr->CURR_DTD_PTR = 0;
                ep_queue_head_ptr->NEXT_DTD_PTR = (Uint32)dTD;

                /* Prime the Endpoint and return if it worked. */
                usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
                if (ENDPOINT_PRIMED(ep_index)) {
                    USB_INTS_ON;
                    return USB_OK;
                }
            }
        }

        /*
         * Prime didn't seem to work (Hardware bug?).  Keep trying.
         */
        for (i = 0; i < 6; i++) {
            Uint32 t0;

            /* OK if request finished right away */
            if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
                USB_INTS_ON;
                return USB_OK;
            }

            /* Prime the Endpoint again. */
            usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);

            /* Hang for up to 30 usecs. to avoid messing up scanner endpoint */
            t0 = *(unsigned volatile int *)HRTCNTL0;
            while (*(unsigned volatile int *)HRTCNTL0 - t0 < 5*133)
                ;

⌨️ 快捷键说明

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