/*FUNCTION*------------------------------------------------------------- * * Function Name : _usb_device_init * Returned Value : USB_OK or error code * Comments : * Initializes the USB device specific data structures and calls * the low-level device controller chip initialization routine. * *END*-----------------------------------------------------------------*/ uint_8 _usb_device_init ( /* [IN] the USB device controller to initialize */ uint_8 devnum, /* [OUT] the USB_USB_dev_initialize state structure */ _usb_device_handle _PTR_ handle, /* [IN] number of endpoints to initialize */ uint_8 endpoints ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; XD_STRUCT_PTR xd_ptr; uint_8 temp, i, error; SCRATCH_STRUCT_PTR temp_scratch_ptr; //uint_32 total_memory; //uint_8_ptr stack_mem_ptr; #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init"); #endif #ifndef REDUCED_ERROR_CHECKING if (devnum > MAX_USB_DEVICES) { #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, error invalid device number"); #endif return USBERR_INVALID_DEVICE_NUM; } /* Endif */ #endif /************************************************************** All memory allocations should be consolidated in one. **************************************************************/ /* Allocate memory for the state structure */ //usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR) // USB_memalloc(sizeof(USB_DEV_STATE_STRUCT)); usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR) malloc(sizeof(USB_DEV_STATE_STRUCT)); if (usb_dev_ptr == NULL) { #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, error NULL device handle"); #endif return USBERR_ALLOC_STATE; } /* Endif */ /* Zero out the internal USB state structure */ USB_memzero((char *)usb_dev_ptr,sizeof(USB_DEV_STATE_STRUCT)); /************************************************************** **************************************************************/ /* Multiple devices will have different base addresses and ** interrupt vectors (For future) */ //usb_dev_ptr->DEV_PTR = 0x1cb20100; usb_dev_ptr->DEV_PTR = (VUSB20_REG_STRUCT_PTR)otg_base + 0x100; usb_dev_ptr->DEV_VEC = otg_irq; usb_dev_ptr->USB_STATE = USB_STATE_UNKNOWN; usb_dev_ptr->MAX_ENDPOINTS = endpoints; #ifndef SMALL_CODE_SIZE temp = (usb_dev_ptr->MAX_ENDPOINTS * 2); #endif /* Allocate MAX_XDS_FOR_TR_CALLS */ xd_ptr = (XD_STRUCT_PTR) malloc(sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); //USB_memalloc(sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); if (xd_ptr == NULL) { #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, malloc error"); #endif return USBERR_ALLOC_TR; } USB_memzero((char *)xd_ptr, sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); /* Allocate memory for internal scratch structure */ usb_dev_ptr->XD_SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR) malloc(sizeof(SCRATCH_STRUCT)*MAX_XDS_FOR_TR_CALLS); //USB_memalloc(sizeof(SCRATCH_STRUCT)*MAX_XDS_FOR_TR_CALLS); if (usb_dev_ptr->XD_SCRATCH_STRUCT_BASE == NULL) { #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, malloc error"); #endif return USBERR_ALLOC; } /* Endif */ usb_dev_ptr->XD_BASE = xd_ptr; temp_scratch_ptr = usb_dev_ptr->XD_SCRATCH_STRUCT_BASE; #ifndef SMALL_CODE_SIZE usb_dev_ptr->XD_HEAD = NULL; usb_dev_ptr->XD_TAIL = NULL; usb_dev_ptr->XD_ENTRIES = 0; #endif /* Enqueue all the XDs */ for (i=0;i<MAX_XDS_FOR_TR_CALLS;i++) { xd_ptr->SCRATCH_PTR = temp_scratch_ptr; xd_ptr->SCRATCH_PTR->FREE = _usb_device_free_XD; xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; _usb_device_free_XD((pointer)xd_ptr); xd_ptr++; temp_scratch_ptr++; } /* Endfor */ usb_dev_ptr->TEMP_XD_PTR = (XD_STRUCT_PTR)malloc(sizeof(XD_STRUCT)); USB_memzero((char *)usb_dev_ptr->TEMP_XD_PTR, sizeof(XD_STRUCT)); /* Initialize the USB controller chip */ error = _usb_dci_vusb20_init(devnum, usb_dev_ptr); if (error) { #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, init failed"); #endif return USBERR_INIT_FAILED; } /* Endif */ *handle = usb_dev_ptr; #ifdef _DEVICE_DEBUG_ DEBUG_LOG_TRACE("_usb_device_init, SUCCESSFUL"); #endif return USB_OK; } /* 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_init * Returned Value : USB_OK or error code * Comments : * Initializes the USB device specific data structures and calls * the low-level device controller chip initialization routine. * *END*-----------------------------------------------------------------*/ uint_8 _usb_device_init ( /* [IN] the USB device controller to initialize */ uint_8 devnum, /* [OUT] the USB_USB_dev_initialize state structure */ _usb_device_handle* handle ) { /* Body */ USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; XD_STRUCT_PTR xd_ptr; uint_8 i, error; SCRATCH_STRUCT_PTR temp_scratch_ptr; /* global_import_funcs must be initailized before */ if(global_import_funcs == NULL) return USBERR_INIT_FAILED; if (devnum > MAX_USB_DEVICES) { USB_printf("_usb_device_init, error invalid device number"); return USBERR_INVALID_DEVICE_NUM; } /* Endif */ /* Allocate memory for the state structure */ usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)USB_memalloc(sizeof(USB_DEV_STATE_STRUCT)); if (usb_dev_ptr == NULL) { USB_printf("_usb_device_init, malloc of %d bytes for USB_DEV_STATE_STRUCT failed\n", sizeof(USB_DEV_STATE_STRUCT)); return USBERR_ALLOC_STATE; } /* Endif */ /* Zero out the internal USB state structure */ USB_memzero(usb_dev_ptr, sizeof(USB_DEV_STATE_STRUCT)); usb_dev_ptr->DEV_NUM = devnum; /* Multiple devices will have different base addresses and ** interrupt vectors (For future) */ usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN; /* Allocate MAX_XDS_FOR_TR_CALLS */ xd_ptr = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); if (xd_ptr == NULL) { _usb_device_cleanup(usb_dev_ptr); USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS); return USBERR_ALLOC_TR; } /* Endif */ usb_dev_ptr->XD_BASE = xd_ptr; _usb_clear_stats(usb_dev_ptr); USB_memzero(xd_ptr, sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); /* Allocate memory for internal scratch structure */ usb_dev_ptr->XD_SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR) USB_memalloc(sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS); if (usb_dev_ptr->XD_SCRATCH_STRUCT_BASE == NULL) { _usb_device_cleanup(usb_dev_ptr); USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS); return USBERR_ALLOC; } /* Endif */ temp_scratch_ptr = usb_dev_ptr->XD_SCRATCH_STRUCT_BASE; usb_dev_ptr->XD_HEAD = NULL; usb_dev_ptr->XD_TAIL = NULL; usb_dev_ptr->XD_ENTRIES = 0; /* Enqueue all the XDs */ for (i=0;i<MAX_XDS_FOR_TR_CALLS;i++) { xd_ptr->SCRATCH_PTR = temp_scratch_ptr; xd_ptr->SCRATCH_PTR->FREE = _usb_device_free_XD; xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; _usb_device_free_XD((pointer)xd_ptr); xd_ptr++; temp_scratch_ptr++; } /* Endfor */ usb_dev_ptr->TEMP_XD_PTR = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT)); if(usb_dev_ptr->TEMP_XD_PTR == NULL) { USB_printf("_usb_device_init, malloc of %d bytes for TEMP_XD_STRUCT failed\n", sizeof(XD_STRUCT)); _usb_device_cleanup(usb_dev_ptr); return USBERR_ALLOC; } USB_memzero(usb_dev_ptr->TEMP_XD_PTR, sizeof(XD_STRUCT)); /* Allocate 2 bytes for USB_STATUS to be sent over USB, so Cache line aligned */ usb_dev_ptr->STATUS_UNAIGNED_PTR = (uint_8*)USB_memalloc(sizeof(uint_16) + PSP_CACHE_LINE_SIZE); if(usb_dev_ptr->STATUS_UNAIGNED_PTR == NULL) { USB_printf("_usb_device_init, malloc of %d bytes for USB_STATUS failed\n", sizeof(uint_16) + PSP_CACHE_LINE_SIZE); _usb_device_cleanup(usb_dev_ptr); return USBERR_ALLOC; } USB_memzero(usb_dev_ptr->STATUS_UNAIGNED_PTR, sizeof(uint_16) + PSP_CACHE_LINE_SIZE); usb_dev_ptr->STATUS_PTR = (uint_16*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->STATUS_UNAIGNED_PTR); /* Allocate 53 bytes for USB Test packet to be sent over USB, so Cache line aligned */ usb_dev_ptr->TEST_PKT_UNAIGNED_PTR = (uint_8*)USB_memalloc(USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); if(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR == NULL) { USB_printf("_usb_device_init, malloc of %d bytes for USB Test packet failed\n", USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); _usb_device_cleanup(usb_dev_ptr); return USBERR_ALLOC; } USB_memzero(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); usb_dev_ptr->TEST_PKT_PTR = (uint_8*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->TEST_PKT_UNAIGNED_PTR); /* Initialize the USB controller chip */ error = _usb_dci_vusb20_init(devnum, usb_dev_ptr); if (error) { _usb_device_cleanup(usb_dev_ptr); USB_printf("_usb_device_init, init failed"); return USBERR_INIT_FAILED; } /* Endif */ USB_printf("device_init: pDev=0x%x, pXD(%d)=0x%x, pSCRATCH(%d)=0x%x, pTempXD=0x%x\n", (unsigned)usb_dev_ptr, MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_BASE, MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_SCRATCH_STRUCT_BASE, (unsigned)usb_dev_ptr->TEMP_XD_PTR); *handle = usb_dev_ptr; return USB_OK; } /* EndBody */