Changeset 9876e34 in mainline
- Timestamp:
- 2017-10-05T15:38:02Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 916991b
- Parents:
- 44063d17
- Location:
- uspace/drv/bus/usb
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.h
r44063d17 r9876e34 59 59 /** Memory mapped I/O registers area */ 60 60 ohci_regs_t *registers; 61 61 62 /** Host controller communication area structure */ 62 63 hcca_t *hcca; … … 64 65 /** Transfer schedules */ 65 66 endpoint_list_t lists[4]; 67 66 68 /** List of active transfers */ 67 69 list_t pending_batches; -
uspace/drv/bus/usb/xhci/rh.c
r44063d17 r9876e34 51 51 static usbvirt_device_ops_t ops; 52 52 53 /* This mask only lists registers, which imply port change. */ 54 static const uint32_t port_change_mask = 55 XHCI_REG_MASK(XHCI_PORT_CSC) | 56 XHCI_REG_MASK(XHCI_PORT_PEC) | 57 XHCI_REG_MASK(XHCI_PORT_WRC) | 58 XHCI_REG_MASK(XHCI_PORT_OCC) | 59 XHCI_REG_MASK(XHCI_PORT_PRC) | 60 XHCI_REG_MASK(XHCI_PORT_PLC) | 61 XHCI_REG_MASK(XHCI_PORT_CEC); 62 53 63 int xhci_rh_init(xhci_rh_t *rh, xhci_hc_t *hc) 54 64 { … … 57 67 58 68 rh->hc = hc; 69 rh->max_ports = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PORTS); 59 70 60 71 usb_hub_descriptor_header_t *header = &rh->hub_descriptor.header; 61 72 header->length = sizeof(usb_hub_descriptor_header_t); 62 73 header->descriptor_type = USB_DESCTYPE_HUB; 63 header->port_count = XHCI_MAX_PORTS;74 header->port_count = rh->max_ports; 64 75 header->characteristics = 65 76 HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG; … … 73 84 // TODO: Check device deallocation, we free device_ctx in hc.c, not 74 85 // sure about the other structs. 75 static int alloc_dev(xhci_hc_t *hc, uint8_t port, uint32_t route_str)76 {77 int err;78 79 xhci_cmd_t cmd;80 xhci_cmd_init(&cmd);81 82 xhci_send_enable_slot_command(hc, &cmd);83 if ((err = xhci_cmd_wait(&cmd, 100000)) != EOK)84 return err;85 86 uint32_t slot_id = cmd.slot_id;87 88 usb_log_debug2("Obtained slot ID: %u.\n", slot_id);89 xhci_cmd_fini(&cmd);90 91 xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t));92 if (!ictx) {93 return ENOMEM;94 }95 96 memset(ictx, 0, sizeof(xhci_input_ctx_t));97 98 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);99 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 1);100 101 /* Initialize slot_ctx according to section 4.3.3 point 3. */102 /* Attaching to root hub port, root string equals to 0. */103 XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, port);104 XHCI_SLOT_CTX_ENTRIES_SET(ictx->slot_ctx, 1);105 XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, route_str);106 107 xhci_trb_ring_t *ep_ring = malloc32(sizeof(xhci_trb_ring_t));108 if (!ep_ring) {109 err = ENOMEM;110 goto err_ictx;111 }112 113 err = xhci_trb_ring_init(ep_ring, hc);114 if (err)115 goto err_ring;116 117 XHCI_EP_TYPE_SET(ictx->endpoint_ctx[0], EP_TYPE_CONTROL);118 // TODO: must be changed with a command after USB descriptor is read119 // See 4.6.5 in XHCI specification, first note120 XHCI_EP_MAX_PACKET_SIZE_SET(ictx->endpoint_ctx[0],121 xhci_is_usb3_port(&hc->rh, port) ? 512 : 8);122 XHCI_EP_MAX_BURST_SIZE_SET(ictx->endpoint_ctx[0], 0);123 /* FIXME physical pointer? */124 XHCI_EP_TR_DPTR_SET(ictx->endpoint_ctx[0], ep_ring->dequeue);125 XHCI_EP_DCS_SET(ictx->endpoint_ctx[0], 1);126 XHCI_EP_INTERVAL_SET(ictx->endpoint_ctx[0], 0);127 XHCI_EP_MAX_P_STREAMS_SET(ictx->endpoint_ctx[0], 0);128 XHCI_EP_MULT_SET(ictx->endpoint_ctx[0], 0);129 XHCI_EP_ERROR_COUNT_SET(ictx->endpoint_ctx[0], 3);130 131 // TODO: What's the alignment?132 xhci_device_ctx_t *dctx = malloc32(sizeof(xhci_device_ctx_t));133 if (!dctx) {134 err = ENOMEM;135 goto err_ring;136 }137 memset(dctx, 0, sizeof(xhci_device_ctx_t));138 139 hc->dcbaa[slot_id] = addr_to_phys(dctx);140 141 memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t));142 hc->dcbaa_virt[slot_id].dev_ctx = dctx;143 hc->dcbaa_virt[slot_id].trs[0] = ep_ring;144 145 xhci_cmd_init(&cmd);146 cmd.slot_id = slot_id;147 xhci_send_address_device_command(hc, &cmd, ictx);148 if ((err = xhci_cmd_wait(&cmd, 100000)) != EOK)149 goto err_dctx;150 151 xhci_cmd_fini(&cmd);152 153 // TODO: Issue configure endpoint commands (sec 4.3.5).154 155 return EOK;156 157 err_dctx:158 if (dctx) {159 free32(dctx);160 hc->dcbaa[slot_id] = 0;161 memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t));162 }163 err_ring:164 if (ep_ring) {165 xhci_trb_ring_fini(ep_ring);166 free32(ep_ring);167 }168 err_ictx:169 free32(ictx);170 return err;171 }172 173 static int handle_connected_device(xhci_hc_t* hc, xhci_port_regs_t* regs, uint8_t port_id)174 {175 uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS);176 const xhci_port_speed_t *speed = xhci_get_port_speed(&hc->rh, port_id);177 178 usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id);179 180 if (speed->major == 3) {181 if(link_state == 0) {182 /* USB3 is automatically advanced to enabled. */183 return alloc_dev(hc, port_id, 0);184 }185 else if (link_state == 5) {186 /* USB 3 failed to enable. */187 usb_log_error("USB 3 port couldn't be enabled.");188 return EAGAIN;189 }190 else {191 usb_log_error("USB 3 port is in invalid state %u.", link_state);192 return EINVAL;193 }194 }195 else {196 usb_log_debug("USB 2 device attached, issuing reset.");197 xhci_reset_hub_port(hc, port_id);198 /*199 FIXME: we need to wait for the event triggered by the reset200 and then alloc_dev()... can't it be done directly instead of201 going around?202 */203 return EOK;204 }205 }86 // static int alloc_dev(xhci_hc_t *hc, uint8_t port, uint32_t route_str) 87 // { 88 // int err; 89 // 90 // xhci_cmd_t cmd; 91 // xhci_cmd_init(&cmd); 92 // 93 // xhci_send_enable_slot_command(hc, &cmd); 94 // if ((err = xhci_cmd_wait(&cmd, 100000)) != EOK) 95 // return err; 96 // 97 // uint32_t slot_id = cmd.slot_id; 98 // 99 // usb_log_debug2("Obtained slot ID: %u.\n", slot_id); 100 // xhci_cmd_fini(&cmd); 101 // 102 // xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t)); 103 // if (!ictx) { 104 // return ENOMEM; 105 // } 106 // 107 // memset(ictx, 0, sizeof(xhci_input_ctx_t)); 108 // 109 // XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0); 110 // XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 1); 111 // 112 // /* Initialize slot_ctx according to section 4.3.3 point 3. */ 113 // /* Attaching to root hub port, root string equals to 0. */ 114 // XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, port); 115 // XHCI_SLOT_CTX_ENTRIES_SET(ictx->slot_ctx, 1); 116 // XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, route_str); 117 // 118 // xhci_trb_ring_t *ep_ring = malloc32(sizeof(xhci_trb_ring_t)); 119 // if (!ep_ring) { 120 // err = ENOMEM; 121 // goto err_ictx; 122 // } 123 // 124 // err = xhci_trb_ring_init(ep_ring, hc); 125 // if (err) 126 // goto err_ring; 127 // 128 // XHCI_EP_TYPE_SET(ictx->endpoint_ctx[0], EP_TYPE_CONTROL); 129 // // TODO: must be changed with a command after USB descriptor is read 130 // // See 4.6.5 in XHCI specification, first note 131 // XHCI_EP_MAX_PACKET_SIZE_SET(ictx->endpoint_ctx[0], 132 // xhci_is_usb3_port(&hc->rh, port) ? 512 : 8); 133 // XHCI_EP_MAX_BURST_SIZE_SET(ictx->endpoint_ctx[0], 0); 134 // /* FIXME physical pointer? */ 135 // XHCI_EP_TR_DPTR_SET(ictx->endpoint_ctx[0], ep_ring->dequeue); 136 // XHCI_EP_DCS_SET(ictx->endpoint_ctx[0], 1); 137 // XHCI_EP_INTERVAL_SET(ictx->endpoint_ctx[0], 0); 138 // XHCI_EP_MAX_P_STREAMS_SET(ictx->endpoint_ctx[0], 0); 139 // XHCI_EP_MULT_SET(ictx->endpoint_ctx[0], 0); 140 // XHCI_EP_ERROR_COUNT_SET(ictx->endpoint_ctx[0], 3); 141 // 142 // // TODO: What's the alignment? 143 // xhci_device_ctx_t *dctx = malloc32(sizeof(xhci_device_ctx_t)); 144 // if (!dctx) { 145 // err = ENOMEM; 146 // goto err_ring; 147 // } 148 // memset(dctx, 0, sizeof(xhci_device_ctx_t)); 149 // 150 // hc->dcbaa[slot_id] = addr_to_phys(dctx); 151 // 152 // memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t)); 153 // hc->dcbaa_virt[slot_id].dev_ctx = dctx; 154 // hc->dcbaa_virt[slot_id].trs[0] = ep_ring; 155 // 156 // xhci_cmd_init(&cmd); 157 // cmd.slot_id = slot_id; 158 // xhci_send_address_device_command(hc, &cmd, ictx); 159 // if ((err = xhci_cmd_wait(&cmd, 100000)) != EOK) 160 // goto err_dctx; 161 // 162 // xhci_cmd_fini(&cmd); 163 // 164 // // TODO: Issue configure endpoint commands (sec 4.3.5). 165 // 166 // return EOK; 167 // 168 // err_dctx: 169 // if (dctx) { 170 // free32(dctx); 171 // hc->dcbaa[slot_id] = 0; 172 // memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t)); 173 // } 174 // err_ring: 175 // if (ep_ring) { 176 // xhci_trb_ring_fini(ep_ring); 177 // free32(ep_ring); 178 // } 179 // err_ictx: 180 // free32(ictx); 181 // return err; 182 // } 183 184 // static int handle_connected_device(xhci_hc_t* hc, xhci_port_regs_t* regs, uint8_t port_id) 185 // { 186 // uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS); 187 // const xhci_port_speed_t *speed = xhci_get_port_speed(&hc->rh, port_id); 188 // 189 // usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id); 190 // 191 // if (speed->major == 3) { 192 // if(link_state == 0) { 193 // /* USB3 is automatically advanced to enabled. */ 194 // return alloc_dev(hc, port_id, 0); 195 // } 196 // else if (link_state == 5) { 197 // /* USB 3 failed to enable. */ 198 // usb_log_error("USB 3 port couldn't be enabled."); 199 // return EAGAIN; 200 // } 201 // else { 202 // usb_log_error("USB 3 port is in invalid state %u.", link_state); 203 // return EINVAL; 204 // } 205 // } 206 // else { 207 // usb_log_debug("USB 2 device attached, issuing reset."); 208 // xhci_reset_hub_port(hc, port_id); 209 // /* 210 // FIXME: we need to wait for the event triggered by the reset 211 // and then alloc_dev()... can't it be done directly instead of 212 // going around? 213 // */ 214 // return EOK; 215 // } 216 // } 206 217 207 218 int xhci_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb) … … 211 222 uint8_t port_id = xhci_get_hub_port(trb); 212 223 usb_log_debug("Port status change event detected for port %u.", port_id); 213 xhci_port_regs_t* regs = &hc->op_regs->portrs[port_id - 1];214 215 /* Port reset change */216 if (XHCI_REG_RD(regs, XHCI_PORT_PRC)) {217 /* Clear the flag. */218 XHCI_REG_WR(regs, XHCI_PORT_PRC, 1);219 220 uint8_t port_speed = XHCI_REG_RD(regs, XHCI_PORT_PS);221 usb_log_debug2("Detected port reset on port %u, port speed id %u.", port_id, port_speed);222 /** FIXME: only if that port is not yet initialized */223 if ((err = alloc_dev(hc, port_id, 0)) != EOK)224 return err;225 }226 227 /* Connection status change */228 if (XHCI_REG_RD(regs, XHCI_PORT_CSC)) {229 XHCI_REG_WR(regs, XHCI_PORT_CSC, 1);230 231 if (XHCI_REG_RD(regs, XHCI_PORT_CCS) == 1) {232 if ((err = handle_connected_device(hc, regs, port_id)) != EOK)233 return err;234 } else {235 // TODO: Device disconnected236 return ENOTSUP;237 }238 }239 224 240 225 // Interrupt on the virtual hub status change pipe. 241 usb_target_t target = { 242 .address = virthub_base_get_address(&hc->rh.base), 243 .endpoint = HUB_STATUS_CHANGE_PIPE 244 }; 245 usb_direction_t dir = USB_DIRECTION_IN; 246 usb_device_request_setup_packet_t setup; 247 uint64_t buffer[2]; 248 size_t real_size = 0; 249 err = virthub_base_request(&hc->rh.base, target, dir, &setup, &buffer, 250 sizeof(buffer), &real_size); 251 226 err = xhci_rh_interrupt(&hc->rh); 252 227 if (err != EOK) { 253 228 usb_log_warning("Invoking interrupt on virtual hub failed: %s", … … 364 339 assert(hub); 365 340 366 if (!setup_packet->index || setup_packet->index > XHCI_MAX_PORTS) {341 if (!setup_packet->index || setup_packet->index > hub->max_ports) { 367 342 return ESTALL; 368 343 } … … 388 363 memcpy(data, &status, sizeof(status)); 389 364 *act_size = sizeof(status); 365 390 366 return EOK; 391 367 } … … 403 379 uint8_t *data, size_t *act_size) 404 380 { 405 /* TODO: Implement me! */ 406 usb_log_debug2("Called req_clear_port_feature()."); 381 xhci_rh_t *hub = virthub_get_data(device); 382 assert(hub); 383 384 if (!setup_packet->index || setup_packet->index > hub->max_ports) { 385 return ESTALL; 386 } 387 388 /* The index is 1-based. */ 389 xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1]; 390 391 #define USB_MAP_XHCI(a, b) [USB_HUB_FEATURE_##a] = XHCI_REG_MASK(XHCI_PORT_##b) 392 393 const usb_hub_class_feature_t feature = uint16_usb2host(setup_packet->value); 394 static const ioport32_t masks[] = { 395 USB_MAP_XHCI(C_PORT_CONNECTION, CSC), 396 USB_MAP_XHCI(C_PORT_ENABLE, PEC), 397 USB_MAP_XHCI(C_PORT_OVER_CURRENT, OCC), 398 USB_MAP_XHCI(C_PORT_RESET, PRC) 399 }; 400 401 #undef USB_MAP_XHCI 402 403 usb_log_debug2("RH: ClearPortFeature(%hu) = %d.", setup_packet->index, 404 feature); 405 406 /* Clear the register by writing 1. */ 407 XHCI_REG_WR_FIELD(®s->portsc, masks[feature], 32); 408 407 409 return EOK; 408 410 } … … 444 446 assert(hub); 445 447 446 if (buffer_size < 16) 448 uint8_t status[STATUS_BYTES(hub->max_ports)]; 449 memset(status, 0, sizeof(status)); 450 451 if (buffer_size < sizeof(status)) 447 452 return ESTALL; 448 453 449 memset(buffer, 0, 16); 450 *actual_size = 16; 451 return ENAK; 454 bool change = false; 455 for (size_t i = 1; i <= hub->max_ports; ++i) { 456 xhci_port_regs_t *regs = &hub->hc->op_regs->portrs[i - 1]; 457 458 if (XHCI_REG_RD_FIELD(®s->portsc, 32) & port_change_mask) { 459 status[i / 8] |= (1 << (i % 8)); 460 change = true; 461 } 462 } 463 464 memcpy(buffer, &status, sizeof(status)); 465 *actual_size = sizeof(status); 466 return change ? EOK : ENAK; 452 467 } 453 468 -
uspace/drv/bus/usb/xhci/rh.h
r44063d17 r9876e34 72 72 uint8_t rempow[STATUS_BYTES(XHCI_MAX_PORTS) * 2]; 73 73 } __attribute__((packed)) hub_descriptor; 74 74 75 /** Interrupt transfer waiting for an actual interrupt to occur */ 75 76 usb_transfer_batch_t *unfinished_interrupt_transfer; 77 78 /* Number of hub ports. */ 79 uint8_t max_ports; 76 80 } xhci_rh_t; 77 81
Note:
See TracChangeset
for help on using the changeset viewer.