1 /* $OpenBSD: rtkit.c,v 1.3 2022/01/10 09:07:28 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_misc.h> 28 #include <dev/ofw/fdt.h> 29 30 #include <arm64/dev/aplmbox.h> 31 #include <arm64/dev/rtkit.h> 32 33 #define RTKIT_EP_MGMT 0 34 #define RTKIT_EP_CRASHLOG 1 35 #define RTKIT_EP_SYSLOG 2 36 #define RTKIT_EP_DEBUG 3 37 #define RTKIT_EP_IOREPORT 4 38 39 #define RTKIT_MGMT_TYPE(x) (((x) >> 52) & 0xff) 40 #define RTKIT_MGMT_TYPE_SHIFT 52 41 42 #define RTKIT_MGMT_PWR_STATE(x) (((x) >> 0) & 0xff) 43 #define RTKIT_MGMT_PWR_STATE_ON 0x20 44 45 #define RTKIT_MGMT_HELLO 1 46 #define RTKIT_MGMT_HELLO_ACK 2 47 #define RTKIT_MGMT_STARTEP 5 48 #define RTKIT_MGMT_IOP_PWR_STATE 6 49 #define RTKIT_MGMT_IOP_PWR_STATE_ACK 7 50 #define RTKIT_MGMT_EPMAP 8 51 52 #define RTKIT_MGMT_HELLO_MINVER(x) (((x) >> 0) & 0xffff) 53 #define RTKIT_MGMT_HELLO_MINVER_SHIFT 0 54 #define RTKIT_MGMT_HELLO_MAXVER(x) (((x) >> 16) & 0xffff) 55 #define RTKIT_MGMT_HELLO_MAXVER_SHIFT 16 56 57 #define RTKIT_MGMT_STARTEP_EP_SHIFT 32 58 #define RTKIT_MGMT_STARTEP_START (1ULL << 1) 59 60 #define RTKIT_MGMT_EPMAP_LAST (1ULL << 51) 61 #define RTKIT_MGMT_EPMAP_BASE(x) (((x) >> 32) & 0x7) 62 #define RTKIT_MGMT_EPMAP_BASE_SHIFT 32 63 #define RTKIT_MGMT_EPMAP_BITMAP(x) (((x) >> 0) & 0xffffffff) 64 #define RTKIT_MGMT_EPMAP_MORE (1ULL << 0) 65 66 #define RTKIT_BUFFER_REQUEST 1 67 #define RTKIT_BUFFER_ADDR(x) (((x) >> 0) & 0xfffffffffff) 68 #define RTKIT_BUFFER_SIZE(x) (((x) >> 44) & 0xff) 69 #define RTKIT_BUFFER_SIZE_SHIFT 44 70 71 /* Versions we support. */ 72 #define RTKIT_MINVER 11 73 #define RTKIT_MAXVER 12 74 75 struct rtkit_state { 76 struct mbox_channel *mc; 77 int pwrstate; 78 uint64_t epmap; 79 void (*callback[32])(void *, uint64_t); 80 void *arg[32]; 81 }; 82 83 int 84 rtkit_recv(struct mbox_channel *mc, struct aplmbox_msg *msg) 85 { 86 int error, timo; 87 88 for (timo = 0; timo < 10000; timo++) { 89 error = mbox_recv(mc, msg, sizeof(*msg)); 90 if (error == 0) 91 break; 92 delay(10); 93 } 94 95 return error; 96 } 97 98 int 99 rtkit_send(struct mbox_channel *mc, uint32_t endpoint, 100 uint64_t type, uint64_t data) 101 { 102 struct aplmbox_msg msg; 103 104 msg.data0 = (type << RTKIT_MGMT_TYPE_SHIFT) | data; 105 msg.data1 = endpoint; 106 return mbox_send(mc, &msg, sizeof(msg)); 107 } 108 109 int 110 rtkit_start(struct rtkit_state *state, uint32_t endpoint) 111 { 112 struct mbox_channel *mc = state->mc; 113 uint64_t reply; 114 115 reply = ((uint64_t)endpoint << RTKIT_MGMT_STARTEP_EP_SHIFT); 116 reply |= RTKIT_MGMT_STARTEP_START; 117 return rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply); 118 } 119 120 int 121 rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg) 122 { 123 struct mbox_channel *mc = state->mc; 124 uint64_t minver, maxver, ver; 125 uint64_t base, bitmap, reply; 126 uint32_t endpoint; 127 int error; 128 129 switch (RTKIT_MGMT_TYPE(msg->data0)) { 130 case RTKIT_MGMT_HELLO: 131 minver = RTKIT_MGMT_HELLO_MINVER(msg->data0); 132 maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0); 133 if (minver > RTKIT_MAXVER) { 134 printf("unsupported minimum firmware version %lld\n", 135 minver); 136 return EINVAL; 137 } 138 if (maxver < RTKIT_MINVER) { 139 printf("unsupported maximum firmware version %lld\n", 140 maxver); 141 return EINVAL; 142 } 143 ver = min(RTKIT_MAXVER, maxver); 144 error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK, 145 (ver << RTKIT_MGMT_HELLO_MINVER_SHIFT) | 146 (ver << RTKIT_MGMT_HELLO_MAXVER_SHIFT)); 147 if (error) 148 return error; 149 break; 150 151 case RTKIT_MGMT_IOP_PWR_STATE_ACK: 152 state->pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0); 153 break; 154 155 case RTKIT_MGMT_EPMAP: 156 base = RTKIT_MGMT_EPMAP_BASE(msg->data0); 157 bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0); 158 state->epmap |= (bitmap << (base * 32)); 159 reply = (base << RTKIT_MGMT_EPMAP_BASE_SHIFT); 160 if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) 161 reply |= RTKIT_MGMT_EPMAP_LAST; 162 else 163 reply |= RTKIT_MGMT_EPMAP_MORE; 164 error = rtkit_send(state->mc, RTKIT_EP_MGMT, 165 RTKIT_MGMT_EPMAP, reply); 166 if (error) 167 return error; 168 if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) { 169 for (endpoint = 1; endpoint < 32; endpoint++) { 170 if ((state->epmap & (1ULL << endpoint)) == 0) 171 continue; 172 173 switch (endpoint) { 174 case RTKIT_EP_CRASHLOG: 175 case RTKIT_EP_DEBUG: 176 case RTKIT_EP_IOREPORT: 177 error = rtkit_start(state, endpoint); 178 if (error) 179 return error; 180 break; 181 } 182 } 183 } 184 break; 185 default: 186 printf("unhandled management event 0x%016lld\n", msg->data0); 187 return EIO; 188 } 189 190 return 0; 191 } 192 193 int 194 rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) 195 { 196 struct mbox_channel *mc = state->mc; 197 bus_addr_t addr; 198 bus_size_t size; 199 int error; 200 201 switch (RTKIT_MGMT_TYPE(msg->data0)) { 202 case RTKIT_BUFFER_REQUEST: 203 addr = RTKIT_BUFFER_ADDR(msg->data0); 204 size = RTKIT_BUFFER_SIZE(msg->data0); 205 if (addr) 206 break; 207 208 error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, 209 size << RTKIT_BUFFER_SIZE_SHIFT | addr); 210 if (error) 211 return error; 212 break; 213 default: 214 printf("unhandled crashlog event 0x%016llx\n", msg->data0); 215 return EIO; 216 } 217 218 return 0; 219 } 220 221 int 222 rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) 223 { 224 struct mbox_channel *mc = state->mc; 225 bus_addr_t addr; 226 bus_size_t size; 227 int error; 228 229 switch (RTKIT_MGMT_TYPE(msg->data0)) { 230 case RTKIT_BUFFER_REQUEST: 231 addr = RTKIT_BUFFER_ADDR(msg->data0); 232 size = RTKIT_BUFFER_SIZE(msg->data0); 233 if (addr) 234 break; 235 236 error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, 237 size << RTKIT_BUFFER_SIZE_SHIFT | addr); 238 if (error) 239 return error; 240 break; 241 default: 242 printf("unhandled ioreport event 0x%016llx\n", msg->data0); 243 return EIO; 244 } 245 246 return 0; 247 } 248 249 int 250 rtkit_poll(struct rtkit_state *state) 251 { 252 struct mbox_channel *mc = state->mc; 253 struct aplmbox_msg msg; 254 void (*callback)(void *, uint64_t); 255 void *arg; 256 uint32_t endpoint; 257 int error; 258 259 error = rtkit_recv(mc, &msg); 260 if (error) 261 return error; 262 263 endpoint = msg.data1; 264 switch (endpoint) { 265 case RTKIT_EP_MGMT: 266 error = rtkit_handle_mgmt(state, &msg); 267 if (error) 268 return error; 269 break; 270 case RTKIT_EP_CRASHLOG: 271 error = rtkit_handle_crashlog(state, &msg); 272 if (error) 273 return error; 274 break; 275 case RTKIT_EP_IOREPORT: 276 error = rtkit_handle_ioreport(state, &msg); 277 if (error) 278 return error; 279 break; 280 default: 281 if (endpoint >= 32 && endpoint < 64 && 282 state->callback[endpoint - 32]) { 283 callback = state->callback[endpoint - 32]; 284 arg = state->arg[endpoint - 32]; 285 callback(arg, msg.data0); 286 break; 287 } 288 289 printf("unhandled endpoint %d\n", msg.data1); 290 return EIO; 291 } 292 293 return 0; 294 } 295 296 void 297 rtkit_rx_callback(void *cookie) 298 { 299 rtkit_poll(cookie); 300 } 301 302 struct rtkit_state * 303 rtkit_init(int node, const char *name) 304 { 305 struct rtkit_state *state; 306 struct mbox_client client; 307 308 state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO); 309 client.mc_rx_callback = rtkit_rx_callback; 310 client.mc_rx_arg = state; 311 state->mc = mbox_channel(node, name, &client); 312 if (state->mc == NULL) { 313 free(state, M_DEVBUF, sizeof(*state)); 314 return NULL; 315 } 316 317 return state; 318 } 319 320 int 321 rtkit_boot(struct rtkit_state *state) 322 { 323 struct mbox_channel *mc = state->mc; 324 int error; 325 326 /* Wake up! */ 327 error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE, 328 RTKIT_MGMT_PWR_STATE_ON); 329 if (error) 330 return error; 331 332 while (state->pwrstate != RTKIT_MGMT_PWR_STATE_ON) 333 rtkit_poll(state); 334 335 return 0; 336 } 337 338 int 339 rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint, 340 void (*callback)(void *, uint64_t), void *arg) 341 { 342 if (endpoint < 32 || endpoint >= 64) 343 return EINVAL; 344 345 if ((state->epmap & (1ULL << endpoint)) == 0) 346 return EINVAL; 347 348 state->callback[endpoint - 32] = callback; 349 state->arg[endpoint - 32] = arg; 350 return rtkit_start(state, endpoint); 351 } 352 353 int 354 rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint, 355 uint64_t data) 356 { 357 return rtkit_send(state->mc, endpoint, 0, data); 358 } 359