pub mod ext_sync_section;
pub mod global_section;
pub mod rx_stream_format_section;
pub mod tx_stream_format_section;
pub mod extension;
pub mod tcd22xx_spec;
pub mod config_rom;
use {
super::*,
glib::{error::ErrorDomain, Quark},
hinawa::{prelude::FwReqExtManual, FwTcode},
std::convert::TryFrom,
};
mod utils;
#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
pub struct Section {
pub offset: usize,
pub size: usize,
}
impl Section {
pub const SIZE: usize = 8;
}
impl From<&[u8]> for Section {
fn from(data: &[u8]) -> Self {
assert!(data.len() >= Self::SIZE);
let mut quadlet = [0; 4];
quadlet.copy_from_slice(&data[..4]);
let offset = 4 * u32::from_be_bytes(quadlet) as usize;
quadlet.copy_from_slice(&data[4..8]);
let size = 4 * u32::from_be_bytes(quadlet) as usize;
Section { offset, size }
}
}
#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
pub struct GeneralSections {
pub global: Section,
pub tx_stream_format: Section,
pub rx_stream_format: Section,
pub ext_sync: Section,
pub reserved: Section,
}
impl GeneralSections {
const SECTION_COUNT: usize = 5;
const SIZE: usize = Section::SIZE * Self::SECTION_COUNT;
}
impl From<&[u8]> for GeneralSections {
fn from(raw: &[u8]) -> Self {
GeneralSections {
global: Section::from(&raw[..8]),
tx_stream_format: Section::from(&raw[8..16]),
rx_stream_format: Section::from(&raw[16..24]),
ext_sync: Section::from(&raw[24..32]),
reserved: Section::from(&raw[32..40]),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum GeneralProtocolError {
Global,
TxStreamFormat,
RxStreamFormat,
Invalid(i32),
}
impl std::fmt::Display for GeneralProtocolError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let msg = match self {
GeneralProtocolError::Global => "global",
GeneralProtocolError::TxStreamFormat => "tx-stream-format",
GeneralProtocolError::RxStreamFormat => "rx-stream-format",
GeneralProtocolError::Invalid(_) => "invalid",
};
write!(f, "GeneralProtocolError::{}", msg)
}
}
impl ErrorDomain for GeneralProtocolError {
fn domain() -> Quark {
Quark::from_str("tcat-general-protocol-error-quark")
}
fn code(self) -> i32 {
match self {
GeneralProtocolError::Global => 0,
GeneralProtocolError::TxStreamFormat => 1,
GeneralProtocolError::RxStreamFormat => 2,
GeneralProtocolError::Invalid(v) => v,
}
}
fn from(code: i32) -> Option<Self> {
let enumeration = match code {
0 => GeneralProtocolError::Global,
1 => GeneralProtocolError::TxStreamFormat,
2 => GeneralProtocolError::RxStreamFormat,
_ => GeneralProtocolError::Invalid(code),
};
Some(enumeration)
}
}
#[derive(Default)]
pub struct GeneralProtocol;
const BASE_ADDR: u64 = 0xffffe0000000;
impl GeneralProtocol {
const MAX_FRAME_SIZE: usize = 512;
pub fn read(
req: &mut FwReq,
node: &mut FwNode,
offset: usize,
mut frames: &mut [u8],
timeout_ms: u32,
) -> Result<(), Error> {
let mut addr = BASE_ADDR + offset as u64;
while frames.len() > 0 {
let len = std::cmp::min(frames.len(), Self::MAX_FRAME_SIZE);
let tcode = if len == 4 {
FwTcode::ReadQuadletRequest
} else {
FwTcode::ReadBlockRequest
};
req.transaction_sync(node, tcode, addr, len, &mut frames[0..len], timeout_ms)?;
addr += len as u64;
frames = &mut frames[len..];
}
Ok(())
}
pub fn write(
req: &mut FwReq,
node: &mut FwNode,
offset: usize,
mut frames: &mut [u8],
timeout_ms: u32,
) -> Result<(), Error> {
let mut addr = BASE_ADDR + (offset as u64);
while frames.len() > 0 {
let len = std::cmp::min(frames.len(), Self::MAX_FRAME_SIZE);
let tcode = if len == 4 {
FwTcode::WriteQuadletRequest
} else {
FwTcode::WriteBlockRequest
};
req.transaction_sync(node, tcode, addr, len, &mut frames[0..len], timeout_ms)?;
addr += len as u64;
frames = &mut frames[len..];
}
Ok(())
}
pub fn read_general_sections(
req: &mut FwReq,
node: &mut FwNode,
timeout_ms: u32,
) -> Result<GeneralSections, Error> {
let mut data = [0; GeneralSections::SIZE];
GeneralProtocol::read(req, node, 0, &mut data, timeout_ms)
.map(|_| GeneralSections::from(&data[..]))
}
}
#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
pub struct Iec60958Param {
pub cap: bool,
pub enable: bool,
}
impl GeneralProtocol {
const NOTIFY_RX_CFG_CHG: u32 = 0x00000001;
const NOTIFY_TX_CFG_CHG: u32 = 0x00000002;
const NOTIFY_LOCK_CHG: u32 = 0x00000010;
const NOTIFY_CLOCK_ACCEPTED: u32 = 0x00000020;
const NOTIFY_EXT_STATUS: u32 = 0x00000040;
pub fn has_rx_config_changed(msg: u32) -> bool {
msg & msg & Self::NOTIFY_RX_CFG_CHG > 0
}
pub fn has_tx_config_changed(msg: u32) -> bool {
msg & Self::NOTIFY_TX_CFG_CHG > 0
}
pub fn has_lock_changed(msg: u32) -> bool {
msg & Self::NOTIFY_LOCK_CHG > 0
}
pub fn has_clock_accepted(msg: u32) -> bool {
msg & Self::NOTIFY_CLOCK_ACCEPTED > 0
}
pub fn has_ext_status_changed(msg: u32) -> bool {
msg & Self::NOTIFY_EXT_STATUS > 0
}
}