Commit 0add30cff44d681d0490b167e666c39d4d7b1e8d
1 parent
f0f2f976
G364 video adapter enhancement
This patch improves G364 video card emulation (used in MIPS Magnum machine): - Use memory dirty tracking to not refresh whole screen each time - Use macros for debugging messages - Add support for hardware cursor - Handle Y-panning - Raise irq at each screen redraw - Support retrieving of some registers - Add load/save support The emulation has been tested in Linux 2.1 and Windows NT 3.5, in 640x480, 800x600, 1024x768 and 1280x1024 resolutions. Signed-off-by: Hervé Poussineau <hpoussin@reactos.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6356 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
445 additions
and
249 deletions
hw/g364fb.c
| 1 | /* | 1 | /* |
| 2 | * QEMU G364 framebuffer Emulator. | 2 | * QEMU G364 framebuffer Emulator. |
| 3 | * | 3 | * |
| 4 | - * Copyright (c) 2007-2008 Hervé Poussineau | 4 | + * Copyright (c) 2007-2009 Herve Poussineau |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
| @@ -25,140 +25,275 @@ | @@ -25,140 +25,275 @@ | ||
| 25 | 25 | ||
| 26 | //#define DEBUG_G364 | 26 | //#define DEBUG_G364 |
| 27 | 27 | ||
| 28 | +#ifdef DEBUG_G364 | ||
| 29 | +#define DPRINTF(fmt, args...) \ | ||
| 30 | +do { printf("g364: " fmt , ##args); } while (0) | ||
| 31 | +#else | ||
| 32 | +#define DPRINTF(fmt, args...) do {} while (0) | ||
| 33 | +#endif | ||
| 34 | +#define BADF(fmt, args...) \ | ||
| 35 | +do { fprintf(stderr, "g364 ERROR: " fmt , ##args);} while (0) | ||
| 36 | + | ||
| 28 | typedef struct G364State { | 37 | typedef struct G364State { |
| 29 | - unsigned int vram_size; | ||
| 30 | - uint8_t *vram_buffer; | 38 | + /* hardware */ |
| 39 | + uint8_t *vram; | ||
| 40 | + ram_addr_t vram_offset; | ||
| 41 | + int vram_size; | ||
| 42 | + qemu_irq irq; | ||
| 43 | + /* registers */ | ||
| 44 | + uint8_t color_palette[256][3]; | ||
| 45 | + uint8_t cursor_palette[3][3]; | ||
| 46 | + uint16_t cursor[512]; | ||
| 47 | + uint32_t cursor_position; | ||
| 31 | uint32_t ctla; | 48 | uint32_t ctla; |
| 32 | - uint8_t palette[256][3]; | 49 | + uint32_t top_of_screen; |
| 50 | + uint32_t width, height; /* in pixels */ | ||
| 33 | /* display refresh support */ | 51 | /* display refresh support */ |
| 34 | DisplayState *ds; | 52 | DisplayState *ds; |
| 35 | - int graphic_mode; | ||
| 36 | - uint32_t scr_width, scr_height; /* in pixels */ | 53 | + int depth; |
| 54 | + int blanked; | ||
| 37 | } G364State; | 55 | } G364State; |
| 38 | 56 | ||
| 39 | -/* | ||
| 40 | - * graphic modes | ||
| 41 | - */ | ||
| 42 | -#define BPP 8 | ||
| 43 | -#define PIXEL_WIDTH 8 | ||
| 44 | -#include "g364fb_template.h" | ||
| 45 | -#undef BPP | ||
| 46 | -#undef PIXEL_WIDTH | ||
| 47 | - | ||
| 48 | -#define BPP 15 | ||
| 49 | -#define PIXEL_WIDTH 16 | ||
| 50 | -#include "g364fb_template.h" | ||
| 51 | -#undef BPP | ||
| 52 | -#undef PIXEL_WIDTH | ||
| 53 | - | ||
| 54 | -#define BPP 16 | ||
| 55 | -#define PIXEL_WIDTH 16 | ||
| 56 | -#include "g364fb_template.h" | ||
| 57 | -#undef BPP | ||
| 58 | -#undef PIXEL_WIDTH | ||
| 59 | - | ||
| 60 | -#define BPP 32 | ||
| 61 | -#define PIXEL_WIDTH 32 | ||
| 62 | -#include "g364fb_template.h" | ||
| 63 | -#undef BPP | ||
| 64 | -#undef PIXEL_WIDTH | ||
| 65 | - | ||
| 66 | -#define REG_DISPLAYX 0x0918 | ||
| 67 | -#define REG_DISPLAYY 0x0940 | ||
| 68 | - | ||
| 69 | -#define CTLA_FORCE_BLANK 0x400 | ||
| 70 | - | ||
| 71 | -static void g364fb_draw_graphic(G364State *s, int full_update) | 57 | +#define REG_ID 0x000000 |
| 58 | +#define REG_BOOT 0x080000 | ||
| 59 | +#define REG_DISPLAY 0x080118 | ||
| 60 | +#define REG_VDISPLAY 0x080150 | ||
| 61 | +#define REG_CTLA 0x080300 | ||
| 62 | +#define REG_TOP 0x080400 | ||
| 63 | +#define REG_CURS_PAL 0x080508 | ||
| 64 | +#define REG_CURS_POS 0x080638 | ||
| 65 | +#define REG_CLR_PAL 0x080800 | ||
| 66 | +#define REG_CURS_PAT 0x081000 | ||
| 67 | +#define REG_RESET 0x180000 | ||
| 68 | + | ||
| 69 | +#define CTLA_FORCE_BLANK 0x00000400 | ||
| 70 | +#define CTLA_NO_CURSOR 0x00800000 | ||
| 71 | + | ||
| 72 | +static inline int check_dirty(ram_addr_t page) | ||
| 73 | +{ | ||
| 74 | + return cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG); | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +static inline void reset_dirty(G364State *s, | ||
| 78 | + ram_addr_t page_min, ram_addr_t page_max) | ||
| 79 | +{ | ||
| 80 | + cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE - 1, | ||
| 81 | + VGA_DIRTY_FLAG); | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +static void g364fb_draw_graphic8(G364State *s) | ||
| 72 | { | 85 | { |
| 86 | + int i, w; | ||
| 87 | + uint8_t *vram; | ||
| 88 | + uint8_t *data_display, *dd; | ||
| 89 | + ram_addr_t page, page_min, page_max; | ||
| 90 | + int x, y; | ||
| 91 | + int xmin, xmax; | ||
| 92 | + int ymin, ymax; | ||
| 93 | + int xcursor, ycursor; | ||
| 94 | + unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b); | ||
| 95 | + | ||
| 73 | switch (ds_get_bits_per_pixel(s->ds)) { | 96 | switch (ds_get_bits_per_pixel(s->ds)) { |
| 74 | case 8: | 97 | case 8: |
| 75 | - g364fb_draw_graphic8(s, full_update); | 98 | + rgb_to_pixel = rgb_to_pixel8; |
| 99 | + w = 1; | ||
| 76 | break; | 100 | break; |
| 77 | case 15: | 101 | case 15: |
| 78 | - g364fb_draw_graphic15(s, full_update); | 102 | + rgb_to_pixel = rgb_to_pixel15; |
| 103 | + w = 2; | ||
| 79 | break; | 104 | break; |
| 80 | case 16: | 105 | case 16: |
| 81 | - g364fb_draw_graphic16(s, full_update); | 106 | + rgb_to_pixel = rgb_to_pixel16; |
| 107 | + w = 2; | ||
| 82 | break; | 108 | break; |
| 83 | case 32: | 109 | case 32: |
| 84 | - g364fb_draw_graphic32(s, full_update); | 110 | + rgb_to_pixel = rgb_to_pixel32; |
| 111 | + w = 4; | ||
| 85 | break; | 112 | break; |
| 86 | default: | 113 | default: |
| 87 | - printf("g364fb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds)); | 114 | + BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds)); |
| 88 | return; | 115 | return; |
| 89 | } | 116 | } |
| 90 | 117 | ||
| 91 | - dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); | 118 | + page = s->vram_offset; |
| 119 | + page_min = (ram_addr_t)-1; | ||
| 120 | + page_max = 0; | ||
| 121 | + | ||
| 122 | + x = y = 0; | ||
| 123 | + xmin = s->width; | ||
| 124 | + xmax = 0; | ||
| 125 | + ymin = s->height; | ||
| 126 | + ymax = 0; | ||
| 127 | + | ||
| 128 | + if (!(s->ctla & CTLA_NO_CURSOR)) { | ||
| 129 | + xcursor = s->cursor_position >> 12; | ||
| 130 | + ycursor = s->cursor_position & 0xfff; | ||
| 131 | + } else { | ||
| 132 | + xcursor = ycursor = -65; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + vram = s->vram + s->top_of_screen; | ||
| 136 | + /* XXX: out of range in vram? */ | ||
| 137 | + data_display = dd = ds_get_data(s->ds); | ||
| 138 | + while (y < s->height) { | ||
| 139 | + if (check_dirty(page)) { | ||
| 140 | + if (y < ymin) | ||
| 141 | + ymin = ymax = y; | ||
| 142 | + if (page_min == (ram_addr_t)-1) | ||
| 143 | + page_min = page; | ||
| 144 | + page_max = page; | ||
| 145 | + if (x < xmin) | ||
| 146 | + xmin = x; | ||
| 147 | + for (i = 0; i < TARGET_PAGE_SIZE; i++) { | ||
| 148 | + uint8_t index; | ||
| 149 | + unsigned int color; | ||
| 150 | + if (unlikely((y >= ycursor && y < ycursor + 64) && | ||
| 151 | + (x >= xcursor && x < xcursor + 64))) { | ||
| 152 | + /* pointer area */ | ||
| 153 | + int xdiff = x - xcursor; | ||
| 154 | + uint16_t curs = s->cursor[(y - ycursor) * 8 + xdiff / 8]; | ||
| 155 | + int op = (curs >> ((xdiff & 7) * 2)) & 3; | ||
| 156 | + if (likely(op == 0)) { | ||
| 157 | + /* transparent */ | ||
| 158 | + index = *vram; | ||
| 159 | + color = (*rgb_to_pixel)( | ||
| 160 | + s->color_palette[index][0], | ||
| 161 | + s->color_palette[index][1], | ||
| 162 | + s->color_palette[index][2]); | ||
| 163 | + } else { | ||
| 164 | + /* get cursor color */ | ||
| 165 | + index = op - 1; | ||
| 166 | + color = (*rgb_to_pixel)( | ||
| 167 | + s->cursor_palette[index][0], | ||
| 168 | + s->cursor_palette[index][1], | ||
| 169 | + s->cursor_palette[index][2]); | ||
| 170 | + } | ||
| 171 | + } else { | ||
| 172 | + /* normal area */ | ||
| 173 | + index = *vram; | ||
| 174 | + color = (*rgb_to_pixel)( | ||
| 175 | + s->color_palette[index][0], | ||
| 176 | + s->color_palette[index][1], | ||
| 177 | + s->color_palette[index][2]); | ||
| 178 | + } | ||
| 179 | + memcpy(dd, &color, w); | ||
| 180 | + dd += w; | ||
| 181 | + x++; | ||
| 182 | + vram++; | ||
| 183 | + if (x == s->width) { | ||
| 184 | + xmax = s->width - 1; | ||
| 185 | + y++; | ||
| 186 | + if (y == s->height) { | ||
| 187 | + ymax = s->height - 1; | ||
| 188 | + goto done; | ||
| 189 | + } | ||
| 190 | + data_display = dd = data_display + ds_get_linesize(s->ds); | ||
| 191 | + xmin = 0; | ||
| 192 | + x = 0; | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + if (x > xmax) | ||
| 196 | + xmax = x; | ||
| 197 | + if (y > ymax) | ||
| 198 | + ymax = y; | ||
| 199 | + } else { | ||
| 200 | + int dy; | ||
| 201 | + if (page_min != (ram_addr_t)-1) { | ||
| 202 | + reset_dirty(s, page_min, page_max); | ||
| 203 | + page_min = (ram_addr_t)-1; | ||
| 204 | + page_max = 0; | ||
| 205 | + dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); | ||
| 206 | + xmin = s->width; | ||
| 207 | + xmax = 0; | ||
| 208 | + ymin = s->height; | ||
| 209 | + ymax = 0; | ||
| 210 | + } | ||
| 211 | + x += TARGET_PAGE_SIZE; | ||
| 212 | + dy = x / s->width; | ||
| 213 | + x = x % s->width; | ||
| 214 | + y += dy; | ||
| 215 | + vram += TARGET_PAGE_SIZE; | ||
| 216 | + data_display += dy * ds_get_linesize(s->ds); | ||
| 217 | + dd = data_display + x * w; | ||
| 218 | + } | ||
| 219 | + page += TARGET_PAGE_SIZE; | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | +done: | ||
| 223 | + if (page_min != (ram_addr_t)-1) { | ||
| 224 | + dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); | ||
| 225 | + reset_dirty(s, page_min, page_max); | ||
| 226 | + } | ||
| 92 | } | 227 | } |
| 93 | 228 | ||
| 94 | -static void g364fb_draw_blank(G364State *s, int full_update) | 229 | +static void g364fb_draw_blank(G364State *s) |
| 95 | { | 230 | { |
| 96 | int i, w; | 231 | int i, w; |
| 97 | uint8_t *d; | 232 | uint8_t *d; |
| 98 | 233 | ||
| 99 | - if (!full_update) | 234 | + if (s->blanked) { |
| 235 | + /* Screen is already blank. No need to redraw it */ | ||
| 100 | return; | 236 | return; |
| 237 | + } | ||
| 101 | 238 | ||
| 102 | - w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); | 239 | + w = s->width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); |
| 103 | d = ds_get_data(s->ds); | 240 | d = ds_get_data(s->ds); |
| 104 | - for(i = 0; i < s->scr_height; i++) { | 241 | + for (i = 0; i < s->height; i++) { |
| 105 | memset(d, 0, w); | 242 | memset(d, 0, w); |
| 106 | d += ds_get_linesize(s->ds); | 243 | d += ds_get_linesize(s->ds); |
| 107 | } | 244 | } |
| 108 | 245 | ||
| 109 | - dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); | 246 | + dpy_update(s->ds, 0, 0, s->width, s->height); |
| 247 | + s->blanked = 1; | ||
| 110 | } | 248 | } |
| 111 | 249 | ||
| 112 | -#define GMODE_GRAPH 0 | ||
| 113 | -#define GMODE_BLANK 1 | ||
| 114 | - | ||
| 115 | static void g364fb_update_display(void *opaque) | 250 | static void g364fb_update_display(void *opaque) |
| 116 | { | 251 | { |
| 117 | G364State *s = opaque; | 252 | G364State *s = opaque; |
| 118 | - int full_update, graphic_mode; | ||
| 119 | 253 | ||
| 120 | - if (s->scr_width == 0 || s->scr_height == 0) | 254 | + if (s->width == 0 || s->height == 0) |
| 121 | return; | 255 | return; |
| 122 | 256 | ||
| 123 | - if (s->ctla & CTLA_FORCE_BLANK) | ||
| 124 | - graphic_mode = GMODE_BLANK; | ||
| 125 | - else | ||
| 126 | - graphic_mode = GMODE_GRAPH; | ||
| 127 | - full_update = 0; | ||
| 128 | - if (graphic_mode != s->graphic_mode) { | ||
| 129 | - s->graphic_mode = graphic_mode; | ||
| 130 | - full_update = 1; | ||
| 131 | - } | ||
| 132 | - if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) { | ||
| 133 | - qemu_console_resize(s->ds, s->scr_width, s->scr_height); | ||
| 134 | - full_update = 1; | 257 | + if (s->width != ds_get_width(s->ds) || s->height != ds_get_height(s->ds)) { |
| 258 | + qemu_console_resize(s->ds, s->width, s->height); | ||
| 135 | } | 259 | } |
| 136 | - switch(graphic_mode) { | ||
| 137 | - case GMODE_GRAPH: | ||
| 138 | - g364fb_draw_graphic(s, full_update); | ||
| 139 | - break; | ||
| 140 | - case GMODE_BLANK: | ||
| 141 | - default: | ||
| 142 | - g364fb_draw_blank(s, full_update); | ||
| 143 | - break; | 260 | + |
| 261 | + if (s->ctla & CTLA_FORCE_BLANK) { | ||
| 262 | + g364fb_draw_blank(s); | ||
| 263 | + } else if (s->depth == 8) { | ||
| 264 | + g364fb_draw_graphic8(s); | ||
| 265 | + } else { | ||
| 266 | + BADF("unknown guest depth %d\n", s->depth); | ||
| 144 | } | 267 | } |
| 268 | + | ||
| 269 | + qemu_irq_raise(s->irq); | ||
| 145 | } | 270 | } |
| 146 | 271 | ||
| 147 | -/* force a full display refresh */ | ||
| 148 | -static void g364fb_invalidate_display(void *opaque) | 272 | +static void inline g364fb_invalidate_display(void *opaque) |
| 149 | { | 273 | { |
| 150 | G364State *s = opaque; | 274 | G364State *s = opaque; |
| 151 | - s->graphic_mode = -1; /* force full update */ | 275 | + int i; |
| 276 | + | ||
| 277 | + s->blanked = 0; | ||
| 278 | + for (i = 0; i < s->vram_size; i += TARGET_PAGE_SIZE) { | ||
| 279 | + cpu_physical_memory_set_dirty(s->vram_offset + i); | ||
| 280 | + } | ||
| 152 | } | 281 | } |
| 153 | 282 | ||
| 154 | static void g364fb_reset(void *opaque) | 283 | static void g364fb_reset(void *opaque) |
| 155 | { | 284 | { |
| 156 | G364State *s = opaque; | 285 | G364State *s = opaque; |
| 157 | - | ||
| 158 | - memset(s->palette, 0, sizeof(s->palette)); | ||
| 159 | - s->scr_width = s->scr_height = 0; | ||
| 160 | - memset(s->vram_buffer, 0, s->vram_size); | ||
| 161 | - s->graphic_mode = -1; /* force full update */ | 286 | + qemu_irq_lower(s->irq); |
| 287 | + | ||
| 288 | + memset(s->color_palette, 0, sizeof(s->color_palette)); | ||
| 289 | + memset(s->cursor_palette, 0, sizeof(s->cursor_palette)); | ||
| 290 | + memset(s->cursor, 0, sizeof(s->cursor)); | ||
| 291 | + s->cursor_position = 0; | ||
| 292 | + s->ctla = 0; | ||
| 293 | + s->top_of_screen = 0; | ||
| 294 | + s->width = s->height = 0; | ||
| 295 | + memset(s->vram, 0, s->vram_size); | ||
| 296 | + g364fb_invalidate_display(opaque); | ||
| 162 | } | 297 | } |
| 163 | 298 | ||
| 164 | static void g364fb_screen_dump(void *opaque, const char *filename) | 299 | static void g364fb_screen_dump(void *opaque, const char *filename) |
| @@ -169,117 +304,223 @@ static void g364fb_screen_dump(void *opaque, const char *filename) | @@ -169,117 +304,223 @@ static void g364fb_screen_dump(void *opaque, const char *filename) | ||
| 169 | uint8_t *data_buffer; | 304 | uint8_t *data_buffer; |
| 170 | FILE *f; | 305 | FILE *f; |
| 171 | 306 | ||
| 307 | + if (s->depth != 8) { | ||
| 308 | + BADF("unknown guest depth %d\n", s->depth); | ||
| 309 | + return; | ||
| 310 | + } | ||
| 311 | + | ||
| 172 | f = fopen(filename, "wb"); | 312 | f = fopen(filename, "wb"); |
| 173 | if (!f) | 313 | if (!f) |
| 174 | return; | 314 | return; |
| 175 | 315 | ||
| 176 | - data_buffer = s->vram_buffer; | ||
| 177 | - fprintf(f, "P6\n%d %d\n%d\n", | ||
| 178 | - s->scr_width, s->scr_height, 255); | ||
| 179 | - for(y = 0; y < s->scr_height; y++) | ||
| 180 | - for(x = 0; x < s->scr_width; x++, data_buffer++) { | ||
| 181 | - index = *data_buffer; | ||
| 182 | - fputc(s->palette[index][0], f); | ||
| 183 | - fputc(s->palette[index][1], f); | ||
| 184 | - fputc(s->palette[index][2], f); | 316 | + if (s->ctla & CTLA_FORCE_BLANK) { |
| 317 | + /* blank screen */ | ||
| 318 | + fprintf(f, "P4\n%d %d\n", | ||
| 319 | + s->width, s->height); | ||
| 320 | + for (y = 0; y < s->height; y++) | ||
| 321 | + for (x = 0; x < s->width; x++) | ||
| 322 | + fputc(0, f); | ||
| 323 | + } else { | ||
| 324 | + data_buffer = s->vram + s->top_of_screen; | ||
| 325 | + fprintf(f, "P6\n%d %d\n%d\n", | ||
| 326 | + s->width, s->height, 255); | ||
| 327 | + for (y = 0; y < s->height; y++) | ||
| 328 | + for (x = 0; x < s->width; x++, data_buffer++) { | ||
| 329 | + index = *data_buffer; | ||
| 330 | + fputc(s->color_palette[index][0], f); | ||
| 331 | + fputc(s->color_palette[index][1], f); | ||
| 332 | + fputc(s->color_palette[index][2], f); | ||
| 185 | } | 333 | } |
| 334 | + } | ||
| 335 | + | ||
| 186 | fclose(f); | 336 | fclose(f); |
| 187 | } | 337 | } |
| 188 | 338 | ||
| 189 | /* called for accesses to io ports */ | 339 | /* called for accesses to io ports */ |
| 190 | -static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr) | 340 | +static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) |
| 191 | { | 341 | { |
| 192 | - //G364State *s = opaque; | 342 | + G364State *s = opaque; |
| 193 | uint32_t val; | 343 | uint32_t val; |
| 194 | 344 | ||
| 195 | - addr &= 0xffff; | ||
| 196 | - | ||
| 197 | - switch (addr) { | ||
| 198 | - default: | ||
| 199 | -#ifdef DEBUG_G364 | ||
| 200 | - printf("g364fb/ctrl: invalid read at [" TARGET_FMT_lx "]\n", addr); | ||
| 201 | -#endif | ||
| 202 | - val = 0; | ||
| 203 | - break; | 345 | + if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) { |
| 346 | + /* cursor pattern */ | ||
| 347 | + int idx = (addr - REG_CURS_PAT) >> 3; | ||
| 348 | + val = s->cursor[idx]; | ||
| 349 | + } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) { | ||
| 350 | + /* cursor palette */ | ||
| 351 | + int idx = (addr - REG_CURS_PAL) >> 3; | ||
| 352 | + val = ((uint32_t)s->cursor_palette[idx][0] << 16); | ||
| 353 | + val |= ((uint32_t)s->cursor_palette[idx][1] << 8); | ||
| 354 | + val |= ((uint32_t)s->cursor_palette[idx][2] << 0); | ||
| 355 | + } else { | ||
| 356 | + switch (addr) { | ||
| 357 | + case REG_ID: | ||
| 358 | + val = 0x10; /* Mips G364 */ | ||
| 359 | + break; | ||
| 360 | + case REG_DISPLAY: | ||
| 361 | + val = s->width / 4; | ||
| 362 | + break; | ||
| 363 | + case REG_VDISPLAY: | ||
| 364 | + val = s->height * 2; | ||
| 365 | + break; | ||
| 366 | + case REG_CTLA: | ||
| 367 | + val = s->ctla; | ||
| 368 | + break; | ||
| 369 | + default: | ||
| 370 | + { | ||
| 371 | + BADF("invalid read at [" TARGET_FMT_plx "]\n", addr); | ||
| 372 | + val = 0; | ||
| 373 | + break; | ||
| 374 | + } | ||
| 375 | + } | ||
| 204 | } | 376 | } |
| 205 | 377 | ||
| 206 | -#ifdef DEBUG_G364 | ||
| 207 | - printf("g364fb/ctrl: read 0x%02x at [" TARGET_FMT_lx "]\n", val, addr); | ||
| 208 | -#endif | 378 | + DPRINTF("read 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); |
| 209 | 379 | ||
| 210 | return val; | 380 | return val; |
| 211 | } | 381 | } |
| 212 | 382 | ||
| 213 | static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr) | 383 | static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr) |
| 214 | { | 384 | { |
| 215 | - uint32_t v; | ||
| 216 | - v = g364fb_ctrl_readb(opaque, addr); | ||
| 217 | - v |= g364fb_ctrl_readb(opaque, addr + 1) << 8; | ||
| 218 | - return v; | 385 | + uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); |
| 386 | + if (addr & 0x2) | ||
| 387 | + return v >> 16; | ||
| 388 | + else | ||
| 389 | + return v & 0xffff; | ||
| 219 | } | 390 | } |
| 220 | 391 | ||
| 221 | -static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) | 392 | +static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr) |
| 222 | { | 393 | { |
| 223 | - uint32_t v; | ||
| 224 | - v = g364fb_ctrl_readb(opaque, addr); | ||
| 225 | - v |= g364fb_ctrl_readb(opaque, addr + 1) << 8; | ||
| 226 | - v |= g364fb_ctrl_readb(opaque, addr + 2) << 16; | ||
| 227 | - v |= g364fb_ctrl_readb(opaque, addr + 3) << 24; | ||
| 228 | - return v; | 394 | + uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); |
| 395 | + return (v >> (8 * (addr & 0x3))) & 0xff; | ||
| 229 | } | 396 | } |
| 230 | 397 | ||
| 231 | -static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | 398 | +static void g364fb_update_depth(G364State *s) |
| 232 | { | 399 | { |
| 233 | - G364State *s = opaque; | 400 | + const static int depths[8] = { 1, 2, 4, 8, 15, 16, 0 }; |
| 401 | + s->depth = depths[(s->ctla & 0x00700000) >> 20]; | ||
| 402 | +} | ||
| 234 | 403 | ||
| 235 | - addr &= 0xffff; | 404 | +static void g364_invalidate_cursor_position(G364State *s) |
| 405 | +{ | ||
| 406 | + int ymin, ymax, start, end, i; | ||
| 236 | 407 | ||
| 237 | -#ifdef DEBUG_G364 | ||
| 238 | - printf("g364fb/ctrl: write 0x%02x at [" TARGET_FMT_lx "]\n", val, addr); | ||
| 239 | -#endif | 408 | + /* invalidate only near the cursor */ |
| 409 | + ymin = s->cursor_position & 0xfff; | ||
| 410 | + ymax = MIN(s->height, ymin + 64); | ||
| 411 | + start = ymin * ds_get_linesize(s->ds); | ||
| 412 | + end = (ymax + 1) * ds_get_linesize(s->ds); | ||
| 240 | 413 | ||
| 241 | - if (addr < 0x0800) { | 414 | + for (i = start; i < end; i += TARGET_PAGE_SIZE) { |
| 415 | + cpu_physical_memory_set_dirty(s->vram_offset + i); | ||
| 416 | + } | ||
| 417 | +} | ||
| 418 | + | ||
| 419 | +static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 420 | +{ | ||
| 421 | + G364State *s = opaque; | ||
| 422 | + | ||
| 423 | + DPRINTF("write 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); | ||
| 424 | + | ||
| 425 | + if (addr >= REG_CLR_PAL && addr < REG_CLR_PAL + 0x800) { | ||
| 242 | /* color palette */ | 426 | /* color palette */ |
| 243 | - int idx = addr >> 3; | ||
| 244 | - int c = addr & 7; | ||
| 245 | - if (c < 3) | ||
| 246 | - s->palette[idx][c] = (uint8_t)val; | 427 | + int idx = (addr - REG_CLR_PAL) >> 3; |
| 428 | + s->color_palette[idx][0] = (val >> 16) & 0xff; | ||
| 429 | + s->color_palette[idx][1] = (val >> 8) & 0xff; | ||
| 430 | + s->color_palette[idx][2] = val & 0xff; | ||
| 431 | + g364fb_invalidate_display(s); | ||
| 432 | + } else if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) { | ||
| 433 | + /* cursor pattern */ | ||
| 434 | + int idx = (addr - REG_CURS_PAT) >> 3; | ||
| 435 | + s->cursor[idx] = val; | ||
| 436 | + g364fb_invalidate_display(s); | ||
| 437 | + } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) { | ||
| 438 | + /* cursor palette */ | ||
| 439 | + int idx = (addr - REG_CURS_PAL) >> 3; | ||
| 440 | + s->cursor_palette[idx][0] = (val >> 16) & 0xff; | ||
| 441 | + s->cursor_palette[idx][1] = (val >> 8) & 0xff; | ||
| 442 | + s->cursor_palette[idx][2] = val & 0xff; | ||
| 443 | + g364fb_invalidate_display(s); | ||
| 247 | } else { | 444 | } else { |
| 248 | switch (addr) { | 445 | switch (addr) { |
| 249 | - case REG_DISPLAYX: | ||
| 250 | - s->scr_width = (s->scr_width & 0xfffffc03) | (val << 2); | 446 | + case REG_ID: /* Card identifier; read-only */ |
| 447 | + case REG_BOOT: /* Boot timing */ | ||
| 448 | + case 0x80108: /* Line timing: half sync */ | ||
| 449 | + case 0x80110: /* Line timing: back porch */ | ||
| 450 | + case 0x80120: /* Line timing: short display */ | ||
| 451 | + case 0x80128: /* Frame timing: broad pulse */ | ||
| 452 | + case 0x80130: /* Frame timing: v sync */ | ||
| 453 | + case 0x80138: /* Frame timing: v preequalise */ | ||
| 454 | + case 0x80140: /* Frame timing: v postequalise */ | ||
| 455 | + case 0x80148: /* Frame timing: v blank */ | ||
| 456 | + case 0x80158: /* Line timing: line time */ | ||
| 457 | + case 0x80160: /* Frame store: line start */ | ||
| 458 | + case 0x80168: /* vram cycle: mem init */ | ||
| 459 | + case 0x80170: /* vram cycle: transfer delay */ | ||
| 460 | + case 0x80200: /* vram cycle: mask register */ | ||
| 461 | + /* ignore */ | ||
| 462 | + break; | ||
| 463 | + case REG_TOP: | ||
| 464 | + s->top_of_screen = val; | ||
| 465 | + g364fb_invalidate_display(s); | ||
| 466 | + break; | ||
| 467 | + case REG_DISPLAY: | ||
| 468 | + s->width = val * 4; | ||
| 251 | break; | 469 | break; |
| 252 | - case REG_DISPLAYX + 1: | ||
| 253 | - s->scr_width = (s->scr_width & 0xfffc03ff) | (val << 10); | 470 | + case REG_VDISPLAY: |
| 471 | + s->height = val / 2; | ||
| 254 | break; | 472 | break; |
| 255 | - case REG_DISPLAYY: | ||
| 256 | - s->scr_height = (s->scr_height & 0xffffff80) | (val >> 1); | 473 | + case REG_CTLA: |
| 474 | + s->ctla = val; | ||
| 475 | + g364fb_update_depth(s); | ||
| 476 | + g364fb_invalidate_display(s); | ||
| 257 | break; | 477 | break; |
| 258 | - case REG_DISPLAYY + 1: | ||
| 259 | - s->scr_height = (s->scr_height & 0xffff801f) | (val << 7); | 478 | + case REG_CURS_POS: |
| 479 | + g364_invalidate_cursor_position(s); | ||
| 480 | + s->cursor_position = val; | ||
| 481 | + g364_invalidate_cursor_position(s); | ||
| 482 | + break; | ||
| 483 | + case REG_RESET: | ||
| 484 | + g364fb_reset(s); | ||
| 260 | break; | 485 | break; |
| 261 | default: | 486 | default: |
| 262 | -#ifdef DEBUG_G364 | ||
| 263 | - printf("g364fb/ctrl: invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr); | ||
| 264 | -#endif | 487 | + BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); |
| 265 | break; | 488 | break; |
| 266 | } | 489 | } |
| 267 | } | 490 | } |
| 268 | - s->graphic_mode = -1; /* force full update */ | 491 | + qemu_irq_lower(s->irq); |
| 269 | } | 492 | } |
| 270 | 493 | ||
| 271 | static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val) | 494 | static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 272 | { | 495 | { |
| 273 | - g364fb_ctrl_writeb(opaque, addr, val & 0xff); | ||
| 274 | - g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff); | 496 | + uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); |
| 497 | + | ||
| 498 | + if (addr & 0x2) | ||
| 499 | + val = (val << 16) | (old_val & 0x0000ffff); | ||
| 500 | + else | ||
| 501 | + val = val | (old_val & 0xffff0000); | ||
| 502 | + g364fb_ctrl_writel(opaque, addr & ~0x3, val); | ||
| 275 | } | 503 | } |
| 276 | 504 | ||
| 277 | -static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | 505 | +static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 278 | { | 506 | { |
| 279 | - g364fb_ctrl_writeb(opaque, addr, val & 0xff); | ||
| 280 | - g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff); | ||
| 281 | - g364fb_ctrl_writeb(opaque, addr + 2, (val >> 16) & 0xff); | ||
| 282 | - g364fb_ctrl_writeb(opaque, addr + 3, (val >> 24) & 0xff); | 507 | + uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); |
| 508 | + | ||
| 509 | + switch (addr & 3) { | ||
| 510 | + case 0: | ||
| 511 | + val = val | (old_val & 0xffffff00); | ||
| 512 | + break; | ||
| 513 | + case 1: | ||
| 514 | + val = (val << 8) | (old_val & 0xffff00ff); | ||
| 515 | + break; | ||
| 516 | + case 2: | ||
| 517 | + val = (val << 16) | (old_val & 0xff00ffff); | ||
| 518 | + break; | ||
| 519 | + case 3: | ||
| 520 | + val = (val << 24) | (old_val & 0x00ffffff); | ||
| 521 | + break; | ||
| 522 | + } | ||
| 523 | + g364fb_ctrl_writel(opaque, addr & ~0x3, val); | ||
| 283 | } | 524 | } |
| 284 | 525 | ||
| 285 | static CPUReadMemoryFunc *g364fb_ctrl_read[3] = { | 526 | static CPUReadMemoryFunc *g364fb_ctrl_read[3] = { |
| @@ -294,90 +535,84 @@ static CPUWriteMemoryFunc *g364fb_ctrl_write[3] = { | @@ -294,90 +535,84 @@ static CPUWriteMemoryFunc *g364fb_ctrl_write[3] = { | ||
| 294 | g364fb_ctrl_writel, | 535 | g364fb_ctrl_writel, |
| 295 | }; | 536 | }; |
| 296 | 537 | ||
| 297 | -/* called for accesses to video ram */ | ||
| 298 | -static uint32_t g364fb_mem_readb(void *opaque, target_phys_addr_t addr) | 538 | +static int g364fb_load(QEMUFile *f, void *opaque, int version_id) |
| 299 | { | 539 | { |
| 300 | G364State *s = opaque; | 540 | G364State *s = opaque; |
| 541 | + unsigned int i, vram_size; | ||
| 542 | + | ||
| 543 | + if (version_id != 1) | ||
| 544 | + return -EINVAL; | ||
| 545 | + | ||
| 546 | + vram_size = qemu_get_be32(f); | ||
| 547 | + if (vram_size < s->vram_size) | ||
| 548 | + return -EINVAL; | ||
| 549 | + qemu_get_buffer(f, s->vram, s->vram_size); | ||
| 550 | + for (i = 0; i < 256; i++) | ||
| 551 | + qemu_get_buffer(f, s->color_palette[i], 3); | ||
| 552 | + for (i = 0; i < 3; i++) | ||
| 553 | + qemu_get_buffer(f, s->cursor_palette[i], 3); | ||
| 554 | + qemu_get_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); | ||
| 555 | + s->cursor_position = qemu_get_be32(f); | ||
| 556 | + s->ctla = qemu_get_be32(f); | ||
| 557 | + s->top_of_screen = qemu_get_be32(f); | ||
| 558 | + s->width = qemu_get_be32(f); | ||
| 559 | + s->height = qemu_get_be32(f); | ||
| 560 | + | ||
| 561 | + /* force refresh */ | ||
| 562 | + g364fb_update_depth(s); | ||
| 563 | + g364fb_invalidate_display(s); | ||
| 301 | 564 | ||
| 302 | - return s->vram_buffer[addr]; | ||
| 303 | -} | ||
| 304 | - | ||
| 305 | -static uint32_t g364fb_mem_readw(void *opaque, target_phys_addr_t addr) | ||
| 306 | -{ | ||
| 307 | - uint32_t v; | ||
| 308 | - v = g364fb_mem_readb(opaque, addr); | ||
| 309 | - v |= g364fb_mem_readb(opaque, addr + 1) << 8; | ||
| 310 | - return v; | ||
| 311 | -} | ||
| 312 | - | ||
| 313 | -static uint32_t g364fb_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 314 | -{ | ||
| 315 | - uint32_t v; | ||
| 316 | - v = g364fb_mem_readb(opaque, addr); | ||
| 317 | - v |= g364fb_mem_readb(opaque, addr + 1) << 8; | ||
| 318 | - v |= g364fb_mem_readb(opaque, addr + 2) << 16; | ||
| 319 | - v |= g364fb_mem_readb(opaque, addr + 3) << 24; | ||
| 320 | - return v; | 565 | + return 0; |
| 321 | } | 566 | } |
| 322 | 567 | ||
| 323 | -static void g364fb_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | 568 | +static void g364fb_save(QEMUFile *f, void *opaque) |
| 324 | { | 569 | { |
| 325 | G364State *s = opaque; | 570 | G364State *s = opaque; |
| 326 | - | ||
| 327 | - s->vram_buffer[addr] = val; | 571 | + int i; |
| 572 | + | ||
| 573 | + qemu_put_be32(f, s->vram_size); | ||
| 574 | + qemu_put_buffer(f, s->vram, s->vram_size); | ||
| 575 | + for (i = 0; i < 256; i++) | ||
| 576 | + qemu_put_buffer(f, s->color_palette[i], 3); | ||
| 577 | + for (i = 0; i < 3; i++) | ||
| 578 | + qemu_put_buffer(f, s->cursor_palette[i], 3); | ||
| 579 | + qemu_put_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); | ||
| 580 | + qemu_put_be32(f, s->cursor_position); | ||
| 581 | + qemu_put_be32(f, s->ctla); | ||
| 582 | + qemu_put_be32(f, s->top_of_screen); | ||
| 583 | + qemu_put_be32(f, s->width); | ||
| 584 | + qemu_put_be32(f, s->height); | ||
| 328 | } | 585 | } |
| 329 | 586 | ||
| 330 | -static void g364fb_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 331 | -{ | ||
| 332 | - g364fb_mem_writeb(opaque, addr, val & 0xff); | ||
| 333 | - g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); | ||
| 334 | -} | ||
| 335 | - | ||
| 336 | -static void g364fb_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 337 | -{ | ||
| 338 | - g364fb_mem_writeb(opaque, addr, val & 0xff); | ||
| 339 | - g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); | ||
| 340 | - g364fb_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); | ||
| 341 | - g364fb_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); | ||
| 342 | -} | ||
| 343 | - | ||
| 344 | -static CPUReadMemoryFunc *g364fb_mem_read[3] = { | ||
| 345 | - g364fb_mem_readb, | ||
| 346 | - g364fb_mem_readw, | ||
| 347 | - g364fb_mem_readl, | ||
| 348 | -}; | ||
| 349 | - | ||
| 350 | -static CPUWriteMemoryFunc *g364fb_mem_write[3] = { | ||
| 351 | - g364fb_mem_writeb, | ||
| 352 | - g364fb_mem_writew, | ||
| 353 | - g364fb_mem_writel, | ||
| 354 | -}; | ||
| 355 | - | ||
| 356 | -int g364fb_mm_init(int vram_size, int it_shift, | ||
| 357 | - target_phys_addr_t vram_base, target_phys_addr_t ctrl_base) | 587 | +int g364fb_mm_init(uint8_t *vram, ram_addr_t vram_offset, |
| 588 | + int vram_size, target_phys_addr_t vram_base, | ||
| 589 | + target_phys_addr_t ctrl_base, int it_shift, | ||
| 590 | + qemu_irq irq) | ||
| 358 | { | 591 | { |
| 359 | G364State *s; | 592 | G364State *s; |
| 360 | - int io_vram, io_ctrl; | 593 | + int io_ctrl; |
| 361 | 594 | ||
| 362 | s = qemu_mallocz(sizeof(G364State)); | 595 | s = qemu_mallocz(sizeof(G364State)); |
| 363 | if (!s) | 596 | if (!s) |
| 364 | return -1; | 597 | return -1; |
| 365 | 598 | ||
| 599 | + s->vram = vram; | ||
| 600 | + s->vram_offset = vram_offset; | ||
| 366 | s->vram_size = vram_size; | 601 | s->vram_size = vram_size; |
| 367 | - s->vram_buffer = qemu_mallocz(s->vram_size); | 602 | + s->irq = irq; |
| 368 | 603 | ||
| 369 | qemu_register_reset(g364fb_reset, s); | 604 | qemu_register_reset(g364fb_reset, s); |
| 605 | + register_savevm("g364fb", 0, 1, g364fb_save, g364fb_load, s); | ||
| 370 | g364fb_reset(s); | 606 | g364fb_reset(s); |
| 371 | 607 | ||
| 372 | s->ds = graphic_console_init(g364fb_update_display, | 608 | s->ds = graphic_console_init(g364fb_update_display, |
| 373 | g364fb_invalidate_display, | 609 | g364fb_invalidate_display, |
| 374 | g364fb_screen_dump, NULL, s); | 610 | g364fb_screen_dump, NULL, s); |
| 375 | 611 | ||
| 376 | - io_vram = cpu_register_io_memory(0, g364fb_mem_read, g364fb_mem_write, s); | ||
| 377 | - cpu_register_physical_memory(vram_base, vram_size, io_vram); | 612 | + cpu_register_physical_memory(vram_base, s->vram_size, s->vram_offset); |
| 378 | 613 | ||
| 379 | io_ctrl = cpu_register_io_memory(0, g364fb_ctrl_read, g364fb_ctrl_write, s); | 614 | io_ctrl = cpu_register_io_memory(0, g364fb_ctrl_read, g364fb_ctrl_write, s); |
| 380 | - cpu_register_physical_memory(ctrl_base, 0x10000, io_ctrl); | 615 | + cpu_register_physical_memory(ctrl_base, 0x200000, io_ctrl); |
| 381 | 616 | ||
| 382 | return 0; | 617 | return 0; |
| 383 | } | 618 | } |
hw/g364fb_template.h deleted
100644 → 0
| 1 | -/* | ||
| 2 | - * QEMU G364 framebuffer Emulator. | ||
| 3 | - * | ||
| 4 | - * Copyright (c) 2007 Hervé Poussineau | ||
| 5 | - * | ||
| 6 | - * This program is free software; you can redistribute it and/or | ||
| 7 | - * modify it under the terms of the GNU General Public License as | ||
| 8 | - * published by the Free Software Foundation; either version 2 of | ||
| 9 | - * the License, or (at your option) any later version. | ||
| 10 | - * | ||
| 11 | - * This program is distributed in the hope that it will be useful, | ||
| 12 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | - * GNU General Public License for more details. | ||
| 15 | - * | ||
| 16 | - * You should have received a copy of the GNU General Public License along | ||
| 17 | - * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | - */ | ||
| 20 | - | ||
| 21 | -static void glue(g364fb_draw_graphic, BPP)(G364State *s, int full_update) | ||
| 22 | -{ | ||
| 23 | - int i, j; | ||
| 24 | - int w_display; | ||
| 25 | - uint8_t *data_buffer; | ||
| 26 | - uint8_t *data_display, *dd; | ||
| 27 | - | ||
| 28 | - data_buffer = s->vram_buffer; | ||
| 29 | - w_display = s->scr_width * PIXEL_WIDTH / 8; | ||
| 30 | - data_display = ds_get_data(s->ds); | ||
| 31 | - for(i = 0; i < s->scr_height; i++) { | ||
| 32 | - dd = data_display; | ||
| 33 | - for (j = 0; j < s->scr_width; j++, dd += PIXEL_WIDTH / 8, data_buffer++) { | ||
| 34 | - uint8_t index = *data_buffer; | ||
| 35 | - *((glue(glue(uint, PIXEL_WIDTH), _t) *)dd) = glue(rgb_to_pixel, BPP)( | ||
| 36 | - s->palette[index][0], | ||
| 37 | - s->palette[index][1], | ||
| 38 | - s->palette[index][2]); | ||
| 39 | - } | ||
| 40 | - data_display += ds_get_linesize(s->ds); | ||
| 41 | - } | ||
| 42 | -} |
hw/mips.h
| @@ -10,8 +10,10 @@ void *ds1225y_init(target_phys_addr_t mem_base, const char *filename); | @@ -10,8 +10,10 @@ void *ds1225y_init(target_phys_addr_t mem_base, const char *filename); | ||
| 10 | void ds1225y_set_protection(void *opaque, int protection); | 10 | void ds1225y_set_protection(void *opaque, int protection); |
| 11 | 11 | ||
| 12 | /* g364fb.c */ | 12 | /* g364fb.c */ |
| 13 | -int g364fb_mm_init(int vram_size, int it_shift, | ||
| 14 | - target_phys_addr_t vram_base, target_phys_addr_t ctrl_base); | 13 | +int g364fb_mm_init(uint8_t *vram, ram_addr_t vram_offset, |
| 14 | + int vram_size, target_phys_addr_t vram_base, | ||
| 15 | + target_phys_addr_t ctrl_base, int it_shift, | ||
| 16 | + qemu_irq irq); | ||
| 15 | 17 | ||
| 16 | /* mipsnet.c */ | 18 | /* mipsnet.c */ |
| 17 | void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); | 19 | void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); |
hw/mips_jazz.c
| @@ -201,7 +201,8 @@ void mips_jazz_init (ram_addr_t ram_size, int vga_ram_size, | @@ -201,7 +201,8 @@ void mips_jazz_init (ram_addr_t ram_size, int vga_ram_size, | ||
| 201 | /* Video card */ | 201 | /* Video card */ |
| 202 | switch (jazz_model) { | 202 | switch (jazz_model) { |
| 203 | case JAZZ_MAGNUM: | 203 | case JAZZ_MAGNUM: |
| 204 | - g364fb_mm_init(vga_ram_size, 0, 0x40000000, 0x60000000); | 204 | + g364fb_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size, |
| 205 | + 0x40000000, 0x60000000, 0, rc4030[3]); | ||
| 205 | break; | 206 | break; |
| 206 | case JAZZ_PICA61: | 207 | case JAZZ_PICA61: |
| 207 | isa_vga_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size, | 208 | isa_vga_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size, |