Changeset 472235a in mainline
- Timestamp:
- 2017-10-03T16:53:47Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 65e079b
- Parents:
- efe9463
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/commands.c
refe9463 r472235a 126 126 { 127 127 link_t *cmd_link = list_first(&hc->commands); 128 129 130 usb_log_debug2("Searching TRB %lu...", phys);131 128 132 129 while (cmd_link != NULL) { -
uspace/drv/bus/usb/xhci/hc.c
refe9463 r472235a 84 84 */ 85 85 86 87 86 unsigned ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF); 87 unsigned ports_to = ports_from 88 88 + XHCI_REG_RD(ec, XHCI_EC_SP_CP_COUNT) - 1; 89 89 … … 468 468 } 469 469 470 static void hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_interrupter_regs_t *intr) 471 { 472 usb_log_debug2("TRB event encountered."); 473 switch (TRB_TYPE(*trb)) { 474 case XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT: 475 xhci_handle_command_completion(hc, trb); 476 break; 477 case XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT: 478 /** 479 * TODO: This is a very crude hotfix, I'm not sure if 480 * we can do this one level above in the event handling 481 * loop (incase the xHC adds more events while we process events). 482 */ 483 hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb)); 484 uint64_t erdp = hc->event_ring.dequeue_ptr; 485 XHCI_REG_WR(intr, XHCI_INTR_ERDP_LO, LOWER32(erdp)); 486 XHCI_REG_WR(intr, XHCI_INTR_ERDP_HI, UPPER32(erdp)); 487 XHCI_REG_SET(intr, XHCI_INTR_ERDP_EHB, 1); 488 xhci_handle_port_status_change_event(hc, trb); 489 break; 490 default: 491 usb_log_debug2("Event type handling not implemented."); 492 break; 493 } 470 typedef int (*event_handler) (xhci_hc_t *, xhci_trb_t *trb); 471 472 static event_handler event_handlers [] = { 473 [XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT] = &xhci_handle_command_completion, 474 [XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT] = &xhci_handle_port_status_change_event, 475 }; 476 477 static int hc_handle_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_interrupter_regs_t *intr) 478 { 479 unsigned type = TRB_TYPE(*trb); 480 if (type >= ARRAY_SIZE(event_handlers) || !event_handlers[type]) 481 return ENOTSUP; 482 483 return event_handlers[type](hc, trb); 494 484 } 495 485 … … 497 487 { 498 488 int err; 499 size_t last_idx = 0; 500 size_t size = 16; // TODO: Define a macro, possibly do size += initial_size instead of *= 2. 501 xhci_trb_t *trbs = malloc32(sizeof(xhci_trb_t) * size); 502 503 err = xhci_event_ring_dequeue(event_ring, trbs + last_idx); 504 505 while (err != ENOENT) { 506 if (err == EOK) { 507 usb_log_debug2("Dequeued trb from event ring: %s", 508 xhci_trb_str_type(TRB_TYPE(trbs[last_idx]))); 509 } else { 510 --last_idx; /* If there are valid trbs they should still get handled. */ 489 ssize_t size = 16; 490 xhci_trb_t *queue = malloc(sizeof(xhci_trb_t) * size); 491 if (!queue) { 492 usb_log_error("Not enough memory to run the event ring."); 493 return; 494 } 495 496 xhci_trb_t *head = queue; 497 498 while ((err = xhci_event_ring_dequeue(event_ring, head)) != ENOENT) { 499 if (err != EOK) { 511 500 usb_log_warning("Error while accessing event ring: %s", str_error(err)); 512 501 break; 513 502 } 514 503 515 ++last_idx;516 err = xhci_event_ring_dequeue(event_ring, trbs + last_idx);504 usb_log_debug2("Dequeued trb from event ring: %s", xhci_trb_str_type(TRB_TYPE(*head))); 505 head++; 517 506 518 507 /* Expand the array if needed. */ 519 if (last_idx >= size) { 520 xhci_trb_t *trbs_old = trbs; 521 size_t size_old = size; 522 508 if (head - queue >= size) { 523 509 size *= 2; 524 trbs = malloc32(sizeof(xhci_trb_t) *size);525 526 for (size_t i = 0; i < size_old; ++i)527 xhci_trb_copy(trbs + i, trbs_old + i); 528 free32(trbs_old);510 xhci_trb_t *new_queue = realloc(queue, size); 511 if (new_queue == NULL) 512 break; /* Will process only those TRBs we have memory for. */ 513 514 head = new_queue + (head - queue); 529 515 } 530 516 } 531 517 532 518 /* Update the ERDP to make room in the ring. */ 519 usb_log_debug2("Copying from ring finished, updating ERDP."); 533 520 hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb)); 534 521 uint64_t erdp = hc->event_ring.dequeue_ptr; … … 538 525 539 526 /* Handle all of the collected events if possible. */ 540 if (last_idx > 0) { 541 for (size_t i = 0; i < last_idx; ++i) 542 hc_handle_event(hc, trbs + i, intr); 543 usb_log_debug2("Event ring processing finished."); 544 } else { 527 if (head == queue) 545 528 usb_log_warning("No events to be handled!"); 546 } 547 548 free32(trbs); 529 530 for (xhci_trb_t *tail = queue; tail != head; tail++) { 531 if ((err = hc_handle_event(hc, tail, intr)) != EOK) { 532 usb_log_error("Failed to handle event: %s", str_error(err)); 533 } 534 } 535 536 free(queue); 537 usb_log_debug2("Event ring run finished."); 549 538 } 550 539 … … 567 556 568 557 if (status & XHCI_REG_MASK(XHCI_OP_EINT)) { 569 usb_log_debug2("Event interrupt .");558 usb_log_debug2("Event interrupt, running the event ring."); 570 559 hc_run_event_ring(hc, &hc->event_ring, &hc->rt_regs->ir[0]); 571 560 status &= ~XHCI_REG_MASK(XHCI_OP_EINT); -
uspace/drv/bus/usb/xhci/rh.c
refe9463 r472235a 135 135 xhci_cmd_fini(&cmd); 136 136 137 137 // TODO: Issue configure endpoint commands (sec 4.3.5). 138 138 139 139 return EOK; … … 165 165 usb_log_debug("Detected new device on port %u, port speed id %u.", port_id, port_speed); 166 166 167 alloc_dev(hc, port_id, 0);167 return alloc_dev(hc, port_id, 0); 168 168 } 169 169 else if (link_state == 5) { 170 170 /* USB 3 failed to enable. */ 171 171 usb_log_error("USB 3 port couldn't be enabled."); 172 return EAGAIN; 172 173 } 173 174 else { 174 175 usb_log_error("USB 3 port is in invalid state %u.", link_state); 176 return EINVAL; 175 177 } 176 178 } … … 183 185 going around? 184 186 */ 185 } 186 187 return EOK; 187 return EOK; 188 } 188 189 } 189 190 190 191 int xhci_handle_port_status_change_event(xhci_hc_t *hc, xhci_trb_t *trb) 191 192 { 193 int err; 194 192 195 uint8_t port_id = xhci_get_hub_port(trb); 193 196 usb_log_debug("Port status change event detected for port %u.", port_id); … … 202 205 usb_log_debug2("Detected port reset on port %u, port speed id %u.", port_id, port_speed); 203 206 /** FIXME: only if that port is not yet initialized */ 204 alloc_dev(hc, port_id, 0); 207 if ((err = alloc_dev(hc, port_id, 0)) != EOK) 208 return err; 205 209 } 206 210 … … 210 214 211 215 if (XHCI_REG_RD(regs, XHCI_PORT_CCS) == 1) { 212 handle_connected_device(hc, regs, port_id); 216 if ((err = handle_connected_device(hc, regs, port_id)) != EOK) 217 return err; 213 218 } else { 214 219 // TODO: Device disconnected 220 return ENOTSUP; 215 221 } 216 222 }
Note:
See TracChangeset
for help on using the changeset viewer.