aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-05-12 10:10:03 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-05-12 10:10:03 +0100
commitde239d043fbfddbcb509e64186f963697127983e (patch)
tree572eae02c73c3850771a8895cc5712d14bccc8f0 /extras
parentaa7e17e11bb354d0cda598c7e6ccff29b210eb1c (diff)
downloadxen-de239d043fbfddbcb509e64186f963697127983e.tar.gz
xen-de239d043fbfddbcb509e64186f963697127983e.tar.bz2
xen-de239d043fbfddbcb509e64186f963697127983e.zip
pvfb/ioemu: transmit refresh interval advice from backend to frontend
which permits the frontend to avoid useless polls. Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'extras')
-rw-r--r--extras/mini-os/fbfront.c55
-rw-r--r--extras/mini-os/include/fbfront.h3
-rw-r--r--extras/mini-os/include/lib.h4
-rw-r--r--extras/mini-os/kernel.c65
-rw-r--r--extras/mini-os/lib/sys.c20
5 files changed, 125 insertions, 22 deletions
diff --git a/extras/mini-os/fbfront.c b/extras/mini-os/fbfront.c
index 3a361b829c..d5acadf085 100644
--- a/extras/mini-os/fbfront.c
+++ b/extras/mini-os/fbfront.c
@@ -255,13 +255,57 @@ struct fbfront_dev {
int offset;
xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
};
void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
{
+#ifdef HAVE_LIBC
+ struct fbfront_dev *dev = data;
+ int fd = dev->fd;
+
+ files[fd].read = 1;
+#endif
wake_up(&fbfront_queue);
}
+int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n)
+{
+ struct xenfb_page *page = dev->page;
+ uint32_t prod, cons;
+ int i;
+
+#ifdef HAVE_LIBC
+ files[dev->fd].read = 0;
+ mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
+#endif
+
+ prod = page->in_prod;
+
+ if (prod == page->in_cons)
+ return 0;
+
+ rmb(); /* ensure we see ring contents up to prod */
+
+ for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
+ memcpy(buf + i, &XENFB_IN_RING_REF(page, cons), sizeof(*buf));
+
+ mb(); /* ensure we got ring contents */
+ page->in_cons = cons;
+ notify_remote_via_evtchn(dev->evtchn);
+
+#ifdef HAVE_LIBC
+ if (cons != prod)
+ /* still some events to read */
+ files[dev->fd].read = 1;
+#endif
+
+ return i;
+}
+
struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n)
{
xenbus_transaction_t xbt;
@@ -482,3 +526,14 @@ void shutdown_fbfront(struct fbfront_dev *dev)
free(dev->backend);
free(dev);
}
+
+#ifdef HAVE_LIBC
+int fbfront_open(struct fbfront_dev *dev)
+{
+ dev->fd = alloc_fd(FTYPE_FB);
+ printk("fb_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].fb.dev = dev;
+ return dev->fd;
+}
+#endif
+
diff --git a/extras/mini-os/include/fbfront.h b/extras/mini-os/include/fbfront.h
index 70b2f2a681..1e4d7ac6d9 100644
--- a/extras/mini-os/include/fbfront.h
+++ b/extras/mini-os/include/fbfront.h
@@ -1,4 +1,5 @@
#include <xen/io/kbdif.h>
+#include <xen/io/fbif.h>
#include <wait.h>
/* from <linux/input.h> */
@@ -36,6 +37,8 @@ struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width,
int fbfront_open(struct fbfront_dev *dev);
#endif
+int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n);
+extern struct wait_queue_head fbfront_queue;
void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height);
void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset);
diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index 0acb0fc4e2..b26a5eda39 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -141,6 +141,7 @@ enum fd_type {
FTYPE_TAP,
FTYPE_BLK,
FTYPE_KBD,
+ FTYPE_FB,
};
#define MAX_EVTCHN_PORTS 16
@@ -175,6 +176,9 @@ extern struct file {
struct {
struct kbdfront_dev *dev;
} kbd;
+ struct {
+ struct fbfront_dev *dev;
+ } fb;
struct {
/* To each xenbus FD is associated a queue of watch events for this
* FD. */
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index c37644bf4f..662acb0b00 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -260,6 +260,7 @@ static void blkfront_thread(void *p)
#define DEPTH 32
static uint32_t *fb;
+static int refresh_period = 50;
static struct fbfront_dev *fb_dev;
static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0);
@@ -333,6 +334,10 @@ static void clip_cursor(int *x, int *y)
static void refresh_cursor(int new_x, int new_y)
{
static int old_x = -1, old_y = -1;
+
+ if (!refresh_period)
+ return;
+
if (old_x != -1 && old_y != -1) {
fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff);
fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff);
@@ -358,43 +363,46 @@ static void kbdfront_thread(void *p)
down(&fbfront_sem);
refresh_cursor(x, y);
while (1) {
- union xenkbd_in_event event;
+ union xenkbd_in_event kbdevent;
+ union xenfb_in_event fbevent;
+ int sleep = 1;
add_waiter(w, kbdfront_queue);
+ add_waiter(w, fbfront_queue);
- if (kbdfront_receive(kbd_dev, &event, 1) == 0)
- schedule();
- else switch(event.type) {
+ while (kbdfront_receive(kbd_dev, &kbdevent, 1) != 0) {
+ sleep = 0;
+ switch(kbdevent.type) {
case XENKBD_TYPE_MOTION:
printk("motion x:%d y:%d z:%d\n",
- event.motion.rel_x,
- event.motion.rel_y,
- event.motion.rel_z);
- x += event.motion.rel_x;
- y += event.motion.rel_y;
- z += event.motion.rel_z;
+ kbdevent.motion.rel_x,
+ kbdevent.motion.rel_y,
+ kbdevent.motion.rel_z);
+ x += kbdevent.motion.rel_x;
+ y += kbdevent.motion.rel_y;
+ z += kbdevent.motion.rel_z;
clip_cursor(&x, &y);
refresh_cursor(x, y);
break;
case XENKBD_TYPE_POS:
printk("pos x:%d y:%d dz:%d\n",
- event.pos.abs_x,
- event.pos.abs_y,
- event.pos.rel_z);
- x = event.pos.abs_x;
- y = event.pos.abs_y;
- z = event.pos.rel_z;
+ kbdevent.pos.abs_x,
+ kbdevent.pos.abs_y,
+ kbdevent.pos.rel_z);
+ x = kbdevent.pos.abs_x;
+ y = kbdevent.pos.abs_y;
+ z = kbdevent.pos.rel_z;
clip_cursor(&x, &y);
refresh_cursor(x, y);
break;
case XENKBD_TYPE_KEY:
printk("key %d %s\n",
- event.key.keycode,
- event.key.pressed ? "pressed" : "released");
- if (event.key.keycode == BTN_LEFT) {
+ kbdevent.key.keycode,
+ kbdevent.key.pressed ? "pressed" : "released");
+ if (kbdevent.key.keycode == BTN_LEFT) {
printk("mouse %s at (%d,%d,%d)\n",
- event.key.pressed ? "clic" : "release", x, y, z);
- if (event.key.pressed) {
+ kbdevent.key.pressed ? "clic" : "release", x, y, z);
+ if (kbdevent.key.pressed) {
uint32_t color = rand();
fbfront_drawvert(x - 16, y - 16, y + 15, color);
fbfront_drawhoriz(x - 16, x + 15, y + 16, color);
@@ -402,13 +410,26 @@ static void kbdfront_thread(void *p)
fbfront_drawhoriz(x - 15, x + 16, y - 16, color);
fbfront_update(fb_dev, x - 16, y - 16, 33, 33);
}
- } else if (event.key.keycode == KEY_Q) {
+ } else if (kbdevent.key.keycode == KEY_Q) {
struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
do_exit();
}
break;
+ }
}
+ while (fbfront_receive(fb_dev, &fbevent, 1) != 0) {
+ sleep = 0;
+ switch(fbevent.type) {
+ case XENFB_TYPE_REFRESH_PERIOD:
+ refresh_period = fbevent.refresh_period.period;
+ printk("refresh period %d\n", refresh_period);
+ refresh_cursor(x, y);
+ break;
+ }
+ }
+ if (sleep)
+ schedule();
}
}
diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
index efa02e5af4..730caab552 100644
--- a/extras/mini-os/lib/sys.c
+++ b/extras/mini-os/lib/sys.c
@@ -249,6 +249,16 @@ int read(int fd, void *buf, size_t nbytes)
}
return ret * sizeof(union xenkbd_in_event);
}
+ case FTYPE_FB: {
+ int ret, n;
+ n = nbytes / sizeof(union xenfb_in_event);
+ ret = fbfront_receive(files[fd].fb.dev, buf, n);
+ if (ret <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return ret * sizeof(union xenfb_in_event);
+ }
case FTYPE_NONE:
case FTYPE_XENBUS:
case FTYPE_EVTCHN:
@@ -290,6 +300,7 @@ int write(int fd, const void *buf, size_t nbytes)
case FTYPE_EVTCHN:
case FTYPE_BLK:
case FTYPE_KBD:
+ case FTYPE_FB:
break;
}
printk("write(%d): Bad descriptor\n", fd);
@@ -348,6 +359,7 @@ int fsync(int fd) {
case FTYPE_TAP:
case FTYPE_BLK:
case FTYPE_KBD:
+ case FTYPE_FB:
break;
}
printk("fsync(%d): Bad descriptor\n", fd);
@@ -394,6 +406,10 @@ int close(int fd)
shutdown_kbdfront(files[fd].kbd.dev);
files[fd].type = FTYPE_NONE;
return 0;
+ case FTYPE_FB:
+ shutdown_fbfront(files[fd].fb.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
case FTYPE_NONE:
break;
}
@@ -485,6 +501,7 @@ int fstat(int fd, struct stat *buf)
case FTYPE_TAP:
case FTYPE_BLK:
case FTYPE_KBD:
+ case FTYPE_FB:
break;
}
@@ -513,6 +530,7 @@ int ftruncate(int fd, off_t length)
case FTYPE_TAP:
case FTYPE_BLK:
case FTYPE_KBD:
+ case FTYPE_FB:
break;
}
@@ -624,6 +642,7 @@ static const char file_types[] = {
[FTYPE_TAP] = 'T',
[FTYPE_BLK] = 'B',
[FTYPE_KBD] = 'K',
+ [FTYPE_FB] = 'G',
};
#ifdef LIBC_DEBUG
static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
@@ -732,6 +751,7 @@ static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exce
case FTYPE_TAP:
case FTYPE_BLK:
case FTYPE_KBD:
+ case FTYPE_FB:
if (FD_ISSET(i, readfds)) {
if (files[i].read)
n++;