qemu: Support textmode gfx init.
[coreboot.git] / src / drivers / emulation / qemu / bochs.c
blob715c94c6ec03864affb8b1578a88d8895b360cc9
1 #include <stdint.h>
2 #include <delay.h>
3 #include <edid.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <arch/io.h>
8 #include <boot/coreboot_tables.h>
9 #include <console/console.h>
10 #include <device/device.h>
11 #include <device/pci.h>
12 #include <device/pci_ids.h>
13 #include <device/pci_ops.h>
14 #include <pc80/vga.h>
15 #include <pc80/vga_io.h>
17 /* VGA init. We use the Bochs VESA VBE extensions */
18 #define VBE_DISPI_IOPORT_INDEX 0x01CE
19 #define VBE_DISPI_IOPORT_DATA 0x01CF
21 #define VBE_DISPI_INDEX_ID 0x0
22 #define VBE_DISPI_INDEX_XRES 0x1
23 #define VBE_DISPI_INDEX_YRES 0x2
24 #define VBE_DISPI_INDEX_BPP 0x3
25 #define VBE_DISPI_INDEX_ENABLE 0x4
26 #define VBE_DISPI_INDEX_BANK 0x5
27 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
28 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
29 #define VBE_DISPI_INDEX_X_OFFSET 0x8
30 #define VBE_DISPI_INDEX_Y_OFFSET 0x9
31 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
33 #define VBE_DISPI_ID0 0xB0C0
34 #define VBE_DISPI_ID1 0xB0C1
35 #define VBE_DISPI_ID2 0xB0C2
36 #define VBE_DISPI_ID4 0xB0C4
37 #define VBE_DISPI_ID5 0xB0C5
39 #define VBE_DISPI_DISABLED 0x00
40 #define VBE_DISPI_ENABLED 0x01
41 #define VBE_DISPI_LFB_ENABLED 0x40
42 #define VBE_DISPI_NOCLEARMEM 0x80
44 #if IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)
45 static int width = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES;
46 static int height = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES;
48 static void bochs_write(int index, int val)
50 outw(index, VBE_DISPI_IOPORT_INDEX);
51 outw(val, VBE_DISPI_IOPORT_DATA);
54 static int bochs_read(int index)
56 outw(index, VBE_DISPI_IOPORT_INDEX);
57 return inw(VBE_DISPI_IOPORT_DATA);
59 #endif
61 static void bochs_init(device_t dev)
63 #if IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)
64 struct edid edid;
65 int id, mem, bar;
66 u32 addr;
68 /* bochs dispi detection */
69 id = bochs_read(VBE_DISPI_INDEX_ID);
70 if ((id & 0xfff0) != VBE_DISPI_ID0) {
71 printk(BIOS_DEBUG, "QEMU VGA: bochs dispi: ID mismatch.\n");
72 return;
74 mem = bochs_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
76 /* find lfb pci bar */
77 addr = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
78 if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
79 /* qemu -vga {std,qxl} */
80 bar = 0;
81 } else {
82 /* qemu -vga vmware */
83 addr = pci_read_config32(dev, PCI_BASE_ADDRESS_1);
84 bar = 1;
86 addr &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
88 if (!addr)
89 return;
91 printk(BIOS_DEBUG, "QEMU VGA: bochs dispi interface found, "
92 "%d MiB video memory\n", mem / ( 1024 * 1024));
93 printk(BIOS_DEBUG, "QEMU VGA: framebuffer @ %x (pci bar %d)\n",
94 addr, bar);
96 /* setup video mode */
97 bochs_write(VBE_DISPI_INDEX_ENABLE, 0);
98 bochs_write(VBE_DISPI_INDEX_BANK, 0);
99 bochs_write(VBE_DISPI_INDEX_BPP, 32);
100 bochs_write(VBE_DISPI_INDEX_XRES, width);
101 bochs_write(VBE_DISPI_INDEX_YRES, height);
102 bochs_write(VBE_DISPI_INDEX_VIRT_WIDTH, width);
103 bochs_write(VBE_DISPI_INDEX_VIRT_HEIGHT, height);
104 bochs_write(VBE_DISPI_INDEX_X_OFFSET, 0);
105 bochs_write(VBE_DISPI_INDEX_Y_OFFSET, 0);
106 bochs_write(VBE_DISPI_INDEX_ENABLE,
107 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
109 outb(0x20, 0x3c0); /* disable blanking */
111 /* setup coreboot framebuffer */
112 edid.ha = width;
113 edid.va = height;
114 edid.x_resolution = width;
115 edid.y_resolution = height;
116 edid.bytes_per_line = width * 4;
117 edid.bpp = 32;
118 set_vbe_mode_info_valid(&edid, addr);
119 #else
120 vga_misc_write(0x1);
121 vga_textmode_init();
122 #endif
125 static struct device_operations qemu_graph_ops = {
126 .read_resources = pci_dev_read_resources,
127 .set_resources = pci_dev_set_resources,
128 .enable_resources = pci_dev_enable_resources,
129 .init = bochs_init,
130 .scan_bus = 0,
133 static const struct pci_driver qemu_stdvga_driver __pci_driver = {
134 .ops = &qemu_graph_ops,
135 .vendor = 0x1234,
136 .device = 0x1111,
139 static const struct pci_driver qemu_vmware_driver __pci_driver = {
140 .ops = &qemu_graph_ops,
141 .vendor = 0x15ad,
142 .device = 0x0405,
144 static const struct pci_driver qemu_qxl_driver __pci_driver = {
145 .ops = &qemu_graph_ops,
146 .vendor = 0x1b36,
147 .device = 0x0100,