Revision 9eb08a43

b/Makefile
319 319
BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
320 320
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
321 321
acpi-dsdt.aml q35-acpi-dsdt.aml \
322
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \
322
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
323 323
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
324 324
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
325 325
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
b/default-configs/sparc-softmmu.mak
10 10
CONFIG_PCNET_COMMON=y
11 11
CONFIG_LANCE=y
12 12
CONFIG_TCX=y
13
CONFIG_CG3=y
13 14
CONFIG_SLAVIO=y
14 15
CONFIG_CS4231=y
15 16
CONFIG_GRLIB=y
b/hw/display/Makefile.objs
28 28
obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o
29 29
obj-$(CONFIG_SM501) += sm501.o
30 30
obj-$(CONFIG_TCX) += tcx.o
31
obj-$(CONFIG_CG3) += cg3.o
31 32

  
32 33
obj-$(CONFIG_VGA) += vga.o
33 34

  
b/hw/display/cg3.c
1
/*
2
 * QEMU CG3 Frame buffer
3
 *
4
 * Copyright (c) 2012 Bob Breuer
5
 * Copyright (c) 2013 Mark Cave-Ayland
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25

  
26
#include "qemu-common.h"
27
#include "qemu/error-report.h"
28
#include "ui/console.h"
29
#include "hw/sysbus.h"
30
#include "hw/loader.h"
31

  
32
/* Change to 1 to enable debugging */
33
#define DEBUG_CG3 0
34

  
35
#define CG3_ROM_FILE  "QEMU,cgthree.bin"
36
#define FCODE_MAX_ROM_SIZE 0x10000
37

  
38
#define CG3_REG_SIZE            0x20
39

  
40
#define CG3_REG_BT458_ADDR      0x0
41
#define CG3_REG_BT458_COLMAP    0x4
42
#define CG3_REG_FBC_CTRL        0x10
43
#define CG3_REG_FBC_STATUS      0x11
44
#define CG3_REG_FBC_CURSTART    0x12
45
#define CG3_REG_FBC_CUREND      0x13
46
#define CG3_REG_FBC_VCTRL       0x14
47

  
48
/* Control register flags */
49
#define CG3_CR_ENABLE_INTS      0x80
50

  
51
/* Status register flags */
52
#define CG3_SR_PENDING_INT      0x80
53
#define CG3_SR_1152_900_76_B    0x60
54
#define CG3_SR_ID_COLOR         0x01
55

  
56
#define CG3_VRAM_SIZE 0x100000
57
#define CG3_VRAM_OFFSET 0x800000
58

  
59
#define DPRINTF(fmt, ...) do { \
60
    if (DEBUG_CG3) { \
61
        printf("CG3: " fmt , ## __VA_ARGS__); \
62
    } \
63
} while (0);
64

  
65
#define TYPE_CG3 "cgthree"
66
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
67

  
68
typedef struct CG3State {
69
    SysBusDevice parent_obj;
70

  
71
    QemuConsole *con;
72
    qemu_irq irq;
73
    hwaddr prom_addr;
74
    MemoryRegion vram_mem;
75
    MemoryRegion rom;
76
    MemoryRegion reg;
77
    uint32_t vram_size;
78
    int full_update;
79
    uint8_t regs[16];
80
    uint8_t r[256], g[256], b[256];
81
    uint16_t width, height, depth;
82
    uint8_t dac_index, dac_state;
83
} CG3State;
84

  
85
static void cg3_update_display(void *opaque)
86
{
87
    CG3State *s = opaque;
88
    DisplaySurface *surface = qemu_console_surface(s->con);
89
    const uint8_t *pix;
90
    uint32_t *data;
91
    uint32_t dval;
92
    int x, y, y_start;
93
    unsigned int width, height;
94
    ram_addr_t page, page_min, page_max;
95

  
96
    if (surface_bits_per_pixel(surface) != 32) {
97
        return;
98
    }
99
    width = s->width;
100
    height = s->height;
101

  
102
    y_start = -1;
103
    page_min = -1;
104
    page_max = 0;
105
    page = 0;
106
    pix = memory_region_get_ram_ptr(&s->vram_mem);
107
    data = (uint32_t *)surface_data(surface);
108

  
109
    for (y = 0; y < height; y++) {
110
        int update = s->full_update;
111

  
112
        page = (y * width) & TARGET_PAGE_MASK;
113
        update |= memory_region_get_dirty(&s->vram_mem, page, page + width,
114
                                          DIRTY_MEMORY_VGA);
115
        if (update) {
116
            if (y_start < 0) {
117
                y_start = y;
118
            }
119
            if (page < page_min) {
120
                page_min = page;
121
            }
122
            if (page > page_max) {
123
                page_max = page;
124
            }
125

  
126
            for (x = 0; x < width; x++) {
127
                dval = *pix++;
128
                dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval];
129
                *data++ = dval;
130
            }
131
        } else {
132
            if (y_start >= 0) {
133
                dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
134
                y_start = -1;
135
            }
136
            pix += width;
137
            data += width;
138
        }
139
    }
