]> Git Repo - qemu.git/blobdiff - hw/adb.c
piix3: use new vmstate infrastructure
[qemu.git] / hw / adb.c
index de06f8789627a2c3c10e85b162caccae7daaa2b0..c57aeaac4a20bb9da5cde7f26415559c4cb867d9 100644 (file)
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -1,8 +1,8 @@
 /*
  * QEMU ADB support
- * 
+ *
  * Copyright (c) 2004 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "vl.h"
+#include "hw.h"
+#include "ppc_mac.h"
+#include "console.h"
+
+/* debug ADB */
+//#define DEBUG_ADB
+
+#ifdef DEBUG_ADB
+#define ADB_DPRINTF(fmt, ...) \
+do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define ADB_DPRINTF(fmt, ...)
+#endif
 
 /* ADB commands */
 #define ADB_BUSRESET           0x00
 #define ADB_MODEM      5
 #define ADB_MISC       7
 
+/* error codes */
+#define ADB_RET_NOTPRESENT (-2)
+
 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
 {
     ADBDevice *d;
     int devaddr, cmd, i;
 
     cmd = buf[0] & 0xf;
-    devaddr = buf[0] >> 4;
-    if (buf[1] == ADB_BUSRESET) {
-        obuf[0] = 0x00;
-        obuf[1] = 0x00;
-        return 2;
-    }
-    if (cmd == ADB_FLUSH) {
-        obuf[0] = 0x00;
-        obuf[1] = 0x00;
-        return 2;
+    if (cmd == ADB_BUSRESET) {
+        for(i = 0; i < s->nb_devices; i++) {
+            d = &s->devices[i];
+            if (d->devreset) {
+                d->devreset(d);
+            }
+        }
+        return 0;
     }
-
+    devaddr = buf[0] >> 4;
     for(i = 0; i < s->nb_devices; i++) {
         d = &s->devices[i];
         if (d->devaddr == devaddr) {
             return d->devreq(d, obuf, buf, len);
         }
     }
-    return 0;
+    return ADB_RET_NOTPRESENT;
 }
 
+/* XXX: move that to cuda ? */
 int adb_poll(ADBBusState *s, uint8_t *obuf)
 {
     ADBDevice *d;
     int olen, i;
+    uint8_t buf[1];
 
     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)
+        buf[0] = ADB_READREG | (d->devaddr << 4);
+        olen = adb_request(s, obuf + 1, buf, 1);
+        /* if there is data, we poll again the same device */
+        if (olen > 0) {
+            obuf[0] = buf[0];
+            olen++;
             break;
+        }
+        s->poll_index++;
     }
     return olen;
 }
 
-ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
-                               ADBDeviceRequest *devreq, 
+ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
+                               ADBDeviceRequest *devreq,
+                               ADBDeviceReset *devreset,
                                void *opaque)
 {
     ADBDevice *d;
@@ -99,7 +120,10 @@ ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
     d->bus = s;
     d->devaddr = devaddr;
     d->devreq = devreq;
+    d->devreset = devreset;
     d->opaque = opaque;
+    qemu_register_reset((QEMUResetHandler *)devreset, d);
+    d->devreset(d);
     return d;
 }
 
@@ -166,10 +190,10 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
                 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;
+            obuf[0] = adb_keycode | (keycode & 0x80);
+            /* NOTE: could put a second keycode if needed */
+            obuf[1] = 0xff;
+            olen = 2;
             ext_keycode = 0;
             break;
         }
