Changeset dbf32b1 in mainline
- Timestamp:
- 2017-10-17T10:09:40Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 95c675b
- Parents:
- bb784ae
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/endpoint.c
rbb784ae rdbf32b1 81 81 } 82 82 83 uint8_t xhci_endpoint_ctx_offset(xhci_endpoint_t *ep) 84 { 85 /* 0 is slot ctx, 1 is EP0, then it's EP1 out, in, EP2 out, in, etc. */ 86 87 uint8_t off = 2 * (ep->base.target.endpoint); 88 if (ep->base.direction == USB_DIRECTION_IN || ep->base.target.endpoint == 0) 89 ++off; 90 91 return off; 83 /** Return an index to the endpoint array. The indices are assigned as follows: 84 * 0 EP0 BOTH 85 * 1 EP1 OUT 86 * 2 EP1 IN 87 * 88 * For control endpoints >0, the IN endpoint index is used. 89 * 90 * The index returned must be usually offset by a number of contexts preceding 91 * the endpoint contexts themselves. 92 */ 93 uint8_t xhci_endpoint_index(xhci_endpoint_t *ep) 94 { 95 return (2 * ep->base.target.endpoint) 96 - (ep->base.direction == USB_DIRECTION_OUT); 92 97 } 93 98 … … 211 216 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0); 212 217 213 const uint8_t ep_ offset = xhci_endpoint_ctx_offset(ep);214 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_ offset);218 const uint8_t ep_idx = xhci_endpoint_index(ep); 219 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */ 215 220 216 221 ep_ring = malloc(sizeof(xhci_trb_ring_t)); … … 227 232 switch (ep->base.transfer_type) { 228 233 case USB_TRANSFER_CONTROL: 229 setup_control_ep_ctx(ep, &ictx->endpoint_ctx[ep_ offset - 1], ep_ring);234 setup_control_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring); 230 235 break; 231 236 232 237 case USB_TRANSFER_BULK: 233 setup_bulk_ep_ctx(ep, &ictx->endpoint_ctx[ep_ offset - 1], ep_ring, &ss_desc);238 setup_bulk_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 234 239 break; 235 240 236 241 case USB_TRANSFER_ISOCHRONOUS: 237 setup_isoch_ep_ctx(ep, &ictx->endpoint_ctx[ep_ offset - 1], ep_ring, &ss_desc);242 setup_isoch_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 238 243 break; 239 244 240 245 case USB_TRANSFER_INTERRUPT: 241 setup_interrupt_ep_ctx(ep, &ictx->endpoint_ctx[ep_ offset - 1], ep_ring, &ss_desc);246 setup_interrupt_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 242 247 break; 243 248 -
uspace/drv/bus/usb/xhci/endpoint.h
rbb784ae rdbf32b1 97 97 void xhci_device_fini(xhci_device_t *); 98 98 99 uint8_t xhci_endpoint_ ctx_offset(xhci_endpoint_t *);99 uint8_t xhci_endpoint_index(xhci_endpoint_t *); 100 100 101 101 int xhci_device_add_endpoint(xhci_device_t *, xhci_endpoint_t *); -
uspace/drv/bus/usb/xhci/hc.c
rbb784ae rdbf32b1 634 634 uint32_t v = host2xhci(32, target & BIT_RRANGE(uint32_t, 7)); 635 635 pio_write_32(&hc->db_arry[doorbell], v); 636 usb_log_debug("Ringing doorbell %d, target = %d", doorbell, target); 636 637 return EOK; 637 638 } -
uspace/drv/bus/usb/xhci/transfers.c
rbb784ae rdbf32b1 43 43 #include "trb_ring.h" 44 44 45 static inline uint8_t get_transfer_type(xhci_trb_t* trb, uint8_t bmRequestType, uint16_t wLength) 45 typedef enum { 46 STAGE_OUT, 47 STAGE_IN, 48 } stage_dir_flag_t; 49 50 #define REQUEST_TYPE_DTD (0x80) 51 #define REQUEST_TYPE_IS_DEVICE_TO_HOST(rq) ((rq) & REQUEST_TYPE_DTD) 52 53 54 /** Get direction flag of data stage. 55 * See Table 7 of xHCI specification. 56 */ 57 static inline stage_dir_flag_t get_status_direction_flag(xhci_trb_t* trb, 58 uint8_t bmRequestType, uint16_t wLength) 46 59 { 47 60 /* See Table 7 of xHCI specification */ 48 if (bmRequestType & 0x80) { 49 /* Device-to-host transfer */ 50 if (wLength) { 51 /* IN data stage */ 52 return 3; 53 } 54 else { 55 /* No data stage */ 56 return 0; 57 } 58 } 59 else { 60 /* Host-to-device transfer */ 61 if (wLength) { 62 /* OUT data stage */ 63 return 2; 64 } 65 else { 66 /* No data stage */ 67 return 0; 68 } 69 } 70 } 71 72 static inline uint8_t get_data_direction(xhci_trb_t* trb, uint8_t bmRequestType, uint16_t wLength) 73 { 61 return REQUEST_TYPE_IS_DEVICE_TO_HOST(bmRequestType) && (wLength > 0) 62 ? STAGE_OUT 63 : STAGE_IN; 64 } 65 66 typedef enum { 67 DATA_STAGE_NO = 0, 68 DATA_STAGE_OUT = 2, 69 DATA_STAGE_IN = 3, 70 } data_stage_type_t; 71 72 /** Get transfer type flag. 73 * See Table 8 of xHCI specification. 74 */ 75 static inline data_stage_type_t get_transfer_type(xhci_trb_t* trb, uint8_t 76 bmRequestType, uint16_t wLength) 77 { 78 if (wLength == 0) 79 return DATA_STAGE_NO; 80 74 81 /* See Table 7 of xHCI specification */ 75 if (bmRequestType & 0x80) { 76 /* Device-to-host transfer */ 77 return 1; 78 } 79 else { 80 /* Host-to-device transfer */ 81 return 0; 82 } 83 } 84 85 static inline uint8_t get_status_direction(xhci_trb_t* trb, uint8_t bmRequestType, uint16_t wLength) 86 { 87 /* See Table 7 of xHCI specification */ 88 if (bmRequestType & 0x80) { 89 /* Device-to-host transfer */ 90 if (wLength) { 91 /* Out direction */ 92 return 0; 93 } 94 else { 95 /* In direction */ 96 return 1; 97 } 98 } 99 else { 100 /* Host-to-device transfer, always IN direction */ 101 return 1; 102 } 82 return REQUEST_TYPE_IS_DEVICE_TO_HOST(bmRequestType) 83 ? DATA_STAGE_IN 84 : DATA_STAGE_NO; 103 85 } 104 86 … … 107 89 usb_request_type_t request_type = SETUP_REQUEST_TYPE_GET_TYPE(setup->request_type); 108 90 109 if (request_type == USB_REQUEST_TYPE_STANDARD) { 110 usb_stddevreq_t request = setup->request; 111 112 switch (request) { 113 case USB_DEVREQ_SET_CONFIGURATION: 114 case USB_DEVREQ_SET_INTERFACE: 115 return true; 116 117 default: 118 return false; 119 } 120 } 121 122 return false; 91 return request_type == USB_REQUEST_TYPE_STANDARD && 92 (setup->request == USB_DEVREQ_SET_CONFIGURATION 93 || setup->request == USB_DEVREQ_SET_INTERFACE); 123 94 } 124 95 … … 190 161 191 162 xhci_trb_t trb_setup; 192 memset(&trb_setup, 0, sizeof(xhci_trb_t));163 xhci_trb_clean(&trb_setup); 193 164 194 165 TRB_CTRL_SET_SETUP_WVALUE(trb_setup, setup->value); … … 210 181 /* Data stage */ 211 182 xhci_trb_t trb_data; 212 memset(&trb_data, 0, sizeof(xhci_trb_t));183 xhci_trb_clean(&trb_data); 213 184 214 185 if (setup->length > 0) { … … 226 197 TRB_CTRL_SET_TRB_TYPE(trb_data, XHCI_TRB_TYPE_DATA_STAGE); 227 198 228 transfer->direction = get_data_direction(&trb_setup, setup->request_type, setup->length); 199 transfer->direction = REQUEST_TYPE_IS_DEVICE_TO_HOST(setup->request_type) 200 ? STAGE_IN : STAGE_OUT; 229 201 TRB_CTRL_SET_DIR(trb_data, transfer->direction); 230 202 } … … 232 204 /* Status stage */ 233 205 xhci_trb_t trb_status; 234 memset(&trb_status, 0, sizeof(xhci_trb_t));206 xhci_trb_clean(&trb_status); 235 207 236 208 // FIXME: Evaluate next TRB? 4.12.3 … … 241 213 242 214 TRB_CTRL_SET_TRB_TYPE(trb_status, XHCI_TRB_TYPE_STATUS_STAGE); 243 TRB_CTRL_SET_DIR(trb_status, get_status_direction (&trb_setup, setup->request_type, setup->length));215 TRB_CTRL_SET_DIR(trb_status, get_status_direction_flag(&trb_setup, setup->request_type, setup->length)); 244 216 245 217 uintptr_t dummy = 0; … … 251 223 252 224 list_append(&transfer->link, &hc->transfers); 253 254 /* For control transfers, the target is always 1. */255 // FIXME: ignoring return code256 const uint8_t target = xhci_endpoint_ctx_offset(xhci_ep);257 hc_ring_doorbell(hc, slot_id, target);258 225 259 226 // Issue a Configure Endpoint command, if needed. … … 264 231 } 265 232 266 return EOK; 233 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbels start at 1 */ 234 return hc_ring_doorbell(hc, slot_id, target); 267 235 } 268 236 … … 284 252 285 253 xhci_trb_t trb; 286 memset(&trb, 0, sizeof(xhci_trb_t));254 xhci_trb_clean(&trb); 287 255 trb.parameter = addr_to_phys(transfer->hc_buffer); 288 256 … … 301 269 302 270 // TODO: target = endpoint | stream_id << 16 303 const uint8_t target = xhci_endpoint_ctx_offset(xhci_ep); 304 hc_ring_doorbell(hc, slot_id, target); 305 return EOK; 271 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */ 272 return hc_ring_doorbell(hc, slot_id, target); 306 273 } 307 274 … … 323 290 324 291 xhci_trb_t trb; 325 memset(&trb, 0, sizeof(xhci_trb_t));292 xhci_trb_clean(&trb); 326 293 trb.parameter = addr_to_phys(transfer->hc_buffer); 327 294 … … 339 306 list_append(&transfer->link, &hc->transfers); 340 307 341 const uint8_t target = xhci_endpoint_ctx_offset(xhci_ep); 342 usb_log_debug("Ringing doorbell for slot_id = %d, target = %d", slot_id, target); 308 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */ 343 309 return hc_ring_doorbell(hc, slot_id, target); 344 310 } … … 367 333 usb_transfer_batch_t *batch = transfer->batch; 368 334 369 batch->error = (TRB_COMPLETION_CODE(*trb) == XHCI_TRBC_SUCCESS) ? EOK : ENAK; 370 batch->transfered_size = batch->buffer_size - TRB_TRANSFER_LENGTH(*trb); 371 if (transfer->direction) { 372 memcpy(batch->buffer, transfer->hc_buffer, batch->buffer_size); 373 374 /* Device-to-host, IN */ 375 if (batch->callback_in) 376 batch->callback_in(batch->error, batch->transfered_size, batch->arg); 377 } 378 else { 379 /* Host-to-device, OUT */ 380 if (batch->callback_out) 381 batch->callback_out(batch->error, batch->arg); 382 } 383 335 const int err = (TRB_COMPLETION_CODE(*trb) == XHCI_TRBC_SUCCESS) ? EOK : ENAK; 336 const size_t size = batch->buffer_size - TRB_TRANSFER_LENGTH(*trb); 337 usb_transfer_batch_finish_error(batch, transfer->hc_buffer, size, err); 384 338 xhci_transfer_fini(transfer); 385 339 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.