All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] vga-pci and MMIO BAR
@ 2012-07-25  3:57 Benjamin Herrenschmidt
  2012-07-25 10:27 ` Avi Kivity
  2012-08-06 12:03 ` Gerd Hoffmann
  0 siblings, 2 replies; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-25  3:57 UTC (permalink / raw)
  To: qemu-devel

Hi folks !

Would there be any objection to adding a second MMIO BAR to qemu-vga
which mirrors the bochs magic VBE ports ?

Support for IO space is optional in PCIe and can be problematic on some
architectures, it would be nice to be able to program the card entirely
using mmio.

Once done, I'd like to look into doing a qemudrmfb similar to the cirrus
one that pretty much gives you generic KMS support (with RandR) on top
of vga-pci. This would have the advantage of potentially lifting the
pitch and size limitations that plague cirrus.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25  3:57 [Qemu-devel] vga-pci and MMIO BAR Benjamin Herrenschmidt
@ 2012-07-25 10:27 ` Avi Kivity
  2012-07-25 10:53   ` Benjamin Herrenschmidt
  2012-08-06 12:03 ` Gerd Hoffmann
  1 sibling, 1 reply; 13+ messages in thread
From: Avi Kivity @ 2012-07-25 10:27 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: qemu-devel

On 07/25/2012 06:57 AM, Benjamin Herrenschmidt wrote:
> Hi folks !
> 
> Would there be any objection to adding a second MMIO BAR to qemu-vga
> which mirrors the bochs magic VBE ports ?
> 
> Support for IO space is optional in PCIe and can be problematic on some
> architectures, it would be nice to be able to program the card entirely
> using mmio.

Can we choose a PCIe chipset that does support IO space?

If not, we can add a second BAR, but it should disappear when running an
older machine type.

> Once done, I'd like to look into doing a qemudrmfb similar to the cirrus
> one that pretty much gives you generic KMS support (with RandR) on top
> of vga-pci. This would have the advantage of potentially lifting the
> pitch and size limitations that plague cirrus.

Have a look at qxl.


-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 10:27 ` Avi Kivity
@ 2012-07-25 10:53   ` Benjamin Herrenschmidt
  2012-07-25 12:48     ` Avi Kivity
  0 siblings, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-25 10:53 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel

On Wed, 2012-07-25 at 13:27 +0300, Avi Kivity wrote:
> On 07/25/2012 06:57 AM, Benjamin Herrenschmidt wrote:
> > Hi folks !
> > 
> > Would there be any objection to adding a second MMIO BAR to qemu-vga
> > which mirrors the bochs magic VBE ports ?
> > 
> > Support for IO space is optional in PCIe and can be problematic on some
> > architectures, it would be nice to be able to program the card entirely
> > using mmio.
> 
> Can we choose a PCIe chipset that does support IO space?

Why bother ? It's not like mode setting is performance critical and IO
space is always going to be a pain on non-x86 ...

> If not, we can add a second BAR, but it should disappear when running an
> older machine type.

Well, the IO ports in legacy space are still there. We can also make the
"register BAR" exist in both mode or we can add a second BAR and have
x86 "prefer" IO... whatever rocks your boat as long as it's a BAR, it's
the legacy hole that's annoying for me :-)

> > Once done, I'd like to look into doing a qemudrmfb similar to the cirrus
> > one that pretty much gives you generic KMS support (with RandR) on top
> > of vga-pci. This would have the advantage of potentially lifting the
> > pitch and size limitations that plague cirrus.
> 
> Have a look at qxl.

No I haven't :-) I'll have a look, thanks.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 10:53   ` Benjamin Herrenschmidt
@ 2012-07-25 12:48     ` Avi Kivity
  2012-07-25 13:41       ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 13+ messages in thread
From: Avi Kivity @ 2012-07-25 12:48 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: qemu-devel

On 07/25/2012 01:53 PM, Benjamin Herrenschmidt wrote:
> On Wed, 2012-07-25 at 13:27 +0300, Avi Kivity wrote:
>> On 07/25/2012 06:57 AM, Benjamin Herrenschmidt wrote:
>> > Hi folks !
>> > 
>> > Would there be any objection to adding a second MMIO BAR to qemu-vga
>> > which mirrors the bochs magic VBE ports ?
>> > 
>> > Support for IO space is optional in PCIe and can be problematic on some
>> > architectures, it would be nice to be able to program the card entirely
>> > using mmio.
>> 
>> Can we choose a PCIe chipset that does support IO space?
> 
> Why bother ? It's not like mode setting is performance critical and IO
> space is always going to be a pain on non-x86 ...

For compatibility?  If it's a special pain, then I understand, but
what's the difference between emulating chipset A or B?

> 
>> If not, we can add a second BAR, but it should disappear when running an
>> older machine type.
> 
> Well, the IO ports in legacy space are still there. We can also make the
> "register BAR" exist in both mode or we can add a second BAR and have
> x86 "prefer" IO... whatever rocks your boat as long as it's a BAR, it's
> the legacy hole that's annoying for me :-)

A guest created with -M old must look exactly the same as it did in an
older version of qemu, no extra BARs.


