Annotation of src/sys/arch/arm/apple/apple_rtkit.c, Revision 1.1
1.1 ! skrll 1: /* $NetBSD$ */
! 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: }
CVSweb <webmaster@jp.NetBSD.org>