]> git.proxmox.com Git - qemu.git/blobdiff - hw/sm501.c
ui: move files to ui/ and include/ui/
[qemu.git] / hw / sm501.c
index 4b0df8fec852156adf2518fa9fcdf1a76b59c94a..714aca0492e39b2be6beb13a45704d7237ebda3f 100644 (file)
 
 #include <stdio.h>
 #include "hw.h"
-#include "pc.h"
-#include "console.h"
+#include "serial.h"
+#include "ui/console.h"
 #include "devices.h"
+#include "sysbus.h"
+#include "qdev-addr.h"
+#include "range.h"
+#include "ui/pixel_ops.h"
 
 /*
- * Status: 2008/11/02
+ * Status: 2010/05/07
  *   - Minimum implementation for Linux console : mmio regs and CRT layer.
- *   - Always updates full screen.
+ *   - 2D grapihcs acceleration partially supported : only fill rectangle.
  *
  * TODO:
  *   - Panel support
- *   - Hardware cursor support
  *   - Touch panel support
  *   - USB support
  *   - UART support
+ *   - More 2D graphics engine support
  *   - Performance tuning
  */
 
 
 /* end of register definitions */
 
+#define SM501_HWC_WIDTH                       (64)
+#define SM501_HWC_HEIGHT                      (64)
 
 /* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
 static const uint32_t sm501_mem_local_size[] = {
@@ -451,10 +457,10 @@ typedef struct SM501State {
     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;
 
@@ -506,6 +512,19 @@ 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;
+    uint32_t twoD_pitch;
+    uint32_t twoD_foreground;
+    uint32_t twoD_stretch;
+    uint32_t twoD_color_compare_mask;
+    uint32_t twoD_mask;
+    uint32_t twoD_window_width;
+    uint32_t twoD_source_base;
+    uint32_t twoD_destination_base;
+
 } SM501State;
 
 static uint32_t get_local_mem_size_index(uint32_t size)
@@ -526,7 +545,190 @@ static uint32_t get_local_mem_size_index(uint32_t size)
     return index;
 }
 
-static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
+/**
+ * Check the availability of hardware cursor.
+ * @param crt  0 for PANEL, 1 for CRT.
+ */
+static inline int is_hwc_enabled(SM501State *state, int crt)
+{
+    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
+    return addr & 0x80000000;
+}
+
+/**
+ * Get the address which holds cursor pattern data.
+ * @param crt  0 for PANEL, 1 for CRT.
+ */
+static inline uint32_t get_hwc_address(SM501State *state, int crt)
+{
+    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
+    return (addr & 0x03FFFFF0)/* >> 4*/;
+}
+
+/**
+ * Get the cursor position in y coordinate.
+ * @param crt  0 for PANEL, 1 for CRT.
+ */
+static inline uint32_t get_hwc_y(SM501State *state, int crt)
+{
+    uint32_t location = crt ? state->dc_crt_hwc_location
+                            : state->dc_panel_hwc_location;
+    return (location & 0x07FF0000) >> 16;
+}
+
+/**
+ * Get the cursor position in x coordinate.
+ * @param crt  0 for PANEL, 1 for CRT.
+ */
+static inline uint32_t get_hwc_x(SM501State *state, int crt)
+{
+    uint32_t location = crt ? state->dc_crt_hwc_location
+                            : state->dc_panel_hwc_location;
+    return location & 0x000007FF;
+}
+
+/**
+ * Get the cursor position in x coordinate.
+ * @param crt  0 for PANEL, 1 for CRT.
+ * @param index  0, 1, 2 or 3 which specifies color of corsor dot.
+ */
+static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)
+{
+    uint32_t color_reg = 0;
+    uint16_t color_565 = 0;
+
+    if (index == 0) {
+        return 0;
+    }
+
+    switch (index) {
+    case 1:
+    case 2:
+        color_reg = crt ? state->dc_crt_hwc_color_1_2
+                        : state->dc_panel_hwc_color_1_2;
+        break;
+    case 3:
+        color_reg = crt ? state->dc_crt_hwc_color_3
+                        : state->dc_panel_hwc_color_3;
+        break;
+    default:
+        printf("invalid hw cursor color.\n");
+        abort();
+    }
+
+    switch (index) {
+    case 1:
+    case 3:
+        color_565 = (uint16_t)(color_reg & 0xFFFF);
+        break;
+    case 2:
+        color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF);
+        break;
+    }
+    return color_565;
+}
+
+static int within_hwc_y_range(SM501State *state, int y, int crt)
+{
+    int hwc_y = get_hwc_y(state, crt);
+    return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
+}
+
+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;
+    int operation_height = s->twoD_dimension & 0xFFFF;
+    uint32_t color = s->twoD_foreground;
+    int format_flags = (s->twoD_stretch >> 20) & 0x3;
+    int addressing = (s->twoD_stretch >> 16) & 0xF;
+
+    /* get frame buffer info */
+    uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
+    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) {
+        printf("%s: only XY addressing is supported.\n", __func__);
+        abort();
+    }
+
+    if ((s->twoD_source_base & 0x08000000) ||
+        (s->twoD_destination_base & 0x08000000)) {
+        printf("%s: only local memory is supported.\n", __func__);
+        abort();
+    }
+
+    switch (operation) {
+    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++) {                            \
+            for (x = 0; x < operation_width; x++) {                         \
+                int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp;   \
+                *(_pixel_type*)&dst[index] = (_pixel_type)color;            \
+            }                                                               \
+        }                                                                   \
+    }
+
+        switch (format_flags) {
+        case 0:
+            FILL_RECT(1, uint8_t);
+            break;
+        case 1:
+            FILL_RECT(2, uint16_t);
+            break;
+        case 2:
+            FILL_RECT(4, uint32_t);
+            break;
+        }
+        break;
+
+    default:
+        printf("non-implemented SM501 2D operation. %d\n", operation);
+        abort();
+        break;
+    }
+}
+
+static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
+                                         unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     uint32_t ret = 0;
@@ -572,18 +774,18 @@ static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
     default:
        printf("sm501 system config : not implemented register read."
               " addr=%x\n", (int)addr);
