WIP2
This commit is contained in:
@@ -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<H: Dwc2Impl> {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
name: Arc<str>,
|
||||
|
||||
channel_bitmask: AtomicU32,
|
||||
port_event_mask: BitmapEvent<AtomicWaker>,
|
||||
}
|
||||
|
||||
@@ -46,10 +51,16 @@ impl<H: Dwc2Impl + 'static> Dwc2<H> {
|
||||
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<Self>, speed: PortSpeed) -> Result<(), Error> {
|
||||
log::info!("{}: setup port", self.name);
|
||||
todo!()
|
||||
@@ -59,6 +70,10 @@ impl<H: Dwc2Impl + 'static> Dwc2<H> {
|
||||
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<H: Dwc2Impl + 'static> Device for Dwc2<H> {
|
||||
|
||||
impl<H: Dwc2Impl + 'static> InterruptHandler for Dwc2<H> {
|
||||
fn handle_irq(self: Arc<Self>, 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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user