Commit 10f7ffab authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/mcayland/tags/qemu-macppc-20200626' into staging



qemu-macppc patches

# gpg: Signature made Fri 26 Jun 2020 10:15:36 BST
# gpg:                using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F
# gpg:                issuer "mark.cave-ayland@ilande.co.uk"
# gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [full]
# Primary key fingerprint: CC62 1AB9 8E82 200D 915C  C9C4 5BC2 C56F AE0F 321F

* remotes/mcayland/tags/qemu-macppc-20200626: (22 commits)
  adb: add ADB bus trace events
  adb: use adb_device prefix for ADB device trace events
  adb: only call autopoll callbacks when autopoll is not blocked
  mac_via: rework ADB state machine to be compatible with both MacOS and Linux
  mac_via: move VIA1 portB write logic into mos6522_q800_via1_write()
  pmu: add adb_autopoll_block() and adb_autopoll_unblock() functions
  cuda: add adb_autopoll_block() and adb_autopoll_unblock() functions
  adb: add autopoll_blocked variable to block autopoll
  adb: use adb_request() only for explicit requests
  adb: add status field for holding information about the last ADB request
  adb: keep track of devices with pending data
  adb: introduce new ADBDeviceHasData method to ADBDeviceClass
  mac_via: convert to use ADBBusState internal autopoll variables
  pmu: convert to use ADBBusState internal autopoll variables
  cuda: convert to use ADBBusState internal autopoll variables
  adb: create autopoll variables directly within ADBBusState
  adb: introduce realize/unrealize and VMStateDescription for ADB bus
  pmu: honour autopoll_rate_ms when rearming the ADB autopoll timer
  pmu: fix duplicate autopoll mask variable
  cuda: convert ADB autopoll timer from ns to ms
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 611ac633 e590e7f0
Loading
Loading
Loading
Loading
+24 −18
Original line number Diff line number Diff line
@@ -243,7 +243,7 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
    olen = 0;
    switch (cmd) {
    case ADB_WRITEREG:
        trace_adb_kbd_writereg(reg, buf[1]);
        trace_adb_device_kbd_writereg(reg, buf[1]);
        switch (reg) {
        case 2:
            /* LED status */
@@ -256,13 +256,12 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
            case ADB_CMD_CHANGE_ID_AND_ACT:
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
                d->devaddr = buf[1] & 0xf;
                trace_adb_kbd_request_change_addr(d->devaddr);
                trace_adb_device_kbd_request_change_addr(d->devaddr);
                break;
            default:
                if (!d->disable_direct_reg3_writes) {
                d->devaddr = buf[1] & 0xf;

                    /* we support handlers:
                /*
                 * we support handlers:
                 * 1: Apple Standard Keyboard
                 * 2: Apple Extended Keyboard (LShift = RShift)
                 * 3: Apple Extended Keyboard (LShift != RShift)
@@ -271,9 +270,8 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                    d->handler = buf[2];
                }

                    trace_adb_kbd_request_change_addr_and_handler(d->devaddr,
                                                                  d->handler);
                }
                trace_adb_device_kbd_request_change_addr_and_handler(
                    d->devaddr, d->handler);
                break;
            }
        }
@@ -296,12 +294,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
            olen = 2;
            break;
        }
        trace_adb_kbd_readreg(reg, obuf[0], obuf[1]);
        trace_adb_device_kbd_readreg(reg, obuf[0], obuf[1]);
        break;
    }
    return olen;
}

static bool adb_kbd_has_data(ADBDevice *d)
{
    KBDState *s = ADB_KEYBOARD(d);

    return s->count > 0;
}

/* This is where keyboard events enter this file */
static void adb_keyboard_event(DeviceState *dev, QemuConsole *src,
                               InputEvent *evt)
@@ -316,7 +321,7 @@ static void adb_keyboard_event(DeviceState *dev, QemuConsole *src,
    /* FIXME: take handler into account when translating qcode */
    keycode = qcode_to_adb_keycode[qcode];
    if (keycode == NO_KEY) {  /* We don't want to send this to the guest */
        trace_adb_kbd_no_key();
        trace_adb_device_kbd_no_key();
        return;
    }
    if (evt->u.key.data->down == false) { /* if key release event */
@@ -384,6 +389,7 @@ static void adb_kbd_class_init(ObjectClass *oc, void *data)
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);

    adc->devreq = adb_kbd_request;
    adc->devhasdata = adb_kbd_has_data;
    dc->reset = adb_kbd_reset;
    dc->vmsd = &vmstate_adb_kbd;
}
+41 −24
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
        s->dx = 0;
        s->dy = 0;
        s->dz = 0;
        trace_adb_mouse_flush();
        trace_adb_device_mouse_flush();
        return 0;
    }

@@ -130,11 +130,21 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
    olen = 0;
    switch (cmd) {
    case ADB_WRITEREG:
        trace_adb_mouse_writereg(reg, buf[1]);
        trace_adb_device_mouse_writereg(reg, buf[1]);
        switch (reg) {
        case 2:
            break;
        case 3:
            /*
             * MacOS 9 has a bug in its ADB driver whereby after configuring
             * the ADB bus devices it sends another write of invalid length
             * to reg 3. Make sure we ignore it to prevent an address clash
             * with the previous device.
             */
            if (len != 3) {
                return 0;
            }

            switch (buf[2]) {
            case ADB_CMD_SELF_TEST:
                break;
@@ -142,13 +152,12 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
            case ADB_CMD_CHANGE_ID_AND_ACT:
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
                d->devaddr = buf[1] & 0xf;
                trace_adb_mouse_request_change_addr(d->devaddr);
                trace_adb_device_mouse_request_change_addr(d->devaddr);
                break;
            default:
                if (!d->disable_direct_reg3_writes) {
                d->devaddr = buf[1] & 0xf;

                    /* we support handlers:
                /*
                 * we support handlers:
                 * 0x01: Classic Apple Mouse Protocol / 100 cpi operations
                 * 0x02: Classic Apple Mouse Protocol / 200 cpi operations
                 * we don't support handlers (at least):
@@ -163,9 +172,8 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                    d->handler = buf[2];
                }

                    trace_adb_mouse_request_change_addr_and_handler(
                trace_adb_device_mouse_request_change_addr_and_handler(
                    d->devaddr, d->handler);
                }
                break;
            }
        }
@@ -183,12 +191,20 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
            olen = 2;
            break;
        }
        trace_adb_mouse_readreg(reg, obuf[0], obuf[1]);
        trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]);
        break;
    }
    return olen;
}

static bool adb_mouse_has_data(ADBDevice *d)
{
    MouseState *s = ADB_MOUSE(d);

    return !(s->last_buttons_state == s->buttons_state &&
             s->dx == 0 && s->dy == 0);
}

static void adb_mouse_reset(DeviceState *dev)
{
    ADBDevice *d = ADB_DEVICE(dev);
@@ -244,6 +260,7 @@ static void adb_mouse_class_init(ObjectClass *oc, void *data)
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);

    adc->devreq = adb_mouse_request;
    adc->devhasdata = adb_mouse_has_data;
    dc->reset = adb_mouse_reset;
    dc->vmsd = &vmstate_adb_mouse;
}
+192 −18
Original line number Diff line number Diff line
@@ -27,20 +27,31 @@
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "adb-internal.h"
#include "trace.h"

/* error codes */
#define ADB_RET_NOTPRESENT (-2)

static const char *adb_commands[] = {
    "RESET", "FLUSH", "(Reserved 0x2)", "(Reserved 0x3)",
    "Reserved (0x4)", "(Reserved 0x5)", "(Reserved 0x6)", "(Reserved 0x7)",
    "LISTEN r0", "LISTEN r1", "LISTEN r2", "LISTEN r3",
    "TALK r0", "TALK r1", "TALK r2", "TALK r3",
};

static void adb_device_reset(ADBDevice *d)
{
    qdev_reset_all(DEVICE(d));
}

int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
static int do_adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf,
                          int len)
{
    ADBDevice *d;
    int devaddr, cmd, i;
    ADBDeviceClass *adc;
    int devaddr, cmd, olen, i;

    cmd = buf[0] & 0xf;
    if (cmd == ADB_BUSRESET) {
@@ -48,20 +59,53 @@ int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
            d = s->devices[i];
            adb_device_reset(d);
        }
        s->status = 0;
        return 0;
    }

    s->pending = 0;
    for (i = 0; i < s->nb_devices; i++) {
        d = s->devices[i];
        adc = ADB_DEVICE_GET_CLASS(d);

        if (adc->devhasdata(d)) {
            s->pending |= (1 << d->devaddr);
        }
    }

    s->status = 0;
    devaddr = buf[0] >> 4;
    for (i = 0; i < s->nb_devices; i++) {
        d = s->devices[i];
        adc = ADB_DEVICE_GET_CLASS(d);

        if (d->devaddr == devaddr) {
            ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
            return adc->devreq(d, obuf, buf, len);
            olen = adc->devreq(d, obuf, buf, len);
            if (!olen) {
                s->status |= ADB_STATUS_BUSTIMEOUT;
            }
            return olen;
        }
    }

    s->status |= ADB_STATUS_BUSTIMEOUT;
    return ADB_RET_NOTPRESENT;
}

/* XXX: move that to cuda ? */
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
{
    int ret;

    trace_adb_bus_request(buf[0] >> 4, adb_commands[buf[0] & 0xf], len);

    assert(s->autopoll_blocked);

    ret = do_adb_request(s, obuf, buf, len);

    trace_adb_bus_request_done(buf[0] >> 4, adb_commands[buf[0] & 0xf], ret);
    return ret;
}

int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
{
    ADBDevice *d;
@@ -70,17 +114,19 @@ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)

    olen = 0;
    for (i = 0; i < s->nb_devices; i++) {
        if (s->poll_index >= s->nb_devices)
        if (s->poll_index >= s->nb_devices) {
            s->poll_index = 0;
        }
        d = s->devices[s->poll_index];
        if ((1 << d->devaddr) & poll_mask) {
            buf[0] = ADB_READREG | (d->devaddr << 4);
            olen = adb_request(s, obuf + 1, buf, 1);
            olen = do_adb_request(s, obuf + 1, buf, 1);
            /* if there is data, we poll again the same device */
            if (olen > 0) {
                s->status |= ADB_STATUS_POLLREPLY;
                obuf[0] = buf[0];
                olen++;
                break;
                return olen;
            }
        }
        s->poll_index++;
@@ -88,10 +134,145 @@ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
    return olen;
}

void adb_set_autopoll_enabled(ADBBusState *s, bool enabled)
{
    if (s->autopoll_enabled != enabled) {
        s->autopoll_enabled = enabled;
        if (s->autopoll_enabled) {
            timer_mod(s->autopoll_timer,
                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
                      s->autopoll_rate_ms);
        } else {
            timer_del(s->autopoll_timer);
        }
    }
}

void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms)
{
    s->autopoll_rate_ms = rate_ms;

    if (s->autopoll_enabled) {
        timer_mod(s->autopoll_timer,
                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
                  s->autopoll_rate_ms);
    }
}

void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask)
{
    if (s->autopoll_mask != mask) {
        s->autopoll_mask = mask;
        if (s->autopoll_enabled && s->autopoll_mask) {
            timer_mod(s->autopoll_timer,
                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
                      s->autopoll_rate_ms);
        } else {
            timer_del(s->autopoll_timer);
        }
    }
}

void adb_autopoll_block(ADBBusState *s)
{
    s->autopoll_blocked = true;
    trace_adb_bus_autopoll_block(s->autopoll_blocked);

    if (s->autopoll_enabled) {
        timer_del(s->autopoll_timer);
    }
}

void adb_autopoll_unblock(ADBBusState *s)
{
    s->autopoll_blocked = false;
    trace_adb_bus_autopoll_block(s->autopoll_blocked);

    if (s->autopoll_enabled) {
        timer_mod(s->autopoll_timer,
                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
                  s->autopoll_rate_ms);
    }
}

static void adb_autopoll(void *opaque)
{
    ADBBusState *s = opaque;

    if (!s->autopoll_blocked) {
        trace_adb_bus_autopoll_cb(s->autopoll_mask);
        s->autopoll_cb(s->autopoll_cb_opaque);
        trace_adb_bus_autopoll_cb_done(s->autopoll_mask);
    }

    timer_mod(s->autopoll_timer,
              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
              s->autopoll_rate_ms);
}

void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque),
                                    void *opaque)
{
    s->autopoll_cb = cb;
    s->autopoll_cb_opaque = opaque;
}

