1#![allow(dead_code)]
13
14use crate::{
15 hardware::pci_client::{self as pci, Bar, ProbeCriteria},
16 memory::{allocate_zeroed_frame, paging, phys_to_virt},
17};
18use alloc::{sync::Arc, vec::Vec};
19use core::{
20 ptr::{read_volatile, write_volatile},
21 sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering},
22};
23use spin::Mutex;
24
25const XHCI_MMIO_SIZE: usize = 0x10000;
26const XHCI_PORT_REG_BASE: usize = 0x400;
27const XHCI_PORT_REG_STRIDE: usize = 0x10;
28const XHCI_RING_TRBS: usize = 64;
29const MAX_ENDPOINTS: usize = 31;
30
31const USBCMD_RUN_STOP: u32 = 1 << 0;
32const USBCMD_HCRST: u32 = 1 << 1;
33const USBCMD_INTE: u32 = 1 << 2;
34
35const USBSTS_HCH: u32 = 1 << 0;
36const USBSTS_CNR: u32 = 1 << 11;
37
38const PORTSC_CCS: u32 = 1 << 0;
39const PORTSC_PED: u32 = 1 << 1;
40const PORTSC_PR: u32 = 1 << 4;
41const PORTSC_PP: u32 = 1 << 9;
42const PORTSC_SPEED_SHIFT: u32 = 10;
43const PORTSC_W1C_MASK: u32 = 0xFE0000;
44
45const TRB_TYPE_NORMAL: u32 = 1;
46const TRB_TYPE_SETUP_STAGE: u32 = 2;
47const TRB_TYPE_DATA_STAGE: u32 = 3;
48const TRB_TYPE_STATUS_STAGE: u32 = 4;
49const TRB_TYPE_ENABLE_SLOT: u32 = 9;
50const TRB_TYPE_ADDRESS_DEVICE: u32 = 11;
51const TRB_TYPE_CONFIGURE_ENDPOINT: u32 = 12;
52const TRB_TYPE_TRANSFER_EVENT: u32 = 32;
53const TRB_TYPE_LINK: u32 = 6;
54
55const TRB_CYCLE: u32 = 1 << 0;
56const TRB_IOC: u32 = 1 << 5;
57const TRB_DIR_IN: u32 = 1 << 16;
58const TRB_DIR_OUT: u32 = 0;
59const TRB_TC: u32 = 1 << 1;
60
61const TRB_TYPE_SHIFT: u32 = 10;
62const TRB_IDT: u32 = 1 << 6;
63const TRB_TD_SIZE_SHIFT: u32 = 17;
64const TRB_TD_SIZE_MASK: u32 = 0x1F;
65
66const EP_TYPE_CONTROL: u32 = 4;
67const EP_TYPE_INTR_IN: u32 = 7;
68
69const fn trb_get_type(d3: u32) -> u32 {
70 (d3 >> TRB_TYPE_SHIFT) & 0xFF
71}
72
73#[repr(C)]
74struct CapRegisters {
75 caplength: u8,
76 _reserved: u8,
77 _hciversion: u16,
78 hcsparams1: u32,
79 _hcsparams2: u32,
80 _hcsparams3: u32,
81 _hccparams1: u32,
82 dboff: u32,
83 rtsoff: u32,
84 _hccparams2: u32,
85}
86
87#[repr(C)]
88struct OpRegisters {
89 usbcmd: u32,
90 usbsts: u32,
91 _pagesize: u32,
92 _reserved0: [u32; 2],
93 _dnctrl: u32,
94 crcr: u64,
95 _reserved1: [u32; 4],
96 dcbaap: u64,
97 config: u32,
98}
99
100#[repr(C)]
101struct RuntimeRegisters {
102 _mfindex: u32,
103 _reserved: [u32; 7],
104 ir: [InterrupterRegisters; 1],
105}
106
107#[repr(C)]
108struct InterrupterRegisters {
109 iman: u32,
110 _imod: u32,
111 erstsz: u32,
112 _reserved: u32,
113 erstba: u64,
114 erdp: u64,
115}
116
117#[repr(C)]
118#[derive(Clone, Copy)]
119struct Trb {
120 d0: u32,
121 d1: u32,
122 d2: u32,
123 d3: u32,
124}
125
126impl Trb {
127 fn link(addr: u64, toggle_cycle: bool) -> Self {
128 Self {
129 d0: (addr & 0xFFFFFFFF) as u32,
130 d1: ((addr >> 32) & 0xFFFFFFFF) as u32,
131 d2: 0,
132 d3: ((TRB_TYPE_LINK << TRB_TYPE_SHIFT) as u32)
133 | TRB_CYCLE
134 | (if toggle_cycle { TRB_TC } else { 0 }),
135 }
136 }
137
138 fn normal(addr: u64, len: u32, cycle: bool, ioc: bool) -> Self {
139 let mut d3 = (TRB_TYPE_NORMAL << TRB_TYPE_SHIFT) as u32 | if cycle { TRB_CYCLE } else { 0 };
140 if ioc {
141 d3 |= TRB_IOC;
142 }
143 Self {
144 d0: (addr & 0xFFFFFFFF) as u32,
145 d1: ((addr >> 32) & 0xFFFFFFFF) as u32,
146 d2: len,
147 d3,
148 }
149 }
150
151 fn setup_stage(addr: u64, cycle: bool) -> Self {
152 let mut d3 =
153 (TRB_TYPE_SETUP_STAGE << TRB_TYPE_SHIFT) as u32 | if cycle { TRB_CYCLE } else { 0 };
154 d3 |= TRB_IDT;
155 Self {
156 d0: (addr & 0xFFFFFFFF) as u32,
157 d1: ((addr >> 32) & 0xFFFFFFFF) as u32,
158 d2: 8,
159 d3,
160 }
161 }
162
163 fn data_stage(addr: u64, len: u32, dir_in: bool, cycle: bool, ioc: bool) -> Self {
164 let mut d3 =
165 (TRB_TYPE_DATA_STAGE << TRB_TYPE_SHIFT) as u32 | if cycle { TRB_CYCLE } else { 0 };
166 if dir_in {
167 d3 |= TRB_DIR_IN;
168 }
169 if ioc {
170 d3 |= TRB_IOC;
171 }
172 let td_size = ((len + TRB_TD_SIZE_MASK) / (TRB_TD_SIZE_MASK + 1)) & TRB_TD_SIZE_MASK;
173 let d2 = (td_size << TRB_TD_SIZE_SHIFT) | len;
174 Self {
175 d0: (addr & 0xFFFFFFFF) as u32,
176 d1: ((addr >> 32) & 0xFFFFFFFF) as u32,
177 d2,
178 d3,
179 }
180 }
181
182 fn status_stage(cycle: bool, dir_in: bool) -> Self {
183 let mut d3 =
184 (TRB_TYPE_STATUS_STAGE << TRB_TYPE_SHIFT) as u32 | if cycle { TRB_CYCLE } else { 0 };
185 if dir_in {
186 d3 |= TRB_DIR_IN;
187 }
188 d3 |= TRB_IOC;
189 Self {
190 d0: 0,
191 d1: 0,
192 d2: 0,
193 d3,
194 }
195 }
196}
197
198#[repr(C, packed)]
199struct SlotContext {
200 d0: u32,
201 d1: u32,
202 d2: u32,
203 d3: u32,
204 d4: u32,
205 d5: u32,
206 d6: u32,
207 d7: u32,
208}
209
210#[repr(C, packed)]
211struct EndpointContext {
212 d0: u32,
213 d1: u32,
214 d2: u32,
215 d3: u32,
216 d4: u32,
217 d5: u32,
218 d6: u32,
219 d7: u32,
220}
221
222#[repr(C, packed)]
223struct InputControlContext {
224 d0: u32,
225 d1: u32,
226 d2: [u32; 30],
227}
228
229#[repr(C, packed)]
230struct InputContext {
231 ctrl: InputControlContext,
232 slot: SlotContext,
233 eps: [EndpointContext; 31],
234}
235
236struct XhciPort {
237 port_num: usize,
238 enabled: bool,
239 connected: bool,
240 speed: u8,
241}
242
243struct DeviceSlot {
244 slot_id: u8,
245 usb_address: u8,
246 input_ctx: *mut InputContext,
247 input_ctx_phys: u64,
248 ep_transfer_rings: [*mut Trb; MAX_ENDPOINTS],
249 ep_transfer_ring_phys: [u64; MAX_ENDPOINTS],
250 ep_dequeue: [usize; MAX_ENDPOINTS],
251 ep_cycle: [bool; MAX_ENDPOINTS],
252 configured: bool,
253 ep_buf: [*mut u8; MAX_ENDPOINTS],
254 ep_buf_phys: [u64; MAX_ENDPOINTS],
255 ep_buf_len: [usize; MAX_ENDPOINTS],
256 ep_active: [bool; MAX_ENDPOINTS],
257}
258
259unsafe impl Send for DeviceSlot {}
260unsafe impl Sync for DeviceSlot {}
261
262impl DeviceSlot {
263 fn new(slot_id: u8) -> Self {
264 Self {
265 slot_id,
266 usb_address: 0,
267 input_ctx: core::ptr::null_mut(),
268 input_ctx_phys: 0,
269 ep_transfer_rings: [core::ptr::null_mut(); MAX_ENDPOINTS],
270 ep_transfer_ring_phys: [0; MAX_ENDPOINTS],
271 ep_dequeue: [0; MAX_ENDPOINTS],
272 ep_cycle: [true; MAX_ENDPOINTS],
273 configured: false,
274 ep_buf: [core::ptr::null_mut(); MAX_ENDPOINTS],
275 ep_buf_phys: [0; MAX_ENDPOINTS],
276 ep_buf_len: [0; MAX_ENDPOINTS],
277 ep_active: [false; MAX_ENDPOINTS],
278 }
279 }
280}
281
282pub struct XhciController {
283 mmio_base: usize,
284 cap_regs: *const CapRegisters,
285 op_regs: *mut OpRegisters,
286 rt_regs: *mut RuntimeRegisters,
287 db_regs: *mut u32,
288 caplength: u8,
289 max_ports: usize,
290 ports: Vec<XhciPort>,
291 device_ctx: *mut u8,
292 device_ctx_phys: u64,
293 cmd_ring: *mut Trb,
294 cmd_ring_phys: u64,
295 cmd_ring_deq: usize,
296 cmd_ring_cycle: bool,
297 event_ring: *mut Trb,
298 event_ring_phys: u64,
299 event_ring_deq: AtomicUsize,
300 event_ring_cycle: AtomicBool,
301 slot_id: AtomicU8,
302 ctrl_transfer_buf: *mut u8,
303 ctrl_transfer_buf_phys: u64,
304 device_slots: Vec<Option<DeviceSlot>>,
305}
306
307unsafe impl Send for XhciController {}
308unsafe impl Sync for XhciController {}
309
310impl XhciController {
311 pub unsafe fn new(pci_dev: pci::PciDevice) -> Result<Self, &'static str> {
312 let bar = match pci_dev.read_bar(0) {
313 Some(Bar::Memory64 { addr, .. }) => addr,
314 Some(Bar::Memory32 { addr, .. }) => addr as u64,
315 _ => {
316 unsafe {
317 core::arch::asm!("out 0xe9, al", in("al") b'z', options(nomem, nostack));
319 core::arch::asm!("out 0xe9, al", in("al") b'B', options(nomem, nostack));
320 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
321 }
322 return Err("Invalid BAR");
323 }
324 };
325 unsafe {
326 core::arch::asm!("out 0xe9, al", in("al") b'z', options(nomem, nostack));
327 core::arch::asm!("out 0xe9, al", in("al") b'b', options(nomem, nostack));
328 let hex = b"0123456789abcdef";
329 let a = bar;
330 for sh in [28usize, 24, 20, 16, 12, 8, 4, 0] {
331 let nib = hex[((a >> sh) & 0xF) as usize];
332 core::arch::asm!("out 0xe9, al", in("al") nib, options(nomem, nostack));
333 }
334 let bdf = pci_dev.address;
336 core::arch::asm!("out 0xe9, al", in("al") b'@', options(nomem, nostack));
337 let raw = pci_dev.read_bar_raw(0).unwrap_or(0xFFFF_FFFF);
338 for sh in [28usize, 24, 20, 16, 12, 8, 4, 0] {
339 let nib = hex[((raw >> sh) & 0xF) as usize];
340 core::arch::asm!("out 0xe9, al", in("al") nib, options(nomem, nostack));
341 }
342 let _ = bdf;
343 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
344 }
345 paging::ensure_identity_map_range(bar, XHCI_MMIO_SIZE as u64);
346
347 let mmio_base = phys_to_virt(bar) as usize;
348 let cap_regs = mmio_base as *const CapRegisters;
349 let caplength = (*cap_regs).caplength;
350 let op_regs = (mmio_base + caplength as usize) as *mut OpRegisters;
351
352 let dboff = (*cap_regs).dboff;
353 let db_regs = (mmio_base + dboff as usize) as *mut u32;
354
355 let rtsoff = (*cap_regs).rtsoff;
356 let rt_regs = (mmio_base + rtsoff as usize) as *mut RuntimeRegisters;
357
358 let max_ports = (((*cap_regs).hcsparams1 >> 24) & 0xFF) as usize;
359
360 let mut controller = Self {
361 mmio_base,
362 cap_regs,
363 op_regs,
364 rt_regs,
365 db_regs,
366 caplength,
367 max_ports,
368 ports: Vec::new(),
369 device_ctx: core::ptr::null_mut(),
370 device_ctx_phys: 0,
371 cmd_ring: core::ptr::null_mut(),
372 cmd_ring_phys: 0,
373 cmd_ring_deq: 0,
374 cmd_ring_cycle: true,
375 event_ring: core::ptr::null_mut(),
376 event_ring_phys: 0,
377 event_ring_deq: AtomicUsize::new(0),
378 event_ring_cycle: AtomicBool::new(true),
379 slot_id: AtomicU8::new(0),
380 ctrl_transfer_buf: core::ptr::null_mut(),
381 ctrl_transfer_buf_phys: 0,
382 device_slots: Vec::new(),
383 };
384
385 controller.init()?;
386 Ok(controller)
387 }
388
389 fn init(&mut self) -> Result<(), &'static str> {
390 unsafe {
391 for _ in 0..100_000 {
392 if self.read_usbsts() & USBSTS_CNR == 0 {
393 break;
394 }
395 core::hint::spin_loop();
396 }
397 if self.read_usbsts() & USBSTS_CNR != 0 {
398 return Err("xHCI: controller not ready (CNR)");
399 }
400
401 let mut usbcmd = self.read_usbcmd();
402 usbcmd &= !USBCMD_RUN_STOP;
403 self.write_usbcmd(usbcmd);
404 for _ in 0..100_000 {
405 if self.read_usbsts() & USBSTS_HCH != 0 {
406 break;
407 }
408 core::hint::spin_loop();
409 }
410 if self.read_usbsts() & USBSTS_HCH == 0 {
411 return Err("xHCI: controller did not halt");
412 }
413
414 self.write_usbcmd(self.read_usbcmd() | USBCMD_HCRST);
415 for _ in 0..100_000 {
416 if self.read_usbcmd() & USBCMD_HCRST == 0 {
417 break;
418 }
419 core::hint::spin_loop();
420 }
421 if self.read_usbcmd() & USBCMD_HCRST != 0 {
422 return Err("xHCI: controller reset timed out");
423 }
424 let mut cnr_timeout = 1_000_000u32;
425 while self.read_usbsts() & USBSTS_CNR != 0 {
426 if cnr_timeout == 0 {
427 return Err("xHCI: CNR did not clear after reset");
428 }
429 cnr_timeout -= 1;
430 core::hint::spin_loop();
431 }
432
433 for i in 0..self.max_ports {
434 let portsc = self.read_portsc(i);
435 self.ports.push(XhciPort {
436 port_num: i,
437 enabled: (portsc & PORTSC_PED) != 0,
438 connected: (portsc & PORTSC_CCS) != 0,
439 speed: ((portsc >> PORTSC_SPEED_SHIFT) & 0xF) as u8,
440 });
441 }
442
443 self.init_rings()?;
444 self.init_interrupter()?;
445 self.init_ctrl_transfer_buf()?;
446
447 let max_slots = self.max_device_slots();
448 self.write_config(max_slots);
449 self.write_usbcmd(self.read_usbcmd() | USBCMD_RUN_STOP | USBCMD_INTE);
450
451 self.enumerate_all_ports();
452 }
453 Ok(())
454 }
455
456 unsafe fn init_rings(&mut self) -> Result<(), &'static str> {
457 let cmd_frame = allocate_zeroed_frame().ok_or("Failed to allocate cmd ring")?;
458 self.cmd_ring_phys = cmd_frame.start_address.as_u64();
459 self.cmd_ring = phys_to_virt(self.cmd_ring_phys) as *mut Trb;
460 core::ptr::write_bytes(self.cmd_ring as *mut u8, 0, 4096);
461 core::ptr::write(
462 self.cmd_ring.add(XHCI_RING_TRBS - 1),
463 Trb::link(self.cmd_ring_phys, true),
464 );
465 self.write_crcr(self.cmd_ring_phys | 1);
466
467 let event_frame = allocate_zeroed_frame().ok_or("Failed to allocate event ring")?;
468 self.event_ring_phys = event_frame.start_address.as_u64();
469 self.event_ring = phys_to_virt(self.event_ring_phys) as *mut Trb;
470 core::ptr::write_bytes(self.event_ring as *mut u8, 0, 4096);
471
472 let dev_frame = allocate_zeroed_frame().ok_or("Failed to allocate DCBAA")?;
473 self.device_ctx_phys = dev_frame.start_address.as_u64();
474 self.device_ctx = phys_to_virt(self.device_ctx_phys) as *mut u8;
475 core::ptr::write_bytes(self.device_ctx, 0, 4096);
476 self.write_dcbaap(self.device_ctx_phys);
477
478 Ok(())
479 }
480
481 unsafe fn init_interrupter(&mut self) -> Result<(), &'static str> {
482 let erst_frame = allocate_zeroed_frame().ok_or("Failed to allocate ERST")?;
483 let erst_phys = erst_frame.start_address.as_u64();
484 let erst_virt = phys_to_virt(erst_phys) as *mut u64;
485 core::ptr::write_bytes(erst_virt as *mut u8, 0, 4096);
486
487 let erst_entry = erst_virt as *mut u8;
488 let addr_bytes = self.event_ring_phys.to_le_bytes();
489 core::ptr::copy_nonoverlapping(addr_bytes.as_ptr(), erst_entry, 8);
490 let seg_size: u32 = XHCI_RING_TRBS as u32;
491 let size_bytes = seg_size.to_le_bytes();
492 core::ptr::copy_nonoverlapping(size_bytes.as_ptr(), erst_entry.add(8), 4);
493
494 let ir = &mut (*self.rt_regs).ir[0];
495 write_volatile(core::ptr::addr_of_mut!(ir.erstsz), 1);
496 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
497 write_volatile(core::ptr::addr_of_mut!(ir.erstba), erst_phys);
498 write_volatile(core::ptr::addr_of_mut!(ir.erdp), self.event_ring_phys);
499 write_volatile(core::ptr::addr_of_mut!(ir.iman), 3);
500
501 Ok(())
502 }
503
504 unsafe fn init_ctrl_transfer_buf(&mut self) -> Result<(), &'static str> {
505 let buf_frame = allocate_zeroed_frame().ok_or("Failed to allocate ctrl buf")?;
506 self.ctrl_transfer_buf_phys = buf_frame.start_address.as_u64();
507 self.ctrl_transfer_buf = phys_to_virt(self.ctrl_transfer_buf_phys) as *mut u8;
508 core::ptr::write_bytes(self.ctrl_transfer_buf, 0, 4096);
509 Ok(())
510 }
511
512 unsafe fn read_portsc(&self, port: usize) -> u32 {
513 let port_offset = XHCI_PORT_REG_BASE + (port * XHCI_PORT_REG_STRIDE);
514 let portsc_ptr = (self.op_regs as *const u8).add(port_offset) as *const u32;
515 portsc_ptr.read_volatile()
516 }
517
518 unsafe fn write_portsc(&self, port: usize, val: u32) {
519 let port_offset = XHCI_PORT_REG_BASE + (port * XHCI_PORT_REG_STRIDE);
520 let portsc_ptr = (self.op_regs as *const u8).add(port_offset) as *mut u32;
521 portsc_ptr.write_volatile(val);
522 }
523
524 unsafe fn read_usbcmd(&self) -> u32 {
525 read_volatile(core::ptr::addr_of!((*self.op_regs).usbcmd))
526 }
527
528 unsafe fn write_usbcmd(&self, value: u32) {
529 write_volatile(core::ptr::addr_of_mut!((*self.op_regs).usbcmd), value);
530 }
531
532 unsafe fn read_usbsts(&self) -> u32 {
533 read_volatile(core::ptr::addr_of!((*self.op_regs).usbsts))
534 }
535
536 unsafe fn write_crcr(&self, value: u64) {
537 write_volatile(core::ptr::addr_of_mut!((*self.op_regs).crcr), value);
538 }
539
540 unsafe fn write_dcbaap(&self, value: u64) {
541 write_volatile(core::ptr::addr_of_mut!((*self.op_regs).dcbaap), value);
542 }
543
544 unsafe fn write_config(&self, value: u32) {
545 write_volatile(core::ptr::addr_of_mut!((*self.op_regs).config), value);
546 }
547
548 fn max_device_slots(&self) -> u32 {
549 unsafe { read_volatile(core::ptr::addr_of!((*self.cap_regs).hcsparams1)) & 0xFF }
550 }
551
552 fn max_ports_from_hw(&self) -> u32 {
553 unsafe { (read_volatile(core::ptr::addr_of!((*self.cap_regs).hcsparams1)) >> 24) & 0xFF }
554 }
555
556 unsafe fn cmd_ring_enqueue(&mut self, trb: Trb) {
557 let idx = self.cmd_ring_deq;
558 let mut trb = trb;
559 if self.cmd_ring_cycle {
560 trb.d3 |= TRB_CYCLE;
561 } else {
562 trb.d3 &= !TRB_CYCLE;
563 }
564 core::ptr::write_volatile(self.cmd_ring.add(idx), trb);
565 self.cmd_ring_deq = idx + 1;
566
567 if self.cmd_ring_deq >= 63 {
568 let link = Trb::link(self.cmd_ring_phys, true);
569 let mut link_trb = link;
570 if self.cmd_ring_cycle {
571 link_trb.d3 |= TRB_CYCLE;
572 } else {
573 link_trb.d3 &= !TRB_CYCLE;
574 }
575 core::ptr::write_volatile(self.cmd_ring.add(63), link_trb);
576 self.cmd_ring_deq = 0;
577 self.cmd_ring_cycle = !self.cmd_ring_cycle;
578 }
579
580 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
581 core::ptr::write_volatile(self.db_regs.add(0), 0);
582 }
583
584 unsafe fn wait_for_event(&mut self) -> Result<Trb, &'static str> {
585 for _ in 0..1000000 {
586 let idx = self.event_ring_deq.load(Ordering::Acquire);
587 let trb = core::ptr::read_volatile(self.event_ring.add(idx));
588
589 let expected_c = if self.event_ring_cycle.load(Ordering::Acquire) {
590 TRB_CYCLE
591 } else {
592 0
593 };
594 if (trb.d3 & TRB_CYCLE) == expected_c {
595 let new_deq = (idx + 1) % 64;
596 self.event_ring_deq.store(new_deq, Ordering::Release);
597 if new_deq == 0 {
598 self.event_ring_cycle.store(
599 !self.event_ring_cycle.load(Ordering::Acquire),
600 Ordering::Release,
601 );
602 }
603 let ir = &mut (*self.rt_regs).ir[0];
604 ir.erdp = (self.event_ring_phys + (new_deq as u64) * 16) | (1 << 3);
605 return Ok(trb);
606 }
607 core::hint::spin_loop();
608 }
609 Err("Event timeout")
610 }
611
612 unsafe fn ring_doorbell(&self, slot_id: u8, endpoint: u8) {
613 let db_index = (slot_id as usize) * 32 + (endpoint as usize);
614 core::ptr::write_volatile(self.db_regs.add(db_index), 0);
615 }
616
617 unsafe fn alloc_input_context(&mut self, slot_id: u8) -> Result<(), &'static str> {
618 let frame = allocate_zeroed_frame().ok_or("Failed to allocate input context")?;
619 let phys = frame.start_address.as_u64();
620 let virt = phys_to_virt(phys) as *mut InputContext;
621
622 let idx = slot_id as usize;
623 if idx >= self.device_slots.len() {
624 self.device_slots.resize_with(idx + 1, || None);
625 }
626 let dev = self.device_slots[idx].as_mut().unwrap();
627 dev.input_ctx = virt;
628 dev.input_ctx_phys = phys;
629
630 let dcbaa = self.device_ctx as *mut u64;
631 dcbaa.add(idx as usize).write_volatile(phys);
632
633 Ok(())
634 }
635
636 unsafe fn alloc_transfer_ring(
637 &mut self,
638 slot_id: u8,
639 endpoint: u8,
640 ) -> Result<(), &'static str> {
641 let frame = allocate_zeroed_frame().ok_or("Failed to allocate transfer ring")?;
642 let phys = frame.start_address.as_u64();
643 let virt = phys_to_virt(phys) as *mut Trb;
644
645 core::ptr::write_bytes(virt as *mut u8, 0, 4096);
646 core::ptr::write(virt.add(XHCI_RING_TRBS - 1), Trb::link(phys, true));
647
648 let idx = slot_id as usize;
649 if idx < self.device_slots.len() {
650 if let Some(ref mut dev) = self.device_slots[idx] {
651 let ep = endpoint as usize;
652 if ep < MAX_ENDPOINTS {
653 dev.ep_transfer_rings[ep] = virt;
654 dev.ep_transfer_ring_phys[ep] = phys;
655 dev.ep_dequeue[ep] = 0;
656 dev.ep_cycle[ep] = true;
657 }
658 }
659 }
660 Ok(())
661 }
662
663 unsafe fn write_endpoint_context(
664 &self,
665 slot_id: u8,
666 endpoint: u8,
667 tr_phys: u64,
668 max_packet: u32,
669 ep_type: u32,
670 interval: u32,
671 ) {
672 let dcbaa = self.device_ctx as *mut u64;
673 let ctx_addr = dcbaa.add(slot_id as usize).read_volatile() as *mut u8;
674 if ctx_addr.is_null() {
675 return;
676 }
677
678 let ep_offset = 32 * ((endpoint - 1) as usize) + 32;
679 let ep_ctx = ctx_addr.add(ep_offset) as *mut EndpointContext;
680
681 let d0 = (ep_type & 0x7) << 3 | 0;
682 let d1 = (max_packet & 0x7FF) | (0 << 16);
683 let d2 = (tr_phys & 0xFFFFFFFF) as u32;
684 let d3 = ((tr_phys >> 32) & 0xFFFFFFFF) as u32;
685 let d4 = interval & 0xFF;
686
687 (*ep_ctx).d0 = d0;
688 (*ep_ctx).d1 = d1;
689 (*ep_ctx).d2 = d2;
690 (*ep_ctx).d3 = d3;
691 (*ep_ctx).d4 = d4;
692 (*ep_ctx).d5 = 0;
693 (*ep_ctx).d6 = 0;
694 (*ep_ctx).d7 = 0;
695 }
696
697 unsafe fn reset_port(&self, port: usize) -> bool {
698 let mut portsc = self.read_portsc(port);
699 if portsc & PORTSC_CCS == 0 {
700 return false;
701 }
702
703 portsc = self.read_portsc(port);
704 self.write_portsc(port, portsc | PORTSC_PR);
705
706 for _ in 0..500_000 {
707 portsc = self.read_portsc(port);
708 if portsc & PORTSC_PR == 0 {
709 break;
710 }
711 core::hint::spin_loop();
712 }
713
714 for _ in 0..500_000 {
715 portsc = self.read_portsc(port);
716 if portsc & PORTSC_PED != 0 {
717 return true;
718 }
719 if portsc & PORTSC_CCS == 0 {
720 return false;
721 }
722 core::hint::spin_loop();
723 }
724
725 self.read_portsc(port) & PORTSC_PED != 0
726 }
727
728 fn enable_slot(&mut self) -> Result<u8, &'static str> {
729 unsafe {
730 self.cmd_ring_enqueue(Trb {
731 d0: 0,
732 d1: 0,
733 d2: 0,
734 d3: (TRB_TYPE_ENABLE_SLOT << TRB_TYPE_SHIFT) as u32,
735 });
736
737 let event = self.wait_for_event()?;
738 let completion_code = (event.d2 >> 24) & 0xFF;
739 if completion_code != 1 {
740 log::warn!("[xHCI] Enable Slot failed: completion={}", completion_code);
741 return Err("Enable slot failed");
742 }
743 let slot_id = ((event.d3 >> 24) & 0xFF) as u8;
744 if slot_id == 0 {
745 return Err("No slot available");
746 }
747 self.slot_id.store(slot_id, Ordering::SeqCst);
748
749 let idx = slot_id as usize;
750 if idx >= self.device_slots.len() {
751 self.device_slots.resize_with(idx + 1, || None);
752 }
753 self.device_slots[idx] = Some(DeviceSlot::new(slot_id));
754
755 self.alloc_input_context(slot_id)?;
756 self.alloc_transfer_ring(slot_id, 1)?;
757
758 let slot_ctx = &mut (*self.device_slots[idx].as_ref().unwrap().input_ctx).slot;
759 slot_ctx.d0 = (1 << 27) | (slot_id as u32);
760 slot_ctx.d1 = 0;
761 slot_ctx.d2 = 0;
762
763 self.write_endpoint_context(
764 slot_id,
765 1,
766 self.device_slots[idx]
767 .as_ref()
768 .unwrap()
769 .ep_transfer_ring_phys[1],
770 8,
771 EP_TYPE_CONTROL,
772 0,
773 );
774
775 log::info!("[xHCI] Enable Slot: slot_id={}", slot_id);
776 Ok(slot_id)
777 }
778 }
779
780 fn set_address(&mut self, slot_id: u8, address: u8) -> Result<(), &'static str> {
781 unsafe {
782 let idx = slot_id as usize;
783 if idx >= self.device_slots.len() || self.device_slots[idx].is_none() {
784 return Err("Invalid slot for Address Device");
785 }
786
787 let input_ctx_phys = self.device_slots[idx].as_ref().unwrap().input_ctx_phys;
788
789 let slot_ctx = &mut (*self.device_slots[idx].as_ref().unwrap().input_ctx).slot;
790 slot_ctx.d0 = (1 << 27) | (address as u32);
791 slot_ctx.d1 = 0;
792 slot_ctx.d2 = 0;
793
794 self.cmd_ring_enqueue(Trb {
795 d0: (input_ctx_phys & 0xFFFFFFFF) as u32,
796 d1: ((input_ctx_phys >> 32) & 0xFFFFFFFF) as u32,
797 d2: (slot_id as u32) << 24,
798 d3: (TRB_TYPE_ADDRESS_DEVICE << TRB_TYPE_SHIFT) as u32,
799 });
800
801 let event = self.wait_for_event()?;
802 let completion = (event.d2 >> 24) & 0xFF;
803 if completion != 1 {
804 unsafe {
805 core::arch::asm!("out 0xe9, al", in("al") b'z', options(nomem, nostack));
806 core::arch::asm!("out 0xe9, al", in("al") b'3', options(nomem, nostack));
807 core::arch::asm!("out 0xe9, al", in("al") (b'0' + (completion & 0xF) as u8), options(nomem, nostack));
808 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
809 }
810 log::warn!(
811 "[xHCI] Address Device failed: slot={} completion={}",
812 slot_id,
813 completion
814 );
815 return Err("Set address failed");
816 }
817
818 self.device_slots[idx].as_mut().unwrap().usb_address = address;
819 log::info!("[xHCI] Address Device: slot={} addr={}", slot_id, address);
820 }
821 Ok(())
822 }
823
824 pub fn setup_endpoint(
825 &mut self,
826 slot_id: u8,
827 endpoint: u8,
828 max_packet: u32,
829 ep_type: u32,
830 interval: u32,
831 _max_burst: u32,
832 ) -> Result<(), &'static str> {
833 unsafe {
834 let idx = slot_id as usize;
835 if idx >= self.device_slots.len() || self.device_slots[idx].is_none() {
836 return Err("Invalid slot for Setup Endpoint");
837 }
838
839 self.alloc_transfer_ring(slot_id, endpoint)?;
840
841 self.write_endpoint_context(
842 slot_id,
843 endpoint,
844 self.device_slots[idx]
845 .as_ref()
846 .unwrap()
847 .ep_transfer_ring_phys[endpoint as usize],
848 max_packet,
849 ep_type,
850 interval,
851 );
852
853 let input_ctx_phys = self.device_slots[idx].as_ref().unwrap().input_ctx_phys;
854
855 self.cmd_ring_enqueue(Trb {
856 d0: (input_ctx_phys & 0xFFFFFFFF) as u32,
857 d1: ((input_ctx_phys >> 32) & 0xFFFFFFFF) as u32,
858 d2: (slot_id as u32) << 24,
859 d3: (TRB_TYPE_CONFIGURE_ENDPOINT << TRB_TYPE_SHIFT) as u32,
860 });
861
862 let event = self.wait_for_event()?;
863 let completion = (event.d2 >> 24) & 0xFF;
864 if completion != 1 {
865 log::warn!(
866 "[xHCI] Configure Endpoint failed: slot={} ep={} completion={}",
867 slot_id,
868 endpoint,
869 completion
870 );
871 return Err("Configure endpoint failed");
872 }
873
874 log::info!(
875 "[xHCI] Endpoint configured: slot={} ep={} type={}",
876 slot_id,
877 endpoint,
878 ep_type
879 );
880 }
881 Ok(())
882 }
883
884 fn enumerate_all_ports(&mut self) {
885 unsafe {
886 core::arch::asm!("out 0xe9, al", in("al") b'x', options(nomem, nostack));
887 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[((self.max_ports >> 4) & 0xF) as usize], options(nomem, nostack));
888 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[(self.max_ports & 0xF) as usize], options(nomem, nostack));
889 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
890 }
891 let mut usb_address: u8 = 1;
892
893 for port in 0..self.max_ports {
894 let portsc = unsafe { self.read_portsc(port) };
895 let connected = (portsc & PORTSC_CCS) != 0;
896 if !connected {
897 continue;
898 }
899 unsafe {
900 core::arch::asm!("out 0xe9, al", in("al") b'e', options(nomem, nostack));
901 core::arch::asm!("out 0xe9, al", in("al") (b'0' + port as u8), options(nomem, nostack));
902 let psc = portsc;
903 for sh in [28usize, 24, 20, 16, 12, 8, 4, 0] {
904 let nib = b"0123456789abcdef"[((psc >> sh) & 0xF) as usize];
905 core::arch::asm!("out 0xe9, al", in("al") nib, options(nomem, nostack));
906 }
907 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
908 }
909
910 if !unsafe { self.reset_port(port) } {
915 unsafe {
916 core::arch::asm!("out 0xe9, al", in("al") b'z', options(nomem, nostack));
917 core::arch::asm!("out 0xe9, al", in("al") b'4', options(nomem, nostack));
918 let portsc = self.read_portsc(port);
919 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[((portsc >> 28) & 0xF) as usize], options(nomem, nostack));
920 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[((portsc >> 24) & 0xF) as usize], options(nomem, nostack));
921 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[((portsc >> 4) & 0xF) as usize], options(nomem, nostack));
922 core::arch::asm!("out 0xe9, al", in("al") b"0123456789abcdef"[(portsc & 0xF) as usize], options(nomem, nostack));
923 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
924 }
925 log::warn!("[xHCI] Port {} reset failed", port);
926 continue;
927 }
928 unsafe {
929 core::arch::asm!("out 0xe9, al", in("al") b'z', options(nomem, nostack));
930 core::arch::asm!("out 0xe9, al", in("al") b'R', options(nomem, nostack));
931 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
932 }
933 unsafe {
934 core::arch::asm!("out 0xe9, al", in("al") b'R', options(nomem, nostack));
935 }
936
937 let speed = unsafe { ((self.read_portsc(port) >> PORTSC_SPEED_SHIFT) & 0xF) as u8 };
938 log::info!("[xHCI] Port {} speed={}", port, speed);
939
940 match self.enable_slot() {
941 Ok(slot_id) => {
942 unsafe {
943 core::arch::asm!("out 0xe9, al", in("al") b'S', options(nomem, nostack));
944 }
945 if self.set_address(slot_id, usb_address).is_err() {
946 log::warn!("[xHCI] Port {} address failed", port);
947 continue;
948 }
949 usb_address += 1;
950 unsafe {
951 core::arch::asm!("out 0xe9, al", in("al") b'A', options(nomem, nostack));
952 }
953
954 let mut dev_desc = [0u8; 18];
955 if self.get_device_descriptor(slot_id, &mut dev_desc).is_ok() {
956 unsafe {
958 core::arch::asm!("out 0xe9, al", in("al") b'G', options(nomem, nostack));
959 let mut k = 0;
960 while k < 18 {
961 let b = dev_desc[k];
962 let hi = b"0123456789abcdef"[(b >> 4) as usize];
963 let lo = b"0123456789abcdef"[(b & 0xF) as usize];
964 core::arch::asm!("out 0xe9, al", in("al") hi, options(nomem, nostack));
965 core::arch::asm!("out 0xe9, al", in("al") lo, options(nomem, nostack));
966 k += 1;
967 }
968 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
969 }
970 let vid = u16::from_le_bytes([dev_desc[2], dev_desc[3]]);
971 let pid = u16::from_le_bytes([dev_desc[4], dev_desc[5]]);
972 let dev_class = dev_desc[4];
973 let max_packet0 = u16::from_le_bytes([dev_desc[7], dev_desc[8]]);
974 log::info!(
975 "[xHCI] Device: VID={:04x} PID={:04x} class={:02x} max_pkt0={}",
976 vid,
977 pid,
978 dev_class,
979 max_packet0
980 );
981
982 if max_packet0 == 64
983 || max_packet0 == 32
984 || max_packet0 == 16
985 || max_packet0 == 8
986 {
987 let idx = slot_id as usize;
988 if idx < self.device_slots.len() {
989 if let Some(ref mut dev) = self.device_slots[idx] {
990 dev.configured = true;
991 }
992 }
993 unsafe {
996 self.write_endpoint_context(
997 slot_id,
998 1,
999 self.device_slots[idx]
1000 .as_ref()
1001 .unwrap()
1002 .ep_transfer_ring_phys[1],
1003 max_packet0 as u32,
1004 EP_TYPE_CONTROL,
1005 0,
1006 );
1007 }
1008 }
1009
1010 crate::hardware::usb::hid::enumerate_device(port, slot_id, &dev_desc);
1011 } else {
1012 log::warn!("[xHCI] Port {} get device descriptor failed", port);
1013 }
1014 }
1015 Err(e) => {
1016 log::warn!("[xHCI] Port {} enable slot failed: {}", port, e);
1017 }
1018 }
1019 }
1020 }
1021
1022 pub fn alloc_interrupt_buffer(
1023 &mut self,
1024 slot_id: u8,
1025 endpoint: u8,
1026 len: usize,
1027 ) -> Result<(*mut u8, u64), &'static str> {
1028 let frame = allocate_zeroed_frame().ok_or("Failed to allocate interrupt buffer")?;
1029 let phys = frame.start_address.as_u64();
1030 let virt = phys_to_virt(phys) as *mut u8;
1031
1032 let idx = slot_id as usize;
1033 if idx < self.device_slots.len() {
1034 if let Some(ref mut dev) = self.device_slots[idx] {
1035 let ep = endpoint as usize;
1036 if ep < MAX_ENDPOINTS {
1037 dev.ep_buf[ep] = virt;
1038 dev.ep_buf_phys[ep] = phys;
1039 dev.ep_buf_len[ep] = len;
1040 }
1041 }
1042 }
1043 Ok((virt, phys))
1044 }
1045
1046 pub fn submit_interrupt_transfer(
1047 &mut self,
1048 slot_id: u8,
1049 endpoint: u8,
1050 ) -> Result<(), &'static str> {
1051 let idx = slot_id as usize;
1052 if idx >= self.device_slots.len() || self.device_slots[idx].is_none() {
1053 return Err("Invalid slot for interrupt transfer");
1054 }
1055
1056 let ep = endpoint as usize;
1057 if ep >= MAX_ENDPOINTS {
1058 return Err("Invalid endpoint");
1059 }
1060
1061 let dev = self.device_slots[idx].as_ref().unwrap();
1062 let tr_ring = dev.ep_transfer_rings[ep];
1063 let _tr_phys = dev.ep_transfer_ring_phys[ep];
1064 let buf_phys = dev.ep_buf_phys[ep];
1065 let buf_len = dev.ep_buf_len[ep];
1066 if tr_ring.is_null() || buf_phys == 0 {
1067 return Err("No transfer ring or buffer for endpoint");
1068 }
1069
1070 let deq = dev.ep_dequeue[ep];
1071 let cycle = dev.ep_cycle[ep];
1072
1073 let trb = Trb::normal(buf_phys, buf_len as u32, cycle, true);
1074 unsafe {
1075 core::ptr::write_volatile(tr_ring.add(deq), trb);
1076 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
1077 self.ring_doorbell(slot_id, endpoint);
1078 }
1079
1080 self.device_slots[idx].as_mut().unwrap().ep_active[ep] = true;
1081
1082 Ok(())
1083 }
1084
1085 pub fn port_count(&self) -> usize {
1086 self.max_ports
1087 }
1088
1089 pub fn is_port_connected(&self, port: usize) -> bool {
1090 if port >= self.ports.len() {
1091 return false;
1092 }
1093 self.ports[port].connected
1094 }
1095
1096 pub fn get_device_descriptor(
1097 &mut self,
1098 slot_id: u8,
1099 buf: &mut [u8; 18],
1100 ) -> Result<usize, &'static str> {
1101 let setup = [0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 18, 0x00];
1102 unsafe { self.ctrl_transfer(slot_id, &setup, Some(buf), 18) }
1103 }
1104
1105 pub fn get_configuration_descriptor(
1106 &mut self,
1107 slot_id: u8,
1108 config_idx: u8,
1109 buf: &mut [u8],
1110 len: usize,
1111 ) -> Result<usize, &'static str> {
1112 let setup = [
1113 0x80,
1114 0x06,
1115 config_idx,
1116 0x02,
1117 0x00,
1118 0x00,
1119 (len & 0xFF) as u8,
1120 ((len >> 8) & 0xFF) as u8,
1121 ];
1122 unsafe { self.ctrl_transfer(slot_id, &setup, Some(buf), len) }
1123 }
1124
1125 pub fn set_configuration(&mut self, slot_id: u8, config_value: u8) -> Result<(), &'static str> {
1126 let setup = [0x00, 0x09, config_value, 0x00, 0x00, 0x00, 0x00, 0x00];
1127 unsafe {
1128 self.ctrl_transfer(slot_id, &setup, None, 0)?;
1129 }
1130 Ok(())
1131 }
1132
1133 pub fn set_protocol(
1134 &mut self,
1135 slot_id: u8,
1136 interface: u8,
1137 protocol: u8,
1138 ) -> Result<(), &'static str> {
1139 let setup = [0x21, 0x0B, protocol, interface, 0x00, 0x00, 0x00, 0x00];
1140 unsafe {
1141 self.ctrl_transfer(slot_id, &setup, None, 0)?;
1142 }
1143 Ok(())
1144 }
1145
1146 pub fn get_port_speed(&self, port: usize) -> u8 {
1147 if port >= self.ports.len() {
1148 return 0;
1149 }
1150 self.ports[port].speed
1151 }
1152
1153 unsafe fn ctrl_transfer(
1154 &mut self,
1155 slot_id: u8,
1156 setup_data: &[u8; 8],
1157 data_buf: Option<&mut [u8]>,
1158 data_len: usize,
1159 ) -> Result<usize, &'static str> {
1160 unsafe {
1161 core::arch::asm!("out 0xe9, al", in("al") b'U', options(nomem, nostack));
1163 }
1164 let idx = slot_id as usize;
1165 if idx >= self.device_slots.len() || self.device_slots[idx].is_none() {
1166 unsafe {
1167 core::arch::asm!("out 0xe9, al", in("al") b'1', options(nomem, nostack));
1168 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
1169 }
1170 return Err("Invalid slot for control transfer");
1171 }
1172
1173 let dev = self.device_slots[idx].as_ref().unwrap();
1174 let tr_ring = dev.ep_transfer_rings[1];
1175 let tr_phys = dev.ep_transfer_ring_phys[1];
1176 if tr_ring.is_null() {
1177 unsafe {
1178 core::arch::asm!("out 0xe9, al", in("al") b'2', options(nomem, nostack));
1179 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
1180 }
1181 return Err("No transfer ring for EP0");
1182 }
1183
1184 let mut deq;
1185 let cycle = !dev.ep_cycle[1];
1191 let deq_start = dev.ep_dequeue[1] as usize;
1192
1193 for i in 0..3 {
1197 core::ptr::write_volatile(
1198 tr_ring.add((deq_start + i) % XHCI_RING_TRBS),
1199 Trb {
1200 d0: 0,
1201 d1: 0,
1202 d2: 0,
1203 d3: 0,
1204 },
1205 );
1206 }
1207 core::ptr::write_volatile(tr_ring.add(XHCI_RING_TRBS - 1), Trb::link(tr_phys, cycle));
1208 deq = deq_start;
1209
1210 let setup_phys = self.ctrl_transfer_buf_phys;
1211 let setup_virt = self.ctrl_transfer_buf;
1212 core::ptr::copy_nonoverlapping(setup_data.as_ptr(), setup_virt, 8);
1213
1214 let setup_trb = Trb::setup_stage(setup_phys, cycle);
1215 core::ptr::write_volatile(tr_ring.add(deq), setup_trb);
1216 deq += 1;
1217
1218 let has_data = data_buf.is_some();
1219 let dir_in = if has_data {
1220 (setup_data[0] & 0x80) != 0
1221 } else {
1222 false
1223 };
1224
1225 if let Some(buf) = &data_buf {
1226 let data_phys = self.ctrl_transfer_buf_phys + 8;
1227 let data_virt = self.ctrl_transfer_buf.add(8);
1228
1229 if dir_in && data_len > 0 {
1230 core::ptr::write_bytes(data_virt, 0, data_len);
1231 } else if !dir_in && data_len > 0 {
1232 core::ptr::copy_nonoverlapping(buf.as_ptr(), data_virt, data_len);
1233 }
1234
1235 let data_trb = Trb::data_stage(data_phys, data_len as u32, dir_in, cycle, false);
1236 core::ptr::write_volatile(tr_ring.add(deq), data_trb);
1237 deq += 1;
1238
1239 let status_trb = Trb::status_stage(cycle, !dir_in);
1240 core::ptr::write_volatile(tr_ring.add(deq), status_trb);
1241 deq += 1;
1242 } else {
1243 let status_trb = Trb::status_stage(cycle, true);
1244 core::ptr::write_volatile(tr_ring.add(deq), status_trb);
1245 deq += 1;
1246 }
1247
1248 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
1249 self.ring_doorbell(slot_id, 1);
1250 unsafe {
1251 core::arch::asm!("out 0xe9, al", in("al") b'C', options(nomem, nostack));
1252 }
1253
1254 let mut transferred = 0;
1255 let mut seen_status = false;
1256 for _ in 0..16 {
1257 let event = match self.wait_for_event() {
1258 Ok(e) => e,
1259 Err(e) => {
1260 unsafe {
1261 core::arch::asm!("out 0xe9, al", in("al") b'X', options(nomem, nostack));
1262 core::arch::asm!("out 0xe9, al", in("al") e.as_bytes()[0], options(nomem, nostack));
1263 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
1264 }
1265 return Err(e);
1266 }
1267 };
1268 let event_slot = ((event.d3 >> 24) & 0xFF) as u8;
1269 let event_ep = ((event.d2 >> 16) & 0x1F) as u8;
1270
1271 if event_slot != slot_id || event_ep != 1 {
1273 continue;
1274 }
1275
1276 let trb_type = trb_get_type(event.d3);
1277 let completion = (event.d2 >> 24) & 0xFF;
1278
1279 if completion != 1 {
1280 unsafe {
1281 core::arch::asm!("out 0xe9, al", in("al") b'E', options(nomem, nostack));
1282 core::arch::asm!("out 0xe9, al", in("al") (b'0' + (completion & 0xF) as u8), options(nomem, nostack));
1283 core::arch::asm!("out 0xe9, al", in("al") b'\n', options(nomem, nostack));
1284 }
1285 log::warn!(
1286 "[xHCI] ctrl_transfer event error: type={} completion={}",
1287 trb_type,
1288 completion
1289 );
1290 return Err("Control transfer event error");
1291 }
1292
1293 if trb_type == TRB_TYPE_STATUS_STAGE {
1294 if has_data && data_len > 0 && dir_in {
1295 let data_virt = self.ctrl_transfer_buf.add(8);
1296 if let Some(buf) = data_buf {
1297 core::ptr::copy_nonoverlapping(data_virt, buf.as_mut_ptr(), data_len);
1298 }
1299 transferred = data_len;
1300 }
1301 seen_status = true;
1302 break;
1303 }
1304 }
1305 if !seen_status {
1306 return Err("Control transfer: status event not received");
1307 }
1308
1309 self.device_slots[idx].as_mut().unwrap().ep_dequeue[1] = deq;
1310 self.device_slots[idx].as_mut().unwrap().ep_cycle[1] = cycle;
1311
1312 Ok(transferred)
1313 }
1314}
1315
1316static XHCI_CONTROLLERS: Mutex<Vec<Arc<Mutex<XhciController>>>> = Mutex::new(Vec::new());
1317static XHCI_INITIALIZED: AtomicBool = AtomicBool::new(false);
1318pub static XHCI_IRQ_LINE: AtomicU8 = AtomicU8::new(0);
1319
1320pub fn init() {
1321 log::info!("[xHCI] Scanning for xHCI controllers...");
1322
1323 let candidates = pci::probe_all(ProbeCriteria {
1324 vendor_id: None,
1325 device_id: None,
1326 class_code: Some(0x0C),
1327 subclass: Some(0x03),
1328 prog_if: Some(0x30),
1329 });
1330
1331 for pci_dev in candidates.into_iter() {
1332 log::info!(
1333 "xHCI: Found controller at {:?} (VEN:{:04x} DEV:{:04x})",
1334 pci_dev.address,
1335 pci_dev.vendor_id,
1336 pci_dev.device_id
1337 );
1338
1339 pci_dev.enable_memory_space();
1340 pci_dev.enable_bus_master();
1341
1342 let (irq, vector) = crate::arch::x86_64::msi::probe_and_enable(&pci_dev, true);
1344
1345 match unsafe { XhciController::new(pci_dev) } {
1346 Ok(controller) => {
1347 log::info!("[xHCI] Initialized with {} ports", controller.port_count());
1348 XHCI_IRQ_LINE.store(vector, Ordering::Relaxed);
1349 XHCI_CONTROLLERS
1350 .lock()
1351 .push(Arc::new(Mutex::new(controller)));
1352 crate::arch::x86_64::idt::register_xhci_irq_vector(vector);
1353 }
1354 Err(e) => {
1355 log::warn!("xHCI: Failed to initialize controller: {}", e);
1356 }
1357 }
1358 }
1359
1360 XHCI_INITIALIZED.store(true, Ordering::SeqCst);
1361 log::info!(
1362 "[xHCI] Found {} controller(s)",
1363 XHCI_CONTROLLERS.lock().len()
1364 );
1365}
1366
1367pub fn get_controller(index: usize) -> Option<Arc<Mutex<XhciController>>> {
1368 XHCI_CONTROLLERS.lock().get(index).cloned()
1369}
1370
1371pub fn is_available() -> bool {
1372 XHCI_INITIALIZED.load(Ordering::Relaxed) && !XHCI_CONTROLLERS.lock().is_empty()
1373}
1374
1375pub fn handle_interrupt() {
1376 unsafe {
1377 core::arch::asm!("out 0xe9, al", in("al") b'i', options(nomem, nostack));
1378 }
1379 if let Some(controller_arc) = get_controller(0) {
1380 let mut controller = controller_arc.lock();
1381 unsafe {
1382 let ir = &mut (*controller.rt_regs).ir[0];
1383 if (ir.iman & 1) != 0 {
1384 let mut processed = 0;
1385 while processed < 16 {
1386 let idx = controller.event_ring_deq.load(Ordering::Acquire);
1387 let trb = core::ptr::read_volatile(controller.event_ring.add(idx));
1388
1389 let expected_c = if controller.event_ring_cycle.load(Ordering::Acquire) {
1390 TRB_CYCLE
1391 } else {
1392 0
1393 };
1394 if (trb.d3 & TRB_CYCLE) != expected_c {
1395 break;
1396 }
1397
1398 let trb_type = trb_get_type(trb.d3);
1399 match trb_type {
1400 TRB_TYPE_TRANSFER_EVENT => {
1401 let slot_id = ((trb.d3 >> 24) & 0xFF) as u8;
1402 let ep_id = ((trb.d2 >> 16) & 0x1F) as u8;
1403 let completion = (trb.d2 >> 24) & 0xFF;
1404 let transferred = (trb.d2 & 0xFFFF) as usize;
1405
1406 if completion == 1 && ep_id >= 1 && (ep_id as usize) < MAX_ENDPOINTS {
1407 let idx = slot_id as usize;
1408 if idx < controller.device_slots.len() {
1409 if let Some(ref mut dev) = controller.device_slots[idx] {
1410 let ep = ep_id as usize;
1411 let buf = dev.ep_buf[ep];
1412 let buf_len = dev.ep_buf_len[ep];
1413 let actual_len = if transferred < buf_len {
1414 transferred
1415 } else {
1416 buf_len
1417 };
1418
1419 if !buf.is_null() && actual_len > 0 {
1420 unsafe {
1423 crate::hardware::usb::hid::receive_interrupt_report(
1424 slot_id, ep_id, buf, actual_len,
1425 );
1426 }
1427 }
1428
1429 dev.ep_dequeue[ep] =
1430 (dev.ep_dequeue[ep] + 1) % (XHCI_RING_TRBS - 1);
1431 if dev.ep_dequeue[ep] == 0 {
1432 dev.ep_cycle[ep] = !dev.ep_cycle[ep];
1433 }
1434 dev.ep_active[ep] = false;
1435 }
1436 }
1437 } else if completion != 1 && completion != 13 {
1438 let idx = slot_id as usize;
1439 if idx < controller.device_slots.len() {
1440 if let Some(ref mut dev) = controller.device_slots[idx] {
1441 let ep = ep_id as usize;
1442 if ep < MAX_ENDPOINTS {
1443 dev.ep_dequeue[ep] =
1444 (dev.ep_dequeue[ep] + 1) % (XHCI_RING_TRBS - 1);
1445 if dev.ep_dequeue[ep] == 0 {
1446 dev.ep_cycle[ep] = !dev.ep_cycle[ep];
1447 }
1448 dev.ep_active[ep] = false;
1449 }
1450 }
1451 }
1452 }
1453 }
1454 _ => {}
1455 }
1456
1457 let new_deq = (idx + 1) % 64;
1458 controller.event_ring_deq.store(new_deq, Ordering::Release);
1459 if new_deq == 0 {
1460 controller.event_ring_cycle.store(
1461 !controller.event_ring_cycle.load(Ordering::Acquire),
1462 Ordering::Release,
1463 );
1464 }
1465
1466 let new_erdp = controller.event_ring_phys + (new_deq as u64) * 16;
1467 ir.erdp = new_erdp | (1 << 3);
1468
1469 processed += 1;
1470 }
1471 }
1472
1473 let db_regs = controller.db_regs;
1474 for slot_idx in 0..controller.device_slots.len() {
1475 if let Some(ref mut dev) = controller.device_slots[slot_idx] {
1476 for ep in 1..MAX_ENDPOINTS {
1477 if dev.ep_active[ep]
1478 || dev.ep_buf[ep].is_null()
1479 || dev.ep_transfer_rings[ep].is_null()
1480 {
1481 continue;
1482 }
1483 let deq = dev.ep_dequeue[ep];
1484 let cycle = dev.ep_cycle[ep];
1485 let buf_phys = dev.ep_buf_phys[ep];
1486 let buf_len = dev.ep_buf_len[ep];
1487 let tr_ring = dev.ep_transfer_rings[ep];
1488 let slot = dev.slot_id;
1489
1490 let trb = Trb::normal(buf_phys, buf_len as u32, cycle, true);
1491 core::ptr::write_volatile(tr_ring.add(deq), trb);
1492
1493 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
1494 let db_index = (slot as usize) * 32 + ep;
1495 core::ptr::write_volatile(db_regs.add(db_index), 0);
1496 dev.ep_active[ep] = true;
1497 }
1498 }
1499 }
1500 }
1501 }
1502}