Commit 0add30cff44d681d0490b167e666c39d4d7b1e8d

Authored by aurel32
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
hw/g364fb.c
1 1 /*
2 2 * QEMU G364 framebuffer Emulator.
3 3 *
4   - * Copyright (c) 2007-2008 Hervé Poussineau
  4 + * Copyright (c) 2007-2009 Herve Poussineau
5 5 *
6 6 * This program is free software; you can redistribute it and/or
7 7 * modify it under the terms of the GNU General Public License as
... ... @@ -25,140 +25,275 @@
25 25  
26 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 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 48 uint32_t ctla;
32   - uint8_t palette[256][3];
  49 + uint32_t top_of_screen;
  50 + uint32_t width, height; /* in pixels */
33 51 /* display refresh support */
34 52 DisplayState *ds;
35   - int graphic_mode;
36   - uint32_t scr_width, scr_height; /* in pixels */
  53 + int depth;
  54 + int blanked;
37 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 96 switch (ds_get_bits_per_pixel(s->ds)) {
74 97 case 8:
75   - g364fb_draw_graphic8(s, full_update);
  98 + rgb_to_pixel = rgb_to_pixel8;
  99 + w = 1;
76 100 break;
77 101 case 15:
78   - g364fb_draw_graphic15(s, full_update);
  102 + rgb_to_pixel = rgb_to_pixel15;
  103 + w = 2;
79 104 break;
80 105 case 16:
81   - g364fb_draw_graphic16(s, full_update);
  106 + rgb_to_pixel = rgb_to_pixel16;
  107 + w = 2;
82 108 break;
83 109 case 32:
84   - g364fb_draw_graphic32(s, full_update);
  110 + rgb_to_pixel = rgb_to_pixel32;
  111 + w = 4;
85 112 break;
86 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 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 231 int i, w;
97 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 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 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 242 memset(d, 0, w);
106 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 250 static void g364fb_update_display(void *opaque)
116 251 {
117 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 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 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 283 static void g364fb_reset(void *opaque)
155 284 {
156 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 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 304 uint8_t *data_buffer;
170 305 FILE *f;
171 306  
  307 + if (s->depth != 8) {
  308 + BADF("unknown guest depth %d\n", s->depth);
  309 + return;
  310 + }
  311 +
172 312 f = fopen(filename, "wb");
173 313 if (!f)
174 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 336 fclose(f);
187 337 }
188 338  
189 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 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 380 return val;
211 381 }
212 382  
213 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 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 444 } else {
248 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 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 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 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 485 break;
261 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 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 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 526 static CPUReadMemoryFunc *g364fb_ctrl_read[3] = {
... ... @@ -294,90 +535,84 @@ static CPUWriteMemoryFunc *g364fb_ctrl_write[3] = {
294 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 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 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 592 G364State *s;
360   - int io_vram, io_ctrl;
  593 + int io_ctrl;
361 594  
362 595 s = qemu_mallocz(sizeof(G364State));
363 596 if (!s)
364 597 return -1;
365 598  
  599 + s->vram = vram;
  600 + s->vram_offset = vram_offset;
366 601 s->vram_size = vram_size;
367   - s->vram_buffer = qemu_mallocz(s->vram_size);
  602 + s->irq = irq;
368 603  
369 604 qemu_register_reset(g364fb_reset, s);
  605 + register_savevm("g364fb", 0, 1, g364fb_save, g364fb_load, s);
370 606 g364fb_reset(s);
371 607  
372 608 s->ds = graphic_console_init(g364fb_update_display,
373 609 g364fb_invalidate_display,
374 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 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 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 10 void ds1225y_set_protection(void *opaque, int protection);
11 11  
12 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 18 /* mipsnet.c */
17 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 201 /* Video card */
202 202 switch (jazz_model) {
203 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 206 break;
206 207 case JAZZ_PICA61:
207 208 isa_vga_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size,
... ...