[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] cg14
From: |
Artyom Tarasenko |
Subject: |
Re: [Qemu-devel] cg14 |
Date: |
Sat, 29 May 2010 00:48:55 +0200 |
2010/5/28 Blue Swirl <address@hidden>:
> On Fri, May 28, 2010 at 7:54 AM, Bob Breuer <address@hidden> wrote:
>> Artyom Tarasenko wrote:
>>> 2010/5/27 Bob Breuer <address@hidden>:
>>>
>>>> Artyom Tarasenko wrote:
>>>>
>>>>> Was going to put some more empty slots into SS-10/20 (VSIMMs, SX)
>>>>> after we are done with SS-5 (due to technical limitations I can switch
>>>>> access from one real SS model to another one once a few days only).
>>>>>
>>>>>
>>>> I have a partial implementation of the SS-20 VSIMM (cg14) that I've been
>>>> working on. With the Sun firmware, I have working text console, color
>>>> boot logo, and programmable video resolutions up to 1600x1280.
>>>>
>>>
>>> Great news! This would allow qemu booting NeXTStep! Are you planning
>>> to submit the patches any time soon?
>>>
>>>
>> It's not in a state to be submitted yet, but I've attached a working
>> patch if you want to give it a try. I need to hook it up to qdev and
>> fill in some more of the obviously incomplete switch cases before I'd
>> sign off on it.
>
> Nice work. I have a few comments below.
>
> This probably needs support from OpenBIOS to be usable without OBP.
Maybe it can be used as a second adapter without OpenBIOS support? At
least under some OSes?
>>
>> Bob
>>
>>
>> diff --git a/Makefile.target b/Makefile.target
>> index fda5bf3..b17b3af 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -250,6 +250,7 @@ else
>> obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
>> obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
>> obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
>> +obj-sparc-y += cg14.o
>> endif
>>
>> obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
>> diff --git a/hw/sun4m.c b/hw/sun4m.c
>> index 7ba0f76..8b23c9b 100644
>> --- a/hw/sun4m.c
>> +++ b/hw/sun4m.c
>> @@ -864,6 +864,13 @@ static void sun4m_hw_init(const struct sun4m_hwdef
>> *hwdef, ram_addr_t RAM_size,
>> fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
>> exit (1);
>> }
>> + if (hwdef->machine_id == 65) { /* SS-20 */
>
> hwdef structure should contain a field for cg14. If non-zero, install
> cg14. Was cg14 only available for SS-20? Was it always included? This
> is also interesting for OpenBIOS, we need to detect cg14 vs. TCX.
>
>> + /* cg14.c */
>> + void cg14_init(target_phys_addr_t ctrl_base, target_phys_addr_t
>> vram_base,
>> + uint32_t vram_size);
>
> This should go to sun4m.h or cg14.h.
>
>> +
>> + cg14_init(0x09c000000ULL, 0x0fc000000ULL, 8<<20);
>> + } else
>
> Please add braces and reindent.
>
>> tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
>> graphic_depth);
>>
>> --- /dev/null Fri May 28 02:08:36 2010
>> +++ hw/cg14.c Fri May 28 01:58:49 2010
>> @@ -0,0 +1,785 @@
>> +/*
>> + * QEMU CG14 Frame buffer
>> + *
>> + * Copyright (c) 2010 Bob Breuer
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> copy
>> + * of this software and associated documentation files (the "Software"), to
>> deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included
>> in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
>> OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#include "console.h"
>> +#include "sysbus.h"
>> +
>> +#ifdef DEBUG
DEBUG_CG14 ?
>> +#define DPRINTF(fmt, ...) \
>> + do { printf("CG14: " fmt , ## __VA_ARGS__); } while (0)
>> +#else
>> +#define DPRINTF(fmt, ...)
>> +#endif
>> +
>> +#define CG14_INFO(fmt, ...) \
>> + do { printf("CG14: " fmt , ## __VA_ARGS__); } while (0)
>> +#define CG14_ERROR(fmt, ...) \
>> + do { printf("CG14: " fmt , ## __VA_ARGS__); } while (0)
>> +
>> +/*
>> + * A[28:26] = slot number (4 to 7)
>> + * regs: size 0x10000 @ 0x09c000000 (0x80000000 + slot * 64M)
>> + * vmem: size upto 16MB @ 0x0fc000000 (0xE0000000 + slot * 64M)
>> + */
>
> If you have any links to chipset docs, it would be nice to mention those here.
>
>> +
>> +/*
>> + * memory map:
>> + * reg+0x0000 = control registers
>> + * reg+0x1000 = cursor registers
>> + * reg+0x2000 = dac registers (ADV7152)
>> + * reg+0x3000 = xlut
>> + * reg+0x4000 = clut1
>> + * reg+0x5000 = clut2
>> + * reg+0x6000 = clut3 (if implemented)
>> + *
>> + * mem+0x0000000 = XBGR (01234567)
>> + * mem+0x1000000 = BGR (.123.567)
>> + * mem+0x2000000 = X16 (0246)
>> + * mem+0x2800000 = C16 (1357)
>> + * mem+0x3000000 = X32 (04)
>> + * mem+0x3400000 = B32 (15)
>> + * mem+0x3800000 = G32 (26)
>> + * mem+0x3c00000 = R32 (37)
>
> Interesting device. You could increase the performance a lot by making
> the XBGR area ordinary memory and detecting the dirtyness with
> VGA_DIRTY_FLAG like TCX. The other areas could use multiple byte
> stores to the memory so dirty information would be updated.
>
>> + */
>> +
>> +#define CG14_REG_SIZE 0x10000
>> +#define CG14_VMEM_SLOTSIZE (64<<20)
>> +
>> +#define CG14_MONID_1024x768 0
>> +#define CG14_MONID_1600x1280 1
>> +#define CG14_MONID_1280x1024 2
>> +#define CG14_MONID_1152x900 7
>> +
>> +#define CG14_MONID_DEFAULT CG14_MONID_1024x768
>> +
>> +#define MCR_PIXMODE_MASK 0x30
>> +#define MCR_PIXMODE_8 0x00
>> +#define MCR_PIXMODE_16 0x20 /* 8+8 (X16,C16) */
>> +#define MCR_PIXMODE_32 0x30 /* XBGR */
>> +
>> +
>> +struct ADV7152_state {
>> + uint8_t mode;
>> + uint8_t address;
>> + int rgb_seq;
>> +};
>> +
>> +typedef struct CG14State {
>> + SysBusDevice busdev;
>> + DisplayState *ds;
>> +
>> + uint8_t *vram;
>> + uint32_t vram_amask;
>> + int width, height;
>> + int dirty, size_changed;
>> + struct {
>> + uint8_t mcr;
>> + uint8_t ppr;
>> + } ctrl;
>> + struct ADV7152_state dac;
>> + struct {
>> + uint16_t hblank_start;
>> + uint16_t hblank_clear;
>> + uint16_t vblank_start;
>> + uint16_t vblank_clear;
>> + } timing;
>> + uint8_t xlut[256];
>> + uint32_t clut1[256];
>> + uint32_t clut2[256];
>> +} CG14State;
>> +
>> +static void cg14_screen_dump(void *opaque, const char *filename);
>> +static void cg14_invalidate_display(void *opaque);
>> +
>> +static inline uint32_t bgr_to_rgb(uint32_t bgr)
>> +{
>> + uint32_t rgb;
>> +
>> + /* swap r & b */
>> + rgb = (bgr & 0x00FF00)
>> + | (bgr & 0x0000FF) << 16
>> + | (bgr & 0xFF0000) >> 16;
>> + return rgb;
>> +}
>> +
>> +static void cg14_draw_line32(const CG14State *s, void *dst, const uint8_t
>> *src, int pixmode, int is_bgr)
>> +{
>> + int i;
>> + int x, r, g, b;
>> + uint8_t xlut_val;
>> + uint32_t dval;
>> + uint32_t abgr;
>> +
>> + xlut_val = s->ctrl.ppr;
>> +
>> + for (i=0; i<s->width; i++) {
>> + x = *src++;
>> + if (pixmode == 8) {
>
> To increase performance, pixmode should not be passed at all but
> instead separate functions should be added for each mode and the
> function should be selected before the line loop.
>
>> + b = x;
>> + } else {
>> + b = *src++;
>> + xlut_val = s->xlut[x];
>> + }
>> + if (pixmode != 32) {
>> + r = g = b;
>> + } else {
>> + g = *src++;
>> + r = *src++;
>> + }
>> + if (xlut_val == 0) {
>> + abgr = b << 16 | g << 8 | r;
>> + } else if (xlut_val == 0x40) {
>> + abgr = s->clut1[x];
>> + } else {
>> + abgr = 0;
>> + }
>> + /* dac lookup ? */
>> +
>> + /* to surface format */
>> + dval = is_bgr ? (abgr & 0xFFFFFF) : bgr_to_rgb(abgr);
>> + ((uint32_t*)dst)[i] = dval;
>> + }
>> +}
>> +
>> +static void cg14_update_display(void *opaque)
>> +{
>> + CG14State *s = opaque;
>> + int h, pixmode;
>> + uint8_t *pix;
>> + uint8_t *data;
>> + int new_width, new_height;
>> +
>> + if (s->size_changed) {
>> + new_width = 4 * (s->timing.hblank_start - s->timing.hblank_clear);
>> + new_height = s->timing.vblank_start - s->timing.vblank_clear;
>> + s->size_changed = 0;
>> + if ((new_width != s->width || new_height != s->height) && new_width
>> > 0 && new_height > 0) {
>> + s->width = new_width;
>> + s->height = new_height;
>> + CG14_INFO("new resolution = %d x %d\n", new_width, new_height);
>> + qemu_console_resize(s->ds, s->width, s->height);
>> + s->dirty = 1;
>> + }
>> + }
>> +
>> + if (!s->dirty || !s->width || !s->height) {
>> + return;
>> + }
>> +
>> + if (ds_get_bits_per_pixel(s->ds) != 32) {
>> + CG14_ERROR("cg14_update: FIXME: bpp (%d) != 32, linesize %d\n",
>> + ds_get_bits_per_pixel(s->ds), ds_get_linesize(s->ds));
>> + return;
>> + }
>> +
>> + switch (s->ctrl.mcr & MCR_PIXMODE_MASK) {
>> + case MCR_PIXMODE_32:
>> + pixmode = 32;
>> + break;
>> + case MCR_PIXMODE_16:
>> + pixmode = 16;
>> + break;
>> + case MCR_PIXMODE_8:
>> + default:
>> + pixmode = 8;
>> + break;
>> + }
>> +
>> + pix = s->vram;
>> + data = ds_get_data(s->ds);
>> +
>> + for (h=0; h<s->height; h++) {
>> + cg14_draw_line32(s, data, pix, pixmode,
>> is_surface_bgr(s->ds->surface));
>> + pix += s->width * (pixmode / 8);
>> + data += ds_get_linesize(s->ds);
>> + }
>> + dpy_update(s->ds, 0, 0, s->width, s->height);
>> + s->dirty = 0;
>> +}
>> +
>> +static void cg14_invalidate_display(void *opaque)
>> +{
>> + CG14State *s = opaque;
>> +
>> + s->dirty = 1;
>> +}
>> +
>> +static void ADV7152_write(struct ADV7152_state *s, unsigned int reg,
>> unsigned int val)
>> +{
>> + switch (reg) {
>> + case 0: /* address register */
>> + DPRINTF("ADV7152 Write address %02x\n", val);
>> + s->address = val;
>> + s->rgb_seq = 0;
>> + break;
>> + case 1: /* look up table */
>> + DPRINTF("ADV7152 Write %02x to lookup table\n", val);
>> + s->rgb_seq++;
>> + break;
>> + case 2: /* control registers */
>> + DPRINTF("ADV7152 Write %02x to control reg %d\n", val, s->address);
>> + switch (s->address) {
>> + default:
>> + break;
>> + }
>> + break;
>> + case 3: /* mode register */
>> + CG14_INFO("ADV7152 Write mode %02x (%d bit DAC, %d bit bus)\n",
>> + val, (val & 2) ? 10 : 8, (val & 4) ? 10 : 8);
>> + if (!val & 0x01) {
>> + // reset the dac
>> + s->rgb_seq = 0;
>> + }
>> + s->mode = val;
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t cg14_reg_readb(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + unsigned int val;
>> +
>> + switch (addr & 0xffff) {
>> + case 0x0000:
>> + val = s->ctrl.mcr;
>> + break;
>> + case 0x0001:
>> + val = s->ctrl.ppr;
>> + break;
>> + case 0x0004: /* status ? */
>> + /* monitor code in bits 1..3 */
>> + val = CG14_MONID_DEFAULT << 1;
>> + break;
>> + case 0x0006: /* hw version */
>> + //val = 0x00; /* old version */
>> + val = 0x30;
>> + break;
>> + default:
>> + val = 0;
>> + break;
>> + }
>> + CG14_INFO("readb %02x from reg %x\n", val, (int)addr);
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_reg_writeb(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t i;
>> +
>> + if ((addr & 0xfcff) == 0x2000) {
>> + i = (addr & 0x300) >> 8;
>> + ADV7152_write(&s->dac, i, val);
>> + return;
>> + }
>> + if ((addr & 0xff00) == 0x3000) {
>> + /* xlut */
>> + i = addr & 0xff;
>> + if (s->xlut[i] != val) {
>> + s->dirty = 1;
>> + s->xlut[i] = val;
>> + if (val && val != 0x40)
>> + CG14_ERROR("writeb xlut[%d] = %02x\n", i, val);
>> + }
>> + return;
>> + }
>> +
>> + s->dirty = 1;
>> +
>> + switch (addr & 0xffff) {
>> + case 0x0000:
>> + s->ctrl.mcr = val;
>> + break;
>> + case 0x0001:
>> + s->ctrl.ppr = val & 0xF0;
>> + break;
>> + case 0x0007:
>> + /* clock control (ICS1562AM-001) */
>> + DPRINTF("write %02x to clock control\n", val);
>> + break;
>> + default:
>> + CG14_ERROR("writeb %02x to reg %x\n", val, (int)addr);
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t cg14_reg_readw(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + unsigned int val;
>> +
>> + switch (addr & 0xffff) {
>> + case 0x0018:
>> + val = s->timing.hblank_start;
>> + break;
>> + case 0x001a:
>> + val = s->timing.hblank_clear;
>> + break;
>> + case 0x0022:
>> + val = s->timing.vblank_start;
>> + break;
>> + case 0x0024:
>> + val = s->timing.vblank_clear;
>> + break;
>> + default:
>> + val = 0;
>> + break;
>> + }
>> + CG14_INFO("readw 0x%08x from reg %x\n", val, (int)addr);
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_reg_writew(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + CG14State *s = opaque;
>> +
>> + CG14_INFO("writew %04x to reg %x\n", val, (int)addr);
>> +
>> + /* timing registers are 16bit */
>> +
>> + switch (addr & 0xffff) {
>> + case 0x0018:
>> + s->timing.hblank_start = val;
>> + break;
>> + case 0x001a:
>> + s->timing.hblank_clear = val;
>> + s->size_changed = 1;
>> + break;
>> + case 0x0022:
>> + s->timing.vblank_start = val;
>> + break;
>> + case 0x0024:
>> + s->timing.vblank_clear = val;
>> + s->size_changed = 1;
>> + break;
>> + case 0x001c: /* hsync_start */
>> + case 0x001e: /* hsync_clear */
>> + case 0x0020: /* csync_clear */
>> + case 0x0026: /* vsync_start */
>> + case 0x0028: /* vsync_clear */
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t cg14_reg_readl(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t val;
>> + uint32_t i;
>> +
>> + i = (addr & 0x3ff) >> 2;
>> + switch (addr & 0xfc00) {
>> + case 0x4000:
>> + val = s->clut1[i];
>> + break;
>> + case 0x5000:
>> + val = s->clut2[i];
>> + break;
>> + default:
>> + val = 0;
>> + CG14_ERROR("readl %08x from reg %x\n", val, (int)addr);
>> + break;
>> + }
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_reg_writel(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t i;
>> +
>> + s->dirty = 1;
>> +
>> + i = (addr & 0x3ff) >> 2;
>> + switch (addr & 0xfc00) {
>> + case 0x4000:
>> + s->clut1[i] = val;
>> + break;
>> + case 0x5000:
>> + s->clut2[i] = val;
>> + break;
>> + default:
>> + CG14_ERROR("writel %08x to reg %x\n", val, (int)addr);
>> + break;
>> + }
>> +}
>> +
>> +static CPUReadMemoryFunc *cg14_reg_read[3] = {
>> + cg14_reg_readb,
>> + cg14_reg_readw,
>> + cg14_reg_readl,
>> +};
>> +
>> +static CPUWriteMemoryFunc *cg14_reg_write[3] = {
>> + cg14_reg_writeb,
>> + cg14_reg_writew,
>> + cg14_reg_writel,
>> +};
>> +
>> +static uint32_t cg14_vram_readb(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t offset;
>> + uint32_t val = 0;
>> +
>> + switch (addr & 0x3000000) {
>> + case 0x0000000:
>> + offset = addr & s->vram_amask;
>> + val = ldub_p(s->vram+offset);
>> + break;
>> + case 0x1000000:
>> + offset = addr & s->vram_amask;
>> + val = 0; // FIXME
>> + break;
>> + case 0x2000000:
>> + offset = ((addr << 1) & s->vram_amask) + ((addr >> 23) & 1);
>> + val = ldub_p(s->vram+offset);
>> + break;
>> + case 0x3000000:
>> + offset = ((addr << 2) & s->vram_amask) + ((addr >> 22) & 3);
>> + val = ldub_p(s->vram+offset);
>> + break;
>> + }
>> + CG14_INFO("readb %02x from vram %x\n", val, (int)addr);
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_vram_writeb(void *opaque, target_phys_addr_t addr,
>> uint32_t val)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t offset;
>> +
>> + switch (addr & 0x3000000) {
>> + case 0x0000000:
>> + offset = addr & s->vram_amask;
>> + stb_p(s->vram+offset, val);
>> + if (offset < 4 * s->width * s->height) {
>> + s->dirty = 1;
>> + }
>> + break;
>> + default:
>> + CG14_ERROR("writeb %02x to vram %x\n", val, (int)addr);
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t cg14_vram_readw(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t offset;
>> + uint32_t val;
>> +
>> + switch (addr & 0x3000000) {
>> + default:
>> + offset = addr & s->vram_amask;
>> + val = 0;
>> + break;
>> + }
>> + CG14_ERROR("readw %04x from vram %x\n", val, (int)addr);
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_vram_writew(void *opaque, target_phys_addr_t addr,
>> uint32_t val)
>> +{
>> + CG14State *s = opaque;
>> +
>> + CG14_ERROR("writew %04x to vram %x\n", val, (int)addr);
>> +
>> + s->dirty = 1;
>> +
>> + switch (addr & 0x3000000) {
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t cg14_vram_readl(void *opaque, target_phys_addr_t addr)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t offset;
>> + uint32_t val = 0;
>> +
>> + switch (addr & 0x3000000) {
>> + case 0x0000000:
>> + offset = addr & s->vram_amask;
>> + val = ldl_be_p(s->vram+offset);
>> + break;
>> + case 0x1000000:
>> + case 0x2000000:
>> + case 0x3000000:
>> + CG14_ERROR("readl %08x from vram %x\n", val, (int)addr);
>> + break;
>> + }
>> +
>> + return val;
>> +}
>> +
>> +static void cg14_vram_writel(void *opaque, target_phys_addr_t addr,
>> uint32_t val)
>> +{
>> + CG14State *s = opaque;
>> + uint32_t offset;
>> +
>> + switch (addr & 0x3000000) {
>> + case 0x0000000:
>> + offset = addr & s->vram_amask;
>> + stl_be_p(s->vram+offset, val);
>> + if (offset < 4 * s->width * s->height) {
>> + s->dirty = 1;
>> + }
>> + break;
>> + case 0x1000000:
>> + case 0x2000000:
>> + case 0x3000000:
>> + CG14_ERROR("writel %08x to vram %x\n", val, (int)addr);
>> + break;
>> + }
>> +}
>> +
>> +static CPUReadMemoryFunc *cg14_vram_read[3] = {
>> + cg14_vram_readb,
>> + cg14_vram_readw,
>> + cg14_vram_readl,
>> +};
>> +
>> +static CPUWriteMemoryFunc *cg14_vram_write[3] = {
>> + cg14_vram_writeb,
>> + cg14_vram_writew,
>> + cg14_vram_writel,
>> +};
>> +
>> +
>> +/******** SX *********/
>> +
>> +static uint32_t sx_reg_readb(void *opaque, target_phys_addr_t addr)
>> +{
>> + //CG14State *s = opaque;
>> + int val;
>> +
>> + printf("SX readb reg " TARGET_FMT_plx "\n", addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + val = 0;
>> + break;
>> + }
>> + return val;
>> +}
>> +
>> +static void sx_reg_writeb(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + //CG14State *s = opaque;
>> +
>> + printf("SX writeb %02x to reg " TARGET_FMT_plx "\n", val, addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t sx_reg_readw(void *opaque, target_phys_addr_t addr)
>> +{
>> + //CG14State *s = opaque;
>> + int val;
>> +
>> + printf("SX readw reg " TARGET_FMT_plx "\n", addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + val = 0;
>> + break;
>> + }
>> + return val;
>> +}
>> +
>> +static void sx_reg_writew(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + //CG14State *s = opaque;
>> +
>> + printf("SX writew %04x to reg " TARGET_FMT_plx "\n", val, addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +static uint32_t sx_reg_readl(void *opaque, target_phys_addr_t addr)
>> +{
>> + //CG14State *s = opaque;
>> + int val;
>> +
>> + printf("SX readl reg " TARGET_FMT_plx "\n", addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + val = 0;
>> + break;
>> + }
>> + return val;
>> +}
>> +
>> +static void sx_reg_writel(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + //CG14State *s = opaque;
>> +
>> + printf("SX writel %08x to reg " TARGET_FMT_plx "\n", val, addr);
>> +
>> + switch (addr & 0xffff) {
>> + default:
>> + break;
>> + }
>> +}
>> +
>> +static CPUReadMemoryFunc *sx_reg_read[3] = {
>> + sx_reg_readb,
>> + sx_reg_readw,
>> + sx_reg_readl,
>> +};
>> +
>> +static CPUWriteMemoryFunc *sx_reg_write[3] = {
>> + sx_reg_writeb,
>> + sx_reg_writew,
>> + sx_reg_writel,
>> +};
>> +
>> +/*********************/
>> +
>> +static uint32_t bad_mem_read(void *opaque, target_phys_addr_t addr)
>> +{
>> + printf("Bad read from " TARGET_FMT_plx "\n", addr);
>> + //cpu_abort(cpu_single_env, "bad ram read access at " TARGET_FMT_plx
>> "\n", addr);
>> + return 0;
>> +}
>> +static void bad_mem_write(void *opaque, target_phys_addr_t addr, uint32_t
>> val)
>> +{
>> + printf("Bad write of 0x%02x to " TARGET_FMT_plx "\n", val, addr);
>> + //cpu_abort(cpu_single_env, "bad ram write access at " TARGET_FMT_plx
>> "\n", addr);
>> +}
>> +static CPUReadMemoryFunc *bad_memr[3] = { bad_mem_read, bad_mem_read,
>> bad_mem_read };
>> +static CPUWriteMemoryFunc *bad_memw[3] = { bad_mem_write, bad_mem_write,
>> bad_mem_write };
>> +
>> +void cg14_init(target_phys_addr_t ctrl_base, target_phys_addr_t vram_base,
>> + uint32_t vram_size)
>> +{
>> +// DeviceState *dev;
>> +// SysBusDevice *s;
>> +
>> +// dev = qdev_create(NULL, "SUNW,cg14");
>> +// qdev_init(dev);
>> +// s = sysbus_from_qdev(dev);
>> +//}
>> +
>> +//static void cg14_init1(SysBusDevice *dev)
>> +//{
>> + CG14State *s;// = FROM_SYSBUS(CG14State, dev);
>> + ram_addr_t vram_offset;
>> + uint8_t *vram;
>> + int ctrl_memory, vram_memory;
>> + int sx_registers;
>> + int bad_mem;
>> +
>> + s = qemu_mallocz(sizeof(CG14State));
>> +
>> + vram_offset = qemu_ram_alloc(vram_size);
>> + vram = qemu_get_ram_ptr(vram_offset);
>> +
>> + s->vram = vram;
>> + s->vram_amask = vram_size - 1;
>> +
>> + ctrl_memory = cpu_register_io_memory(cg14_reg_read, cg14_reg_write, s);
>> + cpu_register_physical_memory_offset(ctrl_base, CG14_REG_SIZE,
>> ctrl_memory, ctrl_base);
>> +
>> + vram_memory = cpu_register_io_memory(cg14_vram_read, cg14_vram_write,
>> s);
>> + cpu_register_physical_memory_offset(vram_base, CG14_VMEM_SLOTSIZE,
>> vram_memory, vram_base);
>> +
>> + s->ds = graphic_console_init(cg14_update_display,
>> + cg14_invalidate_display,
>> + cg14_screen_dump, NULL, s);
>> +
>> + s->width = 640;
>> + s->height = 480;
>> + qemu_console_resize(s->ds, s->width, s->height);
>> +
>> + /* SX or SPAM (Sun Pixel Arithmetic Memory) */
>> + sx_registers = cpu_register_io_memory(sx_reg_read, sx_reg_write, s);
>> + cpu_register_physical_memory(0xf80000000ULL, 0x2000, sx_registers);
>> +
>> + bad_mem = cpu_register_io_memory(bad_memr, bad_memw, s);
>> + /* missing vsimms */
>> + cpu_register_physical_memory_offset(0x90000000, 0x2000, bad_mem,
>> 0x90000000);
>> + cpu_register_physical_memory_offset(0x94000000, 0x2000, bad_mem,
>> 0x94000000);
>> + cpu_register_physical_memory_offset(0x98000000, 0x2000, bad_mem,
>> 0x98000000);
>
> Can't we just have more VSIMMS? The empty_slot device may be useful here.
And btw, VSIMMs addresses may currently overlap with RAM. Maybe we
should keep "SS-20" (and SS-10) compatible with original, and rename
the current machine definition to "SS-20qemu" or SS-20-60G?
>
>> + /* DBRI (audio) */
>> + cpu_register_physical_memory_offset(0xEE0001000ULL, 0x10000, bad_mem,
>> 0xE0001000);
>
> Please add a new DBRI device ;-).
Or maybe just a field in hwdef + empty_slot? :-)
>
>> +}
>> +
>> +/* save to file */
>> +static void cg14_screen_dump(void *opaque, const char *filename)
>> +{
>> + CG14State *s = opaque;
>> + FILE *f;
>> + int y, pixmode, linesize;
>> + void *buf;
>> + uint8_t *pix;
>> +
>> + f = fopen(filename, "wb");
>> + if (!f) {
>> + return;
>> + }
>> + fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
>> +
>> + linesize = s->width * 3;
>> + buf = qemu_mallocz(linesize);
>> + pix = s->vram;
>> +
>> + switch (s->ctrl.mcr & MCR_PIXMODE_MASK) {
>> + case MCR_PIXMODE_32:
>> + pixmode = 32;
>> + break;
>> + case MCR_PIXMODE_16:
>> + pixmode = 16;
>> + break;
>> + case MCR_PIXMODE_8:
>> + default:
>> + pixmode = 8;
>> + break;
>> + }
>> +
>> + for (y=0; y<s->height; y++) {
>> + // cg14_draw_line24_bgr(s, buf, pix, pixmode);
>> + fwrite(buf, 1, linesize, f);
>> + pix += s->width * (pixmode / 8);
>> + }
>> +
>> + qemu_free(buf);
>> + fclose(f);
>> +}
>>
>>
>
--
Regards,
Artyom Tarasenko
solaris/sparc under qemu blog: http://tyom.blogspot.com/