xref: /kvmtool/hw/vesa.c (revision 73f7e5b39938fbb3e2c900701f07e730853432cf)
1 #include "kvm/vesa.h"
2 
3 #include "kvm/virtio-pci-dev.h"
4 #include "kvm/framebuffer.h"
5 #include "kvm/kvm-cpu.h"
6 #include "kvm/ioport.h"
7 #include "kvm/util.h"
8 #include "kvm/irq.h"
9 #include "kvm/kvm.h"
10 #include "kvm/pci.h"
11 
12 #include <sys/types.h>
13 #include <sys/ioctl.h>
14 #include <inttypes.h>
15 #include <unistd.h>
16 
17 static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
18 {
19 	return true;
20 }
21 
22 static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
23 {
24 	return true;
25 }
26 
27 static struct ioport_operations vesa_io_ops = {
28 	.io_in			= vesa_pci_io_in,
29 	.io_out			= vesa_pci_io_out,
30 };
31 
32 static struct pci_device_header vesa_pci_device = {
33 	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
34 	.device_id		= PCI_DEVICE_ID_VESA,
35 	.header_type		= PCI_HEADER_TYPE_NORMAL,
36 	.revision_id		= 0,
37 	.class			= 0x030000,
38 	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
39 	.subsys_id		= PCI_SUBSYSTEM_ID_VESA,
40 	.bar[1]			= VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY,
41 };
42 
43 static void vesa_mmio_callback(u64 addr, u8 *data, u32 len, u8 is_write)
44 {
45 	if (!is_write)
46 		return;
47 
48 	fb__write(addr, data, len);
49 }
50 
51 static struct framebuffer vesafb;
52 
53 struct framebuffer *vesa__init(struct kvm *kvm)
54 {
55 	u16 vesa_base_addr;
56 	u8 dev, line, pin;
57 	char *mem;
58 
59 	if (irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line) < 0)
60 		return NULL;
61 
62 	vesa_pci_device.irq_pin		= pin;
63 	vesa_pci_device.irq_line	= line;
64 	vesa_base_addr			= ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
65 	vesa_pci_device.bar[0]		= vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
66 	pci__register(&vesa_pci_device, dev);
67 
68 	kvm__register_mmio(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, &vesa_mmio_callback);
69 
70 	mem = calloc(1, VESA_MEM_SIZE);
71 	if (!mem)
72 		return NULL;
73 
74 	vesafb = (struct framebuffer) {
75 		.width			= VESA_WIDTH,
76 		.height			= VESA_HEIGHT,
77 		.depth			= VESA_BPP,
78 		.mem			= mem,
79 		.mem_addr		= VESA_MEM_ADDR,
80 	};
81 	return fb__register(&vesafb);
82 }
83