Changeset dcf0597 in mainline
- Timestamp:
- 2017-10-13T17:40:48Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2297fab
- Parents:
- 063dfe8
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/hc.c
r063dfe8 rdcf0597 425 425 XHCI_REG_SET(hc->op_regs, XHCI_OP_RS, 1); 426 426 427 /* The reset changed status of all ports, and SW originated reason does 428 * not cause an interrupt. 429 */ 430 xhci_rh_handle_port_change(&hc->rh); 431 427 432 return EOK; 428 433 } … … 451 456 { 452 457 assert(batch); 453 454 /* Check for root hub communication */455 if (batch->ep->target.address == xhci_rh_get_address(&hc->rh)) {456 usb_log_debug("XHCI root hub request.\n");457 return xhci_rh_schedule(&hc->rh, batch);458 }459 458 460 459 usb_log_debug2("EP(%d:%d) started %s transfer of size %lu.", … … 488 487 static event_handler event_handlers [] = { 489 488 [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion, 490 [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_ handle_port_status_change_event,489 [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_rh_handle_port_status_change_event, 491 490 [XHCI_TRB_TYPE_TRANSFER_EVENT] = &xhci_handle_transfer_event, 492 491 }; … … 559 558 status = xhci2host(32, status); 560 559 561 /* TODO: Figure out how root hub interrupts work. */562 560 if (status & XHCI_REG_MASK(XHCI_OP_PCD)) { 563 561 usb_log_debug2("Root hub interrupt."); 564 xhci_rh_interrupt(&hc->rh); 565 562 xhci_rh_handle_port_change(&hc->rh); 566 563 status &= ~XHCI_REG_MASK(XHCI_OP_PCD); 567 564 } -
uspace/drv/bus/usb/xhci/rh.c
r063dfe8 rdcf0597 1 1 /* 2 n* Copyright (c) 2017 Michal Staruch2 * Copyright (c) 2017 Michal Staruch 3 3 * All rights reserved. 4 4 * … … 46 46 #include "transfers.h" 47 47 48 #define USB_MAP_VALUE(a, b) [USB_HUB_FEATURE_##a] = b49 #define USB_MAP_XHCI(a, b) USB_MAP_VALUE(a, XHCI_REG_MASK(XHCI_PORT_##b))50 51 enum {52 HUB_STATUS_CHANGE_PIPE = 1,53 };54 55 static usbvirt_device_ops_t ops;56 57 48 /* This mask only lists registers, which imply port change. */ 58 49 static const uint32_t port_change_mask = … … 73 64 rh->max_ports = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PORTS); 74 65 75 usb_hub_descriptor_header_t *header = &rh->hub_descriptor.header; 76 header->length = sizeof(usb_hub_descriptor_header_t); 77 header->descriptor_type = USB_DESCTYPE_HUB; 78 header->port_count = rh->max_ports; 79 header->characteristics = 80 HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG; 81 header->power_good_time = 10; /* XHCI section 5.4.9 says 20ms max */ 82 header->max_current = 0; 83 84 return virthub_base_init(&rh->base, "xhci", &ops, rh, NULL, 85 header, HUB_STATUS_CHANGE_PIPE); 66 return EOK; 86 67 } 87 68 … … 186 167 // } 187 168 188 // static int handle_connected_device(xhci_hc_t* hc, xhci_port_regs_t* regs, uint8_t port_id) 189 // { 190 // uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS); 191 // const xhci_port_speed_t *speed = xhci_get_port_speed(&hc->rh, port_id); 192 // 193 // usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id); 194 // 195 // if (speed->major == 3) { 196 // if(link_state == 0) { 197 // /* USB3 is automatically advanced to enabled. */ 198 // return alloc_dev(hc, port_id, 0); 199 // } 200 // else if (link_state == 5) { 201 // /* USB 3 failed to enable. */ 202 // usb_log_error("USB 3 port couldn't be enabled."); 203 // return EAGAIN; 204 // } 205 // else { 206 // usb_log_error("USB 3 port is in invalid state %u.", link_state); 207 // return EINVAL; 208 // } 209 // } 210 // else { 211 // usb_log_debug("USB 2 device attached, issuing reset."); 212 // xhci_reset_hub_port(hc, port_id); 213 // /* 214 // FIXME: we need to wait for the event triggered by the reset 215 // and then alloc_dev()... can't it be done directly instead of 216 // going around? 217 // */ 218 // return EOK; 219 // } 220 // } 221 222 int xhci_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb) 223 { 224 int err; 225 226 uint8_t port_id = xhci_get_hub_port(trb); 169 static int handle_connected_device(xhci_rh_t *rh, uint8_t port_id) 170 { 171 xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port_id - 1]; 172 173 uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS); 174 const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, port_id); 175 176 usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id); 177 178 if (speed->major == 3) { 179 if (link_state == 0) { 180 /* USB3 is automatically advanced to enabled. */ 181 // return alloc_dev(hc, port_id, 0); 182 return ENOTSUP; 183 } 184 else if (link_state == 5) { 185 /* USB 3 failed to enable. */ 186 usb_log_error("USB 3 port couldn't be enabled."); 187 return EAGAIN; 188 } 189 else { 190 usb_log_error("USB 3 port is in invalid state %u.", link_state); 191 return EINVAL; 192 } 193 } 194 else { 195 usb_log_debug("USB 2 device attached, issuing reset."); 196 xhci_rh_reset_port(rh, port_id); 197 /* 198 FIXME: we need to wait for the event triggered by the reset 199 and then alloc_dev()... can't it be done directly instead of 200 going around? 201 */ 202 return EOK; 203 } 204 } 205 206 /** Handle an incoming Port Change Detected Event. 207 */ 208 int xhci_rh_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb) 209 { 210 uint8_t port_id = XHCI_QWORD_EXTRACT(trb->parameter, 31, 24); 227 211 usb_log_debug("Port status change event detected for port %u.", port_id); 228 212 229 // Interrupt on the virtual hub status change pipe. 230 err = xhci_rh_interrupt(&hc->rh); 231 if (err != EOK) { 232 usb_log_warning("Invoking interrupt on virtual hub failed: %s", 233 str_error(err)); 213 /** 214 * We can't be sure that the port change this event announces is the 215 * only port change that happened (see section 4.19.2 of the xHCI 216 * specification). Therefore, we just check all ports for changes. 217 */ 218 xhci_rh_handle_port_change(&hc->rh); 219 220 return EOK; 221 } 222 223 void xhci_rh_handle_port_change(xhci_rh_t *rh) 224 { 225 for (uint8_t i = 1; i <= rh->max_ports; ++i) { 226 xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[i - 1]; 227 228 uint32_t events = XHCI_REG_RD_FIELD(®s->portsc, 32); 229 XHCI_REG_WR_FIELD(®s->portsc, events, 32); 230 231 events &= port_change_mask; 232 233 if (events & XHCI_REG_MASK(XHCI_PORT_CSC)) { 234 usb_log_info("Connected state changed on port %u.", i); 235 events &= ~XHCI_REG_MASK(XHCI_PORT_CSC); 236 237 bool connected = XHCI_REG_RD(regs, XHCI_PORT_CCS); 238 if (connected) 239 handle_connected_device(rh, i); 240 } 241 242 if (events & XHCI_REG_MASK(XHCI_PORT_PEC)) { 243 usb_log_info("Port enabled changed on port %u.", i); 244 events &= ~XHCI_REG_MASK(XHCI_PORT_PEC); 245 } 246 247 if (events & XHCI_REG_MASK(XHCI_PORT_WRC)) { 248 usb_log_info("Warm port reset on port %u completed.", i); 249 events &= ~XHCI_REG_MASK(XHCI_PORT_WRC); 250 } 251 252 if (events & XHCI_REG_MASK(XHCI_PORT_OCC)) { 253 usb_log_info("Over-current change on port %u.", i); 254 events &= ~XHCI_REG_MASK(XHCI_PORT_OCC); 255 } 256 257 if (events & XHCI_REG_MASK(XHCI_PORT_PRC)) { 258 usb_log_info("Port reset on port %u completed.", i); 259 events &= ~XHCI_REG_MASK(XHCI_PORT_PRC); 260 } 261 262 if (events & XHCI_REG_MASK(XHCI_PORT_PLC)) { 263 usb_log_info("Port link state changed on port %u.", i); 264 events &= ~XHCI_REG_MASK(XHCI_PORT_PLC); 265 } 266 267 if (events & XHCI_REG_MASK(XHCI_PORT_CEC)) { 268 usb_log_info("Port %u failed to configure link.", i); 269 events &= ~XHCI_REG_MASK(XHCI_PORT_CEC); 270 } 271 272 if (events) { 273 usb_log_warning("Port change (0x%08x) ignored on port %u.", events, i); 274 } 234 275 } 235 236 return EOK; 237 } 238 239 const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *rh, uint8_t port) 276 277 /** 278 * Theory: 279 * 280 * Although more events could have happened while processing, the PCD 281 * bit in USBSTS will be set on every change. Because the PCD is 282 * cleared even before the interrupt is cleared, it is safe to assume 283 * that this handler will be called again. 284 * 285 * But because we could have handled the event in previous run of this 286 * handler, it is not an error when no event is detected. 287 * 288 * Reality: 289 * 290 * The PCD bit is never set. TODO Check why the interrupt never carries 291 * the PCD flag. Possibly repeat the checking until we're sure the 292 * PSCEG is 0 - check section 4.19.2 of the xHCI spec. 293 */ 294 } 295 296 const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *rh, uint8_t port) 240 297 { 241 298 xhci_port_regs_t *port_regs = &rh->hc->op_regs->portrs[port - 1]; … … 245 302 } 246 303 247 int xhci_get_hub_port(xhci_trb_t *trb) 248 { 249 assert(trb); 250 uint8_t port_id = XHCI_QWORD_EXTRACT(trb->parameter, 31, 24); 251 252 return port_id; 253 } 254 255 int xhci_reset_hub_port(xhci_hc_t* hc, uint8_t port) 304 int xhci_rh_reset_port(xhci_rh_t* rh, uint8_t port) 256 305 { 257 306 usb_log_debug2("Resetting port %u.", port); 258 xhci_port_regs_t *regs = & hc->op_regs->portrs[port-1];259 XHCI_REG_ WR(regs, XHCI_PORT_PR, 1);307 xhci_port_regs_t *regs = &rh->hc->op_regs->portrs[port-1]; 308 XHCI_REG_SET(regs, XHCI_PORT_PR, 1); 260 309 261 310 return EOK; 262 }263 264 int xhci_rh_schedule(xhci_rh_t *rh, usb_transfer_batch_t *batch)265 {266 assert(rh);267 assert(batch);268 const usb_target_t target = batch->ep->target;269 batch->error = virthub_base_request(&rh->base, target,270 usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,271 batch->buffer, batch->buffer_size, &batch->transfered_size);272 if (batch->error == ENAK) {273 /* This is safe because only status change interrupt transfers274 * return NAK. The assertion holds true because the batch275 * existence prevents communication with that ep */276 assert(rh->unfinished_interrupt_transfer == NULL);277 rh->unfinished_interrupt_transfer = batch;278 } else {279 usb_transfer_batch_finish(batch, NULL);280 usb_transfer_batch_destroy(batch);281 }282 return EOK;283 }284 285 int xhci_rh_interrupt(xhci_rh_t *rh)286 {287 usb_log_debug2("Called xhci_rh_interrupt().");288 289 /* TODO: atomic swap needed */290 usb_transfer_batch_t *batch = rh->unfinished_interrupt_transfer;291 rh->unfinished_interrupt_transfer = NULL;292 if (batch) {293 const usb_target_t target = batch->ep->target;294 batch->error = virthub_base_request(&rh->base, target,295 usb_transfer_batch_direction(batch),296 (void*)batch->setup_buffer,297 batch->buffer, batch->buffer_size, &batch->transfered_size);298 usb_transfer_batch_finish(batch, NULL);299 usb_transfer_batch_destroy(batch);300 }301 return EOK;302 }303 304 /** Hub set feature request handler.305 * @param device Virtual hub device306 * @param setup_packet USB setup stage data.307 * @param[out] data destination data buffer, size must be at least308 * setup_packet->length bytes309 * @param[out] act_size Sized of the valid response part of the buffer.310 * @return Error code.311 */312 static int req_clear_hub_feature(usbvirt_device_t *device,313 const usb_device_request_setup_packet_t *setup_packet,314 uint8_t *data, size_t *act_size)315 {316 /* TODO: Implement me! */317 usb_log_debug2("Called req_clear_hub_feature().");318 return EOK;319 }320 321 #define XHCI_TO_USB(usb_feat, reg_set, ...) \322 (((XHCI_REG_RD(reg_set, ##__VA_ARGS__)) ? 1 : 0) << (usb_feat))323 324 /** Port status request handler.325 * @param device Virtual hub device326 * @param setup_packet USB setup stage data.327 * @param[out] data destination data buffer, size must be at least328 * setup_packet->length bytes329 * @param[out] act_size Sized of the valid response part of the buffer.330 * @return Error code.331 */332 static int req_get_port_status(usbvirt_device_t *device,333 const usb_device_request_setup_packet_t *setup_packet,334 uint8_t *data, size_t *act_size)335 {336 xhci_rh_t *hub = virthub_get_data(device);337 assert(hub);338 339 if (!setup_packet->index || setup_packet->index > hub->max_ports) {340 return ESTALL;341 }342 343 /* The index is 1-based. */344 xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];345 346 const uint32_t status = uint32_host2usb(347 XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_CONNECTION, regs, XHCI_PORT_CSC) |348 XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_ENABLE, regs, XHCI_PORT_PEC) |349 XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_OVER_CURRENT, regs, XHCI_PORT_OCC) |350 XHCI_TO_USB(USB_HUB_FEATURE_C_PORT_RESET, regs, XHCI_PORT_PRC) |351 XHCI_TO_USB(USB_HUB_FEATURE_PORT_CONNECTION, regs, XHCI_PORT_CCS) |352 XHCI_TO_USB(USB_HUB_FEATURE_PORT_ENABLE, regs, XHCI_PORT_PED) |353 XHCI_TO_USB(USB_HUB_FEATURE_PORT_OVER_CURRENT, regs, XHCI_PORT_OCA) |354 XHCI_TO_USB(USB_HUB_FEATURE_PORT_RESET, regs, XHCI_PORT_PR) |355 XHCI_TO_USB(USB_HUB_FEATURE_PORT_POWER, regs, XHCI_PORT_PP)356 );357 358 usb_log_debug2("RH: GetPortStatus(%hu) = %u.", setup_packet->index,359 uint32_usb2host(status));360 361 memcpy(data, &status, sizeof(status));362 *act_size = sizeof(status);363 364 return EOK;365 }366 367 /** Port clear feature request handler.368 * @param device Virtual hub device369 * @param setup_packet USB setup stage data.370 * @param[out] data destination data buffer, size must be at least371 * setup_packet->length bytes372 * @param[out] act_size Sized of the valid response part of the buffer.373 * @return Error code.374 */375 static int req_clear_port_feature(usbvirt_device_t *device,376 const usb_device_request_setup_packet_t *setup_packet,377 uint8_t *data, size_t *act_size)378 {379 xhci_rh_t *hub = virthub_get_data(device);380 assert(hub);381 382 if (!setup_packet->index || setup_packet->index > hub->max_ports) {383 return ESTALL;384 }385 386 /* The index is 1-based. */387 xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];388 389 const usb_hub_class_feature_t feature = uint16_usb2host(setup_packet->value);390 static const ioport32_t masks[] = {391 USB_MAP_XHCI(C_PORT_CONNECTION, CSC),392 USB_MAP_XHCI(C_PORT_ENABLE, PEC),393 USB_MAP_XHCI(C_PORT_OVER_CURRENT, OCC),394 USB_MAP_XHCI(C_PORT_RESET, PRC),395 USB_MAP_XHCI(PORT_ENABLE, PED),396 USB_MAP_XHCI(PORT_RESET, PR),397 USB_MAP_XHCI(PORT_POWER, PP)398 };399 400 static const bool is_change[] = {401 USB_MAP_VALUE(C_PORT_CONNECTION, true),402 USB_MAP_VALUE(C_PORT_ENABLE, true),403 USB_MAP_VALUE(C_PORT_OVER_CURRENT, true),404 USB_MAP_VALUE(C_PORT_RESET, true),405 USB_MAP_VALUE(PORT_ENABLE, false),406 USB_MAP_VALUE(PORT_RESET, false),407 USB_MAP_VALUE(PORT_POWER, false)408 };409 410 usb_log_debug2("RH: ClearPortFeature(%hu) = %d.", setup_packet->index,411 feature);412 413 if (is_change[feature]) {414 /* Clear the register by writing 1. */415 XHCI_REG_SET_FIELD(®s->portsc, masks[feature], 32);416 } else {417 /* Clear the register by writing 0. */418 XHCI_REG_CLR_FIELD(®s->portsc, masks[feature], 32);419 }420 421 return EOK;422 }423 424 /** Port set feature request handler.425 * @param device Virtual hub device426 * @param setup_packet USB setup stage data.427 * @param[out] data destination data buffer, size must be at least428 * setup_packet->length bytes429 * @param[out] act_size Sized of the valid response part of the buffer.430 * @return Error code.431 */432 static int req_set_port_feature(usbvirt_device_t *device,433 const usb_device_request_setup_packet_t *setup_packet,434 uint8_t *data, size_t *act_size)435 {436 xhci_rh_t *hub = virthub_get_data(device);437 assert(hub);438 439 if (!setup_packet->index || setup_packet->index > hub->max_ports) {440 return ESTALL;441 }442 443 /* The index is 1-based. */444 xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];445 446 const usb_hub_class_feature_t feature = uint16_usb2host(setup_packet->value);447 static const ioport32_t masks[] = {448 USB_MAP_XHCI(PORT_ENABLE, PED),449 USB_MAP_XHCI(PORT_RESET, PR),450 USB_MAP_XHCI(PORT_POWER, PP)451 };452 453 usb_log_debug2("RH: SetPortFeature(%hu) = %d.", setup_packet->index,454 feature);455 456 /* Set the feature in the PIO register. */457 XHCI_REG_SET_FIELD(®s->portsc, masks[feature], 32);458 459 return EOK;460 }461 462 /** Status change handler.463 * @param device Virtual hub device464 * @param endpoint Endpoint number465 * @param tr_type Transfer type466 * @param buffer Response destination467 * @param buffer_size Bytes available in buffer468 * @param actual_size Size us the used part of the dest buffer.469 *470 * Produces status mask. Bit 0 indicates hub status change the other bits471 * represent port status change.472 */473 static int req_status_change_handler(usbvirt_device_t *device,474 usb_endpoint_t endpoint, usb_transfer_type_t tr_type,475 void *buffer, size_t buffer_size, size_t *actual_size)476 {477 xhci_rh_t *hub = virthub_get_data(device);478 assert(hub);479 480 uint8_t status[STATUS_BYTES(hub->max_ports)];481 memset(status, 0, sizeof(status));482 483 if (buffer_size < sizeof(status))484 return ESTALL;485 486 bool change = false;487 for (size_t i = 1; i <= hub->max_ports; ++i) {488 xhci_port_regs_t *regs = &hub->hc->op_regs->portrs[i - 1];489 490 if (XHCI_REG_RD_FIELD(®s->portsc, 32) & port_change_mask) {491 status[i / 8] |= (1 << (i % 8));492 change = true;493 }494 }495 496 usb_log_debug2("RH: Status change %s", (change ? "occurred" : "did not occur"));497 memcpy(buffer, &status, sizeof(status));498 *actual_size = sizeof(status);499 return change ? EOK : ENAK;500 311 } 501 312 … … 507 318 } 508 319 509 /** XHCI root hub request handlers */510 static const usbvirt_control_request_handler_t control_transfer_handlers[] = {511 {512 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),513 .name = "GetDescriptor",514 .callback = virthub_base_get_hub_descriptor,515 },516 {517 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),518 .name = "GetDescriptor",519 .callback = virthub_base_get_hub_descriptor,520 },521 {522 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),523 .name = "GetHubDescriptor",524 .callback = virthub_base_get_hub_descriptor,525 },526 {527 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),528 .name = "GetPortStatus",529 .callback = req_get_port_status,530 },531 {532 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),533 .name = "ClearHubFeature",534 .callback = req_clear_hub_feature,535 },536 {537 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),538 .name = "ClearPortFeature",539 .callback = req_clear_port_feature,540 },541 {542 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_STATUS),543 .name = "GetHubStatus",544 /* XHCI root hub has no power source,545 * over-current is reported by port */546 .callback = virthub_base_get_null_status,547 },548 {549 CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),550 .name = "GetPortStatus",551 .callback = req_get_port_status,552 },553 {554 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_SET_FEATURE),555 .name = "SetHubFeature",556 .callback = req_nop,557 },558 {559 CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_SET_FEATURE),560 .name = "SetPortFeature",561 .callback = req_set_port_feature,562 },563 {564 .callback = NULL565 }566 };567 568 /** Virtual XHCI root hub ops */569 static usbvirt_device_ops_t ops = {570 .control = control_transfer_handlers,571 .data_in[HUB_STATUS_CHANGE_PIPE] = req_status_change_handler,572 };573 574 575 320 /** 576 321 * @} -
uspace/drv/bus/usb/xhci/rh.h
r063dfe8 rdcf0597 38 38 39 39 #include <usb/host/usb_transfer_batch.h> 40 #include <usbvirt/virthub_base.h>41 40 #include "hw_struct/regs.h" 42 41 43 42 typedef struct xhci_hc xhci_hc_t; 44 45 enum {46 XHCI_MAX_PORTS = 255,47 };48 43 49 44 /** … … 58 53 /* XHCI root hub instance */ 59 54 typedef struct { 60 /** Virtual hub instance */61 virthub_base_t base;62 63 55 /** Host controller */ 64 56 xhci_hc_t *hc; … … 66 58 /** Port speeds reported from HC */ 67 59 xhci_port_speed_t speeds [16]; 68 69 /** USB hub descriptor describing the XHCI root hub */70 struct {71 usb_hub_descriptor_header_t header;72 uint8_t rempow[STATUS_BYTES(XHCI_MAX_PORTS) * 2];73 } __attribute__((packed)) hub_descriptor;74 60 75 61 /** Interrupt transfer waiting for an actual interrupt to occur */ … … 82 68 int xhci_rh_init(xhci_rh_t *, xhci_hc_t *); 83 69 int xhci_rh_fini(xhci_rh_t *); 84 const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *, uint8_t); 85 int xhci_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *); 86 int xhci_get_hub_port(xhci_trb_t *); 87 int xhci_reset_hub_port(xhci_hc_t *, uint8_t); 88 int xhci_rh_schedule(xhci_rh_t *, usb_transfer_batch_t *); 89 int xhci_rh_interrupt(xhci_rh_t *); 70 const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *, uint8_t); 71 int xhci_rh_reset_port(xhci_rh_t *, uint8_t); 90 72 91 /** Get XHCI rh address. 92 * 93 * @param rh XHCI rh instance. 94 * @return USB address assigned to the hub. 95 * Wrapper for virtual hub address 96 */ 97 static inline usb_address_t xhci_rh_get_address(xhci_rh_t *rh) 98 { 99 assert(rh); 100 return virthub_base_get_address(&rh->base); 101 } 73 int xhci_rh_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *); 74 void xhci_rh_handle_port_change(xhci_rh_t *); 102 75 103 static inline bool xhci_is_usb3_port(xhci_rh_t* rh, uint8_t port)104 {105 return xhci_get_port_speed(rh, port)->major == 3;106 }107 76 #endif 108 77 -
uspace/drv/bus/usb/xhci/transfers.c
r063dfe8 rdcf0597 36 36 #include <usb/host/utils/malloc32.h> 37 37 #include <usb/debug.h> 38 #include <usb/request.h> 38 39 #include "endpoint.h" 39 40 #include "hc.h"
Note:
See TracChangeset
for help on using the changeset viewer.