Initial MCTP core code
Just a skeleton of the MCTP library at present.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/core.c b/core.c
new file mode 100644
index 0000000..575d14f
--- /dev/null
+++ b/core.c
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "core: " fmt
+
+#include "libmctp.h"
+#include "libmctp-alloc.h"
+#include "libmctp-log.h"
+
+/* Internal data structures */
+
+struct mctp_bus {
+ mctp_eid_t eid;
+ struct mctp_binding *binding;
+
+ /* todo: routing */
+};
+
+struct mctp {
+ /* todo: multiple busses */
+ struct mctp_bus busses[1];
+
+ struct mctp_pktbuf txbuf;
+
+ /* Message RX callback */
+ mctp_rx_fn message_rx;
+ void *message_rx_data;
+};
+
+#ifndef BUILD_ASSERT
+#define BUILD_ASSERT(x) \
+ do { (void)sizeof(char[0-(!(x))]); } while (0)
+#endif
+
+struct mctp_pktbuf *mctp_pktbuf_alloc(uint8_t len)
+{
+ struct mctp_pktbuf *buf;
+
+ BUILD_ASSERT(MCTP_PKTBUF_SIZE <= 0xff);
+
+ /* todo: pools */
+ buf = __mctp_alloc(sizeof(*buf));
+
+ buf->start = MCTP_PKTBUF_BINDING_PAD;
+ buf->end = buf->start + len;
+ buf->mctp_hdr_off = buf->start;
+
+ return buf;
+}
+
+void mctp_pktbuf_free(struct mctp_pktbuf *pkt)
+{
+ __mctp_free(pkt);
+}
+
+struct mctp_hdr *mctp_pktbuf_hdr(struct mctp_pktbuf *pkt)
+{
+ return (void *)pkt->data + pkt->mctp_hdr_off;
+}
+
+void *mctp_pktbuf_data(struct mctp_pktbuf *pkt)
+{
+ return (void *)pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr);
+}
+
+uint8_t mctp_pktbuf_size(struct mctp_pktbuf *pkt)
+{
+ return pkt->end - pkt->start;
+}
+
+void *mctp_pktbuf_alloc_start(struct mctp_pktbuf *pkt, uint8_t size)
+{
+ assert(size <= pkt->start);
+ pkt->start -= size;
+ return pkt->data + pkt->start;
+}
+
+void *mctp_pktbuf_alloc_end(struct mctp_pktbuf *pkt, uint8_t size)
+{
+ void *buf;
+
+ assert(size < (MCTP_PKTBUF_SIZE - pkt->end));
+ buf = pkt->data + pkt->end;
+ pkt->end += size;
+ return buf;
+}
+
+int mctp_pktbuf_push(struct mctp_pktbuf *pkt, void *data, uint8_t len)
+{
+ void *p;
+
+ assert(pkt->end + len <= MCTP_PKTBUF_SIZE);
+
+ if (pkt->end + len > MCTP_PKTBUF_SIZE)
+ return -1;
+
+ p = pkt->data + pkt->end;
+
+ pkt->end += len;
+ memcpy(p, data, len);
+
+ return 0;
+}
+
+struct mctp *mctp_init(void)
+{
+ struct mctp *mctp;
+
+ mctp = __mctp_alloc(sizeof(*mctp));
+ memset(mctp, 0, sizeof(*mctp));
+
+ return mctp;
+}
+
+int mctp_set_rx_all(struct mctp *mctp, mctp_rx_fn fn, void *data)
+{
+ mctp->message_rx = fn;
+ mctp->message_rx_data = data;
+ return 0;
+}
+
+static struct mctp_bus *find_bus_for_eid(struct mctp *mctp,
+ mctp_eid_t dest __attribute__((unused)))
+{
+ return &mctp->busses[0];
+}
+
+unsigned long mctp_register_bus(struct mctp *mctp,
+ struct mctp_binding *binding,
+ mctp_eid_t eid)
+{
+ assert(!mctp->busses[0].binding);
+ mctp->busses[0].binding = binding;
+ mctp->busses[0].eid = eid;
+ return 0;
+}
+
+void mctp_bus_rx(struct mctp *mctp, unsigned long bus_id,
+ struct mctp_pktbuf *pkt)
+{
+ struct mctp_bus *bus = &mctp->busses[bus_id];
+ size_t len;
+ void *p;
+
+ len = pkt->end - pkt->mctp_hdr_off - sizeof(struct mctp_hdr);
+ p = pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr),
+ mctp->message_rx(bus->eid, mctp->message_rx_data, p, len);
+}
+
+static int mctp_packet_tx(struct mctp *mctp __attribute__((unused)),
+ struct mctp_bus *bus,
+ struct mctp_pktbuf *pkt)
+{
+ return bus->binding->tx(bus->binding, pkt);
+}
+
+int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid,
+ void *msg, size_t msg_len)
+{
+ struct mctp_pktbuf *pkt;
+ struct mctp_hdr *hdr;
+ struct mctp_bus *bus;
+ int rc;
+
+ /* todo: multiple-packet messages, sequence numbers */
+ assert(msg_len <= MCTP_MTU);
+
+ bus = find_bus_for_eid(mctp, eid);
+
+ pkt = mctp_pktbuf_alloc(msg_len + sizeof(*hdr));
+ hdr = mctp_pktbuf_hdr(pkt);
+
+ /* todo: tags */
+ hdr->ver = bus->binding->version & 0xf;
+ hdr->dest = eid;
+ hdr->src = bus->eid;
+ hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
+ MCTP_HDR_FLAG_EOM |
+ (0 << MCTP_HDR_SEQ_SHIFT) |
+ MCTP_HDR_FLAG_TO |
+ (0 << MCTP_HDR_TAG_SHIFT);
+
+ /* todo: zero copy? */
+ memcpy(mctp_pktbuf_data(pkt), msg, msg_len);
+
+ rc = mctp_packet_tx(mctp, bus, pkt);
+
+ return rc;
+}