diff --git a/kernel/device/xhci.c b/kernel/device/xhci.c index c2049b7..816a5b0 100644 --- a/kernel/device/xhci.c +++ b/kernel/device/xhci.c @@ -221,6 +221,7 @@ static void xhci_event_dispatch (struct xhci* xhci, struct xhci_trb* event, uint DEBUG ("cmd completion: code=%u,slot=%u\n", cmpl_code, slot_id); xhci->last_slot_id = slot_id; + xhci->last_cmpl_code = cmpl_code; } break; case XHCI_TRB_PORT_STS_CHNG: { uint8_t port = ((event->param >> 24) & 0xFF) - 1; @@ -645,10 +646,19 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) { list_find (struct xhci_port, xhci->xhci_ports, xhci_port, port_value, pdevice->port_value, ports_link); - xhci_send_cmd (xhci, 0, 0, XHCI_TRB_SLOT_ENAB_CMD << 10, lockflags); - uint8_t slot_id = xhci->last_slot_id; + uint32_t portsc = xhci_portsc_read (xhci, pdevice->port_value); - pdevice->slot_id = slot_id; + uint32_t speed = (portsc >> 10) & 0x0F; + + xhci->last_cmpl_code = 0; + xhci_send_cmd (xhci, 0, 0, XHCI_TRB_SLOT_ENAB_CMD << 10, lockflags); + + if (xhci->last_cmpl_code != 1) { + DEBUG ("Enable slot failed\n"); + continue; + } + + pdevice->slot_id = xhci->last_slot_id; uintptr_t out_ctx_phys = pmm_alloc (1); void* out_ctx_virt = (void*)(out_ctx_phys + (uintptr_t)hhdm->offset); @@ -672,10 +682,11 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) { /* Add slot and endpoint 0 */ ctx64->ctrl.dw[1] = (1 << 0) | (1 << 1); - ctx64->slot.dw[0] = (1 << 27); + ctx64->slot.dw[0] = (1 << 27) | (speed << 20); ctx64->slot.dw[1] = ((pdevice->port_value + 1) << 16); - ctx64->endpoints[0].dw[1] = (3 << 1) | (4 << 3) | (max_packet_size << 16); + ctx64->endpoints[0].dw[0] = 0; + ctx64->endpoints[0].dw[1] = 3 | (4 << 3) | (max_packet_size << 16); ctx64->endpoints[0].dw[2] = (uint32_t)pdevice->endpoint0_ring_phys | (1 << 0); ctx64->endpoints[0].dw[3] = (uint32_t)(pdevice->endpoint0_ring_phys >> 32); } else { @@ -685,20 +696,26 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) { ctx32->ctrl.dw[1] = (1 << 0) | (1 << 1); - ctx32->slot.dw[0] = (1 << 27); + ctx32->slot.dw[0] = (1 << 27) | (speed << 20); ctx32->slot.dw[1] = ((pdevice->port_value + 1) << 16); - ctx32->endpoints[0].dw[1] = (3 << 1) | (4 << 3) | (max_packet_size << 16); + ctx32->endpoints[0].dw[1] = 3 | (4 << 3) | (max_packet_size << 16); ctx32->endpoints[0].dw[2] = (uint32_t)pdevice->endpoint0_ring_phys | (1 << 0); ctx32->endpoints[0].dw[3] = (uint32_t)(pdevice->endpoint0_ring_phys >> 32); } + xhci->last_cmpl_code = 0; uint32_t ctrl = (pdevice->slot_id << 24) | (XHCI_TRB_ADDR_DEV_CMD << 10); xhci_send_cmd (xhci, input_ctx_phys, 0, ctrl, lockflags); stall_ms (500); - DEBUG ("Device on port %u addressed on slot %u!\n", pdevice->port_value, pdevice->slot_id); + if (xhci->last_cmpl_code != 1) { + DEBUG ("Failed to address device. port = %u, slot = %u\n", pdevice->port_value, + pdevice->slot_id); + } else { + DEBUG ("Device on port %u addressed on slot %u!\n", pdevice->port_value, pdevice->slot_id); + } pmm_free (input_ctx_phys, 1); } diff --git a/kernel/device/xhci.h b/kernel/device/xhci.h index 29b0e21..cccc2d2 100644 --- a/kernel/device/xhci.h +++ b/kernel/device/xhci.h @@ -109,6 +109,7 @@ struct xhci { atomic_bool pending; uint8_t last_slot_id; + uint8_t last_cmpl_code; spin_lock_t setup_lock; };