Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JfEES-0005zb-Ke for qemu-devel@nongnu.org; Fri, 28 Mar 2008 09:02:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JfEEO-0005vi-0Q for qemu-devel@nongnu.org; Fri, 28 Mar 2008 09:02:52 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JfEEN-0005vF-D3 for qemu-devel@nongnu.org; Fri, 28 Mar 2008 09:02:51 -0400 Received: from smtp7-g19.free.fr ([212.27.42.64]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JfEEM-0003Qs-L0 for qemu-devel@nongnu.org; Fri, 28 Mar 2008 09:02:51 -0400 Received: from smtp7-g19.free.fr (localhost [127.0.0.1]) by smtp7-g19.free.fr (Postfix) with ESMTP id 9D53E32282C for ; Fri, 28 Mar 2008 14:02:48 +0100 (CET) Received: from [127.0.0.1] (rob92-4-82-225-201-66.fbx.proxad.net [82.225.201.66]) by smtp7-g19.free.fr (Postfix) with ESMTP id 31035322806 for ; Fri, 28 Mar 2008 14:02:48 +0100 (CET) Message-ID: <47ECEC6C.9030100@reactos.org> Date: Fri, 28 Mar 2008 14:02:36 +0100 From: =?ISO-8859-1?Q?Herv=E9_Poussineau?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------030004050109000907050506" Subject: [Qemu-devel] [PATCH] Add g364 framebuffer device v2 Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------030004050109000907050506 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Hi, Attached patch adds emulation for the G364 framebuffer Changelog v1 to v2 - Fully use the 256 color palette - Use glue() macro instead of redefining them - Replace constants by #defines - Remove useless members in G364State structure Thanks Aurelien for your comments. Herv=E9 --------------030004050109000907050506 Content-Type: text/plain; name="g364fb_v2.patch" Content-Disposition: inline; filename="g364fb_v2.patch" Content-Transfer-Encoding: quoted-printable Index: hw/g364fb.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- hw/g364fb.c Thu Jan 1 00:00:00 1970 +++ hw/g364fb.c Fri Mar 28 12:28:11 2008 @@ -0,0 +1,396 @@ +/* + * QEMU G364 framebuffer Emulator. + * + * Copyright (c) 2007-2008 Herv=E9 Poussineau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "hw.h" +#include "console.h" +#include "pixel_ops.h" + +//#define DEBUG_G364 + +typedef struct G364State { + target_phys_addr_t vram_base; + unsigned int vram_size; + uint8_t *vram_buffer; + uint32_t ctla; + uint8_t palette[256][3]; + /* display refresh support */ + DisplayState *ds; + int graphic_mode; + uint32_t scr_width, scr_height; /* in pixels */ + uint32_t last_scr_width, last_scr_height; /* in pixels */ +} G364State; + +/* + * graphic modes + */ +#define BPP 8 +#define PIXEL_WIDTH 8 +#include "g364fb_template.h" +#undef BPP +#undef PIXEL_WIDTH + +#define BPP 15 +#define PIXEL_WIDTH 16 +#include "g364fb_template.h" +#undef BPP +#undef PIXEL_WIDTH + +#define BPP 16 +#define PIXEL_WIDTH 16 +#include "g364fb_template.h" +#undef BPP +#undef PIXEL_WIDTH + +#define BPP 32 +#define PIXEL_WIDTH 32 +#include "g364fb_template.h" +#undef BPP +#undef PIXEL_WIDTH + +#define REG_DISPLAYX 0x0918 +#define REG_DISPLAYY 0x0940 + +#define CTLA_FORCE_BLANK 0x400 + +static void g364fb_draw_graphic(G364State *s, int full_update) +{ + if (s->scr_width =3D=3D 0 || s->scr_height =3D=3D 0) + return; + if (s->scr_width !=3D s->last_scr_width + || s->scr_height !=3D s->last_scr_height) { + s->last_scr_width =3D s->scr_width; + s->last_scr_height =3D s->scr_height; + dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); + full_update =3D 1; + } + + switch (s->ds->depth) { + case 8: + g364fb_draw_graphic8(s, full_update); + break; + case 15: + g364fb_draw_graphic15(s, full_update); + break; + case 16: + g364fb_draw_graphic16(s, full_update); + break; + case 32: + g364fb_draw_graphic32(s, full_update); + break; + default: + printf("g364fb: unknown depth %d\n", s->ds->depth); + return; + } + + dpy_update(s->ds, 0, 0, s->last_scr_width, s->last_scr_height); +} + +static void g364fb_draw_blank(G364State *s, int full_update) +{ + int i, w; + uint8_t *d; + + if (!full_update) + return; + if (s->last_scr_width <=3D 0 || s->last_scr_height <=3D 0) + return; + + w =3D s->last_scr_width * ((s->ds->depth + 7) >> 3); + d =3D s->ds->data; + for(i =3D 0; i < s->last_scr_height; i++) { + memset(d, 0, w); + d +=3D s->ds->linesize; + } + dpy_update(s->ds, 0, 0, + s->last_scr_width, s->last_scr_height); +} + +#define GMODE_GRAPH 0 +#define GMODE_BLANK 1 + +static void g364fb_update_display(void *opaque) +{ + G364State *s =3D opaque; + int full_update, graphic_mode; + + if (s->ctla & CTLA_FORCE_BLANK) + graphic_mode =3D GMODE_BLANK; + else + graphic_mode =3D GMODE_GRAPH; + full_update =3D 0; + if (graphic_mode !=3D s->graphic_mode) { + s->graphic_mode =3D graphic_mode; + full_update =3D 1; + } + switch(graphic_mode) { + case GMODE_GRAPH: + g364fb_draw_graphic(s, full_update); + break; + case GMODE_BLANK: + default: + g364fb_draw_blank(s, full_update); + break; + } +} + +/* force a full display refresh */ +static void g364fb_invalidate_display(void *opaque) +{ + G364State *s =3D opaque; + s->graphic_mode =3D -1; /* force full update */ +} + +static void g364fb_reset(void *opaque) +{ + G364State *s =3D opaque; + + memset(s->palette, 0, sizeof(s->palette)); + s->scr_width =3D s->scr_height =3D 0; + s->last_scr_width =3D s->last_scr_height =3D 0; + memset(s->vram_buffer, 0, s->vram_size); + s->graphic_mode =3D -1; /* force full update */ +} + +static void g364fb_screen_dump(void *opaque, const char *filename) +{ + G364State *s =3D opaque; + int y, x; + uint8_t index; + uint8_t *data_buffer; + FILE *f; + + f =3D fopen(filename, "wb"); + if (!f) + return; + + data_buffer =3D s->vram_buffer; + fprintf(f, "P6\n%d %d\n%d\n", + s->scr_width, s->scr_height, 255); + for(y =3D 0; y < s->scr_height; y++) + for(x =3D 0; x < s->scr_width; x++, data_buffer++) { + index =3D *data_buffer; + fputc(s->palette[index][0], f); + fputc(s->palette[index][1], f); + fputc(s->palette[index][2], f); + } + fclose(f); +} + +/* called for accesses to io ports */ +static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr) +{ + //G364State *s =3D opaque; + uint32_t val; + + addr &=3D 0xffff; + + switch (addr) { + default: +#ifdef DEBUG_G364 + printf("g364fb/ctrl: invalid read at [" TARGET_FMT_lx "]\n",= addr); +#endif + val =3D 0; + break; + } + +#ifdef DEBUG_G364 + printf("g364fb/ctrl: read 0x%02x at [" TARGET_FMT_lx "]\n", val, add= r); +#endif + + return val; +} + +static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; + v =3D g364fb_ctrl_readb(opaque, addr); + v |=3D g364fb_ctrl_readb(opaque, addr + 1) << 8; + return v; +} + +static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; + v =3D g364fb_ctrl_readb(opaque, addr); + v |=3D g364fb_ctrl_readb(opaque, addr + 1) << 8; + v |=3D g364fb_ctrl_readb(opaque, addr + 2) << 16; + v |=3D g364fb_ctrl_readb(opaque, addr + 3) << 24; + return v; +} + +static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, ui= nt32_t val) +{ + G364State *s =3D opaque; + + addr &=3D 0xffff; + +#ifdef DEBUG_G364 + printf("g364fb/ctrl: write 0x%02x at [" TARGET_FMT_lx "]\n", val, ad= dr); +#endif + + if (addr < 0x0800) { + /* color palette */ + int idx =3D addr >> 3; + int c =3D addr & 7; + if (c < 3) + s->palette[idx][c] =3D (uint8_t)val; + } else { + switch (addr) { + case REG_DISPLAYX: + s->scr_width =3D (s->scr_width & 0xfffffc03) | (val << 2= ); + break; + case REG_DISPLAYX + 1: + s->scr_width =3D (s->scr_width & 0xfffc03ff) | (val << 1= 0); + break; + case REG_DISPLAYY: + s->scr_height =3D (s->scr_height & 0xffffff80) | (val >>= 1); + break; + case REG_DISPLAYY + 1: + s->scr_height =3D (s->scr_height & 0xffff801f) | (val <<= 7); + break; + default: +#ifdef DEBUG_G364 + printf("g364fb/ctrl: invalid write of 0x%02x at [" TARGE= T_FMT_lx "]\n", val, addr); +#endif + break; + } + } +} + +static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, ui= nt32_t val) +{ + g364fb_ctrl_writeb(opaque, addr, val & 0xff); + g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff); +} + +static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, ui= nt32_t val) +{ + g364fb_ctrl_writeb(opaque, addr, val & 0xff); + g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff); + g364fb_ctrl_writeb(opaque, addr + 2, (val >> 16) & 0xff); + g364fb_ctrl_writeb(opaque, addr + 3, (val >> 24) & 0xff); +} + +static CPUReadMemoryFunc *g364fb_ctrl_read[3] =3D { + g364fb_ctrl_readb, + g364fb_ctrl_readw, + g364fb_ctrl_readl, +}; + +static CPUWriteMemoryFunc *g364fb_ctrl_write[3] =3D { + g364fb_ctrl_writeb, + g364fb_ctrl_writew, + g364fb_ctrl_writel, +}; + +/* called for accesses to video ram */ +static uint32_t g364fb_mem_readb(void *opaque, target_phys_addr_t addr) +{ + G364State *s =3D opaque; + unsigned int relative_addr =3D addr - s->vram_base; + + return s->vram_buffer[relative_addr]; +} + +static uint32_t g364fb_mem_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; + v =3D g364fb_mem_readb(opaque, addr); + v |=3D g364fb_mem_readb(opaque, addr + 1) << 8; + return v; +} + +static uint32_t g364fb_mem_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; + v =3D g364fb_mem_readb(opaque, addr); + v |=3D g364fb_mem_readb(opaque, addr + 1) << 8; + v |=3D g364fb_mem_readb(opaque, addr + 2) << 16; + v |=3D g364fb_mem_readb(opaque, addr + 3) << 24; + return v; +} + +static void g364fb_mem_writeb(void *opaque, target_phys_addr_t addr, uin= t32_t val) +{ + G364State *s =3D opaque; + unsigned int relative_addr =3D addr - s->vram_base; + + s->vram_buffer[relative_addr] =3D val; +} + +static void g364fb_mem_writew(void *opaque, target_phys_addr_t addr, uin= t32_t val) +{ + g364fb_mem_writeb(opaque, addr, val & 0xff); + g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); +} + +static void g364fb_mem_writel(void *opaque, target_phys_addr_t addr, uin= t32_t val) +{ + g364fb_mem_writeb(opaque, addr, val & 0xff); + g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); + g364fb_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); + g364fb_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); +} + +static CPUReadMemoryFunc *g364fb_mem_read[3] =3D { + g364fb_mem_readb, + g364fb_mem_readw, + g364fb_mem_readl, +}; + +static CPUWriteMemoryFunc *g364fb_mem_write[3] =3D { + g364fb_mem_writeb, + g364fb_mem_writew, + g364fb_mem_writel, +}; + +int g364fb_mm_init(DisplayState *ds, + int vram_size, int it_shift, + target_phys_addr_t vram_base, target_phys_addr_t ctrl= _base) +{ + G364State *s; + int io_vram, io_ctrl; + + s =3D qemu_mallocz(sizeof(G364State)); + if (!s) + return -1; + + s->vram_size =3D vram_size; + s->vram_buffer =3D qemu_mallocz(s->vram_size); + + qemu_register_reset(g364fb_reset, s); + g364fb_reset(s); + + s->ds =3D ds; + s->vram_base =3D vram_base; + + graphic_console_init(ds, g364fb_update_display, + g364fb_invalidate_display, g364fb_screen_dump, + NULL, s); + + io_vram =3D cpu_register_io_memory(0, g364fb_mem_read, g364fb_mem_wr= ite, s); + cpu_register_physical_memory(s->vram_base, vram_size, io_vram); + + io_ctrl =3D cpu_register_io_memory(0, g364fb_ctrl_read, g364fb_ctrl_= write, s); + cpu_register_physical_memory(ctrl_base, 0x10000, io_ctrl); + + return 0; +} Index: hw/g364fb_template.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- hw/g364fb_template.h Thu Jan 1 00:00:00 1970 +++ hw/g364fb_template.h Fri Mar 28 08:55:08 2008 @@ -0,0 +1,43 @@ +/* + * QEMU G364 framebuffer Emulator. + * + * Copyright (c) 2007 Herv=E9 Poussineau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +static void glue(g364fb_draw_graphic, BPP)(G364State *s, int full_update= ) +{ + int i, j; + int w_display; + uint8_t *data_buffer; + uint8_t *data_display, *dd; + + data_buffer =3D s->vram_buffer; + w_display =3D s->last_scr_width * PIXEL_WIDTH / 8; + data_display =3D s->ds->data; + for(i =3D 0; i < s->last_scr_height; i++) { + dd =3D data_display; + for (j =3D 0; j < s->last_scr_width; j++, dd +=3D PIXEL_WIDTH / = 8, data_buffer++) { + uint8_t index =3D *data_buffer; + *((glue(glue(uint, PIXEL_WIDTH), _t) *)dd) =3D glue(rgb_to_p= ixel, BPP)( + s->palette[index][0], + s->palette[index][1], + s->palette[index][2]); + } + data_display +=3D s->ds->linesize; + } +} --------------030004050109000907050506--