-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 12:48     ` Avi Kivity
@ 2012-07-25 13:41       ` Benjamin Herrenschmidt
  2012-07-25 13:59         ` Avi Kivity
  0 siblings, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-25 13:41 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel

On Wed, 2012-07-25 at 15:48 +0300, Avi Kivity wrote:
> >> If not, we can add a second BAR, but it should disappear when running an
> >> older machine type.
> > 
> > Well, the IO ports in legacy space are still there. We can also make the
> > "register BAR" exist in both mode or we can add a second BAR and have
> > x86 "prefer" IO... whatever rocks your boat as long as it's a BAR, it's
> > the legacy hole that's annoying for me :-)
> 
> A guest created with -M old must look exactly the same as it did in an
> older version of qemu, no extra BARs.

Why ? Who cares ? Especially with vga -std which nobody uses in practice
on x86...

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 13:41       ` Benjamin Herrenschmidt
@ 2012-07-25 13:59         ` Avi Kivity
  2012-07-25 22:01           ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 13+ messages in thread
From: Avi Kivity @ 2012-07-25 13:59 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: qemu-devel

On 07/25/2012 04:41 PM, Benjamin Herrenschmidt wrote:
> On Wed, 2012-07-25 at 15:48 +0300, Avi Kivity wrote:
>> >> If not, we can add a second BAR, but it should disappear when running an
>> >> older machine type.
>> > 
>> > Well, the IO ports in legacy space are still there. We can also make the
>> > "register BAR" exist in both mode or we can add a second BAR and have
>> > x86 "prefer" IO... whatever rocks your boat as long as it's a BAR, it's
>> > the legacy hole that's annoying for me :-)
>> 
>> A guest created with -M old must look exactly the same as it did in an
>> older version of qemu, no extra BARs.
> 
> Why ? Who cares ? Especially with vga -std which nobody uses in practice
> on x86...

We'll find out who cares when we break it.

We have a system in place to prevent intentional breakage, let's use it.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 13:59         ` Avi Kivity
@ 2012-07-25 22:01           ` Benjamin Herrenschmidt
  2012-07-26  0:22             ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-25 22:01 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel

On Wed, 2012-07-25 at 16:59 +0300, Avi Kivity wrote:
> > Why ? Who cares ? Especially with vga -std which nobody uses in
> practice
> > on x86...
> 
> We'll find out who cares when we break it.

Chances are pretty much close to 0, especially adding a BAR ... do we
even use vga "std" on anything ?

> We have a system in place to prevent intentional breakage, let's use
> it.

And that system is never improve a device ? :-) Or am I missing
something ?

Cheers,
Ben

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25 22:01           ` Benjamin Herrenschmidt
@ 2012-07-26  0:22             ` Benjamin Herrenschmidt
  2012-07-26  1:08               ` Anthony Liguori
  0 siblings, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-26  0:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel

On Thu, 2012-07-26 at 08:01 +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2012-07-25 at 16:59 +0300, Avi Kivity wrote:
> > > Why ? Who cares ? Especially with vga -std which nobody uses in
> > practice
> > > on x86...
> > 
> > We'll find out who cares when we break it.
> 
> Chances are pretty much close to 0, especially adding a BAR ... do we
> even use vga "std" on anything ?
>
> > We have a system in place to prevent intentional breakage, let's use
> > it.
> 
> And that system is never improve a device ? :-) Or am I missing
> something ?

Allright, had a chat with Anthony who explained the bit I was missing
about what you meant by -M old... I'll make sure I don't break that.

Cheers,
Ben

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-26  0:22             ` Benjamin Herrenschmidt
@ 2012-07-26  1:08               ` Anthony Liguori
  2012-07-26  1:18                 ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2012-07-26  1:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Avi Kivity; +Cc: qemu-devel

Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:

> On Thu, 2012-07-26 at 08:01 +1000, Benjamin Herrenschmidt wrote:
>> On Wed, 2012-07-25 at 16:59 +0300, Avi Kivity wrote:
>> > > Why ? Who cares ? Especially with vga -std which nobody uses in
>> > practice
>> > > on x86...
>> > 
>> > We'll find out who cares when we break it.
>> 
>> Chances are pretty much close to 0, especially adding a BAR ... do we
>> even use vga "std" on anything ?
>>
>> > We have a system in place to prevent intentional breakage, let's use
>> > it.
>> 
>> And that system is never improve a device ? :-) Or am I missing
>> something ?
>
> Allright, had a chat with Anthony who explained the bit I was missing
> about what you meant by -M old... I'll make sure I don't break that.

For the benefit of the list, Ben didn't know that we could just add a
qdev property to control whether the MMIO BAR was visible making it just
a tiny bit of global magic in the old PC machine models.

PPC still doesn't do versioning of machine models.  Ya'll probably
should spend some time looking at what's done for the PC machine types
and start doing the same for spapr.

Regards,

Anthony Liguori

>
> Cheers,
> Ben

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-26  1:08               ` Anthony Liguori
@ 2012-07-26  1:18                 ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-07-26  1:18 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Avi Kivity, qemu-devel

On Wed, 2012-07-25 at 20:08 -0500, Anthony Liguori wrote:
> 
> For the benefit of the list, Ben didn't know that we could just add a
> qdev property to control whether the MMIO BAR was visible making it
> just
> a tiny bit of global magic in the old PC machine models.
> 
> PPC still doesn't do versioning of machine models.  Ya'll probably
> should spend some time looking at what's done for the PC machine types
> and start doing the same for spapr.

For macs, we probably want to have a big overhaul/cleanup day, and just
make them look closer to a real piece of HW, no need to version them. I
want to make a proper G5 model one of these days.

For spapr, it does make some amount of sense to version it, I'll talk to
David about it.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-07-25  3:57 [Qemu-devel] vga-pci and MMIO BAR Benjamin Herrenschmidt
  2012-07-25 10:27 ` Avi Kivity
