Changeset 3f6c94ed in mainline for uspace/drv/bus/usb/xhci/endpoint.c
- Timestamp:
- 2017-10-27T11:33:13Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7010861
- Parents:
- 5bc8250
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/endpoint.c
r5bc8250 r3f6c94ed 66 66 } 67 67 68 static bool endpoint_uses_streams(xhci_endpoint_t *xhci_ep) 69 { 70 return xhci_ep->base.transfer_type == USB_TRANSFER_BULK 71 && xhci_ep->max_streams; 72 } 73 74 static size_t primary_stream_ctx_array_size(xhci_endpoint_t *xhci_ep) 75 { 76 if (!endpoint_uses_streams(xhci_ep)) 68 static int xhci_endpoint_type(xhci_endpoint_t *ep) 69 { 70 const bool in = ep->base.direction == USB_DIRECTION_IN; 71 72 switch (ep->base.transfer_type) { 73 case USB_TRANSFER_CONTROL: 74 return EP_TYPE_CONTROL; 75 76 case USB_TRANSFER_ISOCHRONOUS: 77 return in ? EP_TYPE_ISOCH_IN 78 : EP_TYPE_ISOCH_OUT; 79 80 case USB_TRANSFER_BULK: 81 return in ? EP_TYPE_BULK_IN 82 : EP_TYPE_BULK_OUT; 83 84 case USB_TRANSFER_INTERRUPT: 85 return in ? EP_TYPE_INTERRUPT_IN 86 : EP_TYPE_INTERRUPT_OUT; 87 } 88 89 return EP_TYPE_INVALID; 90 } 91 92 static bool endpoint_using_streams(xhci_endpoint_t *xhci_ep) 93 { 94 return xhci_ep->primary_stream_ctx_array != NULL; 95 } 96 97 static size_t primary_stream_ctx_array_max_size(xhci_endpoint_t *xhci_ep) 98 { 99 if (!xhci_ep->max_streams) 77 100 return 0; 78 101 … … 81 104 } 82 105 83 static bool primary_stream_ctx_has_secondary_array(xhci_stream_ctx_t *primary_ctx) { 84 /* Section 6.2.4.1, SCT values */ 85 return XHCI_STREAM_SCT(*primary_ctx) >= 2; 86 } 87 88 static size_t secondary_stream_ctx_array_size(xhci_stream_ctx_t *primary_ctx) { 89 if (XHCI_STREAM_SCT(*primary_ctx) < 2) return 0; 90 return 2 << XHCI_STREAM_SCT(*primary_ctx); 91 } 92 93 int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *xhci_ep) 94 { 95 if (endpoint_uses_streams(xhci_ep)) { 96 /* Set up primary stream context array if needed. */ 97 const size_t size = primary_stream_ctx_array_size(xhci_ep); 98 usb_log_debug2("Allocating primary stream context array of size %lu for endpoint " XHCI_EP_FMT, 99 size, XHCI_EP_ARGS(*xhci_ep)); 100 101 xhci_ep->primary_stream_ctx_array = malloc32(size * sizeof(xhci_stream_ctx_t)); 106 // static bool primary_stream_ctx_has_secondary_array(xhci_stream_ctx_t *primary_ctx) { 107 // /* Section 6.2.4.1, SCT values */ 108 // return XHCI_STREAM_SCT(*primary_ctx) >= 2; 109 // } 110 // 111 // static size_t secondary_stream_ctx_array_size(xhci_stream_ctx_t *primary_ctx) { 112 // if (XHCI_STREAM_SCT(*primary_ctx) < 2) return 0; 113 // return 2 << XHCI_STREAM_SCT(*primary_ctx); 114 // } 115 116 static void initialize_primary_streams(xhci_hc_t *hc, xhci_endpoint_t *xhci_ep, unsigned count) { 117 for (size_t index = 0; index < count; ++index) { 118 // Create trb ring for every primary stream 119 // Store it somewhere 120 // Set the dequeue pointer in stream context structure 121 122 // Set to linear stream array 123 XHCI_STREAM_SCT_SET(xhci_ep->primary_stream_ctx_array[index], 1); 124 } 125 } 126 127 static void setup_stream_context(xhci_endpoint_t *xhci_ep, xhci_ep_ctx_t *ctx, unsigned pstreams) { 128 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(xhci_ep)); 129 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, xhci_ep->base.max_packet_size); 130 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, xhci_ep->max_burst); 131 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 132 133 XHCI_EP_MAX_P_STREAMS_SET(*ctx, pstreams); 134 XHCI_EP_TR_DPTR_SET(*ctx, addr_to_phys(xhci_ep->primary_stream_ctx_array)); 135 // TODO: set HID? 136 XHCI_EP_LSA_SET(*ctx, 1); 137 } 138 139 int xhci_endpoint_request_streams(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *xhci_ep, unsigned count) { 140 if (xhci_ep->base.transfer_type != USB_TRANSFER_BULK 141 || xhci_ep->base.speed != USB_SPEED_SUPER) { 142 usb_log_error("Streams are only supported by superspeed bulk endpoints."); 143 return EINVAL; 144 } 145 146 if (!primary_stream_ctx_array_max_size(xhci_ep)) { 147 usb_log_error("Streams are not supported by endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 148 return EINVAL; 149 } 150 151 uint8_t max_psa_size = 2 << XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PSA_SIZE); 152 if (count > max_psa_size) { 153 // We don't support secondary stream arrays yet, so we just give up for this 154 return ENOTSUP; 155 } 156 157 if (count > (unsigned) (1 << xhci_ep->max_streams)) { 158 usb_log_error("Endpoint " XHCI_EP_FMT " supports only %u streams.", 159 XHCI_EP_ARGS(*xhci_ep), (1 << xhci_ep->max_streams)); 160 return EINVAL; 161 } 162 163 if (count <= 1024) { 164 usb_log_debug2("Allocating primary stream context array of size %u for endpoint " XHCI_EP_FMT, 165 count, XHCI_EP_ARGS(*xhci_ep)); 166 xhci_ep->primary_stream_ctx_array = malloc32(count * sizeof(xhci_stream_ctx_t)); 102 167 if (!xhci_ep->primary_stream_ctx_array) { 103 168 return ENOMEM; 104 169 } 105 170 106 memset(xhci_ep->primary_stream_ctx_array, 0, size * sizeof(xhci_stream_ctx_t)); 107 } else { 108 usb_log_debug2("Allocating main transfer ring for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 109 110 xhci_ep->primary_stream_ctx_array = NULL; 111 112 int err; 113 if ((err = xhci_trb_ring_init(&xhci_ep->ring))) { 114 return err; 115 } 171 // FIXME: count should be rounded to nearest power of 2 for xHC, workaround for now 172 count = 1024; 173 // FIXME: pstreams are "log2(count) - 1" 174 const size_t pstreams = 9; 175 xhci_ep->primary_stream_ctx_array_size = count; 176 177 memset(xhci_ep->primary_stream_ctx_array, 0, count * sizeof(xhci_stream_ctx_t)); 178 initialize_primary_streams(hc, xhci_ep, count); 179 180 xhci_ep_ctx_t ep_ctx; 181 setup_stream_context(xhci_ep, &ep_ctx, pstreams); 182 return hc_add_endpoint(hc, dev->slot_id, xhci_endpoint_index(xhci_ep), &ep_ctx); 183 } 184 // Complex stuff not supported yet 185 return ENOTSUP; 186 } 187 188 int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *xhci_ep) 189 { 190 191 usb_log_debug2("Allocating main transfer ring for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 192 193 xhci_ep->primary_stream_ctx_array = NULL; 194 195 int err; 196 if ((err = xhci_trb_ring_init(&xhci_ep->ring))) { 197 return err; 116 198 } 117 199 … … 121 203 int xhci_endpoint_free_transfer_ds(xhci_endpoint_t *xhci_ep) 122 204 { 123 if (endpoint_us es_streams(xhci_ep)) {205 if (endpoint_using_streams(xhci_ep)) { 124 206 usb_log_debug2("Freeing primary stream context array for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 125 207 126 208 // maybe check if LSA, then skip? 127 for (size_t index = 0; index < primary_stream_ctx_array_size(xhci_ep); ++index) { 128 xhci_stream_ctx_t *primary_ctx = xhci_ep->primary_stream_ctx_array + index; 129 if (primary_stream_ctx_has_secondary_array(primary_ctx)) { 130 // uintptr_t phys = XHCI_STREAM_DEQ_PTR(*primary_ctx); 131 /* size_t size = */ secondary_stream_ctx_array_size(primary_ctx); 132 // TODO: somehow map the address to virtual and free the secondary array 133 } 209 // for (size_t index = 0; index < primary_stream_ctx_array_size(xhci_ep); ++index) { 210 // xhci_stream_ctx_t *primary_ctx = xhci_ep->primary_stream_ctx_array + index; 211 // if (primary_stream_ctx_has_secondary_array(primary_ctx)) { 212 // // uintptr_t phys = XHCI_STREAM_DEQ_PTR(*primary_ctx); 213 // /* size_t size = */ secondary_stream_ctx_array_size(primary_ctx); 214 // // TODO: somehow map the address to virtual and free the secondary array 215 // } 216 // } 217 for (size_t index = 0; index < xhci_ep->primary_stream_ctx_array_size; ++index) { 218 // FIXME: Get the trb ring associated with stream [index] and fini it 134 219 } 135 220 free32(xhci_ep->primary_stream_ctx_array); … … 170 255 } 171 256 172 static int xhci_endpoint_type(xhci_endpoint_t *ep)173 {174 const bool in = ep->base.direction == USB_DIRECTION_IN;175 176 switch (ep->base.transfer_type) {177 case USB_TRANSFER_CONTROL:178 return EP_TYPE_CONTROL;179 180 case USB_TRANSFER_ISOCHRONOUS:181 return in ? EP_TYPE_ISOCH_IN182 : EP_TYPE_ISOCH_OUT;183 184 case USB_TRANSFER_BULK:185 return in ? EP_TYPE_BULK_IN186 : EP_TYPE_BULK_OUT;187 188 case USB_TRANSFER_INTERRUPT:189 return in ? EP_TYPE_INTERRUPT_IN190 : EP_TYPE_INTERRUPT_OUT;191 }192 193 return EP_TYPE_INVALID;194 }195 196 257 static void setup_control_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx) 197 258 { … … 212 273 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 213 274 214 if (endpoint_uses_streams(ep)) { 215 XHCI_EP_MAX_P_STREAMS_SET(*ctx, ep->max_streams); 216 XHCI_EP_TR_DPTR_SET(*ctx, addr_to_phys(ep->primary_stream_ctx_array)); 217 // TODO: set HID 218 // TODO: set LSA 219 } else { 220 XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0); 221 XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue); 222 XHCI_EP_DCS_SET(*ctx, 1); 223 } 275 XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0); 276 XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue); 277 XHCI_EP_DCS_SET(*ctx, 1); 224 278 } 225 279
Note:
See TracChangeset
for help on using the changeset viewer.