ia64/xen-unstable

changeset 17126:580bcd4c9642

minios: add PVFB support
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Feb 26 14:47:23 2008 +0000 (2008-02-26)
parents ca2cf5c1adcc
children c8b58f82d893
files extras/mini-os/fbfront.c extras/mini-os/include/fbfront.h extras/mini-os/include/lib.h extras/mini-os/kernel.c extras/mini-os/lib/sys.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/extras/mini-os/fbfront.c	Tue Feb 26 14:47:23 2008 +0000
     1.3 @@ -0,0 +1,468 @@
     1.4 +/*
     1.5 + * Frame Buffer + Keyboard driver for Mini-OS. 
     1.6 + * Samuel Thibault <samuel.thibault@eu.citrix.com>, 2008
     1.7 + * Based on blkfront.c.
     1.8 + */
     1.9 +
    1.10 +#include <os.h>
    1.11 +#include <xenbus.h>
    1.12 +#include <events.h>
    1.13 +#include <xen/io/kbdif.h>
    1.14 +#include <xen/io/fbif.h>
    1.15 +#include <xen/io/protocols.h>
    1.16 +#include <gnttab.h>
    1.17 +#include <xmalloc.h>
    1.18 +#include <fbfront.h>
    1.19 +#include <lib.h>
    1.20 +
    1.21 +DECLARE_WAIT_QUEUE_HEAD(kbdfront_queue);
    1.22 +
    1.23 +
    1.24 +
    1.25 +
    1.26 +
    1.27 +
    1.28 +struct kbdfront_dev {
    1.29 +    domid_t dom;
    1.30 +
    1.31 +    struct xenkbd_page *page;
    1.32 +    evtchn_port_t evtchn, local_port;
    1.33 +
    1.34 +    char *nodename;
    1.35 +    char *backend;
    1.36 +
    1.37 +    char *data;
    1.38 +    int width;
    1.39 +    int height;
    1.40 +    int depth;
    1.41 +    int line_length;
    1.42 +    int mem_length;
    1.43 +
    1.44 +#ifdef HAVE_LIBC
    1.45 +    int fd;
    1.46 +#endif
    1.47 +};
    1.48 +
    1.49 +void kbdfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
    1.50 +{
    1.51 +#ifdef HAVE_LIBC
    1.52 +    struct kbdfront_dev *dev = data;
    1.53 +    int fd = dev->fd;
    1.54 +
    1.55 +    files[fd].read = 1;
    1.56 +#endif
    1.57 +    wake_up(&kbdfront_queue);
    1.58 +}
    1.59 +
    1.60 +struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer)
    1.61 +{
    1.62 +    xenbus_transaction_t xbt;
    1.63 +    char* err;
    1.64 +    char* message=NULL;
    1.65 +    struct xenkbd_page *s;
    1.66 +    int retry=0;
    1.67 +    char* msg;
    1.68 +
    1.69 +    struct kbdfront_dev *dev;
    1.70 +
    1.71 +    if (!nodename)
    1.72 +        nodename = "device/vkbd/0";
    1.73 +
    1.74 +    char path[strlen(nodename) + 1 + 10 + 1];
    1.75 +
    1.76 +    printk("******************* KBDFRONT for %s **********\n\n\n", nodename);
    1.77 +
    1.78 +    dev = malloc(sizeof(*dev));
    1.79 +    dev->nodename = strdup(nodename);
    1.80 +
    1.81 +    evtchn_alloc_unbound_t op;
    1.82 +    op.dom = DOMID_SELF;
    1.83 +    snprintf(path, sizeof(path), "%s/backend-id", nodename);
    1.84 +    dev->dom = op.remote_dom = xenbus_read_integer(path); 
    1.85 +    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    1.86 +    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
    1.87 +    dev->local_port = bind_evtchn(op.port, kbdfront_handler, dev);
    1.88 +    dev->evtchn=op.port;
    1.89 +
    1.90 +    dev->page = s = (struct xenkbd_page*) alloc_page();
    1.91 +    memset(s,0,PAGE_SIZE);
    1.92 +
    1.93 +    s->in_cons = s->in_prod = 0;
    1.94 +    s->out_cons = s->out_prod = 0;
    1.95 +
    1.96 +    // FIXME: proper frees on failures
    1.97 +again:
    1.98 +    err = xenbus_transaction_start(&xbt);
    1.99 +    if (err) {
   1.100 +        printk("starting transaction\n");
   1.101 +    }
   1.102 +
   1.103 +    err = xenbus_printf(xbt, nodename, "page-ref","%u", virt_to_mfn(s));
   1.104 +    if (err) {
   1.105 +        message = "writing page-ref";
   1.106 +        goto abort_transaction;
   1.107 +    }
   1.108 +    err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
   1.109 +    if (err) {
   1.110 +        message = "writing event-channel";
   1.111 +        goto abort_transaction;
   1.112 +    }
   1.113 +    if (abs_pointer) {
   1.114 +        err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1");
   1.115 +        if (err) {
   1.116 +            message = "writing event-channel";
   1.117 +            goto abort_transaction;
   1.118 +        }
   1.119 +    }
   1.120 +
   1.121 +    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
   1.122 +    if (err)
   1.123 +        printk("error writing initialized: %s\n", err);
   1.124 +
   1.125 +
   1.126 +    err = xenbus_transaction_end(xbt, 0, &retry);
   1.127 +    if (retry) {
   1.128 +            goto again;
   1.129 +        printk("completing transaction\n");
   1.130 +    }
   1.131 +
   1.132 +    goto done;
   1.133 +
   1.134 +abort_transaction:
   1.135 +    xenbus_transaction_end(xbt, 1, &retry);
   1.136 +    return NULL;
   1.137 +
   1.138 +done:
   1.139 +
   1.140 +    snprintf(path, sizeof(path), "%s/backend", nodename);
   1.141 +    msg = xenbus_read(XBT_NIL, path, &dev->backend);
   1.142 +    if (msg) {
   1.143 +        printk("Error %s when reading the backend path %s\n", msg, path);
   1.144 +        return NULL;
   1.145 +    }
   1.146 +
   1.147 +    printk("backend at %s\n", dev->backend);
   1.148 +
   1.149 +    {
   1.150 +        char path[strlen(dev->backend) + 1 + 6 + 1];
   1.151 +
   1.152 +        snprintf(path, sizeof(path), "%s/state", dev->backend);
   1.153 +
   1.154 +        xenbus_watch_path(XBT_NIL, path);
   1.155 +
   1.156 +        xenbus_wait_for_value(path,"4");
   1.157 +
   1.158 +        xenbus_unwatch_path(XBT_NIL, path);
   1.159 +
   1.160 +        printk("%s connected\n", dev->backend);
   1.161 +
   1.162 +        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
   1.163 +    }
   1.164 +
   1.165 +    printk("************************** KBDFRONT\n");
   1.166 +
   1.167 +    return dev;
   1.168 +}
   1.169 +
   1.170 +int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n)
   1.171 +{
   1.172 +    struct xenkbd_page *page = dev->page;
   1.173 +    uint32_t prod, cons;
   1.174 +    int i;
   1.175 +
   1.176 +#ifdef HAVE_LIBC
   1.177 +    files[dev->fd].read = 0;
   1.178 +    mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
   1.179 +#endif
   1.180 +
   1.181 +    prod = page->in_prod;
   1.182 +
   1.183 +    if (prod == page->in_cons)
   1.184 +        return 0;
   1.185 +
   1.186 +    rmb();      /* ensure we see ring contents up to prod */
   1.187 +
   1.188 +    for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
   1.189 +        memcpy(buf + i, &XENKBD_IN_RING_REF(page, cons), sizeof(*buf));
   1.190 +
   1.191 +    mb();       /* ensure we got ring contents */
   1.192 +    page->in_cons = cons;
   1.193 +    notify_remote_via_evtchn(dev->evtchn);
   1.194 +
   1.195 +#ifdef HAVE_LIBC
   1.196 +    if (cons != prod)
   1.197 +        /* still some events to read */
   1.198 +        files[dev->fd].read = 1;
   1.199 +#endif
   1.200 +
   1.201 +    return i;
   1.202 +}
   1.203 +
   1.204 +
   1.205 +void shutdown_kbdfront(struct kbdfront_dev *dev)
   1.206 +{
   1.207 +    char* err;
   1.208 +    char *nodename = dev->nodename;
   1.209 +
   1.210 +    char path[strlen(dev->backend) + 1 + 5 + 1];
   1.211 +
   1.212 +    printk("close kbd: backend at %s\n",dev->backend);
   1.213 +
   1.214 +    snprintf(path, sizeof(path), "%s/state", dev->backend);
   1.215 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   1.216 +    xenbus_wait_for_value(path,"5");
   1.217 +
   1.218 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   1.219 +    xenbus_wait_for_value(path,"6");
   1.220 +
   1.221 +    unbind_evtchn(dev->local_port);
   1.222 +
   1.223 +    free_pages(dev->page,0);
   1.224 +    free(nodename);
   1.225 +    free(dev->backend);
   1.226 +    free(dev);
   1.227 +}
   1.228 +
   1.229 +#ifdef HAVE_LIBC
   1.230 +int kbdfront_open(struct kbdfront_dev *dev)
   1.231 +{
   1.232 +    dev->fd = alloc_fd(FTYPE_KBD);
   1.233 +    printk("kbd_open(%s) -> %d\n", dev->nodename, dev->fd);
   1.234 +    files[dev->fd].kbd.dev = dev;
   1.235 +    return dev->fd;
   1.236 +}
   1.237 +#endif
   1.238 +
   1.239 +
   1.240 +
   1.241 +
   1.242 +
   1.243 +DECLARE_WAIT_QUEUE_HEAD(fbfront_queue);
   1.244 +
   1.245 +
   1.246 +
   1.247 +
   1.248 +
   1.249 +
   1.250 +struct fbfront_dev {
   1.251 +    domid_t dom;
   1.252 +
   1.253 +    struct xenfb_page *page;
   1.254 +    evtchn_port_t evtchn, local_port;
   1.255 +
   1.256 +    char *nodename;
   1.257 +    char *backend;
   1.258 +
   1.259 +    char *data;
   1.260 +    int width;
   1.261 +    int height;
   1.262 +    int depth;
   1.263 +    int line_length;
   1.264 +    int mem_length;
   1.265 +};
   1.266 +
   1.267 +void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
   1.268 +{
   1.269 +    wake_up(&fbfront_queue);
   1.270 +}
   1.271 +
   1.272 +struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int height, int depth, int line_length, int mem_length)
   1.273 +{
   1.274 +    xenbus_transaction_t xbt;
   1.275 +    char* err;
   1.276 +    char* message=NULL;
   1.277 +    struct xenfb_page *s;
   1.278 +    int retry=0;
   1.279 +    char* msg;
   1.280 +    int i, j;
   1.281 +    struct fbfront_dev *dev;
   1.282 +
   1.283 +    if (!nodename)
   1.284 +        nodename = "device/vfb/0";
   1.285 +
   1.286 +    char path[strlen(nodename) + 1 + 10 + 1];
   1.287 +
   1.288 +    printk("******************* FBFRONT for %s **********\n\n\n", nodename);
   1.289 +
   1.290 +    dev = malloc(sizeof(*dev));
   1.291 +    dev->nodename = strdup(nodename);
   1.292 +
   1.293 +    evtchn_alloc_unbound_t op;
   1.294 +    op.dom = DOMID_SELF;
   1.295 +    snprintf(path, sizeof(path), "%s/backend-id", nodename);
   1.296 +    dev->dom = op.remote_dom = xenbus_read_integer(path); 
   1.297 +    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
   1.298 +    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
   1.299 +    dev->local_port = bind_evtchn(op.port, fbfront_handler, dev);
   1.300 +    dev->evtchn=op.port;
   1.301 +
   1.302 +    dev->page = s = (struct xenfb_page*) alloc_page();
   1.303 +    memset(s,0,PAGE_SIZE);
   1.304 +
   1.305 +    s->in_cons = s->in_prod = 0;
   1.306 +    s->out_cons = s->out_prod = 0;
   1.307 +    dev->width = s->width = width;
   1.308 +    dev->height = s->height = height;
   1.309 +    dev->depth = s->depth = depth;
   1.310 +    dev->line_length = s->line_length = line_length;
   1.311 +    dev->mem_length = s->mem_length = mem_length;
   1.312 +
   1.313 +    ASSERT(!((unsigned long)data & ~PAGE_MASK));
   1.314 +    dev->data = data;
   1.315 +
   1.316 +    const int max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
   1.317 +    unsigned long mapped = 0;
   1.318 +
   1.319 +    for (i = 0; mapped < mem_length && i < max_pd; i++) {
   1.320 +        unsigned long *pd = (unsigned long *) alloc_page();
   1.321 +        for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned long); j++) {
   1.322 +            pd[j] = virt_to_mfn((unsigned long) data + mapped);
   1.323 +            mapped += PAGE_SIZE;
   1.324 +        }
   1.325 +        for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
   1.326 +            pd[j] = 0;
   1.327 +        s->pd[i] = virt_to_mfn(pd);
   1.328 +    }
   1.329 +    for ( ; i < max_pd; i++)
   1.330 +        s->pd[i] = 0;
   1.331 +
   1.332 +
   1.333 +    // FIXME: proper frees on failures
   1.334 +again:
   1.335 +    err = xenbus_transaction_start(&xbt);
   1.336 +    if (err) {
   1.337 +        printk("starting transaction\n");
   1.338 +    }
   1.339 +
   1.340 +    err = xenbus_printf(xbt, nodename, "page-ref","%u", virt_to_mfn(s));
   1.341 +    if (err) {
   1.342 +        message = "writing page-ref";
   1.343 +        goto abort_transaction;
   1.344 +    }
   1.345 +    err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
   1.346 +    if (err) {
   1.347 +        message = "writing event-channel";
   1.348 +        goto abort_transaction;
   1.349 +    }
   1.350 +    err = xenbus_printf(xbt, nodename, "protocol", "%s",
   1.351 +                        XEN_IO_PROTO_ABI_NATIVE);
   1.352 +    if (err) {
   1.353 +        message = "writing event-channel";
   1.354 +        goto abort_transaction;
   1.355 +    }
   1.356 +    err = xenbus_printf(xbt, nodename, "feature-update", "1");
   1.357 +    if (err) {
   1.358 +        message = "writing event-channel";
   1.359 +        goto abort_transaction;
   1.360 +    }
   1.361 +
   1.362 +    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
   1.363 +
   1.364 +
   1.365 +    err = xenbus_transaction_end(xbt, 0, &retry);
   1.366 +    if (retry) {
   1.367 +            goto again;
   1.368 +        printk("completing transaction\n");
   1.369 +    }
   1.370 +
   1.371 +    goto done;
   1.372 +
   1.373 +abort_transaction:
   1.374 +    xenbus_transaction_end(xbt, 1, &retry);
   1.375 +    return NULL;
   1.376 +
   1.377 +done:
   1.378 +
   1.379 +    snprintf(path, sizeof(path), "%s/backend", nodename);
   1.380 +    msg = xenbus_read(XBT_NIL, path, &dev->backend);
   1.381 +    if (msg) {
   1.382 +        printk("Error %s when reading the backend path %s\n", msg, path);
   1.383 +        return NULL;
   1.384 +    }
   1.385 +
   1.386 +    printk("backend at %s\n", dev->backend);
   1.387 +
   1.388 +    {
   1.389 +        char path[strlen(dev->backend) + 1 + 6 + 1];
   1.390 +
   1.391 +        snprintf(path, sizeof(path), "%s/state", dev->backend);
   1.392 +
   1.393 +        xenbus_watch_path(XBT_NIL, path);
   1.394 +
   1.395 +        xenbus_wait_for_value(path,"4");
   1.396 +
   1.397 +        printk("%s connected\n", dev->backend);
   1.398 +
   1.399 +        xenbus_unwatch_path(XBT_NIL, path);
   1.400 +
   1.401 +        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
   1.402 +    }
   1.403 +
   1.404 +    printk("************************** FBFRONT\n");
   1.405 +
   1.406 +    return dev;
   1.407 +}
   1.408 +
   1.409 +void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height)
   1.410 +{
   1.411 +    struct xenfb_page *page = dev->page;
   1.412 +    uint32_t prod;
   1.413 +    DEFINE_WAIT(w);
   1.414 +
   1.415 +    if (x < 0) {
   1.416 +        width += x;
   1.417 +        x = 0;
   1.418 +    }
   1.419 +    if (x + width > dev->width)
   1.420 +        width = dev->width - x;
   1.421 +
   1.422 +    if (y < 0) {
   1.423 +        height += y;
   1.424 +        y = 0;
   1.425 +    }
   1.426 +    if (y + height > dev->height)
   1.427 +        height = dev->height - y;
   1.428 +
   1.429 +    if (width <= 0 || height <= 0)
   1.430 +        return;
   1.431 +
   1.432 +    add_waiter(w, fbfront_queue);
   1.433 +    while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
   1.434 +        schedule();
   1.435 +    remove_waiter(w);
   1.436 +
   1.437 +    prod = page->out_prod;
   1.438 +    mb(); /* ensure ring space available */
   1.439 +    XENFB_OUT_RING_REF(page, prod).type = XENFB_TYPE_UPDATE;
   1.440 +    XENFB_OUT_RING_REF(page, prod).update.x = x;
   1.441 +    XENFB_OUT_RING_REF(page, prod).update.y = y;
   1.442 +    XENFB_OUT_RING_REF(page, prod).update.width = width;
   1.443 +    XENFB_OUT_RING_REF(page, prod).update.height = height;
   1.444 +    wmb(); /* ensure ring contents visible */
   1.445 +    page->out_prod = prod + 1;
   1.446 +    notify_remote_via_evtchn(dev->evtchn);
   1.447 +}
   1.448 +
   1.449 +void shutdown_fbfront(struct fbfront_dev *dev)
   1.450 +{
   1.451 +    char* err;
   1.452 +    char *nodename = dev->nodename;
   1.453 +
   1.454 +    char path[strlen(dev->backend) + 1 + 5 + 1];
   1.455 +
   1.456 +    printk("close fb: backend at %s\n",dev->backend);
   1.457 +
   1.458 +    snprintf(path, sizeof(path), "%s/state", dev->backend);
   1.459 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   1.460 +    xenbus_wait_for_value(path,"5");
   1.461 +
   1.462 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   1.463 +    xenbus_wait_for_value(path,"6");
   1.464 +
   1.465 +    unbind_evtchn(dev->local_port);
   1.466 +
   1.467 +    free_pages(dev->page,0);
   1.468 +    free(nodename);
   1.469 +    free(dev->backend);
   1.470 +    free(dev);
   1.471 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/extras/mini-os/include/fbfront.h	Tue Feb 26 14:47:23 2008 +0000
     2.3 @@ -0,0 +1,38 @@
     2.4 +#include <xen/io/kbdif.h>
     2.5 +#include <wait.h>
     2.6 +
     2.7 +/* from <linux/input.h> */
     2.8 +#ifndef BTN_LEFT
     2.9 +#define BTN_LEFT 0x110
    2.10 +#endif
    2.11 +#ifndef BTN_RIGHT
    2.12 +#define BTN_RIGHT 0x111
    2.13 +#endif
    2.14 +#ifndef BTN_MIDDLE
    2.15 +#define BTN_MIDDLE 0x112
    2.16 +#endif
    2.17 +#ifndef KEY_Q
    2.18 +#define KEY_Q 16
    2.19 +#endif
    2.20 +
    2.21 +
    2.22 +struct kbdfront_dev;
    2.23 +struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer);
    2.24 +#ifdef HAVE_LIBC
    2.25 +int kbdfront_open(struct kbdfront_dev *dev);
    2.26 +#endif
    2.27 +
    2.28 +int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n);
    2.29 +extern struct wait_queue_head kbdfront_queue;
    2.30 +
    2.31 +void shutdown_kbdfront(struct kbdfront_dev *dev);
    2.32 +
    2.33 +
    2.34 +struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int height, int depth, int line_length, int mem_length);
    2.35 +#ifdef HAVE_LIBC
    2.36 +int fbfront_open(struct fbfront_dev *dev);
    2.37 +#endif
    2.38 +
    2.39 +void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height);
    2.40 +
    2.41 +void shutdown_fbfront(struct fbfront_dev *dev);
     3.1 --- a/extras/mini-os/include/lib.h	Tue Feb 26 14:46:57 2008 +0000
     3.2 +++ b/extras/mini-os/include/lib.h	Tue Feb 26 14:47:23 2008 +0000
     3.3 @@ -140,6 +140,7 @@ enum fd_type {
     3.4      FTYPE_SOCKET,
     3.5      FTYPE_TAP,
     3.6      FTYPE_BLK,
     3.7 +    FTYPE_KBD,
     3.8  };
     3.9  
    3.10  #define MAX_EVTCHN_PORTS 16
    3.11 @@ -171,6 +172,9 @@ extern struct file {
    3.12  	struct {
    3.13  	    struct blkfront_dev *dev;
    3.14  	} blk;
    3.15 +	struct {
    3.16 +	    struct kbdfront_dev *dev;
    3.17 +	} kbd;
    3.18          struct {
    3.19              /* To each xenbus FD is associated a queue of watch events for this
    3.20               * FD.  */
     4.1 --- a/extras/mini-os/kernel.c	Tue Feb 26 14:46:57 2008 +0000
     4.2 +++ b/extras/mini-os/kernel.c	Tue Feb 26 14:47:23 2008 +0000
     4.3 @@ -39,6 +39,7 @@
     4.4  #include <gnttab.h>
     4.5  #include <netfront.h>
     4.6  #include <blkfront.h>
     4.7 +#include <fbfront.h>
     4.8  #include <fs.h>
     4.9  #include <xmalloc.h>
    4.10  #include <fcntl.h>
    4.11 @@ -248,6 +249,152 @@ static void blkfront_thread(void *p)
    4.12      }
    4.13  }
    4.14  
    4.15 +#define WIDTH 800
    4.16 +#define HEIGHT 600
    4.17 +#define DEPTH 32
    4.18 +
    4.19 +static uint32_t *fb;
    4.20 +static struct fbfront_dev *fb_dev;
    4.21 +static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0);
    4.22 +
    4.23 +static void fbfront_drawvert(int x, int y1, int y2, uint32_t color)
    4.24 +{
    4.25 +    int y;
    4.26 +    if (x < 0)
    4.27 +        return;
    4.28 +    if (x >= WIDTH)
    4.29 +        return;
    4.30 +    if (y1 < 0)
    4.31 +        y1 = 0;
    4.32 +    if (y2 >= HEIGHT)
    4.33 +        y2 = HEIGHT-1;
    4.34 +    for (y = y1; y <= y2; y++)
    4.35 +        fb[x + y*WIDTH] ^= color;
    4.36 +}
    4.37 +
    4.38 +static void fbfront_drawhoriz(int x1, int x2, int y, uint32_t color)
    4.39 +{
    4.40 +    int x;
    4.41 +    if (y < 0)
    4.42 +        return;
    4.43 +    if (y >= HEIGHT)
    4.44 +        return;
    4.45 +    if (x1 < 0)
    4.46 +        x1 = 0;
    4.47 +    if (x2 >= WIDTH)
    4.48 +        x2 = WIDTH-1;
    4.49 +    for (x = x1; x <= x2; x++)
    4.50 +        fb[x + y*WIDTH] ^= color;
    4.51 +}
    4.52 +
    4.53 +static void fbfront_thread(void *p)
    4.54 +{
    4.55 +    size_t line_length = WIDTH * (DEPTH / 8);
    4.56 +    size_t memsize = HEIGHT * line_length;
    4.57 +
    4.58 +    fb = _xmalloc(memsize, PAGE_SIZE);
    4.59 +    fb_dev = init_fbfront(NULL, fb, WIDTH, HEIGHT, DEPTH, line_length, memsize);
    4.60 +    if (!fb_dev) {
    4.61 +        xfree(fb);
    4.62 +        return;
    4.63 +    }
    4.64 +    up(&fbfront_sem);
    4.65 +}
    4.66 +
    4.67 +static void clip_cursor(int *x, int *y)
    4.68 +{
    4.69 +    if (*x < 0)
    4.70 +        *x = 0;
    4.71 +    if (*x >= WIDTH)
    4.72 +        *x = WIDTH - 1;
    4.73 +    if (*y < 0)
    4.74 +        *y = 0;
    4.75 +    if (*y >= HEIGHT)
    4.76 +        *y = HEIGHT - 1;
    4.77 +}
    4.78 +
    4.79 +static void refresh_cursor(int new_x, int new_y)
    4.80 +{
    4.81 +    static int old_x = -1, old_y = -1;
    4.82 +    if (old_x != -1 && old_y != -1) {
    4.83 +        fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff);
    4.84 +        fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff);
    4.85 +        fbfront_update(fb_dev, old_x, old_y, 9, 9);
    4.86 +    }
    4.87 +    old_x = new_x;
    4.88 +    old_y = new_y;
    4.89 +    fbfront_drawvert(new_x, new_y + 1, new_y + 8, 0xffffffff);
    4.90 +    fbfront_drawhoriz(new_x + 1, new_x + 8, new_y, 0xffffffff);
    4.91 +    fbfront_update(fb_dev, new_x, new_y, 9, 9);
    4.92 +}
    4.93 +
    4.94 +static void kbdfront_thread(void *p)
    4.95 +{
    4.96 +    struct kbdfront_dev *kbd_dev;
    4.97 +    DEFINE_WAIT(w);
    4.98 +    int x = WIDTH / 2, y = HEIGHT / 2, z;
    4.99 +
   4.100 +    kbd_dev = init_kbdfront(NULL, 1);
   4.101 +    if (!kbd_dev)
   4.102 +        return;
   4.103 +
   4.104 +    down(&fbfront_sem);
   4.105 +    refresh_cursor(x, y);
   4.106 +    while (1) {
   4.107 +        union xenkbd_in_event event;
   4.108 +
   4.109 +        add_waiter(w, kbdfront_queue);
   4.110 +
   4.111 +        if (kbdfront_receive(kbd_dev, &event, 1) == 0)
   4.112 +            schedule();
   4.113 +        else switch(event.type) {
   4.114 +            case XENKBD_TYPE_MOTION:
   4.115 +                printk("motion x:%d y:%d z:%d\n",
   4.116 +                        event.motion.rel_x,
   4.117 +                        event.motion.rel_y,
   4.118 +                        event.motion.rel_z);
   4.119 +                x += event.motion.rel_x;
   4.120 +                y += event.motion.rel_y;
   4.121 +                z += event.motion.rel_z;
   4.122 +                clip_cursor(&x, &y);
   4.123 +                refresh_cursor(x, y);
   4.124 +                break;
   4.125 +            case XENKBD_TYPE_POS:
   4.126 +                printk("pos x:%d y:%d z:%d\n",
   4.127 +                        event.pos.abs_x,
   4.128 +                        event.pos.abs_y,
   4.129 +                        event.pos.abs_z);
   4.130 +                x = event.pos.abs_x;
   4.131 +                y = event.pos.abs_y;
   4.132 +                z = event.pos.abs_z;
   4.133 +                clip_cursor(&x, &y);
   4.134 +                refresh_cursor(x, y);
   4.135 +                break;
   4.136 +            case XENKBD_TYPE_KEY:
   4.137 +                printk("key %d %s\n",
   4.138 +                        event.key.keycode,
   4.139 +                        event.key.pressed ? "pressed" : "released");
   4.140 +                if (event.key.keycode == BTN_LEFT) {
   4.141 +                    printk("mouse %s at (%d,%d,%d)\n",
   4.142 +                            event.key.pressed ? "clic" : "release", x, y, z);
   4.143 +                    if (event.key.pressed) {
   4.144 +                        uint32_t color = rand();
   4.145 +                        fbfront_drawvert(x - 16, y - 16, y + 15, color);
   4.146 +                        fbfront_drawhoriz(x - 16, x + 15, y + 16, color);
   4.147 +                        fbfront_drawvert(x + 16, y - 15, y + 16, color);
   4.148 +                        fbfront_drawhoriz(x - 15, x + 16, y - 16, color);
   4.149 +                        fbfront_update(fb_dev, x - 16, y - 16, 33, 33);
   4.150 +                    }
   4.151 +                } else if (event.key.keycode == KEY_Q) {
   4.152 +                    struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
   4.153 +                    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
   4.154 +                    do_exit();
   4.155 +                }
   4.156 +                break;
   4.157 +        }
   4.158 +    }
   4.159 +}
   4.160 +
   4.161  static void fs_thread(void *p)
   4.162  {
   4.163      init_fs_frontend();
   4.164 @@ -261,6 +408,8 @@ static void fs_thread(void *p)
   4.165      create_thread("periodic_thread", periodic_thread, si);
   4.166      create_thread("netfront", netfront_thread, si);
   4.167      create_thread("blkfront", blkfront_thread, si);
   4.168 +    create_thread("fbfront", fbfront_thread, si);
   4.169 +    create_thread("kbdfront", kbdfront_thread, si);
   4.170      create_thread("fs-frontend", fs_thread, si);
   4.171      return 0;
   4.172  }
     5.1 --- a/extras/mini-os/lib/sys.c	Tue Feb 26 14:46:57 2008 +0000
     5.2 +++ b/extras/mini-os/lib/sys.c	Tue Feb 26 14:47:23 2008 +0000
     5.3 @@ -26,6 +26,7 @@
     5.4  #include <wait.h>
     5.5  #include <netfront.h>
     5.6  #include <blkfront.h>
     5.7 +#include <fbfront.h>
     5.8  #include <xenbus.h>
     5.9  #include <xs.h>
    5.10  
    5.11 @@ -221,6 +222,16 @@ int read(int fd, void *buf, size_t nbyte
    5.12  	    }
    5.13  	    return ret;
    5.14  	}
    5.15 +        case FTYPE_KBD: {
    5.16 +            int ret, n;
    5.17 +            n = nbytes / sizeof(union xenkbd_in_event);
    5.18 +            ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
    5.19 +	    if (ret <= 0) {
    5.20 +		errno = EAGAIN;
    5.21 +		return -1;
    5.22 +	    }
    5.23 +	    return ret * sizeof(union xenkbd_in_event);
    5.24 +        }
    5.25  	case FTYPE_NONE:
    5.26  	case FTYPE_XENBUS:
    5.27  	case FTYPE_EVTCHN:
    5.28 @@ -261,6 +272,7 @@ int write(int fd, const void *buf, size_
    5.29  	case FTYPE_XENBUS:
    5.30  	case FTYPE_EVTCHN:
    5.31  	case FTYPE_BLK:
    5.32 +	case FTYPE_KBD:
    5.33  	    break;
    5.34      }
    5.35      printk("write(%d): Bad descriptor\n", fd);
    5.36 @@ -318,6 +330,7 @@ int fsync(int fd) {
    5.37  	case FTYPE_EVTCHN:
    5.38  	case FTYPE_TAP:
    5.39  	case FTYPE_BLK:
    5.40 +	case FTYPE_KBD:
    5.41  	    break;
    5.42      }
    5.43      printk("fsync(%d): Bad descriptor\n", fd);
    5.44 @@ -360,6 +373,10 @@ int close(int fd)
    5.45              shutdown_blkfront(files[fd].blk.dev);
    5.46  	    files[fd].type = FTYPE_NONE;
    5.47  	    return 0;
    5.48 +	case FTYPE_KBD:
    5.49 +            shutdown_kbdfront(files[fd].kbd.dev);
    5.50 +            files[fd].type = FTYPE_NONE;
    5.51 +            return 0;
    5.52  	case FTYPE_NONE:
    5.53  	    break;
    5.54      }
    5.55 @@ -450,6 +467,7 @@ int fstat(int fd, struct stat *buf)
    5.56  	case FTYPE_EVTCHN:
    5.57  	case FTYPE_TAP:
    5.58  	case FTYPE_BLK:
    5.59 +	case FTYPE_KBD:
    5.60  	    break;
    5.61      }
    5.62  
    5.63 @@ -477,6 +495,7 @@ int ftruncate(int fd, off_t length)
    5.64  	case FTYPE_EVTCHN:
    5.65  	case FTYPE_TAP:
    5.66  	case FTYPE_BLK:
    5.67 +	case FTYPE_KBD:
    5.68  	    break;
    5.69      }
    5.70  
    5.71 @@ -587,6 +606,7 @@ static const char file_types[] = {
    5.72      [FTYPE_SOCKET]	= 'S',
    5.73      [FTYPE_TAP]		= 'T',
    5.74      [FTYPE_BLK]		= 'B',
    5.75 +    [FTYPE_KBD]		= 'K',
    5.76  };
    5.77  #ifdef LIBC_DEBUG
    5.78  static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
    5.79 @@ -694,6 +714,7 @@ static int select_poll(int nfds, fd_set 
    5.80  	case FTYPE_EVTCHN:
    5.81  	case FTYPE_TAP:
    5.82  	case FTYPE_BLK:
    5.83 +	case FTYPE_KBD:
    5.84  	    if (FD_ISSET(i, readfds)) {
    5.85  		if (files[i].read)
    5.86  		    n++;
    5.87 @@ -775,6 +796,7 @@ int select(int nfds, fd_set *readfds, fd
    5.88      DEFINE_WAIT(w2);
    5.89      DEFINE_WAIT(w3);
    5.90      DEFINE_WAIT(w4);
    5.91 +    DEFINE_WAIT(w5);
    5.92  
    5.93      assert(thread == main_thread);
    5.94  
    5.95 @@ -795,6 +817,7 @@ int select(int nfds, fd_set *readfds, fd
    5.96      add_waiter(w2, event_queue);
    5.97      add_waiter(w3, blkfront_queue);
    5.98      add_waiter(w4, xenbus_watch_queue);
    5.99 +    add_waiter(w5, kbdfront_queue);
   5.100  
   5.101      myread = *readfds;
   5.102      mywrite = *writefds;
   5.103 @@ -860,6 +883,7 @@ out:
   5.104      remove_waiter(w2);
   5.105      remove_waiter(w3);
   5.106      remove_waiter(w4);
   5.107 +    remove_waiter(w5);
   5.108      return ret;
   5.109  }
   5.110