/*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 : ch9SetAddress * Returned Value : None * Comments : * Chapter 9 SetAddress command * We setup a TX packet of 0 length ready for the IN token * Once we get the TOK_DNE interrupt for the IN token, then * we change the ADDR register and go to the ADDRESS state. * *END*--------------------------------------------------------------------*/ void mvUsbCh9SetAddress(_usb_device_handle handle, boolean setup, SETUP_STRUCT* setup_ptr) { /* Body */ static uint_8 new_address; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "usbDisk %s: setup=%d, address=%d\n", __FUNCTION__, (int)setup, setup_ptr->VALUE); if (setup) { new_address = setup_ptr->VALUE; /******************************************************* * if hardware assitance is enabled for set_address (see * hardware rev for details) we need to do the set_address * before queuing the status phase. *******************************************************/ #ifdef SET_ADDRESS_HARDWARE_ASSISTANCE _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address); #endif /* ack */ _usb_device_send_data(handle, 0, 0, 0); } else { #ifndef SET_ADDRESS_HARDWARE_ASSISTANCE _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address); #endif _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, ARC_USB_STATE_ADDRESS); } }
/*FUNCTION*---------------------------------------------------------------- * * Function Name : ch9SetConfig * Returned Value : None * Comments : * Chapter 9 SetConfig command * We setup a TX packet of 0 length ready for the IN token * Once we get the TOK_DNE interrupt for the IN token, then * we change the configuration number and go to the CONFIG state. * *END*--------------------------------------------------------------------*/ void mvUsbCh9SetConfig(_usb_device_handle handle, boolean setup, SETUP_STRUCT* setup_ptr) { /* Body */ static uint_8 new_config; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "%s: setup=%d, config=%d\n", __FUNCTION__, (int)setup, setup_ptr->VALUE); if (setup) { new_config = setup_ptr->VALUE; /******************************************************* * if hardware assitance is enabled for set_address (see * hardware rev for details) we need to do the set_address * before queuing the status phase. *******************************************************/ _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, new_config); /* ack */ _usb_device_send_data(handle, 0, 0, 0); } else { _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, new_config); _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, ARC_USB_STATE_CONFIG); } }
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_device_call_service * Returned Value : USB_OK or error code * Comments : * Calls the appropriate service for the specified type, if one is * registered. Used internally only. * *END*--------------------------------------------------------------------*/ uint_8 _usb_device_call_service ( /* [IN] Handle to the USB device */ _usb_device_handle handle, /* [OUT] Type of service or endpoint */ uint_8 type, /* [OUT] Is it a Setup transfer? */ boolean setup, /* [OUT] Direction of transmission; is it a Transmit? */ boolean direction, /* [OUT] Pointer to the data */ uint_8_ptr buffer_ptr, /* [OUT] Number of bytes in transmission */ uint_32 length, /* [OUT] Any errors */ uint_8 errors ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; SERVICE_STRUCT _PTR_ service_ptr; int lockKey; usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; /* Needs mutual exclusion */ lockKey = USB_lock(); /* Search for an existing entry for type */ for (service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR; service_ptr; service_ptr = service_ptr->NEXT) { if (service_ptr->TYPE == type) { service_ptr->SERVICE(handle, type, setup, direction, buffer_ptr, length, errors); USB_unlock(lockKey); return USB_OK; } /* Endif */ } /* Endfor */ USB_unlock(lockKey); ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "_usb_device_call_service, service %d is closed\n", type); return USBERR_CLOSED_SERVICE; } /* EndBody */
void mvUsbCh9GetStatus(_usb_device_handle handle, boolean setup, SETUP_STRUCT* ctrl_req) { /* Body */ uint_8 endpoint, direction; uint_16 usb_status; USB_DEV_STATE_STRUCT* usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); if(!setup) return; switch (ctrl_req->REQUESTTYPE) { case (REQ_DIR_IN | REQ_RECIP_DEVICE): /* Device request */ _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); break; case (REQ_DIR_IN | REQ_RECIP_INTERFACE): /* Interface request */ _usb_device_get_status(handle, ARC_USB_STATUS_INTERFACE, &usb_status); break; case (REQ_DIR_IN | REQ_RECIP_ENDPOINT): /* Endpoint request */ endpoint = ctrl_req->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; if( (ctrl_req->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) direction = ARC_USB_SEND; else direction = ARC_USB_RECV; usb_status = _usb_device_is_endpoint_stalled(handle, endpoint, direction); break; default: /* Unknown request */ USB_printf("GetStatus: Unknown request type 0x%x\n", ctrl_req->REQUESTTYPE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endswitch */ /* Send the requested data */ *usb_dev_ptr->STATUS_PTR = USB_16BIT_LE(usb_status); _usb_device_send_data(handle, 0, (uint_8_ptr)usb_dev_ptr->STATUS_PTR, sizeof(uint_16)); /* status phase */ _usb_device_recv_data(handle, 0, NULL, 0); return; } /* 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_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_device_shutdown * Returned Value : USB_OK or error code * Comments : * Shutdown an initialized USB device * *END*-----------------------------------------------------------------*/ void _usb_device_shutdown(_usb_device_handle handle) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; SERVICE_STRUCT_PTR service_ptr; int ep; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "shutdown\n"); usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; for(ep=0; ep<(usb_dev_ptr->MAX_ENDPOINTS); ep++) { /* Cancel all transfers on all endpoints */ while(_usb_device_get_transfer_status(handle, ep, ARC_USB_RECV) != ARC_USB_STATUS_IDLE) { _usb_device_cancel_transfer(handle, ep, ARC_USB_RECV); } while(_usb_device_get_transfer_status(handle, ep, ARC_USB_SEND) != ARC_USB_STATUS_IDLE) { _usb_device_cancel_transfer(handle, ep, ARC_USB_SEND); } } _usb_dci_vusb20_shutdown(usb_dev_ptr); /* Free all the Callback function structure memory */ for( service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR; service_ptr; service_ptr = service_ptr->NEXT) { USB_printf("_usb_device_shutdown: free service_ptr = 0x%x\n", service_ptr); USB_memfree(service_ptr); } usb_dev_ptr->SERVICE_HEAD_PTR = NULL; _usb_device_cleanup(usb_dev_ptr); } /* 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 */
void mvUsbCh9ClearFeature(_usb_device_handle handle, boolean setup, SETUP_STRUCT* setup_ptr) { /* Body */ uint_8 endpoint, direction; uint_16 usb_status; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status); if ((usb_status != ARC_USB_STATE_CONFIG) && (usb_status != ARC_USB_STATE_ADDRESS)) { USB_printf("ClearFeature: Wrong USB state %d\n", usb_status); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ if(!setup) return; switch (setup_ptr->REQUESTTYPE) { case (REQ_DIR_OUT | REQ_RECIP_DEVICE): /* DEVICE */ switch(setup_ptr->VALUE) { case DEVICE_REMOTE_WAKEUP: /* clear remote wakeup */ _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); usb_status &= ~ARC_USB_REMOTE_WAKEUP; _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status); USB_printf("Clear REMOTE_WAKEUP feature\n"); break; case DEVICE_TEST_MODE: /* Exit Test Mode */ _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, 0); break; default: USB_printf("ClearFeature: Unknown Device feature %d\n", setup_ptr->VALUE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ break; case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT): /* ENDPOINT */ if (setup_ptr->VALUE != ENDPOINT_HALT) { USB_printf("ClearFeature: Wrong Endpoint feature %d\n", setup_ptr->VALUE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) direction = ARC_USB_SEND; else direction = ARC_USB_RECV; _usb_device_unstall_endpoint(handle, endpoint, direction); break; default: USB_printf("ClearFeature: Unknown REQUEST_TYPE %d\n", setup_ptr->REQUESTTYPE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endswitch */ /* status phase */ _usb_device_send_data(handle, 0, 0, 0); }
void mvUsbCh9SetFeature(_usb_device_handle handle, boolean setup, SETUP_STRUCT* setup_ptr) { uint_16 usb_status; uint_8 endpoint, direction; USB_DEV_STATE_STRUCT* usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); if (setup) { switch (setup_ptr->REQUESTTYPE) { case (REQ_DIR_OUT | REQ_RECIP_DEVICE): /* DEVICE */ switch (setup_ptr->VALUE) { case DEVICE_REMOTE_WAKEUP: /* set remote wakeup */ _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); usb_status |= ARC_USB_REMOTE_WAKEUP; _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status); USB_printf("Set REMOTE_WAKEUP feature\n"); break; case DEVICE_TEST_MODE: /* Test Mode */ if( (setup_ptr->INDEX & 0x00FF) || (usb_dev_ptr->SPEED != ARC_USB_SPEED_HIGH) ) { USB_printf("SetFeature: Wrong Test mode parameters: mode=%d, speed=%d\n", (setup_ptr->INDEX & 0x00FF), usb_dev_ptr->SPEED); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status); if( (usb_status == ARC_USB_STATE_CONFIG) || (usb_status == ARC_USB_STATE_ADDRESS) || (usb_status == ARC_USB_STATE_DEFAULT)) { /* wait with Set Test mode */ ENTER_TEST_MODE = TRUE; test_mode_index = (setup_ptr->INDEX & 0xFF00); USB_printf("SetFeature: Prepare for Test mode 0x%x\n", test_mode_index); } else { USB_printf("SetFeature: Wrong USB state for Test mode: state=%d\n", usb_status); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ break; default: USB_printf("SetFeature: Unknown Device feature %d\n", setup_ptr->VALUE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endswitch */ break; case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT): /* ENDPOINT */ if (setup_ptr->VALUE != ENDPOINT_HALT) { USB_printf("SetFeature: Unknown Endpoint feature %d\n", setup_ptr->VALUE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endif */ endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) direction = ARC_USB_SEND; else direction = ARC_USB_RECV; _usb_device_stall_endpoint(handle, endpoint, direction); break; default: USB_printf("SetFeature: Unknown REQUEST_TYPE %d\n", setup_ptr->REQUESTTYPE); _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); return; } /* Endswitch */ /* status phase */ _usb_device_send_data(handle, 0, 0, 0); } else { if (ENTER_TEST_MODE) { /* Enter Test Mode */ USB_printf("SetFeature: Activate Test mode 0x%x\n", test_mode_index); _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, test_mode_index); } /* Endif */ } /* Endif */ }
/*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 */
/*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 */