diff options
Diffstat (limited to 'roms/seabios-hppa/vgasrc/bochsdisplay.c')
-rw-r--r-- | roms/seabios-hppa/vgasrc/bochsdisplay.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/roms/seabios-hppa/vgasrc/bochsdisplay.c b/roms/seabios-hppa/vgasrc/bochsdisplay.c new file mode 100644 index 000000000..d7ff3e9f8 --- /dev/null +++ b/roms/seabios-hppa/vgasrc/bochsdisplay.c @@ -0,0 +1,79 @@ +// Simple framebuffer vgabios for use with qemu bochs-display device +// +// Copyright (C) 2019 Gerd Hoffmann <kraxel@redhat.com> +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_BDA +#include "output.h" // dprintf +#include "string.h" // memset16_far +#include "bochsvga.h" // VBE_BOCHS_* +#include "hw/pci.h" // pci_config_readl +#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "vgabios.h" // SET_VGA +#include "vgautil.h" // VBE_total_memory + +#define FRAMEBUFFER_WIDTH 1024 +#define FRAMEBUFFER_HEIGHT 768 +#define FRAMEBUFFER_BPP 4 + +int +bochs_display_setup(void) +{ + dprintf(1, "bochs-display: setup called\n"); + + if (GET_GLOBAL(HaveRunInit)) + return 0; + + int bdf = GET_GLOBAL(VgaBDF); + if (bdf == 0) + return 0; + + u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); + u32 lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK; + bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2); + u32 io_addr = bar & PCI_BASE_ADDRESS_IO_MASK; + dprintf(1, "bochs-display: bdf %02x:%02x.%x, bar 0 at 0x%x, bar 1 at 0x%x\n" + , pci_bdf_to_bus(bdf) , pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), + lfb_addr, io_addr); + + u16 *dispi = (void*)(io_addr + 0x500); + u8 *vga = (void*)(io_addr + 0x400); + u16 id = readw(dispi + VBE_DISPI_INDEX_ID); + dprintf(1, "bochs-display: id is 0x%x, %s\n", id + , id == VBE_DISPI_ID5 ? "good" : "FAIL"); + if (id != VBE_DISPI_ID5) + return -1; + + int i; + u8 *edid = (void*)(io_addr); + for (i = 0; i < sizeof(VBE_edid); i++) + SET_VGA(VBE_edid[i], readb(edid + i)); + + int fb_width = FRAMEBUFFER_WIDTH; + int fb_height = FRAMEBUFFER_HEIGHT; + if (GET_GLOBAL(VBE_edid[0]) == 0x00 && + GET_GLOBAL(VBE_edid[1]) == 0xff) { + fb_width = GET_GLOBAL(VBE_edid[54 + 2]); + fb_width |= (GET_GLOBAL(VBE_edid[54 + 4]) & 0xf0) << 4; + fb_height = GET_GLOBAL(VBE_edid[54 + 5]); + fb_height |= (GET_GLOBAL(VBE_edid[54 + 7]) & 0xf0) << 4; + } + int fb_stride = FRAMEBUFFER_BPP * fb_width; + + dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n" + , fb_width, fb_height + , FRAMEBUFFER_BPP * 8, fb_stride); + + cbvga_setup_modes(lfb_addr, FRAMEBUFFER_BPP * 8, + fb_width, fb_height, fb_stride); + + writew(dispi + VBE_DISPI_INDEX_XRES, fb_width); + writew(dispi + VBE_DISPI_INDEX_YRES, fb_height); + writew(dispi + VBE_DISPI_INDEX_BPP, FRAMEBUFFER_BPP * 8); + writew(dispi + VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED); + + writeb(vga, 0x20); /* unblank (for qemu -device VGA) */ + + return 0; +} |