soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / drivers / emulation / qemu / bochs.c
blob4634021b6772d3247a7c12aa826decaf08d21e19
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/mmio.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <device/pci_ops.h>
10 #include <framebuffer_info.h>
11 #include <pc80/vga.h>
12 #include <pc80/vga_io.h>
13 #include <stdint.h>
15 /* VGA init. We use the Bochs VESA VBE extensions */
16 #define VBE_DISPI_IOPORT_INDEX 0x01CE
17 #define VBE_DISPI_IOPORT_DATA 0x01CF
19 #define VBE_DISPI_INDEX_ID 0x0
20 #define VBE_DISPI_INDEX_XRES 0x1
21 #define VBE_DISPI_INDEX_YRES 0x2
22 #define VBE_DISPI_INDEX_BPP 0x3
23 #define VBE_DISPI_INDEX_ENABLE 0x4
24 #define VBE_DISPI_INDEX_BANK 0x5
25 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
26 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
27 #define VBE_DISPI_INDEX_X_OFFSET 0x8
28 #define VBE_DISPI_INDEX_Y_OFFSET 0x9
29 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
31 #define VBE_DISPI_ID0 0xB0C0
32 #define VBE_DISPI_ID1 0xB0C1
33 #define VBE_DISPI_ID2 0xB0C2
34 #define VBE_DISPI_ID4 0xB0C4
35 #define VBE_DISPI_ID5 0xB0C5
37 #define VBE_DISPI_DISABLED 0x00
38 #define VBE_DISPI_ENABLED 0x01
39 #define VBE_DISPI_LFB_ENABLED 0x40
40 #define VBE_DISPI_NOCLEARMEM 0x80
42 static int width = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_XRES;
43 static int height = CONFIG_DRIVERS_EMULATION_QEMU_BOCHS_YRES;
45 static void bochs_write(struct resource *res, int index, int val)
47 if (res->flags & IORESOURCE_IO) {
48 outw(index, res->base);
49 outw(val, res->base + 1);
50 } else {
51 write16(res2mmio(res, 0x500 + index * 2, 0), val);
55 static int bochs_read(struct resource *res, int index)
57 if (res->flags & IORESOURCE_IO) {
58 outw(index, res->base);
59 return inw(res->base + 1);
60 } else {
61 return read16(res2mmio(res, 0x500 + index * 2, 0));
65 static void bochs_vga_write(struct resource *res, int index, uint8_t val)
67 if (res->flags & IORESOURCE_IO)
68 outb(val, index + 0x3c0);
69 else
70 write8(res2mmio(res, (0x400 - 0x3c0) + index, 0), val);
73 static struct resource res_legacy = {
74 VBE_DISPI_IOPORT_INDEX,
75 VBE_DISPI_IOPORT_DATA - VBE_DISPI_IOPORT_INDEX,
76 VBE_DISPI_IOPORT_DATA,
77 NULL,
78 IORESOURCE_IO,
84 static void bochs_init_linear_fb(struct device *dev)
86 struct resource *res_fb, *res_io;
87 int id, mem, bar;
89 res_fb = probe_resource(dev, PCI_BASE_ADDRESS_0);
90 if (res_fb && res_fb->flags & IORESOURCE_MEM) {
91 /* qemu -vga {std,qxl} */
92 bar = 0;
93 } else {
94 res_fb = probe_resource(dev, PCI_BASE_ADDRESS_1);
95 if (res_fb && res_fb->flags & IORESOURCE_MEM) {
96 /* qemu -vga vmware */
97 bar = 1;
98 } else {
99 printk(BIOS_ERR, "%s: Not bochs compatible\n", dev_name(dev));
100 return;
104 /* MMIO bar supported since qemu 3.0+ */
105 res_io = probe_resource(dev, PCI_BASE_ADDRESS_2);
106 if (((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) ||
107 !res_io || !(res_io->flags & IORESOURCE_MEM)) {
108 printk(BIOS_DEBUG, "QEMU VGA: Using legacy VGA\n");
109 res_io = &res_legacy;
110 } else {
111 printk(BIOS_DEBUG, "QEMU VGA: Using I/O bar at %llx\n", res_io->base);
114 /* bochs dispi detection */
115 id = bochs_read(res_io, VBE_DISPI_INDEX_ID);
116 if ((id & 0xfff0) != VBE_DISPI_ID0) {
117 printk(BIOS_DEBUG, "QEMU VGA: bochs dispi: ID mismatch.\n");
118 return;
120 mem = bochs_read(res_io, VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
122 printk(BIOS_DEBUG, "QEMU VGA: bochs dispi interface found, "
123 "%d MiB video memory\n", mem / (1024 * 1024));
124 printk(BIOS_DEBUG, "QEMU VGA: framebuffer @ %llx (pci bar %d)\n",
125 res_fb->base, bar);
127 /* setup video mode */
128 bochs_write(res_io, VBE_DISPI_INDEX_ENABLE, 0);
129 bochs_write(res_io, VBE_DISPI_INDEX_BANK, 0);
130 bochs_write(res_io, VBE_DISPI_INDEX_BPP, 32);
131 bochs_write(res_io, VBE_DISPI_INDEX_XRES, width);
132 bochs_write(res_io, VBE_DISPI_INDEX_YRES, height);
133 bochs_write(res_io, VBE_DISPI_INDEX_VIRT_WIDTH, width);
134 bochs_write(res_io, VBE_DISPI_INDEX_VIRT_HEIGHT, height);
135 bochs_write(res_io, VBE_DISPI_INDEX_X_OFFSET, 0);
136 bochs_write(res_io, VBE_DISPI_INDEX_Y_OFFSET, 0);
137 bochs_write(res_io, VBE_DISPI_INDEX_ENABLE,
138 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
140 bochs_vga_write(res_io, 0, 0x20); /* disable blanking */
142 /* Advertise new mode */
143 fb_add_framebuffer_info(res_fb->base, width, height, 4 * width, 32);
146 static void bochs_init_text_mode(struct device *dev)
148 vga_misc_write(0x1);
149 vga_textmode_init();
152 static void bochs_init(struct device *dev)
154 if (CONFIG(LINEAR_FRAMEBUFFER))
155 bochs_init_linear_fb(dev);
156 else if (CONFIG(VGA_TEXT_FRAMEBUFFER))
157 bochs_init_text_mode(dev);
160 static struct device_operations qemu_graph_ops = {
161 .read_resources = pci_dev_read_resources,
162 .set_resources = pci_dev_set_resources,
163 .enable_resources = pci_dev_enable_resources,
164 .init = bochs_init,
167 static const struct pci_driver qemu_stdvga_driver __pci_driver = {
168 .ops = &qemu_graph_ops,
169 .vendor = 0x1234,
170 .device = 0x1111,
173 static const struct pci_driver qemu_vmware_driver __pci_driver = {
174 .ops = &qemu_graph_ops,
175 .vendor = 0x15ad,
176 .device = 0x0405,
178 static const struct pci_driver qemu_qxl_driver __pci_driver = {
179 .ops = &qemu_graph_ops,
180 .vendor = 0x1b36,
181 .device = 0x0100,