Module Name: src Committed By: skrll Date: Wed Apr 27 08:06:20 UTC 2022
Modified Files: src/sys/arch/arm/apple: files.apple src/sys/arch/evbarm/conf: GENERIC64 Added Files: src/sys/arch/arm/apple: apple_mbox.c apple_mbox.h apple_rtkit.c apple_rtkit.h Log Message: Add support for the mailbox that provides a communications channel with additional cores integrated in Apple Silicon. Also, add an implementation for the protocol to communicate with coprocessors running firmware based Apple's RTKit OS. >From OpenBSD. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/apple/apple_mbox.c \ src/sys/arch/arm/apple/apple_mbox.h src/sys/arch/arm/apple/apple_rtkit.c \ src/sys/arch/arm/apple/apple_rtkit.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/apple/files.apple cvs rdiff -u -r1.197 -r1.198 src/sys/arch/evbarm/conf/GENERIC64 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/apple/files.apple diff -u src/sys/arch/arm/apple/files.apple:1.4 src/sys/arch/arm/apple/files.apple:1.5 --- src/sys/arch/arm/apple/files.apple:1.4 Wed Apr 27 07:59:18 2022 +++ src/sys/arch/arm/apple/files.apple Wed Apr 27 08:06:20 2022 @@ -1,11 +1,9 @@ -# $NetBSD: files.apple,v 1.4 2022/04/27 07:59:18 skrll Exp $ +# $NetBSD: files.apple,v 1.5 2022/04/27 08:06:20 skrll Exp $ # # Configuration info for Apple Silicon SoCs # # -file arch/arm/apple/apple_platform.c soc_apple - # IOMMU device appledart attach appledart at fdt with apple_dart @@ -16,6 +14,11 @@ device appleintc: pic, pic_splfuncs attach appleintc at fdt with apple_intc file arch/arm/apple/apple_intc.c apple_intc +# Mailbox +device applembox +attach applembox at fdt with apple_mbox +file arch/arm/apple/apple_mbox.c apple_mbox + # PCIe controller device applepcie: pcibus, pcihost_fdt attach applepcie at fdt with apple_pcie @@ -39,3 +42,6 @@ file arch/arm/apple/apple_wdog.c apple_ # SOC parameters defflag opt_soc.h SOC_APPLE + +file arch/arm/apple/apple_platform.c soc_apple +file arch/arm/apple/apple_rtkit.c soc_apple & apple_mbox Index: src/sys/arch/evbarm/conf/GENERIC64 diff -u src/sys/arch/evbarm/conf/GENERIC64:1.197 src/sys/arch/evbarm/conf/GENERIC64:1.198 --- src/sys/arch/evbarm/conf/GENERIC64:1.197 Wed Apr 27 07:59:18 2022 +++ src/sys/arch/evbarm/conf/GENERIC64 Wed Apr 27 08:06:20 2022 @@ -1,5 +1,5 @@ # -# $NetBSD: GENERIC64,v 1.197 2022/04/27 07:59:18 skrll Exp $ +# $NetBSD: GENERIC64,v 1.198 2022/04/27 08:06:20 skrll Exp $ # # GENERIC ARM (aarch64) kernel # @@ -200,6 +200,9 @@ tegrafuse* at fdt? pass 4 # NVIDIA Tegr # Power management controller tegrapmc* at fdt? pass 4 # NVIDIA Tegra PMC +# Mailbox controller +applembox* at fdt? pass 2 # Apple Mailbox + # Clock and Reset controller bcmcprman* at fdt? pass 1 # Broadcom BCM283x Clock Manager bcmaux* at fdt? pass 1 # Broadcom BCM283x Aux Periph Clocks Added files: Index: src/sys/arch/arm/apple/apple_mbox.c diff -u /dev/null src/sys/arch/arm/apple/apple_mbox.c:1.1 --- /dev/null Wed Apr 27 08:06:20 2022 +++ src/sys/arch/arm/apple/apple_mbox.c Wed Apr 27 08:06:20 2022 @@ -0,0 +1,310 @@ +/* $NetBSD: apple_mbox.c,v 1.1 2022/04/27 08:06:20 skrll Exp $ */ +/* $OpenBSD: apple_mbox.c,v 1.2 2022/01/04 20:55:48 kettenis Exp $ */ + +/*- + * Copyright (c) 2022 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2021 Mark Kettenis <kette...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: apple_mbox.c,v 1.1 2022/04/27 08:06:20 skrll Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> + +#include <dev/fdt/fdtvar.h> + +#include <arm/apple/apple_mbox.h> + +#define MBOX_A2I_CTRL 0x110 +#define MBOX_A2I_CTRL_FULL __BIT(16) +#define MBOX_I2A_CTRL 0x114 +#define MBOX_I2A_CTRL_EMPTY __BIT(17) +#define MBOX_A2I_SEND0 0x800 +#define MBOX_A2I_SEND1 0x808 +#define MBOX_I2A_RECV0 0x830 +#define MBOX_I2A_RECV1 0x838 + +#define MBOX_READ4(sc, reg) \ + (bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))) +#define MBOX_READ8(sc, reg) \ + (bus_space_read_8((sc)->sc_bst, (sc)->sc_bsh, (reg))) +#define MBOX_WRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) +#define MBOX_WRITE8(sc, reg, val) \ + bus_space_write_8((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) + +static int apple_mbox_intr(void *); + +static struct mbox_interrupt { + const char *mi_name; + bool mi_claim; + int (*mi_handler)(void *); +} mbox_interrupts[] = { + { + .mi_name = "send-empty", + .mi_claim = false, + .mi_handler = apple_mbox_intr, + }, + { + .mi_name = "send-not-empty", + .mi_claim = false, + }, + { + .mi_name = "recv-empty", + .mi_claim = false, + }, + { + .mi_name = "recv-not-empty", + .mi_claim = true, + .mi_handler = apple_mbox_intr, + }, +}; + +struct apple_mbox_softc { + device_t sc_dev; + int sc_phandle; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + + void *sc_intr[__arraycount(mbox_interrupts)]; + void (*sc_rx_callback)(void *); + void *sc_rx_arg; + +// struct fdtbus_mbox_device sc_md; +}; + +static const struct device_compatible_entry compat_data[] = { + { .compat = "apple,asc-mailbox" }, + { .compat = "apple,asc-mailbox-v4" }, + DEVICE_COMPAT_EOL +}; + + +static int +apple_mbox_intr(void *arg) +{ + struct apple_mbox_softc const *sc = arg; + const uint32_t ctrl = MBOX_READ4(sc, MBOX_I2A_CTRL); + + if (ctrl & MBOX_I2A_CTRL_EMPTY) + return 0; + + if (sc->sc_rx_callback) { + sc->sc_rx_callback(sc->sc_rx_arg); + } else { + printf("%s: 0x%016" PRIx64 "0x%016" PRIx64 "\n", + device_xname(sc->sc_dev), + MBOX_READ8(sc, MBOX_I2A_RECV0), + MBOX_READ8(sc, MBOX_I2A_RECV1)); + } + + return 1; +} + +static void * +apple_mbox_acquire(device_t dev, const void *cells, size_t len, + void (*cb)(void *), void *arg) +{ + struct apple_mbox_softc * const sc = device_private(dev); + + if (sc->sc_rx_callback == NULL && sc->sc_rx_arg == NULL) { + sc->sc_rx_callback = cb; + sc->sc_rx_arg = arg; + + return sc; + } + + return NULL; +} + +static void +apple_mbox_release(device_t dev, void *priv) +{ + struct apple_mbox_softc * const sc = device_private(dev); + + KASSERT(sc == priv); + + sc->sc_rx_callback = NULL; + sc->sc_rx_arg = NULL; +} + +static int +apple_mbox_send(device_t dev, void *priv, const void *data, size_t len) +{ + struct apple_mbox_softc * const sc = device_private(dev); + const struct apple_mbox_msg *msg = data; + + KASSERT(sc == priv); + + if (len != sizeof(struct apple_mbox_msg)) + return EINVAL; + + + uint32_t ctrl = MBOX_READ4(sc, MBOX_A2I_CTRL); + if (ctrl & MBOX_A2I_CTRL_FULL) + return EBUSY; + + MBOX_WRITE8(sc, MBOX_A2I_SEND0, msg->data0); + MBOX_WRITE8(sc, MBOX_A2I_SEND1, msg->data1); + + return 0; +} + +static int +apple_mbox_recv(device_t dev, void *priv, void *data, size_t len) +{ + struct apple_mbox_softc * const sc = device_private(dev); + struct apple_mbox_msg *msg = data; + + KASSERT(sc == priv); + if (len != sizeof(struct apple_mbox_msg)) + return EINVAL; + + uint32_t ctrl = MBOX_READ4(sc, MBOX_I2A_CTRL); + if (ctrl & MBOX_I2A_CTRL_EMPTY) + return EAGAIN; + + msg->data0 = MBOX_READ8(sc, MBOX_I2A_RECV0); + msg->data1 = MBOX_READ8(sc, MBOX_I2A_RECV1); + + return 0; +} + + +static int +apple_mbox_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +apple_mbox_attach(device_t parent, device_t self, void *aux) +{ + struct apple_mbox_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + bus_addr_t addr; + bus_size_t size; + + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { + aprint_error(": couldn't get registers\n"); + return; + } + + sc->sc_dev = self; + sc->sc_rx_callback = NULL; + sc->sc_rx_arg = NULL; + sc->sc_bst = faa->faa_bst; + if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { + aprint_error(": couldn't map registers\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": Apple Mailbox\n"); + + for (size_t i = 0; i < __arraycount(mbox_interrupts); i++) { + struct mbox_interrupt *mi = &mbox_interrupts[i]; + + if (!mi->mi_claim) + continue; + + int index; + int err = fdtbus_get_index(phandle, "interrupt-names", + mi->mi_name, &index); + if (err != 0) { + aprint_error_dev(self, + "couldn't get %s interrupt index\n", mi->mi_name); + continue; + } + + char istr[128]; + if (!fdtbus_intr_str(phandle, index, istr, sizeof(istr))) { + aprint_error_dev(self, + "couldn't decode %s interrupt\n", mi->mi_name); + continue; + } + + sc->sc_intr[i] = fdtbus_intr_establish_xname(phandle, index, + IPL_VM, FDT_INTR_MPSAFE, mi->mi_handler, sc, + device_xname(self)); + if (sc->sc_intr[i] == NULL) { + aprint_error_dev(self, + "couldn't establish %s interrupt\n", mi->mi_name); + continue; + } + + aprint_normal_dev(self, "'%s' interrupting on %s\n", + mi->mi_name, istr); + } + + static struct fdtbus_mbox_controller_func funcs = { + .mc_acquire = apple_mbox_acquire, + .mc_release = apple_mbox_release, + .mc_send = apple_mbox_send, + .mc_recv = apple_mbox_recv, + }; + + int error = fdtbus_register_mbox_controller(self, phandle, &funcs); + if (error) { + aprint_error_dev(self, "couldn't register mailbox\n"); + goto fail_register; + } + return; + +fail_register: + for (size_t i = 0; i < __arraycount(mbox_interrupts); i++) { + if (sc->sc_intr[i] != NULL) { + fdtbus_intr_disestablish(phandle, sc->sc_intr[i]); + } + } + + return; +} + +CFATTACH_DECL_NEW(apple_mbox, sizeof(struct apple_mbox_softc), + apple_mbox_match, apple_mbox_attach, NULL, NULL); Index: src/sys/arch/arm/apple/apple_mbox.h diff -u /dev/null src/sys/arch/arm/apple/apple_mbox.h:1.1 --- /dev/null Wed Apr 27 08:06:20 2022 +++ src/sys/arch/arm/apple/apple_mbox.h Wed Apr 27 08:06:20 2022 @@ -0,0 +1,23 @@ +/* $NetBSD: apple_mbox.h,v 1.1 2022/04/27 08:06:20 skrll Exp $ */ + +/* $OpenBSD: aplmbox.h,v 1.1 2021/12/18 13:33:52 kettenis Exp $ */ +/* + * Copyright (c) 2021 Mark Kettenis <kette...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct apple_mbox_msg { + uint64_t data0; + uint32_t data1; +}; Index: src/sys/arch/arm/apple/apple_rtkit.c diff -u /dev/null src/sys/arch/arm/apple/apple_rtkit.c:1.1 --- /dev/null Wed Apr 27 08:06:20 2022 +++ src/sys/arch/arm/apple/apple_rtkit.c Wed Apr 27 08:06:20 2022 @@ -0,0 +1,368 @@ +/* $NetBSD: apple_rtkit.c,v 1.1 2022/04/27 08:06:20 skrll Exp $ */ +/* $OpenBSD: rtkit.c,v 1.3 2022/01/10 09:07:28 kettenis Exp $ */ + +/* + * Copyright (c) 2021 Mark Kettenis <kette...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <sys/kmem.h> + +#include <dev/fdt/fdtvar.h> + +#include <arm/apple/apple_rtkit.h> +#include <arm/apple/apple_mbox.h> + + +#define RTKIT_EP_MGMT 0 +#define RTKIT_EP_CRASHLOG 1 +#define RTKIT_EP_SYSLOG 2 +#define RTKIT_EP_DEBUG 3 +#define RTKIT_EP_IOREPORT 4 + +#define RTKIT_MGMT_TYPE_MASK __BITS(59, 52) +#define RTKIT_MGMT_TYPE(x) __SHIFTOUT((x), RTKIT_MGMT_TYPE_MASK) + +#define RTKIT_MGMT_PWR_STATE_MASK __BITS(7, 0) +#define RTKIT_MGMT_PWR_STATE(x) __SHIFTOUT((x), RTKIT_MGMT_PWR_STATE_MASK) +#define RTKIT_MGMT_PWR_STATE_ON 0x20 + +#define RTKIT_MGMT_HELLO 1 +#define RTKIT_MGMT_HELLO_ACK 2 +#define RTKIT_MGMT_STARTEP 5 +#define RTKIT_MGMT_IOP_PWR_STATE 6 +#define RTKIT_MGMT_IOP_PWR_STATE_ACK 7 +#define RTKIT_MGMT_EPMAP 8 + +#define RTKIT_MGMT_HELLO_MINVER_MASK __BITS(15, 0) +#define RTKIT_MGMT_HELLO_MINVER(x) __SHIFTOUT((x), RTKIT_MGMT_HELLO_MINVER_MASK) +#define RTKIT_MGMT_HELLO_MAXVER_MASK __BITS(31, 16) +#define RTKIT_MGMT_HELLO_MAXVER(x) __SHIFTOUT((x), RTKIT_MGMT_HELLO_MAXVER_MASK) + +#define RTKIT_MGMT_STARTEP_EP_SHIFT 32 +#define RTKIT_MGMT_STARTEP_EP_MASK __BITS(39, 32) +#define RTKIT_MGMT_STARTEP_START __BIT(1) + +#define RTKIT_MGMT_EPMAP_LAST __BIT(51) +#define RTKIT_MGMT_EPMAP_BASE_MASK __BITS(34, 32) +#define RTKIT_MGMT_EPMAP_BASE(x) __SHIFTOUT((x), RTKIT_MGMT_EPMAP_BASE_MASK) +#define RTKIT_MGMT_EPMAP_BITMAP_MASK __BITS(31, 0) +#define RTKIT_MGMT_EPMAP_BITMAP(x) __SHIFTOUT((x), RTKIT_MGMT_EPMAP_BITMAP_MASK) +#define RTKIT_MGMT_EPMAP_MORE __BIT(0) + +#define RTKIT_BUFFER_REQUEST 1 +#define RTKIT_BUFFER_ADDR_MASK __BITS(41, 0) +#define RTKIT_BUFFER_ADDR(x) __SHIFTOUT((x), RTKIT_BUFFER_ADDR_MASK) +#define RTKIT_BUFFER_SIZE_MASK __BITS(51, 44) +#define RTKIT_BUFFER_SIZE(x) __SHIFTOUT((x), RTKIT_BUFFER_SIZE_MASK) + +/* Versions we support. */ +#define RTKIT_MINVER 11 +#define RTKIT_MAXVER 12 + +struct rtkit_state { + struct fdtbus_mbox_channel *mc; + int pwrstate; + uint64_t epmap; + void (*callback[32])(void *, uint64_t); + void *arg[32]; +}; + +static int +rtkit_recv(struct fdtbus_mbox_channel *mc, struct apple_mbox_msg *msg) +{ + int error, timo; + + for (timo = 0; timo < 10000; timo++) { + error = fdtbus_mbox_recv(mc, msg, sizeof(*msg)); + if (error == 0) + break; + delay(10); + } + + return error; +} + +static int +rtkit_send(struct fdtbus_mbox_channel *mc, uint32_t endpoint, + uint64_t type, uint64_t data) +{ + struct apple_mbox_msg msg; + + msg.data0 = __SHIFTIN(type, RTKIT_MGMT_TYPE_MASK) | data; + msg.data1 = endpoint; + return fdtbus_mbox_send(mc, &msg, sizeof(msg)); +} + +static int +rtkit_start(struct rtkit_state *state, uint32_t endpoint) +{ + struct fdtbus_mbox_channel *mc = state->mc; + uint64_t reply; + + reply = __SHIFTIN(endpoint, RTKIT_MGMT_STARTEP_EP_MASK); + reply |= RTKIT_MGMT_STARTEP_START; + return rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply); +} + +static int +rtkit_handle_mgmt(struct rtkit_state *state, struct apple_mbox_msg *msg) +{ + struct fdtbus_mbox_channel *mc = state->mc; + uint64_t minver, maxver, ver; + uint64_t base, bitmap, reply; + uint32_t endpoint; + int error; + + switch (RTKIT_MGMT_TYPE(msg->data0)) { + case RTKIT_MGMT_HELLO: + minver = RTKIT_MGMT_HELLO_MINVER(msg->data0); + maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0); + if (minver > RTKIT_MAXVER) { + printf("unsupported minimum firmware version " + "%"PRId64"\n", minver); + return EINVAL; + } + if (maxver < RTKIT_MINVER) { + printf("unsupported maximum firmware version " + "%"PRId64"\n", maxver); + return EINVAL; + } + ver = MIN(RTKIT_MAXVER, maxver); + error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK, + __SHIFTIN(ver, RTKIT_MGMT_HELLO_MINVER_MASK) | + __SHIFTIN(ver, RTKIT_MGMT_HELLO_MAXVER_MASK)); + if (error) + return error; + break; + + case RTKIT_MGMT_IOP_PWR_STATE_ACK: + state->pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0); + break; + + case RTKIT_MGMT_EPMAP: + base = RTKIT_MGMT_EPMAP_BASE(msg->data0); + bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0); + state->epmap |= (bitmap << (base * 32)); + reply = __SHIFTIN(base, RTKIT_MGMT_EPMAP_BASE_MASK); + if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) + reply |= RTKIT_MGMT_EPMAP_LAST; + else + reply |= RTKIT_MGMT_EPMAP_MORE; + error = rtkit_send(state->mc, RTKIT_EP_MGMT, + RTKIT_MGMT_EPMAP, reply); + if (error) + return error; + if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) { + for (endpoint = 1; endpoint < 32; endpoint++) { + if ((state->epmap & __BIT(endpoint)) == 0) + continue; + + switch (endpoint) { + case RTKIT_EP_CRASHLOG: + case RTKIT_EP_DEBUG: + case RTKIT_EP_IOREPORT: + error = rtkit_start(state, endpoint); + if (error) + return error; + break; + } + } + } + break; + default: + printf("unhandled management event " + "0x%016"PRIx64"\n", msg->data0); + return EIO; + } + + return 0; +} + +static int +rtkit_handle_crashlog(struct rtkit_state *state, struct apple_mbox_msg *msg) +{ + struct fdtbus_mbox_channel *mc = state->mc; + bus_addr_t addr; + bus_size_t size; + int error; + + switch (RTKIT_MGMT_TYPE(msg->data0)) { + case RTKIT_BUFFER_REQUEST: + addr = RTKIT_BUFFER_ADDR(msg->data0); + size = RTKIT_BUFFER_SIZE(msg->data0); + // XXXNH WTF is this conditional + if (addr) + break; + + error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, + __SHIFTIN(size, RTKIT_BUFFER_SIZE_MASK) | addr); + if (error) + return error; + break; + default: + printf("unhandled crashlog event " + "0x%016"PRIx64"\n", msg->data0); + return EIO; + } + + return 0; +} + +static int +rtkit_handle_ioreport(struct rtkit_state *state, struct apple_mbox_msg *msg) +{ + struct fdtbus_mbox_channel *mc = state->mc; + bus_addr_t addr; + bus_size_t size; + int error; + + switch (RTKIT_MGMT_TYPE(msg->data0)) { + case RTKIT_BUFFER_REQUEST: + addr = RTKIT_BUFFER_ADDR(msg->data0); + size = RTKIT_BUFFER_SIZE(msg->data0); + // XXXNH WTF is this conditional + if (addr) + break; + error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, + __SHIFTIN(size, RTKIT_BUFFER_SIZE_MASK) | addr); + if (error) + return error; + break; + default: + printf("unhandled ioreport event" + "0x%016"PRIx64"\n", msg->data0); + return EIO; + } + + return 0; +} + +int +rtkit_poll(struct rtkit_state *state) +{ + struct fdtbus_mbox_channel *mc = state->mc; + struct apple_mbox_msg msg; + void (*callback)(void *, uint64_t); + void *arg; + uint32_t endpoint; + int error; + + error = rtkit_recv(mc, &msg); + if (error) + return error; + + endpoint = msg.data1; + switch (endpoint) { + case RTKIT_EP_MGMT: + error = rtkit_handle_mgmt(state, &msg); + if (error) + return error; + break; + case RTKIT_EP_CRASHLOG: + error = rtkit_handle_crashlog(state, &msg); + if (error) + return error; + break; + case RTKIT_EP_IOREPORT: + error = rtkit_handle_ioreport(state, &msg); + if (error) + return error; + break; + default: + if (endpoint >= 32 && endpoint < 64 && + state->callback[endpoint - 32]) { + callback = state->callback[endpoint - 32]; + arg = state->arg[endpoint - 32]; + callback(arg, msg.data0); + break; + } + + printf("unhandled endpoint %d\n", msg.data1); + return EIO; + } + + return 0; +} + +static void +rtkit_rx_callback(void *cookie) +{ + rtkit_poll(cookie); +} + +struct rtkit_state * +rtkit_init(int node, const char *name) +{ + struct rtkit_state *state; + + state = kmem_zalloc(sizeof(*state), KM_SLEEP); + if (name) { + state->mc = fdtbus_mbox_get(node, name, rtkit_rx_callback, state); + } else { + state->mc = fdtbus_mbox_get_index(node, 0, rtkit_rx_callback, state); + } + if (state->mc == NULL) { + kmem_free(state, sizeof(*state)); + + return NULL; + } + + return state; +} + +int +rtkit_boot(struct rtkit_state *state) +{ + struct fdtbus_mbox_channel *mc = state->mc; + int error; + + /* Wake up! */ + error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE, + RTKIT_MGMT_PWR_STATE_ON); + if (error) { + return error; + } + + while (state->pwrstate != RTKIT_MGMT_PWR_STATE_ON) + rtkit_poll(state); + + return 0; +} + +int +rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint, + void (*callback)(void *, uint64_t), void *arg) +{ + if (endpoint < 32 || endpoint >= 64) + return EINVAL; + + if ((state->epmap & __BIT(endpoint)) == 0) + return EINVAL; + + state->callback[endpoint - 32] = callback; + state->arg[endpoint - 32] = arg; + return rtkit_start(state, endpoint); +} + +int +rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint, + uint64_t data) +{ + + return rtkit_send(state->mc, endpoint, 0, data); +} Index: src/sys/arch/arm/apple/apple_rtkit.h diff -u /dev/null src/sys/arch/arm/apple/apple_rtkit.h:1.1 --- /dev/null Wed Apr 27 08:06:20 2022 +++ src/sys/arch/arm/apple/apple_rtkit.h Wed Apr 27 08:06:20 2022 @@ -0,0 +1,10 @@ +/* public domain */ + +struct rtkit_state; + +struct rtkit_state *rtkit_init(int, const char *); +int rtkit_boot(struct rtkit_state *); +int rtkit_poll(struct rtkit_state *); +int rtkit_start_endpoint(struct rtkit_state *, uint32_t, + void (*)(void *, uint64_t), void *); +int rtkit_send_endpoint(struct rtkit_state *, uint32_t, uint64_t);