use super::Link;
use bit_field::BitField;
use core::convert::TryInto;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
allowed! {
enum {
Normal,
SetupStage,
DataStage,
StatusStage,
Isoch,
Link,
EventData,
Noop
}
}
impl Allowed {
#[allow(clippy::too_many_lines)]
pub fn set_interrupt_on_completion(&mut self, ioc: bool) {
match self {
Allowed::Normal(ref mut n) => {
n.set_interrupt_on_completion(ioc);
}
Allowed::SetupStage(ref mut s) => {
s.set_interrupt_on_completion(ioc);
}
Allowed::DataStage(ref mut d) => {
d.set_interrupt_on_completion(ioc);
}
Allowed::StatusStage(ref mut s) => {
s.set_interrupt_on_completion(ioc);
}
Allowed::Isoch(ref mut i) => {
i.set_interrupt_on_completion(ioc);
}
Allowed::Link(ref mut l) => {
l.set_interrupt_on_completion(ioc);
}
Allowed::EventData(ref mut e) => {
e.set_interrupt_on_completion(ioc);
}
Allowed::Noop(ref mut n) => {
n.set_interrupt_on_completion(ioc);
}
}
}
#[must_use]
pub fn interrupt_on_completion(&self) -> bool {
match self {
Allowed::Normal(n) => n.interrupt_on_completion(),
Allowed::SetupStage(s) => s.interrupt_on_completion(),
Allowed::DataStage(d) => d.interrupt_on_completion(),
Allowed::StatusStage(s) => s.interrupt_on_completion(),
Allowed::Isoch(i) => i.interrupt_on_completion(),
Allowed::Link(l) => l.interrupt_on_completion(),
Allowed::EventData(e) => e.interrupt_on_completion(),
Allowed::Noop(n) => n.interrupt_on_completion(),
}
}
}
macro_rules! interrupt_on_completion {
($name:ident) => {
impl $name {
pub fn set_interrupt_on_completion(&mut self, ioc: bool) -> &mut Self {
self.0[3].set_bit(5, ioc);
self
}
#[must_use]
pub fn interrupt_on_completion(&self) -> bool {
self.0[3].get_bit(5)
}
}
};
}
macro_rules! transfer_trb {
($name:ident,$full:expr,$type:expr) => {
add_trb!($name, $full, $type);
interrupt_on_completion!($name);
};
}
macro_rules! transfer_trb_with_default {
($name:ident,$full:expr,$type:expr) => {
add_trb_with_default!($name, $full, $type);
interrupt_on_completion!($name);
};
}
macro_rules! impl_debug_for_transfer_trb{
($name:ident {})=>{
impl_debug_for_trb!($name{
interrupt_on_completion
});
};
($name:ident {
$($method:ident),*
})=>{
impl_debug_for_trb!($name{
interrupt_on_completion,
$($method),*
});
}
}
transfer_trb_with_default!(Normal, "Normal TRB", Type::Normal);
impl Normal {
pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self {
let l = p.get_bits(0..32);
let u = p.get_bits(32..64);
self.0[0] = l.try_into().unwrap();
self.0[1] = u.try_into().unwrap();
self
}
#[must_use]
pub fn data_buffer_pointer(&self) -> u64 {
let l: u64 = self.0[0].into();
let u: u64 = self.0[1].into();
(l << 32) | u
}
pub fn set_trb_transfer_length(&mut self, l: u32) -> &mut Self {
self.0[2].set_bits(0..=16, l);
self
}
#[must_use]
pub fn trb_transfer_length(&self) -> u32 {
self.0[2].get_bits(0..=16)
}
}
impl_debug_for_transfer_trb!(Normal {
data_buffer_pointer,
trb_transfer_length
});
transfer_trb!(SetupStage, "Setup Stage TRB", Type::SetupStage);
impl SetupStage {
#[must_use]
pub fn new() -> Self {
*Self([0; 4]).set_trb_type().set_idt()
}
pub fn set_request_type(&mut self, t: u8) -> &mut Self {
self.0[0].set_bits(0..=7, t.into());
self
}
#[must_use]
pub fn request_type(&self) -> u8 {
self.0[0].get_bits(0..=7).try_into().unwrap()
}
pub fn set_request(&mut self, r: u8) -> &mut Self {
self.0[0].set_bits(8..=15, r.into());
self
}
#[must_use]
pub fn request(&self) -> u8 {
self.0[0].get_bits(8..=15).try_into().unwrap()
}
pub fn set_value(&mut self, v: u16) -> &mut Self {
self.0[0].set_bits(16..=31, v.into());
self
}
#[must_use]
pub fn value(&self) -> u16 {
self.0[0].get_bits(16..=31).try_into().unwrap()
}
pub fn set_length(&mut self, l: u16) -> &mut Self {
self.0[1].set_bits(16..=31, l.into());
self
}
#[must_use]
pub fn length(&self) -> u16 {
self.0[1].get_bits(16..=31).try_into().unwrap()
}
pub fn set_trb_transfer_length(&mut self, l: u32) -> &mut Self {
self.0[2].set_bits(0..=16, l);
self
}
#[must_use]
pub fn trb_transfer_length(&self) -> u32 {
self.0[2].get_bits(0..=16)
}
pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self {
self.0[3].set_bits(16..=17, t as _);
self
}
#[must_use]
pub fn transfer_type(&self) -> TransferType {
FromPrimitive::from_u32(self.0[3].get_bits(16..=17)).expect("Transfer Type 1 is reserved.")
}
fn set_idt(&mut self) -> &mut Self {
self.0[3].set_bit(6, true);
self
}
}
impl Default for SetupStage {
fn default() -> Self {
Self::new()
}
}
impl_debug_for_transfer_trb!(SetupStage {
request_type,
request,
value,
length,
trb_transfer_length,
transfer_type
});
transfer_trb_with_default!(DataStage, "Data Stage TRB", Type::DataStage);
impl DataStage {
pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self {
let l = p.get_bits(0..32);
let u = p.get_bits(32..64);
self.0[0] = l.try_into().unwrap();
self.0[1] = u.try_into().unwrap();
self
}
#[must_use]
pub fn data_buffer_pointer(&self) -> u64 {
let l: u64 = self.0[0].into();
let u: u64 = self.0[1].into();
(u << 32) | l
}
pub fn set_trb_transfer_length(&mut self, l: u32) -> &mut Self {
self.0[2].set_bits(0..=16, l);
self
}
#[must_use]
pub fn trb_transfer_length(&self) -> u32 {
self.0[2].get_bits(0..=16)
}
pub fn set_direction(&mut self, d: Direction) -> &mut Self {
self.0[3].set_bit(16, d.into());
self
}
#[must_use]
pub fn direction(&self) -> Direction {
self.0[3].get_bit(16).into()
}
}
impl_debug_for_transfer_trb!(DataStage {
data_buffer_pointer,
trb_transfer_length,
direction
});
transfer_trb_with_default!(StatusStage, "Status Stage TRB", Type::StatusStage);
impl_debug_for_transfer_trb!(StatusStage {});
transfer_trb_with_default!(Isoch, "Isoch TRB", Type::Isoch);
impl Isoch {
pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self {
let l = p.get_bits(0..32);
let u = p.get_bits(32..64);
self.0[0] = l.try_into().unwrap();
self.0[1] = u.try_into().unwrap();
self
}
#[must_use]
pub fn data_buffer_pointer(&self) -> u64 {
let l: u64 = self.0[0].into();
let u: u64 = self.0[1].into();
(u << 32) | l
}
pub fn set_trb_transfer_length(&mut self, l: u32) -> &mut Self {
self.0[2].set_bits(0..=16, l);
self
}
#[must_use]
pub fn trb_transfer_length(&self) -> u32 {
self.0[2].get_bits(0..=16)
}
pub fn set_td_size_or_tbc(&mut self, t: u8) -> &mut Self {
self.0[2].set_bits(17..=21, t.into());
self
}
#[must_use]
pub fn td_size_or_tbc(&self) -> u8 {
self.0[2].get_bits(17..=21).try_into().unwrap()
}
pub fn set_interrupter_target(&mut self, t: u16) -> &mut Self {
self.0[2].set_bits(22..=31, t.into());
self
}
#[must_use]
pub fn interrupter_target(&self) -> u16 {
self.0[2].get_bits(22..=31).try_into().unwrap()
}
pub fn set_evaluate_next_trb(&mut self, ent: bool) -> &mut Self {
self.0[3].set_bit(1, ent);
self
}
#[must_use]
pub fn evaluate_next_trb(&self) -> bool {
self.0[3].get_bit(1)
}
pub fn set_interrupt_on_short_packet(&mut self, isp: bool) -> &mut Self {
self.0[3].set_bit(2, isp);
self
}
#[must_use]
pub fn interrupt_on_short_packet(&self) -> bool {
self.0[3].get_bit(2)
}
pub fn set_no_snoop(&mut self, s: bool) -> &mut Self {
self.0[3].set_bit(3, s);
self
}
#[must_use]
pub fn no_snoop(&self) -> bool {
self.0[3].get_bit(3)
}
pub fn set_chain_bit(&mut self, b: bool) -> &mut Self {
self.0[3].set_bit(4, b);
self
}
#[must_use]
pub fn chain_bit(&self) -> bool {
self.0[3].get_bit(4)
}
pub fn set_immediate_data(&mut self, idt: bool) -> &mut Self {
self.0[3].set_bit(6, idt);
self
}
#[must_use]
pub fn immediate_data(&self) -> bool {
self.0[3].get_bit(6)
}
pub fn set_transfer_burst_count(&mut self, c: u8) -> &mut Self {
self.0[3].set_bits(7..=8, c.into());
self
}
#[must_use]
pub fn transfer_burst_count(&self) -> u8 {
self.0[3].get_bits(7..=8).try_into().unwrap()
}
pub fn set_block_event_interrupt(&mut self, bei: bool) -> &mut Self {
self.0[3].set_bit(9, bei);
self
}
#[must_use]
pub fn block_event_interrupt(&self) -> bool {
self.0[3].get_bit(9)
}
pub fn set_transfer_last_burst_packet_count(&mut self, c: u8) -> &mut Self {
self.0[3].set_bits(16..=19, c.into());
self
}
#[must_use]
pub fn transfer_last_burst_packet_count(&self) -> u8 {
self.0[3].get_bits(16..=19).try_into().unwrap()
}
pub fn set_frame_id(&mut self, id: u16) -> &mut Self {
self.0[3].set_bits(20..=30, id.into());
self
}
#[must_use]
pub fn frame_id(&self) -> u16 {
self.0[3].get_bits(20..=30).try_into().unwrap()
}
pub fn set_start_isoch_asap(&mut self, sia: bool) -> &mut Self {
self.0[3].set_bit(31, sia);
self
}
#[must_use]
pub fn start_isoch_asap(&self) -> bool {
self.0[3].get_bit(31)
}
}
impl_debug_for_transfer_trb!(Isoch {
data_buffer_pointer,
trb_transfer_length,
td_size_or_tbc,
interrupter_target,
evaluate_next_trb,
interrupt_on_short_packet,
no_snoop,
chain_bit,
immediate_data,
transfer_burst_count,
block_event_interrupt,
transfer_last_burst_packet_count,
frame_id,
start_isoch_asap
});
transfer_trb_with_default!(EventData, "Event Data TRB", Type::EventData);
impl EventData {
pub fn set_event_data(&mut self, d: u64) -> &mut Self {
let l = d.get_bits(0..32);
let u = d.get_bits(32..64);
self.0[0] = l.try_into().unwrap();
self.0[1] = u.try_into().unwrap();
self
}
#[must_use]
pub fn event_data(&self) -> u64 {
let l: u64 = self.0[0].into();
let u: u64 = self.0[1].into();
(u << 32) | l
}
pub fn set_interrupter_target(&mut self, t: u16) -> &mut Self {
self.0[2].set_bits(22..=31, t.into());
self
}
#[must_use]
pub fn interrupter_target(&self) -> u16 {
self.0[2].get_bits(22..=31).try_into().unwrap()
}
pub fn set_evaluate_next_trb(&mut self, ent: bool) -> &mut Self {
self.0[3].set_bit(1, ent);
self
}
#[must_use]
pub fn evaluate_next_trb(&self) -> bool {
self.0[3].get_bit(1)
}
pub fn set_chain_bit(&mut self, b: bool) -> &mut Self {
self.0[3].set_bit(4, b);
self
}
#[must_use]
pub fn chain_bit(&self) -> bool {
self.0[3].get_bit(4)
}
pub fn set_block_event_interrupt(&mut self, bei: bool) -> &mut Self {
self.0[3].set_bit(9, bei);
self
}
#[must_use]
pub fn block_event_interrupt(&self) -> bool {
self.0[3].get_bit(9)
}
}
impl_debug_for_transfer_trb!(EventData {
event_data,
interrupter_target,
evaluate_next_trb,
chain_bit,
block_event_interrupt
});
transfer_trb_with_default!(Noop, "No Op TRB", Type::NoopTransfer);
impl Noop {
pub fn set_interrupter_target(&mut self, t: u16) -> &mut Self {
self.0[2].set_bits(22..=31, t.into());
self
}
#[must_use]
pub fn interrupter_target(&self) -> u16 {
self.0[2].get_bits(22..=31).try_into().unwrap()
}
pub fn set_evaluate_next_trb(&mut self, ent: bool) -> &mut Self {
self.0[3].set_bit(1, ent);
self
}
#[must_use]
pub fn evaluate_next_trb(&self) -> bool {
self.0[3].get_bit(1)
}
pub fn set_chain_bit(&mut self, b: bool) -> &mut Self {
self.0[3].set_bit(4, b);
self
}
#[must_use]
pub fn chain_bit(&self) -> bool {
self.0[3].get_bit(4)
}
}
impl_debug_for_transfer_trb!(Noop {
interrupter_target,
evaluate_next_trb,
chain_bit
});
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
pub enum Direction {
Out = 0,
In = 1,
}
impl From<Direction> for bool {
fn from(d: Direction) -> Self {
match d {
Direction::Out => false,
Direction::In => true,
}
}
}
impl From<bool> for Direction {
fn from(b: bool) -> Self {
if b {
Direction::In
} else {
Direction::Out
}
}
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
#[allow(clippy::module_name_repetitions)]
pub enum TransferType {
No = 0,
Out = 2,
In = 3,
}