XHCI generic way of putting TRBs onto a ring

This commit is contained in:
2026-04-03 16:46:02 +02:00
parent 92ed1fb968
commit 6dd7a7c654

View File

@@ -605,31 +605,30 @@ 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_usb_device* usb_device, struct xhci_trb put_trb) {
if (usb_device->endpoint0_ring.idx == usb_device->endpoint0_ring.size - 1) {
struct xhci_trb* link = &usb_device->endpoint0_ring.trbs[usb_device->endpoint0_ring.idx];
link->param = usb_device->endpoint0_ring.phys;
static void xhci_ring_put_trb (struct xhci_ring* ring, struct xhci_trb put_trb) {
if (ring->idx == ring->size - 1) {
struct xhci_trb* link = &ring->trbs[ring->idx];
link->param = ring->phys;
link->status = 0;
write_memory_barrier ();
link->ctrl = (XHCI_TRB_LINK << XHCI_LNKTRB_CTRL_TRB_TYPE) |
(1 << XHCI_LNKTRB_CTRL_TC) |
usb_device->endpoint0_ring.cycle_bit;
link->ctrl =
(XHCI_TRB_LINK << XHCI_LNKTRB_CTRL_TRB_TYPE) | (1 << XHCI_LNKTRB_CTRL_TC) | ring->cycle_bit;
usb_device->endpoint0_ring.idx = 0;
usb_device->endpoint0_ring.cycle_bit ^= 1;
ring->idx = 0;
ring->cycle_bit ^= 1;
}
struct xhci_trb* trb = &usb_device->endpoint0_ring.trbs[usb_device->endpoint0_ring.idx];
struct xhci_trb* trb = &ring->trbs[ring->idx];
trb->param = put_trb.param;
trb->status = put_trb.status;
write_memory_barrier ();
trb->ctrl = (put_trb.ctrl & ~XHCI_LNKTRB_CTRL_TC) | usb_device->endpoint0_ring.cycle_bit;
trb->ctrl = (put_trb.ctrl & ~XHCI_LNKTRB_CTRL_TC) | ring->cycle_bit;
usb_device->endpoint0_ring.idx++;
ring->idx++;
}
static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_usb_device* usb_device,
@@ -656,7 +655,7 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_usb_device* u
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 (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
/* data stage */
memset (&trb, 0, sizeof (trb));
@@ -666,7 +665,7 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_usb_device* u
write_memory_barrier ();
trb.ctrl = (XHCI_TRB_DATA_STAGE << XHCI_DSTRB_CTRL_TRB_TYPE) | (1 << XHCI_DSTRB_CTRL_DIR);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
/* status stage */
memset (&trb, 0, sizeof (trb));
@@ -676,7 +675,7 @@ static bool xhci_endpoint0_ctrl_in (struct xhci* xhci, struct xhci_usb_device* u
write_memory_barrier ();
trb.ctrl = (XHCI_TRB_STATUS_STAGE << XHCI_STSTRB_CTRL_TRB_TYPE) | (1 << XHCI_STSTRB_CTRL_IOC);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
atomic_store (&xhci->pending, true);
@@ -724,12 +723,12 @@ static bool xhci_endpoint0_ctrl_out (struct xhci* xhci, struct xhci_usb_device*
trb.ctrl = (XHCI_TRB_SETUP_STAGE << XHCI_SSTRB_CTRL_TRB_TYPE) |
(1 << XHCI_SSTRB_CTRL_IDT) |
(XHCI_SSTRB_TRT_NO_DATA_STAGE << XHCI_SSTRB_CTRL_TRT);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
} else {
trb.ctrl = (XHCI_TRB_SETUP_STAGE << XHCI_SSTRB_CTRL_TRB_TYPE) |
(1 << XHCI_SSTRB_CTRL_IDT) |
(XHCI_SSTRB_TRT_OUT_DATA_STAGE << XHCI_SSTRB_CTRL_TRT);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
/* data stage */
memset (&trb, 0, sizeof (trb));
@@ -739,7 +738,7 @@ static bool xhci_endpoint0_ctrl_out (struct xhci* xhci, struct xhci_usb_device*
write_memory_barrier ();
trb.ctrl = (XHCI_TRB_DATA_STAGE << XHCI_DSTRB_CTRL_TRB_TYPE);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
}
/* status stage */
@@ -752,7 +751,7 @@ static bool xhci_endpoint0_ctrl_out (struct xhci* xhci, struct xhci_usb_device*
trb.ctrl = (XHCI_TRB_STATUS_STAGE << XHCI_STSTRB_CTRL_TRB_TYPE) |
(1 << XHCI_STSTRB_CTRL_IOC) |
(1 << XHCI_STSTRB_CTRL_DIR);
xhci_endpoint0_put_trb (usb_device, trb);
xhci_ring_put_trb (&usb_device->endpoint0_ring, trb);
atomic_store (&xhci->pending, true);