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