/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 12448 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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.29 2005/11/13 00:14:09 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 /* #define debug fatal */
51
52 #define MTE_TEST
53
54 #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 unsigned char buf[16384]; /* must be power of 2, at most 65536 */
94 int copy_len, copy_offset;
95 uint64_t old_fb_offset = 0;
96 int tweaked = 1;
97
98 #ifdef MTE_TEST
99 return;
100 #endif
101
102 /* debug("[ sgi_gbe: dev_sgi_gbe_tick() ]\n"); */
103
104 tiletable = (d->frm_control & 0xfffffe00);
105 if (tiletable == 0)
106 on_screen = 0;
107 /*
108 tweaked = 0;
109 */
110 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 #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 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 if (writeflag == MEM_WRITE)
209 idata = memory_readmax64(cpu, data, len);
210
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
404 /* 640x480 for Linux: */
405 d->xres = GBE_DEFAULT_XRES;
406 d->yres = GBE_DEFAULT_YRES;
407 d->bitdepth = 8;
408 d->control = 0x20aa000; /* or 0x00000001? */
409
410 /* 1280x1024 for booting the O2's PROM: */
411 d->xres = 1280; d->yres = 1024;
412
413 d->fb_data = dev_fb_init(machine, mem, FAKE_GBE_FB_ADDRESS,
414 VFB_GENERIC, d->xres, d->yres, d->xres, d->yres, 8, "SGI GBE");
415 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, DM_DEFAULT, NULL);
419 machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18);
420 }
421

  ViewVC Help
Powered by ViewVC 1.1.26