static const VMStateDescription vmstate_adb_bus = {
    .name = "adb_bus",
    .version_id = 0,
    .minimum_version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_TIMER_PTR(autopoll_timer, ADBBusState),
        VMSTATE_BOOL(autopoll_enabled, ADBBusState),
        VMSTATE_UINT8(autopoll_rate_ms, ADBBusState),
        VMSTATE_UINT16(autopoll_mask, ADBBusState),
        VMSTATE_BOOL(autopoll_blocked, ADBBusState),
        VMSTATE_END_OF_LIST()
    }
};

static void adb_bus_reset(BusState *qbus)
{
    ADBBusState *adb_bus = ADB_BUS(qbus);

    adb_bus->autopoll_enabled = false;
    adb_bus->autopoll_mask = 0xffff;
    adb_bus->autopoll_rate_ms = 20;
}

static void adb_bus_realize(BusState *qbus, Error **errp)
{
    ADBBusState *adb_bus = ADB_BUS(qbus);

    adb_bus->autopoll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, adb_autopoll,
                                           adb_bus);

    vmstate_register(NULL, -1, &vmstate_adb_bus, adb_bus);
}

static void adb_bus_unrealize(BusState *qbus)
{
    ADBBusState *adb_bus = ADB_BUS(qbus);

    timer_del(adb_bus->autopoll_timer);

    vmstate_unregister(NULL, &vmstate_adb_bus, adb_bus);
}

