@@ -7,6 +7,8 @@ xhci_command_ring::xhci_command_ring(size_t max_trbs) {
77 m_max_trb_count = max_trbs;
88 m_rcs_bit = XHCI_CRCR_RING_CYCLE_STATE;
99 m_enqueue_ptr = 0 ;
10+ m_dequeue_ptr = 0 ;
11+ m_consumer_cycle_state = true ;
1012
1113 const uint64_t ring_size = max_trbs * sizeof (xhci_trb_t );
1214
@@ -25,7 +27,14 @@ xhci_command_ring::xhci_command_ring(size_t max_trbs) {
2527 (XHCI_TRB_TYPE_LINK << XHCI_TRB_TYPE_SHIFT) | XHCI_LINK_TRB_TC_BIT | m_rcs_bit;
2628}
2729
28- void xhci_command_ring::enqueue (xhci_trb_t * trb) {
30+ bool xhci_command_ring::enqueue (xhci_trb_t * trb) {
31+ auto can_enqueue = m_consumer_cycle_state == m_rcs_bit
32+ ? m_enqueue_ptr >= m_dequeue_ptr
33+ : m_enqueue_ptr < m_dequeue_ptr;
34+ if (!can_enqueue) {
35+ return false ;
36+ }
37+
2938 // Adjust the TRB's cycle bit to the current RCS
3039 trb->cycle_bit = m_rcs_bit;
3140
@@ -43,6 +52,25 @@ void xhci_command_ring::enqueue(xhci_trb_t* trb) {
4352 m_enqueue_ptr = 0 ;
4453 m_rcs_bit = !m_rcs_bit;
4554 }
55+
56+ return true ;
57+ }
58+
59+ void xhci_command_ring::process_event (xhci_command_completion_trb_t * event) {
60+ // xHCI 4.9.3 Command Ring Management
61+ // > The location of the Command Ring Dequeue Pointer is reported on the Event Ring in Command Completion Events.
62+ // xHCI 3.3 Command Interface
63+ // > Commands are executed by the xHC in the order that they are placed on the Command Ring.
64+ auto command_index = (event->command_trb_pointer - m_physical_base) / sizeof (xhci_trb_t );
65+ // This could result in the dequeue pointer pointing to a Link TRB, which should be pretty instantly processed.
66+ // But we can't assume that the xHC processed the Link TRB and we shouldn't overwrite it until we're sure.
67+ // Since commands are executed in order, we don't need to worry about the dequeue pointer getting moved back because of out-of-order events.
68+ auto new_dequeue_ptr = command_index + 1 ;
69+ // If the consumer (xHC) looped around, it must have toggled its consumer cycle state
70+ if (new_dequeue_ptr < m_dequeue_ptr) {
71+ m_consumer_cycle_state = !m_consumer_cycle_state;
72+ }
73+ m_dequeue_ptr = new_dequeue_ptr;
4674}
4775
4876xhci_event_ring::xhci_event_ring (
0 commit comments