blob: e95673a537cbf3844505439139cbd71d6deaa3cb [file] [log] [blame]
Andrew Jeffery0247c732020-02-06 11:48:52 +10301/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10303#ifdef HAVE_CONFIG_H
Andrew Jeffery0247c732020-02-06 11:48:52 +10304#include "config.h"
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10305#endif
6
Andrew Jefferydf5f6b92020-05-12 21:39:06 +09307#include "astlpc.c"
8
9#ifdef pr_fmt
10#undef pr_fmt
11#define pr_fmt(x) "test: " x
12#endif
13
Andrew Jeffery0247c732020-02-06 11:48:52 +103014#include "libmctp-astlpc.h"
15#include "libmctp-log.h"
Przemyslaw Czarnowskiff25d7e2020-03-26 11:39:37 +010016#include "container_of.h"
Andrew Jeffery0247c732020-02-06 11:48:52 +103017
18#ifdef NDEBUG
19#undef NDEBUG
20#endif
21
22#define RX_BUFFER_DATA 0x100 + 4 + 4
23
24#include <assert.h>
25#include <stdint.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
Andrew Jeffery0247c732020-02-06 11:48:52 +103030struct mctp_binding_astlpc_mmio {
31 struct mctp_binding_astlpc astlpc;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093032 bool bmc;
Andrew Jeffery0247c732020-02-06 11:48:52 +103033
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093034 uint8_t (*kcs)[2];
Andrew Jeffery0247c732020-02-06 11:48:52 +103035
36 size_t lpc_size;
37 uint8_t *lpc;
38};
39
Andrew Jeffery0247c732020-02-06 11:48:52 +103040#define binding_to_mmio(b) \
41 container_of(b, struct mctp_binding_astlpc_mmio, astlpc)
42
Andrew Jeffery53ea1472020-05-23 21:06:24 +093043static int mctp_astlpc_mmio_kcs_read(void *data,
44 enum mctp_binding_astlpc_kcs_reg reg,
45 uint8_t *val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103046{
47 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
48
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093049 *val = (*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103050
51 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val, reg ? "status" : "data");
52
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093053 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
54 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
55 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
56 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103057
58 return 0;
59}
60
Andrew Jeffery53ea1472020-05-23 21:06:24 +093061static int mctp_astlpc_mmio_kcs_write(void *data,
62 enum mctp_binding_astlpc_kcs_reg reg,
63 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103064{
65 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093066 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103067
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093068 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
69 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103070
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093071 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
72 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
73 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
74 }
75
76 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103077 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093078 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103079 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093080 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +103081
82 mctp_prdebug("%s: 0x%hhx to %s", __func__, val, reg ? "status" : "data");
83
84 return 0;
85}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +103086int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +103087{
88 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
89
Andrew Jeffery1dbf0212020-05-12 13:53:50 +093090 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
91
Andrew Jeffery06b2cd82020-03-17 23:12:27 +103092 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +103093 assert(offset + len < mmio->lpc_size);
94
95 memcpy(buf, mmio->lpc + offset, len);
96
Andrew Jeffery0247c732020-02-06 11:48:52 +103097 return 0;
98}
99
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030100int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030101{
102 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
103
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930104 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
105
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030106 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030107 assert(offset + len < mmio->lpc_size);
108
109 memcpy(mmio->lpc + offset, buf, len);
110
Andrew Jeffery0247c732020-02-06 11:48:52 +1030111 return 0;
112}
113
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930114#define __unused __attribute__((unused))
115
116static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
117 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030118{
119 uint8_t type;
120
121 type = *(uint8_t *)msg;
122
123 mctp_prdebug("MCTP message received: len %zd, type %d",
124 len, type);
125}
126
Andrew Jeffery53ea1472020-05-23 21:06:24 +0930127static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030128 .kcs_read = mctp_astlpc_mmio_kcs_read,
129 .kcs_write = mctp_astlpc_mmio_kcs_write,
130 .lpc_read = mctp_astlpc_mmio_lpc_read,
131 .lpc_write = mctp_astlpc_mmio_lpc_write,
132};
133
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930134struct astlpc_endpoint {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030135 struct mctp_binding_astlpc_mmio mmio;
136 struct mctp_binding_astlpc *astlpc;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030137 struct mctp *mctp;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930138};
139
140static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
141 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
142 size_t lpc_size)
143{
144 /*
145 * Configure the direction of the KCS interface so we know whether to
146 * set or clear IBF or OBF on writes or reads.
147 */
148 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
149
150 ep->mctp = mctp_init();
151 assert(ep->mctp);
152
153 mctp_set_rx_all(ep->mctp, rx_message, NULL);
154
155 /* Inject KCS registers */
156 ep->mmio.kcs = kcs;
157
158 /* Inject the heap allocation as the LPC mapping */
159 ep->mmio.lpc_size = lpc_size;
160 ep->mmio.lpc = lpc_mem;
161
162 /* Initialise the binding */
163 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, NULL,
164 &mctp_binding_astlpc_mmio_ops, &ep->mmio);
165
166 mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
167}
168
169static void endpoint_destroy(struct astlpc_endpoint *ep)
170{
171 mctp_astlpc_destroy(ep->astlpc);
172 mctp_destroy(ep->mctp);
173}
174
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930175struct astlpc_test {
176 struct astlpc_endpoint bmc;
177 struct astlpc_endpoint host;
178 uint8_t kcs[2];
179 uint8_t *lpc_mem;
180};
181
182static void network_init(struct astlpc_test *ctx)
183{
184 const size_t lpc_size = 1 * 1024 * 1024;
185
186 ctx->lpc_mem = calloc(1, lpc_size);
187 assert(ctx->lpc_mem);
188
189 /* BMC initialisation */
190 endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx->kcs,
191 ctx->lpc_mem, lpc_size);
192
193 /* Host initialisation */
194 endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &ctx->kcs,
195 ctx->lpc_mem, lpc_size);
196
197 /* BMC processes host channel init request, alerts host */
198 mctp_astlpc_poll(ctx->bmc.astlpc);
199 assert(ctx->kcs[KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
200 assert(ctx->kcs[KCS_REG_DATA] == 0xff);
201
202 /* Host dequeues channel init result */
203 mctp_astlpc_poll(ctx->host.astlpc);
204}
205
206static void network_destroy(struct astlpc_test *ctx)
207{
208 endpoint_destroy(&ctx->bmc);
209 endpoint_destroy(&ctx->host);
210 free(ctx->lpc_mem);
211}
212
Andrew Jefferye756de82020-05-22 12:30:58 +0930213static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930214{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930215 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930216 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030217 int rc;
218
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930219 /* Test harness initialisation */
220
Andrew Jeffery0247c732020-02-06 11:48:52 +1030221 memset(&msg[0], 0x5a, MCTP_BTU);
222 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
223
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930224 network_init(&ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030225
226 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930227 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030228 assert(rc == 0);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930229 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
230 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030231
232 /* Verify it's the packet we expect */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930233 assert(!memcmp(ctx.lpc_mem + RX_BUFFER_DATA, &msg[0], MCTP_BTU));
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930234
235 /* Host receives a packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930236 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030237
238 /* Host returns Rx area ownership to BMC */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930239 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
240 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
241 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030242
243 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930244 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030245 assert(rc == 0);
246
247 /* Host receives a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930248 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
249 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030250
251 /* Verify it's the packet we expect */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930252 assert(!memcmp(ctx.lpc_mem + RX_BUFFER_DATA, &msg[MCTP_BTU], MCTP_BTU));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030253
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930254 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930255}
256
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930257static void astlpc_test_simple_init(void)
258{
259 struct astlpc_endpoint bmc, host;
260 uint8_t kcs[2] = { 0 };
261 size_t lpc_size;
262 void *lpc_mem;
263
264 /* Test harness initialisation */
265 lpc_size = 1 * 1024 * 1024;
266 lpc_mem = calloc(1, lpc_size);
267 assert(lpc_mem);
268
269 /* Bus owner (BMC) initialisation */
270 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
271 lpc_size);
272
273 /* Verify the BMC binding was initialised */
274 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
275
276 /* Device (Host) initialisation */
277 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
278 lpc_size);
279
280 /* Host sends channel init command */
281 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
282 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
283
284 /* BMC receives host channel init request */
285 mctp_astlpc_poll(bmc.astlpc);
286
287 /* BMC sends init response */
288 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
289 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
290 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
291
292 /* Host dequeues data */
293 mctp_astlpc_poll(host.astlpc);
294
295 endpoint_destroy(&bmc);
296 endpoint_destroy(&host);
297 free(lpc_mem);
298}
299
Andrew Jefferye756de82020-05-22 12:30:58 +0930300int main(void)
301{
302 mctp_set_log_stdio(MCTP_LOG_DEBUG);
303
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930304 astlpc_test_simple_init();
Andrew Jefferye756de82020-05-22 12:30:58 +0930305 astlpc_test_packetised_message_bmc_to_host();
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030306
Andrew Jeffery0247c732020-02-06 11:48:52 +1030307 return 0;
308}