Changeset 47e9494 in mainline
- Timestamp:
- 2018-01-16T18:02:46Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- eeca8a6
- Parents:
- 7d1dd2b
- Location:
- uspace
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/Makefile
r7d1dd2b r47e9494 43 43 rh.c \ 44 44 scratchpad.c \ 45 streams.c \ 45 46 transfers.c \ 46 47 trb_ring.c -
uspace/drv/bus/usb/xhci/endpoint.c
r7d1dd2b r47e9494 44 44 #include "commands.h" 45 45 #include "endpoint.h" 46 #include "streams.h" 46 47 47 48 static int alloc_transfer_ds(xhci_endpoint_t *); … … 131 132 * @return EP_TYPE_[CONTROL|ISOCH|BULK|INTERRUPT]_[IN|OUT] 132 133 */ 133 staticint xhci_endpoint_type(xhci_endpoint_t *ep)134 int xhci_endpoint_type(xhci_endpoint_t *ep) 134 135 { 135 136 const bool in = ep->base.direction == USB_DIRECTION_IN; … … 153 154 154 155 return EP_TYPE_INVALID; 155 }156 157 /**158 * Test whether an XHCI endpoint uses streams.159 * @param[in] xhci_ep XHCI endpoint to query.160 *161 * @return True if the endpoint uses streams.162 */163 static bool endpoint_using_streams(xhci_endpoint_t *xhci_ep)164 {165 return xhci_ep->primary_stream_ctx_array != NULL;166 }167 168 // static bool primary_stream_ctx_has_secondary_array(xhci_stream_ctx_t *primary_ctx) {169 // /* Section 6.2.4.1, SCT values */170 // return XHCI_STREAM_SCT(*primary_ctx) >= 2;171 // }172 //173 // static size_t secondary_stream_ctx_array_size(xhci_stream_ctx_t *primary_ctx) {174 // if (XHCI_STREAM_SCT(*primary_ctx) < 2) return 0;175 // return 2 << XHCI_STREAM_SCT(*primary_ctx);176 // }177 178 /** Initialize primary streams of XHCI bulk endpoint.179 * @param[in] hc Host controller of the endpoint.180 * @param[in] xhci_epi XHCI bulk endpoint to use.181 * @param[in] count Number of primary streams to initialize.182 */183 static void initialize_primary_streams(xhci_hc_t *hc, xhci_endpoint_t *xhci_ep, unsigned count) {184 for (size_t index = 0; index < count; ++index) {185 xhci_stream_ctx_t *ctx = &xhci_ep->primary_stream_ctx_array[index];186 xhci_trb_ring_t *ring = &xhci_ep->primary_stream_rings[index];187 188 /* Init and register TRB ring for every primary stream */189 xhci_trb_ring_init(ring); // FIXME: Not checking error code?190 XHCI_STREAM_DEQ_PTR_SET(*ctx, ring->dequeue);191 192 /* Set to linear stream array */193 XHCI_STREAM_SCT_SET(*ctx, 1);194 }195 }196 197 /** Configure XHCI bulk endpoint's stream context.198 * @param[in] xhci_ep Associated XHCI bulk endpoint.199 * @param[in] ctx Endpoint context to configure.200 * @param[in] pstreams The value of MaxPStreams.201 */202 static void setup_stream_context(xhci_endpoint_t *xhci_ep, xhci_ep_ctx_t *ctx, unsigned pstreams) {203 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(xhci_ep));204 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, xhci_ep->base.max_packet_size);205 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, xhci_ep->max_burst - 1);206 XHCI_EP_ERROR_COUNT_SET(*ctx, 3);207 208 XHCI_EP_MAX_P_STREAMS_SET(*ctx, pstreams);209 XHCI_EP_TR_DPTR_SET(*ctx, xhci_ep->primary_stream_ctx_dma.phys);210 // TODO: set HID?211 XHCI_EP_LSA_SET(*ctx, 1);212 }213 214 /** TODO document this215 */216 int xhci_endpoint_request_streams(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *xhci_ep, unsigned count) {217 if (xhci_ep->base.transfer_type != USB_TRANSFER_BULK218 || dev->base.speed != USB_SPEED_SUPER) {219 usb_log_error("Streams are only supported by superspeed bulk endpoints.");220 return EINVAL;221 }222 223 if (xhci_ep->max_streams == 1) {224 usb_log_error("Streams are not supported by endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));225 return EINVAL;226 }227 228 uint8_t max_psa_size = 2 << XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PSA_SIZE);229 if (count > max_psa_size) {230 // FIXME: We don't support secondary stream arrays yet, so we just give up for this231 return ENOTSUP;232 }233 234 if (count > xhci_ep->max_streams) {235 usb_log_error("Endpoint " XHCI_EP_FMT " supports only %" PRIu32 " streams.",236 XHCI_EP_ARGS(*xhci_ep), xhci_ep->max_streams);237 return EINVAL;238 }239 240 if (count <= 1024) {241 usb_log_debug2("Allocating primary stream context array of size %u for endpoint " XHCI_EP_FMT,242 count, XHCI_EP_ARGS(*xhci_ep));243 if ((dma_buffer_alloc(&xhci_ep->primary_stream_ctx_dma, count * sizeof(xhci_stream_ctx_t))))244 return ENOMEM;245 xhci_ep->primary_stream_ctx_array = xhci_ep->primary_stream_ctx_dma.virt;246 247 xhci_ep->primary_stream_rings = calloc(count, sizeof(xhci_trb_ring_t));248 if (!xhci_ep->primary_stream_rings) {249 dma_buffer_free(&xhci_ep->primary_stream_ctx_dma);250 return ENOMEM;251 }252 253 // FIXME: count should be rounded to nearest power of 2 for xHC, workaround for now254 count = 1024;255 // FIXME: pstreams are "log2(count) - 1"256 const size_t pstreams = 9;257 xhci_ep->primary_stream_ctx_array_size = count;258 259 memset(xhci_ep->primary_stream_ctx_array, 0, count * sizeof(xhci_stream_ctx_t));260 initialize_primary_streams(hc, xhci_ep, count);261 262 xhci_ep_ctx_t ep_ctx;263 setup_stream_context(xhci_ep, &ep_ctx, pstreams);264 return hc_add_endpoint(hc, dev->slot_id, xhci_endpoint_index(xhci_ep), &ep_ctx);265 }266 // FIXME: Complex stuff not supported yet267 return ENOTSUP;268 156 } 269 157 … … 300 188 static void free_transfer_ds(xhci_endpoint_t *xhci_ep) 301 189 { 302 if (endpoint_using_streams(xhci_ep)) { 303 usb_log_debug2("Freeing primary stream context array of endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 304 305 // maybe check if LSA, then skip? 306 // for (size_t index = 0; index < primary_stream_ctx_array_size(xhci_ep); ++index) { 307 // xhci_stream_ctx_t *primary_ctx = xhci_ep->primary_stream_ctx_array + index; 308 // if (primary_stream_ctx_has_secondary_array(primary_ctx)) { 309 // // uintptr_t phys = XHCI_STREAM_DEQ_PTR(*primary_ctx); 310 // /* size_t size = */ secondary_stream_ctx_array_size(primary_ctx); 311 // // TODO: somehow map the address to virtual and free the secondary array 312 // } 313 // } 314 for (size_t index = 0; index < xhci_ep->primary_stream_ctx_array_size; ++index) { 315 // FIXME: Get the trb ring associated with stream [index] and fini it 316 } 317 dma_buffer_free(&xhci_ep->primary_stream_ctx_dma); 190 if (xhci_ep->primary_stream_data_size) { 191 xhci_stream_free_ds(xhci_ep); 318 192 } else { 319 193 usb_log_debug2("Freeing main transfer ring of endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep)); 320 321 194 xhci_trb_ring_fini(&xhci_ep->ring); 322 195 } -
uspace/drv/bus/usb/xhci/endpoint.h
r7d1dd2b r47e9494 51 51 typedef struct xhci_device xhci_device_t; 52 52 typedef struct xhci_endpoint xhci_endpoint_t; 53 typedef struct xhci_stream_data xhci_stream_data_t; 53 54 typedef struct xhci_bus xhci_bus_t; 54 55 … … 71 72 xhci_trb_ring_t ring; 72 73 73 /** Primary stream context array (or NULL if endpoint doesn't use streams). */ 74 /** Primary stream context data array (or NULL if endpoint doesn't use streams). */ 75 xhci_stream_data_t *primary_stream_data_array; 76 77 /** Primary stream context array - allocated for xHC hardware. */ 74 78 xhci_stream_ctx_t *primary_stream_ctx_array; 75 79 dma_buffer_t primary_stream_ctx_dma; 76 80 77 /** Primary stream ring array (or NULL if endpoint doesn't use streams). */ 78 xhci_trb_ring_t *primary_stream_rings; 79 80 /** Size of the allocated primary stream context array (and ring array). */ 81 uint16_t primary_stream_ctx_array_size; 81 /** Size of the allocated primary stream data array (and context array). */ 82 uint16_t primary_stream_data_size; 82 83 83 84 /* Maximum number of primary streams (0 - 2^16). */ … … 129 130 #define XHCI_DEV_ARGS(dev) ddf_fun_get_name((dev).base.fun), (dev).slot_id 130 131 132 int xhci_endpoint_type(xhci_endpoint_t *ep); 133 131 134 int xhci_endpoint_init(xhci_endpoint_t *, device_t *, const usb_endpoint_descriptors_t *); 132 135 void xhci_endpoint_fini(xhci_endpoint_t *); 133 134 int xhci_endpoint_request_streams(xhci_hc_t *, xhci_device_t *, xhci_endpoint_t *, unsigned);135 136 136 137 uint8_t xhci_endpoint_dci(xhci_endpoint_t *); -
uspace/drv/bus/usb/xhci/hw_struct/context.h
r7d1dd2b r47e9494 167 167 #define XHCI_STREAM_DCS(ctx) XHCI_QWORD_EXTRACT((ctx).data[0], 0, 0) 168 168 #define XHCI_STREAM_SCT(ctx) XHCI_QWORD_EXTRACT((ctx).data[0], 3, 1) 169 #define XHCI_STREAM_DEQ_PTR(ctx) XHCI_QWORD_EXTRACT((ctx).data[0], 63,4)169 #define XHCI_STREAM_DEQ_PTR(ctx) (XHCI_QWORD_EXTRACT((ctx).data[0], 63, 4) << 4) 170 170 #define XHCI_STREAM_EDTLA(ctx) XHCI_QWORD_EXTRACT((ctx).data[1], 24, 0) 171 171 -
uspace/drv/bus/usb/xhci/hw_struct/trb.h
r7d1dd2b r47e9494 102 102 #define TRB_LINK_TC(trb) XHCI_DWORD_EXTRACT((trb).control, 1, 1) 103 103 #define TRB_IOC(trb) XHCI_DWORD_EXTRACT((trb).control, 5, 5) 104 #define TRB_EVENT_DATA(trb) XHCI_DWORD_EXTRACT((trb).control, 2, 2) 104 105 105 106 #define TRB_TRANSFER_LENGTH(trb) XHCI_DWORD_EXTRACT((trb).status, 23, 0) -
uspace/drv/bus/usb/xhci/transfers.c
r7d1dd2b r47e9494 39 39 #include "hc.h" 40 40 #include "hw_struct/trb.h" 41 #include "streams.h" 41 42 #include "transfers.h" 42 43 #include "trb_ring.h" … … 121 122 static xhci_trb_ring_t *get_ring(xhci_hc_t *hc, xhci_transfer_t *transfer) 122 123 { 123 return &xhci_endpoint_get(transfer->batch.ep)->ring; 124 xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep); 125 if (ep->primary_stream_data_size == 0) return &ep->ring; 126 uint32_t stream_id = transfer->batch.target.stream; 127 128 xhci_stream_data_t *stream_data = xhci_get_stream_ctx_data(ep, stream_id); 129 if (stream_data == NULL) { 130 usb_log_warning("No transfer ring was found for stream %u.", stream_id); 131 return NULL; 132 } 133 134 return &stream_data->ring; 124 135 } 125 136 … … 202 213 // data size (sent for OUT, or buffer size) 203 214 TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size); 204 // FIXME: TD size 4.11.2.4 205 TRB_CTRL_SET_TD_SIZE(trb, 1); 206 207 // we want an interrupt after this td is done 208 TRB_CTRL_SET_IOC(trb, 1); 209 210 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 211 212 xhci_trb_ring_t* ring = get_ring(hc, transfer); 213 214 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 215 216 /* The stream-enabled endpoints need to chain ED trb */ 217 xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep); 218 if (!ep->primary_stream_data_size) { 219 // FIXME: TD size 4.11.2.4 220 TRB_CTRL_SET_TD_SIZE(trb, 1); 221 222 // we want an interrupt after this td is done 223 TRB_CTRL_SET_IOC(trb, 1); 224 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 225 226 xhci_trb_ring_t* ring = get_ring(hc, transfer); 227 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 228 } 229 else { 230 TRB_CTRL_SET_TD_SIZE(trb, 2); 231 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 232 TRB_CTRL_SET_CHAIN(trb, 1); 233 TRB_CTRL_SET_ENT(trb, 1); 234 235 xhci_trb_ring_t* ring = get_ring(hc, transfer); 236 int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 237 238 if (err) { 239 return err; 240 } 241 242 xhci_trb_clean(&trb); 243 trb.parameter = host2xhci(64, (uintptr_t) transfer); 244 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA); 245 TRB_CTRL_SET_IOC(trb, 1); 246 247 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 248 } 215 249 } 216 250 … … 267 301 xhci_endpoint_t *ep = xhci_endpoint_get(ep_base); 268 302 269 xhci_trb_ring_update_dequeue(&ep->ring, addr); 270 271 if (ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) { 272 isoch_handle_transfer_event(hc, ep, trb); 273 endpoint_del_ref(&ep->base); 274 return EOK; 275 } 276 277 fibril_mutex_lock(&ep->base.guard); 278 usb_transfer_batch_t *batch = ep->base.active_batch; 279 if (!batch) { 303 usb_transfer_batch_t *batch; 304 xhci_transfer_t *transfer; 305 306 if (TRB_EVENT_DATA(*trb)) { 307 assert(ep->base.transfer_type != USB_TRANSFER_ISOCHRONOUS); 308 /* We are received transfer pointer instead - work with that */ 309 transfer = (xhci_transfer_t *) addr; 310 xhci_trb_ring_t * ring = get_ring(hc, transfer); 311 xhci_trb_ring_update_dequeue(ring, transfer->interrupt_trb_phys); 312 batch = &transfer->batch; 313 314 fibril_mutex_lock(&ep->base.guard); 315 endpoint_deactivate_locked(&ep->base); 280 316 fibril_mutex_unlock(&ep->base.guard); 281 endpoint_del_ref(&ep->base); 282 return ENOENT; 317 } 318 else { 319 xhci_trb_ring_update_dequeue(&ep->ring, addr); 320 321 if (ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) { 322 isoch_handle_transfer_event(hc, ep, trb); 323 endpoint_del_ref(&ep->base); 324 return EOK; 325 } 326 327 fibril_mutex_lock(&ep->base.guard); 328 batch = ep->base.active_batch; 329 if (!batch) { 330 fibril_mutex_unlock(&ep->base.guard); 331 endpoint_del_ref(&ep->base); 332 return ENOENT; 333 } 334 335 transfer = xhci_transfer_from_batch(batch); 336 337 endpoint_deactivate_locked(&ep->base); 338 fibril_mutex_unlock(&ep->base.guard); 283 339 } 284 340 … … 296 352 } 297 353 298 endpoint_deactivate_locked(&ep->base);299 fibril_mutex_unlock(&ep->base.guard);300 301 xhci_transfer_t *transfer = xhci_transfer_from_batch(batch);302 303 354 if (batch->dir == USB_DIRECTION_IN) { 304 355 assert(batch->buffer); … … 370 421 371 422 const uint8_t slot_id = xhci_dev->slot_id; 372 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */ 423 /* EP Doorbells start at 1 */ 424 const uint8_t target = (xhci_endpoint_index(xhci_ep) + 1) | (batch->target.stream << 16); 373 425 hc_ring_doorbell(hc, slot_id, target); 374 426 return EOK; -
uspace/lib/drv/include/usb_iface.h
r7d1dd2b r47e9494 89 89 usb_address_t address; 90 90 usb_endpoint_t endpoint; 91 uint32_t stream; 91 92 } __attribute__((packed)); 92 uint 32_t packed;93 uint64_t packed; 93 94 } usb_target_t; 94 95
Note:
See TracChangeset
for help on using the changeset viewer.