7 #include <satcat5/ethernet.h>
8 #include <satcat5/eth_dispatch.h>
10 #include <satcat5/net_cfgbus.h>
11 #include <satcat5/udp_core.h>
12 #include <satcat5/udp_dispatch.h>
14 namespace log = satcat5::log;
20 static const unsigned DEBUG_VERBOSE = 0;
23 static const u8 OPMASK_CMD = 0xF0;
24 static const u8 OPMASK_WREN = 0x0F;
25 static const u8 OPCODE_NOOP = 0x00;
26 static const u8 OPCODE_WRITE0 = 0x20;
27 static const u8 OPCODE_WRITE1 = 0x30;
28 static const u8 OPCODE_READ0 = 0x40;
29 static const u8 OPCODE_READ1 = 0x50;
32 static const Type TYPE_ETH_CMD =
33 Type(satcat5::eth::ETYPE_CFGBUS_CMD.value);
34 static const Type TYPE_ETH_ACK =
35 Type(satcat5::eth::ETYPE_CFGBUS_ACK.value);
36 static const Type TYPE_UDP_CMD =
37 Type(satcat5::udp::PORT_CFGBUS_CMD.value);
38 static const Type TYPE_UDP_ACK =
39 Type(satcat5::udp::PORT_CFGBUS_ACK.value);
43 #ifndef SATCAT5_PROTOCFG_SUPPORT_WRMASK
44 #define SATCAT5_PROTOCFG_SUPPORT_WRMASK 0
48 inline void write_mask(
volatile u32* reg, u32 val, u8 mask)
50 #if SATCAT5_PROTOCFG_SUPPORT_WRMASK
53 volatile u8* reg8 = (
volatile u8*)ptr;
54 if (satcat5::HOST_BYTE_ORDER() == satcat5::SATCAT5_BIG_ENDIAN) {
55 if (mask & 0x08) reg8[0] = val8[0];
56 if (mask & 0x04) reg8[1] = val8[1];
57 if (mask & 0x02) reg8[2] = val8[2];
58 if (mask & 0x01) reg8[3] = val8[3];
60 if (mask & 0x01) reg8[0] = val8[0];
61 if (mask & 0x02) reg8[1] = val8[1];
62 if (mask & 0x04) reg8[2] = val8[2];
63 if (mask & 0x08) reg8[3] = val8[3];
68 satcat5::eth::ProtoConfig::ProtoConfig(
73 cfg, iface, TYPE_ETH_CMD, TYPE_ETH_ACK, max_devices)
78 satcat5::udp::ProtoConfig::ProtoConfig(
83 cfg, iface, TYPE_UDP_CMD, TYPE_UDP_ACK, max_devices)
88 ProtoConfig::ProtoConfig(
98 , m_max_devices(max_devices)
103 #if SATCAT5_ALLOW_DELETION
114 log::Log(log::ERROR,
"ProtoConfig: Invalid command");
123 u32 addr = src.read_u32();
125 u8 cmd = opcode & OPMASK_CMD;
126 u8 wren = opcode & OPMASK_WREN;
127 unsigned cmd_len = 1 + (unsigned)len8;
130 if (DEBUG_VERBOSE > 0) {
131 log::Log(log::DEBUG,
"ProtoConfig: Received command")
136 unsigned reply_bytes = 8;
137 if (cmd == OPCODE_READ0 || cmd == OPCODE_READ1) {
138 reply_bytes += 4*cmd_len + 1;
144 log::Log(log::WARNING,
"ProtoConfig: Reply error");
153 dst->write_u32(addr);
157 u32 devaddr = (addr / REGS_PER_DEVICE);
158 u32 regaddr = (addr % REGS_PER_DEVICE);
161 const char* errmsg = 0;
162 if (cmd == OPCODE_NOOP) {
165 || regaddr >= REGS_PER_DEVICE
166 || regaddr + cmd_len > REGS_PER_DEVICE) {
167 errmsg =
"Bad address";
168 }
else if ((cmd == OPCODE_WRITE0 || cmd == OPCODE_WRITE1) && wren) {
171 errmsg =
"Bad length";
172 }
else if (SATCAT5_PROTOCFG_SUPPORT_WRMASK && wren < OPMASK_WREN) {
173 for (
unsigned a = 0 ; a < cmd_len ; ++a) {
174 write_mask(regptr, src.read_u32(), wren);
175 if (cmd == OPCODE_WRITE1) ++regptr;
178 for (
unsigned a = 0 ; a < cmd_len ; ++a) {
179 *regptr = src.read_u32();
180 if (cmd == OPCODE_WRITE1) ++regptr;
183 }
else if ((cmd == OPCODE_READ0 || cmd == OPCODE_READ1) && !wren) {
185 for (
unsigned a = 0 ; a < cmd_len ; ++a) {
186 dst->write_u32(*regptr);
187 if (cmd == OPCODE_READ1) ++regptr;
192 errmsg =
"Bad opcode";
200 if (ok && DEBUG_VERBOSE > 1) {
201 log::Log(log::DEBUG,
"ProtoConfig: Sent response")
204 if (!ok) errmsg =
"Reply error";
208 if (errmsg)
log::Log(log::ERROR,
"ProtoConfig: ").
write(errmsg);
ConfigBus core definitions.
const unsigned REGS_PER_DEVICE
Fixed ConfigBus gateware interface parameters.
Memory-mapped local ConfigBus.
volatile u32 * get_register_mmap(unsigned addr) const
Get a raw pointer to the designated combined-address.
Implemention of "net::Dispatch" for Ethernet frames.
Limited read of next N bytes.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
u8 read_u8()
One of many functions for reading integer/floating point values, see details.
Abstract API for writing byte-streams and packets.
virtual void write_abort()
If possible, abort the current partially-written packet.
void write_u8(u8 data)
One of many functions for writing integer/floating point values, see details.
virtual bool write_finalize()
Mark end of frame and release temporary working data.
The Log class creates and formats one log message.
Log & write(const char *str)
Formatting methods for various data types.
The "Dispatch" is a generic interface that knows how to read a designated protocol layer and sort inc...
void add(satcat5::net::Protocol *proto)
Register a Protocol object.
virtual satcat5::io::Writeable * open_reply(const satcat5::net::Type &type, unsigned len)=0
Open a reply to the sender of the most recent message by writing frame header(s) and returning a stre...
void remove(satcat5::net::Protocol *proto)
Unregister a Protocol object.
Handler for ConfigBus network commands.
~ProtoConfig() SATCAT5_OPTIONAL_DTOR
Only children can access constructor/destructor.
satcat5::cfg::ConfigBusMmap *const m_cfg
ConfigBus instance.
void frame_rcvd(satcat5::io::LimitedRead &src) override
Event handler to process incoming frames and respond.
satcat5::net::Dispatch *const m_iface
Registered iface.
satcat5::net::Type const m_acktype
Type for replies.
const unsigned m_max_devices
Max # of devices.
A net::Protocol is the counterpart to net::Dispatch that handles a particular data stream,...
Dispatcher sorts incoming UDP messages by port index.
Diagnostic logging to UART and/or Ethernet ports.
Multipurpose filter for matching fields in network packets.