55
66static struct xhci_hc * g_xhci ; /* single controller */
77
8- static void xhci_deliver_ep1in (struct xhci_hc * hc , const struct trb * ev );
8+ static void xhci_deliver_ep1in (struct xhci_hc * hc , const struct trb * ev , bool deliver_to_driver );
99
10- static void xhci_handle_unrelated_transfer_event (struct xhci_hc * hc , const struct trb * e )
10+ static inline uint8_t trb_get_type (const struct trb * e ) {
11+ return (uint8_t )((e -> ctrl >> 10 ) & 0x3F );
12+ }
13+
14+ static inline uint8_t trb_get_epid (const struct trb * e ) {
15+ return (uint8_t )((e -> ctrl >> 16 ) & 0x1F );
16+ }
17+
18+ static inline uint32_t trb_get_evtl (const struct trb * e ) {
19+ return (e -> sts & 0x00FFFFFFu );
20+ }
21+
22+ static inline uint8_t trb_get_cc (const struct trb * e )
1123{
12- if (!hc || !e ) {
13- return ;
14- }
24+ return (uint8_t )((e -> sts >> 24 ) & 0xFF );
25+ }
1526
16- uint8_t type = (uint8_t )((e -> ctrl >> 10 ) & 0x3F );
17- if (type != TRB_TRANSFER_EVENT ) {
18- return ;
19- }
27+ static inline uint32_t trb_get_bytes_remaining (const struct trb * e )
28+ {
29+ return (e -> sts & 0x00FFFFFFu );
30+ }
31+
32+ static inline uint8_t trb_get_slotid (const struct trb * e )
33+ {
34+ /* SlotID is bits [7:0] of control dword per xHCI spec */
35+ return (uint8_t )(e -> ctrl & 0xFF );
36+ }
37+
38+ static void xhci_handle_unrelated_transfer_event (struct xhci_hc * hc , struct trb * e )
39+ {
40+ if (!hc || !e ) return ;
41+
42+ switch (trb_get_type (e )) {
43+ case TRB_TRANSFER_EVENT : {
44+ /* If this is our INT IN endpoint, deliver to HID and re-arm */
45+ 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 ) {
48+ xhci_deliver_ep1in (hc , e , false);
49+ }
50+ break ;
51+ }
2052
21- uint8_t epid = (uint8_t )((e -> ctrl >> 16 ) & 0x1F );
22- if (epid == EPID_EP1_IN ) {
23- /* Forward HID report events even during EP0 polling */
24- xhci_deliver_ep1in (hc , e );
53+ /* We don’t act on other event types here; callers still consume & advance ERDP. */
54+ case TRB_CMD_COMPLETION :
55+ case TRB_PORT_STATUS :
56+ case TRB_HOST_CONTROLLER_EVENT :
57+ default :
58+ break ;
2559 }
2660}
2761
62+
63+ /* Decode a Transfer Event TRB -> slot_id, endpoint_id, cc, bytes (EVTL). */
64+ static inline void xhci_decode_xfer_evt (const struct trb * e , uint8_t * slot_id , uint8_t * ep_id , uint8_t * cc , uint32_t * bytes )
65+ {
66+ /* Dword3: [31:24]=CC, [23:17]=rsvd, [16:8]=EPID, [7:0]=SlotID */
67+ uint32_t ctrl = e -> ctrl ;
68+ uint32_t sts = e -> sts ;
69+ * cc = (uint8_t )((sts >> 24 ) & 0xFF );
70+ * ep_id = (uint8_t )((ctrl >> 16 ) & 0x1F );
71+ * slot_id = (uint8_t )(ctrl & 0xFF );
72+ * bytes = (sts & 0x00FFFFFFu ); /* EVTL: bytes remaining */
73+ }
74+
2875/* ring_init with debug — set Toggle Cycle (TC) like libpayload */
2976static void ring_init (struct xhci_ring * r , size_t bytes , uint64_t phys , void * virt ) {
30- dprintf ("xhci.dbg: ring_init bytes=%u phys=%llx virt=%llx\n" ,
31- (unsigned )bytes , (unsigned long long )phys , (unsigned long long )(uintptr_t )virt );
77+ dprintf ("xhci.dbg: ring_init bytes=%lu phys=%lx virt=%p\n" , bytes , phys , virt );
3278
3379 r -> base = (struct trb * ) virt ;
3480 r -> phys = phys ;
@@ -44,23 +90,17 @@ static void ring_init(struct xhci_ring *r, size_t bytes, uint64_t phys, void *vi
4490 link -> sts = 0 ;
4591 link -> ctrl = TRB_SET_TYPE (TRB_LINK ) | TRB_TOGGLE | TRB_CYCLE ;
4692
47- dprintf ("xhci.dbg: TRBs=%u link_trb@%u lo=%08x hi=%08x ctrl=%08x\n" ,
48- r -> num_trbs , r -> num_trbs - 1 , link -> lo , link -> hi , link -> ctrl );
93+ 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 );
4994}
5095
5196/* ring_push with debug */
5297static struct trb * ring_push (struct xhci_ring * r ) {
53- uint32_t before = r -> enqueue ;
5498 if (r -> enqueue == r -> num_trbs - 1 ) {
55- dprintf ("xhci.dbg: ring_push wrap at idx=%u, flip cycle %u->%u\n" ,
56- r -> enqueue , r -> cycle , r -> cycle ^ 1u );
5799 r -> enqueue = 0 ;
58100 r -> cycle ^= 1u ;
59101 }
60102 struct trb * t = & r -> base [r -> enqueue ++ ];
61103 memset (t , 0 , sizeof (* t ));
62- dprintf ("xhci.dbg: ring_push from %u to %u, cycle=%u trb=%llx\n" ,
63- before , r -> enqueue , r -> cycle , (unsigned long long )(uintptr_t )t );
64104 return t ;
65105}
66106
@@ -70,8 +110,7 @@ static int xhci_cmd_submit_wait(struct xhci_hc *hc, struct trb *cmd_trb, uint64_
70110 uint64_t cmd_phys = hc -> cmd .phys +
71111 (uint64_t )((uintptr_t )cmd_trb - (uintptr_t )hc -> cmd .base );
72112
73- dprintf ("xhci.dbg: cmd_submit dbell0, trb_virt=%lx trb_phys=%lx ctrl=%08x\n" ,
74- (uintptr_t )cmd_trb , cmd_phys , cmd_trb -> ctrl );
113+ dprintf ("xhci.dbg: cmd_submit dbell0, trb_virt=%lx trb_phys=%lx ctrl=%08x\n" , (uintptr_t )cmd_trb , cmd_phys , cmd_trb -> ctrl );
75114
76115 volatile uint8_t * ir0 = hc -> rt + XHCI_RT_IR0 ;
77116
@@ -147,6 +186,7 @@ static struct trb *xhci_cmd_begin(struct xhci_hc *hc) {
147186
148187static void xhci_irq_sanity_dump (struct xhci_hc * hc , const char * tag )
149188{
189+ return ;
150190 volatile uint8_t * ir0 = hc -> rt + XHCI_RT_IR0 ;
151191
152192 uint32_t usbcmd = mmio_read32 (hc -> op + XHCI_USBCMD );
@@ -755,47 +795,55 @@ static int xhci_enumerate_first_device(struct xhci_hc *hc, struct usb_dev *out_u
755795 return 1 ;
756796}
757797
758- static inline uint8_t trb_get_type (const struct trb * e ) { return (uint8_t )((e -> ctrl >> 10 ) & 0x3F ); }
759- /* xHCI Transfer Event fields (dword 3 in 'sts'):
760- bits 24..31: Completion Code (we don't need here)
761- bits 16..20: Endpoint ID (EPID)
762- bits 24..31 of *lo/hi* are pointer; length remaining is sts & 0x00FFFFFF */
763- static inline uint8_t trb_get_epid (const struct trb * e ) { return (uint8_t )((e -> ctrl >> 16 ) & 0x1F ); }
764- static inline uint32_t trb_get_evtl (const struct trb * e ) { return (e -> sts & 0x00FFFFFFu ); }
765-
766- static void xhci_deliver_ep1in (struct xhci_hc * hc , const struct trb * ev )
798+ static void xhci_deliver_ep1in (struct xhci_hc * hc , const struct trb * e , bool deliver_to_driver )
767799{
768- if (!hc -> dev .int_cb || !hc -> dev .int_buf || !hc -> dev .int_pkt_len ) return ;
769-
770- /* Posted length was the TRB->sts TL when we queued (hc->dev.int_pkt_len).
771- Event Transfer Length (EVTL) is "bytes remaining".
772- For Normal TRB with ISP, a device short (<= posted) is success. */
773- uint32_t remaining = trb_get_evtl (ev );
774- uint32_t posted = (uint32_t )hc -> dev .int_pkt_len ;
775- uint32_t actual = (remaining <= posted ) ? (posted - remaining ) : 0u ;
776-
777- /* Some firmware/hw returns EVTL==0 even on full 8-byte report; treat 0 as "posted". */
778- if (actual == 0 && remaining == 0 ) actual = posted ;
779-
780- struct usb_dev ud = {0 };
781- ud .hc = hc ;
782- ud .slot_id = hc -> dev .slot_id ;
783-
784- /* Deliver (even if actual<8, leave filtering to upper layer) */
785- hc -> dev .int_cb (& ud , hc -> dev .int_buf , (uint16_t )actual );
786-
787- /* Re-arm EP1-IN: one Normal TRB (IOC|ISP) with same buffer, posted len again */
788- struct trb * n = ring_push (& hc -> dev .int_in_tr );
789- n -> lo = (uint32_t )(hc -> dev .int_buf_phys & 0xFFFFFFFFu );
790- n -> hi = (uint32_t )(hc -> dev .int_buf_phys >> 32 );
791- n -> sts = hc -> dev .int_pkt_len ; /* TL = posted len */
792- n -> ctrl = TRB_SET_TYPE (TRB_NORMAL ) | TRB_IOC | TRB_ISP |
793- (hc -> dev .int_in_tr .cycle ? TRB_CYCLE : 0 );
794- mmio_write32 (hc -> db + 4u * hc -> dev .slot_id , EPID_EP1_IN );
800+ /* Sanity: must be our current device and EP1 IN (EPID=3). */
801+ uint8_t slot_id = trb_get_slotid (e );
802+ uint8_t epid = trb_get_epid (e );
803+ if (slot_id != hc -> dev .slot_id || epid != EPID_EP1_IN )
804+ return ;
805+
806+ if (!hc -> dev .int_cb || !hc -> dev .int_buf || !hc -> dev .int_pkt_len )
807+ return ;
808+
809+ uint8_t cc = trb_get_cc (e );
810+ uint32_t rem = trb_get_bytes_remaining (e );
811+ uint32_t req = hc -> dev .int_pkt_len ;
812+ uint32_t xfer ;
813+
814+ /* Only deliver on Success or Short Packet. Others can be handled if needed. */
815+ if (cc == CC_SUCCESS || cc == CC_SHORT_PACKET ) {
816+ /* Actual bytes = requested - remaining; guard against weird reports. */
817+ xfer = (rem <= req ) ? (req - rem ) : req ;
818+ if (xfer == 0 ) xfer = req ; /* many boot keyboards always send 8 */
819+
820+ if (deliver_to_driver ) {
821+ struct usb_dev ud = {0 };
822+ ud .hc = hc ;
823+ ud .slot_id = hc -> dev .slot_id ;
824+
825+ /* Up-call into HID with the bytes we actually got. */
826+ hc -> dev .int_cb (& ud , hc -> dev .int_buf , (uint16_t ) xfer );
827+ }
828+
829+ /* Re-arm exactly one new Normal TRB to keep a steady queue depth. */
830+ struct trb * n = ring_push (& hc -> dev .int_in_tr );
831+ n -> lo = (uint32_t )(hc -> dev .int_buf_phys & 0xFFFFFFFFu );
832+ n -> hi = (uint32_t )(hc -> dev .int_buf_phys >> 32 );
833+ n -> sts = hc -> dev .int_pkt_len ;
834+ n -> ctrl = TRB_SET_TYPE (TRB_NORMAL ) | TRB_IOC | TRB_ISP | (hc -> dev .int_in_tr .cycle ? TRB_CYCLE : 0 );
835+
836+ /* Ring EP1 IN doorbell (per-slot doorbell, target = EPID). */
837+ mmio_write32 (hc -> db + 4u * hc -> dev .slot_id , EPID_EP1_IN );
838+ } else {
839+ /* Optional: recover on errors (stall -> stop/reset EP) */
840+ dprintf ("xhci.dbg: EP1-IN TE cc=%u rem=%u (ignored)\n" , cc , rem );
841+ }
795842}
796843
797844static void xhci_isr (uint8_t isr , uint64_t error , uint64_t irq , void * opaque )
798845{
846+ dprintf ("xhci_isr\n" );
799847 struct xhci_hc * hc = (struct xhci_hc * )opaque ;
800848 if (!hc || !hc -> cap ) return ;
801849
@@ -810,19 +858,21 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
810858 volatile uint8_t * ir0 = hc -> rt + XHCI_RT_IR0 ;
811859 uint64_t erdp_cur = mmio_read64 (ir0 + IR_ERDP ) & ~0x7ull ;
812860
861+ /* IMPORTANT: ensure EHB is CLEAR so future interrupts can retrigger */
862+ mmio_write64 (ir0 + IR_ERDP , erdp_cur ); /* bit3=0 */
863+
813864 for (uint32_t i = 0 ; i < hc -> evt .num_trbs ; i ++ ) {
814865 struct trb * e = & hc -> evt .base [i ];
815866 if ((e -> lo | e -> hi | e -> sts | e -> ctrl ) == 0u ) continue ;
816867
817868 uint8_t type = trb_get_type (e );
818- dprintf ("xhci.dbg: ISR evt[%u] type=%u lo=%08x hi=%08x sts=%08x\n" ,
819- i , type , e -> lo , e -> hi , e -> sts );
869+ //dprintf("xhci.dbg: ISR evt[%u] type=%u lo=%08x hi=%08x sts=%08x\n", i, type, e->lo, e->hi, e->sts);
820870
821871 if (type == TRB_TRANSFER_EVENT ) {
822872 uint8_t epid = trb_get_epid (e );
823873 /* Only deliver to HID for EP1-IN completions */
824874 if (epid == EPID_EP1_IN ) {
825- xhci_deliver_ep1in (hc , e );
875+ xhci_deliver_ep1in (hc , e , true );
826876 }
827877 }
828878
@@ -843,8 +893,7 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
843893}
844894
845895int xhci_arm_int_in (struct usb_dev * ud , uint16_t pkt_len , xhci_int_in_cb cb ) {
846- dprintf ("xhci.dbg: ARM INT-IN enter ud=%p hc=%p slot_id=%u pkt_len=%u cb=%p\n" ,
847- ud , ud ? ud -> hc : 0 , ud ? ud -> slot_id : 0 , (unsigned )pkt_len , cb );
896+ dprintf ("xhci.dbg: ARM INT-IN enter ud=%p hc=%p slot_id=%u pkt_len=%u cb=%p\n" , ud , ud ? ud -> hc : 0 , ud ? ud -> slot_id : 0 , (unsigned )pkt_len , cb );
848897
849898 if (!ud || !ud -> hc || !pkt_len || !cb ) {
850899 dprintf ("xhci.dbg: ARM INT-IN early-exit (arg check) ud=%p hc=%p pkt_len=%u cb=%p\n" ,
0 commit comments