/[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 4 - (hide annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 12113 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.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     * $Id: dev_sgi_gbe.c,v 1.21 2005/02/11 09:29:48 debug Exp $
29     *
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    
51     #define GBE_DEFAULT_XRES 640
52     #define GBE_DEFAULT_YRES 480
53    
54    
55     struct sgi_gbe_data {
56     int xres, yres;
57    
58     uint32_t control; /* 0x00000 */
59     uint32_t dotclock; /* 0x00004 */
60     uint32_t i2c; /* 0x00008 */
61     uint32_t i2cfp; /* 0x00010 */
62     uint32_t plane0ctrl; /* 0x30000 */
63     uint32_t frm_control; /* 0x3000c */
64     int freeze;
65    
66     int bitdepth;
67     struct vfb_data *fb_data;
68     };
69    
70    
71     /*
72     * dev_sgi_gbe_tick():
73     *
74     * Every now and then, copy data from the framebuffer in normal ram
75     * to the actual framebuffer (which will then redraw the window).
76     * TODO: This is utterly slow, even slower than the normal framebuffer
77     * which is really slow as it is.
78     *
79     * frm_control (bits 31..9) is a pointer to an array of uint16_t.
80     * These numbers (when << 16 bits) are pointers to the tiles. Tiles are
81     * 512x128 in 8-bit mode, 256x128 in 16-bit mode, and 128x128 in 32-bit mode.
82     */
83     void dev_sgi_gbe_tick(struct cpu *cpu, void *extra)
84     {
85     struct sgi_gbe_data *d = extra;
86     int tile_nr = 0, on_screen = 1, xbase = 0, ybase = 0;
87     unsigned char tileptr_buf[sizeof(uint16_t)];
88     uint64_t tileptr, tiletable;
89     int lines_to_copy, pixels_per_line, y;
90     unsigned char buf[16384]; /* must be power of 2, at most 65536 */
91     int copy_len, copy_offset;
92     uint64_t old_fb_offset = 0;
93     int tweaked = 1;
94    
95     /* debug("[ sgi_gbe: dev_sgi_gbe_tick() ]\n"); */
96    
97     tiletable = (d->frm_control & 0xfffffe00);
98     if (tiletable == 0)
99     on_screen = 0;
100    
101     while (on_screen) {
102     /* Get pointer to a tile: */
103     cpu->memory_rw(cpu, cpu->mem, tiletable +
104     sizeof(tileptr_buf) * tile_nr,
105     tileptr_buf, sizeof(tileptr_buf), MEM_READ,
106     NO_EXCEPTIONS | PHYSICAL);
107     tileptr = 256 * tileptr_buf[0] + tileptr_buf[1];
108     /* TODO: endianness */
109     tileptr <<= 16;
110    
111     /* tileptr is now a physical address of a tile. */
112     debug("[ sgi_gbe: tile_nr = %2i, tileptr = 0x%08lx, xbase"
113     " = %4i, ybase = %4i ]\n", tile_nr, tileptr, xbase, ybase);
114    
115     if (tweaked) {
116     /* Tweaked (linear) mode: */
117    
118     /* Copy data from this 64KB physical RAM block to the framebuffer: */
119     /* NOTE: Copy it in smaller chunks than 64KB, in case the framebuffer
120     device can optimize away portions that aren't modified that way */
121     copy_len = sizeof(buf);
122     copy_offset = 0;
123    
124     while (on_screen && copy_offset < 65536) {
125     if (old_fb_offset + copy_len > d->xres * d->yres * d->bitdepth / 8) {
126     copy_len = d->xres * d->yres * d->bitdepth / 8 - old_fb_offset;
127     /* Stop after copying this block... */
128     on_screen = 0;
129     }
130    
131     /* debug("old_fb_offset = %08x copylen"
132     "=%i\n", old_fb_offset, copy_len); */
133    
134     cpu->memory_rw(cpu, cpu->mem, tileptr +
135     copy_offset, buf, copy_len, MEM_READ,
136     NO_EXCEPTIONS | PHYSICAL);
137     dev_fb_access(cpu, cpu->mem, old_fb_offset,
138     buf, copy_len, MEM_WRITE, d->fb_data);
139     copy_offset += sizeof(buf);
140     old_fb_offset += sizeof(buf);
141     }
142     } else {
143     /* This is for non-tweaked (tiled) mode. Not really tested
144     with correct image data, but might work: */
145    
146     lines_to_copy = 128;
147     if (ybase + lines_to_copy > d->yres)
148     lines_to_copy = d->yres - ybase;
149    
150     pixels_per_line = 512 * 8 / d->bitdepth;
151     if (xbase + pixels_per_line > d->xres)
152     pixels_per_line = d->xres - xbase;
153    
154     for (y=0; y<lines_to_copy; y++) {
155     cpu->memory_rw(cpu, cpu->mem, tileptr + 512 * y,
156     buf, pixels_per_line * d->bitdepth / 8,
157     MEM_READ, NO_EXCEPTIONS | PHYSICAL);
158    
159     dev_fb_access(cpu, cpu->mem, ((ybase + y) *
160     d->xres + xbase) * d->bitdepth / 8,
161     buf, pixels_per_line * d->bitdepth / 8,
162     MEM_WRITE, d->fb_data);
163     }
164    
165     /* Go to next tile: */
166     xbase += (512 * 8 / d->bitdepth);
167     if (xbase >= d->xres) {
168     xbase = 0;
169     ybase += 128;
170     if (ybase >= d->yres)
171     on_screen = 0;
172     }
173     }
174    
175     /* Go to next tile: */
176     tile_nr ++;
177     }
178    
179     /* debug("[ sgi_gbe: dev_sgi_gbe_tick() end]\n"); */
180     }
181    
182    
183     /*
184     * dev_sgi_gbe_access():
185     */
186     int dev_sgi_gbe_access(struct cpu *cpu, struct memory *mem,
187     uint64_t relative_addr, unsigned char *data, size_t len,
188     int writeflag, void *extra)
189     {
190     struct sgi_gbe_data *d = extra;
191     uint64_t idata = 0, odata = 0;
192    
193     idata = memory_readmax64(cpu, data, len);
194    
195     #ifdef GBE_DEBUG
196     if (writeflag == MEM_WRITE)
197     debug("[ sgi_gbe: DEBUG: write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata);
198     #endif
199    
200     switch (relative_addr) {
201    
202     case 0x0:
203     if (writeflag == MEM_WRITE)
204     d->control = idata;
205     else
206     odata = d->control;
207     break;
208    
209     case 0x4:
210     if (writeflag == MEM_WRITE)
211     d->dotclock = idata;
212     else
213     odata = d->dotclock;
214     break;
215    
216     case 0x8: /* i2c? */
217     /*
218     * "CRT I2C control".
219     *
220     * I'm not sure what this does. It isn't really commented
221     * in the linux sources. The IP32 prom writes the values
222     * 0x03, 0x01, and then 0x00 to this address, and then
223     * reads back a value.
224     */
225     if (writeflag == MEM_WRITE) {
226     d->i2c = idata;
227     } else {
228     odata = d->i2c;
229     odata |= 1; /* ? The IP32 prom wants this? */
230     }
231     break;
232    
233     case 0x10: /* i2cfp, flat panel control */
234     if (writeflag == MEM_WRITE) {
235     d->i2cfp = idata;
236     } else {
237     odata = d->i2cfp;
238     odata |= 1; /* ? The IP32 prom wants this? */
239     }
240     break;
241    
242     case 0x10000: /* vt_xy, according to Linux */
243     if (writeflag == MEM_WRITE)
244     d->freeze = idata & ((uint32_t)1<<31)? 1 : 0;
245     else {
246     /* bit 31 = freeze, 23..12 = cury, 11.0 = curx */
247     odata = ((random() % (d->yres + 10)) << 12)
248     + (random() % (d->xres + 10)) + (d->freeze? ((uint32_t)1 << 31) : 0);
249     odata = random(); /* testhack for the ip32 prom */
250     }
251     break;
252    
253     case 0x10004: /* vt_xymax, according to Linux */
254     odata = ((d->yres-1) << 12) + d->xres-1; /* ... 12 bits maxy, 12 bits maxx. */
255     break;
256    
257     case 0x10034: /* vt_hpixen, according to Linux */
258     odata = (0 << 12) + d->xres-1; /* ... 12 bits on, 12 bits off. */
259     break;
260    
261     case 0x10038: /* vt_vpixen, according to Linux */
262     odata = (0 << 12) + d->yres-1; /* ... 12 bits on, 12 bits off. */
263     break;
264    
265     case 0x20004:
266     odata = random(); /* IP32 prom test hack. TODO */
267     /* IRIX wants 0x20, it seems. */
268     if (random() & 1)
269     odata = 0x20;
270     break;
271    
272     case 0x30000: /* normal plane ctrl 0 */
273     /* bit 15 = fifo reset, 14..13 = depth, 12..5 = tile width, 4..0 = rhs */
274     if (writeflag == MEM_WRITE) {
275     d->plane0ctrl = idata;
276     d->bitdepth = 8 << ((d->plane0ctrl >> 13) & 3);
277     debug("[ sgi_gbe: setting color depth to %i bits ]\n", d->bitdepth);
278     if (d->bitdepth != 8)
279     fatal("sgi_gbe: warning: bitdepth %i not really implemented yet\n", d->bitdepth);
280     } else
281     odata = d->plane0ctrl;
282     break;
283    
284     case 0x30008: /* normal plane ctrl 2 */
285     odata = random(); /* IP32 prom test hack. TODO */
286     /* IRIX wants 0x20, it seems. */
287     if (random() & 1)
288     odata = 0x20;
289     break;
290    
291     case 0x3000c: /* normal plane ctrl 3 */
292     /* Writes to 3000c should be readable back at 30008? At least bit 0 (dma) */
293     /* ctrl 3: Bits 31..9 = tile table pointer bits, Bit 1 = linear, Bit 0 = dma */
294     if (writeflag == MEM_WRITE) {
295     d->frm_control = idata;
296     debug("[ sgi_gbe: frm_control = 0x%08x ]\n", d->frm_control);
297     } else
298     odata = d->frm_control;
299     break;
300    
301     case 0x40000:
302     odata = random(); /* IP32 prom test hack. TODO */
303     /* IRIX wants 0x20, it seems. */
304     if (random() & 1)
305     odata = 0x20;
306     break;
307    
308     /*
309     * Linux/sgimips seems to write color palette data to offset 0x50000 - 0x503xx,
310     * and gamma correction data to 0x60000 - 0x603ff, as 32-bit values at addresses
311     * divisible by 4 (formated as 0xrrggbb00).
312     *
313     * sgio2fb: initializing
314     * sgio2fb: I/O at 0xffffffffb6000000
315     * sgio2fb: tiles at ffffffffa2ef5000
316     * sgio2fb: framebuffer at ffffffffa1000000
317     * sgio2fb: 8192kB memory
318     * Console: switching to colour frame buffer device 80x30
319     */
320    
321     default:
322     /* Gamma correction: */
323     if (relative_addr >= 0x60000 && relative_addr <= 0x603ff) {
324     /* ignore gamma correction for now */
325     break;
326     }
327    
328     /* RGB Palette: */
329     if (relative_addr >= 0x50000 && relative_addr <= 0x503ff) {
330     int color_nr, r, g, b;
331     int old_r, old_g, old_b;
332    
333     color_nr = (relative_addr & 0x3ff) / 4;
334     r = (idata >> 24) & 0xff;
335     g = (idata >> 16) & 0xff;
336     b = (idata >> 8) & 0xff;
337    
338     old_r = d->fb_data->rgb_palette[color_nr * 3 + 0];
339     old_g = d->fb_data->rgb_palette[color_nr * 3 + 1];
340     old_b = d->fb_data->rgb_palette[color_nr * 3 + 2];
341    
342     d->fb_data->rgb_palette[color_nr * 3 + 0] = r;
343     d->fb_data->rgb_palette[color_nr * 3 + 1] = g;
344     d->fb_data->rgb_palette[color_nr * 3 + 2] = b;
345    
346     if (r != old_r || g != old_g || b != old_b) {
347     /* If the palette has been changed, the entire image needs to be redrawn... :-/ */
348     d->fb_data->update_x1 = 0;
349     d->fb_data->update_x2 = d->fb_data->xsize - 1;
350     d->fb_data->update_y1 = 0;
351     d->fb_data->update_y2 = d->fb_data->ysize - 1;
352     }
353     break;
354     }
355    
356     if (writeflag == MEM_WRITE)
357     debug("[ sgi_gbe: unimplemented write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata);
358     else
359     debug("[ sgi_gbe: unimplemented read from address 0x%llx ]\n", (long long)relative_addr);
360     }
361    
362     if (writeflag == MEM_READ) {
363     #ifdef GBE_DEBUG
364     debug("[ sgi_gbe: DEBUG: read from address 0x%llx: 0x%llx ]\n", (long long)relative_addr, (long long)odata);
365     #endif
366     memory_writemax64(cpu, data, len, odata);
367     }
368    
369     return 1;
370     }
371    
372    
373     /*
374     * dev_sgi_gbe_init():
375     */
376     void dev_sgi_gbe_init(struct machine *machine, struct memory *mem,
377     uint64_t baseaddr)
378     {
379     struct sgi_gbe_data *d;
380    
381     d = malloc(sizeof(struct sgi_gbe_data));
382     if (d == NULL) {
383     fprintf(stderr, "out of memory\n");
384     exit(1);
385     }
386     memset(d, 0, sizeof(struct sgi_gbe_data));
387     d->xres = GBE_DEFAULT_XRES;
388     d->yres = GBE_DEFAULT_YRES;
389     d->bitdepth = 8;
390     d->control = 0x20aa000; /* or 0x00000001? */
391     d->fb_data = dev_fb_init(machine, mem, FAKE_GBE_FB_ADDRESS,
392     VFB_GENERIC, d->xres, d->yres, d->xres, d->yres, 8, "SGI GBE", 0);
393     set_grayscale_palette(d->fb_data, 256);
394    
395     memory_device_register(mem, "sgi_gbe", baseaddr, DEV_SGI_GBE_LENGTH,
396     dev_sgi_gbe_access, d, MEM_DEFAULT, NULL);
397     machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18);
398     }
399    

  ViewVC Help
Powered by ViewVC 1.1.26