1*3ac25236SPhilippe Mathieu-Daudé /* 2*3ac25236SPhilippe Mathieu-Daudé * QEMU MMIO VGA Emulator. 3*3ac25236SPhilippe Mathieu-Daudé * 4*3ac25236SPhilippe Mathieu-Daudé * Copyright (c) 2003 Fabrice Bellard 5*3ac25236SPhilippe Mathieu-Daudé * 6*3ac25236SPhilippe Mathieu-Daudé * Permission is hereby granted, free of charge, to any person obtaining a copy 7*3ac25236SPhilippe Mathieu-Daudé * of this software and associated documentation files (the "Software"), to deal 8*3ac25236SPhilippe Mathieu-Daudé * in the Software without restriction, including without limitation the rights 9*3ac25236SPhilippe Mathieu-Daudé * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10*3ac25236SPhilippe Mathieu-Daudé * copies of the Software, and to permit persons to whom the Software is 11*3ac25236SPhilippe Mathieu-Daudé * furnished to do so, subject to the following conditions: 12*3ac25236SPhilippe Mathieu-Daudé * 13*3ac25236SPhilippe Mathieu-Daudé * The above copyright notice and this permission notice shall be included in 14*3ac25236SPhilippe Mathieu-Daudé * all copies or substantial portions of the Software. 15*3ac25236SPhilippe Mathieu-Daudé * 16*3ac25236SPhilippe Mathieu-Daudé * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*3ac25236SPhilippe Mathieu-Daudé * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*3ac25236SPhilippe Mathieu-Daudé * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*3ac25236SPhilippe Mathieu-Daudé * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20*3ac25236SPhilippe Mathieu-Daudé * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21*3ac25236SPhilippe Mathieu-Daudé * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22*3ac25236SPhilippe Mathieu-Daudé * THE SOFTWARE. 23*3ac25236SPhilippe Mathieu-Daudé */ 24*3ac25236SPhilippe Mathieu-Daudé 25*3ac25236SPhilippe Mathieu-Daudé #include "qemu/osdep.h" 26*3ac25236SPhilippe Mathieu-Daudé #include "qemu/bitops.h" 27*3ac25236SPhilippe Mathieu-Daudé #include "qemu/units.h" 28*3ac25236SPhilippe Mathieu-Daudé #include "migration/vmstate.h" 29*3ac25236SPhilippe Mathieu-Daudé #include "hw/display/vga.h" 30*3ac25236SPhilippe Mathieu-Daudé #include "vga_int.h" 31*3ac25236SPhilippe Mathieu-Daudé #include "ui/pixel_ops.h" 32*3ac25236SPhilippe Mathieu-Daudé 33*3ac25236SPhilippe Mathieu-Daudé #define VGA_RAM_SIZE (8 * MiB) 34*3ac25236SPhilippe Mathieu-Daudé 35*3ac25236SPhilippe Mathieu-Daudé typedef struct VGAMmioState { 36*3ac25236SPhilippe Mathieu-Daudé VGACommonState vga; 37*3ac25236SPhilippe Mathieu-Daudé int it_shift; 38*3ac25236SPhilippe Mathieu-Daudé } VGAMmioState; 39*3ac25236SPhilippe Mathieu-Daudé 40*3ac25236SPhilippe Mathieu-Daudé /* Memory mapped interface */ 41*3ac25236SPhilippe Mathieu-Daudé static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size) 42*3ac25236SPhilippe Mathieu-Daudé { 43*3ac25236SPhilippe Mathieu-Daudé VGAMmioState *s = opaque; 44*3ac25236SPhilippe Mathieu-Daudé 45*3ac25236SPhilippe Mathieu-Daudé return vga_ioport_read(&s->vga, addr >> s->it_shift) & 46*3ac25236SPhilippe Mathieu-Daudé MAKE_64BIT_MASK(0, size * 8); 47*3ac25236SPhilippe Mathieu-Daudé } 48*3ac25236SPhilippe Mathieu-Daudé 49*3ac25236SPhilippe Mathieu-Daudé static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value, 50*3ac25236SPhilippe Mathieu-Daudé unsigned size) 51*3ac25236SPhilippe Mathieu-Daudé { 52*3ac25236SPhilippe Mathieu-Daudé VGAMmioState *s = opaque; 53*3ac25236SPhilippe Mathieu-Daudé 54*3ac25236SPhilippe Mathieu-Daudé vga_ioport_write(&s->vga, addr >> s->it_shift, 55*3ac25236SPhilippe Mathieu-Daudé value & MAKE_64BIT_MASK(0, size * 8)); 56*3ac25236SPhilippe Mathieu-Daudé } 57*3ac25236SPhilippe Mathieu-Daudé 58*3ac25236SPhilippe Mathieu-Daudé static const MemoryRegionOps vga_mm_ctrl_ops = { 59*3ac25236SPhilippe Mathieu-Daudé .read = vga_mm_read, 60*3ac25236SPhilippe Mathieu-Daudé .write = vga_mm_write, 61*3ac25236SPhilippe Mathieu-Daudé .valid.min_access_size = 1, 62*3ac25236SPhilippe Mathieu-Daudé .valid.max_access_size = 4, 63*3ac25236SPhilippe Mathieu-Daudé .impl.min_access_size = 1, 64*3ac25236SPhilippe Mathieu-Daudé .impl.max_access_size = 4, 65*3ac25236SPhilippe Mathieu-Daudé .endianness = DEVICE_NATIVE_ENDIAN, 66*3ac25236SPhilippe Mathieu-Daudé }; 67*3ac25236SPhilippe Mathieu-Daudé 68*3ac25236SPhilippe Mathieu-Daudé static void vga_mm_init(VGAMmioState *s, hwaddr vram_base, 69*3ac25236SPhilippe Mathieu-Daudé hwaddr ctrl_base, int it_shift, 70*3ac25236SPhilippe Mathieu-Daudé MemoryRegion *address_space) 71*3ac25236SPhilippe Mathieu-Daudé { 72*3ac25236SPhilippe Mathieu-Daudé MemoryRegion *s_ioport_ctrl, *vga_io_memory; 73*3ac25236SPhilippe Mathieu-Daudé 74*3ac25236SPhilippe Mathieu-Daudé s->it_shift = it_shift; 75*3ac25236SPhilippe Mathieu-Daudé s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); 76*3ac25236SPhilippe Mathieu-Daudé memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s, 77*3ac25236SPhilippe Mathieu-Daudé "vga-mm-ctrl", 0x100000); 78*3ac25236SPhilippe Mathieu-Daudé memory_region_set_flush_coalesced(s_ioport_ctrl); 79*3ac25236SPhilippe Mathieu-Daudé 80*3ac25236SPhilippe Mathieu-Daudé vga_io_memory = g_malloc(sizeof(*vga_io_memory)); 81*3ac25236SPhilippe Mathieu-Daudé /* XXX: endianness? */ 82*3ac25236SPhilippe Mathieu-Daudé memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga, 83*3ac25236SPhilippe Mathieu-Daudé "vga-mem", 0x20000); 84*3ac25236SPhilippe Mathieu-Daudé 85*3ac25236SPhilippe Mathieu-Daudé vmstate_register(NULL, 0, &vmstate_vga_common, s); 86*3ac25236SPhilippe Mathieu-Daudé 87*3ac25236SPhilippe Mathieu-Daudé memory_region_add_subregion(address_space, ctrl_base, s_ioport_ctrl); 88*3ac25236SPhilippe Mathieu-Daudé s->vga.bank_offset = 0; 89*3ac25236SPhilippe Mathieu-Daudé memory_region_add_subregion(address_space, 90*3ac25236SPhilippe Mathieu-Daudé vram_base + 0x000a0000, vga_io_memory); 91*3ac25236SPhilippe Mathieu-Daudé memory_region_set_coalescing(vga_io_memory); 92*3ac25236SPhilippe Mathieu-Daudé } 93*3ac25236SPhilippe Mathieu-Daudé 94*3ac25236SPhilippe Mathieu-Daudé int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, 95*3ac25236SPhilippe Mathieu-Daudé int it_shift, MemoryRegion *address_space) 96*3ac25236SPhilippe Mathieu-Daudé { 97*3ac25236SPhilippe Mathieu-Daudé VGAMmioState *s; 98*3ac25236SPhilippe Mathieu-Daudé 99*3ac25236SPhilippe Mathieu-Daudé s = g_malloc0(sizeof(*s)); 100*3ac25236SPhilippe Mathieu-Daudé 101*3ac25236SPhilippe Mathieu-Daudé s->vga.vram_size_mb = VGA_RAM_SIZE / MiB; 102*3ac25236SPhilippe Mathieu-Daudé s->vga.global_vmstate = true; 103*3ac25236SPhilippe Mathieu-Daudé vga_common_init(&s->vga, NULL); 104*3ac25236SPhilippe Mathieu-Daudé vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); 105*3ac25236SPhilippe Mathieu-Daudé 106*3ac25236SPhilippe Mathieu-Daudé s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); 107*3ac25236SPhilippe Mathieu-Daudé 108*3ac25236SPhilippe Mathieu-Daudé memory_region_add_subregion(address_space, 109*3ac25236SPhilippe Mathieu-Daudé VBE_DISPI_LFB_PHYSICAL_ADDRESS, 110*3ac25236SPhilippe Mathieu-Daudé &s->vga.vram); 111*3ac25236SPhilippe Mathieu-Daudé 112*3ac25236SPhilippe Mathieu-Daudé return 0; 113*3ac25236SPhilippe Mathieu-Daudé } 114