qemu-devel
[Top][All Lists]
Advanced

[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 15:26:25 +0200

2010/5/29 Bob Breuer <address@hidden>:
> Artyom Tarasenko wrote:
>> 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?
>>
>>
> Probably won't be used without at least being in the firmware device
> tree.  One area that OpenBIOS could enhance would be a larger memory
> size option.  The real hardware was only available in 4M and 8M options,
> but the memory map allows for 16M.  OBP will identify a 16M VSIMM but
> won't do anything else with it, and with 16M of vram it would allow for
> a potential 2560x1600 32bit resolution.
>>>> 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.
>>>
> The cg14 was only an option for SS-20 and the rare SS-10SX, but not the
> regular SS-10, though the SS-10 chipset may have been capable of
> supporting it.  Each cg14 vsimm takes the place of a stick of memory
> with 2 slots physically capable of holding a vsimm.

The few SS-10 OBP versions I have probe for VSIMMs. So we need to put
either empty_slot (when the -nographics option is used) or VSIMMs
there.

> Is there a way to pass the framebuffer type and/or address to OpenBIOS?
> I would be inclined to have the SS-20 machine default to cg14 instead of
> TCX, but it will blow a hole in the support of more than 2G of emulated
> system ram.
>>>> +    /* 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.
>>>
> Chipset docs are hard to come by.  But here's what I've found:
>    "Sun-4M System Architecture" section A.II.3 briefly covers VSIMM and
> DSIMM size detection.
>    Linux kernel 2.6 drivers/video/cg14.c has most of the registers named.
>    US Patent 5815137 covers the cursor implementation, but it includes
> drawings which show the various color and lookup table muxing and
> blending capability.  I will not be implementing the cursor functionality.
>
>>>> +
>>>> +/*
>>>> + * 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.
>>>
>
> Hmm, interesting.  Might be cumbersome if the width isn't 1024 though.
>
>>>> + */
>>>> +
>>>> +#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.
>>>
>
> Yes, at least for 8bit mode.  The per-pixel xlut value offers a lot of
> flexibility that may be hard to speed up when fully implemented.  The
> hardware supports simultaneous true-color and palette lookups to
> generate 2 color values to blend together for every displayed pixel.
>
>>>> +            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.
>>>
> Each VSIMM would have it's own monitor attached.  Does Qemu and/or
> OpenBIOS support multiple displays?  I think the limit for a real SS-20
> is 5 displays - 2 VSIMMs and 3 GX/TGX cards.  I'll just go with
> empty_slot for the extras.
>>
>> 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?
>>
> Well, the real machines are limited to 512M, so dropping the framebuffer
> registers into the middle of the first 4G wasn't an issue back then.  I
> think the SX accelerator also limits the system and video memory to the
> lower 4G of address space.
>
>>>> +    /* 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? :-)
>>
> Yes, empty_slot should work fine.  I was trying to hack in enough to get
> it to boot, but no luck yet.

I have a trivial hack which allows booting. It wasn't interesting
before, but now it is,
cause with the hack Solaris 2.3 - 2.5.1 can be started in a single user mode.
Didn't check the multi-user yet. Will submit the patch.

> The cpu models are still lacking - with
> the SS-20 v2.25 rom, SuperSparc 61 fails before initializing the
> display, SuperSparc 60 has a data access error when trying to boot, and
> Ross 625 is mis-detected as an incompatible cpu type.

Yes, one MXCC register is missing in qemu SuperSPARCs with MXCC.
So, I prefer using CPUs without MXCC: "Ross RT620" and "TI SuperSparc 50".


-- 
Regards,
Artyom Tarasenko

solaris/sparc under qemu blog: http://tyom.blogspot.com/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]