/*FUNCTION*---------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_is_endpoint_stalled * Returned Value : None * Comments : * Gets the endpoint status * *END*--------------------------------------------------------------------*/ uint_8 _usb_dci_vusb20_is_endpoint_stalled ( /* [IN] Handle to the USB device */ _usb_device_handle handle, /* [IN] Endpoint number */ uint_8 ep, /* [IN] Endpoint direction */ uint_8 dir ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; uint_32 value; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "is_endpoint_stalled\n"); usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; if(dir) { value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & (USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL)); } else { value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & (USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL)); } return (value) ? 1 : 0; } /* EndBody */
/*FUNCTION*------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_unstall_endpoint * Returned Value : None * Comments : * Unstall the specified endpoint in the specified direction * *END*-----------------------------------------------------------------*/ void _usb_dci_vusb20_unstall_endpoint ( /* [IN] the USB_dev_initialize state structure */ _usb_device_handle handle, /* [IN] the Endpoint number */ uint_8 ep_num, /* [IN] direction */ uint_8 direction ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; /* Enable the endpoint for Rx or Tx and set the endpoint type */ if(direction) { dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= USB_32BIT_LE(EHCI_EPCTRL_TX_DATA_TOGGLE_RST); dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= ~(USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL)); } else { dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= USB_32BIT_LE(EHCI_EPCTRL_RX_DATA_TOGGLE_RST); dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= ~(USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL)); } ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, "UNSTALL ep=%d %s: EPCTRLX=0x%x\n", ep_num, direction ? "SEND" : "RECV", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num])); } /* EndBody */
/*FUNCTION*------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_stall_endpoint * Returned Value : None * Comments : * Stalls the specified endpoint * *END*-----------------------------------------------------------------*/ void _usb_dci_vusb20_stall_endpoint ( /* [IN] the USB_dev_initialize state structure */ _usb_device_handle handle, /* [IN] the Endpoint number */ uint_8 ep_num, /* [IN] direction */ uint_8 direction ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; VUSB20_EP_QUEUE_HEAD_STRUCT _PTR_ ep_queue_head_ptr; usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; /* Get the endpoint queue head address */ ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 2*ep_num + direction; /* Stall the endpoint for Rx or Tx and set the endpoint type */ if (ep_queue_head_ptr->MAX_PKT_LENGTH & USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_IOS)) { /* This is a control endpoint so STALL both directions */ dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= USB_32BIT_LE((EHCI_EPCTRL_TX_EP_STALL | EHCI_EPCTRL_RX_EP_STALL)); } else { if(direction) { dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL); } else { dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL); } } /* Endif */ ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, "STALL ep=%d %s: EPCTRLX=0x%x, CURR_dTD=0x%x, NEXT_dTD=0x%x, SIZE=0x%x\n", ep_num, direction ? "SEND" : "RECV", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]), (unsigned)USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR), (unsigned)USB_32BIT_LE(ep_queue_head_ptr->NEXT_DTD_PTR), (unsigned)USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS)); } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_set_test_mode * Returned Value : None * Comments : * sets/resets the test mode * *END*--------------------------------------------------------------------*/ void _usb_dci_vusb20_set_test_mode ( /* [IN] Handle to the USB device */ _usb_device_handle handle, /* [IN] Test mode */ uint_16 test_mode ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; uint_32 temp; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ANY, "set_test_mode\n"); usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]); dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0] = USB_32BIT_LE((temp | EHCI_EPCTRL_TX_DATA_TOGGLE_RST)); if (test_mode == ARC_USB_TEST_MODE_TEST_PACKET) { USB_memcopy(test_packet, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH); _usb_device_send_data(handle, 0, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH); } /* Endif */ temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]); temp &= ~EHCI_PORTSCX_W1C_BITS; dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(temp | ((uint_32)test_mode << 8)); } /* EndBody */
/*FUNCTION*------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_assert_resume * Returned Value : None * Comments : * Resume signalling for remote wakeup * *END*-----------------------------------------------------------------*/ void _usb_dci_vusb20_assert_resume ( /* [IN] the USB_dev_initialize state structure */ _usb_device_handle handle ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; uint_32 temp; usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; /* Assert the Resume signal */ temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]); temp &= ~EHCI_PORTSCX_W1C_BITS; temp |= EHCI_PORTSCX_PORT_FORCE_RESUME; dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(temp); /* Port change interrupt will be asserted at the end of resume ** operation */ } /* EndBody */
/*FUNCTION*------------------------------------------------------------- * * Function Name : _usb_dci_vusb20_cancel_transfer * Returned Value : USB_OK or error code * Comments : * Cancels a transfer * *END*-----------------------------------------------------------------*/ uint_8 _usb_dci_vusb20_cancel_transfer ( /* [IN] the USB_dev_initialize state structure */ _usb_device_handle handle, /* [IN] the Endpoint number */ uint_8 ep_num, /* [IN] direction */ uint_8 direction ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; VUSB20_REG_STRUCT_PTR dev_ptr; VUSB20_EP_TR_STRUCT_PTR dTD_ptr, check_dTD_ptr; VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; XD_STRUCT_PTR xd_ptr; uint_32 temp, bit_pos; volatile unsigned long timeout, status_timeout; usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; bit_pos = (1 << (16 * direction + ep_num)); temp = (2*ep_num + direction); ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp; /* Unlink the dTD */ dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp]; if (dTD_ptr) { ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_cancel_count++)); check_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, ((uint_32)USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK)); if (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) { /* Flushing will halt the pipe */ /* Write 1 to the Flush register */ dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos); /* Wait until flushing completed */ timeout = 0x1000000; while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) { /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */ timeout--; if(timeout == 0) { USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, bit_pos=0x%x \n", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), (unsigned)bit_pos); break; } } /* EndWhile */ status_timeout = 0x100000; while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) { status_timeout--; if(status_timeout == 0) { USB_printf("USB Cancel: - TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), (unsigned)bit_pos); break; } /* Write 1 to the Flush register */ dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos); /* Wait until flushing completed */ timeout = 0x1000000; while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) { /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */ timeout--; if(timeout == 0) { USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), (unsigned)bit_pos); break; } } /* EndWhile */ } /* EndWhile */ } /* Endif */ /* Retire the current dTD */ dTD_ptr->SIZE_IOC_STS = 0; dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSBHS_TD_NEXT_TERMINATE); /* The transfer descriptor for this dTD */ xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; dTD_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, "cncl_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p, bit=0x%x\n", usb_dev_ptr->STATS.usb_cancel_count & 0xFFFF, USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), ep_num, direction ? "in" : "out", xd_ptr->WSTARTADDRESS, xd_ptr->WTOTALLENGTH, xd_ptr, dTD_ptr, check_dTD_ptr, bit_pos); /* Free the dTD */ _usb_dci_vusb20_free_dTD((pointer)dTD_ptr); /* Update the dTD head and tail for specific endpoint/direction */ if (!check_dTD_ptr) { usb_dev_ptr->EP_DTD_HEADS[temp] = NULL; usb_dev_ptr->EP_DTD_TAILS[temp] = NULL; if (xd_ptr) { xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; /* Free the transfer descriptor */ _usb_device_free_XD((pointer)xd_ptr); } /* Endif */ /* No other transfers on the queue */ ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE); ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; } else { usb_dev_ptr->EP_DTD_HEADS[temp] = check_dTD_ptr; if (xd_ptr) { if ((uint_32)check_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD != (uint_32)xd_ptr) { xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; /* Free the transfer descriptor */ _usb_device_free_XD((pointer)xd_ptr); } /* Endif */ } /* Endif */ if (USB_32BIT_LE(check_dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) { /* Start CR 1015 */ /* Prime the Endpoint */ dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos)) { timeout = 0x100000; while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos) { /* Wait for the ENDPTPRIME to go to zero */ timeout--; if(timeout == 0) { USB_printf("USB Cancel: - TIMEOUT for ENDPTPRIME=0x%x, bit_pos=0x%x\n", (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), (unsigned)bit_pos); break; } } /* EndWhile */ if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) { /* The endpoint was not not primed so no other transfers on ** the queue */ goto done; } /* Endif */ } else { goto done; } /* Endif */ /* No other transfers on the queue */ ep_queue_head_ptr->NEXT_DTD_PTR = (uint_32)USB_32BIT_LE((uint_32)check_dTD_ptr); ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; /* Prime the Endpoint */ dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); } /* Endif */ } /* Endif */ } /* Endif */ done: /* End CR 1015 */ return USB_OK; } /* EndBody */