static void adb_bus_class_init(ObjectClass *klass, void *data)
{
    BusClass *k = BUS_CLASS(klass);

    k->realize = adb_bus_realize;
    k->unrealize = adb_bus_unrealize;
    k->reset = adb_bus_reset;
}

static const TypeInfo adb_bus_type_info = {
    .name = TYPE_ADB_BUS,
    .parent = TYPE_BUS,
    .instance_size = sizeof(ADBBusState),
    .class_init = adb_bus_class_init,
};

const VMStateDescription vmstate_adb_device = {
@@ -117,18 +298,11 @@ static void adb_device_realizefn(DeviceState *dev, Error **errp)
    bus->devices[bus->nb_devices++] = d;
}

static Property adb_device_properties[] = {
    DEFINE_PROP_BOOL("disable-direct-reg3-writes", ADBDevice,
                     disable_direct_reg3_writes, false),
    DEFINE_PROP_END_OF_LIST(),
};

static void adb_device_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = adb_device_realizefn;
    device_class_set_props(dc, adb_device_properties);
    dc->bus_type = TYPE_ADB_BUS;
}

+17 −10
Original line number Diff line number Diff line
# See docs/devel/tracing.txt for syntax documentation.

# adb-kbd.c
adb_kbd_no_key(void) "Ignoring NO_KEY"
adb_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
adb_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
adb_kbd_request_change_addr(int devaddr) "change addr to 0x%x"
adb_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"
adb_device_kbd_no_key(void) "Ignoring NO_KEY"
adb_device_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
adb_device_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
adb_device_kbd_request_change_addr(int devaddr) "change addr to 0x%x"
adb_device_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"

# adb-mouse.c
adb_mouse_flush(void) "flush"
adb_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
adb_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
adb_mouse_request_change_addr(int devaddr) "change addr to 0x%x"
adb_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"
adb_device_mouse_flush(void) "flush"
adb_device_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
adb_device_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
adb_device_mouse_request_change_addr(int devaddr) "change addr to 0x%x"
adb_device_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"

# adb.c
adb_bus_request(uint8_t addr, const char *cmd, int size) "device 0x%x %s cmdsize=%d"
adb_bus_request_done(uint8_t addr, const char *cmd, int size) "device 0x%x %s replysize=%d"
adb_bus_autopoll_block(bool blocked) "blocked: %d"
adb_bus_autopoll_cb(uint16_t mask) "executing autopoll_cb with autopoll mask 0x%x"
adb_bus_autopoll_cb_done(uint16_t mask) "done executing autopoll_cb with autopoll mask 0x%x"

# pckbd.c
pckbd_kbd_read_data(uint32_t val) "0x%02x"
+269 −142

File changed.

Preview size limit exceeded, changes collapsed.

Loading