140
    s->full_update = 0;
141
    if (y_start >= 0) {
142
        dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
143
    }
144
    if (page_max >= page_min) {
145
        memory_region_reset_dirty(&s->vram_mem,
146
                              page_min, page_max - page_min + TARGET_PAGE_SIZE,
147
                              DIRTY_MEMORY_VGA);
148
    }
149
    /* vsync interrupt? */
150
    if (s->regs[0] & CG3_CR_ENABLE_INTS) {
151
        s->regs[1] |= CG3_SR_PENDING_INT;
152
        qemu_irq_raise(s->irq);
153
    }
154
}
155

  
156
static void cg3_invalidate_display(void *opaque)
157
{
158
    CG3State *s = opaque;
159

  
160
    memory_region_set_dirty(&s->vram_mem, 0, CG3_VRAM_SIZE);
161
}
162

  
163
static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
164
{
165
    CG3State *s = opaque;
166
    int val;
167

  
168
    switch (addr) {
169
    case CG3_REG_BT458_ADDR:
170
    case CG3_REG_BT458_COLMAP:
171
        val = 0;
172
        break;
173
    case CG3_REG_FBC_CTRL:
174
        val = s->regs[0];
175
        break;
176
    case CG3_REG_FBC_STATUS:
177
        /* monitor ID 6, board type = 1 (color) */
178
        val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
179
        break;
180
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
181
        val = s->regs[addr - 0x10];
182
        break;
183
    default:
184
        qemu_log_mask(LOG_UNIMP,
185
                  "cg3: Unimplemented register read "
186
                  "reg 0x%" HWADDR_PRIx " size 0x%x\n",
187
                  addr, size);
188
        val = 0;
189
        break;
190
    }
191
    DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr);
192
    return val;
193
}
194

  
195
static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
196
                          unsigned size)
197
{
198
    CG3State *s = opaque;
199
    uint8_t regval;
200
    int i;
201

  
202
    DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n",
203
            val, addr, size);
204

  
205
    switch (addr) {
206
    case CG3_REG_BT458_ADDR:
207
        s->dac_index = val;
208
        s->dac_state = 0;
209
        break;
210
    case CG3_REG_BT458_COLMAP:
211
        /* This register can be written to as either a long word or a byte */
212
        if (size == 1) {
213
            val <<= 24;
214
        }
215

  
216
        for (i = 0; i < size; i++) {
217
            regval = val >> 24;
218

  
219
            switch (s->dac_state) {
220
            case 0:
221
                s->r[s->dac_index] = regval;
222
                s->dac_state++;
223
                break;
224
            case 1:
225
                s->g[s->dac_index] = regval;
226
                s->dac_state++;
227
                break;
228
            case 2:
229
                s->b[s->dac_index] = regval;
230
                /* Index autoincrement */
231
                s->dac_index = (s->dac_index + 1) & 0xff;
232
            default:
233
                s->dac_state = 0;
234
                break;
235
            }
236
            val <<= 8;
237
        }
238
        s->full_update = 1;
239
        break;
240
    case CG3_REG_FBC_CTRL:
241
        s->regs[0] = val;
242
        break;
243
    case CG3_REG_FBC_STATUS:
244
        if (s->regs[1] & CG3_SR_PENDING_INT) {
245
            /* clear interrupt */
246
            s->regs[1] &= ~CG3_SR_PENDING_INT;
247
            qemu_irq_lower(s->irq);
248
        }
249
        break;
250
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
251
        s->regs[addr - 0x10] = val;
252
        break;
253
    default:
254
        qemu_log_mask(LOG_UNIMP,
255
                  "cg3: Unimplemented register write "
256
                  "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
257
                  addr, size, val);
258
        break;
259
    }
260
}
261

  
262
static const MemoryRegionOps cg3_reg_ops = {
263
    .read = cg3_reg_read,
264
    .write = cg3_reg_write,
265
    .endianness = DEVICE_NATIVE_ENDIAN,
266
    .valid = {
267
        .min_access_size = 1,
268
        .max_access_size = 4,
269
    },
270
};
271

  
272
static const GraphicHwOps cg3_ops = {
273
    .invalidate = cg3_invalidate_display,
274
    .gfx_update = cg3_update_display,
275
};
276

  
277
static void cg3_realizefn(DeviceState *dev, Error **errp)
278
{
279
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
280
    CG3State *s = CG3(dev);
281
    int ret;
282
    char *fcode_filename;
283

  
284
    /* FCode ROM */
285
    memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
286
    vmstate_register_ram_global(&s->rom);
287
    memory_region_set_readonly(&s->rom, true);
288
    sysbus_init_mmio(sbd, &s->rom);
289

  
290
    fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
291
    if (fcode_filename) {
292
        ret = load_image_targphys(fcode_filename, s->prom_addr,
293
                                  FCODE_MAX_ROM_SIZE);
294
        if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
295
            error_report("cg3: could not load prom '%s'", CG3_ROM_FILE);
296
        }
297
    }
