xref: /kvmtool/hw/vesa.c (revision 7af40b910218435a553d510f50796e5cc19fc1dd)
1b025083dSJohn Floren #include "kvm/vesa.h"
2de960f08SPekka Enberg 
3de960f08SPekka Enberg #include "kvm/virtio-pci-dev.h"
4aba1efa5SPekka Enberg #include "kvm/framebuffer.h"
5de960f08SPekka Enberg #include "kvm/kvm-cpu.h"
6b025083dSJohn Floren #include "kvm/ioport.h"
7b025083dSJohn Floren #include "kvm/util.h"
8de960f08SPekka Enberg #include "kvm/irq.h"
9b025083dSJohn Floren #include "kvm/kvm.h"
10b025083dSJohn Floren #include "kvm/pci.h"
1148d9e01aSSasha Levin 
12aa73be70SMatt Evans #include <linux/byteorder.h>
1396feb589SPekka Enberg #include <sys/mman.h>
1448d9e01aSSasha Levin #include <linux/err.h>
15b025083dSJohn Floren #include <sys/types.h>
16b025083dSJohn Floren #include <sys/ioctl.h>
17b025083dSJohn Floren #include <inttypes.h>
18b025083dSJohn Floren #include <unistd.h>
19b025083dSJohn Floren 
20c9f6a037SXiao Guangrong static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
21b025083dSJohn Floren {
22b025083dSJohn Floren 	return true;
23b025083dSJohn Floren }
24b025083dSJohn Floren 
25c9f6a037SXiao Guangrong static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
26b025083dSJohn Floren {
27b025083dSJohn Floren 	return true;
28b025083dSJohn Floren }
29b025083dSJohn Floren 
30b025083dSJohn Floren static struct ioport_operations vesa_io_ops = {
31b025083dSJohn Floren 	.io_in			= vesa_pci_io_in,
32b025083dSJohn Floren 	.io_out			= vesa_pci_io_out,
33b025083dSJohn Floren };
34b025083dSJohn Floren 
35b025083dSJohn Floren static struct pci_device_header vesa_pci_device = {
36aa73be70SMatt Evans 	.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
37aa73be70SMatt Evans 	.device_id		= cpu_to_le16(PCI_DEVICE_ID_VESA),
38b025083dSJohn Floren 	.header_type		= PCI_HEADER_TYPE_NORMAL,
39b025083dSJohn Floren 	.revision_id		= 0,
40aa73be70SMatt Evans 	.class[2]		= 0x03,
41aa73be70SMatt Evans 	.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
42aa73be70SMatt Evans 	.subsys_id		= cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
43aa73be70SMatt Evans 	.bar[1]			= cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
444f045c57SSasha Levin 	.bar_size[1]		= VESA_MEM_SIZE,
45b025083dSJohn Floren };
46b025083dSJohn Floren 
47aba1efa5SPekka Enberg static struct framebuffer vesafb;
48aba1efa5SPekka Enberg 
49aba1efa5SPekka Enberg struct framebuffer *vesa__init(struct kvm *kvm)
50b025083dSJohn Floren {
51947392bcSSasha Levin 	u16 vesa_base_addr;
52aba1efa5SPekka Enberg 	u8 dev, line, pin;
53aba1efa5SPekka Enberg 	char *mem;
5448d9e01aSSasha Levin 	int r;
55b025083dSJohn Floren 
5648d9e01aSSasha Levin 	r = irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line);
5748d9e01aSSasha Levin 	if (r < 0)
5848d9e01aSSasha Levin 		return ERR_PTR(r);
59b025083dSJohn Floren 
60*7af40b91SSasha Levin 	r = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
61*7af40b91SSasha Levin 	if (r < 0)
62*7af40b91SSasha Levin 		return ERR_PTR(r);
63*7af40b91SSasha Levin 
64b025083dSJohn Floren 	vesa_pci_device.irq_pin		= pin;
65b025083dSJohn Floren 	vesa_pci_device.irq_line	= line;
66*7af40b91SSasha Levin 	vesa_base_addr			= (u16)r;
67aa73be70SMatt Evans 	vesa_pci_device.bar[0]		= cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
68b025083dSJohn Floren 	pci__register(&vesa_pci_device, dev);
69de960f08SPekka Enberg 
7096feb589SPekka Enberg 	mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
7196feb589SPekka Enberg 	if (mem == MAP_FAILED)
7248d9e01aSSasha Levin 		ERR_PTR(-errno);
73aba1efa5SPekka Enberg 
7496feb589SPekka Enberg 	kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem);
7596feb589SPekka Enberg 
76aba1efa5SPekka Enberg 	vesafb = (struct framebuffer) {
77aba1efa5SPekka Enberg 		.width			= VESA_WIDTH,
78aba1efa5SPekka Enberg 		.height			= VESA_HEIGHT,
79aba1efa5SPekka Enberg 		.depth			= VESA_BPP,
80aba1efa5SPekka Enberg 		.mem			= mem,
81aba1efa5SPekka Enberg 		.mem_addr		= VESA_MEM_ADDR,
827fca1897SSasha Levin 		.mem_size		= VESA_MEM_SIZE,
83aba1efa5SPekka Enberg 	};
84aba1efa5SPekka Enberg 	return fb__register(&vesafb);
85b025083dSJohn Floren }
86