@@ -180,10 +204,13 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                            const uint8_t *buf, int len)
 {
+    KBDState *s = d->opaque;
     int cmd, reg, olen;
 
-    if (!buf) {
-        return adb_kbd_poll(d, obuf);
+    if ((buf[0] & 0x0f) == ADB_FLUSH) {
+        /* flush keyboard fifo */
+        s->wptr = s->rptr = s->count = 0;
+        return 0;
     }
 
     cmd = buf[0] & 0xc;
@@ -214,6 +241,9 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
         break;
     case ADB_READREG:
         switch(reg) {
+        case 0:
+            olen = adb_kbd_poll(d, obuf);
+            break;
         case 1:
             break;
         case 2:
@@ -232,14 +262,52 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
     return olen;
 }
 
+static void adb_kbd_save(QEMUFile *f, void *opaque)
+{
+    KBDState *s = (KBDState *)opaque;
+
+    qemu_put_buffer(f, s->data, sizeof(s->data));
+    qemu_put_sbe32s(f, &s->rptr);
+    qemu_put_sbe32s(f, &s->wptr);
+    qemu_put_sbe32s(f, &s->count);
+}
+
+static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
+{
+    KBDState *s = (KBDState *)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_buffer(f, s->data, sizeof(s->data));
+    qemu_get_sbe32s(f, &s->rptr);
+    qemu_get_sbe32s(f, &s->wptr);
+    qemu_get_sbe32s(f, &s->count);
+
+    return 0;
+}
+
+static int adb_kbd_reset(ADBDevice *d)
+{
+    KBDState *s = d->opaque;
+
+    d->handler = 1;
+    d->devaddr = ADB_KEYBOARD;
+    memset(s, 0, sizeof(KBDState));
+
+    return 0;
+}
+
 void adb_kbd_init(ADBBusState *bus)
 {
     ADBDevice *d;
     KBDState *s;
     s = qemu_mallocz(sizeof(KBDState));
-    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, s);
-    d->handler = 1;
+    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
+                            adb_kbd_reset, s);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
+    register_savevm("adb_kbd", -1, 1, adb_kbd_save,
+                    adb_kbd_load, s);
 }
 
 /***************************************************************/
@@ -271,44 +339,49 @@ static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
     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 = 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 (s->buttons_state & MOUSE_EVENT_LBUTTON)
+
+    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
         dy |= 0x80;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
         dx |= 0x80;
-    
-    obuf[0] = (d->devaddr << 4) | 0x0c;
-    obuf[1] = dy;
-    obuf[2] = dx;
-    return 3;
+
+    obuf[0] = dy;
+    obuf[1] = dx;
+    return 2;
 }
 
 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                              const uint8_t *buf, int len)
 {
+    MouseState *s = d->opaque;
     int cmd, reg, olen;
-    
-    if (!buf) {
-        return adb_mouse_poll(d, obuf);
+
+    if ((buf[0] & 0x0f) == ADB_FLUSH) {
+        /* flush mouse fifo */
+        s->buttons_state = s->last_buttons_state;
+        s->dx = 0;
+        s->dy = 0;
+        s->dz = 0;
+        return 0;
     }
 
     cmd = buf[0] & 0xc;
@@ -316,6 +389,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
     olen = 0;
     switch(cmd) {
     case ADB_WRITEREG:
+        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
         switch(reg) {
         case 2:
             break;
@@ -337,6 +411,9 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
         break;
     case ADB_READREG:
         switch(reg) {
+        case 0:
+            olen = adb_mouse_poll(d, obuf);
+            break;
         case 1:
             break;
         case 3:
@@ -345,18 +422,60 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
             olen = 2;
             break;
         }
+        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
+                    obuf[0], obuf[1]);
         break;
     }
     return olen;
 }
 
+static int adb_mouse_reset(ADBDevice *d)
+{
+    MouseState *s = d->opaque;
+
+    d->handler = 2;
+    d->devaddr = ADB_MOUSE;
+    memset(s, 0, sizeof(MouseState));
+
+    return 0;
+}
+
+static void adb_mouse_save(QEMUFile *f, void *opaque)
+{
+    MouseState *s = (MouseState *)opaque;
+
+    qemu_put_sbe32s(f, &s->buttons_state);
+    qemu_put_sbe32s(f, &s->last_buttons_state);
+    qemu_put_sbe32s(f, &s->dx);
+    qemu_put_sbe32s(f, &s->dy);
+    qemu_put_sbe32s(f, &s->dz);
+}
+
+static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
+{
+    MouseState *s = (MouseState *)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_sbe32s(f, &s->buttons_state);
+    qemu_get_sbe32s(f, &s->last_buttons_state);
+    qemu_get_sbe32s(f, &s->dx);
+    qemu_get_sbe32s(f, &s->dy);
+    qemu_get_sbe32s(f, &s->dz);
+
+    return 0;
+}
+
 void adb_mouse_init(ADBBusState *bus)
 {
     ADBDevice *d;
     MouseState *s;
 
     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);
+    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
+                            adb_mouse_reset, s);
+    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
+    register_savevm("adb_mouse", -1, 1, adb_mouse_save,
+                    adb_mouse_load, s);
 }
This page took 0.033379 seconds and 4 git commands to generate.