/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 6 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 /*
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