298

  
299
    memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
300
                          CG3_REG_SIZE);
301
    sysbus_init_mmio(sbd, &s->reg);
302

  
303
    memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
304
    vmstate_register_ram_global(&s->vram_mem);
305
    sysbus_init_mmio(sbd, &s->vram_mem);
306

  
307
    sysbus_init_irq(sbd, &s->irq);
308

  
309
    s->con = graphic_console_init(DEVICE(dev), &cg3_ops, s);
310
    qemu_console_resize(s->con, s->width, s->height);
311
}
312

  
313
static int vmstate_cg3_post_load(void *opaque, int version_id)
314
{
315
    CG3State *s = opaque;
316

  
317
    cg3_invalidate_display(s);
318

  
319
    return 0;
320
}
321

  
322
static const VMStateDescription vmstate_cg3 = {
323
    .name = "cg3",
324
    .version_id = 1,
325
    .minimum_version_id = 1,
326
    .post_load = vmstate_cg3_post_load,
327
    .fields    = (VMStateField[]) {
328
        VMSTATE_UINT16(height, CG3State),
329
        VMSTATE_UINT16(width, CG3State),
330
        VMSTATE_UINT16(depth, CG3State),
331
        VMSTATE_BUFFER(r, CG3State),
332
        VMSTATE_BUFFER(g, CG3State),
333
        VMSTATE_BUFFER(b, CG3State),
334
        VMSTATE_UINT8(dac_index, CG3State),
335
        VMSTATE_UINT8(dac_state, CG3State),
336
        VMSTATE_END_OF_LIST()
337
    }
338
};
339

  
340
static void cg3_reset(DeviceState *d)
341
{
342
    CG3State *s = CG3(d);
343

  
344
    /* Initialize palette */
345
    memset(s->r, 0, 256);
346
    memset(s->g, 0, 256);
347
    memset(s->b, 0, 256);
348

  
349
    s->dac_state = 0;
350
    s->full_update = 1;
351
    qemu_irq_lower(s->irq);
352
}
353

  
354
static Property cg3_properties[] = {
355
    DEFINE_PROP_UINT32("vram-size",    CG3State, vram_size, -1),
356
    DEFINE_PROP_UINT16("width",        CG3State, width,     -1),
357
    DEFINE_PROP_UINT16("height",       CG3State, height,    -1),
358
    DEFINE_PROP_UINT16("depth",        CG3State, depth,     -1),
359
    DEFINE_PROP_UINT64("prom-addr",    CG3State, prom_addr, -1),
360
    DEFINE_PROP_END_OF_LIST(),
361
};
362

  
363
static void cg3_class_init(ObjectClass *klass, void *data)
364
{
365
    DeviceClass *dc = DEVICE_CLASS(klass);
366

  
367
    dc->realize = cg3_realizefn;
368
    dc->reset = cg3_reset;
369
    dc->vmsd = &vmstate_cg3;
370
    dc->props = cg3_properties;
371
}
372

  
373
static const TypeInfo cg3_info = {
374
    .name          = TYPE_CG3,
375
    .parent        = TYPE_SYS_BUS_DEVICE,
376
    .instance_size = sizeof(CG3State),
377
    .class_init    = cg3_class_init,
378
};
379

  
380
static void cg3_register_types(void)
381
{
382
    type_register_static(&cg3_info);
383
}
384

  
385
type_init(cg3_register_types)
b/pc-bios/README
11 11
  firmware implementation. The goal is to implement a 100% IEEE
12 12
  1275-1994 (referred to as Open Firmware) compliant firmware.
13 13
  The included images for PowerPC (for 32 and 64 bit PPC CPUs),
14
  Sparc32 (including QEMU,tcx.bin) and Sparc64 are built from OpenBIOS SVN
15
  revision 1246.
14
  Sparc32 (including QEMU,tcx.bin and QEMU,cgthree.bin) and Sparc64 are built
15
  from OpenBIOS SVN revision 1246.
16 16

  
17 17
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
18 18
  implementation for certain IBM POWER hardware.  The sources are at

Also available in: Unified diff