Changeset 2b61945 in mainline
- Timestamp:
- 2017-10-22T03:47:41Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2e5aea1
- Parents:
- 766043c
- Location:
- uspace
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/bus.c
r766043c r2b61945 35 35 #include <adt/hash_table.h> 36 36 #include <adt/hash.h> 37 #include <usb/host/utils/malloc32.h> 37 38 #include <usb/host/ddf_helpers.h> 38 39 #include <usb/host/endpoint.h> … … 58 59 } hashed_device_t; 59 60 61 static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev); 62 static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev); 63 static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev); 64 60 65 /** TODO: Still some copy-pasta left... 61 66 */ … … 63 68 { 64 69 int err; 70 xhci_device_t *xhci_dev = xhci_device_get(dev); 65 71 66 72 /* TODO: get speed from the default address reservation */ … … 85 91 } 86 92 93 assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL); 94 bus->devices_by_slot[xhci_dev->slot_id] = xhci_dev; 95 96 hashed_device_t *hashed_dev = NULL; 97 if ((err = hashed_device_insert(bus, &hashed_dev, xhci_dev))) 98 goto err_address; 99 87 100 /* Read the device descriptor, derive the match ids */ 88 101 if ((err = hcd_ddf_device_explore(hc->hcd, dev))) { 89 102 usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err)); 90 bus_release_address(&bus->base, dev->address); 91 return err; 92 } 93 94 return EOK; 103 goto err_hash; 104 } 105 106 return EOK; 107 108 err_hash: 109 bus->devices_by_slot[xhci_dev->slot_id] = NULL; 110 hashed_device_remove(bus, hashed_dev); 111 err_address: 112 bus_release_address(&bus->base, dev->address); 113 return err; 95 114 } 96 115 97 116 int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev) 98 117 { 99 // TODO: Implement me! 118 xhci_device_t *xhci_dev = xhci_device_get(dev); 119 120 // TODO: Release remaining EPs 121 122 hashed_device_t *hashed_dev; 123 int res = hashed_device_find_by_address(bus, dev->address, &hashed_dev); 124 if (res) 125 return res; 126 127 res = hashed_device_remove(bus, hashed_dev); 128 if (res != EOK) 129 return res; 130 131 // XXX: Ugly here. Move to device_destroy at endpoint.c? 132 free32(xhci_dev->dev_ctx); 133 hc->dcbaa[xhci_dev->slot_id] = 0; 100 134 return ENOTSUP; 101 135 } … … 134 168 xhci_bus_t *bus = bus_to_xhci_bus(base); 135 169 136 xhci_endpoint_t *ep = malloc(sizeof(xhci_endpoint_t));170 xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t)); 137 171 if (!ep) 138 172 return NULL; … … 179 213 } 180 214 181 static int hashed_device_create(xhci_bus_t *bus, hashed_device_t **hashed_dev, usb_address_t address) 182 { 183 int res; 184 xhci_device_t *dev = (xhci_device_t *) malloc(sizeof(xhci_device_t)); 185 if (!dev) { 186 res = ENOMEM; 187 goto err_xhci_dev_alloc; 188 } 189 190 res = xhci_device_init(dev, bus, address); 191 if (res != EOK) { 192 goto err_xhci_dev_init; 193 } 194 195 hashed_device_t *ret_dev = (hashed_device_t *) malloc(sizeof(hashed_device_t)); 196 if (!ret_dev) { 197 res = ENOMEM; 198 goto err_hashed_dev_alloc; 199 } 215 static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev) 216 { 217 hashed_device_t *ret_dev = (hashed_device_t *) calloc(1, sizeof(hashed_device_t)); 218 if (!ret_dev) 219 return ENOMEM; 200 220 201 221 ret_dev->device = dev; 202 222 203 usb_log_info("Device(%d) registered to XHCI bus.", dev-> address);223 usb_log_info("Device(%d) registered to XHCI bus.", dev->base.address); 204 224 205 225 hash_table_insert(&bus->devices, &ret_dev->link); 206 226 *hashed_dev = ret_dev; 207 227 return EOK; 208 209 err_hashed_dev_alloc:210 err_xhci_dev_init:211 free(dev);212 err_xhci_dev_alloc:213 return res;214 228 } 215 229 216 230 static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev) 217 231 { 218 usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->address); 219 220 hash_table_remove(&bus->devices, &hashed_dev->device->address); 221 xhci_device_fini(hashed_dev->device); 222 free(hashed_dev->device); 232 usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->base.address); 233 234 hash_table_remove(&bus->devices, &hashed_dev->device->base.address); 223 235 free(hashed_dev); 224 236 … … 231 243 assert(bus); 232 244 233 hashed_device_t *hashed_dev;234 int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);235 if (res != EOK && res != ENOENT)236 return res;237 238 if (res == ENOENT) {239 res = hashed_device_create(bus, &hashed_dev, ep->target.address);240 241 if (res != EOK)242 return res;243 }244 245 245 usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint); 246 246 247 return xhci_device_add_endpoint(hashed_dev->device, xhci_endpoint_get(ep)); 247 xhci_device_t *xhci_dev = xhci_device_get(ep->device); 248 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep); 249 return xhci_device_add_endpoint(xhci_dev, xhci_ep); 248 250 } 249 251 … … 255 257 usb_log_info("Endpoint(%d:%d) released from XHCI bus.", ep->target.address, ep->target.endpoint); 256 258 257 hashed_device_t *hashed_dev; 258 int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev); 259 xhci_device_t *xhci_dev = xhci_device_get(ep->device); 260 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep); 261 const int res = xhci_device_remove_endpoint(xhci_dev, xhci_ep); 259 262 if (res != EOK) 260 263 return res; 261 264 262 res = xhci_device_remove_endpoint(hashed_dev->device, xhci_endpoint_get(ep));263 if (res != EOK)264 return res;265 266 if (hashed_dev->device->active_endpoint_count == 0) {267 res = hashed_device_remove(bus, hashed_dev);268 269 if (res != EOK)270 return res;271 }272 273 265 return EOK; 274 266 } … … 278 270 xhci_bus_t *bus = bus_to_xhci_bus(bus_base); 279 271 assert(bus); 280 272 281 273 xhci_endpoint_t *ep; 282 274 int res = xhci_endpoint_find_by_target(bus, target, &ep); … … 349 341 { 350 342 hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link); 351 return (size_t) hash_mix(dev->device-> address);343 return (size_t) hash_mix(dev->device->base.address); 352 344 } 353 345 … … 360 352 { 361 353 hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link); 362 return dev->device-> address == *(usb_address_t *) key;354 return dev->device->base.address == *(usb_address_t *) key; 363 355 } 364 356 … … 372 364 }; 373 365 374 int xhci_bus_init(xhci_bus_t *bus) 375 { 376 assert(bus); 377 378 bus_init(&bus->base, sizeof(device_t)); 366 int xhci_bus_init(xhci_bus_t *bus, xhci_hc_t *hc) 367 { 368 assert(bus); 369 370 bus_init(&bus->base, sizeof(xhci_device_t)); 371 372 bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *)); 373 if (!bus->devices_by_slot) 374 return ENOMEM; 379 375 380 376 if (!hash_table_create(&bus->devices, 0, 0, &device_ht_ops)) { 381 // FIXME: Dealloc base!377 free(bus->devices_by_slot); 382 378 return ENOMEM; 383 379 } -
uspace/drv/bus/usb/xhci/bus.h
r766043c r2b61945 43 43 44 44 typedef struct xhci_hc xhci_hc_t; 45 typedef struct xhci_device xhci_device_t; 45 46 46 47 /** Endpoint management structure */ … … 48 49 bus_t base; /**< Inheritance. Keep this first. */ 49 50 50 /** TODO: some mechanism to keep endpoints alive :) 51 * We may inspire in the usb2_bus, but keep in mind xHCI have much 52 * larger address space, thus simple array of lists for all available 53 * addresses can be just too big. 54 */ 51 xhci_device_t **devices_by_slot; /**< Devices by Slot ID */ 55 52 56 hash_table_t devices; 53 /** TODO: Do we really need this? */ 54 hash_table_t devices; /**< Devices by address */ 57 55 } xhci_bus_t; 58 56 59 int xhci_bus_init(xhci_bus_t * );57 int xhci_bus_init(xhci_bus_t *, xhci_hc_t *); 60 58 void xhci_bus_fini(xhci_bus_t *); 61 59 -
uspace/drv/bus/usb/xhci/endpoint.c
r766043c r2b61945 53 53 54 54 endpoint_init(ep, bus); 55 xhci_ep->device = NULL; 56 57 return EOK; 55 56 return xhci_trb_ring_init(&xhci_ep->ring); 58 57 } 59 58 … … 63 62 64 63 /* FIXME: Tear down TR's? */ 65 } 66 67 int xhci_device_init(xhci_device_t *dev, xhci_bus_t *bus, usb_address_t address) 68 { 69 memset(&dev->endpoints, 0, sizeof(dev->endpoints)); 70 dev->active_endpoint_count = 0; 71 dev->address = address; 72 dev->slot_id = 0; 73 74 return EOK; 75 } 76 77 void xhci_device_fini(xhci_device_t *dev) 78 { 79 // TODO: Check that all endpoints are dead. 80 assert(dev); 64 xhci_trb_ring_fini(&xhci_ep->ring); 65 } 66 67 /** See section 4.5.1 of the xHCI spec. 68 */ 69 uint8_t xhci_endpoint_dci(xhci_endpoint_t *ep) 70 { 71 return (2 * ep->base.target.endpoint) + 72 (ep->base.transfer_type == USB_TRANSFER_CONTROL 73 || ep->base.direction == USB_DIRECTION_IN); 81 74 } 82 75 … … 93 86 uint8_t xhci_endpoint_index(xhci_endpoint_t *ep) 94 87 { 95 return (2 * ep->base.target.endpoint) 96 - (ep->base.direction == USB_DIRECTION_OUT); 88 return xhci_endpoint_dci(ep) - 1; 97 89 } 98 90 … … 139 131 XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep)); 140 132 XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size); 141 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ep->device->usb3 ? ss_desc->max_burst : 0); 133 XHCI_EP_MAX_BURST_SIZE_SET(*ctx, 134 xhci_device_get(ep->base.device)->usb3 ? ss_desc->max_burst : 0); 142 135 XHCI_EP_ERROR_COUNT_SET(*ctx, 3); 143 136 … … 186 179 int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep) 187 180 { 188 assert(dev->address == ep->base.target.address); 189 assert(!dev->endpoints[ep->base.target.endpoint]); 190 assert(!ep->device); 191 192 int err; 193 xhci_input_ctx_t *ictx = NULL; 194 xhci_trb_ring_t *ep_ring = NULL; 195 if (ep->base.target.endpoint > 0) { 196 // FIXME: Retrieve this from somewhere, if applicable. 197 usb_superspeed_endpoint_companion_descriptor_t ss_desc; 198 memset(&ss_desc, 0, sizeof(ss_desc)); 199 200 // Prepare input context. 201 ictx = malloc32(sizeof(xhci_input_ctx_t)); 202 if (!ictx) { 203 return ENOMEM; 204 } 205 206 memset(ictx, 0, sizeof(xhci_input_ctx_t)); 207 208 // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up. 209 XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1); 210 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0); 211 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1); 212 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0); 213 214 const uint8_t ep_idx = xhci_endpoint_index(ep); 215 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */ 216 217 ep_ring = malloc(sizeof(xhci_trb_ring_t)); 218 if (!ep_ring) { 219 err = ENOMEM; 220 goto err_ictx; 221 } 222 223 // FIXME: This ring need not be allocated all the time. 224 err = xhci_trb_ring_init(ep_ring); 225 if (err) 226 goto err_ring; 227 228 switch (ep->base.transfer_type) { 229 case USB_TRANSFER_CONTROL: 230 setup_control_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring); 231 break; 232 233 case USB_TRANSFER_BULK: 234 setup_bulk_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 235 break; 236 237 case USB_TRANSFER_ISOCHRONOUS: 238 setup_isoch_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 239 break; 240 241 case USB_TRANSFER_INTERRUPT: 242 setup_interrupt_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc); 243 break; 244 245 } 246 247 dev->hc->dcbaa_virt[dev->slot_id].trs[ep->base.target.endpoint] = ep_ring; 248 249 // Issue configure endpoint command (sec 4.3.5). 250 xhci_cmd_t cmd; 251 xhci_cmd_init(&cmd); 252 253 cmd.slot_id = dev->slot_id; 254 xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx); 255 if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK) 256 goto err_cmd; 257 258 xhci_cmd_fini(&cmd); 181 assert(dev); 182 assert(ep); 183 184 int err = ENOMEM; 185 usb_endpoint_t ep_num = ep->base.target.endpoint; 186 187 assert(&dev->base == ep->base.device); 188 assert(dev->base.address == ep->base.target.address); 189 assert(!dev->endpoints[ep_num]); 190 191 dev->endpoints[ep_num] = ep; 192 ++dev->active_endpoint_count; 193 194 if (ep_num == 0) 195 /* EP 0 is initialized while setting up the device, 196 * so we must not issue the command now. */ 197 return EOK; 198 199 // FIXME: Retrieve this from somewhere, if applicable. 200 usb_superspeed_endpoint_companion_descriptor_t ss_desc; 201 memset(&ss_desc, 0, sizeof(ss_desc)); 202 203 // Prepare input context. 204 xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t)); 205 if (!ictx) 206 goto err; 207 208 memset(ictx, 0, sizeof(xhci_input_ctx_t)); 209 210 // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up. 211 XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1); 212 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0); 213 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1); 214 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0); 215 216 unsigned ep_idx = xhci_endpoint_index(ep); 217 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */ 218 219 xhci_trb_ring_t *ep_ring = &ep->ring; 220 xhci_ep_ctx_t *ep_ctx = &ictx->endpoint_ctx[ep_idx]; 221 222 // TODO: Convert to table 223 switch (ep->base.transfer_type) { 224 case USB_TRANSFER_CONTROL: 225 setup_control_ep_ctx(ep, ep_ctx, ep_ring); 226 break; 227 228 case USB_TRANSFER_BULK: 229 setup_bulk_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc); 230 break; 231 232 case USB_TRANSFER_ISOCHRONOUS: 233 setup_isoch_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc); 234 break; 235 236 case USB_TRANSFER_INTERRUPT: 237 setup_interrupt_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc); 238 break; 259 239 } 260 240 261 ep->device = dev; 262 dev->endpoints[ep->base.target.endpoint] = ep; 263 ++dev->active_endpoint_count; 241 // Issue configure endpoint command (sec 4.3.5). 242 xhci_cmd_t cmd; 243 xhci_cmd_init(&cmd); 244 245 cmd.slot_id = dev->slot_id; 246 xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx); 247 if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK) 248 goto err_ictx; 249 250 xhci_cmd_fini(&cmd); 251 252 free32(ictx); 264 253 return EOK; 265 254 266 err_cmd:267 err_ring:268 if (ep_ring) {269 xhci_trb_ring_fini(ep_ring);270 free(ep_ring);271 }272 255 err_ictx: 273 free(ictx); 256 free32(ictx); 257 err: 258 dev->endpoints[ep_idx] = NULL; 259 dev->active_endpoint_count--; 274 260 return err; 275 261 } … … 277 263 int xhci_device_remove_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep) 278 264 { 279 assert(dev->address == ep->base.target.address); 265 assert(&dev->base == ep->base.device); 266 assert(dev->base.address == ep->base.target.address); 280 267 assert(dev->endpoints[ep->base.target.endpoint]); 281 assert(dev == ep->device);282 268 283 269 // TODO: Issue configure endpoint command to drop this endpoint. 284 270 285 ep->device = NULL;286 271 dev->endpoints[ep->base.target.endpoint] = NULL; 287 272 --dev->active_endpoint_count; -
uspace/drv/bus/usb/xhci/endpoint.h
r766043c r2b61945 44 44 45 45 #include "hc.h" 46 #include "transfers.h" 46 47 47 48 typedef struct xhci_device xhci_device_t; … … 64 65 endpoint_t base; /**< Inheritance. Keep this first. */ 65 66 66 /** Parent device. */ 67 xhci_device_t *device; 67 /** Main TRB ring */ 68 xhci_trb_ring_t ring; 69 70 /** There shall be only one transfer active on an endpoint. The 71 * synchronization is performed using the active flag in base 72 * endpoint_t */ 73 xhci_transfer_t active_transfer; 68 74 } xhci_endpoint_t; 69 75 70 76 typedef struct xhci_device { 71 /** Unique USB address assigned to the device. */ 72 usb_address_t address; 77 device_t base; /**< Inheritance. Keep this first. */ 73 78 74 79 /** Slot ID assigned to the device by xHC. */ 75 80 uint32_t slot_id; 76 81 77 /** Associated device in libusbhost.*/78 device_t *device;82 /** Place to store virtual address for allocated context */ 83 xhci_device_ctx_t *dev_ctx; 79 84 80 85 /** All endpoints of the device. Inactive ones are NULL */ … … 97 102 void xhci_device_fini(xhci_device_t *); 98 103 104 uint8_t xhci_endpoint_dci(xhci_endpoint_t *); 99 105 uint8_t xhci_endpoint_index(xhci_endpoint_t *); 100 106 … … 104 110 int xhci_device_configure(xhci_device_t *, xhci_hc_t *); 105 111 112 static inline xhci_device_t * xhci_device_get(device_t *dev) 113 { 114 assert(dev); 115 return (xhci_device_t *) dev; 116 } 117 106 118 static inline xhci_endpoint_t * xhci_endpoint_get(endpoint_t *ep) 107 119 { 108 120 assert(ep); 109 121 return (xhci_endpoint_t *) ep; 122 } 123 124 static inline xhci_device_t * xhci_ep_to_dev(xhci_endpoint_t *ep) 125 { 126 assert(ep); 127 return xhci_device_get(ep->base.device); 110 128 } 111 129 -
uspace/drv/bus/usb/xhci/hc.c
r766043c r2b61945 196 196 return ENOMEM; 197 197 198 hc->dcbaa_virt = malloc((1 + hc->max_slots) * sizeof(xhci_virt_device_ctx_t)); 199 if (!hc->dcbaa_virt) { 200 err = ENOMEM; 198 if ((err = xhci_trb_ring_init(&hc->command_ring))) 201 199 goto err_dcbaa; 202 }203 204 if ((err = xhci_trb_ring_init(&hc->command_ring)))205 goto err_dcbaa_virt;206 200 207 201 if ((err = xhci_event_ring_init(&hc->event_ring))) … … 214 208 goto err_scratch; 215 209 216 if ((err = xhci_ init_transfers(hc)))210 if ((err = xhci_rh_init(&hc->rh, hc, device))) 217 211 goto err_cmd; 218 212 219 if ((err = xhci_rh_init(&hc->rh, hc, device))) 220 goto err_transfers; 221 222 if ((err = xhci_bus_init(&hc->bus))) 213 if ((err = xhci_bus_init(&hc->bus, hc))) 223 214 goto err_rh; 224 215 … … 228 219 err_rh: 229 220 xhci_rh_fini(&hc->rh); 230 err_transfers:231 xhci_fini_transfers(hc);232 221 err_cmd: 233 222 xhci_fini_commands(hc); … … 238 227 err_cmd_ring: 239 228 xhci_trb_ring_fini(&hc->command_ring); 240 err_dcbaa_virt:241 free32(hc->dcbaa_virt);242 229 err_dcbaa: 243 230 free32(hc->dcbaa); … … 527 514 /* Update the ERDP to make room in the ring. */ 528 515 usb_log_debug2("Copying from ring finished, updating ERDP."); 529 hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb));530 516 uint64_t erdp = hc->event_ring.dequeue_ptr; 531 517 XHCI_REG_WR(intr, XHCI_INTR_ERDP_LO, LOWER32(erdp)); … … 580 566 static void hc_dcbaa_fini(xhci_hc_t *hc) 581 567 { 582 xhci_trb_ring_t* trb_ring;583 568 xhci_scratchpad_free(hc); 584 585 /* Idx 0 already deallocated by xhci_scratchpad_free. */586 for (unsigned i = 1; i < hc->max_slots + 1; ++i) {587 if (hc->dcbaa_virt[i].dev_ctx) {588 free32(hc->dcbaa_virt[i].dev_ctx);589 hc->dcbaa_virt[i].dev_ctx = NULL;590 }591 592 for (unsigned i = 0; i < XHCI_EP_COUNT; ++i) {593 trb_ring = hc->dcbaa_virt[i].trs[i];594 if (trb_ring) {595 hc->dcbaa_virt[i].trs[i] = NULL;596 xhci_trb_ring_fini(trb_ring);597 free32(trb_ring);598 }599 }600 }601 602 569 free32(hc->dcbaa); 603 free32(hc->dcbaa_virt);604 570 } 605 571 … … 610 576 xhci_event_ring_fini(&hc->event_ring); 611 577 hc_dcbaa_fini(hc); 612 xhci_fini_transfers(hc);613 578 xhci_fini_commands(hc); 614 579 xhci_rh_fini(&hc->rh); -
uspace/drv/bus/usb/xhci/hc.h
r766043c r2b61945 46 46 #include "bus.h" 47 47 48 typedef struct xhci_virt_device_ctx {49 xhci_device_ctx_t *dev_ctx;50 xhci_trb_ring_t *trs[XHCI_EP_COUNT];51 } xhci_virt_device_ctx_t;52 53 48 typedef struct xhci_hc { 54 49 /* MMIO range */ … … 68 63 xhci_event_ring_t event_ring; 69 64 uint64_t *dcbaa; 70 xhci_virt_device_ctx_t *dcbaa_virt;71 65 xhci_scratchpad_t *scratchpad; 72 66 … … 84 78 list_t commands; 85 79 fibril_mutex_t commands_mtx; 86 87 list_t transfers;88 80 89 81 /* TODO: Hack. Figure out a better way. */ -
uspace/drv/bus/usb/xhci/hw_struct/trb.h
r766043c r2b61945 100 100 #define TRB_CYCLE(trb) XHCI_DWORD_EXTRACT((trb).control, 0, 0) 101 101 #define TRB_LINK_TC(trb) XHCI_DWORD_EXTRACT((trb).control, 1, 1) 102 #define TRB_IOC(trb) XHCI_DWORD_EXTRACT((trb).control, 5, 5) 102 103 103 104 #define TRB_TRANSFER_LENGTH(trb) XHCI_DWORD_EXTRACT((trb).status, 23, 0) -
uspace/drv/bus/usb/xhci/rh.c
r766043c r2b61945 92 92 } 93 93 94 // TODO: Check device deallocation, we free device_ctx in hc.c, not95 // sure about the other structs.96 94 // TODO: This currently assumes the device is attached to rh directly. 97 95 // Also, we should consider moving a lot of functionailty to xhci bus 98 96 int xhci_rh_address_device(xhci_rh_t *rh, device_t *dev, xhci_bus_t *bus) 99 97 { 98 int err; 99 xhci_device_t *xhci_dev = xhci_device_get(dev); 100 100 101 /* FIXME: Certainly not generic solution. */ 101 102 const uint32_t route_str = 0; 102 103 103 int err;104 xhci_hc_t *hc = rh->hc; 104 xhci_dev->hc = rh->hc; 105 105 106 const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, dev->port); 107 xhci_dev->usb3 = speed->major == 3; 106 108 107 109 /* Enable new slot */ 108 uint32_t slot_id; 109 if ((err = hc_enable_slot(hc, &slot_id)) != EOK) 110 if ((err = hc_enable_slot(rh->hc, &xhci_dev->slot_id)) != EOK) 110 111 return err; 111 usb_log_debug2("Obtained slot ID: %u.\n", slot_id);112 usb_log_debug2("Obtained slot ID: %u.\n", xhci_dev->slot_id); 112 113 113 114 /* Setup input context */ 114 xhci_input_ctx_t *ictx = malloc (sizeof(xhci_input_ctx_t));115 xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t)); 115 116 if (!ictx) 116 117 return ENOMEM; … … 126 127 XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, route_str); 127 128 128 xhci_trb_ring_t *ep_ring = malloc(sizeof(xhci_trb_ring_t)); 129 if (!ep_ring) { 130 err = ENOMEM; 129 endpoint_t *ep0_base = bus_create_endpoint(&rh->hc->bus.base); 130 if (!ep0_base) 131 131 goto err_ictx; 132 } 133 134 err = xhci_trb_ring_init(ep_ring); 135 if (err) 136 goto err_ring; 137 setup_control_ep0_ctx(&ictx->endpoint_ctx[0], ep_ring, speed); 132 xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base); 133 setup_control_ep0_ctx(&ictx->endpoint_ctx[0], &ep0->ring, speed); 138 134 139 135 /* Setup and register device context */ … … 141 137 if (!dctx) { 142 138 err = ENOMEM; 143 goto err_ring; 144 } 139 goto err_ep; 140 } 141 xhci_dev->dev_ctx = dctx; 142 rh->hc->dcbaa[xhci_dev->slot_id] = addr_to_phys(dctx); 145 143 memset(dctx, 0, sizeof(xhci_device_ctx_t)); 146 hc->dcbaa[slot_id] = addr_to_phys(dctx);147 148 memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t));149 hc->dcbaa_virt[slot_id].dev_ctx = dctx;150 hc->dcbaa_virt[slot_id].trs[0] = ep_ring;151 144 152 145 /* Address device */ 153 if ((err = hc_address_device( hc,slot_id, ictx)) != EOK)146 if ((err = hc_address_device(rh->hc, xhci_dev->slot_id, ictx)) != EOK) 154 147 goto err_dctx; 155 148 dev->address = XHCI_SLOT_DEVICE_ADDRESS(dctx->slot_ctx); 156 149 usb_log_debug2("Obtained USB address: %d.\n", dev->address); 157 150 158 // Ask libusbhost to create a control endpoint for EP0. 159 bus_t *bus_base = &bus->base; 160 usb_target_t ep0_target = { .address = dev->address, .endpoint = 0 }; 161 usb_direction_t ep0_direction = USB_DIRECTION_BOTH; 162 163 // TODO: Should this call be unified with other calls to `bus_add_ep()`? 164 err = bus_add_ep(bus_base, dev, ep0_target.endpoint, ep0_direction, 165 USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1); 166 167 if (err != EOK) 168 goto err_add_ep; 169 170 // Save all data structures in the corresponding xhci_device_t. 171 endpoint_t *ep0_base = bus_find_endpoint(bus_base, ep0_target, ep0_direction); 172 xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base); 173 xhci_device_t *xhci_dev = ep0->device; 174 175 xhci_dev->device = dev; 176 xhci_dev->slot_id = slot_id; 177 xhci_dev->usb3 = speed->major == 3; 178 xhci_dev->hc = hc; 151 // XXX: Going around bus, duplicating code 152 ep0_base->device = dev; 153 ep0_base->target.address = dev->address; 154 ep0_base->target.endpoint = 0; 155 ep0_base->direction = USB_DIRECTION_BOTH; 156 ep0_base->transfer_type = USB_TRANSFER_CONTROL; 157 ep0_base->max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE; 158 ep0_base->packets = 1; 159 ep0_base->bandwidth = CTRL_PIPE_MIN_PACKET_SIZE; 160 161 bus_register_endpoint(&rh->hc->bus.base, ep0_base); 179 162 180 163 if (!rh->devices[dev->port - 1]) { … … 183 166 } 184 167 185 return EOK;186 187 err_add_ep: 168 free32(ictx); 169 return EOK; 170 188 171 err_dctx: 189 if (dctx) { 190 free(dctx); 191 hc->dcbaa[slot_id] = 0; 192 memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t)); 193 } 194 err_ring: 195 if (ep_ring) { 196 xhci_trb_ring_fini(ep_ring); 197 free(ep_ring); 198 } 172 free32(dctx); 173 rh->hc->dcbaa[xhci_dev->slot_id] = 0; 174 err_ep: 175 xhci_endpoint_fini(ep0); 176 free(ep0); 199 177 err_ictx: 200 free (ictx);178 free32(ictx); 201 179 return err; 202 180 } -
uspace/drv/bus/usb/xhci/scratchpad.c
r766043c r2b61945 132 132 133 133 hc->dcbaa[0] = 0; 134 memset(&hc->dcbaa_virt[0], 0, sizeof(xhci_virt_device_ctx_t));135 134 136 135 return; -
uspace/drv/bus/usb/xhci/transfers.c
r766043c r2b61945 94 94 } 95 95 96 int xhci_init_transfers(xhci_hc_t *hc) 97 { 98 assert(hc); 99 100 list_initialize(&hc->transfers); 101 return EOK; 102 } 103 104 void xhci_fini_transfers(xhci_hc_t *hc) 105 { 106 // Note: Untested. 107 assert(hc); 108 } 109 110 xhci_transfer_t* xhci_transfer_create(endpoint_t* ep) { 111 xhci_transfer_t* transfer = calloc(1, sizeof(xhci_transfer_t)); 112 if (!transfer) 113 return NULL; 96 /** 97 * There can currently be only one active transfer, because 98 * usb_transfer_batch_init locks the endpoint by endpoint_use. 99 * Therefore, we store the only active transfer per endpoint there. 100 */ 101 xhci_transfer_t* xhci_transfer_create(endpoint_t* ep) 102 { 103 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep); 104 xhci_transfer_t *transfer = &xhci_ep->active_transfer; 105 106 /* Do not access the transfer yet, it may be still in use. */ 114 107 115 108 usb_transfer_batch_init(&transfer->batch, ep); 116 117 link_initialize(&transfer->link); 109 assert(ep->active); 110 111 /* Clean just our data. */ 112 memset(((void *) transfer) + sizeof(usb_transfer_batch_t), 0, 113 sizeof(xhci_transfer_t) - sizeof(usb_transfer_batch_t)); 118 114 119 115 return transfer; … … 126 122 if (transfer->hc_buffer) 127 123 free32(transfer->hc_buffer); 128 129 free(transfer);130 124 } 131 125 132 126 static xhci_trb_ring_t *get_ring(xhci_hc_t *hc, xhci_transfer_t *transfer) 133 127 { 134 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep); 135 uint8_t slot_id = xhci_ep->device->slot_id; 136 137 xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint]; 138 assert(ring); 139 return ring; 128 return &xhci_endpoint_get(transfer->batch.ep)->ring; 140 129 } 141 130 … … 202 191 // Issue a Configure Endpoint command, if needed. 203 192 if (configure_endpoint_needed(setup)) { 204 const int err = xhci_device_configure(xhci_ep ->device, hc);193 const int err = xhci_device_configure(xhci_ep_to_dev(xhci_ep), hc); 205 194 if (err) 206 195 return err; … … 226 215 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 227 216 228 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep); 229 uint8_t slot_id = xhci_ep->device->slot_id; 230 xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint]; 217 xhci_trb_ring_t* ring = get_ring(hc, transfer); 231 218 232 219 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); … … 249 236 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL); 250 237 251 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep); 252 uint8_t slot_id = xhci_ep->device->slot_id; 253 xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint]; 238 xhci_trb_ring_t* ring = get_ring(hc, transfer); 254 239 255 240 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys); … … 266 251 { 267 252 uintptr_t addr = trb->parameter; 268 xhci_transfer_t *transfer = NULL; 269 270 link_t *transfer_link = list_first(&hc->transfers); 271 while (transfer_link) { 272 transfer = list_get_instance(transfer_link, xhci_transfer_t, link); 273 274 if (transfer->interrupt_trb_phys == addr) 275 break; 276 277 transfer_link = list_next(transfer_link, &hc->transfers); 278 } 279 280 if (!transfer_link) { 281 usb_log_warning("Transfer not found."); 253 const unsigned slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24); 254 const unsigned ep_dci = XHCI_DWORD_EXTRACT(trb->control, 20, 16); 255 256 xhci_device_t *dev = hc->bus.devices_by_slot[slot_id]; 257 if (!dev) { 258 usb_log_error("Transfer event on unknown device slot %u!", slot_id); 282 259 return ENOENT; 283 260 } 284 261 285 list_remove(transfer_link); 262 const usb_endpoint_t ep_num = ep_dci / 2; 263 xhci_endpoint_t *ep = xhci_device_get_endpoint(dev, ep_num); 264 if (!ep) { 265 usb_log_error("Transfer event on unknown endpoint num %u, device slot %u!", ep_num, slot_id); 266 return ENOENT; 267 } 268 269 xhci_transfer_t *transfer = &ep->active_transfer; 270 271 /** FIXME: This is racy. Do we care? */ 272 ep->ring.dequeue = addr; 273 286 274 usb_transfer_batch_t *batch = &transfer->batch; 287 275 … … 314 302 xhci_transfer_t *transfer = xhci_transfer_from_batch(batch); 315 303 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep); 316 uint8_t slot_id = xhci_ep->device->slot_id;317 318 304 assert(xhci_ep); 319 assert(slot_id);320 305 321 306 const usb_transfer_type_t type = batch->ep->transfer_type; … … 336 321 return err; 337 322 338 list_append(&transfer->link, &hc->transfers); 339 323 const uint8_t slot_id = xhci_ep_to_dev(xhci_ep)->slot_id; 340 324 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */ 341 325 return hc_ring_doorbell(hc, slot_id, target); -
uspace/drv/bus/usb/xhci/transfers.h
r766043c r2b61945 54 54 } xhci_transfer_t; 55 55 56 int xhci_init_transfers(xhci_hc_t*);57 void xhci_fini_transfers(xhci_hc_t*);58 59 56 xhci_transfer_t* xhci_transfer_create(endpoint_t *); 60 57 int xhci_transfer_schedule(xhci_hc_t*, usb_transfer_batch_t *); -
uspace/drv/bus/usb/xhci/trb_ring.c
r766043c r2b61945 155 155 } 156 156 157 static bool trb_generates_interrupt(xhci_trb_t *trb) 158 { 159 return TRB_TYPE(*trb) >= XHCI_TRB_TYPE_ENABLE_SLOT_CMD 160 || TRB_IOC(*trb); 161 } 162 157 163 /** 158 164 * Enqueue TDs composed of TRBs. … … 188 194 xhci_trb_t *trb = first_trb; 189 195 for (size_t i = 0; i < trbs; ++i, ++trb) { 196 if (trb_generates_interrupt(trb)) { 197 if (*phys) 198 return ENOTSUP; 199 *phys = trb_ring_enqueue_phys(ring); 200 } 201 190 202 ring->enqueue_trb++; 191 203 … … 205 217 trb = first_trb; 206 218 for (size_t i = 0; i < trbs; ++i, ++trb) { 207 if (phys && i == trbs - 1)208 *phys = trb_ring_enqueue_phys(ring);209 210 219 xhci_trb_set_cycle(trb, ring->pcs); 211 220 xhci_trb_copy(ring->enqueue_trb, trb); -
uspace/lib/usbhost/src/hcd.c
r766043c r2b61945 41 41 #include <errno.h> 42 42 #include <usb_iface.h> 43 #include <str_error.h> 43 44 44 45 #include "hcd.h" … … 128 129 129 130 const int ret = hcd->ops.schedule(hcd, batch); 130 if (ret != EOK) 131 if (ret != EOK) { 132 usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret)); 131 133 usb_transfer_batch_destroy(batch); 134 } 132 135 133 136 /* Drop our own reference to ep. */ -
uspace/lib/usbhost/src/usb_transfer_batch.c
r766043c r2b61945 40 40 #include <assert.h> 41 41 #include <errno.h> 42 #include <str_error.h> 42 43 43 44 … … 62 63 void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep) 63 64 { 65 endpoint_use(ep); 66 64 67 memset(batch, 0, sizeof(*batch)); 65 66 68 batch->ep = ep; 67 68 endpoint_use(ep);69 69 } 70 70 … … 103 103 assert(batch->ep->bus); 104 104 105 usb_log_debug2("batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",106 batch, USB_TRANSFER_BATCH_ARGS(*batch));107 108 105 bus_t *bus = batch->ep->bus; 109 if (bus->ops.destroy_batch) 106 if (bus->ops.destroy_batch) { 107 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.\n", 108 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 110 109 bus->ops.destroy_batch(batch); 111 else 110 } 111 else { 112 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 113 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 112 114 free(batch); 115 } 113 116 114 117 endpoint_release(batch->ep); … … 123 126 void usb_transfer_batch_finish(usb_transfer_batch_t *batch) 124 127 { 125 if (!batch_complete(batch)) 126 usb_log_warning("failed to complete batch %p!", batch); 128 const int err = batch_complete(batch); 129 if (err) 130 usb_log_warning("batch %p failed to complete: %s", batch, str_error(err)); 127 131 128 132 usb_transfer_batch_destroy(batch); … … 159 163 struct old_handler_wrapper_data *data = malloc(sizeof(*data)); 160 164 165 assert((!in_callback) != (!out_callback)); 166 161 167 data->in_callback = in_callback; 162 168 data->out_callback = out_callback;
Note:
See TracChangeset
for help on using the changeset viewer.