-       assert(0);
+        abort();
     }
 
     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:
@@ -621,24 +823,22 @@ 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);
-       assert(0);
+              " addr=%x, val=%x\n", (int)addr, (uint32_t)value);
+        abort();
     }
 }
 
-static CPUReadMemoryFunc *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 *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);
@@ -646,12 +846,12 @@ static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t 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",
@@ -660,11 +860,12 @@ static void sm501_palette_write(void *opaque,
     /* 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;
@@ -736,13 +937,13 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
        ret = s->dc_crt_hwc_addr;
        break;
     case SM501_DC_CRT_HWC_LOC:
-       ret = s->dc_crt_hwc_addr;
+       ret = s->dc_crt_hwc_location;
        break;
     case SM501_DC_CRT_HWC_COLOR_1_2:
-       ret = s->dc_crt_hwc_addr;
+       ret = s->dc_crt_hwc_color_1_2;
        break;
     case SM501_DC_CRT_HWC_COLOR_3:
-       ret = s->dc_crt_hwc_addr;
+       ret = s->dc_crt_hwc_color_3;
        break;
 
     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
@@ -752,19 +953,18 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
     default:
        printf("sm501 disp ctrl : not implemented register read."
               " addr=%x\n", (int)addr);
-       assert(0);
+        abort();
     }
 
     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:
@@ -809,13 +1009,13 @@ static void sm501_disp_ctrl_write(void *opaque,
        s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
        break;
     case SM501_DC_PANEL_HWC_LOC:
-       s->dc_panel_hwc_addr = value & 0x0FFF0FFF;
+       s->dc_panel_hwc_location = value & 0x0FFF0FFF;
        break;
     case SM501_DC_PANEL_HWC_COLOR_1_2:
-       s->dc_panel_hwc_addr = value;
+       s->dc_panel_hwc_color_1_2 = value;
        break;
     case SM501_DC_PANEL_HWC_COLOR_3:
-       s->dc_panel_hwc_addr = value & 0x0000FFFF;
+       s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
        break;
 
     case SM501_DC_CRT_CONTROL:
@@ -844,13 +1044,13 @@ static void sm501_disp_ctrl_write(void *opaque,
        s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
        break;
     case SM501_DC_CRT_HWC_LOC:
-       s->dc_crt_hwc_addr = value & 0x0FFF0FFF;
+       s->dc_crt_hwc_location = value & 0x0FFF0FFF;
        break;
     case SM501_DC_CRT_HWC_COLOR_1_2:
-       s->dc_crt_hwc_addr = value;
+       s->dc_crt_hwc_color_1_2 = value;
        break;
     case SM501_DC_CRT_HWC_COLOR_3:
-       s->dc_crt_hwc_addr = value & 0x0000FFFF;
+       s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
        break;
 
     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
@@ -859,30 +1059,117 @@ 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);
-       assert(0);
+              " addr=%x, val=%x\n", (int)addr, (unsigned)value);
+        abort();
     }
 }
 
-static CPUReadMemoryFunc *sm501_disp_ctrl_readfn[] = {
-    NULL,
-    NULL,
-    &sm501_disp_ctrl_read,
+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 CPUWriteMemoryFunc *sm501_disp_ctrl_writefn[] = {
-    NULL,
-    NULL,
-    &sm501_disp_ctrl_write,
+static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
+                                     unsigned size)
+{
+    SM501State * s = (SM501State *)opaque;
+    uint32_t ret = 0;
+    SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
+
+    switch(addr) {
+    case SM501_2D_SOURCE_BASE:
+        ret = s->twoD_source_base;
+        break;
+    default:
+        printf("sm501 disp ctrl : not implemented register read."
+               " addr=%x\n", (int)addr);
+        abort();
+    }
+
+    return ret;
+}
+
+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",
+                  (unsigned)addr, (unsigned)value);
+
+    switch(addr) {
+    case SM501_2D_SOURCE:
+        s->twoD_source = value;
+        break;
+    case SM501_2D_DESTINATION:
+        s->twoD_destination = value;
+        break;
+    case SM501_2D_DIMENSION:
+        s->twoD_dimension = value;
+        break;
+    case SM501_2D_CONTROL:
+        s->twoD_control = value;
+
+        /* do 2d operation if start flag is set. */
+        if (value & 0x80000000) {
+            sm501_2d_operation(s);
+            s->twoD_control &= ~0x80000000; /* start flag down */
+        }
+
+        break;
+    case SM501_2D_PITCH:
+        s->twoD_pitch = value;
+        break;
+    case SM501_2D_FOREGROUND:
+        s->twoD_foreground = value;
+        break;
+    case SM501_2D_STRETCH:
+        s->twoD_stretch = value;
+        break;
+    case SM501_2D_COLOR_COMPARE_MASK:
+        s->twoD_color_compare_mask = value;
+        break;
+    case SM501_2D_MASK:
+        s->twoD_mask = value;
+        break;
+    case SM501_2D_WINDOW_WIDTH:
+        s->twoD_window_width = value;
+        break;
+    case SM501_2D_SOURCE_BASE:
+        s->twoD_source_base = value;
+        break;
+    case SM501_2D_DESTINATION_BASE:
+        s->twoD_destination_base = value;
+        break;
+    default:
+        printf("sm501 2d engine : not implemented register write."
+               " addr=%x, val=%x\n", (int)addr, (unsigned)value);
+        abort();
+    }
+}
+
+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 */
 
