1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) Microsoft Corporation. All rights reserved. */ 4 /* */ 5 /* This software is licensed under the Microsoft Software License */ 6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8 /* and in the root directory of this software. */ 9 /* */ 10 /**************************************************************************/ 11 12 13 /**************************************************************************/ 14 /**************************************************************************/ 15 /** */ 16 /** USBX Component */ 17 /** */ 18 /** EHCI Controller Driver */ 19 /** */ 20 /**************************************************************************/ 21 /**************************************************************************/ 22 23 24 /* Include necessary system files. */ 25 26 #define UX_SOURCE_CODE 27 28 #include "ux_api.h" 29 #include "ux_hcd_ehci.h" 30 #include "ux_host_stack.h" 31 32 33 /**************************************************************************/ 34 /* */ 35 /* FUNCTION RELEASE */ 36 /* */ 37 /* _ux_hcd_ehci_asynchronous_endpoint_create PORTABLE C */ 38 /* 6.1.2 */ 39 /* AUTHOR */ 40 /* */ 41 /* Chaoqiong Xiao, Microsoft Corporation */ 42 /* */ 43 /* DESCRIPTION */ 44 /* */ 45 /* This function will create an asynchronous endpoint. The control */ 46 /* and bulk endpoints fall into this category. */ 47 /* */ 48 /* INPUT */ 49 /* */ 50 /* hcd_ehci Pointer to EHCI controller */ 51 /* endpoint Pointer to endpoint */ 52 /* */ 53 /* OUTPUT */ 54 /* */ 55 /* Completion Status */ 56 /* */ 57 /* CALLS */ 58 /* */ 59 /* _ux_hcd_ehci_ed_obtain Obtain EHCI ED */ 60 /* _ux_utility_physical_address Get physical address */ 61 /* */ 62 /* CALLED BY */ 63 /* */ 64 /* EHCI Controller Driver */ 65 /* */ 66 /* RELEASE HISTORY */ 67 /* */ 68 /* DATE NAME DESCRIPTION */ 69 /* */ 70 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ 71 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ 72 /* optimized based on compile */ 73 /* definitions, */ 74 /* resulting in version 6.1 */ 75 /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ 76 /* fixed compile warnings, */ 77 /* resulting in version 6.1.2 */ 78 /* */ 79 /**************************************************************************/ _ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI * hcd_ehci,UX_ENDPOINT * endpoint)80UINT _ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) 81 { 82 83 UX_DEVICE *device; 84 UX_EHCI_ED *ed; 85 UX_EHCI_LINK_POINTER queue_head; 86 87 88 /* We need to take into account the nature of the HCD to define the max size 89 of any transfer in the transfer request. */ 90 endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length = UX_EHCI_MAX_PAYLOAD; 91 92 /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active 93 and will be the container for the tds. */ 94 ed = _ux_hcd_ehci_ed_obtain(hcd_ehci); 95 if (ed == UX_NULL) 96 return(UX_NO_ED_AVAILABLE); 97 98 /* Attach the ED to the endpoint container. */ 99 endpoint -> ux_endpoint_ed = (VOID *) ed; 100 101 /* Now do the opposite, attach the ED container to the physical ED. */ 102 ed -> REF_AS.INTR.ux_ehci_ed_endpoint = endpoint; 103 104 /* Set the default MPS Capability info in the ED. */ 105 ed -> ux_ehci_ed_cap0 = endpoint -> ux_endpoint_descriptor.wMaxPacketSize << UX_EHCI_QH_MPS_LOC; 106 107 /* Set the default NAK reload count. */ 108 ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_NCR; 109 110 /* If the device is not high speed and the endpoint is control, then the CEF bit must be set to on. */ 111 device = endpoint -> ux_endpoint_device; 112 if ((device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) && 113 ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_CONTROL_ENDPOINT)) 114 ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_CEF; 115 116 /* Set the device address. */ 117 ed -> ux_ehci_ed_cap0 |= device -> ux_device_address; 118 119 /* Add the endpoint address. */ 120 ed -> ux_ehci_ed_cap0 |= (endpoint -> ux_endpoint_descriptor.bEndpointAddress & 121 ~UX_ENDPOINT_DIRECTION) << UX_EHCI_QH_ED_AD_LOC; 122 123 /* Set the High Bandwidth Pipe Multiplier to 1. */ 124 ed -> ux_ehci_ed_cap1 |= UX_EHCI_QH_HBPM; 125 126 /* Set the device speed for full and low speed devices behind a hub the hub address and the 127 port index must be stored in the endpoint. */ 128 switch (device -> ux_device_speed) 129 { 130 131 case UX_HIGH_SPEED_DEVICE: 132 133 ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_HIGH_SPEED; 134 break; 135 136 137 case UX_LOW_SPEED_DEVICE: 138 139 ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_LOW_SPEED; 140 break; 141 142 case UX_FULL_SPEED_DEVICE: 143 144 #if UX_MAX_DEVICES > 1 145 /* The device must be on a hub for this code to execute. We still do a sanity check. */ 146 if (device -> ux_device_parent != UX_NULL) 147 { 148 149 /* Store the parent hub device address. */ 150 ed -> ux_ehci_ed_cap1 |= device -> ux_device_parent -> ux_device_address << UX_EHCI_QH_HUB_ADDR_LOC; 151 152 /* And the port index onto which this device is attached. */ 153 ed -> ux_ehci_ed_cap1 |= device -> ux_device_port_location << UX_EHCI_QH_PORT_NUMBER_LOC; 154 } 155 #endif 156 break; 157 } 158 159 /* We need to insert this new endpoint into the asynchronous list. All new EDs are inserted at the 160 end of the list. The current ED will be pointing to the first ED in the list. */ 161 queue_head.void_ptr = _ux_utility_physical_address(hcd_ehci -> ux_hcd_ehci_asynch_first_list); 162 queue_head.value |= UX_EHCI_QH_TYP_QH; 163 ed -> ux_ehci_ed_queue_head = queue_head.ed_ptr; 164 ed -> ux_ehci_ed_next_ed = hcd_ehci -> ux_hcd_ehci_asynch_first_list; 165 166 /* Now we compute the address and the data type to fill the QH pointer with. */ 167 queue_head.void_ptr = _ux_utility_physical_address(ed); 168 queue_head.value |= UX_EHCI_QH_TYP_QH; 169 hcd_ehci -> ux_hcd_ehci_asynch_last_list -> ux_ehci_ed_queue_head = queue_head.ed_ptr; 170 ed -> ux_ehci_ed_previous_ed = hcd_ehci -> ux_hcd_ehci_asynch_last_list; 171 172 /* Update the link of the previous ED. */ 173 ed -> ux_ehci_ed_previous_ed -> ux_ehci_ed_next_ed = ed; 174 175 /* Remember the new last QH. */ 176 hcd_ehci -> ux_hcd_ehci_asynch_last_list = ed; 177 178 /* Return successful completion. */ 179 return(UX_SUCCESS); 180 } 181 182