blob: 575d14f6342a1616961320bb2210a908c65e55e5 [file] [log] [blame]
Jeremy Kerr4cdc2002019-02-07 16:49:12 +08001/* SPDX-License-Identifier: Apache-2.0 */
2
3#include <assert.h>
4#include <stdarg.h>
5#include <stddef.h>
6#include <stdint.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#undef pr_fmt
12#define pr_fmt(fmt) "core: " fmt
13
14#include "libmctp.h"
15#include "libmctp-alloc.h"
16#include "libmctp-log.h"
17
18/* Internal data structures */
19
20struct mctp_bus {
21 mctp_eid_t eid;
22 struct mctp_binding *binding;
23
24 /* todo: routing */
25};
26
27struct mctp {
28 /* todo: multiple busses */
29 struct mctp_bus busses[1];
30
31 struct mctp_pktbuf txbuf;
32
33 /* Message RX callback */
34 mctp_rx_fn message_rx;
35 void *message_rx_data;
36};
37
38#ifndef BUILD_ASSERT
39#define BUILD_ASSERT(x) \
40 do { (void)sizeof(char[0-(!(x))]); } while (0)
41#endif
42
43struct mctp_pktbuf *mctp_pktbuf_alloc(uint8_t len)
44{
45 struct mctp_pktbuf *buf;
46
47 BUILD_ASSERT(MCTP_PKTBUF_SIZE <= 0xff);
48
49 /* todo: pools */
50 buf = __mctp_alloc(sizeof(*buf));
51
52 buf->start = MCTP_PKTBUF_BINDING_PAD;
53 buf->end = buf->start + len;
54 buf->mctp_hdr_off = buf->start;
55
56 return buf;
57}
58
59void mctp_pktbuf_free(struct mctp_pktbuf *pkt)
60{
61 __mctp_free(pkt);
62}
63
64struct mctp_hdr *mctp_pktbuf_hdr(struct mctp_pktbuf *pkt)
65{
66 return (void *)pkt->data + pkt->mctp_hdr_off;
67}
68
69void *mctp_pktbuf_data(struct mctp_pktbuf *pkt)
70{
71 return (void *)pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr);
72}
73
74uint8_t mctp_pktbuf_size(struct mctp_pktbuf *pkt)
75{
76 return pkt->end - pkt->start;
77}
78
79void *mctp_pktbuf_alloc_start(struct mctp_pktbuf *pkt, uint8_t size)
80{
81 assert(size <= pkt->start);
82 pkt->start -= size;
83 return pkt->data + pkt->start;
84}
85
86void *mctp_pktbuf_alloc_end(struct mctp_pktbuf *pkt, uint8_t size)
87{
88 void *buf;
89
90 assert(size < (MCTP_PKTBUF_SIZE - pkt->end));
91 buf = pkt->data + pkt->end;
92 pkt->end += size;
93 return buf;
94}
95
96int mctp_pktbuf_push(struct mctp_pktbuf *pkt, void *data, uint8_t len)
97{
98 void *p;
99
100 assert(pkt->end + len <= MCTP_PKTBUF_SIZE);
101
102 if (pkt->end + len > MCTP_PKTBUF_SIZE)
103 return -1;
104
105 p = pkt->data + pkt->end;
106
107 pkt->end += len;
108 memcpy(p, data, len);
109
110 return 0;
111}
112
113struct mctp *mctp_init(void)
114{
115 struct mctp *mctp;
116
117 mctp = __mctp_alloc(sizeof(*mctp));
118 memset(mctp, 0, sizeof(*mctp));
119
120 return mctp;
121}
122
123int mctp_set_rx_all(struct mctp *mctp, mctp_rx_fn fn, void *data)
124{
125 mctp->message_rx = fn;
126 mctp->message_rx_data = data;
127 return 0;
128}
129
130static struct mctp_bus *find_bus_for_eid(struct mctp *mctp,
131 mctp_eid_t dest __attribute__((unused)))
132{
133 return &mctp->busses[0];
134}
135
136unsigned long mctp_register_bus(struct mctp *mctp,
137 struct mctp_binding *binding,
138 mctp_eid_t eid)
139{
140 assert(!mctp->busses[0].binding);
141 mctp->busses[0].binding = binding;
142 mctp->busses[0].eid = eid;
143 return 0;
144}
145
146void mctp_bus_rx(struct mctp *mctp, unsigned long bus_id,
147 struct mctp_pktbuf *pkt)
148{
149 struct mctp_bus *bus = &mctp->busses[bus_id];
150 size_t len;
151 void *p;
152
153 len = pkt->end - pkt->mctp_hdr_off - sizeof(struct mctp_hdr);
154 p = pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr),
155 mctp->message_rx(bus->eid, mctp->message_rx_data, p, len);
156}
157
158static int mctp_packet_tx(struct mctp *mctp __attribute__((unused)),
159 struct mctp_bus *bus,
160 struct mctp_pktbuf *pkt)
161{
162 return bus->binding->tx(bus->binding, pkt);
163}
164
165int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid,
166 void *msg, size_t msg_len)
167{
168 struct mctp_pktbuf *pkt;
169 struct mctp_hdr *hdr;
170 struct mctp_bus *bus;
171 int rc;
172
173 /* todo: multiple-packet messages, sequence numbers */
174 assert(msg_len <= MCTP_MTU);
175
176 bus = find_bus_for_eid(mctp, eid);
177
178 pkt = mctp_pktbuf_alloc(msg_len + sizeof(*hdr));
179 hdr = mctp_pktbuf_hdr(pkt);
180
181 /* todo: tags */
182 hdr->ver = bus->binding->version & 0xf;
183 hdr->dest = eid;
184 hdr->src = bus->eid;
185 hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
186 MCTP_HDR_FLAG_EOM |
187 (0 << MCTP_HDR_SEQ_SHIFT) |
188 MCTP_HDR_FLAG_TO |
189 (0 << MCTP_HDR_TAG_SHIFT);
190
191 /* todo: zero copy? */
192 memcpy(mctp_pktbuf_data(pkt), msg, msg_len);
193
194 rc = mctp_packet_tx(mctp, bus, pkt);
195
196 return rc;
197}