[BACK]Return to apple_rtkit.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / apple

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>