xref: /kvmtool/hw/vesa.c (revision df4239fb27a9670b554d71fb4a79bacfb804d477)
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 <linux/byteorder.h>
13 #include <sys/mman.h>
14 #include <linux/err.h>
15 #include <sys/types.h>
16 #include <sys/ioctl.h>
17 #include <inttypes.h>
18 #include <unistd.h>
19 
20 static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
21 {
22 	return true;
23 }
24 
25 static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
26 {
27 	return true;
28 }
29 
30 static struct ioport_operations vesa_io_ops = {
31 	.io_in			= vesa_pci_io_in,
32 	.io_out			= vesa_pci_io_out,
33 };
34 
35 static struct pci_device_header vesa_pci_device = {
36 	.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
37 	.device_id		= cpu_to_le16(PCI_DEVICE_ID_VESA),
38 	.header_type		= PCI_HEADER_TYPE_NORMAL,
39 	.revision_id		= 0,
40 	.class[2]		= 0x03,
41 	.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
42 	.subsys_id		= cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
43 	.bar[1]			= cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
44 	.bar_size[1]		= VESA_MEM_SIZE,
45 };
46 
47 static struct framebuffer vesafb;
48 
49 struct framebuffer *vesa__init(struct kvm *kvm)
50 {
51 	u16 vesa_base_addr;
52 	u8 dev, line, pin;
53 	char *mem;
54 	int r;
55 
56 	r = irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line);
57 	if (r < 0)
58 		return ERR_PTR(r);
59 
60 	r = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
61 	if (r < 0)
62 		return ERR_PTR(r);
63 
64 	vesa_pci_device.irq_pin		= pin;
65 	vesa_pci_device.irq_line	= line;
66 	vesa_base_addr			= (u16)r;
67 	vesa_pci_device.bar[0]		= cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
68 	pci__register(&vesa_pci_device, dev);
69 
70 	mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
71 	if (mem == MAP_FAILED)
72 		ERR_PTR(-errno);
73 
74 	kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem);
75 
76 	vesafb = (struct framebuffer) {
77 		.width			= VESA_WIDTH,
78 		.height			= VESA_HEIGHT,
79 		.depth			= VESA_BPP,
80 		.mem			= mem,
81 		.mem_addr		= VESA_MEM_ADDR,
82 		.mem_size		= VESA_MEM_SIZE,
83 		.kvm			= kvm,
84 	};
85 	return fb__register(&vesafb);
86 }
87