Changeset 2b61945 in mainline for uspace/drv/bus/usb/xhci/endpoint.c
- Timestamp:
- 2017-10-22T03:47:41Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2e5aea1
- Parents:
- 766043c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note:
See TracChangeset
for help on using the changeset viewer.