]> Git Repo - qemu.git/blobdiff - hw/sm501.c
Replace assert(0) with abort() or cpu_abort()
[qemu.git] / hw / sm501.c
index ca9528b60e75b34de8e07604fd075dd31e97b9f3..80185864c48ea3c0bbac95660c697baabb83432d 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <stdio.h>
-#include <assert.h>
 #include "hw.h"
 #include "pc.h"
 #include "console.h"
@@ -47,9 +46,9 @@
 //#define DEBUG_BITBLT
 
 #ifdef DEBUG_SM501
-#define SM501_DPRINTF(fmt...) printf(fmt)
+#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
 #else
-#define SM501_DPRINTF(fmt...) do {} while(0)
+#define SM501_DPRINTF(fmt...) do {} while(0)
 #endif
 
 
 
 /* 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[] = {
@@ -455,6 +456,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;
     uint32_t last_width;
     uint32_t last_height;
 
@@ -526,6 +528,95 @@ static uint32_t get_local_mem_size_index(uint32_t size)
     return index;
 }
 
+/**
+ * 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)
+{
+    uint16_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 uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
 {
     SM501State * s = (SM501State *)opaque;
@@ -572,7 +663,7 @@ 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;
@@ -622,17 +713,17 @@ 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);
+        abort();
     }
 }
 
-static CPUReadMemoryFunc *sm501_system_config_readfn[] = {
+static CPUReadMemoryFunc * const sm501_system_config_readfn[] = {
     NULL,
     NULL,
     &sm501_system_config_read,
 };
 
-static CPUWriteMemoryFunc *sm501_system_config_writefn[] = {
+static CPUWriteMemoryFunc * const sm501_system_config_writefn[] = {
     NULL,
     NULL,
     &sm501_system_config_write,
@@ -736,13 +827,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,7 +843,7 @@ 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;
@@ -809,13 +900,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 +935,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:
@@ -860,17 +951,17 @@ 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);
+        abort();
     }
 }
 
-static CPUReadMemoryFunc *sm501_disp_ctrl_readfn[] = {
+static CPUReadMemoryFunc * const sm501_disp_ctrl_readfn[] = {
     NULL,
     NULL,
     &sm501_disp_ctrl_read,
 };
 
-static CPUWriteMemoryFunc *sm501_disp_ctrl_writefn[] = {
+static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
     NULL,
     NULL,
     &sm501_disp_ctrl_write,
@@ -883,6 +974,9 @@ static CPUWriteMemoryFunc *sm501_disp_ctrl_writefn[] = {
 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 +1031,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)) {
@@ -948,7 +1052,10 @@ static inline int get_depth_index(DisplayState *s)
     case 16:
         return 2;
     case 32:
-        return 3;
+       if (is_surface_bgr(s->surface))
+           return 4;
+       else
+           return 3;
     }
 }
 
@@ -963,12 +1070,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;
 
     /* choose draw_line function */
     switch (s->dc_crt_control & 3) {
@@ -987,10 +1097,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);
@@ -1001,11 +1127,11 @@ static void sm501_draw_crt(SM501State * s)
 
     /* draw each line according to conditions */
     for (y = 0; y < height; y++) {
-       int update = full_update;
-       uint8_t * line_end = &src[width * src_bpp - 1];
-       int page0 = (src - phys_ram_base) & TARGET_PAGE_MASK;
-       int page1 = (line_end - phys_ram_base) & TARGET_PAGE_MASK;
-       int 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 & TARGET_PAGE_MASK;
+       ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
+       ram_addr_t page;
 
        /* check dirty flags for each line */
        for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
@@ -1014,7 +1140,16 @@ static void sm501_draw_crt(SM501State * s)
 
        /* 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)
@@ -1030,6 +1165,7 @@ static void sm501_draw_crt(SM501State * s)
        }
 
        src += width * src_bpp;
+       offset += width * src_bpp;
     }
 
     /* complete flush to display */
@@ -1050,8 +1186,8 @@ static void sm501_update_display(void *opaque)
        sm501_draw_crt(s);
 }
 
-void sm501_init(uint32_t base, unsigned long local_mem_base,
-               uint32_t local_mem_bytes, CharDriverState *chr)
+void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
+                CharDriverState *chr)
 {
     SM501State * s;
     int sm501_system_config_index;
@@ -1070,24 +1206,29 @@ void sm501_init(uint32_t base, unsigned long local_mem_base,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    s->local_mem = (uint8 *)phys_ram_base + local_mem_base;
-    cpu_register_physical_memory(base, local_mem_bytes, local_mem_base);
+    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);
 
     /* map mmio */
     sm501_system_config_index
-       = cpu_register_io_memory(0, sm501_system_config_readfn,
+       = 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(0, sm501_disp_ctrl_readfn,
+    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);
 
+    /* bridge to usb host emulation module */
+    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base,
+                        2, -1, irq);
+
     /* bridge to serial emulation module */
     if (chr)
        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
-                      0, /* TODO : chain irq to IRL */
+                      NULL, /* TODO : chain irq to IRL */
                       115200, chr, 1);
 
     /* create qemu graphic console */
This page took 0.037804 seconds and 4 git commands to generate.