Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/minibar/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ start = true
task-slots = ["sys", "i2c_driver"]
stacksize = 800

[tasks.update_server]
name = "stm32h7-update-server"
priority = 2
max-sizes = {flash = 16384, ram = 4096}
stacksize = 2048
start = true
uses = ["flash_controller"]
extern-regions = ["bank2"]
interrupts = {"flash_controller.irq" = "flash-irq"}
notifications = ["flash-irq"]

[tasks.idle]
name = "task-idle"
priority = 8
Expand Down
30 changes: 30 additions & 0 deletions app/minibar/rev-b.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,29 @@ extern-regions = [ "sram1", "sram2", "sram3", "sram4" ]
notifications = ["socket"]
features = ["net", "vlan"]

# Rev A boards had a hardware bug that kept the minibar's SP from being
# reachable over the management network, therefore we only include
# control-plane-agent for rev B.
[tasks.control_plane_agent]
name = "task-control-plane-agent"
priority = 7
stacksize = 8000
start = true
task-slots = [
"jefe",
"net",
"sys",
"packrat",
"sensor",
"sprot",
"ignition",
"validate",
"update_server",
"dump_agent",
]
features = ["minibar", "vlan"]
notifications = ["socket", "timer"]


# VLAN configuration
[config.net.vlans.port1]
Expand All @@ -76,3 +99,10 @@ port = 11113
tx = { packets = 3, bytes = 1024 }
rx = { packets = 3, bytes = 1024 }

[config.net.sockets.control_plane_agent]
kind = "udp"
owner = {name = "control_plane_agent", notification = "socket"}
port = 11111
tx = { packets = 3, bytes = 2048 }
rx = { packets = 3, bytes = 2048 }

1 change: 1 addition & 0 deletions task/control-plane-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ gimlet = ["compute-sled"]
cosmo = ["compute-sled"]
sidecar = ["drv-sidecar-seq-api", "drv-monorail-api", "drv-ignition-api", "drv-transceivers-api", "p256", "sha2", "drv-rng-api"]
psc = ["drv-user-leds-api"]
minibar = ["drv-ignition-api"]
vpd = ["task-vpd-api"]
vlan = ["task-net-api/vlan"]

Expand Down
207 changes: 207 additions & 0 deletions task/control-plane-agent/src/ignition_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use core::cell::Cell;
use drv_ignition_api::{
AllLinkEventsIter, AllPortsIter, Ignition, IgnitionError,
};
use gateway_messages::ignition::{
IgnitionState, LinkEvents, ReceiverStatus, SystemFaults, SystemPowerState,
SystemType, TargetState, TransceiverEvents,
};

use super::IGNITION;

pub(super) struct IgnitionController {
task: Ignition,
num_ports: Cell<Option<u32>>,
}

impl IgnitionController {
pub(super) fn new() -> Self {
Self {
task: Ignition::new(IGNITION.get_task_id()),
num_ports: Cell::new(None),
}
}

pub(super) fn num_ports(&self) -> Result<u32, IgnitionError> {
if let Some(n) = self.num_ports.get() {
return Ok(n);
}

let n = u32::from(self.task.port_count()?);
self.num_ports.set(Some(n));
Ok(n)
}

pub(super) fn target_state(
&self,
target: u8,
) -> Result<IgnitionState, IgnitionError> {
let port = self.task.port(target)?;
Ok(PortConvert(port).into())
}

pub(super) fn bulk_state(
&self,
offset: u32,
) -> Result<BulkIgnitionStateIter, IgnitionError> {
let iter = self.task.all_ports()?;
Ok(BulkIgnitionStateIter {
iter: iter.skip(offset as usize),
})
}

pub(super) fn target_link_events(
&self,
target: u8,
) -> Result<LinkEvents, IgnitionError> {
let events = self.task.link_events(target)?;
Ok(LinkEventsConvert(events).into())
}

pub(super) fn bulk_link_events(
&self,
offset: u32,
) -> Result<BulkIgnitionLinkEventsIter, IgnitionError> {
let iter = self.task.all_link_events()?;
Ok(BulkIgnitionLinkEventsIter {
iter: iter.skip(offset as usize),
})
}
}

pub struct BulkIgnitionStateIter {
iter: core::iter::Skip<AllPortsIter>,
}

impl Iterator for BulkIgnitionStateIter {
type Item = IgnitionState;

fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|state| PortConvert(state).into())
}
}

pub struct BulkIgnitionLinkEventsIter {
iter: core::iter::Skip<AllLinkEventsIter>,
}

impl Iterator for BulkIgnitionLinkEventsIter {
type Item = LinkEvents;

fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|events| LinkEventsConvert(events).into())
}
}

struct PortConvert(drv_ignition_api::Port);

impl From<PortConvert> for IgnitionState {
fn from(port: PortConvert) -> Self {
let PortConvert(port) = port;
Self {
receiver: ReceiverStatusConvert(port.receiver_status).into(),
target: port.target.map(|t| TargetConvert(t).into()),
}
}
}

