aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb/xhci.c
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-04-04 19:26:45 -0400
committerIan Moffett <ian@osmora.org>2024-04-04 19:27:10 -0400
commit8d6088386c1fa0bf09678b328bee19768f138dcb (patch)
treeb907ef43d90f12681fbdef7ce6d412f4cef53c45 /sys/dev/usb/xhci.c
parentf78c52a09994d281e043110d01049cbfe393e5ac (diff)
kernel: xhci: Add link TRB at end of cmd ring
Make the command ring circular by pointing the xHC to the start once it reaches the end. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/dev/usb/xhci.c')
-rw-r--r--sys/dev/usb/xhci.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index a6996bf..2550768 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -116,14 +116,24 @@ xhci_submit_cmd(struct xhci_hc *hc, struct xhci_trb trb)
hc->cmd_ring[hc->cmd_ptr++] = trb.dword3 | hc->cycle;
hc->cmd_count++;
- if (hc->cmd_count >= XHCI_CMDRING_LEN) {
- /* TODO: Add link TRB */
- __assert(0 && "TODO");
- }
-
/* Ring the command doorbell */
cmd_db = XHCI_CMD_DB(hc->base, caps->dboff);
*cmd_db = 0;
+
+ if (hc->cmd_count >= XHCI_CMDRING_LEN - 1) {
+ /* Create raw link TRB and ring the doorbell */
+ hc->cmd_ring[hc->cmd_ptr++] = VIRT_TO_PHYS(hc->cmd_ring) & 0xFFFFFFFF;
+ hc->cmd_ring[hc->cmd_ptr++] = VIRT_TO_PHYS(hc->cmd_ring) >> 32;
+ hc->cmd_ring[hc->cmd_ptr++] = 0;
+ hc->cmd_ring[hc->cmd_ptr++] = hc->cycle | (XHCI_LINK << 10) | __BIT(1);
+ *cmd_db = 0;
+
+ /* Reset command state and flip cycle */
+ hc->cmd_ptr = 0;
+ hc->cmd_count = 0;
+ hc->cycle = ~hc->cycle;
+ }
+
return 0;
}