Add PowerPC power-management state check callback.
[qemu] / hw / adb.c
index de06f87..1e43792 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
 #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,6 +108,7 @@ ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
     d->bus = s;
     d->devaddr = devaddr;
     d->devreq = devreq;
+    d->devreset = devreset;
     d->opaque = opaque;
     return d;
 }
@@ -166,10 +176,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 +190,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 +227,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,13 +248,25 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
     return olen;
 }
 
+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);
+    adb_kbd_reset(d);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
 }
 
@@ -271,44 +299,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;
@@ -337,6 +370,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:
@@ -350,13 +386,25 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
     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;
+}
+
 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);
+    adb_mouse_reset(d);
+    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
 }