void _usb_device_free_XD
   (
      /* [IN] the dTD to enqueue */
      pointer  xd_ptr
   )
{ /* Body */
    int                         lockKey;
    USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
  
    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)(((XD_STRUCT_PTR)xd_ptr)->SCRATCH_PTR->PRIVATE);

    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "free_XD: xd_ptr=0x%x\n", (unsigned)xd_ptr);

    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.free_XD_count++));

   /*
   ** This function can be called from any context, and it needs mutual
   ** exclusion with itself.
   */

   lockKey = USB_lock();

   /*
   ** Add the XD to the free XD queue (linked via PRIVATE) and
   ** increment the tail to the next descriptor
   */
   USB_XD_QADD(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, (XD_STRUCT_PTR)xd_ptr);
   usb_dev_ptr->XD_ENTRIES++;

   USB_unlock(lockKey);

} /* 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 */
/*FUNCTION*-------------------------------------------------------------
*
*  Function Name  : _usb_device_send_data
*  Returned Value : USB_OK or error code
*  Comments       :
*        Sends data on a specified endpoint.
*
*END*-----------------------------------------------------------------*/
uint_8 _usb_device_send_data
   (
      /* [IN] the USB_USB_dev_initialize state structure */
      _usb_device_handle         handle,
            
      /* [IN] the Endpoint number */
      uint_8                     ep_num,
            
      /* [IN] buffer to send */
      uint_8_ptr                 buff_ptr,
            
      /* [IN] length of the transfer */
      uint_32                    size
   )
{ /* Body */
   int 	                        lockKey;
   uint_8                       error = 0;
   XD_STRUCT_PTR                xd_ptr;
   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
   boolean                      toSend = TRUE;

   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;

   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TX,
       "send_data: handle=%p, ep=%d, pBuf=0x%x, size=%d, EP_QH=%p\n", 
       handle, ep_num, (unsigned)buff_ptr, (int)size, usb_dev_ptr->EP_QUEUE_HEAD_PTR);

   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_send_count++));
      
   lockKey = USB_lock();

   if (!usb_dev_ptr->XD_ENTRIES) 
   {
      USB_unlock(lockKey);
      USB_printf("_usb_device_send_data, transfer in progress\n");
      return ARC_USB_STATUS_TRANSFER_IN_PROGRESS;
   } /* Endif */

#if defined(USB_UNDERRUN_WA)
    {
        int 			                head;
       	VUSB20_EP_QUEUE_HEAD_STRUCT* 	ep_queue_head_ptr;

		ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 
                       						                  2*ep_num + ARC_USB_SEND;

        if( ((ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF) > global_wa_threshold) 
        {
            /* Only Endpoints with maxPktSize more than 128 bytes need special processing */
            if( (size > global_wa_threshold) || 
                (usbSendQueue.num != 0) )
            {
/*
                USB_printf("_usb_device_send_data: ep_num=%d, maxPktSize=%d, size=%d\n",
                        ep_num, (ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF, size);
*/
                /* Check if usbSendQueue is not Full */
                if(usbSendQueue.num == MAX_XDS_FOR_TR_CALLS)
                {
                    USB_printf("ep=%d: usbSendQueue is FULL\n", ep_num);
                    USB_unlock(lockKey);
                    return USBERR_TX_FAILED;
                }

                /* Add to usbSendQueu */
                head = usbSendQueue.head;

                usbSendQueue.num++;
		        usbSendQueue.num_dma++;
                usbSendQueue.size[head] = size;
                usbSendQueue.buff_ptr[head] = buff_ptr;
                usbSendQueue.ep_num[head] = ep_num;

                head++;
                if(head == MAX_XDS_FOR_TR_CALLS)
                    head = 0;

                usbSendQueue.head = head;

                /* Process first usbSendQueue element if possible */
                if(usbSendQueue.num == 1)
                {
		            error = _usb_prepare_to_send(handle);
		        }
		        toSend = FALSE;
            }
        }
    }
#endif /* USB_UNDERRUN_WA */

    if(toSend == TRUE)
    {
        /* Get a transfer descriptor */
        USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr);

        usb_dev_ptr->XD_ENTRIES--;

        if(buff_ptr != NULL)
            USB_dcache_flush((pointer)buff_ptr, size);   

        /* Initialize the new transfer descriptor */      
        xd_ptr->EP_NUM = ep_num;
        xd_ptr->BDIRECTION = ARC_USB_SEND;
        xd_ptr->WTOTALLENGTH = size;
        xd_ptr->WSOFAR = 0;
        xd_ptr->WSTARTADDRESS = buff_ptr;   
        xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED;

        error = _usb_dci_vusb20_add_dTD(handle, xd_ptr);
    }
    USB_unlock(lockKey);
   
    if (error) 
    {
        USB_printf("_usb_device_send_data, transfer failed\n");
        return USBERR_TX_FAILED;
    } /* Endif */
    return error;

} /* EndBody */
Beispiel #4
0
/*FUNCTION*-------------------------------------------------------------
*
*  Function Name  : _usb_device_recv_data
*  Returned Value : USB_OK or error code
*  Comments       :
*        Receives data on a specified endpoint.
*
*END*-----------------------------------------------------------------*/
uint_8 _usb_device_recv_data
   (
      /* [IN] the USB_USB_dev_initialize state structure */
      _usb_device_handle         handle,
            
      /* [IN] the Endpoint number */
      uint_8                     ep_num,
            
      /* [IN] buffer to receive data */
      uint_8_ptr                 buff_ptr,
            
      /* [IN] length of the transfer */
      uint_32                    size
   )
{ /* Body */
    int                              lockKey;
    uint_8                           error = USB_OK;
    XD_STRUCT_PTR                    xd_ptr;
    USB_DEV_STATE_STRUCT_PTR         usb_dev_ptr;
   
    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;

    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RX, "recv_data: ep=%d, buf_ptr=0x%x, size=%d\n",
                                       ep_num, (unsigned)buff_ptr, (int)size);

    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_recv_count++));

    if(buff_ptr != NULL)
        USB_dcache_inv((pointer)buff_ptr,size);   
    
    lockKey = USB_lock();

    if (!usb_dev_ptr->XD_ENTRIES) 
    {
        USB_unlock(lockKey);
        USB_printf("_usb_device_recv_data, transfer in progress\n");
        return ARC_USB_STATUS_TRANSFER_IN_PROGRESS;
    } /* Endif */

    /* Get a transfer descriptor for the specified endpoint 
    ** and direction 
    */
    USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr);
   
    usb_dev_ptr->XD_ENTRIES--;

    /* Initialize the new transfer descriptor */      
    xd_ptr->EP_NUM = ep_num;
    xd_ptr->BDIRECTION = ARC_USB_RECV;
    xd_ptr->WTOTALLENGTH = size;
    xd_ptr->WSOFAR = 0;
    xd_ptr->WSTARTADDRESS = buff_ptr;
   
    xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED;

    error = _usb_dci_vusb20_add_dTD(handle, xd_ptr);

    USB_unlock(lockKey);
   
    if (error) 
    {
        USB_printf("_usb_device_recv_data, receive failed\n");
        return USBERR_RX_FAILED;
    } /* Endif */

    return error;

} /* EndBody */