forked from M-Labs/artiq
firmware: implement DRTIO destination survey
This commit is contained in:
parent
6cf3db3485
commit
fa872c3341
|
@ -10,14 +10,21 @@ pub use proto_artiq::drtioaux_proto::Packet;
|
||||||
// this is parametric over T because there's no impl Fail for !.
|
// this is parametric over T because there's no impl Fail for !.
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Fail, Debug)]
|
||||||
pub enum Error<T> {
|
pub enum Error<T> {
|
||||||
#[fail(display = "packet CRC failed")]
|
|
||||||
CorruptedPacket,
|
|
||||||
#[fail(display = "timed out waiting for data")]
|
|
||||||
TimedOut,
|
|
||||||
#[fail(display = "invalid node number")]
|
#[fail(display = "invalid node number")]
|
||||||
NoRoute,
|
NoRoute,
|
||||||
|
|
||||||
#[fail(display = "gateware reported error")]
|
#[fail(display = "gateware reported error")]
|
||||||
GatewareError,
|
GatewareError,
|
||||||
|
#[fail(display = "packet CRC failed")]
|
||||||
|
CorruptedPacket,
|
||||||
|
|
||||||
|
#[fail(display = "link is down")]
|
||||||
|
LinkDown,
|
||||||
|
#[fail(display = "timed out waiting for data")]
|
||||||
|
TimedOut,
|
||||||
|
#[fail(display = "unexpected reply")]
|
||||||
|
UnexpectedReply,
|
||||||
|
|
||||||
#[fail(display = "protocol error: {}", _0)]
|
#[fail(display = "protocol error: {}", _0)]
|
||||||
Protocol(#[cause] ProtocolError<T>)
|
Protocol(#[cause] ProtocolError<T>)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,12 @@ pub enum Packet {
|
||||||
ResetAck,
|
ResetAck,
|
||||||
TSCAck,
|
TSCAck,
|
||||||
|
|
||||||
RtioErrorRequest,
|
DestinationStatusRequest { destination: u8 },
|
||||||
RtioNoErrorReply,
|
DestinationDownReply,
|
||||||
RtioErrorSequenceErrorReply { channel: u16 },
|
DestinationOkReply,
|
||||||
RtioErrorCollisionReply { channel: u16 },
|
DestinationSequenceErrorReply { channel: u16 },
|
||||||
RtioErrorBusyReply { channel: u16 },
|
DestinationCollisionReply { channel: u16 },
|
||||||
|
DestinationBusyReply { channel: u16 },
|
||||||
|
|
||||||
RoutingSetPath { destination: u8, hops: [u8; 32] },
|
RoutingSetPath { destination: u8, hops: [u8; 32] },
|
||||||
RoutingSetRank { rank: u8 },
|
RoutingSetRank { rank: u8 },
|
||||||
|
@ -67,15 +68,18 @@ impl Packet {
|
||||||
0x03 => Packet::ResetAck,
|
0x03 => Packet::ResetAck,
|
||||||
0x04 => Packet::TSCAck,
|
0x04 => Packet::TSCAck,
|
||||||
|
|
||||||
0x20 => Packet::RtioErrorRequest,
|
0x20 => Packet::DestinationStatusRequest {
|
||||||
0x21 => Packet::RtioNoErrorReply,
|
destination: reader.read_u8()?
|
||||||
0x22 => Packet::RtioErrorSequenceErrorReply {
|
},
|
||||||
|
0x21 => Packet::DestinationDownReply,
|
||||||
|
0x22 => Packet::DestinationOkReply,
|
||||||
|
0x23 => Packet::DestinationSequenceErrorReply {
|
||||||
channel: reader.read_u16()?
|
channel: reader.read_u16()?
|
||||||
},
|
},
|
||||||
0x23 => Packet::RtioErrorCollisionReply {
|
0x24 => Packet::DestinationCollisionReply {
|
||||||
channel: reader.read_u16()?
|
channel: reader.read_u16()?
|
||||||
},
|
},
|
||||||
0x24 => Packet::RtioErrorBusyReply {
|
0x25 => Packet::DestinationBusyReply {
|
||||||
channel: reader.read_u16()?
|
channel: reader.read_u16()?
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -186,22 +190,26 @@ impl Packet {
|
||||||
Packet::TSCAck =>
|
Packet::TSCAck =>
|
||||||
writer.write_u8(0x04)?,
|
writer.write_u8(0x04)?,
|
||||||
|
|
||||||
Packet::RtioErrorRequest =>
|
Packet::DestinationStatusRequest {destination } => {
|
||||||
writer.write_u8(0x20)?,
|
writer.write_u8(0x20)?;
|
||||||
Packet::RtioNoErrorReply =>
|
writer.write_u8(destination)?;
|
||||||
writer.write_u8(0x21)?,
|
|
||||||
Packet::RtioErrorSequenceErrorReply { channel } => {
|
|
||||||
writer.write_u8(0x22)?;
|
|
||||||
writer.write_u16(channel)?;
|
|
||||||
},
|
},
|
||||||
Packet::RtioErrorCollisionReply { channel } => {
|
Packet::DestinationDownReply =>
|
||||||
|
writer.write_u8(0x21)?,
|
||||||
|
Packet::DestinationOkReply =>
|
||||||
|
writer.write_u8(0x22)?,
|
||||||
|
Packet::DestinationSequenceErrorReply { channel } => {
|
||||||
writer.write_u8(0x23)?;
|
writer.write_u8(0x23)?;
|
||||||
writer.write_u16(channel)?;
|
writer.write_u16(channel)?;
|
||||||
},
|
},
|
||||||
Packet::RtioErrorBusyReply { channel } => {
|
Packet::DestinationCollisionReply { channel } => {
|
||||||
writer.write_u8(0x24)?;
|
writer.write_u8(0x24)?;
|
||||||
writer.write_u16(channel)?;
|
writer.write_u16(channel)?;
|
||||||
},
|
},
|
||||||
|
Packet::DestinationBusyReply { channel } => {
|
||||||
|
writer.write_u8(0x25)?;
|
||||||
|
writer.write_u16(channel)?;
|
||||||
|
},
|
||||||
|
|
||||||
Packet::RoutingSetPath { destination, hops } => {
|
Packet::RoutingSetPath { destination, hops } => {
|
||||||
writer.write_u8(0x30)?;
|
writer.write_u8(0x30)?;
|
||||||
|
|
|
@ -201,22 +201,63 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_aux_errors(io: &Io, linkno: u8) {
|
fn destination_survey(io: &Io, routing_table: &drtio_routing::RoutingTable,
|
||||||
drtioaux::send_link(linkno, &drtioaux::Packet::RtioErrorRequest).unwrap();
|
up_destinations: &mut [bool; drtio_routing::DEST_COUNT]) {
|
||||||
|
for destination in 0..drtio_routing::DEST_COUNT {
|
||||||
|
let hop = routing_table.0[destination][0];
|
||||||
|
|
||||||
|
if hop == 0 {
|
||||||
|
/* local RTIO */
|
||||||
|
up_destinations[destination] = true;
|
||||||
|
} else if hop as usize <= csr::DRTIO.len() {
|
||||||
|
let linkno = hop - 1;
|
||||||
|
if up_destinations[destination] {
|
||||||
|
if link_up(linkno) {
|
||||||
|
drtioaux::send_link(linkno, &drtioaux::Packet::DestinationStatusRequest {
|
||||||
|
destination: destination as u8
|
||||||
|
}).unwrap();
|
||||||
match recv_aux_timeout(io, linkno, 200) {
|
match recv_aux_timeout(io, linkno, 200) {
|
||||||
Ok(drtioaux::Packet::RtioNoErrorReply) => (),
|
Ok(drtioaux::Packet::DestinationDownReply) => {
|
||||||
Ok(drtioaux::Packet::RtioErrorSequenceErrorReply { channel }) =>
|
info!("[DEST#{}] destination is down", destination);
|
||||||
error!("[LINK#{}] RTIO sequence error involving channel {}", linkno, channel),
|
up_destinations[destination] = false;
|
||||||
Ok(drtioaux::Packet::RtioErrorCollisionReply { channel }) =>
|
},
|
||||||
error!("[LINK#{}] RTIO collision involving channel {}", linkno, channel),
|
Ok(drtioaux::Packet::DestinationOkReply) => (),
|
||||||
Ok(drtioaux::Packet::RtioErrorBusyReply { channel }) =>
|
Ok(drtioaux::Packet::DestinationSequenceErrorReply { channel }) =>
|
||||||
error!("[LINK#{}] RTIO busy error involving channel {}", linkno, channel),
|
error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}", destination, channel),
|
||||||
Ok(_) => error!("[LINK#{}] received unexpected aux packet", linkno),
|
Ok(drtioaux::Packet::DestinationCollisionReply { channel }) =>
|
||||||
Err(e) => error!("[LINK#{}] communication failed ({})", linkno, e)
|
error!("[DEST#{}] RTIO collision involving channel 0x{:04x}", destination, channel),
|
||||||
|
Ok(drtioaux::Packet::DestinationBusyReply { channel }) =>
|
||||||
|
error!("[DEST#{}] RTIO busy error involving channel 0x{:04x}", destination, channel),
|
||||||
|
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
||||||
|
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("[DEST#{}] destination is down", destination);
|
||||||
|
up_destinations[destination] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if link_up(linkno) {
|
||||||
|
drtioaux::send_link(linkno, &drtioaux::Packet::DestinationStatusRequest {
|
||||||
|
destination: destination as u8
|
||||||
|
}).unwrap();
|
||||||
|
match recv_aux_timeout(io, linkno, 200) {
|
||||||
|
Ok(drtioaux::Packet::DestinationDownReply) => (),
|
||||||
|
Ok(drtioaux::Packet::DestinationOkReply) => {
|
||||||
|
info!("[DEST#{}] destination is up", destination);
|
||||||
|
up_destinations[destination] = true;
|
||||||
|
/* TODO: get buffer space */
|
||||||
|
},
|
||||||
|
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
||||||
|
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_thread(io: Io, routing_table: &drtio_routing::RoutingTable) {
|
pub fn link_thread(io: Io, routing_table: &drtio_routing::RoutingTable) {
|
||||||
|
let mut up_destinations = [false; drtio_routing::DEST_COUNT];
|
||||||
loop {
|
loop {
|
||||||
for linkno in 0..csr::DRTIO.len() {
|
for linkno in 0..csr::DRTIO.len() {
|
||||||
let linkno = linkno as u8;
|
let linkno = linkno as u8;
|
||||||
|
@ -225,7 +266,6 @@ pub mod drtio {
|
||||||
if link_rx_up(linkno) {
|
if link_rx_up(linkno) {
|
||||||
process_unsolicited_aux(linkno);
|
process_unsolicited_aux(linkno);
|
||||||
process_local_errors(linkno);
|
process_local_errors(linkno);
|
||||||
process_aux_errors(&io, linkno);
|
|
||||||
} else {
|
} else {
|
||||||
info!("[LINK#{}] link is down", linkno);
|
info!("[LINK#{}] link is down", linkno);
|
||||||
set_link_up(linkno, false);
|
set_link_up(linkno, false);
|
||||||
|
@ -255,6 +295,7 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
destination_survey(&io, routing_table, &mut up_destinations);
|
||||||
io.sleep(200).unwrap();
|
io.sleep(200).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,13 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::ResetAck)
|
drtioaux::send_link(0, &drtioaux::Packet::ResetAck)
|
||||||
},
|
},
|
||||||
|
|
||||||
drtioaux::Packet::RtioErrorRequest => {
|
drtioaux::Packet::DestinationStatusRequest { destination } => {
|
||||||
|
#[cfg(has_drtio_routing)]
|
||||||
|
let hop = _routing_table.0[destination as usize][*_rank as usize];
|
||||||
|
#[cfg(not(has_drtio_routing))]
|
||||||
|
let hop = 0;
|
||||||
|
|
||||||
|
if hop == 0 {
|
||||||
let errors;
|
let errors;
|
||||||
unsafe {
|
unsafe {
|
||||||
errors = csr::drtiosat::rtio_error_read();
|
errors = csr::drtiosat::rtio_error_read();
|
||||||
|
@ -83,7 +89,7 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
|
||||||
csr::drtiosat::rtio_error_write(1);
|
csr::drtiosat::rtio_error_write(1);
|
||||||
}
|
}
|
||||||
drtioaux::send_link(0,
|
drtioaux::send_link(0,
|
||||||
&drtioaux::Packet::RtioErrorSequenceErrorReply { channel })
|
&drtioaux::Packet::DestinationSequenceErrorReply { channel })?;
|
||||||
} else if errors & 2 != 0 {
|
} else if errors & 2 != 0 {
|
||||||
let channel;
|
let channel;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -91,7 +97,7 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
|
||||||
csr::drtiosat::rtio_error_write(2);
|
csr::drtiosat::rtio_error_write(2);
|
||||||
}
|
}
|
||||||
drtioaux::send_link(0,
|
drtioaux::send_link(0,
|
||||||
&drtioaux::Packet::RtioErrorCollisionReply { channel })
|
&drtioaux::Packet::DestinationCollisionReply { channel })?;
|
||||||
} else if errors & 4 != 0 {
|
} else if errors & 4 != 0 {
|
||||||
let channel;
|
let channel;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -99,13 +105,38 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
|
||||||
csr::drtiosat::rtio_error_write(4);
|
csr::drtiosat::rtio_error_write(4);
|
||||||
}
|
}
|
||||||
drtioaux::send_link(0,
|
drtioaux::send_link(0,
|
||||||
&drtioaux::Packet::RtioErrorBusyReply { channel })
|
&drtioaux::Packet::DestinationBusyReply { channel })?;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::RtioNoErrorReply)
|
drtioaux::send_link(0, &drtioaux::Packet::DestinationOkReply)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_drtio_routing)]
|
||||||
|
{
|
||||||
|
if hop != 0 {
|
||||||
|
let hop = hop as usize;
|
||||||
|
if hop <= csr::DRTIOREP.len() {
|
||||||
|
let repno = hop - 1;
|
||||||
|
match _repeaters[repno].aux_forward(&drtioaux::Packet::DestinationStatusRequest {
|
||||||
|
destination: destination
|
||||||
|
}) {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(drtioaux::Error::LinkDown) => drtioaux::send_link(0, &drtioaux::Packet::DestinationDownReply)?,
|
||||||
|
Err(e) => {
|
||||||
|
drtioaux::send_link(0, &drtioaux::Packet::DestinationDownReply)?;
|
||||||
|
error!("aux error when handling destination status request: {}", e);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drtioaux::send_link(0, &drtioaux::Packet::DestinationDownReply)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(has_drtio_routing)]
|
#[cfg(has_drtio_routing)]
|
||||||
drtioaux::Packet::RoutingSetPath { destination, hops } => {
|
drtioaux::Packet::RoutingSetPath { destination, hops } => {
|
||||||
_routing_table.0[destination as usize] = hops;
|
_routing_table.0[destination as usize] = hops;
|
||||||
|
@ -135,11 +166,11 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(has_drtio_routing))]
|
#[cfg(not(has_drtio_routing))]
|
||||||
drtioaux::Packet::RoutingSetPath { _destination, _hops } => {
|
drtioaux::Packet::RoutingSetPath { destination, hops } => {
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::RoutingAck)
|
drtioaux::send_link(0, &drtioaux::Packet::RoutingAck)
|
||||||
}
|
}
|
||||||
#[cfg(not(has_drtio_routing))]
|
#[cfg(not(has_drtio_routing))]
|
||||||
drtioaux::Packet::RoutingSetRank { _rank } => {
|
drtioaux::Packet::RoutingSetRank { rank } => {
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::RoutingAck)
|
drtioaux::send_link(0, &drtioaux::Packet::RoutingAck)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,24 +153,34 @@ impl Repeater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv_aux_timeout(&self, timeout: u32) -> Result<drtioaux::Packet, &'static str> {
|
fn recv_aux_timeout(&self, timeout: u32) -> Result<drtioaux::Packet, drtioaux::Error<!>> {
|
||||||
let max_time = clock::get_ms() + timeout as u64;
|
let max_time = clock::get_ms() + timeout as u64;
|
||||||
loop {
|
loop {
|
||||||
if !rep_link_rx_up(self.repno) {
|
if !rep_link_rx_up(self.repno) {
|
||||||
return Err("link went down");
|
return Err(drtioaux::Error::LinkDown);
|
||||||
}
|
}
|
||||||
if clock::get_ms() > max_time {
|
if clock::get_ms() > max_time {
|
||||||
return Err("timeout");
|
return Err(drtioaux::Error::TimedOut);
|
||||||
}
|
}
|
||||||
match drtioaux::recv_link(self.auxno) {
|
match drtioaux::recv_link(self.auxno) {
|
||||||
Ok(Some(packet)) => return Ok(packet),
|
Ok(Some(packet)) => return Ok(packet),
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Err(_) => return Err("aux packet error")
|
Err(e) => return Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_tsc(&self) -> Result<(), &'static str> {
|
pub fn aux_forward(&self, request: &drtioaux::Packet) -> Result<(), drtioaux::Error<!>> {
|
||||||
|
if self.state != RepeaterState::Up {
|
||||||
|
return Err(drtioaux::Error::LinkDown);
|
||||||
|
}
|
||||||
|
drtioaux::send_link(self.auxno, request).unwrap();
|
||||||
|
let reply = self.recv_aux_timeout(200)?;
|
||||||
|
drtioaux::send_link(0, &reply).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sync_tsc(&self) -> Result<(), drtioaux::Error<!>> {
|
||||||
if self.state != RepeaterState::Up {
|
if self.state != RepeaterState::Up {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -187,11 +197,11 @@ impl Repeater {
|
||||||
if reply == drtioaux::Packet::TSCAck {
|
if reply == drtioaux::Packet::TSCAck {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err("unexpected reply");
|
return Err(drtioaux::Error::UnexpectedReply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_path(&self, destination: u8, hops: &[u8; drtio_routing::MAX_HOPS]) -> Result<(), &'static str> {
|
pub fn set_path(&self, destination: u8, hops: &[u8; drtio_routing::MAX_HOPS]) -> Result<(), drtioaux::Error<!>> {
|
||||||
if self.state != RepeaterState::Up {
|
if self.state != RepeaterState::Up {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -202,19 +212,19 @@ impl Repeater {
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
let reply = self.recv_aux_timeout(200)?;
|
let reply = self.recv_aux_timeout(200)?;
|
||||||
if reply != drtioaux::Packet::RoutingAck {
|
if reply != drtioaux::Packet::RoutingAck {
|
||||||
return Err("unexpected reply");
|
return Err(drtioaux::Error::UnexpectedReply);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_routing_table(&self, routing_table: &drtio_routing::RoutingTable) -> Result<(), &'static str> {
|
pub fn load_routing_table(&self, routing_table: &drtio_routing::RoutingTable) -> Result<(), drtioaux::Error<!>> {
|
||||||
for i in 0..drtio_routing::DEST_COUNT {
|
for i in 0..drtio_routing::DEST_COUNT {
|
||||||
self.set_path(i as u8, &routing_table.0[i])?;
|
self.set_path(i as u8, &routing_table.0[i])?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_rank(&self, rank: u8) -> Result<(), &'static str> {
|
pub fn set_rank(&self, rank: u8) -> Result<(), drtioaux::Error<!>> {
|
||||||
if self.state != RepeaterState::Up {
|
if self.state != RepeaterState::Up {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -223,12 +233,12 @@ impl Repeater {
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
let reply = self.recv_aux_timeout(200)?;
|
let reply = self.recv_aux_timeout(200)?;
|
||||||
if reply != drtioaux::Packet::RoutingAck {
|
if reply != drtioaux::Packet::RoutingAck {
|
||||||
return Err("unexpected reply");
|
return Err(drtioaux::Error::UnexpectedReply);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rtio_reset(&self, phy: bool) -> Result<(), &'static str> {
|
pub fn rtio_reset(&self, phy: bool) -> Result<(), drtioaux::Error<!>> {
|
||||||
if self.state != RepeaterState::Up {
|
if self.state != RepeaterState::Up {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -237,7 +247,7 @@ impl Repeater {
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
let reply = self.recv_aux_timeout(200)?;
|
let reply = self.recv_aux_timeout(200)?;
|
||||||
if reply != drtioaux::Packet::ResetAck {
|
if reply != drtioaux::Packet::ResetAck {
|
||||||
return Err("unexpected reply");
|
return Err(drtioaux::Error::UnexpectedReply);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue