| /*******************************************************************************
|
|
|
| This software file (the "File") is distributed by Marvell International Ltd.
|
| or its affiliate(s) under the terms of the GNU General Public License Version 2,
|
| June 1991 (the "License"). You may use, redistribute and/or modify this File
|
| in accordance with the terms and conditions of the License, a copy of which
|
| is available along with the File in the license.txt file or by writing to the
|
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
| or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
|
|
|
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
|
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
|
| DISCLAIMED. The GPL License provides additional details about this warranty
|
| disclaimer.
|
|
|
| (C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
|
| (C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
|
|
|
| *******************************************************************************/
|
|
|
| #include "usb/api/mvUsbDevApi.h" |
| #include "usb/device/mvUsbDevPrv.h" |
| |
| /*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 */ |
| |
| /* EOF */ |