Changeset 9b2f69e in mainline
- Timestamp:
- 2017-10-15T20:08:16Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b7db009
- Parents:
- 816f5f4
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/bus.c
r816f5f4 r9b2f69e 187 187 ret_dev->device = dev; 188 188 189 usb_log_debug("Device(%d) registered to XHCI bus.", dev->address); 190 189 191 hash_table_insert(&bus->devices, &ret_dev->link); 190 192 *hashed_dev = ret_dev; … … 200 202 static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev) 201 203 { 204 usb_log_debug("Device(%d) released from XHCI bus.", hashed_dev->device->address); 205 202 206 hash_table_remove(&bus->devices, &hashed_dev->device->address); 203 207 xhci_device_fini(hashed_dev->device); … … 225 229 } 226 230 231 usb_log_debug("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint); 232 227 233 return xhci_device_add_endpoint(hashed_dev->device, xhci_endpoint_get(ep)); 228 234 } … … 232 238 xhci_bus_t *bus = bus_to_xhci_bus(bus_base); 233 239 assert(bus); 240 241 usb_log_debug("Endpoint(%d:%d) released from XHCI bus.", ep->target.address, ep->target.endpoint); 234 242 235 243 hashed_device_t *hashed_dev; -
uspace/drv/bus/usb/xhci/endpoint.c
r816f5f4 r9b2f69e 35 35 36 36 #include <usb/host/endpoint.h> 37 #include <usb/descriptor.h> 37 38 38 39 #include <errno.h> … … 53 54 xhci_ep->device = NULL; 54 55 55 usb_log_debug("Endpoint %d:%d initialized.", ep->target.address, ep->target.endpoint);56 57 56 return EOK; 58 57 } … … 63 62 64 63 /* FIXME: Tear down TR's? */ 65 66 endpoint_t *ep = &xhci_ep->base;67 68 usb_log_debug("Endpoint %d:%d destroyed.", ep->target.address, ep->target.endpoint);69 64 } 70 65 … … 76 71 dev->slot_id = 0; 77 72 78 usb_log_debug("Device %d initialized.", dev->address);79 73 return EOK; 80 74 } … … 83 77 { 84 78 // TODO: Check that all endpoints are dead. 85 usb_log_debug("Device %d destroyed.", dev->address); 79 assert(dev); 80 } 81 82 static inline uint8_t xhci_endpoint_ctx_offset(xhci_endpoint_t *ep) 83 { 84 /* 0 is slot ctx, 1 is EP0, then it's EP1 out, in, EP2 out, in, etc. */ 85 86 uint8_t off = 2 + 2 * (ep->base.target.endpoint - 1); 87 if (ep->base.direction == USB_DIRECTION_IN) 88 ++off; 89 90 return off; 91 } 92 93 static int xhci_endpoint_type(xhci_endpoint_t *ep) 94 { 95 const bool in = ep->base.direction == USB_DIRECTION_IN; 96 97 switch (ep->base.transfer_type) { 98 case USB_TRANSFER_CONTROL: 99 return EP_TYPE_CONTROL; 100 101 case USB_TRANSFER_ISOCHRONOUS: 102 return in ? EP_TYPE_ISOCH_IN 103 : EP_TYPE_ISOCH_OUT; 104 105 case USB_TRANSFER_BULK: 106 return in ? EP_TYPE_BULK_IN 107 : EP_TYPE_BULK_OUT; 108 109 case USB_TRANSFER_INTERRUPT: 110 return in ? EP_TYPE_INTERRUPT_IN 111 : EP_TYPE_INTERRUPT_OUT; 112 } 113 114 return EP_TYPE_INVALID; 115 } 116 117 static void setup_control_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx, 118 xhci_trb_ring_t *ring) 119 { 120 // EP0 is configured elsewhere. 121 assert(ep->base.target.endpoint > 0); 122 123 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep)); 124 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size); 125 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 126 XHCI_EP_TR_DPTR_SET(*ctx, ring->dequeue); 127 XHCI_EP_DCS_SET(*ctx, 1); 128 } 129 130 static void setup_bulk_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx, 131 xhci_trb_ring_t *ring, usb_superspeed_endpoint_companion_descriptor_t *ss_desc) 132 { 133 134 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep)); 135 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size); 136 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ep->device->usb3 ? ss_desc->max_burst : 0); 137 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 138 139 // FIXME: Get maxStreams and other things from ss_desc 140 const uint8_t maxStreams = 0; 141 if (maxStreams > 0) { 142 // TODO: allocate and clear primary stream array 143 // TODO: XHCI_EP_MAX_P_STREAMS_SET(ctx, psa_size); 144 // TODO: XHCI_EP_TR_DPTR_SET(ctx, psa_start_phys_addr); 145 // TODO: set HID 146 // TODO: set LSA 147 } else { 148 XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0); 149 /* FIXME physical pointer? */ 150 XHCI_EP_TR_DPTR_SET(*ctx, ring->dequeue); 151 XHCI_EP_DCS_SET(*ctx, 1); 152 } 153 } 154 155 static void setup_isoch_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx, 156 xhci_trb_ring_t *ring, usb_superspeed_endpoint_companion_descriptor_t *ss_desc) 157 { 158 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep)); 159 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size & 0x07FF); 160 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ss_desc->max_burst); 161 // FIXME: get Mult field from SS companion descriptor somehow 162 XHCI_EP_MULT_SET(*ctx, 0); 163 XHCI_EP_ERROR_COUNT_SET(*ctx, 0); 164 /* FIXME physical pointer? */ 165 XHCI_EP_TR_DPTR_SET(*ctx, ring->dequeue); 166 XHCI_EP_DCS_SET(*ctx, 1); 167 // TODO: max ESIT payload 168 } 169 170 static void setup_interrupt_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx, 171 xhci_trb_ring_t *ring, usb_superspeed_endpoint_companion_descriptor_t *ss_desc) 172 { 173 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep)); 174 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size & 0x07FF); 175 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ss_desc->max_burst); 176 XHCI_EP_MULT_SET(*ctx, 0); 177 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 178 /* FIXME physical pointer? */ 179 XHCI_EP_TR_DPTR_SET(*ctx, ring->dequeue); 180 XHCI_EP_DCS_SET(*ctx, 1); 181 // TODO: max ESIT payload 86 182 } 87 183 … … 92 188 assert(!ep->device); 93 189 190 int err; 191 xhci_input_ctx_t *ictx = NULL; 192 xhci_trb_ring_t *ep_ring = NULL; 193 if (ep->base.target.endpoint > 0) { 194 // FIXME: Retrieve this from somewhere, if applicable. 195 usb_superspeed_endpoint_companion_descriptor_t ss_desc; 196 memset(&ss_desc, 0, sizeof(ss_desc)); 197 198 // Prepare input context. 199 ictx = malloc(sizeof(xhci_input_ctx_t)); 200 if (!ictx) { 201 return ENOMEM; 202 } 203 204 memset(ictx, 0, sizeof(xhci_input_ctx_t)); 205 206 // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up. 207 XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1); 208 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0); 209 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1); 210 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0); 211 212 const uint8_t ep_offset = xhci_endpoint_ctx_offset(ep); 213 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_offset); 214 215 ep_ring = malloc(sizeof(xhci_trb_ring_t)); 216 if (!ep_ring) { 217 err = ENOMEM; 218 goto err_ictx; 219 } 220 221 // FIXME: This ring need not be allocated all the time. 222 err = xhci_trb_ring_init(ep_ring); 223 if (err) 224 goto err_ring; 225 226 switch (ep->base.transfer_type) { 227 case USB_TRANSFER_CONTROL: 228 setup_control_ep_ctx(ep, &ictx->endpoint_ctx[ep_offset], ep_ring); 229 break; 230 231 case USB_TRANSFER_BULK: 232 setup_bulk_ep_ctx(ep, &ictx->endpoint_ctx[ep_offset], ep_ring, &ss_desc); 233 break; 234 235 case USB_TRANSFER_ISOCHRONOUS: 236 setup_isoch_ep_ctx(ep, &ictx->endpoint_ctx[ep_offset], ep_ring, &ss_desc); 237 break; 238 239 case USB_TRANSFER_INTERRUPT: 240 setup_interrupt_ep_ctx(ep, &ictx->endpoint_ctx[ep_offset], ep_ring, &ss_desc); 241 break; 242 243 } 244 245 dev->hc->dcbaa_virt[dev->slot_id].trs[ep->base.target.endpoint] = ep_ring; 246 247 // Issue configure endpoint command (sec 4.3.5). 248 xhci_cmd_t cmd; 249 xhci_cmd_init(&cmd); 250 251 cmd.slot_id = dev->slot_id; 252 xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx); 253 if ((err = xhci_cmd_wait(&cmd, 100000)) != EOK) 254 goto err_cmd; 255 256 xhci_cmd_fini(&cmd); 257 } 258 94 259 ep->device = dev; 95 260 dev->endpoints[ep->base.target.endpoint] = ep; 96 261 ++dev->active_endpoint_count; 97 262 return EOK; 263 264 err_cmd: 265 err_ring: 266 if (ep_ring) { 267 xhci_trb_ring_fini(ep_ring); 268 free(ep_ring); 269 } 270 err_ictx: 271 free(ictx); 272 return err; 98 273 } 99 274 … … 103 278 assert(dev->endpoints[ep->base.target.endpoint]); 104 279 assert(dev == ep->device); 280 281 // TODO: Issue configure endpoint command to drop this endpoint. 105 282 106 283 ep->device = NULL; -
uspace/drv/bus/usb/xhci/endpoint.h
r816f5f4 r9b2f69e 49 49 typedef struct xhci_bus xhci_bus_t; 50 50 51 #define XHCI_DEVICE_MAX_ENDPOINTS 3252 53 51 enum { 54 52 EP_TYPE_INVALID = 0, … … 81 79 82 80 /** All endpoints of the device. Inactive ones are NULL */ 83 xhci_endpoint_t *endpoints[XHCI_ DEVICE_MAX_ENDPOINTS];81 xhci_endpoint_t *endpoints[XHCI_EP_COUNT]; 84 82 85 83 /** Number of non-NULL endpoints. Reference count of sorts. */ 86 84 uint8_t active_endpoint_count; 85 86 /** Need HC to schedule commands from bus callbacks. TODO: Move this elsewhere. */ 87 xhci_hc_t *hc; 88 89 /** Flag indicating whether the device is USB3 (it's USB2 otherwise). */ 90 bool usb3; 87 91 } xhci_device_t; 88 92 -
uspace/drv/bus/usb/xhci/hc.c
r816f5f4 r9b2f69e 201 201 } 202 202 203 if ((err = xhci_trb_ring_init(&hc->command_ring , hc)))203 if ((err = xhci_trb_ring_init(&hc->command_ring))) 204 204 goto err_dcbaa_virt; 205 205 206 if ((err = xhci_event_ring_init(&hc->event_ring , hc)))206 if ((err = xhci_event_ring_init(&hc->event_ring))) 207 207 goto err_cmd_ring; 208 208 … … 462 462 assert(batch); 463 463 464 usb_log_debug2("E P(%d:%d) started %s transfer of size %lu.",464 usb_log_debug2("Endpoint(%d:%d) started %s transfer of size %lu.", 465 465 batch->ep->target.address, batch->ep->target.endpoint, 466 466 usb_str_transfer_type(batch->ep->transfer_type), … … 482 482 return xhci_schedule_bulk_transfer(hc, batch); 483 483 case USB_TRANSFER_INTERRUPT: 484 /* TODO: Implement me. */ 485 usb_log_error("Interrupt transfers are not yet implemented!"); 486 return ENOTSUP; 484 return xhci_schedule_interrupt_transfer(hc, batch); 487 485 } 488 486 -
uspace/drv/bus/usb/xhci/rh.c
r816f5f4 r9b2f69e 120 120 } 121 121 122 err = xhci_trb_ring_init(ep_ring , hc);122 err = xhci_trb_ring_init(ep_ring); 123 123 if (err) 124 124 goto err_ring; … … 181 181 xhci_dev->device = dev; 182 182 xhci_dev->slot_id = slot_id; 183 xhci_dev->usb3 = speed->major == 3; 184 xhci_dev->hc = hc; 183 185 184 186 // TODO: Save anything else? -
uspace/drv/bus/usb/xhci/transfers.c
r816f5f4 r9b2f69e 266 266 } 267 267 268 int xhci_schedule_bulk_transfer(xhci_hc_t* hc, usb_transfer_batch_t* batch) { 268 int xhci_schedule_bulk_transfer(xhci_hc_t* hc, usb_transfer_batch_t* batch) 269 { 269 270 if (batch->setup_size) { 270 271 usb_log_warning("Setup packet present for a bulk transfer."); … … 276 277 277 278 xhci_transfer_t *transfer = xhci_transfer_alloc(batch); 278 memcpy(transfer->hc_buffer, batch->buffer, batch->buffer_size); 279 if (!transfer->direction) { 280 // Sending stuff from host to device, we need to copy the actual data. 281 memcpy(transfer->hc_buffer, batch->buffer, batch->buffer_size); 282 } 279 283 280 284 xhci_trb_t trb; … … 300 304 } 301 305 306 int xhci_schedule_interrupt_transfer(xhci_hc_t* hc, usb_transfer_batch_t* batch) 307 { 308 /* FIXME: Removing the next 2 rows causes QEMU to crash lol */ 309 usb_log_warning("Interrupt transfers not yet implemented!"); 310 return ENOTSUP; 311 312 if (batch->setup_size) { 313 usb_log_warning("Setup packet present for a interrupt transfer."); 314 } 315 316 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep); 317 uint8_t slot_id = xhci_ep->device->slot_id; 318 xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[batch->ep->target.endpoint]; 319 320 xhci_transfer_t *transfer = xhci_transfer_alloc(batch); 321 if (!transfer->direction) { 322 // Sending stuff from host to device, we need to copy the actual data. 323 memcpy(transfer->hc_buffer, batch->buffer, batch->buffer_size); 324 } 325 326 xhci_trb_t trb; 327 memset(&trb, 0, sizeof(xhci_trb_t)); 328 trb.parameter = addr_to_phys(transfer->hc_buffer); 329 330 // data size (sent for OUT, or buffer size) 331 TRB_CTRL_SET_XFER_LEN(trb, batch->buffer_size); 332 // FIXME: TD size 4.11.2.4 333 TRB_CTRL_SET_TD_SIZE(trb, 1); 334 335 // we want an interrupt after this td is done 336 TRB_CTRL_SET_IOC(trb, 1); 337 338 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 339 340 xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); 341 list_append(&transfer->link, &hc->transfers); 342 343 const uint8_t target = 2 * batch->ep->target.endpoint 344 + (batch->ep->direction == USB_DIRECTION_IN ? 1 : 0); 345 usb_log_debug("Ringing doorbell for slot_id = %d, target = %d", slot_id, target); 346 return hc_ring_doorbell(hc, slot_id, target); 347 } 348 302 349 int xhci_handle_transfer_event(xhci_hc_t* hc, xhci_trb_t* trb) 303 350 { -
uspace/drv/bus/usb/xhci/transfers.h
r816f5f4 r9b2f69e 54 54 int xhci_schedule_control_transfer(xhci_hc_t*, usb_transfer_batch_t*); 55 55 int xhci_schedule_bulk_transfer(xhci_hc_t*, usb_transfer_batch_t*); 56 int xhci_schedule_interrupt_transfer(xhci_hc_t*, usb_transfer_batch_t*); 56 57 int xhci_handle_transfer_event(xhci_hc_t*, xhci_trb_t*); -
uspace/drv/bus/usb/xhci/trb_ring.c
r816f5f4 r9b2f69e 92 92 * Event when it fails, the structure needs to be finalized. 93 93 */ 94 int xhci_trb_ring_init(xhci_trb_ring_t *ring , xhci_hc_t *hc)94 int xhci_trb_ring_init(xhci_trb_ring_t *ring) 95 95 { 96 96 struct trb_segment *segment; … … 237 237 * Even when it fails, the structure needs to be finalized. 238 238 */ 239 int xhci_event_ring_init(xhci_event_ring_t *ring , xhci_hc_t *hc)239 int xhci_event_ring_init(xhci_event_ring_t *ring) 240 240 { 241 241 struct trb_segment *segment; -
uspace/drv/bus/usb/xhci/trb_ring.h
r816f5f4 r9b2f69e 73 73 } xhci_trb_ring_t; 74 74 75 int xhci_trb_ring_init(xhci_trb_ring_t * , xhci_hc_t *);75 int xhci_trb_ring_init(xhci_trb_ring_t *); 76 76 int xhci_trb_ring_fini(xhci_trb_ring_t *); 77 77 int xhci_trb_ring_enqueue(xhci_trb_ring_t *, xhci_trb_t *, uintptr_t *); … … 110 110 } xhci_event_ring_t; 111 111 112 int xhci_event_ring_init(xhci_event_ring_t * , xhci_hc_t *);112 int xhci_event_ring_init(xhci_event_ring_t *); 113 113 int xhci_event_ring_fini(xhci_event_ring_t *); 114 114 int xhci_event_ring_dequeue(xhci_event_ring_t *, xhci_trb_t *);
Note:
See TracChangeset
for help on using the changeset viewer.