diff options
-rw-r--r-- | hw/adb.c | 248 | ||||
-rw-r--r-- | hw/cuda.c | 50 | ||||
-rw-r--r-- | vl.h | 20 |
3 files changed, 210 insertions, 108 deletions
@@ -43,53 +43,53 @@ #define ADB_MODEM 5 #define ADB_MISC 7 -#define ADB_RET_OK 0 -#define ADB_RET_INUSE 1 -#define ADB_RET_NOTPRESENT 2 -#define ADB_RET_TIMEOUT 3 -#define ADB_RET_UNEXPECTED_RESULT 4 -#define ADB_RET_REQUEST_ERROR 5 -#define ADB_RET_BUS_ERROR 6 - - -static void adb_send_packet1(ADBBusState *s, uint8_t reply) -{ - adb_send_packet(s, &reply, 1); -} - -void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len) +int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) { ADBDevice *d; int devaddr, cmd, i; - uint8_t obuf[4]; cmd = buf[0] & 0xf; devaddr = buf[0] >> 4; if (buf[1] == ADB_BUSRESET) { obuf[0] = 0x00; obuf[1] = 0x00; - adb_send_packet(s, obuf, 2); - return; + return 2; } if (cmd == ADB_FLUSH) { obuf[0] = 0x00; obuf[1] = 0x00; - adb_send_packet(s, obuf, 2); - return; + return 2; } for(i = 0; i < s->nb_devices; i++) { d = &s->devices[i]; if (d->devaddr == devaddr) { - d->receive_packet(d, buf, len); - return; + return d->devreq(d, obuf, buf, len); } } - adb_send_packet1(s, ADB_RET_NOTPRESENT); + return 0; +} + +int adb_poll(ADBBusState *s, uint8_t *obuf) +{ + ADBDevice *d; + int olen, i; + + olen = 0; + for(i = 0; i < s->nb_devices; i++) { + if (s->poll_index >= s->nb_devices) + s->poll_index = 0; + d = &s->devices[s->poll_index]; + olen = d->devreq(d, obuf, NULL, 0); + s->poll_index++; + if (olen) + break; + } + return olen; } ADBDevice *adb_register_device(ADBBusState *s, int devaddr, - ADBDeviceReceivePacket *receive_packet, + ADBDeviceRequest *devreq, void *opaque) { ADBDevice *d; @@ -98,7 +98,7 @@ ADBDevice *adb_register_device(ADBBusState *s, int devaddr, d = &s->devices[s->nb_devices++]; d->bus = s; d->devaddr = devaddr; - d->receive_packet = receive_packet; + d->devreq = devreq; d->opaque = opaque; return d; } @@ -106,80 +106,108 @@ ADBDevice *adb_register_device(ADBBusState *s, int devaddr, /***************************************************************/ /* Keyboard ADB device */ +typedef struct KBDState { + uint8_t data[128]; + int rptr, wptr, count; +} KBDState; + static const uint8_t pc_to_adb_keycode[256] = { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48, 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1, 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9, 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96, 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83, - 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0, 0, 0, 0, 0, 0, - 76,125, 75,105,124,110,115, 62,116, 59, 60,119, 61,121,114,117, - 0, 0, 0, 0,127, 81, 0,113, 0, 0, 0, 0, 95, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119, + 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static void adb_kbd_put_keycode(void *opaque, int keycode) { - static int ext_keycode; ADBDevice *d = opaque; - uint8_t buf[4]; - int adb_keycode; - - if (keycode == 0xe0) { - ext_keycode = 1; - } else { - - if (ext_keycode) - adb_keycode = pc_to_adb_keycode[keycode | 0x80]; - else - adb_keycode = pc_to_adb_keycode[keycode & 0x7f]; - - buf[0] = 0x40; - buf[1] = (d->devaddr << 4) | 0x0c; - buf[2] = adb_keycode | (keycode & 0x80); - buf[3] = 0xff; - adb_send_packet(d->bus, buf, 4); - ext_keycode = 0; + KBDState *s = d->opaque; + + if (s->count < sizeof(s->data)) { + s->data[s->wptr] = keycode; + if (++s->wptr == sizeof(s->data)) + s->wptr = 0; + s->count++; } } -static void adb_kbd_receive_packet(ADBDevice *d, const uint8_t *buf, int len) +static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) { - int cmd, reg; - uint8_t obuf[4]; + static int ext_keycode; + KBDState *s = d->opaque; + int adb_keycode, keycode; + int olen; + + olen = 0; + for(;;) { + if (s->count == 0) + break; + keycode = s->data[s->rptr]; + if (++s->rptr == sizeof(s->data)) + s->rptr = 0; + s->count--; + + if (keycode == 0xe0) { + ext_keycode = 1; + } else { + if (ext_keycode) + adb_keycode = pc_to_adb_keycode[keycode | 0x80]; + else + adb_keycode = pc_to_adb_keycode[keycode & 0x7f]; + obuf[0] = (d->devaddr << 4) | 0x0c; + obuf[1] = adb_keycode | (keycode & 0x80); + obuf[2] = 0xff; + olen = 3; + ext_keycode = 0; + break; + } + } + return olen; +} + +static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, + const uint8_t *buf, int len) +{ + int cmd, reg, olen; + + if (!buf) { + return adb_kbd_poll(d, obuf); + } cmd = buf[0] & 0xc; reg = buf[0] & 0x3; + olen = 0; switch(cmd) { case ADB_WRITEREG: switch(reg) { case 2: /* LED status */ - adb_send_packet1(d->bus, ADB_RET_OK); break; case 3: switch(buf[2]) { case ADB_CMD_SELF_TEST: - adb_send_packet1(d->bus, ADB_RET_OK); break; case ADB_CMD_CHANGE_ID: case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; - adb_send_packet1(d->bus, ADB_RET_OK); break; default: /* XXX: check this */ d->devaddr = buf[1] & 0xf; d->handler = buf[2]; - adb_send_packet1(d->bus, ADB_RET_OK); break; } } @@ -187,98 +215,122 @@ static void adb_kbd_receive_packet(ADBDevice *d, const uint8_t *buf, int len) case ADB_READREG: switch(reg) { case 1: - adb_send_packet1(d->bus, ADB_RET_OK); break; case 2: - obuf[0] = ADB_RET_OK; - obuf[1] = 0x00; /* XXX: check this */ - obuf[2] = 0x07; /* led status */ - adb_send_packet(d->bus, obuf, 3); + obuf[0] = 0x00; /* XXX: check this */ + obuf[1] = 0x07; /* led status */ + olen = 2; break; case 3: - obuf[0] = ADB_RET_OK; - obuf[1] = d->handler; - obuf[2] = d->devaddr; - adb_send_packet(d->bus, obuf, 3); + obuf[0] = d->handler; + obuf[1] = d->devaddr; + olen = 2; break; } break; } + return olen; } void adb_kbd_init(ADBBusState *bus) { ADBDevice *d; - - d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_receive_packet, NULL); + KBDState *s; + s = qemu_mallocz(sizeof(KBDState)); + d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, s); + d->handler = 1; qemu_add_kbd_event_handler(adb_kbd_put_keycode, d); } /***************************************************************/ /* Mouse ADB device */ +typedef struct MouseState { + int buttons_state, last_buttons_state; + int dx, dy, dz; +} MouseState; + static void adb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state) { ADBDevice *d = opaque; - uint8_t buf[4]; + MouseState *s = d->opaque; + + s->dx += dx1; + s->dy += dy1; + s->dz += dz1; + s->buttons_state = buttons_state; +} + + +static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf) +{ + MouseState *s = d->opaque; int dx, dy; - dx = dx1; + if (s->last_buttons_state == s->buttons_state && + s->dx == 0 && s->dy == 0) + return 0; + + dx = s->dx; if (dx < -63) dx = -63; else if (dx > 63) dx = 63; - - dy = dy1; + + dy = s->dy; if (dy < -63) dy = -63; else if (dy > 63) dy = 63; - + + s->dx -= dx; + s->dy -= dy; + s->last_buttons_state = s->buttons_state; + dx &= 0x7f; dy &= 0x7f; - - if (buttons_state & MOUSE_EVENT_LBUTTON) + + if (s->buttons_state & MOUSE_EVENT_LBUTTON) dy |= 0x80; - if (buttons_state & MOUSE_EVENT_RBUTTON) + if (s->buttons_state & MOUSE_EVENT_RBUTTON) dx |= 0x80; - - buf[0] = 0x40; - buf[1] = (d->devaddr << 4) | 0x0c; - buf[2] = dy; - buf[3] = dx; - adb_send_packet(d->bus, buf, 4); + + obuf[0] = (d->devaddr << 4) | 0x0c; + obuf[1] = dy; + obuf[2] = dx; + return 3; } -static void adb_mouse_receive_packet(ADBDevice *d, const uint8_t *buf, int len) +static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, + const uint8_t *buf, int len) { - int cmd, reg; - uint8_t obuf[4]; + int cmd, reg, olen; + + if (!buf) { + return adb_mouse_poll(d, obuf); + } cmd = buf[0] & 0xc; reg = buf[0] & 0x3; + olen = 0; switch(cmd) { case ADB_WRITEREG: switch(reg) { case 2: - adb_send_packet1(d->bus, ADB_RET_OK); break; case 3: switch(buf[2]) { case ADB_CMD_SELF_TEST: - adb_send_packet1(d->bus, ADB_RET_OK); break; case ADB_CMD_CHANGE_ID: case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; - adb_send_packet1(d->bus, ADB_RET_OK); break; default: /* XXX: check this */ d->devaddr = buf[1] & 0xf; - adb_send_packet1(d->bus, ADB_RET_OK); break; } } @@ -286,23 +338,25 @@ static void adb_mouse_receive_packet(ADBDevice *d, const uint8_t *buf, int len) case ADB_READREG: switch(reg) { case 1: - adb_send_packet1(d->bus, ADB_RET_OK); break; case 3: - obuf[0] = ADB_RET_OK; - obuf[1] = d->handler; - obuf[2] = d->devaddr; - adb_send_packet(d->bus, obuf, 3); + obuf[0] = d->handler; + obuf[1] = d->devaddr; + olen = 2; break; } break; } + return olen; } void adb_mouse_init(ADBBusState *bus) { ADBDevice *d; + MouseState *s; - d = adb_register_device(bus, ADB_MOUSE, adb_mouse_receive_packet, NULL); + s = qemu_mallocz(sizeof(MouseState)); + d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, s); + d->handler = 2; qemu_add_mouse_event_handler(adb_mouse_event, d); } @@ -85,6 +85,7 @@ #define CUDA_COMBINED_FORMAT_IIC 0x25 #define CUDA_TIMER_FREQ (4700000 / 6) +#define CUDA_ADB_POLL_FREQ 50 typedef struct CUDATimer { unsigned int latch; @@ -121,6 +122,7 @@ typedef struct CUDAState { uint8_t autopoll; uint8_t data_in[128]; uint8_t data_out[16]; + QEMUTimer *adb_poll_timer; } CUDAState; static CUDAState cuda_state; @@ -469,15 +471,42 @@ void adb_send_packet(ADBBusState *bus, const uint8_t *buf, int len) cuda_send_packet_to_host(s, data, len + 1); } +void cuda_adb_poll(void *opaque) +{ + CUDAState *s = opaque; + uint8_t obuf[ADB_MAX_OUT_LEN + 2]; + int olen; + + olen = adb_poll(&adb_bus, obuf + 2); + if (olen > 0) { + obuf[0] = ADB_PACKET; + obuf[1] = 0x40; /* polled data */ + cuda_send_packet_to_host(s, obuf, olen + 2); + } + qemu_mod_timer(s->adb_poll_timer, + qemu_get_clock(vm_clock) + + (ticks_per_sec / CUDA_ADB_POLL_FREQ)); +} + static void cuda_receive_packet(CUDAState *s, const uint8_t *data, int len) { uint8_t obuf[16]; - int ti; + int ti, autopoll; switch(data[0]) { case CUDA_AUTOPOLL: - s->autopoll = data[1]; + autopoll = (data[1] != 0); + if (autopoll != s->autopoll) { + s->autopoll = autopoll; + if (autopoll) { + qemu_mod_timer(s->adb_poll_timer, + qemu_get_clock(vm_clock) + + (ticks_per_sec / CUDA_ADB_POLL_FREQ)); + } else { + qemu_del_timer(s->adb_poll_timer); + } + } obuf[0] = CUDA_PACKET; obuf[1] = data[1]; cuda_send_packet_to_host(s, obuf, 2); @@ -522,7 +551,20 @@ static void cuda_receive_packet_from_host(CUDAState *s, #endif switch(data[0]) { case ADB_PACKET: - adb_receive_packet(&adb_bus, data + 1, len - 1); + { + uint8_t obuf[ADB_MAX_OUT_LEN + 2]; + int olen; + olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1); + if (olen != 0) { + obuf[0] = ADB_PACKET; + obuf[1] = 0x00; + } else { + /* empty reply */ + obuf[0] = ADB_PACKET; + obuf[1] = 0x02; + } + cuda_send_packet_to_host(s, obuf, olen + 2); + } break; case CUDA_PACKET: cuda_receive_packet(s, data + 1, len - 1); @@ -574,6 +616,8 @@ int cuda_init(openpic_t *openpic, int irq) s->timers[1].latch = 0x10000; s->ier = T1_INT | SR_INT; set_counter(s, &s->timers[1], 0xffff); + + s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s); cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s); return cuda_mem_index; } @@ -528,8 +528,7 @@ PCIBus *pci_pmac_init(void); /* openpic.c */ typedef struct openpic_t openpic_t; void openpic_set_irq (openpic_t *opp, int n_IRQ, int level); -openpic_t *openpic_init (PCIBus *bus, - uint32_t isu_base, uint32_t idu_base, int nb_cpus); +openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus); /* vga.c */ @@ -727,28 +726,33 @@ int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, #define MAX_ADB_DEVICES 16 -typedef struct ADBDevice ADBDevice; +#define ADB_MAX_OUT_LEN 16 -typedef void ADBDeviceReceivePacket(ADBDevice *d, const uint8_t *buf, int len); +typedef struct ADBDevice ADBDevice; +/* buf = NULL means polling */ +typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, + const uint8_t *buf, int len); struct ADBDevice { struct ADBBusState *bus; int devaddr; int handler; - ADBDeviceReceivePacket *receive_packet; + ADBDeviceRequest *devreq; void *opaque; }; typedef struct ADBBusState { ADBDevice devices[MAX_ADB_DEVICES]; int nb_devices; + int poll_index; } ADBBusState; -void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len); -void adb_send_packet(ADBBusState *s, const uint8_t *buf, int len); +int adb_request(ADBBusState *s, uint8_t *buf_out, + const uint8_t *buf, int len); +int adb_poll(ADBBusState *s, uint8_t *buf_out); ADBDevice *adb_register_device(ADBBusState *s, int devaddr, - ADBDeviceReceivePacket *receive_packet, + ADBDeviceRequest *devreq, void *opaque); void adb_kbd_init(ADBBusState *bus); void adb_mouse_init(ADBBusState *bus); |