@ 2012-08-06 12:03 ` Gerd Hoffmann
  2012-08-06 21:07   ` Benjamin Herrenschmidt
  2012-08-10 15:27   ` Alon Levy
  1 sibling, 2 replies; 13+ messages in thread
From: Gerd Hoffmann @ 2012-08-06 12:03 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 693 bytes --]

On 07/25/12 05:57, Benjamin Herrenschmidt wrote:
> Hi folks !
> 
> Would there be any objection to adding a second MMIO BAR to qemu-vga
> which mirrors the bochs magic VBE ports ?

No.

> Once done, I'd like to look into doing a qemudrmfb similar to the cirrus
> one that pretty much gives you generic KMS support (with RandR) on top
> of vga-pci. This would have the advantage of potentially lifting the
> pitch and size limitations that plague cirrus.

Hacked up something like that a while back (patch attached).  Doesn't
use DRM though, just plain old fbdev.  Maybe you can reuse some bits
nevertheless.

/me wonders what the advantage of using drm is for non-3D hardware?

cheers,
  Gerd

[-- Attachment #2: 0001-add-bochs-dispi-interface-framebuffer-driver.patch --]
[-- Type: text/plain, Size: 13039 bytes --]

From 637f637df63a2fc676d7fa09c4fec40172559bab Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 6 Mar 2012 14:34:38 +0100
Subject: [PATCH] add bochs dispi interface framebuffer driver

This patchs adds a frame buffer driver for (virtual/emulated) vga cards
implementing the bochs dispi interface.  Supported hardware are the
bochs vga card with vbe extension and the qemu standard vga.

The driver uses a fixed depth of 32bpp.  Otherwise it supports the full
(but small) feature set of the bochs dispi interface:  Resolution
switching and display panning.  It is tweaked to maximize fbcon speed,
so you'll get the comfort of the framebuffer console in kvm guests
without performance penalty.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/video/Kconfig   |   18 +++
 drivers/video/Makefile  |    1 +
 drivers/video/bochsfb.c |  385 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 404 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/bochsfb.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0217f74..cf401ce 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -286,6 +286,24 @@ config FB_CIRRUS
 	  Say N unless you have such a graphics board or plan to get one
 	  before you next recompile the kernel.
 
+config FB_BOCHS
+	tristate "Bochs dispi interface support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  This is the frame buffer driver for (virtual/emulated) vga
+          cards implementing the bochs dispi interface.  Supported
+          hardware are the bochs vga card with vbe extension and the
+          qemu standard vga.
+
+          The driver handles the PCI variants only.  It uses a fixed
+          depth of 32bpp, anything else doesn't make sense these days.
+
+          Say Y here if you plan to run the kernel in a virtual machine
+          emulated by bochs or qemu.
+
 config FB_PM2
 	tristate "Permedia2 support"
 	depends on FB && ((AMIGA && BROKEN) || PCI)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ee8dafb..81b78f1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -102,6 +102,7 @@ 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_BOCHS)		  += bochsfb.o
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
 obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
diff --git a/drivers/video/bochsfb.c b/drivers/video/bochsfb.c
new file mode 100644
index 0000000..18a94dc
--- /dev/null
+++ b/drivers/video/bochsfb.c
@@ -0,0 +1,385 @@
+/*
+ *  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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include <asm/io.h>
+
+#define VBE_DISPI_IOPORT_INDEX           0x01CE
+#define VBE_DISPI_IOPORT_DATA            0x01CF
+
+#define VBE_DISPI_INDEX_ID               0x0
+#define VBE_DISPI_INDEX_XRES             0x1
+#define VBE_DISPI_INDEX_YRES             0x2
+#define VBE_DISPI_INDEX_BPP              0x3
+#define VBE_DISPI_INDEX_ENABLE           0x4
+#define VBE_DISPI_INDEX_BANK             0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
+#define VBE_DISPI_INDEX_X_OFFSET         0x8
+#define VBE_DISPI_INDEX_Y_OFFSET         0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0                    0xB0C0
+#define VBE_DISPI_ID1                    0xB0C1
+#define VBE_DISPI_ID2                    0xB0C2
+#define VBE_DISPI_ID3                    0xB0C3
+#define VBE_DISPI_ID4                    0xB0C4
+#define VBE_DISPI_ID5                    0xB0C5
+
+#define VBE_DISPI_DISABLED               0x00
+#define VBE_DISPI_ENABLED                0x01
+#define VBE_DISPI_GETCAPS                0x02
+#define VBE_DISPI_8BIT_DAC               0x20
+#define VBE_DISPI_LFB_ENABLED            0x40
+#define VBE_DISPI_NOCLEARMEM             0x80
+
+enum bochs_types {
+	BOCHS_QEMU_STDVGA,
+	BOCHS_UNKNOWN,
+};
+
+static const char *bochs_names[] = {
+	[ BOCHS_QEMU_STDVGA ] = "QEMU standard vga",
+	[ BOCHS_UNKNOWN ]     = "unknown",
+};
+
+static struct fb_fix_screeninfo bochsfb_fix __devinitdata = {
+	.id          = "bochsfb",
+	.type        = FB_TYPE_PACKED_PIXELS,
+	.visual      = FB_VISUAL_TRUECOLOR,
+	.accel       = FB_ACCEL_NONE,
+	.xpanstep    = 1,
+	.ypanstep    = 1,
+};
+
+static struct fb_var_screeninfo bochsfb_var __devinitdata = {
+	.xres           = 1024,
+	.yres           = 768,
+	.bits_per_pixel = 32,
+#ifdef __BIG_ENDIAN
+	.transp         = { .length = 8, .offset =  0 },
+	.red            = { .length = 8, .offset =  8 },
+	.green          = { .length = 8, .offset = 16 },
+	.blue           = { .length = 8, .offset = 24 },
+#else
+	.transp         = { .length = 8, .offset = 24 },
+	.red            = { .length = 8, .offset = 16 },
+	.green          = { .length = 8, .offset =  8 },
+	.blue           = { .length = 8, .offset =  0 },
+#endif
+	.height         = -1,
+	.width          = -1,
+	.vmode          = FB_VMODE_NONINTERLACED,
+	.pixclock       = 10000,
+	.left_margin    = 16,
+	.right_margin   = 16,
+	.upper_margin   = 16,
+	.lower_margin   = 16,
+	.hsync_len      = 8,
+	.vsync_len      = 8,
+};
+
+static char *mode __devinitdata;
+module_param(mode, charp, 0);
+MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480'");
+
+static u16 bochs_read(u16 reg)
+{
+	outw(reg, VBE_DISPI_IOPORT_INDEX);
+	return inw(VBE_DISPI_IOPORT_DATA);
+}
+
+static void bochs_write(u16 reg, u16 val)
+{
+	outw(reg, VBE_DISPI_IOPORT_INDEX);
+	outw(val, VBE_DISPI_IOPORT_DATA);
+}
+
+static int bochsfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	uint32_t x,y, xv,yv, pixels;
+
+	if (var->bits_per_pixel != 32 ||
+	    var->xres > 65535 ||
+	    var->xres_virtual > 65535 ||
+	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	x  = var->xres & ~0x0f;
+	y  = var->yres & ~0x03;
+	xv = var->xres_virtual & ~0x0f;
+	yv = var->yres_virtual & ~0x03;
+	if (xv < x)
+		xv = x;
+	pixels = info->fix.smem_len * 8 / info->var.bits_per_pixel;
+	yv = pixels / xv;
+	if (y > yv)
+		return -EINVAL;
+
+	var->xres = x;
+	var->yres = y;
+	var->xres_virtual = xv;
+	var->yres_virtual = yv;
+	var->xoffset = 0;
+	var->yoffset = 0;
+
+	return 0;
+}
+
+static int bochsfb_set_par(struct fb_info *info)
+{
+	dev_dbg(info->dev, "set mode: real: %dx%d, virtual: %dx%d\n",
+		info->var.xres, info->var.yres,
+		info->var.xres_virtual, info->var.yres_virtual);
+
+	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
+
+	bochs_write(VBE_DISPI_INDEX_BPP,         info->var.bits_per_pixel);
+	bochs_write(VBE_DISPI_INDEX_XRES,        info->var.xres);
+	bochs_write(VBE_DISPI_INDEX_YRES,        info->var.yres);
+	bochs_write(VBE_DISPI_INDEX_BANK,        0);
+	bochs_write(VBE_DISPI_INDEX_VIRT_WIDTH,  info->var.xres_virtual);
+	bochs_write(VBE_DISPI_INDEX_VIRT_HEIGHT, info->var.yres_virtual);
+	bochs_write(VBE_DISPI_INDEX_X_OFFSET,    info->var.xoffset);
+	bochs_write(VBE_DISPI_INDEX_Y_OFFSET,    info->var.yoffset);
+
+	bochs_write(VBE_DISPI_INDEX_ENABLE,
+		    VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+	return 0;
+}
+
+static int bochsfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info)
+{
+	if (regno < 16 && info->var.bits_per_pixel == 32) {
+		red   >>= 8;
+		green >>= 8;
+		blue  >>= 8;
+		((u32 *)(info->pseudo_palette))[regno] =
+			(red   << info->var.red.offset)   |
+			(green << info->var.green.offset) |
+			(blue  << info->var.blue.offset);
+	}
+	return 0;
+}
+
+static int bochsfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	bochs_write(VBE_DISPI_INDEX_X_OFFSET, var->xoffset);
+	bochs_write(VBE_DISPI_INDEX_Y_OFFSET, var->yoffset);
+	return 0;
+}
+
+static struct fb_ops bochsfb_ops = {
+	.owner	        = THIS_MODULE,
+	.fb_check_var   = bochsfb_check_var,
+	.fb_set_par     = bochsfb_set_par,
+	.fb_setcolreg   = bochsfb_setcolreg,
+	.fb_pan_display = bochsfb_pan_display,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+};
+
+static int __devinit
+bochsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
+{
+	struct fb_info *p;
+	unsigned long addr, size, mem;
+	u16 id;
+	int rc = -ENODEV;
+
+	id = bochs_read(VBE_DISPI_INDEX_ID);;
+	mem = bochs_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
+	dev_info(&dp->dev,"Found bochs VGA, ID 0x%x, mem %ldk, type \"%s\".\n",
+		 id, mem / 1024, bochs_names[ent->driver_data]);
+	if ((id & 0xfff0) != VBE_DISPI_ID0) {
+		dev_err(&dp->dev, "ID mismatch\n");
+		goto err_out;
+	}
+
+	if (pci_enable_device(dp) < 0) {
+		dev_err(&dp->dev, "Cannot enable PCI device\n");
+		goto err_out;
+	}
+
+	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
+		goto err_disable;
+	addr = pci_resource_start(dp, 0);
+	size = pci_resource_len(dp, 0);
+	if (addr == 0)
+		goto err_disable;
+	if (size != mem) {
+		dev_err(&dp->dev, "Size mismatch: pci=%ld, bochs=%ld\n", size, mem);
+		size = min(size, mem);
+	}
+
+	p = framebuffer_alloc(0, &dp->dev);
+	if (p == NULL) {
+		dev_err(&dp->dev, "Cannot allocate framebuffer structure\n");
+		rc = -ENOMEM;
+		goto err_disable;
+	}
+
+	if (pci_request_region(dp, 0, "bochsfb") != 0) {
+		dev_err(&dp->dev, "Cannot request framebuffer\n");
+		rc = -EBUSY;
+		goto err_release_fb;
+	}
+
+	if (!request_region(VBE_DISPI_IOPORT_INDEX, 2, "bochsfb")) {
+		dev_err(&dp->dev, "Cannot request ioports\n");
+		rc = -EBUSY;
+		goto err_release_pci;
+	}
+
+	p->screen_base = ioremap(addr, size);
+	if (p->screen_base == NULL) {
+		dev_err(&dp->dev, "Cannot map framebuffer\n");
+		rc = -ENOMEM;
+		goto err_release_ports;
+	}
+	memset(p->screen_base, 0, size);
+
+	pci_set_drvdata(dp, p);
+	p->fbops = &bochsfb_ops;
+	p->flags = FBINFO_FLAG_DEFAULT
+		| FBINFO_READS_FAST
+		| FBINFO_HWACCEL_XPAN
+		| FBINFO_HWACCEL_YPAN;
+	p->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+	p->fix = bochsfb_fix;
+	p->fix.smem_start = addr;
+	p->fix.smem_len = size;
+
+	p->var = bochsfb_var;
+	bochsfb_check_var(&p->var, p);
+	if (mode) {
+		fb_find_mode(&p->var, p, mode, NULL, 0, NULL, 32);
+	}
+
+	if (register_framebuffer(p) < 0) {
+		dev_err(&dp->dev,"Framebuffer failed to register\n");
+		goto err_unmap;
+	}
+
+	dev_info(&dp->dev,"fb%d: bochs VGA frame buffer initialized.\n",
+		 p->node);
+
+	return 0;
+
+ err_unmap:
+	iounmap(p->screen_base);
+ err_release_ports:
+	release_region(VBE_DISPI_IOPORT_INDEX, 2);
+ err_release_pci:
+	pci_release_region(dp, 0);
+ err_release_fb:
+	framebuffer_release(p);
+ err_disable:
+ err_out:
+	return rc;
+}
+
+static void __devexit bochsfb_remove(struct pci_dev *dp)
+{
+	struct fb_info *p = pci_get_drvdata(dp);
+
+	if (p->screen_base == NULL)
+		return;
+	unregister_framebuffer(p);
+	iounmap(p->screen_base);
+	p->screen_base = NULL;
+	release_region(VBE_DISPI_IOPORT_INDEX, 2);
+	pci_release_region(dp, 0);
+	kfree(p->pseudo_palette);
+	framebuffer_release(p);
+}
+
+static struct pci_device_id bochsfb_pci_tbl[] = {
+	{
+		.vendor      = 0x1234,
+		.device      = 0x1111,
+		.subvendor   = 0x1af4,
+		.subdevice   = 0x1100,
+		.driver_data = BOCHS_QEMU_STDVGA,
+	},
+	{
+		.vendor      = 0x1234,
+		.device      = 0x1111,
+		.subvendor   = PCI_ANY_ID,
+		.subdevice   = PCI_ANY_ID,
+		.driver_data = BOCHS_UNKNOWN,
+	},
+	{ /* end of list */ }
+};
+
+MODULE_DEVICE_TABLE(pci, bochsfb_pci_tbl);
+
+static struct pci_driver bochsfb_driver = {
+	.name =		"bochsfb",
+	.id_table =	bochsfb_pci_tbl,
+	.probe =	bochsfb_pci_init,
+	.remove =	__devexit_p(bochsfb_remove),
+};
+
+#ifndef MODULE
+static int __init bochsfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			mode = this_opt + 5;
+		else
+			mode = this_opt;
+	}
+	return 0;
+}
+#endif
+
+int __init bochs_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("bochsfb", &option))
+		return -ENODEV;
+	bochsfb_setup(option);
+#endif
+	return pci_register_driver(&bochsfb_driver);
+}
+
+module_init(bochs_init);
+
+static void __exit bochsfb_exit(void)
+{
+	pci_unregister_driver(&bochsfb_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
+MODULE_DESCRIPTION("bochs dispi interface framebuffer driver");
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-08-06 12:03 ` Gerd Hoffmann
@ 2012-08-06 21:07   ` Benjamin Herrenschmidt
  2012-08-10 15:27   ` Alon Levy
  1 sibling, 0 replies; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2012-08-06 21:07 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Mon, 2012-08-06 at 14:03 +0200, Gerd Hoffmann wrote:
