diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2013-06-18 23:41:21 +0200 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2013-06-19 02:00:08 +0200 |
commit | 414b9478518836ce72084edba1c3a51b0a745d0c (patch) | |
tree | fb34cae69da830af28d24022fbbd5883448180e6 /src/drivers/emulation/qemu/bochs.c | |
parent | 0ea3664bc30f81fbeb9d2ce9b7ca1e83e788aa23 (diff) |
qemu: complete bochs dispi interface vga driver.
Ditch unused fb*.h files.
Rename init.c (name is _way_ to generic) to bochs.c.
Add proper bochs dispi interface detection and mode setup.
Hook up coreboot framebuffer table initialization.
Change-Id: I7154b1593902e7d42606b64819217872eee10683
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-on: http://review.coreboot.org/3500
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/drivers/emulation/qemu/bochs.c')
-rw-r--r-- | src/drivers/emulation/qemu/bochs.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/drivers/emulation/qemu/bochs.c b/src/drivers/emulation/qemu/bochs.c new file mode 100644 index 0000000000..1fd7e28ef2 --- /dev/null +++ b/src/drivers/emulation/qemu/bochs.c @@ -0,0 +1,150 @@ +#include <delay.h> +#include <stdlib.h> +#include <string.h> +#include <arch/io.h> + +#include <boot/coreboot_tables.h> +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> + +/* VGA init. We use the Bochs VESA VBE extensions */ +#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_ID4 0xB0C4 +#define VBE_DISPI_ID5 0xB0C5 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +static int width = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES; +static int height = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES; +static u32 addr = 0; + +static void bochs_write(int index, int val) +{ + outw(index, VBE_DISPI_IOPORT_INDEX); + outw(val, VBE_DISPI_IOPORT_DATA); +} + +static int bochs_read(int index) +{ + outw(index, VBE_DISPI_IOPORT_INDEX); + return inw(VBE_DISPI_IOPORT_DATA); +} + +static void bochs_init(device_t dev) +{ + int id, mem, bar; + + /* bochs dispi detection */ + id = bochs_read(VBE_DISPI_INDEX_ID); + if ((id & 0xfff0) != VBE_DISPI_ID0) { + printk(BIOS_DEBUG, "QEMU VGA: bochs dispi: ID mismatch.\n"); + return; + } + mem = bochs_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024; + printk(BIOS_DEBUG, "QEMU VGA: bochs dispi interface found, " + "%d MiB video memory\n", mem / ( 1024 * 1024)); + + /* find lfb pci bar */ + addr = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { + /* qemu -vga {std,qxl} */ + bar = 0; + } else { + /* qemu -vga vmware */ + addr = pci_read_config32(dev, PCI_BASE_ADDRESS_1); + bar = 1; + } + addr &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK; + printk(BIOS_DEBUG, "QEMU VGA: framebuffer @ %x (pci bar %d)\n", + addr, bar); + + /* setup video mode */ + bochs_write(VBE_DISPI_INDEX_ENABLE, 0); + bochs_write(VBE_DISPI_INDEX_BANK, 0); + bochs_write(VBE_DISPI_INDEX_BPP, 32); + bochs_write(VBE_DISPI_INDEX_XRES, width); + bochs_write(VBE_DISPI_INDEX_YRES, height); + bochs_write(VBE_DISPI_INDEX_VIRT_WIDTH, width); + bochs_write(VBE_DISPI_INDEX_VIRT_HEIGHT, height); + bochs_write(VBE_DISPI_INDEX_X_OFFSET, 0); + bochs_write(VBE_DISPI_INDEX_Y_OFFSET, 0); + bochs_write(VBE_DISPI_INDEX_ENABLE, + VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + + outb(0x20, 0x3c0); /* disable blanking */ +} + +int vbe_mode_info_valid(void); +int vbe_mode_info_valid(void) +{ + return addr != 0; +} + +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer) +{ + printk(BIOS_DEBUG, "QEMU VGA: fill lb_framebuffer: %dx%d @ %x\n", + width, height, addr); + + framebuffer->physical_address = addr; + framebuffer->x_resolution = width; + framebuffer->y_resolution = height; + framebuffer->bytes_per_line = width * 4; + framebuffer->bits_per_pixel = 32; + framebuffer->red_mask_pos = 16; + framebuffer->red_mask_size = 8; + framebuffer->green_mask_pos = 8; + framebuffer->green_mask_size = 8; + framebuffer->blue_mask_pos = 0; + framebuffer->blue_mask_size = 8; + framebuffer->reserved_mask_pos = 24; + framebuffer->reserved_mask_size = 8; +} + +static struct device_operations qemu_graph_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = bochs_init, + .scan_bus = 0, +}; + +static const struct pci_driver qemu_stdvga_driver __pci_driver = { + .ops = &qemu_graph_ops, + .vendor = 0x1234, + .device = 0x1111, +}; + +static const struct pci_driver qemu_vmware_driver __pci_driver = { + .ops = &qemu_graph_ops, + .vendor = 0x15ad, + .device = 0x0405, +}; +static const struct pci_driver qemu_qxl_driver __pci_driver = { + .ops = &qemu_graph_ops, + .vendor = 0x1b36, + .device = 0x0100, +}; |