diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-05-12 10:10:03 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-05-12 10:10:03 +0100 |
commit | de239d043fbfddbcb509e64186f963697127983e (patch) | |
tree | 572eae02c73c3850771a8895cc5712d14bccc8f0 /extras/mini-os | |
parent | aa7e17e11bb354d0cda598c7e6ccff29b210eb1c (diff) | |
download | xen-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/mini-os')
-rw-r--r-- | extras/mini-os/fbfront.c | 55 | ||||
-rw-r--r-- | extras/mini-os/include/fbfront.h | 3 | ||||
-rw-r--r-- | extras/mini-os/include/lib.h | 4 | ||||
-rw-r--r-- | extras/mini-os/kernel.c | 65 | ||||
-rw-r--r-- | extras/mini-os/lib/sys.c | 20 |
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++; |