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" 11*aa73be70SMatt Evans #include <linux/byteorder.h> 1296feb589SPekka Enberg #include <sys/mman.h> 13b025083dSJohn Floren 14b025083dSJohn Floren #include <sys/types.h> 15b025083dSJohn Floren #include <sys/ioctl.h> 16b025083dSJohn Floren #include <inttypes.h> 17b025083dSJohn Floren #include <unistd.h> 18b025083dSJohn Floren 19c9f6a037SXiao Guangrong static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 20b025083dSJohn Floren { 21b025083dSJohn Floren return true; 22b025083dSJohn Floren } 23b025083dSJohn Floren 24c9f6a037SXiao Guangrong static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 25b025083dSJohn Floren { 26b025083dSJohn Floren return true; 27b025083dSJohn Floren } 28b025083dSJohn Floren 29b025083dSJohn Floren static struct ioport_operations vesa_io_ops = { 30b025083dSJohn Floren .io_in = vesa_pci_io_in, 31b025083dSJohn Floren .io_out = vesa_pci_io_out, 32b025083dSJohn Floren }; 33b025083dSJohn Floren 34b025083dSJohn Floren static struct pci_device_header vesa_pci_device = { 35*aa73be70SMatt Evans .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), 36*aa73be70SMatt Evans .device_id = cpu_to_le16(PCI_DEVICE_ID_VESA), 37b025083dSJohn Floren .header_type = PCI_HEADER_TYPE_NORMAL, 38b025083dSJohn Floren .revision_id = 0, 39*aa73be70SMatt Evans .class[2] = 0x03, 40*aa73be70SMatt Evans .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET), 41*aa73be70SMatt Evans .subsys_id = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA), 42*aa73be70SMatt Evans .bar[1] = cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY), 434f045c57SSasha Levin .bar_size[1] = VESA_MEM_SIZE, 44b025083dSJohn Floren }; 45b025083dSJohn Floren 46aba1efa5SPekka Enberg static struct framebuffer vesafb; 47aba1efa5SPekka Enberg 48aba1efa5SPekka Enberg struct framebuffer *vesa__init(struct kvm *kvm) 49b025083dSJohn Floren { 50947392bcSSasha Levin u16 vesa_base_addr; 51aba1efa5SPekka Enberg u8 dev, line, pin; 52aba1efa5SPekka Enberg char *mem; 53b025083dSJohn Floren 54b025083dSJohn Floren if (irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line) < 0) 55aba1efa5SPekka Enberg return NULL; 56b025083dSJohn Floren 57b025083dSJohn Floren vesa_pci_device.irq_pin = pin; 58b025083dSJohn Floren vesa_pci_device.irq_line = line; 59947392bcSSasha Levin vesa_base_addr = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL); 60*aa73be70SMatt Evans vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO); 61b025083dSJohn Floren pci__register(&vesa_pci_device, dev); 62de960f08SPekka Enberg 6396feb589SPekka Enberg mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0); 6496feb589SPekka Enberg if (mem == MAP_FAILED) 65b025083dSJohn Floren return NULL; 66aba1efa5SPekka Enberg 6796feb589SPekka Enberg kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem); 6896feb589SPekka Enberg 69aba1efa5SPekka Enberg vesafb = (struct framebuffer) { 70aba1efa5SPekka Enberg .width = VESA_WIDTH, 71aba1efa5SPekka Enberg .height = VESA_HEIGHT, 72aba1efa5SPekka Enberg .depth = VESA_BPP, 73aba1efa5SPekka Enberg .mem = mem, 74aba1efa5SPekka Enberg .mem_addr = VESA_MEM_ADDR, 757fca1897SSasha Levin .mem_size = VESA_MEM_SIZE, 76aba1efa5SPekka Enberg }; 77aba1efa5SPekka Enberg return fb__register(&vesafb); 78b025083dSJohn Floren } 79