From aba41cb5b2742f4708812892b6e058669dc04525 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Mon, 29 Sep 2025 14:01:54 +0300 Subject: [PATCH] WIP2 --- kernel/driver/usb/dwc2/src/lib.rs | 39 ++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/kernel/driver/usb/dwc2/src/lib.rs b/kernel/driver/usb/dwc2/src/lib.rs index 8c9698fe..eba6254d 100644 --- a/kernel/driver/usb/dwc2/src/lib.rs +++ b/kernel/driver/usb/dwc2/src/lib.rs @@ -1,6 +1,9 @@ #![no_std] -use core::{sync::atomic::AtomicBool, time::Duration}; +use core::{ + sync::atomic::{AtomicBool, AtomicU32}, + time::Duration, +}; use alloc::sync::Arc; use device_api::{ @@ -15,6 +18,7 @@ use tock_registers::{ interfaces::{ReadWriteable, Readable, Writeable}, LocalRegisterCopy, }; +use yggdrasil_abi::bitflags; use crate::{ regs::{PortSpeed, Regs}, @@ -31,6 +35,7 @@ pub struct Dwc2 { regs: IrqSafeSpinlock>, name: Arc, + channel_bitmask: AtomicU32, port_event_mask: BitmapEvent, } @@ -46,10 +51,16 @@ impl Dwc2 { imp, regs, name, + channel_bitmask: AtomicU32::new(0), port_event_mask: BitmapEvent::new(AtomicWaker::new()), }) } + fn signal_events(&self, channels: u16, ports: u32) { + self.port_event_mask + .signal(((channels as u64) << 32) | (ports as u64)); + } + async fn setup_port(self: Arc, speed: PortSpeed) -> Result<(), Error> { log::info!("{}: setup port", self.name); todo!() @@ -59,6 +70,10 @@ impl Dwc2 { LocalRegisterCopy::new(self.port_event_mask.wait_mask(0x2A).await as u32) } + async fn wait_for_channel_events(&self) -> u16 { + (self.port_event_mask.wait_mask(0xFFFF00000000).await >> 32) as u16 + } + async fn wait_for_device(&self) -> PortSpeed { let hprt = self.regs.lock().HPRT.extract(); // If already connected, begin init, if not, wait for connect change @@ -189,17 +204,19 @@ impl Device for Dwc2 { impl InterruptHandler for Dwc2 { fn handle_irq(self: Arc, vector: IrqVector) -> bool { - let (port_status, interrupt) = { - let regs = self.regs.lock(); - (regs.take_port_status(), regs.take_interrupt()) + let regs = self.regs.lock(); + let gintsts = regs.take_interrupt(); + + let hprt = if gintsts.matches_all(regs::GINTSTS::HPRTINT::SET) { + regs.take_port_status().get() + } else { + 0 }; - log::info!( - "USB IRQ: {:#x}, port {:#x} ({})", - interrupt.get(), - port_status.get(), - port_status.get() & 0x2A != 0 - ); - self.port_event_mask.signal(port_status.get() as u64); + + if hprt != 0 { + self.signal_events(0, hprt); + } + true } }