@@ -35,6 +35,41 @@ static inline uint8_t trb_get_slotid(const struct trb *e)
3535 return (uint8_t )(e -> ctrl & 0xFF );
3636}
3737
38+ /* === Event-ring consumer helpers (xHC produces; we only consume) === */
39+
40+ static inline struct trb * evt_cur (struct xhci_hc * hc )
41+ {
42+ return & hc -> evt .base [hc -> evt .enqueue ];
43+ }
44+
45+ /* Is the next event TRB owned by software? (C-bit matches CCS/consumer cycle) */
46+ static inline int evt_has_ready (struct xhci_hc * hc )
47+ {
48+ const struct trb * e = evt_cur (hc );
49+ const uint32_t cbit = (e -> ctrl & TRB_CYCLE ) ? 1u : 0u ;
50+ return (cbit == (hc -> evt .cycle & 1u ));
51+ }
52+
53+ /* Consume exactly one TRB and advance consumer cursor/cycle */
54+ static inline void evt_consume (struct xhci_hc * hc )
55+ {
56+ struct trb * e = evt_cur (hc );
57+ memset (e , 0 , sizeof (* e )); /* optional but handy */
58+ hc -> evt .enqueue ++ ;
59+ if (hc -> evt .enqueue == hc -> evt .num_trbs ) {
60+ hc -> evt .enqueue = 0 ;
61+ hc -> evt .cycle ^= 1u ; /* toggle consumer cycle on wrap */
62+ }
63+ }
64+
65+ /* Program ERDP to the *next-to-consume* TRB, EHB clear (bit3=0) */
66+ static inline void evt_update_erdp (struct xhci_hc * hc )
67+ {
68+ volatile uint8_t * ir0 = hc -> rt + XHCI_RT_IR0 ;
69+ uint64_t erdp = hc -> evt .phys + ((uint64_t )hc -> evt .enqueue * sizeof (struct trb ));
70+ mmio_write64 (ir0 + IR_ERDP , erdp ); /* keep EHB clear in steady state */
71+ }
72+
3873static void xhci_handle_unrelated_transfer_event (struct xhci_hc * hc , struct trb * e )
3974{
4075 if (!hc || !e ) return ;
@@ -43,8 +78,7 @@ static void xhci_handle_unrelated_transfer_event(struct xhci_hc *hc, struct trb
4378 case TRB_TRANSFER_EVENT : {
4479 /* If this is our INT IN endpoint, deliver to HID and re-arm */
4580 uint8_t epid = trb_get_epid (e );
46- if (epid == EPID_EP1_IN &&
47- hc -> dev .int_cb && hc -> dev .int_buf && hc -> dev .int_pkt_len ) {
81+ if (epid == EPID_EP1_IN && hc -> dev .int_cb && hc -> dev .int_buf && hc -> dev .int_pkt_len ) {
4882 xhci_deliver_ep1in (hc , e , false);
4983 }
5084 break ;
@@ -93,15 +127,45 @@ static void ring_init(struct xhci_ring *r, size_t bytes, uint64_t phys, void *vi
93127 dprintf ("xhci.dbg: TRBs=%u link_trb@%u lo=%08x hi=%08x ctrl=%08x\n" , r -> num_trbs , r -> num_trbs - 1 , link -> lo , link -> hi , link -> ctrl );
94128}
95129
96- /* ring_push with debug */
97- static struct trb * ring_push (struct xhci_ring * r ) {
98- if (r -> enqueue == r -> num_trbs - 1 ) {
130+ // assumes: slot (last index) is pre-initialized as LINK TRB:
131+ // link->lo = ring_phys; // target
132+ // link->ctrl = TRB_SET_TYPE(TRB_LINK) | TRB_TOGGLE; // TC=1
133+ // r->cycle = 1; r->enqueue = 0;
134+
135+ static inline struct trb * ring_push (struct xhci_ring * r )
136+ {
137+ struct trb * cur = & r -> base [r -> enqueue ];
138+
139+ // Ensure caller can set the C bit on the TRB they’re about to fill.
140+ // (Caller will set TRB_CYCLE according to r->cycle.)
141+ // Do NOT zero a LINK TRB.
142+
143+ // Advance the producer pointer
144+ r -> enqueue ++ ;
145+ dprintf ("enqueue=%u num_trbs=%u\n" , r -> enqueue , r -> num_trbs );
146+
147+ // If we landed on the LINK TRB, present it to HW and wrap
148+ if (r -> enqueue == r -> num_trbs ) {
149+ dprintf ("wrap LINK\n" );
150+ struct trb * link = & r -> base [r -> num_trbs - 1 ];
151+
152+ // Set LINK’s C bit to current producer cycle
153+ link -> ctrl = (link -> ctrl & ~TRB_CYCLE ) | (r -> cycle ? TRB_CYCLE : 0 );
154+
155+ // “Post” the LINK TRB by moving past it
99156 r -> enqueue = 0 ;
100- r -> cycle ^= 1u ;
157+
158+ // If LINK.TC=1, flip producer cycle bit
159+ if (link -> ctrl & TRB_TOGGLE )
160+ r -> cycle ^= 1u ;
161+
162+ // Now cur becomes the first slot of the ring
163+ cur = & r -> base [r -> enqueue ];
101164 }
102- struct trb * t = & r -> base [r -> enqueue ++ ];
103- memset (t , 0 , sizeof (* t ));
104- return t ;
165+
166+ // Hand back the slot to be filled; clear only non-LINK slots
167+ memset (cur , 0 , sizeof (* cur ));
168+ return cur ;
105169}
106170
107171static int xhci_cmd_submit_wait (struct xhci_hc * hc , struct trb * cmd_trb , uint64_t * out_cc_trb_lohi ) {
@@ -340,10 +404,7 @@ static int xhci_reset_controller(struct xhci_hc *hc) {
340404 mmio_write32 (ir0 + IR_IMOD , 0 );
341405 mmio_write32 (ir0 + IR_IMAN , IR_IMAN_IE );
342406
343- dprintf ("xhci.dbg: ERSTSZ=1 ERSTBA=%llx ERDP=%llx IMOD=64 IMAN=%08x\n" ,
344- (unsigned long long )hc -> erst_phys ,
345- (unsigned long long )(er_phys | (1ull << 3 )),
346- mmio_read32 (ir0 + IR_IMAN ));
407+ dprintf ("xhci.dbg: ERSTSZ=1 ERSTBA=%lx ERDP=%lx IMOD=64 IMAN=%08x\n" , hc -> erst_phys , (uint64_t )(er_phys | (1ull << 3 )), mmio_read32 (ir0 + IR_IMAN ));
347408
348409 /* CONFIG, RS+INTE */
349410 mmio_write32 (hc -> op + XHCI_CONFIG , hc -> max_slots ? hc -> max_slots : 8 );
@@ -841,9 +902,11 @@ static void xhci_deliver_ep1in(struct xhci_hc *hc, const struct trb *e, bool del
841902 }
842903}
843904
905+ static uint64_t xhci_ints ;
906+
844907static void xhci_isr (uint8_t isr , uint64_t error , uint64_t irq , void * opaque )
845908{
846- dprintf ("xhci_isr\n" );
909+ dprintf ("xhci_isr %lu \n" , xhci_ints ++ );
847910 struct xhci_hc * hc = (struct xhci_hc * )opaque ;
848911 if (!hc || !hc -> cap ) return ;
849912
@@ -873,11 +936,15 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
873936 /* Only deliver to HID for EP1-IN completions */
874937 if (epid == EPID_EP1_IN ) {
875938 xhci_deliver_ep1in (hc , e , true);
939+ } else {
940+ /* Consume and advance ERDP by one TRB (leave EHB clear) */
941+ xhci_handle_unrelated_transfer_event (hc , e );
876942 }
943+ } else {
944+ /* Consume and advance ERDP by one TRB (leave EHB clear) */
945+ xhci_handle_unrelated_transfer_event (hc , e );
877946 }
878947
879- /* Consume and advance ERDP by one TRB (leave EHB clear) */
880- xhci_handle_unrelated_transfer_event (hc , e );
881948 memset (e , 0 , sizeof (* e ));
882949 erdp_cur = (erdp_cur + 16 ) & ~0x7ull ;
883950 mmio_write64 (ir0 + IR_ERDP , erdp_cur );
@@ -910,8 +977,7 @@ int xhci_arm_int_in(struct usb_dev *ud, uint16_t pkt_len, xhci_int_in_cb cb) {
910977 /* Only EP1 IN is supported in this driver (EPID==3). */
911978 if (ep_num != 1 ) {
912979 uint8_t epid = (uint8_t )(2u * ep_num + 1u );
913- dprintf ("xhci.dbg: WARNING: device INT-IN at EP%u (EPID=%u), driver only supports EP1 IN; not arming.\n" ,
914- ep_num , epid );
980+ dprintf ("xhci.dbg: WARNING: device INT-IN at EP%u (EPID=%u), driver only supports EP1 IN; not arming.\n" , ep_num , epid );
915981 return 0 ;
916982 }
917983
@@ -1059,7 +1125,7 @@ int xhci_arm_int_in(struct usb_dev *ud, uint16_t pkt_len, xhci_int_in_cb cb) {
10591125 {
10601126 volatile uint8_t * ir0 = hc -> rt + XHCI_RT_IR0 ;
10611127
1062- mmio_write32 (ir0 + IR_IMOD , 0 );
1128+ mmio_write32 (ir0 + IR_IMOD , 64 );
10631129
10641130 uint32_t sts = mmio_read32 (hc -> op + XHCI_USBSTS );
10651131 if (sts & USBSTS_EINT ) mmio_write32 (hc -> op + XHCI_USBSTS , USBSTS_EINT );
0 commit comments