#![allow(non_snake_case, non_upper_case_globals)]
use crate::ral;
use crate::{td::Td, vcell::VCell};
#[repr(C, align(64))]
pub struct Qh {
CAPABILITIES: VCell<u32>,
_current_td_pointer: u32,
overlay: Td,
setup: VCell<u64>,
}
impl Qh {
pub const fn new() -> Self {
Qh {
CAPABILITIES: VCell::new(0),
_current_td_pointer: 0,
overlay: Td::new(),
setup: VCell::new(0),
}
}
#[inline(always)]
pub fn setup(&self) -> u64 {
self.setup.read()
}
pub fn overlay_mut(&mut self) -> &mut Td {
&mut self.overlay
}
pub fn set_max_packet_len(&mut self, max_packet_len: usize) {
ral::modify_reg!(crate::qh, self, CAPABILITIES, MAXIMUM_PACKET_LENGTH: max_packet_len.min(1024) as u32);
}
pub fn max_packet_len(&self) -> usize {
ral::read_reg!(crate::qh, self, CAPABILITIES, MAXIMUM_PACKET_LENGTH) as usize
}
pub fn set_zero_length_termination(&mut self, zlt: bool) {
ral::modify_reg!(crate::qh, self, CAPABILITIES, ZLT: !zlt as u32);
}
pub fn set_interrupt_on_setup(&mut self, ios: bool) {
ral::modify_reg!(crate::qh, self, CAPABILITIES, IOS: ios as u32);
}
pub fn clean_invalidate_dcache(&self) {
crate::cache::clean_invalidate_dcache_by_address(
&self as *const _ as usize,
core::mem::size_of_val(self),
);
}
}
mod CAPABILITIES {
pub mod ZLT {
pub const offset: u32 = 29;
pub const mask: u32 = 1 << offset;
pub mod RW {}
pub mod R {}
pub mod W {}
}
pub mod MAXIMUM_PACKET_LENGTH {
pub const offset: u32 = 16;
pub const mask: u32 = 0x7FF << offset;
pub mod RW {}
pub mod R {}
pub mod W {}
}
pub mod IOS {
pub const offset: u32 = 15;
pub const mask: u32 = 1 << offset;
pub mod RW {}
pub mod R {}
pub mod W {}
}
}
const _: [(); 1] = [(); (core::mem::size_of::<Qh>() <= 64) as usize];
#[cfg(test)]
mod test {
use super::Qh;
#[test]
fn max_packet_len() {
let mut qh = Qh::new();
qh.set_max_packet_len(0x333);
assert_eq!(qh.max_packet_len(), 0x333);
assert_eq!(qh.CAPABILITIES.read(), 0x333 << 16);
}
#[test]
fn ios() {
let mut qh = Qh::new();
qh.set_interrupt_on_setup(true);
assert_eq!(qh.CAPABILITIES.read(), 1 << 15);
}
#[test]
fn zlt() {
let mut qh = Qh::new();
qh.set_zero_length_termination(false);
assert_eq!(qh.CAPABILITIES.read(), 1 << 29);
}
}