graphical_console_init change (Stefano Stabellini)
[qemu] / hw / g364fb.c
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 }