/[gxemul]/trunk/src/devices/dev_sgi_gbe.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/devices/dev_sgi_gbe.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18 - (hide annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 12449 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


1 dpavlin 4 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 18 * $Id: dev_sgi_gbe.c,v 1.28 2005/10/26 14:37:04 debug Exp $
29 dpavlin 4 *
30     * SGI "gbe", graphics controller. Framebuffer.
31     * Loosely inspired by Linux code.
32     */
33    
34     #include <stdio.h>
35     #include <stdlib.h>
36     #include <string.h>
37    
38     #include "console.h"
39     #include "cpu.h"
40     #include "devices.h"
41     #include "machine.h"
42     #include "memory.h"
43     #include "misc.h"
44    
45    
46     /* Let's hope nothing is there already... */
47     #define FAKE_GBE_FB_ADDRESS 0x38000000
48    
49     #define GBE_DEBUG
50 dpavlin 12 /* #define debug fatal */
51 dpavlin 4
52 dpavlin 14 #define MTE_TEST
53 dpavlin 12
54 dpavlin 4 #define GBE_DEFAULT_XRES 640
55     #define GBE_DEFAULT_YRES 480
56    
57    
58     struct sgi_gbe_data {
59     int xres, yres;
60    
61     uint32_t control; /* 0x00000 */
62     uint32_t dotclock; /* 0x00004 */
63     uint32_t i2c; /* 0x00008 */
64     uint32_t i2cfp; /* 0x00010 */
65     uint32_t plane0ctrl; /* 0x30000 */
66     uint32_t frm_control; /* 0x3000c */
67     int freeze;
68    
69     int bitdepth;
70     struct vfb_data *fb_data;
71     };
72    
73    
74     /*
75     * dev_sgi_gbe_tick():
76     *
77     * Every now and then, copy data from the framebuffer in normal ram
78     * to the actual framebuffer (which will then redraw the window).
79     * TODO: This is utterly slow, even slower than the normal framebuffer
80     * which is really slow as it is.
81     *
82     * frm_control (bits 31..9) is a pointer to an array of uint16_t.
83     * These numbers (when << 16 bits) are pointers to the tiles. Tiles are
84     * 512x128 in 8-bit mode, 256x128 in 16-bit mode, and 128x128 in 32-bit mode.
85     */
86     void dev_sgi_gbe_tick(struct cpu *cpu, void *extra)
87     {
88     struct sgi_gbe_data *d = extra;
89     int tile_nr = 0, on_screen = 1, xbase = 0, ybase = 0;
90     unsigned char tileptr_buf[sizeof(uint16_t)];
91     uint64_t tileptr, tiletable;
92     int lines_to_copy, pixels_per_line, y;
93 dpavlin 12 unsigned char buf[16384]; /* must be power of 2, at most 65536 */
94 dpavlin 4 int copy_len, copy_offset;
95     uint64_t old_fb_offset = 0;
96     int tweaked = 1;
97    
98 dpavlin 12 #ifdef MTE_TEST
99     return;
100     #endif
101    
102 dpavlin 4 /* debug("[ sgi_gbe: dev_sgi_gbe_tick() ]\n"); */
103    
104     tiletable = (d->frm_control & 0xfffffe00);
105     if (tiletable == 0)
106     on_screen = 0;
107 dpavlin 12 /*
108     tweaked = 0;
109     */
110 dpavlin 4 while (on_screen) {
111     /* Get pointer to a tile: */
112     cpu->memory_rw(cpu, cpu->mem, tiletable +
113     sizeof(tileptr_buf) * tile_nr,
114     tileptr_buf, sizeof(tileptr_buf), MEM_READ,
115     NO_EXCEPTIONS | PHYSICAL);
116     tileptr = 256 * tileptr_buf[0] + tileptr_buf[1];
117     /* TODO: endianness */
118     tileptr <<= 16;
119    
120     /* tileptr is now a physical address of a tile. */
121     debug("[ sgi_gbe: tile_nr = %2i, tileptr = 0x%08lx, xbase"
122     " = %4i, ybase = %4i ]\n", tile_nr, tileptr, xbase, ybase);
123    
124     if (tweaked) {
125     /* Tweaked (linear) mode: */
126    
127     /* Copy data from this 64KB physical RAM block to the framebuffer: */
128     /* NOTE: Copy it in smaller chunks than 64KB, in case the framebuffer
129     device can optimize away portions that aren't modified that way */
130     copy_len = sizeof(buf);
131     copy_offset = 0;
132    
133     while (on_screen && copy_offset < 65536) {
134     if (old_fb_offset + copy_len > d->xres * d->yres * d->bitdepth / 8) {
135     copy_len = d->xres * d->yres * d->bitdepth / 8 - old_fb_offset;
136     /* Stop after copying this block... */
137     on_screen = 0;
138     }
139    
140     /* debug("old_fb_offset = %08x copylen"
141     "=%i\n", old_fb_offset, copy_len); */
142    
143     cpu->memory_rw(cpu, cpu->mem, tileptr +
144     copy_offset, buf, copy_len, MEM_READ,
145     NO_EXCEPTIONS | PHYSICAL);
146     dev_fb_access(cpu, cpu->mem, old_fb_offset,
147     buf, copy_len, MEM_WRITE, d->fb_data);
148     copy_offset += sizeof(buf);
149     old_fb_offset += sizeof(buf);
150     }
151     } else {
152     /* This is for non-tweaked (tiled) mode. Not really tested
153     with correct image data, but might work: */
154    
155     lines_to_copy = 128;
156     if (ybase + lines_to_copy > d->yres)
157     lines_to_copy = d->yres - ybase;
158    
159     pixels_per_line = 512 * 8 / d->bitdepth;
160     if (xbase + pixels_per_line > d->xres)
161     pixels_per_line = d->xres - xbase;
162    
163     for (y=0; y<lines_to_copy; y++) {
164     cpu->memory_rw(cpu, cpu->mem, tileptr + 512 * y,
165     buf, pixels_per_line * d->bitdepth / 8,
166     MEM_READ, NO_EXCEPTIONS | PHYSICAL);
167 dpavlin 12 #if 0
168     {
169     int i;
170     for (i=0; i<pixels_per_line * d->bitdepth / 8; i++)
171     buf[i] ^= (random() & 0x20);
172     }
173     #endif
174 dpavlin 4 dev_fb_access(cpu, cpu->mem, ((ybase + y) *
175     d->xres + xbase) * d->bitdepth / 8,
176     buf, pixels_per_line * d->bitdepth / 8,
177     MEM_WRITE, d->fb_data);
178     }
179    
180     /* Go to next tile: */
181     xbase += (512 * 8 / d->bitdepth);
182     if (xbase >= d->xres) {
183     xbase = 0;
184     ybase += 128;
185     if (ybase >= d->yres)
186     on_screen = 0;
187     }
188     }
189    
190     /* Go to next tile: */
191     tile_nr ++;
192     }
193    
194     /* debug("[ sgi_gbe: dev_sgi_gbe_tick() end]\n"); */
195     }
196    
197    
198     /*
199     * dev_sgi_gbe_access():
200     */
201     int dev_sgi_gbe_access(struct cpu *cpu, struct memory *mem,
202     uint64_t relative_addr, unsigned char *data, size_t len,
203     int writeflag, void *extra)
204     {
205     struct sgi_gbe_data *d = extra;
206     uint64_t idata = 0, odata = 0;
207    
208 dpavlin 18 if (writeflag == MEM_WRITE)
209     idata = memory_readmax64(cpu, data, len);
210 dpavlin 4
211     #ifdef GBE_DEBUG
212     if (writeflag == MEM_WRITE)
213     debug("[ sgi_gbe: DEBUG: write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata);
214     #endif
215    
216     switch (relative_addr) {
217    
218     case 0x0:
219     if (writeflag == MEM_WRITE)
220     d->control = idata;
221     else
222     odata = d->control;
223     break;
224    
225     case 0x4:
226     if (writeflag == MEM_WRITE)
227     d->dotclock = idata;
228     else
229     odata = d->dotclock;
230     break;
231    
232     case 0x8: /* i2c? */
233     /*
234     * "CRT I2C control".
235     *
236     * I'm not sure what this does. It isn't really commented
237     * in the linux sources. The IP32 prom writes the values
238     * 0x03, 0x01, and then 0x00 to this address, and then
239     * reads back a value.
240     */
241     if (writeflag == MEM_WRITE) {
242     d->i2c = idata;
243     } else {
244     odata = d->i2c;
245     odata |= 1; /* ? The IP32 prom wants this? */
246     }
247     break;
248    
249     case 0x10: /* i2cfp, flat panel control */
250     if (writeflag == MEM_WRITE) {
251     d->i2cfp = idata;
252     } else {
253     odata = d->i2cfp;
254     odata |= 1; /* ? The IP32 prom wants this? */
255     }
256     break;
257    
258     case 0x10000: /* vt_xy, according to Linux */
259     if (writeflag == MEM_WRITE)
260     d->freeze = idata & ((uint32_t)1<<31)? 1 : 0;
261     else {
262     /* bit 31 = freeze, 23..12 = cury, 11.0 = curx */
263     odata = ((random() % (d->yres + 10)) << 12)
264     + (random() % (d->xres + 10)) + (d->freeze? ((uint32_t)1 << 31) : 0);
265     odata = random(); /* testhack for the ip32 prom */
266     }
267     break;
268    
269     case 0x10004: /* vt_xymax, according to Linux */
270     odata = ((d->yres-1) << 12) + d->xres-1; /* ... 12 bits maxy, 12 bits maxx. */
271     break;
272    
273     case 0x10034: /* vt_hpixen, according to Linux */
274     odata = (0 << 12) + d->xres-1; /* ... 12 bits on, 12 bits off. */
275     break;
276    
277     case 0x10038: /* vt_vpixen, according to Linux */
278     odata = (0 << 12) + d->yres-1; /* ... 12 bits on, 12 bits off. */
279     break;
280    
281     case 0x20004:
282     odata = random(); /* IP32 prom test hack. TODO */
283     /* IRIX wants 0x20, it seems. */
284     if (random() & 1)
285     odata = 0x20;
286     break;
287    
288     case 0x30000: /* normal plane ctrl 0 */
289     /* bit 15 = fifo reset, 14..13 = depth, 12..5 = tile width, 4..0 = rhs */
290     if (writeflag == MEM_WRITE) {
291     d->plane0ctrl = idata;
292     d->bitdepth = 8 << ((d->plane0ctrl >> 13) & 3);
293     debug("[ sgi_gbe: setting color depth to %i bits ]\n", d->bitdepth);
294     if (d->bitdepth != 8)
295     fatal("sgi_gbe: warning: bitdepth %i not really implemented yet\n", d->bitdepth);
296     } else
297     odata = d->plane0ctrl;
298     break;
299    
300     case 0x30008: /* normal plane ctrl 2 */
301     odata = random(); /* IP32 prom test hack. TODO */
302     /* IRIX wants 0x20, it seems. */
303     if (random() & 1)
304     odata = 0x20;
305     break;
306    
307     case 0x3000c: /* normal plane ctrl 3 */
308     /* Writes to 3000c should be readable back at 30008? At least bit 0 (dma) */
309     /* ctrl 3: Bits 31..9 = tile table pointer bits, Bit 1 = linear, Bit 0 = dma */
310     if (writeflag == MEM_WRITE) {
311     d->frm_control = idata;
312     debug("[ sgi_gbe: frm_control = 0x%08x ]\n", d->frm_control);
313     } else
314     odata = d->frm_control;
315     break;
316    
317     case 0x40000:
318     odata = random(); /* IP32 prom test hack. TODO */
319     /* IRIX wants 0x20, it seems. */
320     if (random() & 1)
321     odata = 0x20;
322     break;
323    
324     /*
325     * Linux/sgimips seems to write color palette data to offset 0x50000 - 0x503xx,
326     * and gamma correction data to 0x60000 - 0x603ff, as 32-bit values at addresses
327     * divisible by 4 (formated as 0xrrggbb00).
328     *
329     * sgio2fb: initializing
330     * sgio2fb: I/O at 0xffffffffb6000000
331     * sgio2fb: tiles at ffffffffa2ef5000
332     * sgio2fb: framebuffer at ffffffffa1000000
333     * sgio2fb: 8192kB memory
334     * Console: switching to colour frame buffer device 80x30
335     */
336    
337     default:
338     /* Gamma correction: */
339     if (relative_addr >= 0x60000 && relative_addr <= 0x603ff) {
340     /* ignore gamma correction for now */
341     break;
342     }
343    
344     /* RGB Palette: */
345     if (relative_addr >= 0x50000 && relative_addr <= 0x503ff) {
346     int color_nr, r, g, b;
347     int old_r, old_g, old_b;
348    
349     color_nr = (relative_addr & 0x3ff) / 4;
350     r = (idata >> 24) & 0xff;
351     g = (idata >> 16) & 0xff;
352     b = (idata >> 8) & 0xff;
353    
354     old_r = d->fb_data->rgb_palette[color_nr * 3 + 0];
355     old_g = d->fb_data->rgb_palette[color_nr * 3 + 1];
356     old_b = d->fb_data->rgb_palette[color_nr * 3 + 2];
357    
358     d->fb_data->rgb_palette[color_nr * 3 + 0] = r;
359     d->fb_data->rgb_palette[color_nr * 3 + 1] = g;
360     d->fb_data->rgb_palette[color_nr * 3 + 2] = b;
361    
362     if (r != old_r || g != old_g || b != old_b) {
363     /* If the palette has been changed, the entire image needs to be redrawn... :-/ */
364     d->fb_data->update_x1 = 0;
365     d->fb_data->update_x2 = d->fb_data->xsize - 1;
366     d->fb_data->update_y1 = 0;
367     d->fb_data->update_y2 = d->fb_data->ysize - 1;
368     }
369     break;
370     }
371    
372     if (writeflag == MEM_WRITE)
373     debug("[ sgi_gbe: unimplemented write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata);
374     else
375     debug("[ sgi_gbe: unimplemented read from address 0x%llx ]\n", (long long)relative_addr);
376     }
377    
378     if (writeflag == MEM_READ) {
379     #ifdef GBE_DEBUG
380     debug("[ sgi_gbe: DEBUG: read from address 0x%llx: 0x%llx ]\n", (long long)relative_addr, (long long)odata);
381     #endif
382     memory_writemax64(cpu, data, len, odata);
383     }
384    
385     return 1;
386     }
387    
388    
389     /*
390     * dev_sgi_gbe_init():
391     */
392     void dev_sgi_gbe_init(struct machine *machine, struct memory *mem,
393     uint64_t baseaddr)
394     {
395     struct sgi_gbe_data *d;
396    
397     d = malloc(sizeof(struct sgi_gbe_data));
398     if (d == NULL) {
399     fprintf(stderr, "out of memory\n");
400     exit(1);
401     }
402     memset(d, 0, sizeof(struct sgi_gbe_data));
403 dpavlin 14
404     /* 640x480 for Linux: */
405 dpavlin 4 d->xres = GBE_DEFAULT_XRES;
406     d->yres = GBE_DEFAULT_YRES;
407     d->bitdepth = 8;
408     d->control = 0x20aa000; /* or 0x00000001? */
409 dpavlin 14
410     /* 1280x1024 for booting the O2's PROM: */
411     d->xres = 1280; d->yres = 1024;
412    
413 dpavlin 4 d->fb_data = dev_fb_init(machine, mem, FAKE_GBE_FB_ADDRESS,
414 dpavlin 12 VFB_GENERIC, d->xres, d->yres, d->xres, d->yres, 8, "SGI GBE");
415 dpavlin 4 set_grayscale_palette(d->fb_data, 256);
416    
417     memory_device_register(mem, "sgi_gbe", baseaddr, DEV_SGI_GBE_LENGTH,
418     dev_sgi_gbe_access, d, MEM_DEFAULT, NULL);
419     machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18);
420     }
421    

  ViewVC Help
Powered by ViewVC 1.1.26