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