X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fsm501.c;h=786e07629c9c3e5eb12e50fdd84da812f731545d;hb=d4a5b622b5522274597b4073ca236ae93b3816cf;hp=705e0a5c76ae769facd3b85f69904038f15de7a9;hpb=a287916c712b0c57a97cd35c663c5e7ba061bc7e;p=qemu.git diff --git a/hw/sm501.c b/hw/sm501.c index 705e0a5c7..786e07629 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -459,7 +459,7 @@ typedef struct SM501State { target_phys_addr_t base; uint32_t local_mem_size_index; uint8_t * local_mem; - ram_addr_t local_mem_offset; + MemoryRegion local_mem_region; uint32_t last_width; uint32_t last_height; @@ -511,6 +511,7 @@ typedef struct SM501State { uint32_t dc_crt_hwc_color_1_2; uint32_t dc_crt_hwc_color_3; + uint32_t twoD_source; uint32_t twoD_destination; uint32_t twoD_dimension; uint32_t twoD_control; @@ -592,7 +593,7 @@ static inline uint32_t get_hwc_x(SM501State *state, int crt) */ static inline uint16_t get_hwc_color(SM501State *state, int crt, int index) { - uint16_t color_reg = 0; + uint32_t color_reg = 0; uint16_t color_565 = 0; if (index == 0) { @@ -636,6 +637,9 @@ static void sm501_2d_operation(SM501State * s) { /* obtain operation parameters */ int operation = (s->twoD_control >> 16) & 0x1f; + int rtl = s->twoD_control & 0x8000000; + int src_x = (s->twoD_source >> 16) & 0x01FFF; + int src_y = s->twoD_source & 0xFFFF; int dst_x = (s->twoD_destination >> 16) & 0x01FFF; int dst_y = s->twoD_destination & 0xFFFF; int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; @@ -645,10 +649,9 @@ static void sm501_2d_operation(SM501State * s) int addressing = (s->twoD_stretch >> 16) & 0xF; /* get frame buffer info */ -#if 0 /* for future use */ uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF); -#endif uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF); + int src_width = (s->dc_crt_h_total & 0x00000FFF) + 1; int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1; if (addressing != 0x0) { @@ -663,8 +666,36 @@ static void sm501_2d_operation(SM501State * s) } switch (operation) { - case 0x01: /* fill rectangle */ + case 0x00: /* copy area */ +#define COPY_AREA(_bpp, _pixel_type, rtl) { \ + int y, x, index_d, index_s; \ + for (y = 0; y < operation_height; y++) { \ + for (x = 0; x < operation_width; x++) { \ + if (rtl) { \ + index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ + index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ + } else { \ + index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \ + index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ + } \ + *(_pixel_type*)&dst[index_d] = *(_pixel_type*)&src[index_s];\ + } \ + } \ + } + switch (format_flags) { + case 0: + COPY_AREA(1, uint8_t, rtl); + break; + case 1: + COPY_AREA(2, uint16_t, rtl); + break; + case 2: + COPY_AREA(4, uint32_t, rtl); + break; + } + break; + case 0x01: /* fill rectangle */ #define FILL_RECT(_bpp, _pixel_type) { \ int y, x; \ for (y = 0; y < operation_height; y++) { \ @@ -695,7 +726,8 @@ static void sm501_2d_operation(SM501State * s) } } -static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr) +static uint64_t sm501_system_config_read(void *opaque, target_phys_addr_t addr, + unsigned size) { SM501State * s = (SM501State *)opaque; uint32_t ret = 0; @@ -747,12 +779,12 @@ static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr) return ret; } -static void sm501_system_config_write(void *opaque, - target_phys_addr_t addr, uint32_t value) +static void sm501_system_config_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n", - addr, value); + (uint32_t)addr, (uint32_t)value); switch(addr) { case SM501_SYSTEM_CONTROL: @@ -790,21 +822,19 @@ static void sm501_system_config_write(void *opaque, default: printf("sm501 system config : not implemented register write." - " addr=%x, val=%x\n", (int)addr, value); + " addr=%x, val=%x\n", (int)addr, (uint32_t)value); abort(); } } -static CPUReadMemoryFunc * const sm501_system_config_readfn[] = { - NULL, - NULL, - &sm501_system_config_read, -}; - -static CPUWriteMemoryFunc * const sm501_system_config_writefn[] = { - NULL, - NULL, - &sm501_system_config_write, +static const MemoryRegionOps sm501_system_config_ops = { + .read = sm501_system_config_read, + .write = sm501_system_config_write, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr) @@ -833,7 +863,8 @@ static void sm501_palette_write(void *opaque, *(uint32_t*)&s->dc_palette[addr] = value; } -static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr) +static uint64_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr, + unsigned size) { SM501State * s = (SM501State *)opaque; uint32_t ret = 0; @@ -927,13 +958,12 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr) return ret; } -static void sm501_disp_ctrl_write(void *opaque, - target_phys_addr_t addr, - uint32_t value) +static void sm501_disp_ctrl_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n", - addr, value); + (unsigned)addr, (unsigned)value); switch(addr) { case SM501_DC_PANEL_CONTROL: @@ -1028,24 +1058,23 @@ static void sm501_disp_ctrl_write(void *opaque, default: printf("sm501 disp ctrl : not implemented register write." - " addr=%x, val=%x\n", (int)addr, value); + " addr=%x, val=%x\n", (int)addr, (unsigned)value); abort(); } } -static CPUReadMemoryFunc * const sm501_disp_ctrl_readfn[] = { - NULL, - NULL, - &sm501_disp_ctrl_read, -}; - -static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = { - NULL, - NULL, - &sm501_disp_ctrl_write, +static const MemoryRegionOps sm501_disp_ctrl_ops = { + .read = sm501_disp_ctrl_read, + .write = sm501_disp_ctrl_write, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr) +static uint64_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr, + unsigned size) { SM501State * s = (SM501State *)opaque; uint32_t ret = 0; @@ -1064,14 +1093,17 @@ static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr) return ret; } -static void sm501_2d_engine_write(void *opaque, - target_phys_addr_t addr, uint32_t value) +static void sm501_2d_engine_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) { SM501State * s = (SM501State *)opaque; SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n", - addr, value); + (unsigned)addr, (unsigned)value); switch(addr) { + case SM501_2D_SOURCE: + s->twoD_source = value; + break; case SM501_2D_DESTINATION: s->twoD_destination = value; break; @@ -1114,21 +1146,19 @@ static void sm501_2d_engine_write(void *opaque, break; default: printf("sm501 2d engine : not implemented register write." - " addr=%x, val=%x\n", (int)addr, value); + " addr=%x, val=%x\n", (int)addr, (unsigned)value); abort(); } } -static CPUReadMemoryFunc * const sm501_2d_engine_readfn[] = { - NULL, - NULL, - &sm501_2d_engine_read, -}; - -static CPUWriteMemoryFunc * const sm501_2d_engine_writefn[] = { - NULL, - NULL, - &sm501_2d_engine_write, +static const MemoryRegionOps sm501_2d_engine_ops = { + .read = sm501_2d_engine_read, + .write = sm501_2d_engine_write, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; /* draw line functions for all console modes */ @@ -1240,9 +1270,9 @@ static void sm501_draw_crt(SM501State * s) draw_hwc_line_func * draw_hwc_line = NULL; int full_update = 0; int y_start = -1; - int page_min = 0x7fffffff; - int page_max = -1; - ram_addr_t offset = s->local_mem_offset; + ram_addr_t page_min = ~0l; + ram_addr_t page_max = 0l; + ram_addr_t offset = 0; /* choose draw_line function */ switch (s->dc_crt_control & 3) { @@ -1293,14 +1323,12 @@ static void sm501_draw_crt(SM501State * s) for (y = 0; y < height; y++) { int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0; int update = full_update || update_hwc; - ram_addr_t page0 = offset & TARGET_PAGE_MASK; - ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK; - ram_addr_t page; + ram_addr_t page0 = offset; + ram_addr_t page1 = offset + width * src_bpp - 1; /* check dirty flags for each line */ - for (page = page0; page <= page1; page += TARGET_PAGE_SIZE) - if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) - update = 1; + update = memory_region_get_dirty(&s->local_mem_region, page0, + page1 - page0, DIRTY_MEMORY_VGA); /* draw line and change status */ if (update) { @@ -1337,9 +1365,11 @@ static void sm501_draw_crt(SM501State * s) dpy_update(s->ds, 0, y_start, width, y - y_start); /* clear dirty flags */ - if (page_max != -1) - cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE, - VGA_DIRTY_FLAG); + if (page_min != ~0l) { + memory_region_reset_dirty(&s->local_mem_region, + page_min, page_max + TARGET_PAGE_SIZE, + DIRTY_MEMORY_VGA); + } } static void sm501_update_display(void *opaque) @@ -1350,17 +1380,17 @@ static void sm501_update_display(void *opaque) sm501_draw_crt(s); } -void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq, - CharDriverState *chr) +void sm501_init(MemoryRegion *address_space_mem, uint32_t base, + uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr) { SM501State * s; DeviceState *dev; - int sm501_system_config_index; - int sm501_disp_ctrl_index; - int sm501_2d_engine_index; + MemoryRegion *sm501_system_config = g_new(MemoryRegion, 1); + MemoryRegion *sm501_disp_ctrl = g_new(MemoryRegion, 1); + MemoryRegion *sm501_2d_engine = g_new(MemoryRegion, 1); /* allocate management data region */ - s = (SM501State *)qemu_mallocz(sizeof(SM501State)); + s = (SM501State *)g_malloc0(sizeof(SM501State)); s->base = base; s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes); @@ -1372,24 +1402,27 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq, s->dc_crt_control = 0x00010000; /* allocate local memory */ - s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes); - s->local_mem = qemu_get_ram_ptr(s->local_mem_offset); - cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset); + memory_region_init_ram(&s->local_mem_region, "sm501.local", + local_mem_bytes); + vmstate_register_ram_global(&s->local_mem_region); + s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); + memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); /* map mmio */ - sm501_system_config_index - = cpu_register_io_memory(sm501_system_config_readfn, - sm501_system_config_writefn, s); - cpu_register_physical_memory(base + MMIO_BASE_OFFSET, - 0x6c, sm501_system_config_index); - sm501_disp_ctrl_index = cpu_register_io_memory(sm501_disp_ctrl_readfn, - sm501_disp_ctrl_writefn, s); - cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC, - 0x1000, sm501_disp_ctrl_index); - sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn, - sm501_2d_engine_writefn, s); - cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE, - 0x54, sm501_2d_engine_index); + memory_region_init_io(sm501_system_config, &sm501_system_config_ops, s, + "sm501-system-config", 0x6c); + memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET, + sm501_system_config); + memory_region_init_io(sm501_disp_ctrl, &sm501_disp_ctrl_ops, s, + "sm501-disp-ctrl", 0x1000); + memory_region_add_subregion(address_space_mem, + base + MMIO_BASE_OFFSET + SM501_DC, + sm501_disp_ctrl); + memory_region_init_io(sm501_2d_engine, &sm501_2d_engine_ops, s, + "sm501-2d-engine", 0x54); + memory_region_add_subregion(address_space_mem, + base + MMIO_BASE_OFFSET + SM501_2D_ENGINE, + sm501_2d_engine); /* bridge to usb host emulation module */ dev = qdev_create(NULL, "sysbus-ohci"); @@ -1402,15 +1435,10 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq, /* bridge to serial emulation module */ if (chr) { -#ifdef TARGET_WORDS_BIGENDIAN - serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2, + serial_mm_init(address_space_mem, + base + MMIO_BASE_OFFSET + SM501_UART0, 2, NULL, /* TODO : chain irq to IRL */ - 115200, chr, 1, 1); -#else - serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2, - NULL, /* TODO : chain irq to IRL */ - 115200, chr, 1, 0); -#endif + 115200, chr, DEVICE_NATIVE_ENDIAN); } /* create qemu graphic console */