@@ -76,17 +76,30 @@ static int xhci_cmd_submit_wait(struct xhci_hc *hc, struct trb *cmd_trb, uint64_
7676 uint32_t type = (e -> ctrl >> 10 ) & 0x3Fu ;
7777 uint64_t evt_ptr = ((uint64_t )e -> hi << 32 ) | e -> lo ;
7878
79- dprintf ("xhci.dbg: evt[%u] type=%u lo=%08x hi=%08x sts=%08x match=%s\n" ,
80- i , type , e -> lo , e -> hi , e -> sts , (evt_ptr == cmd_phys ? "yes" : "no" ));
81-
82- if (type == TRB_CMD_COMPLETION && evt_ptr == cmd_phys ) {
83- /* bump ERDP and consume */
84- memset (e , 0 , sizeof (* e ));
85- uint64_t erdp = mmio_read64 (ir0 + IR_ERDP );
86- erdp = (erdp & ~0x7ull ) + 16 ;
87- mmio_write64 (ir0 + IR_ERDP , erdp | (1ull << 3 ));
88- dprintf ("xhci.dbg: cmd complete, ERDP=%llx\n" , (unsigned long long )(erdp | (1ull << 3 )));
89- return 1 ;
79+ if (type == TRB_CMD_COMPLETION ) {
80+ uint32_t cc = (e -> sts >> 24 ) & 0xFFu ;
81+ dprintf ("xhci.dbg: evt[%u] type=%u lo=%08x hi=%08x sts=%08x cc=%02x match=%s\n" ,
82+ i , type , e -> lo , e -> hi , e -> sts , cc , (evt_ptr == cmd_phys ? "yes" : "no" ));
83+
84+ if (evt_ptr == cmd_phys ) {
85+ /* consume event and bump ERDP */
86+ memset (e , 0 , sizeof (* e ));
87+ uint64_t erdp = mmio_read64 (ir0 + IR_ERDP );
88+ erdp = (erdp & ~0x7ull ) + 16 ;
89+ mmio_write64 (ir0 + IR_ERDP , erdp | (1ull << 3 ));
90+ dprintf ("xhci.dbg: cmd complete, ERDP=%llx\n" ,
91+ (unsigned long long )(erdp | (1ull << 3 )));
92+
93+ /* success only if CC == 1 */
94+ if (cc != 0x01u ) {
95+ dprintf ("xhci.dbg: command failed, cc=%02x\n" , cc );
96+ return 0 ;
97+ }
98+ return 1 ;
99+ }
100+ } else {
101+ dprintf ("xhci.dbg: evt[%u] type=%u lo=%08x hi=%08x sts=%08x match=%s\n" ,
102+ i , type , e -> lo , e -> hi , e -> sts , (evt_ptr == cmd_phys ? "yes" : "no" ));
90103 }
91104 }
92105 if ((int64_t )(get_ticks () - deadline ) > 0 ) break ;
@@ -264,10 +277,41 @@ static void ctx_program_ep0(struct ep_ctx *e, uint16_t mps, uint64_t tr_deq_phys
264277 e -> dword4 = 8u ; /* avg TRB len */
265278}
266279
267- static void ctx_program_ep1_in (struct ep_ctx * e , uint16_t mps , uint64_t tr_deq_phys , uint16_t esit_payload ) {
268- e -> dword0 = ((uint32_t )mps << 16 ) | (7u << 3 ) | (3u << 1 ); /* Interrupt IN */
269- e -> deq = (tr_deq_phys | 1u );
270- e -> dword4 = ((uint32_t )esit_payload << 16 ) | (uint32_t )esit_payload ;
280+ /* ---- EP context helpers ---- */
281+ static void ctx_program_ep1_in (struct ep_ctx * e ,
282+ uint16_t mps ,
283+ uint64_t tr_deq_phys ,
284+ uint16_t esit_payload /* bytes per interval */ )
285+ {
286+ /*
287+ * Dword0:
288+ * bits 31:16 = Max Packet Size
289+ * bits 10:8 = EP Type (7 = Interrupt IN)
290+ * bits 2:1 = CErr (3)
291+ */
292+ e -> dword0 = ((uint32_t )mps << 16 ) | (7u << 3 ) | (3u << 1 );
293+
294+ /*
295+ * Dword1:
296+ * bits 15:0 = Interval (ESIT interval in microframes/frames encoding).
297+ * A small non-zero works with QEMU/typical HID; set 1 as a safe default.
298+ * (If you later parse the endpoint descriptor, use bInterval here.)
299+ */
300+ e -> dword1 = 1u ; /* Interval = 1 (minimum, valid) */
301+
302+ /*
303+ * Dword2/Dword3:
304+ * Transfer Ring Dequeue Pointer (64-bit) with DCS bit set to current ring cycle.
305+ * You already keep your transfer ring's cycle = 1 initially, so set DCS=1.
306+ */
307+ e -> deq = (tr_deq_phys | 1u ); /* DCS=1 */
308+
309+ /*
310+ * Dword4:
311+ * bits 31:16 = Average TRB Length (best-effort hint; 8 is fine for 8-byte reports)
312+ * bits 15:0 = Max ESIT Payload (max bytes per service interval)
313+ */
314+ e -> dword4 = ((uint32_t )esit_payload << 16 ) | (uint32_t )esit_payload ;
271315}
272316
273317/* ---- tiny inline control transfer used during enum (debug/verbose) ---- */
@@ -505,8 +549,8 @@ static int xhci_enumerate_first_device(struct xhci_hc *hc, struct usb_dev *out_u
505549 }
506550
507551 /* === GET_DESCRIPTOR(Device, first 8 bytes) === */
508- uint8_t __attribute__((aligned (64 ))) setup_dev8 [8 ] = { 0x80 , 0x06 , 0x00 , 0x01 , 0x00 , 0x00 , 8 , 0x00 };
509- uint8_t __attribute__((aligned (64 ))) dev_desc [256 ];
552+ uint8_t __attribute__((aligned (64 ))) setup_dev8 [8 ] = { 0x80 , 0x06 , 0x00 , 0x01 , 0x00 , 0x00 , 8 , 0x00 };
553+ uint8_t __attribute__((aligned (64 ))) dev_desc [256 ];
510554 memset (dev_desc , 0 , sizeof (dev_desc ));
511555
512556 dprintf ("HERE 1 setup8_dev=%p dev_desc=%p\n" , & setup_dev8 , & dev_desc );
@@ -603,7 +647,6 @@ static int xhci_enumerate_first_device(struct xhci_hc *hc, struct usb_dev *out_u
603647
604648static void xhci_isr (uint8_t isr , uint64_t error , uint64_t irq , void * opaque )
605649{
606- (void )isr ; (void )error ; (void )irq ;
607650 struct xhci_hc * hc = (struct xhci_hc * )opaque ;
608651 if (!hc || !hc -> cap ) return ;
609652
@@ -617,6 +660,8 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
617660 mmio_write32 (ir0 + IR_IMAN , iman & ~IR_IMAN_IP );
618661 }
619662
663+ dprintf ("xhci int\n" );
664+
620665 for (uint32_t i = 0 ; i < hc -> evt .num_trbs ; i ++ ) {
621666 struct trb * e = & hc -> evt .base [i ];
622667 if (e -> ctrl == 0 && e -> lo == 0 && e -> hi == 0 && e -> sts == 0 ) continue ;
@@ -626,6 +671,7 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
626671 i , type , e -> lo , e -> hi , e -> sts );
627672
628673 if (type == TRB_TRANSFER_EVENT ) {
674+ dprintf ("xhci transfer event\n" );
629675 if (hc -> dev .int_cb && hc -> dev .int_buf && hc -> dev .int_pkt_len ) {
630676 struct usb_dev ud = {0 };
631677 ud .hc = hc ;
@@ -650,44 +696,78 @@ static void xhci_isr(uint8_t isr, uint64_t error, uint64_t irq, void *opaque)
650696 }
651697}
652698
653- /* ---- public interrupts-in arming ---- */
654699int xhci_arm_int_in (struct usb_dev * ud , uint16_t pkt_len , xhci_int_in_cb cb ) {
655700 if (!ud || !ud -> hc || !pkt_len || !cb ) return 0 ;
656701 struct xhci_hc * hc = (struct xhci_hc * ) ud -> hc ;
657702
658703 if (!hc -> dev .int_in_tr .base ) {
659704 void * v = kmalloc_aligned (4096 , 4096 );
660705 uint64_t p = (uint64_t )(uintptr_t ) v ;
706+ if (!v ) { dprintf ("xhci.dbg: INT-IN TR alloc fail\n" ); return 0 ; }
661707 ring_init (& hc -> dev .int_in_tr , 4096 , p , v );
662708 }
663709
664710 if (!hc -> dev .int_buf ) {
665711 hc -> dev .int_buf = (uint8_t * ) kmalloc_aligned (pkt_len , 64 );
712+ if (!hc -> dev .int_buf ) { dprintf ("xhci.dbg: INT-IN buf alloc fail (%u)\n" , pkt_len ); return 0 ; }
666713 hc -> dev .int_buf_phys = (uint64_t )(uintptr_t ) hc -> dev .int_buf ;
667714 }
668715 hc -> dev .int_cb = cb ;
669716 hc -> dev .int_pkt_len = pkt_len ;
670717
671- /* Configure EP1 IN via Configure Endpoint */
672- hc -> dev .ic -> add_flags = 0x00000009u ; /* A0(slot) + A3(ep1 in) */
673- ctx_program_ep1_in ( & hc -> dev .ic -> ep1_in , 8u /* default */ , hc -> dev . int_in_tr . phys , pkt_len );
718+ /* Input Control Context */
719+ hc -> dev .ic -> drop_flags = 0 ;
720+ hc -> dev .ic -> add_flags = 0x0000000B ; /* A0(slot) | A1(ep0) | A3(ep1 IN) */
674721
722+ /* Ensure Slot Context Context Entries covers EPID=3 (slot+ep0+ep1 IN => CE >= 3) */
723+ {
724+ uint32_t s0 = hc -> dev .ic -> slot .dword0 ;
725+ uint32_t ce = (s0 >> 27 ) & 0x1F ;
726+ if (ce < 3u ) { s0 = (s0 & ~(0x1Fu << 27 )) | (3u << 27 ); hc -> dev .ic -> slot .dword0 = s0 ; }
727+ }
728+
729+ /* ICC "config triplet": config=1, interface=0, alt=0 */
730+ * (volatile uint32_t * )((uint8_t * )hc -> dev .ic + 0x08 ) = 1 ;
731+ * (volatile uint32_t * )((uint8_t * )hc -> dev .ic + 0x0C ) = 0 ;
732+ * (volatile uint32_t * )((uint8_t * )hc -> dev .ic + 0x10 ) = 0 ;
733+
734+ /* Program EP1 IN context (clear first, then set fields) */
735+ memset (& hc -> dev .ic -> ep1_in , 0 , sizeof (hc -> dev .ic -> ep1_in ));
736+ ctx_program_ep1_in (& hc -> dev .ic -> ep1_in ,
737+ 8u , /* MPS for boot kbd int IN */
738+ hc -> dev .int_in_tr .phys , /* TR Dequeue (DCS set inside) */
739+ pkt_len ); /* Max ESIT payload */
740+
741+ dprintf ("xhci.dbg: CONFIGURE_EP add_flags=%08x slot.dword0=%08x (CE=%u)\n" ,
742+ hc -> dev .ic -> add_flags ,
743+ hc -> dev .ic -> slot .dword0 ,
744+ (hc -> dev .ic -> slot .dword0 >> 27 ) & 0x1F );
745+
746+ /* Issue Configure Endpoint */
675747 struct trb * ce = xhci_cmd_begin (hc );
676748 ce -> lo = (uint32_t )(hc -> dev .ic_phys & 0xFFFFFFFFu );
677749 ce -> hi = (uint32_t )(hc -> dev .ic_phys >> 32 );
678750 ce -> ctrl |= TRB_SET_TYPE (TRB_CONFIGURE_EP ) | ((uint32_t )ud -> slot_id << 24 );
751+ dprintf ("xhci.dbg: ring_push for CONFIGURE_EP trb=%08x ic_phys=%08x\n" ,
752+ (uint32_t )(uintptr_t )ce , (uint32_t )(hc -> dev .ic_phys & 0xFFFFFFFFu ));
753+
679754 if (!xhci_cmd_submit_wait (hc , ce , NULL )) {
755+ dprintf ("xhci.dbg: CONFIGURE_EP timeout/fail\n" );
680756 return 0 ;
681757 }
682758
683- /* Post first Normal TRB; ISR will keep re-arming */
759+ /* Post first INT-IN Normal TRB and doorbell EP1 IN */
684760 struct trb * n = ring_push (& hc -> dev .int_in_tr );
685761 n -> lo = (uint32_t )(hc -> dev .int_buf_phys & 0xFFFFFFFFu );
686762 n -> hi = (uint32_t )(hc -> dev .int_buf_phys >> 32 );
687763 n -> sts = hc -> dev .int_pkt_len ;
688- n -> ctrl = TRB_SET_TYPE (TRB_NORMAL ) | TRB_IOC | (hc -> dev .int_in_tr .cycle ? TRB_CYCLE : 0 );
764+ n -> ctrl = TRB_SET_TYPE (TRB_NORMAL ) | TRB_IOC |
765+ (hc -> dev .int_in_tr .cycle ? TRB_CYCLE : 0 );
766+ dprintf ("xhci.dbg: INT-IN normal TRB @%08x lo=%08x hi=%08x len=%u\n" ,
767+ (uint32_t )(uintptr_t )n , n -> lo , n -> hi , n -> sts );
689768
690769 mmio_write32 (hc -> db + 4u * ud -> slot_id , EPID_EP1_IN );
770+ dprintf ("xhci.dbg: doorbell EP1 IN (slot=%u)\n" , ud -> slot_id );
691771 return 1 ;
692772}
693773
@@ -725,12 +805,12 @@ int xhci_probe_and_init(uint8_t bus, uint8_t dev, uint8_t func) {
725805 struct usb_dev ud ;
726806 if (!xhci_enumerate_first_device (g_xhci , & ud )) {
727807 dprintf ("xhci: controller up, 0 devices present\n" );
728- kprintf ("USB xHCI: controller ready (interrupts on), published 0 devices\n" );
808+ dprintf ("USB xHCI: controller ready (interrupts on), published 0 devices\n" );
729809 return 1 ; /* host is fine; no device yet */
730810 }
731811
732812 usb_core_device_added (& ud );
733- kprintf ("USB xHCI: controller ready (interrupts on), published 1 device\n" );
813+ dprintf ("USB xHCI: controller ready (interrupts on), published 1 device\n" );
734814 return 1 ;
735815}
736816
0 commit comments