-#include "pixel_ops.h"
-
 typedef void draw_line_func(uint8_t *d, const uint8_t *s,
                            int width, const uint32_t *pal);
 
+typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
+                                int c_y, uint8_t *d, int width);
+
 #define DEPTH 8
 #include "sm501_template.h"
 
@@ -937,6 +1224,16 @@ static draw_line_func * draw_line32_funcs[] = {
     draw_line32_16bgr,
 };
 
+static draw_hwc_line_func * draw_hwc_line_funcs[] = {
+    draw_hwc_line_8,
+    draw_hwc_line_15,
+    draw_hwc_line_16,
+    draw_hwc_line_32,
+    draw_hwc_line_32bgr,
+    draw_hwc_line_15bgr,
+    draw_hwc_line_16bgr,
+};
+
 static inline int get_depth_index(DisplayState *s)
 {
     switch(ds_get_bits_per_pixel(s)) {
@@ -966,13 +1263,15 @@ static void sm501_draw_crt(SM501State * s)
     int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
     uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
                                                    - SM501_DC_PANEL_PALETTE];
+    uint8_t hwc_palette[3 * 3];
     int ds_depth_index = get_depth_index(s->ds);
     draw_line_func * draw_line = NULL;
+    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) {
@@ -991,10 +1290,26 @@ static void sm501_draw_crt(SM501State * s)
     default:
        printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n",
               s->dc_crt_control);
