blob: c2cbba2f17d80063884c78240206ea51d3840bec [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 Jefferye756de82020-05-22 12:30:58 +0930175static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930176{
177 uint8_t msg[2 * MCTP_BTU];
178 struct astlpc_endpoint bmc, host;
179 size_t lpc_size;
180 uint8_t kcs[2] = { 0 };
181 void *lpc_mem;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030182 int rc;
183
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930184 /* Test harness initialisation */
185
Andrew Jeffery0247c732020-02-06 11:48:52 +1030186 memset(&msg[0], 0x5a, MCTP_BTU);
187 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
188
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930189 lpc_size = 1 * 1024 * 1024;
190 lpc_mem = calloc(1, lpc_size);
191 assert(lpc_mem);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030192
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930193 /* BMC initialisation */
194 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
195 lpc_size);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030196
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930197 /* Verify the BMC binding was initialised */
198 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030199
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930200 /* Host initialisation */
201 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
202 lpc_size);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030203
Andrew Jeffery0247c732020-02-06 11:48:52 +1030204 /* Host sends channel init command */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930205 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
206 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030207
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930208 /* BMC receives host channel init request */
209 mctp_astlpc_poll(bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030210
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930211 /* BMC sends init response */
212 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
213 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
214 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030215
216 /* Host dequeues data */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930217 mctp_astlpc_poll(host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030218
219 /* BMC sends a message */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930220 rc = mctp_message_tx(bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030221 assert(rc == 0);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930222 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
223 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030224
225 /* Verify it's the packet we expect */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930226 assert(!memcmp(lpc_mem + RX_BUFFER_DATA, &msg[0], MCTP_BTU));
227
228 /* Host receives a packet */
229 mctp_astlpc_poll(host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030230
231 /* Host returns Rx area ownership to BMC */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930232 assert(!(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
233 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
234 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030235
236 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930237 rc = mctp_astlpc_poll(bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030238 assert(rc == 0);
239
240 /* Host receives a message */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930241 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
242 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030243
244 /* Verify it's the packet we expect */
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930245 assert(!memcmp(lpc_mem + RX_BUFFER_DATA, &msg[MCTP_BTU], MCTP_BTU));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030246
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930247 endpoint_destroy(&bmc);
248 endpoint_destroy(&host);
249 free(lpc_mem);
Andrew Jefferye756de82020-05-22 12:30:58 +0930250}
251
252int main(void)
253{
254 mctp_set_log_stdio(MCTP_LOG_DEBUG);
255
256 astlpc_test_packetised_message_bmc_to_host();
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030257
Andrew Jeffery0247c732020-02-06 11:48:52 +1030258 return 0;
259}