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