> Hacked up something like that a while back (patch attached).  Doesn't
> use DRM though, just plain old fbdev.  Maybe you can reuse some bits
> nevertheless.
> 
> /me wonders what the advantage of using drm is for non-3D hardware?

Thanks. Yeah fbdev is easier, but drm makes fedora happy :-)

Also makes things easier to support RandR in X nowadays using KMS APIs
etc... Besides I have evil plans to look at piping GL through the virtio
tube :-)

In fact, I've changed my focus and am now working on a virtio-vga (ie
new device). It still does VBE/VGA legacy (so the BIOS stuff works
etc...), but has BAR 0 as a virtio BAR on which I added a FB BAR.

I'll post more when I have more to show, I'm juggling with many
different things at the moment so it will take time.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] vga-pci and MMIO BAR
  2012-08-06 12:03 ` Gerd Hoffmann
  2012-08-06 21:07   ` Benjamin Herrenschmidt
@ 2012-08-10 15:27   ` Alon Levy
  1 sibling, 0 replies; 13+ messages in thread
From: Alon Levy @ 2012-08-10 15:27 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Mon, Aug 06, 2012 at 02:03:59PM +0200, Gerd Hoffmann wrote:
> On 07/25/12 05:57, Benjamin Herrenschmidt wrote:
> > Hi folks !
> > 
> > Would there be any objection to adding a second MMIO BAR to qemu-vga
> > which mirrors the bochs magic VBE ports ?
> 
> No.
> 
> > Once done, I'd like to look into doing a qemudrmfb similar to the cirrus
> > one that pretty much gives you generic KMS support (with RandR) on top
> > of vga-pci. This would have the advantage of potentially lifting the
> > pitch and size limitations that plague cirrus.
> 
> Hacked up something like that a while back (patch attached).  Doesn't
> use DRM though, just plain old fbdev.  Maybe you can reuse some bits
> nevertheless.
> 
> /me wonders what the advantage of using drm is for non-3D hardware?

Supporting kernel mode setting for plymouth for instance.

> 
> cheers,
>   Gerd

> From 637f637df63a2fc676d7fa09c4fec40172559bab Mon Sep 17 00:00:00 2001
> From: Gerd Hoffmann <kraxel@redhat.com>
> Date: Tue, 6 Mar 2012 14:34:38 +0100
> Subject: [PATCH] add bochs dispi interface framebuffer driver
> 
> This patchs adds a frame buffer driver for (virtual/emulated) vga cards
> implementing the bochs dispi interface.  Supported hardware are the
> bochs vga card with vbe extension and the qemu standard vga.
> 
> The driver uses a fixed depth of 32bpp.  Otherwise it supports the full
> (but small) feature set of the bochs dispi interface:  Resolution
> switching and display panning.  It is tweaked to maximize fbcon speed,
> so you'll get the comfort of the framebuffer console in kvm guests
> without performance penalty.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  drivers/video/Kconfig   |   18 +++
>  drivers/video/Makefile  |    1 +
>  drivers/video/bochsfb.c |  385 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 404 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/video/bochsfb.c
> 
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 0217f74..cf401ce 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -286,6 +286,24 @@ config FB_CIRRUS
>  	  Say N unless you have such a graphics board or plan to get one
>  	  before you next recompile the kernel.
>  
> +config FB_BOCHS
> +	tristate "Bochs dispi interface support"
> +	depends on FB && PCI
> +	select FB_CFB_FILLRECT
> +	select FB_CFB_COPYAREA
> +	select FB_CFB_IMAGEBLIT
> +	---help---
> +	  This is the frame buffer driver for (virtual/emulated) vga
> +          cards implementing the bochs dispi interface.  Supported
> +          hardware are the bochs vga card with vbe extension and the
> +          qemu standard vga.
> +
> +          The driver handles the PCI variants only.  It uses a fixed
> +          depth of 32bpp, anything else doesn't make sense these days.
> +
> +          Say Y here if you plan to run the kernel in a virtual machine
> +          emulated by bochs or qemu.
> +
>  config FB_PM2
>  	tristate "Permedia2 support"
>  	depends on FB && ((AMIGA && BROKEN) || PCI)
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index ee8dafb..81b78f1 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -102,6 +102,7 @@ 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_BOCHS)		  += bochsfb.o
>  obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
>  obj-$(CONFIG_FB_PXA)		  += pxafb.o
>  obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
> diff --git a/drivers/video/bochsfb.c b/drivers/video/bochsfb.c
> new file mode 100644
> index 0000000..18a94dc
> --- /dev/null
> +++ b/drivers/video/bochsfb.c
> @@ -0,0 +1,385 @@
> +/*
> + *  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/module.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/mm.h>
> +#include <linux/vmalloc.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/fb.h>
> +#include <linux/pm.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/console.h>
> +#include <asm/io.h>
> +
> +#define VBE_DISPI_IOPORT_INDEX           0x01CE
> +#define VBE_DISPI_IOPORT_DATA            0x01CF
> +
> +#define VBE_DISPI_INDEX_ID               0x0
> +#define VBE_DISPI_INDEX_XRES             0x1
> +#define VBE_DISPI_INDEX_YRES             0x2
> +#define VBE_DISPI_INDEX_BPP              0x3
> +#define VBE_DISPI_INDEX_ENABLE           0x4
> +#define VBE_DISPI_INDEX_BANK             0x5
> +#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
> +#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
> +#define VBE_DISPI_INDEX_X_OFFSET         0x8
> +#define VBE_DISPI_INDEX_Y_OFFSET         0x9
> +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
> +
> +#define VBE_DISPI_ID0                    0xB0C0
> +#define VBE_DISPI_ID1                    0xB0C1
> +#define VBE_DISPI_ID2                    0xB0C2
> +#define VBE_DISPI_ID3                    0xB0C3
> +#define VBE_DISPI_ID4                    0xB0C4
> +#define VBE_DISPI_ID5                    0xB0C5
> +
> +#define VBE_DISPI_DISABLED               0x00
> +#define VBE_DISPI_ENABLED                0x01
> +#define VBE_DISPI_GETCAPS                0x02
> +#define VBE_DISPI_8BIT_DAC               0x20
> +#define VBE_DISPI_LFB_ENABLED            0x40
> +#define VBE_DISPI_NOCLEARMEM             0x80
> +
> +enum bochs_types {
> +	BOCHS_QEMU_STDVGA,
> +	BOCHS_UNKNOWN,
> +};
> +
> +static const char *bochs_names[] = {
> +	[ BOCHS_QEMU_STDVGA ] = "QEMU standard vga",
> +	[ BOCHS_UNKNOWN ]     = "unknown",
> +};
> +
> +static struct fb_fix_screeninfo bochsfb_fix __devinitdata = {
> +	.id          = "bochsfb",
> +	.type        = FB_TYPE_PACKED_PIXELS,
> +	.visual      = FB_VISUAL_TRUECOLOR,
> +	.accel       = FB_ACCEL_NONE,
> +	.xpanstep    = 1,
> +	.ypanstep    = 1,
> +};
> +
> +static struct fb_var_screeninfo bochsfb_var __devinitdata = {
> +	.xres           = 1024,
> +	.yres           = 768,
> +	.bits_per_pixel = 32,
> +#ifdef __BIG_ENDIAN
> +	.transp         = { .length = 8, .offset =  0 },
> +	.red            = { .length = 8, .offset =  8 },
> +	.green          = { .length = 8, .offset = 16 },
> +	.blue           = { .length = 8, .offset = 24 },
> +#else
> +	.transp         = { .length = 8, .offset = 24 },
> +	.red            = { .length = 8, .offset = 16 },
> +	.green          = { .length = 8, .offset =  8 },
> +	.blue           = { .length = 8, .offset =  0 },
> +#endif
> +	.height         = -1,
> +	.width          = -1,
> +	.vmode          = FB_VMODE_NONINTERLACED,
> +	.pixclock       = 10000,
> +	.left_margin    = 16,
> +	.right_margin   = 16,
> +	.upper_margin   = 16,
> +	.lower_margin   = 16,
> +	.hsync_len      = 8,
> +	.vsync_len      = 8,
> +};
> +
> +static char *mode __devinitdata;
> +module_param(mode, charp, 0);
> +MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480'");
> +
> +static u16 bochs_read(u16 reg)
> +{
> +	outw(reg, VBE_DISPI_IOPORT_INDEX);
> +	return inw(VBE_DISPI_IOPORT_DATA);
> +}
> +
> +static void bochs_write(u16 reg, u16 val)
> +{
> +	outw(reg, VBE_DISPI_IOPORT_INDEX);
> +	outw(val, VBE_DISPI_IOPORT_DATA);
> +}
> +
> +static int bochsfb_check_var(struct fb_var_screeninfo *var,
> +			     struct fb_info *info)
> +{
> +	uint32_t x,y, xv,yv, pixels;
> +
> +	if (var->bits_per_pixel != 32 ||
> +	    var->xres > 65535 ||
> +	    var->xres_virtual > 65535 ||
> +	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
> +		return -EINVAL;
> +
> +	x  = var->xres & ~0x0f;
> +	y  = var->yres & ~0x03;
> +	xv = var->xres_virtual & ~0x0f;
> +	yv = var->yres_virtual & ~0x03;
> +	if (xv < x)
> +		xv = x;
> +	pixels = info->fix.smem_len * 8 / info->var.bits_per_pixel;
> +	yv = pixels / xv;
> +	if (y > yv)
> +		return -EINVAL;
> +
> +	var->xres = x;
> +	var->yres = y;
> +	var->xres_virtual = xv;
> +	var->yres_virtual = yv;
> +	var->xoffset = 0;
> +	var->yoffset = 0;
> +
> +	return 0;
> +}
> +
> +static int bochsfb_set_par(struct fb_info *info)
> +{
> +	dev_dbg(info->dev, "set mode: real: %dx%d, virtual: %dx%d\n",
> +		info->var.xres, info->var.yres,
> +		info->var.xres_virtual, info->var.yres_virtual);
> +
> +	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
> +
> +	bochs_write(VBE_DISPI_INDEX_BPP,         info->var.bits_per_pixel);
> +	bochs_write(VBE_DISPI_INDEX_XRES,        info->var.xres);
> +	bochs_write(VBE_DISPI_INDEX_YRES,        info->var.yres);
> +	bochs_write(VBE_DISPI_INDEX_BANK,        0);
> +	bochs_write(VBE_DISPI_INDEX_VIRT_WIDTH,  info->var.xres_virtual);
> +	bochs_write(VBE_DISPI_INDEX_VIRT_HEIGHT, info->var.yres_virtual);
> +	bochs_write(VBE_DISPI_INDEX_X_OFFSET,    info->var.xoffset);
> +	bochs_write(VBE_DISPI_INDEX_Y_OFFSET,    info->var.yoffset);
> +
> +	bochs_write(VBE_DISPI_INDEX_ENABLE,
> +		    VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
> +	return 0;
> +}
> +
> +static int bochsfb_setcolreg(unsigned regno, unsigned red, unsigned green,
> +			     unsigned blue, unsigned transp,
> +			     struct fb_info *info)
> +{
> +	if (regno < 16 && info->var.bits_per_pixel == 32) {
> +		red   >>= 8;
> +		green >>= 8;
> +		blue  >>= 8;
> +		((u32 *)(info->pseudo_palette))[regno] =
> +			(red   << info->var.red.offset)   |
> +			(green << info->var.green.offset) |
> +			(blue  << info->var.blue.offset);
> +	}
> +	return 0;
> +}
> +
> +static int bochsfb_pan_display(struct fb_var_screeninfo *var,
> +			       struct fb_info *info)
> +{
> +	bochs_write(VBE_DISPI_INDEX_X_OFFSET, var->xoffset);
> +	bochs_write(VBE_DISPI_INDEX_Y_OFFSET, var->yoffset);
> +	return 0;
> +}
> +
> +static struct fb_ops bochsfb_ops = {
> +	.owner	        = THIS_MODULE,
> +	.fb_check_var   = bochsfb_check_var,
> +	.fb_set_par     = bochsfb_set_par,
> +	.fb_setcolreg   = bochsfb_setcolreg,
> +	.fb_pan_display = bochsfb_pan_display,
> +	.fb_fillrect    = cfb_fillrect,
> +	.fb_copyarea    = cfb_copyarea,
> +	.fb_imageblit   = cfb_imageblit,
> +};
> +
> +static int __devinit
> +bochsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
> +{
> +	struct fb_info *p;
> +	unsigned long addr, size, mem;
> +	u16 id;
> +	int rc = -ENODEV;
> +
> +	id = bochs_read(VBE_DISPI_INDEX_ID);;
> +	mem = bochs_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
> +	dev_info(&dp->dev,"Found bochs VGA, ID 0x%x, mem %ldk, type \"%s\".\n",
> +		 id, mem / 1024, bochs_names[ent->driver_data]);
> +	if ((id & 0xfff0) != VBE_DISPI_ID0) {
> +		dev_err(&dp->dev, "ID mismatch\n");
> +		goto err_out;
> +	}
> +
> +	if (pci_enable_device(dp) < 0) {
> +		dev_err(&dp->dev, "Cannot enable PCI device\n");
> +		goto err_out;
> +	}
> +
> +	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
> +		goto err_disable;
> +	addr = pci_resource_start(dp, 0);
> +	size = pci_resource_len(dp, 0);
> +	if (addr == 0)
> +		goto err_disable;
> +	if (size != mem) {
> +		dev_err(&dp->dev, "Size mismatch: pci=%ld, bochs=%ld\n", size, mem);
> +		size = min(size, mem);
> +	}
> +
> +	p = framebuffer_alloc(0, &dp->dev);
> +	if (p == NULL) {
> +		dev_err(&dp->dev, "Cannot allocate framebuffer structure\n");
> +		rc = -ENOMEM;
> +		goto err_disable;
> +	}
> +
> +	if (pci_request_region(dp, 0, "bochsfb") != 0) {
> +		dev_err(&dp->dev, "Cannot request framebuffer\n");
> +		rc = -EBUSY;
> +		goto err_release_fb;
> +	}
> +
> +	if (!request_region(VBE_DISPI_IOPORT_INDEX, 2, "bochsfb")) {
> +		dev_err(&dp->dev, "Cannot request ioports\n");
> +		rc = -EBUSY;
> +		goto err_release_pci;
> +	}
> +
> +	p->screen_base = ioremap(addr, size);
> +	if (p->screen_base == NULL) {
> +		dev_err(&dp->dev, "Cannot map framebuffer\n");
> +		rc = -ENOMEM;
> +		goto err_release_ports;
> +	}
> +	memset(p->screen_base, 0, size);
> +
> +	pci_set_drvdata(dp, p);
> +	p->fbops = &bochsfb_ops;
> +	p->flags = FBINFO_FLAG_DEFAULT
> +		| FBINFO_READS_FAST
> +		| FBINFO_HWACCEL_XPAN
> +		| FBINFO_HWACCEL_YPAN;
> +	p->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
> +	p->fix = bochsfb_fix;
> +	p->fix.smem_start = addr;
> +	p->fix.smem_len = size;
> +
> +	p->var = bochsfb_var;
> +	bochsfb_check_var(&p->var, p);
> +	if (mode) {
> +		fb_find_mode(&p->var, p, mode, NULL, 0, NULL, 32);
> +	}
> +
> +	if (register_framebuffer(p) < 0) {
> +		dev_err(&dp->dev,"Framebuffer failed to register\n");
> +		goto err_unmap;
> +	}
> +
> +	dev_info(&dp->dev,"fb%d: bochs VGA frame buffer initialized.\n",
> +		 p->node);
> +
> +	return 0;
> +
> + err_unmap:
> +	iounmap(p->screen_base);
> + err_release_ports:
> +	release_region(VBE_DISPI_IOPORT_INDEX, 2);
> + err_release_pci:
> +	pci_release_region(dp, 0);
> + err_release_fb:
> +	framebuffer_release(p);
> + err_disable:
> + err_out:
> +	return rc;
> +}
> +
> +static void __devexit bochsfb_remove(struct pci_dev *dp)
> +{
> +	struct fb_info *p = pci_get_drvdata(dp);
> +
> +	if (p->screen_base == NULL)
> +		return;
> +	unregister_framebuffer(p);
> +	iounmap(p->screen_base);
> +	p->screen_base = NULL;
> +	release_region(VBE_DISPI_IOPORT_INDEX, 2);
> +	pci_release_region(dp, 0);
> +	kfree(p->pseudo_palette);
> +	framebuffer_release(p);
> +}
> +
> +static struct pci_device_id bochsfb_pci_tbl[] = {
> +	{
> +		.vendor      = 0x1234,
> +		.device      = 0x1111,
> +		.subvendor   = 0x1af4,
> +		.subdevice   = 0x1100,
> +		.driver_data = BOCHS_QEMU_STDVGA,
> +	},
> +	{
> +		.vendor      = 0x1234,
> +		.device      = 0x1111,
> +		.subvendor   = PCI_ANY_ID,
> +		.subdevice   = PCI_ANY_ID,
> +		.driver_data = BOCHS_UNKNOWN,
> +	},
> +	{ /* end of list */ }
> +};
> +
> +MODULE_DEVICE_TABLE(pci, bochsfb_pci_tbl);
> +
> +static struct pci_driver bochsfb_driver = {
> +	.name =		"bochsfb",
> +	.id_table =	bochsfb_pci_tbl,
> +	.probe =	bochsfb_pci_init,
> +	.remove =	__devexit_p(bochsfb_remove),
> +};
> +
> +#ifndef MODULE
> +static int __init bochsfb_setup(char *options)
> +{
> +	char *this_opt;
> +
> +	if (!options || !*options)
> +		return 0;
> +
> +	while ((this_opt = strsep(&options, ",")) != NULL) {
> +		if (!*this_opt)
> +			continue;
> +		if (!strncmp(this_opt, "mode:", 5))
> +			mode = this_opt + 5;
> +		else
> +			mode = this_opt;
> +	}
> +	return 0;
> +}
> +#endif
> +
> +int __init bochs_init(void)
> +{
> +#ifndef MODULE
> +	char *option = NULL;
> +
> +	if (fb_get_options("bochsfb", &option))
> +		return -ENODEV;
> +	bochsfb_setup(option);
> +#endif
> +	return pci_register_driver(&bochsfb_driver);
> +}
> +
> +module_init(bochs_init);
> +
> +static void __exit bochsfb_exit(void)
> +{
> +	pci_unregister_driver(&bochsfb_driver);
> +}
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
> +MODULE_DESCRIPTION("bochs dispi interface framebuffer driver");
> -- 
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-08-10 15:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-25  3:57 [Qemu-devel] vga-pci and MMIO BAR Benjamin Herrenschmidt
2012-07-25 10:27 ` Avi Kivity
2012-07-25 10:53   ` Benjamin Herrenschmidt
2012-07-25 12:48     ` Avi Kivity
2012-07-25 13:41       ` Benjamin Herrenschmidt
2012-07-25 13:59         ` Avi Kivity
2012-07-25 22:01           ` Benjamin Herrenschmidt
2012-07-26  0:22             ` Benjamin Herrenschmidt
2012-07-26  1:08               ` Anthony Liguori
2012-07-26  1:18                 ` Benjamin Herrenschmidt
2012-08-06 12:03 ` Gerd Hoffmann
2012-08-06 21:07   ` Benjamin Herrenschmidt
2012-08-10 15:27   ` Alon Levy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.