#include <stdio.h>
#include "hw.h"
-#include "pc.h"
+#include "serial.h"
#include "console.h"
#include "devices.h"
#include "sysbus.h"
#include "qdev-addr.h"
+#include "range.h"
/*
* Status: 2010/05/07
DisplayState *ds;
/* status & internal resources */
- target_phys_addr_t base;
+ hwaddr 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;
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;
*/
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) {
{
/* 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;
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) {
}
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++) { \
}
}
-static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
+static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
+ unsigned size)
{
SM501State * s = (SM501State *)opaque;
uint32_t ret = 0;
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, hwaddr 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:
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 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 CPUWriteMemoryFunc * const sm501_system_config_writefn[] = {
- NULL,
- NULL,
- &sm501_system_config_write,
-};
-
-static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
+static uint32_t sm501_palette_read(void *opaque, hwaddr addr)
{
SM501State * s = (SM501State *)opaque;
SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
/* TODO : consider BYTE/WORD access */
/* TODO : consider endian */
- assert(0 <= addr && addr < 0x400 * 3);
+ assert(range_covers_byte(0, 0x400 * 3, addr));
return *(uint32_t*)&s->dc_palette[addr];
}
static void sm501_palette_write(void *opaque,
- target_phys_addr_t addr, uint32_t value)
+ hwaddr addr, uint32_t value)
{
SM501State * s = (SM501State *)opaque;
SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
/* TODO : consider BYTE/WORD access */
/* TODO : consider endian */
- assert(0 <= addr && addr < 0x400 * 3);
+ assert(range_covers_byte(0, 0x400 * 3, addr));
*(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, hwaddr addr,
+ unsigned size)
{
SM501State * s = (SM501State *)opaque;
uint32_t ret = 0;
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, hwaddr 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:
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, hwaddr addr,
+ unsigned size)
{
SM501State * s = (SM501State *)opaque;
uint32_t ret = 0;
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, hwaddr 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;
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 */
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) {
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) {
} else {
if (y_start >= 0) {
/* flush to display */
- dpy_update(s->ds, 0, y_start, width, y - y_start);
+ dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
y_start = -1;
}
}
/* complete flush to display */
if (y_start >= 0)
- dpy_update(s->ds, 0, y_start, width, y - y_start);
+ dpy_gfx_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)
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);
s->dc_crt_control = 0x00010000;
/* allocate local memory */
- s->local_mem_offset = qemu_ram_alloc(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");
/* 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 */