/[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 20 - (hide 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 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 20 * $Id: dev_sgi_gbe.c,v 1.29 2005/11/13 00:14:09 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 dpavlin 20 dev_sgi_gbe_access, d, DM_DEFAULT, NULL);
419 dpavlin 4 machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18);
420     }
421    

  ViewVC Help
Powered by ViewVC 1.1.26