Commit 1fc3d392009d5de7f2787e4e5acea299f6c3ff1e

Authored by aurel32
1 parent f2c7ba15

g364 framebuffer device

(Hervé Poussineau)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4127 c046a42c-6fe2-441c-8c8c-71466251a162
hw/g364fb.c 0 → 100644
  1 +/*
  2 + * QEMU G364 framebuffer Emulator.
  3 + *
  4 + * Copyright (c) 2007-2008 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
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + */
  21 +
  22 +#include "hw.h"
  23 +#include "console.h"
  24 +#include "pixel_ops.h"
  25 +
  26 +//#define DEBUG_G364
  27 +
  28 +typedef struct G364State {
  29 + target_phys_addr_t vram_base;
  30 + unsigned int vram_size;
  31 + uint8_t *vram_buffer;
  32 + uint32_t ctla;
  33 + uint8_t palette[256][3];
  34 + /* display refresh support */
  35 + DisplayState *ds;
  36 + int graphic_mode;
  37 + uint32_t scr_width, scr_height; /* in pixels */
  38 + uint32_t last_scr_width, last_scr_height; /* in pixels */
  39 +} G364State;
  40 +
  41 +/*
  42 + * graphic modes
  43 + */
  44 +#define BPP 8
  45 +#define PIXEL_WIDTH 8
  46 +#include "g364fb_template.h"
  47 +#undef BPP
  48 +#undef PIXEL_WIDTH
  49 +
  50 +#define BPP 15
  51 +#define PIXEL_WIDTH 16
  52 +#include "g364fb_template.h"
  53 +#undef BPP
  54 +#undef PIXEL_WIDTH
  55 +
  56 +#define BPP 16
  57 +#define PIXEL_WIDTH 16
  58 +#include "g364fb_template.h"
  59 +#undef BPP
  60 +#undef PIXEL_WIDTH
  61 +
  62 +#define BPP 32
  63 +#define PIXEL_WIDTH 32
  64 +#include "g364fb_template.h"
  65 +#undef BPP
  66 +#undef PIXEL_WIDTH
  67 +
  68 +#define REG_DISPLAYX 0x0918
  69 +#define REG_DISPLAYY 0x0940
  70 +
  71 +#define CTLA_FORCE_BLANK 0x400
  72 +
  73 +static void g364fb_draw_graphic(G364State *s, int full_update)
  74 +{
  75 + if (s->scr_width == 0 || s->scr_height == 0)
  76 + return;
  77 + if (s->scr_width != s->last_scr_width
  78 + || s->scr_height != s->last_scr_height) {
  79 + s->last_scr_width = s->scr_width;
  80 + s->last_scr_height = s->scr_height;
  81 + dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
  82 + full_update = 1;
  83 + }
  84 +
  85 + switch (s->ds->depth) {
  86 + case 8:
  87 + g364fb_draw_graphic8(s, full_update);
  88 + break;
  89 + case 15:
  90 + g364fb_draw_graphic15(s, full_update);
  91 + break;
  92 + case 16:
  93 + g364fb_draw_graphic16(s, full_update);
  94 + break;
  95 + case 32:
  96 + g364fb_draw_graphic32(s, full_update);
  97 + break;
  98 + default:
  99 + printf("g364fb: unknown depth %d\n", s->ds->depth);
  100 + return;
  101 + }
  102 +
  103 + dpy_update(s->ds, 0, 0, s->last_scr_width, s->last_scr_height);
  104 +}
  105 +
  106 +static void g364fb_draw_blank(G364State *s, int full_update)
  107 +{
  108 + int i, w;
  109 + uint8_t *d;
  110 +
  111 + if (!full_update)
  112 + return;
  113 + if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
  114 + return;
  115 +
  116 + w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
  117 + d = s->ds->data;
  118 + for(i = 0; i < s->last_scr_height; i++) {
  119 + memset(d, 0, w);
  120 + d += s->ds->linesize;
  121 + }
  122 + dpy_update(s->ds, 0, 0,
  123 + s->last_scr_width, s->last_scr_height);
  124 +}
  125 +
  126 +#define GMODE_GRAPH 0
  127 +#define GMODE_BLANK 1
  128 +
  129 +static void g364fb_update_display(void *opaque)
  130 +{
  131 + G364State *s = opaque;
  132 + int full_update, graphic_mode;
  133 +
  134 + if (s->ctla & CTLA_FORCE_BLANK)
  135 + graphic_mode = GMODE_BLANK;
  136 + else
  137 + graphic_mode = GMODE_GRAPH;
  138 + full_update = 0;
  139 + if (graphic_mode != s->graphic_mode) {
  140 + s->graphic_mode = graphic_mode;
  141 + full_update = 1;
  142 + }
  143 + switch(graphic_mode) {
  144 + case GMODE_GRAPH:
  145 + g364fb_draw_graphic(s, full_update);
  146 + break;
  147 + case GMODE_BLANK:
  148 + default:
  149 + g364fb_draw_blank(s, full_update);
  150 + break;
  151 + }
  152 +}
  153 +
  154 +/* force a full display refresh */
  155 +static void g364fb_invalidate_display(void *opaque)
  156 +{
  157 + G364State *s = opaque;
  158 + s->graphic_mode = -1; /* force full update */
  159 +}
  160 +
  161 +static void g364fb_reset(void *opaque)
  162 +{
  163 + G364State *s = opaque;
  164 +
  165 + memset(s->palette, 0, sizeof(s->palette));
  166 + s->scr_width = s->scr_height = 0;
  167 + s->last_scr_width = s->last_scr_height = 0;
  168 + memset(s->vram_buffer, 0, s->vram_size);
  169 + s->graphic_mode = -1; /* force full update */
  170 +}
  171 +
  172 +static void g364fb_screen_dump(void *opaque, const char *filename)
  173 +{
  174 + G364State *s = opaque;
  175 + int y, x;
  176 + uint8_t index;
  177 + uint8_t *data_buffer;
  178 + FILE *f;
  179 +
  180 + f = fopen(filename, "wb");
  181 + if (!f)
  182 + return;
  183 +
  184 + data_buffer = s->vram_buffer;
  185 + fprintf(f, "P6\n%d %d\n%d\n",
  186 + s->scr_width, s->scr_height, 255);
  187 + for(y = 0; y < s->scr_height; y++)
  188 + for(x = 0; x < s->scr_width; x++, data_buffer++) {
  189 + index = *data_buffer;
  190 + fputc(s->palette[index][0], f);
  191 + fputc(s->palette[index][1], f);
  192 + fputc(s->palette[index][2], f);
  193 + }
  194 + fclose(f);
  195 +}
  196 +
  197 +/* called for accesses to io ports */
  198 +static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr)
  199 +{
  200 + //G364State *s = opaque;
  201 + uint32_t val;
  202 +
  203 + addr &= 0xffff;
  204 +
  205 + switch (addr) {
  206 + default:
  207 +#ifdef DEBUG_G364
  208 + printf("g364fb/ctrl: invalid read at [" TARGET_FMT_lx "]\n", addr);
  209 +#endif
  210 + val = 0;
  211 + break;
  212 + }
  213 +
  214 +#ifdef DEBUG_G364
  215 + printf("g364fb/ctrl: read 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
  216 +#endif
  217 +
  218 + return val;
  219 +}
  220 +
  221 +static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr)
  222 +{
  223 + uint32_t v;
  224 + v = g364fb_ctrl_readb(opaque, addr);
  225 + v |= g364fb_ctrl_readb(opaque, addr + 1) << 8;
  226 + return v;
  227 +}
  228 +
  229 +static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr)
  230 +{
  231 + uint32_t v;
  232 + v = g364fb_ctrl_readb(opaque, addr);
  233 + v |= g364fb_ctrl_readb(opaque, addr + 1) << 8;
  234 + v |= g364fb_ctrl_readb(opaque, addr + 2) << 16;
  235 + v |= g364fb_ctrl_readb(opaque, addr + 3) << 24;
  236 + return v;
  237 +}
  238 +
  239 +static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  240 +{
  241 + G364State *s = opaque;
  242 +
  243 + addr &= 0xffff;
  244 +
  245 +#ifdef DEBUG_G364
  246 + printf("g364fb/ctrl: write 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
  247 +#endif
  248 +
  249 + if (addr < 0x0800) {
  250 + /* color palette */
  251 + int idx = addr >> 3;
  252 + int c = addr & 7;
  253 + if (c < 3)
  254 + s->palette[idx][c] = (uint8_t)val;
  255 + } else {
  256 + switch (addr) {
  257 + case REG_DISPLAYX:
  258 + s->scr_width = (s->scr_width & 0xfffffc03) | (val << 2);
  259 + break;
  260 + case REG_DISPLAYX + 1:
  261 + s->scr_width = (s->scr_width & 0xfffc03ff) | (val << 10);
  262 + break;
  263 + case REG_DISPLAYY:
  264 + s->scr_height = (s->scr_height & 0xffffff80) | (val >> 1);
  265 + break;
  266 + case REG_DISPLAYY + 1:
  267 + s->scr_height = (s->scr_height & 0xffff801f) | (val << 7);
  268 + break;
  269 + default:
  270 +#ifdef DEBUG_G364
  271 + printf("g364fb/ctrl: invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
  272 +#endif
  273 + break;
  274 + }
  275 + }
  276 +}
  277 +
  278 +static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  279 +{
  280 + g364fb_ctrl_writeb(opaque, addr, val & 0xff);
  281 + g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  282 +}
  283 +
  284 +static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  285 +{
  286 + g364fb_ctrl_writeb(opaque, addr, val & 0xff);
  287 + g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  288 + g364fb_ctrl_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  289 + g364fb_ctrl_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  290 +}
  291 +
  292 +static CPUReadMemoryFunc *g364fb_ctrl_read[3] = {
  293 + g364fb_ctrl_readb,
  294 + g364fb_ctrl_readw,
  295 + g364fb_ctrl_readl,
  296 +};
  297 +
  298 +static CPUWriteMemoryFunc *g364fb_ctrl_write[3] = {
  299 + g364fb_ctrl_writeb,
  300 + g364fb_ctrl_writew,
  301 + g364fb_ctrl_writel,
  302 +};
  303 +
  304 +/* called for accesses to video ram */
  305 +static uint32_t g364fb_mem_readb(void *opaque, target_phys_addr_t addr)
  306 +{
  307 + G364State *s = opaque;
  308 + target_phys_addr_t relative_addr = addr - s->vram_base;
  309 +
  310 + return s->vram_buffer[relative_addr];
  311 +}
  312 +
  313 +static uint32_t g364fb_mem_readw(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 + return v;
  319 +}
  320 +
  321 +static uint32_t g364fb_mem_readl(void *opaque, target_phys_addr_t addr)
  322 +{
  323 + uint32_t v;
  324 + v = g364fb_mem_readb(opaque, addr);
  325 + v |= g364fb_mem_readb(opaque, addr + 1) << 8;
  326 + v |= g364fb_mem_readb(opaque, addr + 2) << 16;
  327 + v |= g364fb_mem_readb(opaque, addr + 3) << 24;
  328 + return v;
  329 +}
  330 +
  331 +static void g364fb_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  332 +{
  333 + G364State *s = opaque;
  334 + target_phys_addr_t relative_addr = addr - s->vram_base;
  335 +
  336 + s->vram_buffer[relative_addr] = val;
  337 +}
  338 +
  339 +static void g364fb_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  340 +{
  341 + g364fb_mem_writeb(opaque, addr, val & 0xff);
  342 + g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  343 +}
  344 +
  345 +static void g364fb_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  346 +{
  347 + g364fb_mem_writeb(opaque, addr, val & 0xff);
  348 + g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  349 + g364fb_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  350 + g364fb_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  351 +}
  352 +
  353 +static CPUReadMemoryFunc *g364fb_mem_read[3] = {
  354 + g364fb_mem_readb,
  355 + g364fb_mem_readw,
  356 + g364fb_mem_readl,
  357 +};
  358 +
  359 +static CPUWriteMemoryFunc *g364fb_mem_write[3] = {
  360 + g364fb_mem_writeb,
  361 + g364fb_mem_writew,
  362 + g364fb_mem_writel,
  363 +};
  364 +
  365 +int g364fb_mm_init(DisplayState *ds,
  366 + int vram_size, int it_shift,
  367 + target_phys_addr_t vram_base, target_phys_addr_t ctrl_base)
  368 +{
  369 + G364State *s;
  370 + int io_vram, io_ctrl;
  371 +
  372 + s = qemu_mallocz(sizeof(G364State));
  373 + if (!s)
  374 + return -1;
  375 +
  376 + s->vram_size = vram_size;
  377 + s->vram_buffer = qemu_mallocz(s->vram_size);
  378 +
  379 + qemu_register_reset(g364fb_reset, s);
  380 + g364fb_reset(s);
  381 +
  382 + s->ds = ds;
  383 + s->vram_base = vram_base;
  384 +
  385 + graphic_console_init(ds, g364fb_update_display,
  386 + g364fb_invalidate_display, g364fb_screen_dump,
  387 + NULL, s);
  388 +
  389 + io_vram = cpu_register_io_memory(0, g364fb_mem_read, g364fb_mem_write, s);
  390 + cpu_register_physical_memory(s->vram_base, vram_size, io_vram);
  391 +
  392 + io_ctrl = cpu_register_io_memory(0, g364fb_ctrl_read, g364fb_ctrl_write, s);
  393 + cpu_register_physical_memory(ctrl_base, 0x10000, io_ctrl);
  394 +
  395 + return 0;
  396 +}
... ...
hw/g364fb_template.h 0 → 100644
  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
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + */
  21 +
  22 +static void glue(g364fb_draw_graphic, BPP)(G364State *s, int full_update)
  23 +{
  24 + int i, j;
  25 + int w_display;
  26 + uint8_t *data_buffer;
  27 + uint8_t *data_display, *dd;
  28 +
  29 + data_buffer = s->vram_buffer;
  30 + w_display = s->last_scr_width * PIXEL_WIDTH / 8;
  31 + data_display = s->ds->data;
  32 + for(i = 0; i < s->last_scr_height; i++) {
  33 + dd = data_display;
  34 + for (j = 0; j < s->last_scr_width; j++, dd += PIXEL_WIDTH / 8, data_buffer++) {
  35 + uint8_t index = *data_buffer;
  36 + *((glue(glue(uint, PIXEL_WIDTH), _t) *)dd) = glue(rgb_to_pixel, BPP)(
  37 + s->palette[index][0],
  38 + s->palette[index][1],
  39 + s->palette[index][2]);
  40 + }
  41 + data_display += s->ds->linesize;
  42 + }
  43 +}
... ...