-       assert(0);
+        abort();
        break;
     }
 
+    /* set up to draw hardware cursor */
+    if (is_hwc_enabled(s, 1)) {
+        int i;
+
+        /* get cursor palette */
+        for (i = 0; i < 3; i++) {
+            uint16_t rgb565 = get_hwc_color(s, 1, i + 1);
+            hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */
+            hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */
+            hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */
+        }
+
+        /* choose cursor draw line function */
+        draw_hwc_line = draw_hwc_line_funcs[ds_depth_index];
+    }
+
     /* adjust console size */
     if (s->last_width != width || s->last_height != height) {
        qemu_console_resize(s->ds, width, height);
@@ -1005,19 +1320,27 @@ static void sm501_draw_crt(SM501State * s)
 
     /* draw each line according to conditions */
     for (y = 0; y < height; y++) {
-       int update = full_update;
-       ram_addr_t page0 = offset & TARGET_PAGE_MASK;
-       ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
-       ram_addr_t page;
+       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;
+        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) {
-           draw_line(&(ds_get_data(s->ds)[y * width * dst_bpp]), src, width, palette);
+            uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
+
+            /* draw graphics layer */
+            draw_line(d, src, width, palette);
+
+            /* draw haredware cursor */
+            if (update_hwc) {
+                draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width);
+            }
+
            if (y_start < 0)
                y_start = y;
            if (page0 < page_min)
@@ -1027,7 +1350,7 @@ static void sm501_draw_crt(SM501State * s)
        } 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;
            }
        }
@@ -1038,12 +1361,14 @@ static void sm501_draw_crt(SM501State * s)
 
     /* 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)
@@ -1054,15 +1379,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;
-    int sm501_system_config_index;
-    int sm501_disp_ctrl_index;
+    DeviceState *dev;
+    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);
@@ -1074,30 +1401,44 @@ 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(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(0, 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(0, sm501_disp_ctrl_readfn,
-                                                  sm501_disp_ctrl_writefn, s);
-    cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
-                                 0x1000, sm501_disp_ctrl_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 */
-    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base,
-                        2, -1, irq);
+    dev = qdev_create(NULL, "sysbus-ohci");
+    qdev_prop_set_uint32(dev, "num-ports", 2);
+    qdev_prop_set_taddr(dev, "dma-offset", base);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+                    base + MMIO_BASE_OFFSET + SM501_USB_HOST);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
 
     /* bridge to serial emulation module */
-    if (chr)
-       serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
-                      0, /* TODO : chain irq to IRL */
-                      115200, chr, 1);
+    if (chr) {
+        serial_mm_init(address_space_mem,
+                       base + MMIO_BASE_OFFSET + SM501_UART0, 2,
+                       NULL, /* TODO : chain irq to IRL */
+                       115200, chr, DEVICE_NATIVE_ENDIAN);
+    }
 
     /* create qemu graphic console */
     s->ds = graphic_console_init(sm501_update_display, NULL,