Changeset 9b2f69e in mainline for uspace/drv/bus/usb/xhci/endpoint.c
- Timestamp:
- 2017-10-15T20:08:16Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b7db009
- Parents:
- 816f5f4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note:
See TracChangeset
for help on using the changeset viewer.