char *backend;
int request_update;
- char *data;
int width;
int height;
int depth;
- int line_length;
+ int stride;
int mem_length;
+ int offset;
};
void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
wake_up(&fbfront_queue);
}
-struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int height, int depth, int line_length, int mem_length)
+struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n)
{
xenbus_transaction_t xbt;
char* err;
dev->width = s->width = width;
dev->height = s->height = height;
dev->depth = s->depth = depth;
- dev->line_length = s->line_length = line_length;
- dev->mem_length = s->mem_length = mem_length;
-
- ASSERT(!((unsigned long)data & ~PAGE_MASK));
- dev->data = data;
+ dev->stride = s->line_length = stride;
+ dev->mem_length = s->mem_length = n * PAGE_SIZE;
+ dev->offset = 0;
const int max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
unsigned long mapped = 0;
- for (i = 0; mapped < mem_length && i < max_pd; i++) {
+ for (i = 0; mapped < n && i < max_pd; i++) {
unsigned long *pd = (unsigned long *) alloc_page();
- for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned long); j++) {
- /* Trigger CoW */
- * ((char *)data + mapped) = 0;
- barrier();
- pd[j] = virtual_to_mfn((unsigned long) data + mapped);
- mapped += PAGE_SIZE;
- }
+ for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++)
+ pd[j] = mfns[mapped++];
for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
pd[j] = 0;
s->pd[i] = virt_to_mfn(pd);
return dev;
}
-void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height)
+static void fbfront_out_event(struct fbfront_dev *dev, union xenfb_out_event *event)
{
struct xenfb_page *page = dev->page;
uint32_t prod;
DEFINE_WAIT(w);
+ add_waiter(w, fbfront_queue);
+ while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
+ schedule();
+ remove_waiter(w);
+
+ prod = page->out_prod;
+ mb(); /* ensure ring space available */
+ XENFB_OUT_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->out_prod = prod + 1;
+ notify_remote_via_evtchn(dev->evtchn);
+}
+
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height)
+{
+ struct xenfb_update update;
+
if (dev->request_update <= 0)
return;
if (width <= 0 || height <= 0)
return;
- add_waiter(w, fbfront_queue);
- while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
- schedule();
- remove_waiter(w);
+ update.type = XENFB_TYPE_UPDATE;
+ update.x = x;
+ update.y = y;
+ update.width = width;
+ update.height = height;
+ fbfront_out_event(dev, (union xenfb_out_event *) &update);
+}
- prod = page->out_prod;
- mb(); /* ensure ring space available */
- XENFB_OUT_RING_REF(page, prod).type = XENFB_TYPE_UPDATE;
- XENFB_OUT_RING_REF(page, prod).update.x = x;
- XENFB_OUT_RING_REF(page, prod).update.y = y;
- XENFB_OUT_RING_REF(page, prod).update.width = width;
- XENFB_OUT_RING_REF(page, prod).update.height = height;
- wmb(); /* ensure ring contents visible */
- page->out_prod = prod + 1;
- notify_remote_via_evtchn(dev->evtchn);
+void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset)
+{
+ struct xenfb_resize resize;
+
+ resize.type = XENFB_TYPE_RESIZE;
+ dev->width = resize.width = width;
+ dev->height = resize.height = height;
+ dev->stride = resize.stride = stride;
+ dev->depth = resize.depth = depth;
+ dev->offset = resize.offset = offset;
+ fbfront_out_event(dev, (union xenfb_out_event *) &resize);
}
void shutdown_fbfront(struct fbfront_dev *dev)
void shutdown_kbdfront(struct kbdfront_dev *dev);
-struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int height, int depth, int line_length, int mem_length);
+struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n);
#ifdef HAVE_LIBC
int fbfront_open(struct fbfront_dev *dev);
#endif
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);
void shutdown_fbfront(struct fbfront_dev *dev);
{
size_t line_length = WIDTH * (DEPTH / 8);
size_t memsize = HEIGHT * line_length;
+ unsigned long *mfns;
+ int i, n = (memsize + PAGE_SIZE-1) / PAGE_SIZE;
+ memsize = n * PAGE_SIZE;
fb = _xmalloc(memsize, PAGE_SIZE);
- fb_dev = init_fbfront(NULL, fb, WIDTH, HEIGHT, DEPTH, line_length, memsize);
+ mfns = xmalloc_array(unsigned long, n);
+ for (i = 0; i < n; i++) {
+ /* trigger CoW */
+ ((char *) fb) [i * PAGE_SIZE] = 0;
+ barrier();
+ mfns[i] = virtual_to_mfn((char *) fb + i * PAGE_SIZE);
+ }
+ fb_dev = init_fbfront(NULL, mfns, WIDTH, HEIGHT, DEPTH, line_length, n);
+ xfree(mfns);
if (!fb_dev) {
xfree(fb);
return;