[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/4][RFC] Paravirtual Framebuffer/Keyboard


  • To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • From: Anthony Liguori <aliguori@xxxxxxxxxx>
  • Date: Sun, 15 Jan 2006 17:40:50 -0600
  • Delivery-date: Sun, 15 Jan 2006 23:48:30 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>


# HG changeset patch
# User Anthony Liguori <anthony@xxxxxxxxxxxxx>
# Node ID 2b1f225753ed4480c9968866b5955df878eea04d
# Parent  431a5f12b57f2fbc2f462523f0ff71a667837a9d
Xen Paravirtual Framebuffer driver

This driver setups up a region of shared memory that can be rendered to by the
guest.  Due to the amount of shared memory required, dom0 must map it via
an array of PFNs using the xc_map_foreign_*() set of calls.  The driver
implements write-faulting to keep track of which areas of the framebuffer are
updated.

This driver is largely based on Gerd Hoffman's framebuffer driver for UML.

Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>

diff -r 431a5f12b57f -r 2b1f225753ed linux-2.6-xen-sparse/drivers/video/Makefile
--- /dev/null   Sun Jan 15 18:05:57 2006 -0500
+++ b/linux-2.6-xen-sparse/drivers/video/Makefile       Sun Jan 15 18:08:56 
2006 -0500
@@ -0,0 +1,103 @@
+# Makefile for the Linux video drivers.
+# 5 Aug 1999, James Simmons, <mailto:jsimmons@xxxxxxxxxxxx>
+# Rewritten to use lists instead of if-statements.
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_VT)                 += console/
+obj-$(CONFIG_LOGO)               += logo/
+obj-$(CONFIG_SYSFS)              += backlight/
+
+obj-$(CONFIG_FB)                  += fb.o
+fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o 
modedb.o
+fb-objs                           := $(fb-y)
+
+obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
+obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
+obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SOFT_CURSOR)   += softcursor.o
+obj-$(CONFIG_FB_MACMODES)      += macmodes.o
+
+# Hardware specific drivers go first
+obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
+obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
+obj-$(CONFIG_FB_CYBER)            += cyberfb.o
+obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
+obj-$(CONFIG_FB_PM2)              += pm2fb.o
+obj-$(CONFIG_FB_PM3)             += pm3fb.o
+
+obj-$(CONFIG_FB_MATROX)                  += matrox/
+obj-$(CONFIG_FB_RIVA)            += riva/ vgastate.o
+obj-$(CONFIG_FB_NVIDIA)                  += nvidia/
+obj-$(CONFIG_FB_ATY)             += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128)                  += aty/ macmodes.o
+obj-$(CONFIG_FB_RADEON)                  += aty/
+obj-$(CONFIG_FB_SIS)             += sis/
+obj-$(CONFIG_FB_KYRO)             += kyro/
+obj-$(CONFIG_FB_SAVAGE)                  += savage/
+obj-$(CONFIG_FB_GEODE)           += geode/
+obj-$(CONFIG_FB_I810)             += vgastate.o
+obj-$(CONFIG_FB_RADEON_OLD)      += radeonfb.o
+obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
+obj-$(CONFIG_FB_VIRGE)            += virgefb.o
+obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
+obj-$(CONFIG_FB_CONTROL)          += controlfb.o
+obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
+obj-$(CONFIG_FB_CT65550)          += chipsfb.o
+obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
+obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
+obj-$(CONFIG_FB_FM2)              += fm2fb.o
+obj-$(CONFIG_FB_TRIDENT)         += tridentfb.o
+obj-$(CONFIG_FB_STI)              += stifb.o
+obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
+obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
+obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o
+obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o
+obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o
+obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o
+obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
+obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
+obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
+obj-$(CONFIG_FB_ACORN)            += acornfb.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_MAC)              += macfb.o
+obj-$(CONFIG_FB_HGA)              += hgafb.o
+obj-$(CONFIG_FB_IGA)              += igafb.o
+obj-$(CONFIG_FB_APOLLO)           += dnfb.o
+obj-$(CONFIG_FB_Q40)              += q40fb.o
+obj-$(CONFIG_FB_TGA)              += tgafb.o
+obj-$(CONFIG_FB_HP300)            += hpfb.o
+obj-$(CONFIG_FB_G364)             += g364fb.o
+obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
+obj-$(CONFIG_FB_SUN3)             += sun3fb.o
+obj-$(CONFIG_FB_HIT)              += hitfb.o
+obj-$(CONFIG_FB_EPSON1355)       += epson1355fb.o
+obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
+obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD)         += amba-clcd.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o
+obj-$(CONFIG_FB_GBE)              += gbefb.o
+obj-$(CONFIG_FB_CIRRUS)                  += cirrusfb.o
+obj-$(CONFIG_FB_ASILIANT)        += asiliantfb.o
+obj-$(CONFIG_FB_PXA)             += pxafb.o
+obj-$(CONFIG_FB_W100)            += w100fb.o
+obj-$(CONFIG_FB_AU1100)                  += au1100fb.o fbgen.o
+obj-$(CONFIG_FB_PMAG_AA)         += pmag-aa-fb.o
+obj-$(CONFIG_FB_PMAG_BA)         += pmag-ba-fb.o
+obj-$(CONFIG_FB_PMAGB_B)         += pmagb-b-fb.o
+obj-$(CONFIG_FB_MAXINE)                  += maxinefb.o
+obj-$(CONFIG_FB_TX3912)                  += tx3912fb.o
+obj-$(CONFIG_FB_S1D13XXX)        += s1d13xxxfb.o
+obj-$(CONFIG_FB_IMX)              += imxfb.o
+
+# Platform or fallback drivers go here
+obj-$(CONFIG_FB_VESA)             += vesafb.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+obj-$(CONFIG_FB_OF)               += offb.o
+
+obj-$(CONFIG_FB_XENFB)            += xenfb.o
+
+# the test framebuffer is last
+obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff -r 431a5f12b57f -r 2b1f225753ed linux-2.6-xen-sparse/drivers/video/xenfb.c
--- /dev/null   Sun Jan 15 18:05:57 2006 -0500
+++ b/linux-2.6-xen-sparse/drivers/video/xenfb.c        Sun Jan 15 18:08:56 
2006 -0500
@@ -0,0 +1,526 @@
+/*
+ * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Based on linux/drivers/video/q40fb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <asm/hypervisor.h>
+#include <asm-xen/evtchn.h>
+#include <linux/xenfb.h>
+#include <linux/kthread.h>
+
+static int xenfb_fps = 20;
+static unsigned long xenfb_mem_len = 2 * 1024 * 1024;
+
+struct xenfb_mapping
+{
+       struct list_head        next;
+       struct vm_area_struct   *vma;
+       atomic_t                map_refs;
+       int                     faults;
+       struct xenfb_info       *info;
+};
+
+struct xenfb_info
+{
+       struct task_struct              *kthread;
+       wait_queue_head_t               wq;
+
+       unsigned char                   *fb;
+       struct fb_fix_screeninfo        *fix;
+       struct fb_var_screeninfo        *var;
+       struct fb_info                  *fb_info;
+       struct timer_list               refresh;
+       int                             dirty;
+       int                             y1, y2;
+       int                             x1, x2;
+
+       struct semaphore                mm_lock;
+       int                             nr_pages;
+       struct page                     **pages;
+       struct list_head                mappings;
+
+       struct xenfb_page               *page;
+       unsigned long                   *mfns;
+};
+
+static void xenfb_do_update(struct xenfb_info *info,
+                           int x, int y, int w, int h)
+{
+       union xenfb_out_event event;
+       __u32 cons, prod;
+
+       event.type = XENFB_TYPE_UPDATE;
+       event.update.x = x;
+       event.update.y = y;
+       event.update.width = w;
+       event.update.height = h;
+
+       /* FIXME barriers */
+       prod = XENFB_MASK_RING(info->page->out_prod, info->page->out);
+       cons = XENFB_MASK_RING(info->page->out_cons, info->page->out);
+       prod = XENFB_MASK_RING(prod + 1, info->page->out);
+
+       if (prod == cons)
+               return;
+
+       memcpy(&info->page->out[prod], &event, sizeof(event));
+       info->page->out_prod = prod;
+
+       notify_remote_via_evtchn(xen_start_info->fbdev_evtchn);
+}
+
+static int xenfb_queue_full(struct xenfb_info *info)
+{
+       __u32 cons, prod;
+
+       prod = XENFB_MASK_RING(info->page->out_prod, info->page->out);
+       cons = XENFB_MASK_RING(info->page->out_cons, info->page->out);
+       prod = XENFB_MASK_RING(prod + 1, info->page->out);
+
+       return (prod == cons);
+}
+
+static void xenfb_update_screen(struct xenfb_info *info)
+{
+       int y1, y2, x1, x2;
+       struct list_head *item;
+       struct xenfb_mapping *map;
+
+       if (xenfb_queue_full(info))
+               return;
+
+       y1 = info->y1;
+       y2 = info->y2;
+       x1 = info->x1;
+       x2 = info->x2;
+       info->dirty = info->y1 = info->y2 = info->x1 = info->x2 = 0;
+       down(&info->mm_lock);
+       list_for_each(item, &info->mappings) {
+               map = list_entry(item, struct xenfb_mapping, next);
+               if (!map->faults)
+                       continue;
+               zap_page_range(map->vma, map->vma->vm_start,
+                              map->vma->vm_end - map->vma->vm_start, NULL);
+               map->faults = 0;
+       }
+       up(&info->mm_lock);
+
+       xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
+}
+
+static int xenfb_thread(void *data)
+{
+       struct xenfb_info *info = data;
+       DECLARE_WAITQUEUE(wait, current);
+
+       add_wait_queue(&info->wq, &wait);
+       for (;;) {
+               if (kthread_should_stop())
+                       break;
+               if (info->dirty)
+                       xenfb_update_screen(info);
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+       }
+       remove_wait_queue(&info->wq, &wait);
+       return 0;
+}
+
+static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       u32 v;
+
+       if (regno > info->cmap.len)
+               return 1;
+
+       red   >>= (16 - info->var.red.length);
+       green >>= (16 - info->var.green.length);
+       blue  >>= (16 - info->var.blue.length);
+
+       v = (red << info->var.red.offset) |
+           (green << info->var.green.offset) |
+           (blue << info->var.blue.offset);
+
+       switch (info->var.bits_per_pixel) {
+       case 16:
+       case 24:
+       case 32:
+               ((u32 *)info->pseudo_palette)[regno] = v;
+               break;
+       }
+       
+       return 0;
+}
+
+static void xenfb_timer(unsigned long data)
+{
+       struct xenfb_info *info = (struct xenfb_info *)data;
+       info->dirty++;
+       wake_up(&info->wq);
+}
+
+static void xenfb_refresh(struct xenfb_info *info,
+                         int x1, int y1, int w, int h)
+{
+       int y2, x2;
+
+       y2 = y1 + h;
+       x2 = x1 + w;
+       if (info->y2 == 0) {
+               info->y1 = y1;
+               info->y2 = y2;
+       }
+       if (info->x2 == 0) {
+               info->x1 = x1;
+               info->x2 = x2;
+       }
+
+       if (info->y1 > y1)
+               info->y1 = y1;
+       if (info->y2 < y2)
+               info->y2 = y2;
+       if (info->x1 > x1)
+               info->x1 = x1;
+       if (info->x2 < x2)
+               info->x2 = x2;
+
+       if (timer_pending(&info->refresh))
+               return;
+
+       mod_timer(&info->refresh, jiffies + HZ/xenfb_fps);
+}
+
+static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_fillrect(p, rect);
+       xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_imageblit(p, image);
+       xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
+}
+
+static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_copyarea(p, area);
+       xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
+}
+
+static void xenfb_vm_open(struct vm_area_struct *vma)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       atomic_inc(&map->map_refs);
+}
+
+static void xenfb_vm_close(struct vm_area_struct *vma)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       struct xenfb_info *info = map->info;
+
+       down(&info->mm_lock);
+       if (atomic_dec_and_test(&map->map_refs)) {
+               list_del(&map->next);
+               kfree(map);
+       }
+       up(&info->mm_lock);
+}
+
+static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
+                                   unsigned long vaddr, int *type)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       struct xenfb_info *info = map->info;
+       int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
+       struct page *page;
+       int y1, y2;
+
+       if (pgnr >= info->nr_pages)
+               return NOPAGE_SIGBUS;
+
+       down(&info->mm_lock);
+       page = info->pages[pgnr];
+       get_page(page);
+       map->faults++;
+
+       y1 = pgnr * PAGE_SIZE / info->fix->line_length;
+       y2 = (pgnr * PAGE_SIZE + PAGE_SIZE - 1) / info->fix->line_length;
+       if (y2 > info->var->yres)
+               y2 = info->var->yres;
+       xenfb_refresh(info, 0, y1, info->var->xres, y2 - y1);
+       up(&info->mm_lock);
+
+       if (type)
+               *type = VM_FAULT_MINOR;
+
+       return page;
+}
+
+static struct vm_operations_struct xenfb_vm_ops = {
+       .open   = xenfb_vm_open,
+       .close  = xenfb_vm_close,
+       .nopage = xenfb_vm_nopage,
+};
+
+static int xenfb_mmap(struct fb_info *fb_info, struct file *file,
+                     struct vm_area_struct *vma)
+{
+       struct xenfb_info *info = fb_info->par;
+       struct xenfb_mapping *map;
+       int ret;
+       int map_pages;
+
+       down(&info->mm_lock);
+
+       ret = -EINVAL;
+       if (!(vma->vm_flags & VM_WRITE))
+               goto out;
+       if (!(vma->vm_flags & VM_SHARED))
+               goto out;
+       if (vma->vm_pgoff != 0)
+               goto out;
+
+       map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT;
+       if (map_pages > info->nr_pages)
+               goto out;
+
+       ret = -ENOMEM;
+       map = kmalloc(sizeof(*map), GFP_KERNEL);
+       if (map == NULL)
+               goto out;
+       memset(map, 0, sizeof(*map));
+
+       map->vma = vma;
+       map->faults = 0;
+       map->info = info;
+       atomic_set(&map->map_refs, 1);
+       list_add(&map->next, &info->mappings);
+       vma->vm_ops = &xenfb_vm_ops;
+       vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
+       vma->vm_private_data = map;
+       ret = 0;
+
+ out:
+       up(&info->mm_lock);
+       return ret;
+}
+
+static struct fb_ops xenfb_fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = xenfb_setcolreg,
+       .fb_cursor      = soft_cursor,
+       .fb_fillrect    = xenfb_fillrect,
+       .fb_copyarea    = xenfb_copyarea,
+       .fb_imageblit   = xenfb_imageblit,
+       .fb_mmap        = xenfb_mmap,
+};
+
+static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
+                                      struct pt_regs *regs)
+{
+       struct xenfb_info *info = dev_id;
+       __u32 cons, prod;
+
+       if (!info->page || !info->page->initialized)
+               return IRQ_NONE;
+
+       /* FIXME barriers */
+       prod = XENFB_MASK_RING(info->page->in_prod, info->page->in);
+       cons = XENFB_MASK_RING(info->page->in_cons, info->page->in);
+
+       if (prod == cons)
+               return IRQ_HANDLED;
+
+       for (; cons!=prod; cons = XENFB_MASK_RING(cons+1, info->page->in)) {
+               union xenfb_in_event *event;
+               event = &info->page->in[cons];
+               notify_remote_via_evtchn(xen_start_info->fbdev_evtchn);
+       }
+
+       info->page->in_cons = cons;
+
+       return IRQ_HANDLED;
+}
+
+static unsigned long vmalloc_to_mfn(void *address)
+{
+       return pfn_to_mfn(vmalloc_to_pfn(address));
+}
+
+static struct xenfb_info *xenfb_info;
+static int xenfb_irq;
+
+static int __init xenfb_probe(void)
+{
+       struct xenfb_info *info;
+       int i, ret;
+       struct fb_info *fb_info;
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (info == NULL)
+               return -ENOMEM;
+       memset(info, 0, sizeof(*info));
+
+       INIT_LIST_HEAD(&info->mappings);
+
+       info->fb = vmalloc(xenfb_mem_len);
+       if (info->fb == NULL)
+               goto error;
+       memset(info->fb, 0, xenfb_mem_len);
+       info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       info->pages = kmalloc(sizeof(struct page*)*info->nr_pages, GFP_KERNEL);
+       if (info->pages == NULL)
+               goto error_vfree;
+       for (i = 0; i < info->nr_pages; i++)
+               info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE);
+
+       fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+       if (fb_info == NULL)
+               goto error_kfree;
+
+       /* FIXME giant turd sandwhich */
+       info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+       info->page = mfn_to_virt(xen_start_info->fbdev_mfn);
+
+       for (i = 0; i < info->nr_pages; i++)
+               info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+       info->page->pd[0] = vmalloc_to_mfn(info->mfns);
+       info->page->width = 800;
+       info->page->height = 600;
+       info->page->depth = 24;
+       info->page->line_length = (info->page->depth / 8) * info->page->width;
+       info->page->mem_length = xenfb_mem_len;
+
+       ret = bind_evtchn_to_irqhandler(xen_start_info->fbdev_evtchn,
+                                       xenfb_event_handler, 0, "xenfb", info);
+       if (ret <= 0)
+               goto error_kfree;
+
+       xenfb_irq = ret;
+       xenfb_info = info;
+       /* END turd sandwhich */
+
+       fb_info->pseudo_palette = fb_info->par;
+       fb_info->par = info;
+       fb_info->screen_base = info->fb;
+
+
+       memset(&fb_info->var, 0, sizeof(fb_info->var));
+       memset(&fb_info->fix, 0, sizeof(fb_info->fix));
+
+       fb_info->fbops = &xenfb_fb_ops;
+       fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
+       fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
+       fb_info->var.bits_per_pixel = info->page->depth;
+
+       fb_info->var.red = (struct fb_bitfield){16, 8, 0};
+       fb_info->var.green = (struct fb_bitfield){8, 8, 0};
+       fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
+
+       fb_info->var.activate = FB_ACTIVATE_NOW;
+       fb_info->var.height = -1;
+       fb_info->var.width = -1;
+       fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+       fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+       fb_info->fix.line_length = info->page->line_length;
+       fb_info->fix.smem_start = 0;
+       fb_info->fix.smem_len = xenfb_mem_len;
+       strcpy(fb_info->fix.id, "xen");
+       fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+       fb_info->fix.accel = FB_ACCEL_NONE;
+
+       fb_info->flags = FBINFO_FLAG_DEFAULT;
+
+       fb_alloc_cmap(&fb_info->cmap, 256, 0);
+
+       info->fb_info = fb_info;
+       info->fix = &fb_info->fix;
+       info->var = &fb_info->var;
+
+       init_MUTEX(&info->mm_lock);
+       init_waitqueue_head(&info->wq);
+       init_timer(&info->refresh);
+       info->refresh.function = xenfb_timer;
+       info->refresh.data = (unsigned long)info;
+
+       info->kthread = kthread_run(xenfb_thread, info, "xenfb thread");
+
+       register_framebuffer(fb_info);
+
+       info->page->initialized = 1;
+
+       return 0;
+
+
+ error_kfree:
+       kfree(info->pages);
+ error_vfree:
+       vfree(info->fb);
+ error:
+       kfree(info);
+
+       return -ENODEV;
+}
+
+void xenfb_resume(void)
+{
+       int i, ret;
+
+       xenfb_info->page = mfn_to_virt(xen_start_info->fbdev_mfn);
+       for (i = 0; i < xenfb_info->nr_pages; i++)
+               xenfb_info->mfns[i] = vmalloc_to_mfn(xenfb_info->fb + i * 
PAGE_SIZE);
+       xenfb_info->page->pd[0] = vmalloc_to_mfn(xenfb_info->mfns);
+
+#if 0
+       if (xenfb_irq)
+               unbind_from_irqhandler(xenfb_irq, NULL);
+#endif
+
+       printk("xenfb: resume(%d)\n", xen_start_info->fbdev_evtchn);
+       ret = bind_evtchn_to_irqhandler(xen_start_info->fbdev_evtchn,
+                                       xenfb_event_handler, 0, "xenfb", 
xenfb_info);
+       if (ret <= 0)
+               return;
+       xenfb_irq = ret;
+}
+
+static int __init xenfb_init(void)
+{
+       if (xen_start_info->fbdev_evtchn == 0)
+               return -ENODEV;
+
+       return xenfb_probe();
+}
+
+static void __exit xenfb_cleanup(void)
+{
+       /* FIXME */
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
diff -r 431a5f12b57f -r 2b1f225753ed linux-2.6-xen-sparse/include/linux/xenfb.h
--- /dev/null   Sun Jan 15 18:05:57 2006 -0500
+++ b/linux-2.6-xen-sparse/include/linux/xenfb.h        Sun Jan 15 18:08:56 
2006 -0500
@@ -0,0 +1,96 @@
+/*
+ * linux/include/linux/xenfb.h -- Xen virtual frame buffer device
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef _LINUX_XENFB_H
+#define _LINUX_XENFB_H
+
+#include <asm/types.h>
+
+/* out events */
+
+#define XENFB_TYPE_MOTION 1
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_motion
+{
+       __u8 type;          /* XENFB_TYPE_MOTION */
+       __u16 x;            /* The new x coordinate */
+       __u16 y;            /* The new y coordinate */
+};
+
+struct xenfb_update
+{
+       __u8 type;          /* XENFB_TYPE_UPDATE */
+       __u16 x;            /* source x */
+       __u16 y;            /* source y */
+       __u16 width;        /* rect width */
+       __u16 height;       /* rect height */
+};
+
+union xenfb_out_event
+{
+       __u8 type;
+       struct xenfb_motion motion;
+       struct xenfb_update update;
+       char _[40];
+};
+
+/* in events */
+
+#define XENFB_TYPE_SET_EVENTS 1
+
+#define XENFB_FLAG_MOTION 1
+#define XENFB_FLAG_UPDATE 2
+#define XENFB_FLAG_COPY 4
+#define XENFB_FLAG_FILL 8
+
+struct xenfb_set_events
+{
+       __u8 type;          /* XENFB_TYPE_SET_EVENTS */
+       __u32 flags;        /* combination of XENFB_FLAG_* */
+};
+
+union xenfb_in_event
+{
+       __u8 type;
+       struct xenfb_set_events set_events;
+       char _[40];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE (1024 / 40)
+#define XENFB_OUT_RING_SIZE (2048 / 40)
+
+#define XENFB_MASK_RING(idx, ring) ((idx)%(sizeof((ring))/sizeof((ring)[0])))
+
+struct xenfb_page
+{
+       __u8 initialized;
+       __u16 width;         /* the width of the framebuffer (in pixels) */
+       __u16 height;        /* the height of the framebuffer (in pixels) */
+       __u32 line_length;   /* the length of a row of pixels (in bytes) */
+       __u32 mem_length;    /* the length of the framebuffer (in bytes) */
+       __u8 depth;          /* the depth of a pixel (in bits) */
+
+       unsigned long pd[2];
+
+       __u32 in_cons, in_prod;
+       __u32 out_cons, out_prod;
+
+       union xenfb_in_event in[XENFB_IN_RING_SIZE];
+       union xenfb_out_event out[XENFB_OUT_RING_SIZE];
+};
+
+void xenfb_resume(void);
+
+#endif
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.