1use alloc::{string::String, vec, vec::Vec};
9
10use super::{
11 device::UsbPortStatus,
12 transfer::{UhciQh, UhciTd, UsbTransfer},
13 UsbSpeed,
14};
15use crate::error::KernelError;
16
17pub trait UsbHostController: Send + Sync {
19 fn name(&self) -> &str;
21
22 fn init(&mut self) -> Result<(), KernelError>;
24
25 fn reset(&mut self) -> Result<(), KernelError>;
27
28 fn get_port_count(&self) -> u8;
30
31 fn get_port_status(&self, port: u8) -> Result<UsbPortStatus, KernelError>;
33
34 fn reset_port(&mut self, port: u8) -> Result<(), KernelError>;
36
37 fn enable_port(&mut self, port: u8) -> Result<(), KernelError>;
39
40 fn disable_port(&mut self, port: u8) -> Result<(), KernelError>;
42
43 fn transfer(
45 &mut self,
46 device_address: u8,
47 transfer: UsbTransfer,
48 ) -> Result<Vec<u8>, KernelError>;
49
50 fn set_device_address(&mut self, old_address: u8, new_address: u8) -> Result<(), KernelError>;
52}
53
54#[allow(dead_code)] mod uhci_regs {
57 pub const USBCMD: u16 = 0x00; pub const USBSTS: u16 = 0x02; pub const USBINTR: u16 = 0x04; pub const FRNUM: u16 = 0x06; pub const FLBASEADD: u16 = 0x08; pub const SOFMOD: u16 = 0x0C; pub const PORTSC1: u16 = 0x10; pub const PORTSC2: u16 = 0x12; pub const CMD_RUN: u16 = 0x0001;
68 pub const CMD_HCRESET: u16 = 0x0002;
69 pub const CMD_GRESET: u16 = 0x0004;
70 pub const CMD_EGSM: u16 = 0x0008;
71 pub const CMD_FGR: u16 = 0x0010;
72 pub const CMD_SWDBG: u16 = 0x0020;
73 pub const CMD_CF: u16 = 0x0040;
74 pub const CMD_MAXP: u16 = 0x0080;
75
76 pub const STS_USBINT: u16 = 0x0001;
78 pub const STS_ERROR: u16 = 0x0002;
79 pub const STS_RD: u16 = 0x0004;
80 pub const STS_HSE: u16 = 0x0008;
81 pub const STS_HCPE: u16 = 0x0010;
82 pub const STS_HCH: u16 = 0x0020;
83
84 pub const PORT_CCS: u16 = 0x0001; pub const PORT_CSC: u16 = 0x0002; pub const PORT_PE: u16 = 0x0004; pub const PORT_PEC: u16 = 0x0008; pub const PORT_LS: u16 = 0x0030; pub const PORT_RD: u16 = 0x0040; pub const PORT_LSDA: u16 = 0x0100; pub const PORT_PR: u16 = 0x0200; pub const PORT_SUSP: u16 = 0x1000; }
95
96pub struct UhciController {
98 base_address: u32,
99 port_count: u8,
100 name: String,
101 frame_list_phys: u64,
103 control_qh_phys: u64,
105 td_buffer_phys: u64,
107 data_buffer_phys: u64,
109 initialized: bool,
111}
112
113impl UhciController {
114 pub fn new(base_address: u32) -> Self {
115 Self {
116 base_address,
117 port_count: 2, name: String::from("UHCI"),
119 frame_list_phys: 0,
120 control_qh_phys: 0,
121 td_buffer_phys: 0,
122 data_buffer_phys: 0,
123 initialized: false,
124 }
125 }
126
127 #[cfg(target_arch = "x86_64")]
129 fn read_reg16(&self, offset: u16) -> u16 {
130 use crate::arch::x86_64::inw;
131 unsafe { inw((self.base_address as u16).wrapping_add(offset)) }
135 }
136
137 #[cfg(not(target_arch = "x86_64"))]
138 fn read_reg16(&self, offset: u16) -> u16 {
139 let addr = (self.base_address as usize) + (offset as usize);
141 unsafe { core::ptr::read_volatile(addr as *const u16) }
145 }
146
147 #[cfg(target_arch = "x86_64")]
149 fn write_reg16(&self, offset: u16, value: u16) {
150 use crate::arch::x86_64::outw;
151 unsafe { outw((self.base_address as u16).wrapping_add(offset), value) }
154 }
155
156 #[cfg(not(target_arch = "x86_64"))]
157 fn write_reg16(&self, offset: u16, value: u16) {
158 let addr = (self.base_address as usize) + (offset as usize);
160 unsafe { core::ptr::write_volatile(addr as *mut u16, value) }
163 }
164
165 #[allow(dead_code)] #[cfg(target_arch = "x86_64")]
170 fn read_reg32(&self, offset: u16) -> u32 {
171 use crate::arch::x86_64::inl;
172 unsafe { inl((self.base_address as u16).wrapping_add(offset)) }
174 }
175
176 #[allow(dead_code)] #[cfg(not(target_arch = "x86_64"))]
180 fn read_reg32(&self, offset: u16) -> u32 {
181 let addr = (self.base_address as usize) + (offset as usize);
182 unsafe { core::ptr::read_volatile(addr as *const u32) }
184 }
185
186 #[cfg(target_arch = "x86_64")]
188 fn write_reg32(&self, offset: u16, value: u32) {
189 use crate::arch::x86_64::outl;
190 unsafe { outl((self.base_address as u16).wrapping_add(offset), value) }
192 }
193
194 #[cfg(not(target_arch = "x86_64"))]
195 fn write_reg32(&self, offset: u16, value: u32) {
196 let addr = (self.base_address as usize) + (offset as usize);
197 unsafe { core::ptr::write_volatile(addr as *mut u32, value) }
199 }
200
201 fn read_port_status(&self, port: u8) -> u16 {
203 let offset = if port == 1 {
204 uhci_regs::PORTSC1
205 } else {
206 uhci_regs::PORTSC2
207 };
208 self.read_reg16(offset)
209 }
210
211 fn write_port_status(&self, port: u8, value: u16) {
213 let offset = if port == 1 {
214 uhci_regs::PORTSC1
215 } else {
216 uhci_regs::PORTSC2
217 };
218 self.write_reg16(offset, value);
219 }
220
221 fn allocate_structures(&mut self) -> Result<(), KernelError> {
223 let frame_list_pages =
225 crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
226 requested: 4096,
227 available: 0,
228 })?;
229 let frame_list_frame = frame_list_pages.first().ok_or(KernelError::OutOfMemory {
230 requested: 4096,
231 available: 0,
232 })?;
233 self.frame_list_phys = frame_list_frame.as_addr().as_u64();
234
235 let frame_list_ptr = self.frame_list_phys as *mut u32;
237 unsafe {
241 for i in 0..1024 {
242 core::ptr::write_volatile(frame_list_ptr.add(i), 1); }
244 }
245
246 let qh_pages =
248 crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
249 requested: 4096,
250 available: 0,
251 })?;
252 let qh_frame = qh_pages.first().ok_or(KernelError::OutOfMemory {
253 requested: 4096,
254 available: 0,
255 })?;
256 self.control_qh_phys = qh_frame.as_addr().as_u64();
257
258 let qh_ptr = self.control_qh_phys as *mut UhciQh;
260 unsafe {
264 core::ptr::write_volatile(qh_ptr, UhciQh::new());
265 }
266
267 unsafe {
272 for i in 0..1024 {
273 core::ptr::write_volatile(frame_list_ptr.add(i), (self.control_qh_phys as u32) | 2);
275 }
276 }
277
278 let td_pages =
280 crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
281 requested: 4096,
282 available: 0,
283 })?;
284 let td_frame = td_pages.first().ok_or(KernelError::OutOfMemory {
285 requested: 4096,
286 available: 0,
287 })?;
288 self.td_buffer_phys = td_frame.as_addr().as_u64();
289
290 unsafe {
294 core::ptr::write_bytes(self.td_buffer_phys as *mut u8, 0, 4096);
295 }
296
297 let data_pages =
299 crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
300 requested: 4096,
301 available: 0,
302 })?;
303 let data_frame = data_pages.first().ok_or(KernelError::OutOfMemory {
304 requested: 4096,
305 available: 0,
306 })?;
307 self.data_buffer_phys = data_frame.as_addr().as_u64();
308
309 Ok(())
310 }
311
312 fn wait_for_transfer(&self, td_ptr: *mut UhciTd, timeout_ms: u32) -> Result<(), KernelError> {
314 let mut elapsed = 0u32;
315 let poll_interval = 1; while elapsed < timeout_ms {
318 let td = unsafe { core::ptr::read_volatile(td_ptr) };
322
323 if !td.is_active() {
324 if td.has_error() {
325 return Err(KernelError::HardwareError {
326 device: "uhci",
327 code: 1,
328 });
329 }
330 return Ok(());
331 }
332
333 for _ in 0..1000 {
335 core::hint::spin_loop();
336 }
337 elapsed += poll_interval;
338 }
339
340 Err(KernelError::Timeout {
341 operation: "usb transfer",
342 duration_ms: timeout_ms as u64,
343 })
344 }
345}
346
347impl UsbHostController for UhciController {
348 fn name(&self) -> &str {
349 &self.name
350 }
351
352 fn init(&mut self) -> Result<(), KernelError> {
353 crate::println!(
354 "[USB] Initializing UHCI controller at 0x{:x}",
355 self.base_address
356 );
357
358 if self.base_address == 0 {
360 crate::println!("[USB] UHCI: No hardware present, using software emulation");
361 self.initialized = true;
362 return Ok(());
363 }
364
365 self.allocate_structures()?;
367
368 self.reset()?;
370
371 self.write_reg32(uhci_regs::FLBASEADD, self.frame_list_phys as u32);
373
374 self.write_reg16(uhci_regs::SOFMOD, 64);
376
377 self.write_reg16(uhci_regs::FRNUM, 0);
379
380 self.write_reg16(uhci_regs::USBSTS, 0x003F);
382
383 self.write_reg16(uhci_regs::USBINTR, 0x000F);
385
386 self.write_reg16(
388 uhci_regs::USBCMD,
389 uhci_regs::CMD_RUN | uhci_regs::CMD_CF | uhci_regs::CMD_MAXP,
390 );
391
392 for _ in 0..100 {
394 let status = self.read_reg16(uhci_regs::USBSTS);
395 if (status & uhci_regs::STS_HCH) == 0 {
396 break; }
398 core::hint::spin_loop();
399 }
400
401 for port in 1..=self.port_count {
403 let _status = self.read_port_status(port);
404 crate::println!("[USB] Port {} initial status: 0x{:04x}", port, _status);
406 }
407
408 self.initialized = true;
409 crate::println!("[USB] UHCI controller initialized");
410
411 Ok(())
412 }
413
414 fn reset(&mut self) -> Result<(), KernelError> {
415 if self.base_address == 0 {
416 return Ok(());
417 }
418
419 let cmd = self.read_reg16(uhci_regs::USBCMD);
421 self.write_reg16(uhci_regs::USBCMD, cmd & !uhci_regs::CMD_RUN);
422
423 for _ in 0..100 {
425 let status = self.read_reg16(uhci_regs::USBSTS);
426 if (status & uhci_regs::STS_HCH) != 0 {
427 break;
428 }
429 core::hint::spin_loop();
430 }
431
432 self.write_reg16(uhci_regs::USBCMD, uhci_regs::CMD_GRESET);
434
435 for _ in 0..10000 {
437 core::hint::spin_loop();
438 }
439
440 self.write_reg16(uhci_regs::USBCMD, 0);
442
443 self.write_reg16(uhci_regs::USBCMD, uhci_regs::CMD_HCRESET);
445
446 for _ in 0..100 {
448 let cmd = self.read_reg16(uhci_regs::USBCMD);
449 if (cmd & uhci_regs::CMD_HCRESET) == 0 {
450 break;
451 }
452 core::hint::spin_loop();
453 }
454
455 crate::println!("[USB] UHCI controller reset complete");
456 Ok(())
457 }
458
459 fn get_port_count(&self) -> u8 {
460 self.port_count
461 }
462
463 fn get_port_status(&self, port: u8) -> Result<UsbPortStatus, KernelError> {
464 if port == 0 || port > self.port_count {
465 return Err(KernelError::InvalidArgument {
466 name: "port",
467 value: "out of range",
468 });
469 }
470
471 if self.base_address == 0 {
473 return Ok(UsbPortStatus {
474 connected: false,
475 enabled: false,
476 suspended: false,
477 reset: false,
478 speed: UsbSpeed::Full,
479 power: true,
480 });
481 }
482
483 let status = self.read_port_status(port);
484
485 Ok(UsbPortStatus {
486 connected: (status & uhci_regs::PORT_CCS) != 0,
487 enabled: (status & uhci_regs::PORT_PE) != 0,
488 suspended: (status & uhci_regs::PORT_SUSP) != 0,
489 reset: (status & uhci_regs::PORT_PR) != 0,
490 speed: if (status & uhci_regs::PORT_LSDA) != 0 {
491 UsbSpeed::Low
492 } else {
493 UsbSpeed::Full
494 },
495 power: true, })
497 }
498
499 fn reset_port(&mut self, port: u8) -> Result<(), KernelError> {
500 if port == 0 || port > self.port_count {
501 return Err(KernelError::InvalidArgument {
502 name: "port",
503 value: "out of range",
504 });
505 }
506
507 if self.base_address == 0 {
508 return Ok(());
509 }
510
511 let current = self.read_port_status(port);
512
513 self.write_port_status(port, current | uhci_regs::PORT_PR);
515
516 for _ in 0..50000 {
518 core::hint::spin_loop();
519 }
520
521 let current = self.read_port_status(port);
523 self.write_port_status(port, current & !uhci_regs::PORT_PR);
524
525 for _ in 0..1000 {
527 core::hint::spin_loop();
528 }
529
530 let status = self.read_port_status(port);
532 self.write_port_status(port, status | uhci_regs::PORT_CSC | uhci_regs::PORT_PEC);
533
534 crate::println!("[USB] Port {} reset complete", port);
535 Ok(())
536 }
537
538 fn enable_port(&mut self, port: u8) -> Result<(), KernelError> {
539 if port == 0 || port > self.port_count {
540 return Err(KernelError::InvalidArgument {
541 name: "port",
542 value: "out of range",
543 });
544 }
545
546 if self.base_address == 0 {
547 return Ok(());
548 }
549
550 let current = self.read_port_status(port);
551
552 self.write_port_status(port, current | uhci_regs::PORT_PE);
554
555 let status = self.read_port_status(port);
557 if (status & uhci_regs::PORT_PE) != 0 {
558 crate::println!("[USB] Port {} enabled", port);
559 Ok(())
560 } else {
561 Err(KernelError::HardwareError {
562 device: "uhci",
563 code: 2,
564 })
565 }
566 }
567
568 fn disable_port(&mut self, port: u8) -> Result<(), KernelError> {
569 if port == 0 || port > self.port_count {
570 return Err(KernelError::InvalidArgument {
571 name: "port",
572 value: "out of range",
573 });
574 }
575
576 if self.base_address == 0 {
577 return Ok(());
578 }
579
580 let current = self.read_port_status(port);
581
582 self.write_port_status(port, current & !uhci_regs::PORT_PE);
584
585 crate::println!("[USB] Port {} disabled", port);
586 Ok(())
587 }
588
589 fn transfer(
590 &mut self,
591 device_address: u8,
592 transfer: UsbTransfer,
593 ) -> Result<Vec<u8>, KernelError> {
594 if self.base_address == 0 || !self.initialized {
596 return match transfer {
597 UsbTransfer::Setup { data, value, .. } => {
598 if (value >> 8) == 1 {
600 let mut response = vec![0u8; data.len().min(18)];
602 if response.len() >= 18 {
603 response[0] = 18; response[1] = 1; response[2] = 0x10; response[3] = 0x02; response[4] = 0; response[5] = 0; response[6] = 0; response[7] = 64; response[8] = 0x34; response[9] = 0x12; response[10] = 0x78; response[11] = 0x56; response[12] = 0x00; response[13] = 0x01; response[14] = 0; response[15] = 0; response[16] = 0; response[17] = 1; }
622 Ok(response)
623 } else {
624 Ok(vec![0u8; data.len()])
625 }
626 }
627 UsbTransfer::In { length, .. } => Ok(vec![0u8; length]),
628 UsbTransfer::Out { .. } => Ok(Vec::new()),
629 };
630 }
631
632 let td_ptr = self.td_buffer_phys as *mut UhciTd;
634 let data_ptr = self.data_buffer_phys as *mut u8;
635 let qh_ptr = self.control_qh_phys as *mut UhciQh;
636
637 match transfer {
638 UsbTransfer::Setup {
639 request_type,
640 request,
641 value,
642 index,
643 data,
644 } => {
645 let setup_packet = [
647 request_type,
648 request,
649 (value & 0xFF) as u8,
650 ((value >> 8) & 0xFF) as u8,
651 (index & 0xFF) as u8,
652 ((index >> 8) & 0xFF) as u8,
653 (data.len() & 0xFF) as u8,
654 ((data.len() >> 8) & 0xFF) as u8,
655 ];
656
657 unsafe {
665 core::ptr::copy_nonoverlapping(setup_packet.as_ptr(), data_ptr, 8);
667
668 let setup_td = &mut *td_ptr;
670 setup_td.setup_packet(device_address, 0, false, 8);
671 setup_td.buffer_pointer = self.data_buffer_phys as u32;
672 setup_td.link_pointer = (self.td_buffer_phys as u32 + 16) | 4; let data_td = &mut *td_ptr.add(1);
676 let response_len = data.len().min(64) as u16;
677 data_td.in_packet(device_address, 0, true, response_len);
678 data_td.buffer_pointer = (self.data_buffer_phys + 64) as u32;
679 data_td.link_pointer = (self.td_buffer_phys as u32 + 32) | 4; let status_td = &mut *td_ptr.add(2);
683 status_td.out_packet(device_address, 0, true, 0);
684 status_td.buffer_pointer = 0;
685 status_td.link_pointer = 1; let qh = &mut *qh_ptr;
689 qh.element_link = self.td_buffer_phys as u32; self.wait_for_transfer(td_ptr.add(2), 1000)?;
693
694 let actual_len = (*td_ptr.add(1)).actual_length() as usize;
696 let mut response = vec![0u8; actual_len.min(data.len())];
697 core::ptr::copy_nonoverlapping(
698 (self.data_buffer_phys + 64) as *const u8,
699 response.as_mut_ptr(),
700 response.len(),
701 );
702
703 Ok(response)
704 }
705 }
706
707 UsbTransfer::In { endpoint, length } => {
708 let transfer_len = length.min(4096) as u16;
709
710 unsafe {
714 let in_td = &mut *td_ptr;
715 in_td.in_packet(device_address, endpoint, false, transfer_len);
716 in_td.buffer_pointer = self.data_buffer_phys as u32;
717 in_td.link_pointer = 1; let qh = &mut *qh_ptr;
720 qh.element_link = self.td_buffer_phys as u32;
721
722 self.wait_for_transfer(td_ptr, 1000)?;
723
724 let actual_len = (*td_ptr).actual_length() as usize;
725 let mut response = vec![0u8; actual_len];
726 core::ptr::copy_nonoverlapping(data_ptr, response.as_mut_ptr(), actual_len);
727
728 Ok(response)
729 }
730 }
731
732 UsbTransfer::Out { endpoint, data } => {
733 let transfer_len = data.len().min(4096);
734
735 unsafe {
739 core::ptr::copy_nonoverlapping(data.as_ptr(), data_ptr, transfer_len);
741
742 let out_td = &mut *td_ptr;
743 out_td.out_packet(device_address, endpoint, false, transfer_len as u16);
744 out_td.buffer_pointer = self.data_buffer_phys as u32;
745 out_td.link_pointer = 1; let qh = &mut *qh_ptr;
748 qh.element_link = self.td_buffer_phys as u32;
749
750 self.wait_for_transfer(td_ptr, 1000)?;
751
752 Ok(Vec::new())
753 }
754 }
755 }
756 }
757
758 fn set_device_address(&mut self, old_address: u8, new_address: u8) -> Result<(), KernelError> {
759 let transfer = UsbTransfer::Setup {
761 request_type: 0x00, request: 0x05, value: new_address as u16,
764 index: 0,
765 data: Vec::new(),
766 };
767
768 self.transfer(old_address, transfer)?;
770
771 for _ in 0..2000 {
773 core::hint::spin_loop();
774 }
775
776 crate::println!(
777 "[USB] Device address changed from {} to {}",
778 old_address,
779 new_address
780 );
781
782 Ok(())
783 }
784}