diff --git a/aux/qemu_amd64.sh b/aux/qemu_amd64.sh index 35e3145..11897a9 100755 --- a/aux/qemu_amd64.sh +++ b/aux/qemu_amd64.sh @@ -43,4 +43,4 @@ done [ "$ENABLE_KVM" -eq 1 ] && KVM_FLAG="-enable-kvm" || KVM_FLAG="" qemu-system-x86_64 -M pc -m 4G -serial stdio $KVM_FLAG \ - -cdrom mop3.iso -smp 1 -boot d $QEMU_EXTRA "${POSITIONAL_ARGS[@]}" + -cdrom mop3.iso -smp 4 -boot d $QEMU_EXTRA "${POSITIONAL_ARGS[@]}" diff --git a/kernel/device/pci/pci_xhci.c b/kernel/device/pci/pci_xhci.c index 02e5307..e4d5479 100644 --- a/kernel/device/pci/pci_xhci.c +++ b/kernel/device/pci/pci_xhci.c @@ -88,6 +88,10 @@ bool pci_xhci_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_i DEBUG ("IRQ support=%d\n", irqs_support); + if (!irqs_support) { + return false; + } + struct xhci_init init = { .xhci_mmio_base = xhci_base, .irqs_support = irqs_support, diff --git a/kernel/device/usb/usb.h b/kernel/device/usb/usb.h index 8bc653d..6b7a842 100644 --- a/kernel/device/usb/usb.h +++ b/kernel/device/usb/usb.h @@ -15,7 +15,7 @@ struct usb_device_desc { uint8_t dev_class; uint8_t dev_subclass; uint8_t dev_proto; - uint8_t max_packet_size; + uint8_t max_packet_size; /* If USB 3.0, this must be read as (1 << max_packet_size) */ uint16_t vendor_id; uint16_t product_id; uint16_t bcd_device; diff --git a/kernel/device/usb/xhci.c b/kernel/device/usb/xhci.c index d6a1fc1..5dfa6f3 100644 --- a/kernel/device/usb/xhci.c +++ b/kernel/device/usb/xhci.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -189,6 +190,11 @@ #define XHCI_SSTRB_PARAM_BREQUEST 8 #define XHCI_SSTRB_PARAM_BMREQUEST_TYPE 0 +/* setup stage TRB transfer types */ +#define XHCI_SSTRB_TRT_NO_DATA_STAGE 0 +#define XHCI_SSTRB_TRT_OUT_DATA_STAGE 2 +#define XHCI_SSTRB_TRT_IN_DATA_STAGE 3 + /* data stage TRB */ #define XHCI_DSTRB_CTRL_DIR 16 #define XHCI_DSTRB_CTRL_TRB_TYPE 10 @@ -365,31 +371,33 @@ static void xhci_port_reset (struct xhci* xhci, uint8_t port) { stall_ms (100); } -static void xhci_create_pdevice (struct xhci* xhci, uint8_t port) { +static void xhci_create_pdevice (struct xhci* xhci, struct xhci_port* xhci_port) { struct xhci_pdevice* pdevice; - list_find (struct xhci_pdevice, xhci->xhci_pdevices, pdevice, port_value, port, pdevices_link); + list_find (struct xhci_pdevice, xhci->xhci_pdevices, pdevice, xhci_port->port_value, + xhci_port->port_value, pdevices_link); if (pdevice != NULL) return; pdevice = malloc (sizeof (*pdevice)); memset (pdevice, 0, sizeof (*pdevice)); - pdevice->port_value = port; + pdevice->xhci_port = xhci_port; pdevice->slot_id = -1; list_append (xhci->xhci_pdevices, &pdevice->pdevices_link); } -static void xhci_delete_pdevice (struct xhci* xhci, uint8_t port) { +static void xhci_delete_pdevice (struct xhci* xhci, struct xhci_port* xhci_port) { struct xhci_pdevice* pdevice; - list_find (struct xhci_pdevice, xhci->xhci_pdevices, pdevice, port_value, port, pdevices_link); + list_find (struct xhci_pdevice, xhci->xhci_pdevices, pdevice, xhci_port->port_value, + xhci_port->port_value, pdevices_link); list_remove (xhci->xhci_pdevices, &pdevice->pdevices_link); - if (pdevice->endpoint0_ring_phys != 0) - pmm_free (pdevice->endpoint0_ring_phys, 1); + if (pdevice->endpoint0_ring.phys != 0) + pmm_free (pdevice->endpoint0_ring.phys, 1); pmm_free (xhci->xhci_dcbaa[pdevice->slot_id], 1); xhci->xhci_dcbaa[pdevice->slot_id] = 0; @@ -431,10 +439,12 @@ static void xhci_event_dispatch (struct xhci* xhci, struct xhci_trb* event, uint DEBUG ("transfer completion: code=%u,slot=%u,endpoint_id=%u\n", cmpl_code, slot_id, endpoint_id); + + xhci->last_slot_id = slot_id; xhci->last_cmpl_code = cmpl_code; } break; default: - DEBUG ("Unhandled event type %u at %u\n", type, xhci->event_ring_idx); + DEBUG ("Unhandled event type %u at %u\n", type, xhci->event_ring.idx); break; } } @@ -444,9 +454,9 @@ static void xhci_poll_events (struct xhci* xhci) { bool serviced = false; for (;;) { - struct xhci_trb* event = &xhci->event_ring[xhci->event_ring_idx]; + struct xhci_trb* event = &xhci->event_ring.trbs[xhci->event_ring.idx]; - if ((event->ctrl & (1 << XHCI_GTRB_CYCLE_BIT)) != xhci->event_cycle_bit) { + if ((event->ctrl & (1 << XHCI_GTRB_CYCLE_BIT)) != xhci->event_ring.cycle_bit) { break; } @@ -456,17 +466,17 @@ static void xhci_poll_events (struct xhci* xhci) { xhci_event_dispatch (xhci, event, type); - xhci->event_ring_idx++; + xhci->event_ring.idx++; - if (xhci->event_ring_idx >= xhci->event_ring_size) { - xhci->event_ring_idx = 0; - xhci->event_cycle_bit ^= 1; + if (xhci->event_ring.idx >= xhci->event_ring.size) { + xhci->event_ring.idx = 0; + xhci->event_ring.cycle_bit ^= 1; } } if (serviced) { uintptr_t dequeue_ptr = - xhci->event_ring_phys + (xhci->event_ring_idx * sizeof (struct xhci_trb)); + xhci->event_ring.phys + (xhci->event_ring.idx * sizeof (struct xhci_trb)); xhci_write32 (ir_base, XHCI_ERDP, (uint32_t)dequeue_ptr | (1 << 3)); xhci_write32 (ir_base, XHCI_ERDP + 4, (uint32_t)(dequeue_ptr >> 32)); @@ -495,25 +505,25 @@ static void xhci_irq (void* arg, void* regs, bool user, struct reschedule_ctx* r spin_unlock (&xhci->device->lock, fd); } -static void xhci_endpoint0_put_trb (struct xhci_pdevice* pdevice, struct xhci_trb trb) { - if (pdevice->endpoint0_ring_idx == pdevice->endpoint0_ring_size - 1) { - struct xhci_trb* link = &pdevice->endpoint0_ring[pdevice->endpoint0_ring_idx]; - link->param = pdevice->endpoint0_ring_phys; +static void xhci_endpoint0_put_trb (struct xhci_pdevice* pdevice, struct xhci_trb put_trb) { + if (pdevice->endpoint0_ring.idx == pdevice->endpoint0_ring.size - 1) { + struct xhci_trb* link = &pdevice->endpoint0_ring.trbs[pdevice->endpoint0_ring.idx]; + link->param = pdevice->endpoint0_ring.phys; link->status = 0; link->ctrl = (XHCI_TRB_LINK << XHCI_LNKTRB_CTRL_TRB_TYPE) | (1 << XHCI_LNKTRB_CTRL_TC) | - pdevice->endpoint0_cycle_bit; + pdevice->endpoint0_ring.cycle_bit; - pdevice->endpoint0_ring_idx = 0; - pdevice->endpoint0_cycle_bit ^= 1; + pdevice->endpoint0_ring.idx = 0; + pdevice->endpoint0_ring.cycle_bit ^= 1; } - pdevice->endpoint0_ring[pdevice->endpoint0_ring_idx] = trb; - pdevice->endpoint0_ring[pdevice->endpoint0_ring_idx].ctrl = - (pdevice->endpoint0_ring[pdevice->endpoint0_ring_idx].ctrl & ~1u) | - pdevice->endpoint0_cycle_bit; + struct xhci_trb* trb = &pdevice->endpoint0_ring.trbs[pdevice->endpoint0_ring.idx]; + trb->param = put_trb.param; + trb->status = put_trb.status; + trb->ctrl = (put_trb.ctrl & ~XHCI_LNKTRB_CTRL_TC) | pdevice->endpoint0_ring.cycle_bit; - pdevice->endpoint0_ring_idx++; + pdevice->endpoint0_ring.idx++; } static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_pdevice* pdevice, @@ -530,23 +540,20 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_pdevice* pdev struct xhci_trb trb; - xhci->last_cmpl_code = 0; - atomic_store (&xhci->pending, true); - /* setup stage */ memset (&trb, 0, sizeof (trb)); trb.param = setup; trb.status = 8; - trb.ctrl = - (XHCI_TRB_SETUP_STAGE << XHCI_SSTRB_CTRL_TRB_TYPE) | (1 << XHCI_SSTRB_CTRL_IDT) | (1 << 4); + trb.ctrl = (XHCI_TRB_SETUP_STAGE << XHCI_SSTRB_CTRL_TRB_TYPE) | + (1 << XHCI_SSTRB_CTRL_IDT) | + (XHCI_SSTRB_TRT_IN_DATA_STAGE << XHCI_SSTRB_CTRL_TRT); xhci_endpoint0_put_trb (pdevice, trb); /* data stage */ memset (&trb, 0, sizeof (trb)); trb.param = data_phys; trb.status = length; - trb.ctrl = - (XHCI_TRB_DATA_STAGE << XHCI_DSTRB_CTRL_TRB_TYPE) | (1 << XHCI_DSTRB_CTRL_DIR) | (1 << 4); + trb.ctrl = (XHCI_TRB_DATA_STAGE << XHCI_DSTRB_CTRL_TRB_TYPE) | (1 << XHCI_DSTRB_CTRL_DIR); xhci_endpoint0_put_trb (pdevice, trb); /* status stage */ @@ -556,12 +563,14 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_pdevice* pdev trb.ctrl = (XHCI_TRB_STATUS_STAGE << XHCI_STSTRB_CTRL_TRB_TYPE) | (1 << XHCI_STSTRB_CTRL_IOC); xhci_endpoint0_put_trb (pdevice, trb); - xhci_write32 (xhci->xhci_doorbell_base, pdevice->slot_id * 4, 1); + atomic_store (&xhci->pending, true); int timeout = 100; spin_unlock (&xhci->device->lock, *lockflags); + xhci_write32 (xhci->xhci_doorbell_base, pdevice->slot_id * 4, 1); + while (atomic_load (&xhci->pending) && --timeout > 0) stall_ms (10); @@ -577,47 +586,40 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_pdevice* pdev static void xhci_send_cmd (struct xhci* xhci, uint64_t param, uint32_t status, uint32_t ctrl, uint64_t* lockflags) { - if (xhci->irqs_support) { - if (xhci->cmd_ring_idx == (xhci->cmd_ring_size - 1)) { - struct xhci_trb* link = &xhci->cmd_ring[xhci->cmd_ring_idx]; - link->param = xhci->cmd_ring_phys; - link->status = 0; - link->ctrl = (XHCI_TRB_LINK << XHCI_LNKTRB_CTRL_TRB_TYPE) | - (1 << XHCI_LNKTRB_CTRL_TC) | - xhci->cmd_cycle_bit; + if (xhci->cmd_ring.idx == (xhci->cmd_ring.size - 1)) { + struct xhci_trb* link = &xhci->cmd_ring.trbs[xhci->cmd_ring.idx]; + link->param = xhci->cmd_ring.phys; + link->status = 0; + link->ctrl = (XHCI_TRB_LINK << XHCI_LNKTRB_CTRL_TRB_TYPE) | + (1 << XHCI_LNKTRB_CTRL_TC) | + xhci->cmd_ring.cycle_bit; - xhci->cmd_ring_idx = 0; - xhci->cmd_cycle_bit ^= 1; - } - - struct xhci_trb* trb = &xhci->cmd_ring[xhci->cmd_ring_idx]; - trb->param = param; - trb->status = status; - trb->ctrl = (ctrl & ~XHCI_LNKTRB_CTRL_TC) | xhci->cmd_cycle_bit; - - xhci->cmd_ring_idx++; - - atomic_store (&xhci->pending, true); - - xhci_write32 (xhci->xhci_doorbell_base, 0, 0); - - int timeout = 100; - - spin_unlock (&xhci->device->lock, *lockflags); - - while (atomic_load (&xhci->pending) && --timeout > 0) - stall_ms (10); - - spin_lock (&xhci->device->lock, lockflags); - - if (timeout == 0) - DEBUG ("timed out\n"); - } else { - while (atomic_load (&xhci->pending)) { - xhci_poll_events (xhci); - spin_lock_relax (); - } + xhci->cmd_ring.idx = 0; + xhci->cmd_ring.cycle_bit ^= 1; } + + struct xhci_trb* trb = &xhci->cmd_ring.trbs[xhci->cmd_ring.idx]; + trb->param = param; + trb->status = status; + trb->ctrl = (ctrl & ~XHCI_LNKTRB_CTRL_TC) | xhci->cmd_ring.cycle_bit; + + xhci->cmd_ring.idx++; + + atomic_store (&xhci->pending, true); + + int timeout = 100; + + spin_unlock (&xhci->device->lock, *lockflags); + + xhci_write32 (xhci->xhci_doorbell_base, 0, 0); + + while (atomic_load (&xhci->pending) && --timeout > 0) + stall_ms (10); + + spin_lock (&xhci->device->lock, lockflags); + + if (timeout == 0) + DEBUG ("timed out\n"); } static void xhci_bios_handover (struct xhci* xhci) { @@ -704,7 +706,7 @@ static void xhci_reset_ports (struct xhci* xhci) { if ((portsc & (1 << XHCI_PORTSC_CCS))) { DEBUG ("Device connected. resetting\n"); xhci_port_reset (xhci, port); - xhci_create_pdevice (xhci, port); + xhci_create_pdevice (xhci, xhci_port); } DEBUG ("PORT %u: USB %u.%u\n", port, major, minor); @@ -724,10 +726,10 @@ static void xhci_pdevice_setup_addressing (struct xhci* xhci, struct xhci_pdevic struct limine_hhdm_response* hhdm = limine_hhdm_request.response; struct xhci_port* xhci_port; - list_find (struct xhci_port, xhci->xhci_ports, xhci_port, port_value, pdevice->port_value, - ports_link); + list_find (struct xhci_port, xhci->xhci_ports, xhci_port, port_value, + pdevice->xhci_port->port_value, ports_link); - uint32_t portsc = xhci_portsc_read (xhci, pdevice->port_value); + uint32_t portsc = xhci_portsc_read (xhci, pdevice->xhci_port->port_value); uint32_t speed = (portsc >> XHCI_PORTSC_PORTSPEED) & 0x0F; @@ -746,13 +748,13 @@ static void xhci_pdevice_setup_addressing (struct xhci* xhci, struct xhci_pdevic memset (out_ctx_virt, 0, PAGE_SIZE); xhci->xhci_dcbaa[pdevice->slot_id] = out_ctx_phys; - pdevice->endpoint0_ring_phys = pmm_alloc (1); - pdevice->endpoint0_ring = - (struct xhci_trb*)(pdevice->endpoint0_ring_phys + (uintptr_t)hhdm->offset); - memset (pdevice->endpoint0_ring, 0, PAGE_SIZE); - pdevice->endpoint0_ring_size = PAGE_SIZE / sizeof (struct xhci_trb); - pdevice->endpoint0_ring_idx = 0; - pdevice->endpoint0_cycle_bit = 1; + pdevice->endpoint0_ring.phys = pmm_alloc (1); + pdevice->endpoint0_ring.trbs = + (struct xhci_trb*)(pdevice->endpoint0_ring.phys + (uintptr_t)hhdm->offset); + memset (pdevice->endpoint0_ring.trbs, 0, PAGE_SIZE); + pdevice->endpoint0_ring.size = PAGE_SIZE / sizeof (struct xhci_trb); + pdevice->endpoint0_ring.idx = 0; + pdevice->endpoint0_ring.cycle_bit = 1; uintptr_t input_ctx_phys = pmm_alloc (1); void* input_ctx_virt = (void*)(input_ctx_phys + (uintptr_t)hhdm->offset); @@ -767,13 +769,14 @@ static void xhci_pdevice_setup_addressing (struct xhci* xhci, struct xhci_pdevic ctx64->ctrl.dw[1] = (1 << 0) | (1 << 1); ctx64->slot.dw[0] = (1 << XHCI_SLCTX_SLOT_STATE) | (speed << XHCI_SLCTX_SPEED); - ctx64->slot.dw[1] = ((pdevice->port_value + 1) << XHCI_SLCTX_ROOTHUBPRNUM); + ctx64->slot.dw[1] = ((pdevice->xhci_port->port_value + 1) << XHCI_SLCTX_ROOTHUBPRNUM); ctx64->endpoints[0].dw[0] = 0; - ctx64->endpoints[0].dw[1] = - 3 | (XHCI_EP_CTRL_BI << XHCI_EPCTX_EP_TYPE) | (max_packet_size << XHCI_EPCTX_MAX_PKT_SZ); - 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); + ctx64->endpoints[0].dw[1] = (3 << XHCI_EPCTX_ERR_COUNT) | + (XHCI_EP_CTRL_BI << XHCI_EPCTX_EP_TYPE) | + (max_packet_size << XHCI_EPCTX_MAX_PKT_SZ); + 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 { struct xhci_input_ctx32* ctx32 = input_ctx_virt; @@ -782,12 +785,13 @@ static void xhci_pdevice_setup_addressing (struct xhci* xhci, struct xhci_pdevic ctx32->ctrl.dw[1] = (1 << 0) | (1 << 1); ctx32->slot.dw[0] = (1 << XHCI_SLCTX_SLOT_STATE) | (speed << XHCI_SLCTX_SPEED); - ctx32->slot.dw[1] = ((pdevice->port_value + 1) << XHCI_SLCTX_ROOTHUBPRNUM); + ctx32->slot.dw[1] = ((pdevice->xhci_port->port_value + 1) << XHCI_SLCTX_ROOTHUBPRNUM); - ctx32->endpoints[0].dw[1] = - 3 | (XHCI_EP_CTRL_BI << XHCI_EPCTX_EP_TYPE) | (max_packet_size << XHCI_EPCTX_MAX_PKT_SZ); - 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); + ctx32->endpoints[0].dw[1] = (3 << XHCI_EPCTX_ERR_COUNT) | + (XHCI_EP_CTRL_BI << XHCI_EPCTX_EP_TYPE) | + (max_packet_size << XHCI_EPCTX_MAX_PKT_SZ); + 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; @@ -797,10 +801,11 @@ static void xhci_pdevice_setup_addressing (struct xhci* xhci, struct xhci_pdevic stall_ms (500); if (xhci->last_cmpl_code != 1) { - DEBUG ("Failed to address device. port = %u, slot = %u\n", pdevice->port_value, + DEBUG ("Failed to address device. port = %u, slot = %u\n", pdevice->xhci_port->port_value, pdevice->slot_id); } else { - DEBUG ("Device on port %u addressed on slot %u!\n", pdevice->port_value, pdevice->slot_id); + DEBUG ("Device on port %u addressed on slot %u!\n", pdevice->xhci_port->port_value, + pdevice->slot_id); } pmm_free (input_ctx_phys, 1); @@ -829,6 +834,35 @@ static bool xhci_pdevice_setup_get_info (struct xhci* xhci, struct xhci_pdevice* usb_desc->vendor_id, usb_desc->product_id, usb_desc->dev_class, usb_desc->dev_subclass, usb_desc->max_packet_size, usb_desc->num_configs); + pdevice->device_desc = *usb_desc; + + pmm_free (response_buf_phys, 1); + return true; +} + +static bool xhci_pdevice_setup_get_config (struct xhci* xhci, struct xhci_pdevice* pdevice, + uint64_t* lockflags) { + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t response_buf_phys = pmm_alloc (1); + + void* response_buf = (void*)(response_buf_phys + (uintptr_t)hhdm->offset); + memset (response_buf, 0, PAGE_SIZE); + + bool ok = + xhci_endpoint0_ctrl_in (xhci, pdevice, 0x80, 6, (2 << 8), 0, response_buf_phys, 9, lockflags); + + if (!ok) { + pmm_free (response_buf_phys, 1); + return false; + } + + struct usb_config_desc* usb_config = response_buf; + + DEBUG ("USB device config: total_len=%u num_ifs=%u, cfgval=%u cfg=%u attrs=%02x maxpow=%u\n", + usb_config->total_length, usb_config->num_ifs, usb_config->config_value, + usb_config->config, usb_config->attrs, usb_config->max_power); + pmm_free (response_buf_phys, 1); return true; } @@ -846,11 +880,14 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) { xhci_pdevice_setup_addressing (xhci, pdevice, lockflags); xhci_pdevice_setup_get_info (xhci, pdevice, lockflags); + + xhci_pdevice_setup_get_config (xhci, pdevice, lockflags); } } static void xhci_poll_port_changes (struct xhci* xhci) { struct list_node_link *port_change_link, *tmp_port_change_link; + struct xhci_port* xhci_port; list_foreach (xhci->port_changes, port_change_link, tmp_port_change_link) { struct xhci_port_status_change* change = @@ -858,16 +895,18 @@ static void xhci_poll_port_changes (struct xhci* xhci) { list_remove (xhci->port_changes, &change->port_changes_link); + list_find (struct xhci_port, xhci->xhci_ports, xhci_port, port_value, change->port, ports_link); + if ((change->portsc & (1 << XHCI_PORTSC_CSC))) { if ((change->portsc & (1 << XHCI_PORTSC_CCS))) { DEBUG ("Device attached to port %u!\n", change->port); xhci_port_reset (xhci, change->port); - xhci_create_pdevice (xhci, change->port); + xhci_create_pdevice (xhci, xhci_port); } else { DEBUG ("Device detached from port %u!\n", change->port); - xhci_delete_pdevice (xhci, change->port); + xhci_delete_pdevice (xhci, xhci_port); } } @@ -972,29 +1011,29 @@ DEFINE_DEVICE_INIT (xhci_init) { xhci_write32 (xhci->xhci_oper_base, XHCI_DCBAAP, (uint32_t)xhci->xhci_dcbaa_phys); xhci_write32 (xhci->xhci_oper_base, XHCI_DCBAAP + 4, (uint32_t)(xhci->xhci_dcbaa_phys >> 32)); - xhci->cmd_ring_phys = pmm_alloc (1); - xhci->cmd_ring = (struct xhci_trb*)(xhci->cmd_ring_phys + (uintptr_t)hhdm->offset); - memset (xhci->cmd_ring, 0, PAGE_SIZE); - xhci->cmd_ring_size = PAGE_SIZE / sizeof (struct xhci_trb); - xhci->cmd_ring_idx = 0; - xhci->cmd_cycle_bit = 1; + xhci->cmd_ring.phys = pmm_alloc (1); + xhci->cmd_ring.trbs = (struct xhci_trb*)(xhci->cmd_ring.phys + (uintptr_t)hhdm->offset); + memset (xhci->cmd_ring.trbs, 0, PAGE_SIZE); + xhci->cmd_ring.size = PAGE_SIZE / sizeof (struct xhci_trb); + xhci->cmd_ring.idx = 0; + xhci->cmd_ring.cycle_bit = 1; - uint64_t crcr = xhci->cmd_ring_phys | xhci->cmd_cycle_bit; + uint64_t crcr = xhci->cmd_ring.phys | xhci->cmd_ring.cycle_bit; xhci_write32 (xhci->xhci_oper_base, XHCI_CRCR, (uint32_t)crcr); xhci_write32 (xhci->xhci_oper_base, XHCI_CRCR + 4, (uint32_t)(crcr >> 32)); - xhci->event_ring_phys = pmm_alloc (1); - xhci->event_ring = (struct xhci_trb*)(xhci->event_ring_phys + (uintptr_t)hhdm->offset); - memset (xhci->event_ring, 0, PAGE_SIZE); - xhci->event_ring_size = PAGE_SIZE / sizeof (struct xhci_trb); - xhci->event_ring_idx = 0; - xhci->event_cycle_bit = 1; + xhci->event_ring.phys = pmm_alloc (1); + xhci->event_ring.trbs = (struct xhci_trb*)(xhci->event_ring.phys + (uintptr_t)hhdm->offset); + memset (xhci->event_ring.trbs, 0, PAGE_SIZE); + xhci->event_ring.size = PAGE_SIZE / sizeof (struct xhci_trb); + xhci->event_ring.idx = 0; + xhci->event_ring.cycle_bit = 1; xhci->erst_phys = pmm_alloc (1); xhci->erst = (struct xhci_erst_entry*)(xhci->erst_phys + (uintptr_t)hhdm->offset); memset (xhci->erst, 0, PAGE_SIZE); - xhci->erst[0].ptr = xhci->event_ring_phys; - xhci->erst[0].size = xhci->event_ring_size; + xhci->erst[0].ptr = xhci->event_ring.phys; + xhci->erst[0].size = xhci->event_ring.size; xhci->erst[0]._rsvd = 0; uintptr_t ir_base = xhci->xhci_runtime_base + 0x20; @@ -1002,14 +1041,12 @@ DEFINE_DEVICE_INIT (xhci_init) { xhci_write32 (ir_base, XHCI_ERSTBA, (uint32_t)xhci->erst_phys); xhci_write32 (ir_base, XHCI_ERSTBA + 4, (uint32_t)(xhci->erst_phys >> 32)); - xhci_write32 (ir_base, XHCI_ERDP, (uint32_t)xhci->event_ring_phys | (1 << 3)); - xhci_write32 (ir_base, XHCI_ERDP + 4, (uint32_t)(xhci->event_ring_phys >> 32)); + xhci_write32 (ir_base, XHCI_ERDP, (uint32_t)xhci->event_ring.phys | (1 << 3)); + xhci_write32 (ir_base, XHCI_ERDP + 4, (uint32_t)(xhci->event_ring.phys >> 32)); - if (xhci->irqs_support) { - /* enable interrupter */ - irq_attach (&xhci_irq, xhci, xhci->irq); - xhci_write32 (ir_base, XHCI_IMAN, xhci_read32 (ir_base, XHCI_IMAN) | (1 << 1)); - } + /* enable interrupter */ + irq_attach (&xhci_irq, xhci, xhci->irq); + xhci_write32 (ir_base, XHCI_IMAN, xhci_read32 (ir_base, XHCI_IMAN) | (1 << 1)); usbcmd = xhci_read32 (xhci->xhci_oper_base, XHCI_USBCMD); xhci_write32 (xhci->xhci_oper_base, XHCI_USBCMD, usbcmd | (1 << 0) | (1 << 2)); @@ -1047,8 +1084,8 @@ DEFINE_DEVICE_FINI (xhci_fini) { } pmm_free (xhci->xhci_dcbaa_phys, 1); - pmm_free (xhci->cmd_ring_phys, 1); - pmm_free (xhci->event_ring_phys, 1); + pmm_free (xhci->cmd_ring.phys, 1); + pmm_free (xhci->event_ring.phys, 1); pmm_free (xhci->erst_phys, 1); struct list_node_link *port_link, *tmp_port_link; diff --git a/kernel/device/usb/xhci.h b/kernel/device/usb/xhci.h index 707675c..d574890 100644 --- a/kernel/device/usb/xhci.h +++ b/kernel/device/usb/xhci.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -58,16 +59,21 @@ struct xhci_port { int type; }; +struct xhci_ring { + struct xhci_trb* trbs; + uintptr_t phys; + uint32_t idx; + uint32_t size; + uint8_t cycle_bit; +}; + struct xhci_pdevice { struct list_node_link pdevices_link; - uint8_t port_value; + struct xhci_port* xhci_port; int slot_id; - struct xhci_trb* endpoint0_ring; - uintptr_t endpoint0_ring_phys; - uint32_t endpoint0_ring_idx; - uint32_t endpoint0_ring_size; - uint8_t endpoint0_cycle_bit; + struct xhci_ring endpoint0_ring; + struct usb_device_desc device_desc; }; struct xhci_port_status_change { @@ -96,17 +102,8 @@ struct xhci { uint32_t max_slots; - struct xhci_trb* cmd_ring; - uintptr_t cmd_ring_phys; - uint32_t cmd_ring_idx; - uint32_t cmd_ring_size; - uint8_t cmd_cycle_bit; - - struct xhci_trb* event_ring; - uintptr_t event_ring_phys; - uint32_t event_ring_idx; - uint32_t event_ring_size; - uint8_t event_cycle_bit; + struct xhci_ring cmd_ring; + struct xhci_ring event_ring; struct xhci_erst_entry* erst; uintptr_t erst_phys; diff --git a/usb/usb.c b/usb/usb.c index 6ff79b2..9a0e158 100644 --- a/usb/usb.c +++ b/usb/usb.c @@ -8,8 +8,6 @@ #include #include -static void usb_poll_driver_proc (void* arg) { struct device_info* info = arg; } - void app_main (void) { libprocess_self_init (); @@ -39,7 +37,8 @@ void app_main (void) { for (;;) { device_do (info->key, XUSBCTRL_POLL_DRIVER, NULL, NULL, NULL, NULL); - sched (); + for (volatile int i = 0; i < 1000; i++) + sched (); } } } else {