Statistics
| Branch: | Revision:

root / hw / g364fb.c @ 3023f332

History | View | Annotate | Download (9.9 kB)

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 along
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20

    
21
#include "hw.h"
22
#include "mips.h"
23
#include "console.h"
24
#include "pixel_ops.h"
25

    
26
//#define DEBUG_G364
27

    
28
typedef struct G364State {
29
    unsigned int vram_size;
30
    uint8_t *vram_buffer;
31
    uint32_t ctla;
32
    uint8_t palette[256][3];
33
    /* display refresh support */
34
    DisplayState *ds;
35
    int graphic_mode;
36
    uint32_t scr_width, scr_height; /* in pixels */
37
} G364State;
38

    
39
/*
40
 * graphic modes
41
 */
42
#define BPP 8
43
#define PIXEL_WIDTH 8
44
#include "g364fb_template.h"
45
#undef BPP
46
#undef PIXEL_WIDTH
47

    
48
#define BPP 15
49
#define PIXEL_WIDTH 16
50
#include "g364fb_template.h"
51
#undef BPP
52
#undef PIXEL_WIDTH
53

    
54
#define BPP 16
55
#define PIXEL_WIDTH 16
56
#include "g364fb_template.h"
57
#undef BPP
58
#undef PIXEL_WIDTH
59

    
60
#define BPP 32
61
#define PIXEL_WIDTH 32
62
#include "g364fb_template.h"
63
#undef BPP
64
#undef PIXEL_WIDTH
65

    
66
#define REG_DISPLAYX 0x0918
67
#define REG_DISPLAYY 0x0940
68

    
69
#define CTLA_FORCE_BLANK 0x400
70

    
71
static void g364fb_draw_graphic(G364State *s, int full_update)
72
{
73
    switch (ds_get_bits_per_pixel(s->ds)) {
74
        case 8:
75
            g364fb_draw_graphic8(s, full_update);
76
            break;
77
        case 15:
78
            g364fb_draw_graphic15(s, full_update);
79
            break;
80
        case 16:
81
            g364fb_draw_graphic16(s, full_update);
82
            break;
83
        case 32:
84
            g364fb_draw_graphic32(s, full_update);
85
            break;
86
        default:
87
            printf("g364fb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds));
88
            return;
89
    }
90

    
91
    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
92
}
93

    
94
static void g364fb_draw_blank(G364State *s, int full_update)
95
{
96
    int i, w;
97
    uint8_t *d;
98

    
99
    if (!full_update)
100
        return;
101

    
102
    w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
103
    d = ds_get_data(s->ds);
104
    for(i = 0; i < s->scr_height; i++) {
105
        memset(d, 0, w);
106
        d += ds_get_linesize(s->ds);
107
    }
108

    
109
    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
110
}
111

    
112
#define GMODE_GRAPH 0
113
#define GMODE_BLANK 1
114

    
115
static void g364fb_update_display(void *opaque)
116
{
117
    G364State *s = opaque;
118
    int full_update, graphic_mode;
119

    
120
    if (s->scr_width == 0 || s->scr_height == 0)
121
        return;
122

    
123
    if (s->ctla & CTLA_FORCE_BLANK)
124
        graphic_mode = GMODE_BLANK;
125
    else
126
        graphic_mode = GMODE_GRAPH;
127
    full_update = 0;
128
    if (graphic_mode != s->graphic_mode) {
129
        s->graphic_mode = graphic_mode;
130
        full_update = 1;
131
    }
132
    if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) {
133
        qemu_console_resize(s->ds, s->scr_width, s->scr_height);
134
        full_update = 1;
135
    }
136
    switch(graphic_mode) {
137
        case GMODE_GRAPH:
138
            g364fb_draw_graphic(s, full_update);
139
            break;
140
        case GMODE_BLANK:
141
        default:
142
            g364fb_draw_blank(s, full_update);
143
            break;
144
    }
145
}
146

    
147
/* force a full display refresh */
148
static void g364fb_invalidate_display(void *opaque)
149
{
150
    G364State *s = opaque;
151
    s->graphic_mode = -1; /* force full update */
152
}
153

    
154
static void g364fb_reset(void *opaque)
155
{
156
    G364State *s = opaque;
157

    
158
    memset(s->palette, 0, sizeof(s->palette));
159
    s->scr_width = s->scr_height = 0;
160
    memset(s->vram_buffer, 0, s->vram_size);
161
    s->graphic_mode = -1; /* force full update */
162
}
163

    
164
static void g364fb_screen_dump(void *opaque, const char *filename)
165
{
166
    G364State *s = opaque;
167
    int y, x;
168
    uint8_t index;
169
    uint8_t *data_buffer;
170
    FILE *f;
171

    
172
    f = fopen(filename, "wb");
173
    if (!f)
174
        return;
175

    
176
    data_buffer = s->vram_buffer;
177
    fprintf(f, "P6\n%d %d\n%d\n",
178
        s->scr_width, s->scr_height, 255);
179
    for(y = 0; y < s->scr_height; y++)
180
        for(x = 0; x < s->scr_width; x++, data_buffer++) {
181
            index = *data_buffer;
182
            fputc(s->palette[index][0], f);
183
            fputc(s->palette[index][1], f);
184
            fputc(s->palette[index][2], f);
185
        }
186
    fclose(f);
187
}
188

    
189
/* called for accesses to io ports */
190
static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr)
191
{
192
    //G364State *s = opaque;
193
    uint32_t val;
194

    
195
    addr &= 0xffff;
196

    
197
    switch (addr) {
198
        default:
199
#ifdef DEBUG_G364
200
            printf("g364fb/ctrl: invalid read at [" TARGET_FMT_lx "]\n", addr);
201
#endif
202
            val = 0;
203
            break;
204
    }
205

    
206
#ifdef DEBUG_G364
207
    printf("g364fb/ctrl: read 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
208
#endif
209

    
210
    return val;
211
}
212

    
213
static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr)
214
{
215
    uint32_t v;
216
    v = g364fb_ctrl_readb(opaque, addr);
217
    v |= g364fb_ctrl_readb(opaque, addr + 1) << 8;
218
    return v;
219
}
220

    
221
static uint32_t g364fb_ctrl_readl(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
    v |= g364fb_ctrl_readb(opaque, addr + 2) << 16;
227
    v |= g364fb_ctrl_readb(opaque, addr + 3) << 24;
228
    return v;
229
}
230

    
231
static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
232
{
233
    G364State *s = opaque;
234

    
235
    addr &= 0xffff;
236

    
237
#ifdef DEBUG_G364
238
    printf("g364fb/ctrl: write 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
239
#endif
240

    
241
    if (addr < 0x0800) {
242
        /* color palette */
243
        int idx = addr >> 3;
244
        int c = addr & 7;
245
        if (c < 3)
246
            s->palette[idx][c] = (uint8_t)val;
247
    } else {
248
        switch (addr) {
249
            case REG_DISPLAYX:
250
                s->scr_width = (s->scr_width & 0xfffffc03) | (val << 2);
251
                break;
252
            case REG_DISPLAYX + 1:
253
                s->scr_width = (s->scr_width & 0xfffc03ff) | (val << 10);
254
                break;
255
            case REG_DISPLAYY:
256
                s->scr_height = (s->scr_height & 0xffffff80) | (val >> 1);
257
                break;
258
            case REG_DISPLAYY + 1:
259
                s->scr_height = (s->scr_height & 0xffff801f) | (val << 7);
260
                break;
261
            default:
262
#ifdef DEBUG_G364
263
                printf("g364fb/ctrl: invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
264
#endif
265
                break;
266
        }
267
    }
268
    s->graphic_mode = -1; /* force full update */
269
}
270

    
271
static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
272
{
273
    g364fb_ctrl_writeb(opaque, addr, val & 0xff);
274
    g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff);
275
}
276

    
277
static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
278
{
279
    g364fb_ctrl_writeb(opaque, addr, val & 0xff);
280
    g364fb_ctrl_writeb(opaque, addr + 1, (val >> 8) & 0xff);
281
    g364fb_ctrl_writeb(opaque, addr + 2, (val >> 16) & 0xff);
282
    g364fb_ctrl_writeb(opaque, addr + 3, (val >> 24) & 0xff);
283
}
284

    
285
static CPUReadMemoryFunc *g364fb_ctrl_read[3] = {
286
    g364fb_ctrl_readb,
287
    g364fb_ctrl_readw,
288
    g364fb_ctrl_readl,
289
};
290

    
291
static CPUWriteMemoryFunc *g364fb_ctrl_write[3] = {
292
    g364fb_ctrl_writeb,
293
    g364fb_ctrl_writew,
294
    g364fb_ctrl_writel,
295
};
296

    
297
/* called for accesses to video ram */
298
static uint32_t g364fb_mem_readb(void *opaque, target_phys_addr_t addr)
299
{
300
    G364State *s = opaque;
301

    
302
    return s->vram_buffer[addr];
303
}
304

    
305
static uint32_t g364fb_mem_readw(void *opaque, target_phys_addr_t addr)
306
{
307
    uint32_t v;
308
    v = g364fb_mem_readb(opaque, addr);
309
    v |= g364fb_mem_readb(opaque, addr + 1) << 8;
310
    return v;
311
}
312

    
313
static uint32_t g364fb_mem_readl(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
    v |= g364fb_mem_readb(opaque, addr + 2) << 16;
319
    v |= g364fb_mem_readb(opaque, addr + 3) << 24;
320
    return v;
321
}
322

    
323
static void g364fb_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
324
{
325
    G364State *s = opaque;
326

    
327
    s->vram_buffer[addr] = val;
328
}
329

    
330
static void g364fb_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
331
{
332
    g364fb_mem_writeb(opaque, addr, val & 0xff);
333
    g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
334
}
335

    
336
static void g364fb_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
337
{
338
    g364fb_mem_writeb(opaque, addr, val & 0xff);
339
    g364fb_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
340
    g364fb_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
341
    g364fb_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
342
}
343

    
344
static CPUReadMemoryFunc *g364fb_mem_read[3] = {
345
    g364fb_mem_readb,
346
    g364fb_mem_readw,
347
    g364fb_mem_readl,
348
};
349

    
350
static CPUWriteMemoryFunc *g364fb_mem_write[3] = {
351
    g364fb_mem_writeb,
352
    g364fb_mem_writew,
353
    g364fb_mem_writel,
354
};
355

    
356
int g364fb_mm_init(int vram_size, int it_shift,
357
                   target_phys_addr_t vram_base, target_phys_addr_t ctrl_base)
358
{
359
    G364State *s;
360
    int io_vram, io_ctrl;
361

    
362
    s = qemu_mallocz(sizeof(G364State));
363
    if (!s)
364
        return -1;
365

    
366
    s->vram_size = vram_size;
367
    s->vram_buffer = qemu_mallocz(s->vram_size);
368

    
369
    qemu_register_reset(g364fb_reset, s);
370
    g364fb_reset(s);
371

    
372
    s->ds = graphic_console_init(g364fb_update_display,
373
                                 g364fb_invalidate_display,
374
                                 g364fb_screen_dump, NULL, s);
375

    
376
    io_vram = cpu_register_io_memory(0, g364fb_mem_read, g364fb_mem_write, s);
377
    cpu_register_physical_memory(vram_base, vram_size, io_vram);
378

    
379
    io_ctrl = cpu_register_io_memory(0, g364fb_ctrl_read, g364fb_ctrl_write, s);
380
    cpu_register_physical_memory(ctrl_base, 0x10000, io_ctrl);
381

    
382
    return 0;
383
}