struct ReceiverStatusConvert(drv_ignition_api::ReceiverStatus);

impl From<ReceiverStatusConvert> for ReceiverStatus {
fn from(s: ReceiverStatusConvert) -> Self {
Self {
aligned: s.0.aligned,
locked: s.0.locked,
polarity_inverted: s.0.polarity_inverted,
}
}
}

struct TargetConvert(drv_ignition_api::Target);

impl From<TargetConvert> for TargetState {
fn from(target: TargetConvert) -> Self {
let TargetConvert(target) = target;
Self {
// Minibar uses SystemId(u8), convert to SystemType via u16
system_type: SystemType::from(u16::from(target.id.0)),
power_state: SystemPowerStateConvert(target.power_state).into(),
power_reset_in_progress: target.power_reset_in_progress,
controller0_present: target.controller0_present,
controller1_present: target.controller1_present,
link0_receiver_status: ReceiverStatusConvert(
target.link0_receiver_status,
)
.into(),
link1_receiver_status: ReceiverStatusConvert(
target.link1_receiver_status,
)
.into(),
faults: SystemFaultsConvert(target.faults).into(),
}
}
}

struct SystemPowerStateConvert(drv_ignition_api::SystemPowerState);

impl From<SystemPowerStateConvert> for SystemPowerState {
fn from(s: SystemPowerStateConvert) -> Self {
match s.0 {
drv_ignition_api::SystemPowerState::Off => Self::Off,
drv_ignition_api::SystemPowerState::On => Self::On,
drv_ignition_api::SystemPowerState::PoweringOff => {
Self::PoweringOff
}
drv_ignition_api::SystemPowerState::PoweringOn => Self::PoweringOn,
drv_ignition_api::SystemPowerState::Aborted => Self::Aborted,
}
}
}

struct SystemFaultsConvert(drv_ignition_api::SystemFaults);

impl From<SystemFaultsConvert> for SystemFaults {
fn from(faults: SystemFaultsConvert) -> Self {
Self {
power_a3: faults.0.power_a3,
power_a2: faults.0.power_a2,
sp: faults.0.sp,
rot: faults.0.rot,
}
}
}

struct LinkEventsConvert(drv_ignition_api::LinkEvents);

impl From<LinkEventsConvert> for LinkEvents {
fn from(events: LinkEventsConvert) -> Self {
Self {
controller: TransceiverEventsConvert(events.0.controller).into(),
target_link0: TransceiverEventsConvert(events.0.target_link0)
.into(),
target_link1: TransceiverEventsConvert(events.0.target_link1)
.into(),
}
}
}

struct TransceiverEventsConvert(drv_ignition_api::TransceiverEvents);

impl From<TransceiverEventsConvert> for TransceiverEvents {
fn from(events: TransceiverEventsConvert) -> Self {
Self {
encoding_error: events.0.encoding_error,
decoding_error: events.0.decoding_error,
ordered_set_invalid: events.0.ordered_set_invalid,
message_version_invalid: events.0.message_version_invalid,
message_type_invalid: events.0.message_type_invalid,
message_checksum_invalid: events.0.message_checksum_invalid,
}
}
}
16 changes: 13 additions & 3 deletions task/control-plane-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ mod update;

pub(crate) mod dump;

// If the build system enables multiple of the gimlet/sidecar/psc features, this
// If the build system enables multiple of the gimlet/sidecar/psc/minibar features, this
// sequence of `cfg_attr`s will trigger an unused_attributes warning. We build
// everything with -Dunused_attributes, which will catch any such build system
// misconfiguration.
#[cfg_attr(feature = "compute-sled", path = "mgs_compute_sled.rs")]
#[cfg_attr(feature = "sidecar", path = "mgs_sidecar.rs")]
#[cfg_attr(feature = "psc", path = "mgs_psc.rs")]
#[cfg_attr(feature = "minibar", path = "mgs_minibar.rs")]
mod mgs_handler;

use self::mgs_handler::MgsHandler;
Expand Down Expand Up @@ -259,12 +260,21 @@ impl ServerImpl {

impl NotificationHandler for ServerImpl {
fn current_notification_mask(&self) -> u32 {
notifications::SOCKET_MASK
#[cfg(not(feature = "minibar"))]
let mask = notifications::SOCKET_MASK
| notifications::USART_IRQ_MASK
| notifications::TIMER_MASK
| notifications::TIMER_MASK;

// Minibar does not configure USART for serial console, so omit it
// from the mask.
#[cfg(feature = "minibar")]
let mask = notifications::SOCKET_MASK | notifications::TIMER_MASK;

mask
}

fn handle_notification(&mut self, bits: userlib::NotificationBits) {
#[cfg(not(feature = "minibar"))]
if bits.check_notification_mask(notifications::USART_IRQ_MASK) {
self.mgs_handler.drive_usart();
}
Expand Down
Loading