1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_sgi_gbe.c,v 1.29 2005/11/13 00:14:09 debug Exp $ |
* $Id: dev_sgi_gbe.c,v 1.35 2006/12/30 13:30:59 debug Exp $ |
29 |
* |
* |
30 |
* SGI "gbe", graphics controller. Framebuffer. |
* SGI "gbe", graphics controller. Framebuffer. |
31 |
* Loosely inspired by Linux code. |
* Loosely inspired by Linux code. |
96 |
int tweaked = 1; |
int tweaked = 1; |
97 |
|
|
98 |
#ifdef MTE_TEST |
#ifdef MTE_TEST |
99 |
|
/* Actually just a return, but this fools the Compaq compiler... */ |
100 |
|
if (cpu != NULL) |
101 |
return; |
return; |
102 |
#endif |
#endif |
103 |
|
|
126 |
if (tweaked) { |
if (tweaked) { |
127 |
/* Tweaked (linear) mode: */ |
/* Tweaked (linear) mode: */ |
128 |
|
|
129 |
/* Copy data from this 64KB physical RAM block to the framebuffer: */ |
/* |
130 |
/* NOTE: Copy it in smaller chunks than 64KB, in case the framebuffer |
* Copy data from this 64KB physical RAM block to the |
131 |
device can optimize away portions that aren't modified that way */ |
* framebuffer: |
132 |
|
* |
133 |
|
* NOTE: Copy it in smaller chunks than 64KB, in case |
134 |
|
* the framebuffer device can optimize away |
135 |
|
* portions that aren't modified that way. |
136 |
|
*/ |
137 |
copy_len = sizeof(buf); |
copy_len = sizeof(buf); |
138 |
copy_offset = 0; |
copy_offset = 0; |
139 |
|
|
140 |
while (on_screen && copy_offset < 65536) { |
while (on_screen && copy_offset < 65536) { |
141 |
if (old_fb_offset + copy_len > d->xres * d->yres * d->bitdepth / 8) { |
if (old_fb_offset + copy_len > (uint64_t) |
142 |
copy_len = d->xres * d->yres * d->bitdepth / 8 - old_fb_offset; |
(d->xres * d->yres * d->bitdepth / 8)) { |
143 |
|
copy_len = d->xres * d->yres * |
144 |
|
d->bitdepth / 8 - old_fb_offset; |
145 |
/* Stop after copying this block... */ |
/* Stop after copying this block... */ |
146 |
on_screen = 0; |
on_screen = 0; |
147 |
} |
} |
158 |
old_fb_offset += sizeof(buf); |
old_fb_offset += sizeof(buf); |
159 |
} |
} |
160 |
} else { |
} else { |
161 |
/* This is for non-tweaked (tiled) mode. Not really tested |
/* This is for non-tweaked (tiled) mode. Not really |
162 |
with correct image data, but might work: */ |
tested with correct image data, but might work: */ |
163 |
|
|
164 |
lines_to_copy = 128; |
lines_to_copy = 128; |
165 |
if (ybase + lines_to_copy > d->yres) |
if (ybase + lines_to_copy > d->yres) |
207 |
/* |
/* |
208 |
* dev_sgi_gbe_access(): |
* dev_sgi_gbe_access(): |
209 |
*/ |
*/ |
210 |
int dev_sgi_gbe_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_gbe) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
211 |
{ |
{ |
212 |
struct sgi_gbe_data *d = extra; |
struct sgi_gbe_data *d = extra; |
213 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
217 |
|
|
218 |
#ifdef GBE_DEBUG |
#ifdef GBE_DEBUG |
219 |
if (writeflag == MEM_WRITE) |
if (writeflag == MEM_WRITE) |
220 |
debug("[ sgi_gbe: DEBUG: write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata); |
debug("[ sgi_gbe: DEBUG: write to address 0x%llx, data" |
221 |
|
"=0x%llx ]\n", (long long)relative_addr, (long long)idata); |
222 |
#endif |
#endif |
223 |
|
|
224 |
switch (relative_addr) { |
switch (relative_addr) { |
269 |
else { |
else { |
270 |
/* bit 31 = freeze, 23..12 = cury, 11.0 = curx */ |
/* bit 31 = freeze, 23..12 = cury, 11.0 = curx */ |
271 |
odata = ((random() % (d->yres + 10)) << 12) |
odata = ((random() % (d->yres + 10)) << 12) |
272 |
+ (random() % (d->xres + 10)) + (d->freeze? ((uint32_t)1 << 31) : 0); |
+ (random() % (d->xres + 10)) + |
273 |
|
(d->freeze? ((uint32_t)1 << 31) : 0); |
274 |
odata = random(); /* testhack for the ip32 prom */ |
odata = random(); /* testhack for the ip32 prom */ |
275 |
} |
} |
276 |
break; |
break; |
277 |
|
|
278 |
case 0x10004: /* vt_xymax, according to Linux */ |
case 0x10004: /* vt_xymax, according to Linux */ |
279 |
odata = ((d->yres-1) << 12) + d->xres-1; /* ... 12 bits maxy, 12 bits maxx. */ |
odata = ((d->yres-1) << 12) + d->xres-1; |
280 |
|
/* ... 12 bits maxy, 12 bits maxx. */ |
281 |
break; |
break; |
282 |
|
|
283 |
case 0x10034: /* vt_hpixen, according to Linux */ |
case 0x10034: /* vt_hpixen, according to Linux */ |
284 |
odata = (0 << 12) + d->xres-1; /* ... 12 bits on, 12 bits off. */ |
odata = (0 << 12) + d->xres-1; |
285 |
|
/* ... 12 bits on, 12 bits off. */ |
286 |
break; |
break; |
287 |
|
|
288 |
case 0x10038: /* vt_vpixen, according to Linux */ |
case 0x10038: /* vt_vpixen, according to Linux */ |
289 |
odata = (0 << 12) + d->yres-1; /* ... 12 bits on, 12 bits off. */ |
odata = (0 << 12) + d->yres-1; |
290 |
|
/* ... 12 bits on, 12 bits off. */ |
291 |
break; |
break; |
292 |
|
|
293 |
case 0x20004: |
case 0x20004: |
298 |
break; |
break; |
299 |
|
|
300 |
case 0x30000: /* normal plane ctrl 0 */ |
case 0x30000: /* normal plane ctrl 0 */ |
301 |
/* bit 15 = fifo reset, 14..13 = depth, 12..5 = tile width, 4..0 = rhs */ |
/* bit 15 = fifo reset, 14..13 = depth, |
302 |
|
12..5 = tile width, 4..0 = rhs */ |
303 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
304 |
d->plane0ctrl = idata; |
d->plane0ctrl = idata; |
305 |
d->bitdepth = 8 << ((d->plane0ctrl >> 13) & 3); |
d->bitdepth = 8 << ((d->plane0ctrl >> 13) & 3); |
306 |
debug("[ sgi_gbe: setting color depth to %i bits ]\n", d->bitdepth); |
debug("[ sgi_gbe: setting color depth to %i bits ]\n", |
307 |
|
d->bitdepth); |
308 |
if (d->bitdepth != 8) |
if (d->bitdepth != 8) |
309 |
fatal("sgi_gbe: warning: bitdepth %i not really implemented yet\n", d->bitdepth); |
fatal("sgi_gbe: warning: bitdepth %i not " |
310 |
|
"really implemented yet\n", d->bitdepth); |
311 |
} else |
} else |
312 |
odata = d->plane0ctrl; |
odata = d->plane0ctrl; |
313 |
break; |
break; |
320 |
break; |
break; |
321 |
|
|
322 |
case 0x3000c: /* normal plane ctrl 3 */ |
case 0x3000c: /* normal plane ctrl 3 */ |
323 |
/* Writes to 3000c should be readable back at 30008? At least bit 0 (dma) */ |
/* |
324 |
/* ctrl 3: Bits 31..9 = tile table pointer bits, Bit 1 = linear, Bit 0 = dma */ |
* Writes to 3000c should be readable back at 30008? |
325 |
|
* At least bit 0 (dma) ctrl 3. |
326 |
|
* |
327 |
|
* Bits 31..9 = tile table pointer bits, |
328 |
|
* Bit 1 = linear |
329 |
|
* Bit 0 = dma |
330 |
|
*/ |
331 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
332 |
d->frm_control = idata; |
d->frm_control = idata; |
333 |
debug("[ sgi_gbe: frm_control = 0x%08x ]\n", d->frm_control); |
debug("[ sgi_gbe: frm_control = 0x%08x ]\n", |
334 |
|
d->frm_control); |
335 |
} else |
} else |
336 |
odata = d->frm_control; |
odata = d->frm_control; |
337 |
break; |
break; |
344 |
break; |
break; |
345 |
|
|
346 |
/* |
/* |
347 |
* Linux/sgimips seems to write color palette data to offset 0x50000 - 0x503xx, |
* Linux/sgimips seems to write color palette data to offset 0x50000 |
348 |
* and gamma correction data to 0x60000 - 0x603ff, as 32-bit values at addresses |
* to 0x503xx, and gamma correction data to 0x60000 - 0x603ff, as |
349 |
* divisible by 4 (formated as 0xrrggbb00). |
* 32-bit values at addresses divisible by 4 (formated as 0xrrggbb00). |
350 |
* |
* |
351 |
* sgio2fb: initializing |
* sgio2fb: initializing |
352 |
* sgio2fb: I/O at 0xffffffffb6000000 |
* sgio2fb: I/O at 0xffffffffb6000000 |
382 |
d->fb_data->rgb_palette[color_nr * 3 + 2] = b; |
d->fb_data->rgb_palette[color_nr * 3 + 2] = b; |
383 |
|
|
384 |
if (r != old_r || g != old_g || b != old_b) { |
if (r != old_r || g != old_g || b != old_b) { |
385 |
/* If the palette has been changed, the entire image needs to be redrawn... :-/ */ |
/* If the palette has been changed, the entire |
386 |
|
image needs to be redrawn... :-/ */ |
387 |
d->fb_data->update_x1 = 0; |
d->fb_data->update_x1 = 0; |
388 |
d->fb_data->update_x2 = d->fb_data->xsize - 1; |
d->fb_data->update_x2 = d->fb_data->xsize - 1; |
389 |
d->fb_data->update_y1 = 0; |
d->fb_data->update_y1 = 0; |
393 |
} |
} |
394 |
|
|
395 |
if (writeflag == MEM_WRITE) |
if (writeflag == MEM_WRITE) |
396 |
debug("[ sgi_gbe: unimplemented write to address 0x%llx, data=0x%llx ]\n", (long long)relative_addr, (long long)idata); |
debug("[ sgi_gbe: unimplemented write to address " |
397 |
|
"0x%llx, data=0x%llx ]\n", |
398 |
|
(long long)relative_addr, (long long)idata); |
399 |
else |
else |
400 |
debug("[ sgi_gbe: unimplemented read from address 0x%llx ]\n", (long long)relative_addr); |
debug("[ sgi_gbe: unimplemented read from address " |
401 |
|
"0x%llx ]\n", (long long)relative_addr); |
402 |
} |
} |
403 |
|
|
404 |
if (writeflag == MEM_READ) { |
if (writeflag == MEM_READ) { |
405 |
#ifdef GBE_DEBUG |
#ifdef GBE_DEBUG |
406 |
debug("[ sgi_gbe: DEBUG: read from address 0x%llx: 0x%llx ]\n", (long long)relative_addr, (long long)odata); |
debug("[ sgi_gbe: DEBUG: read from address 0x%llx: 0x%llx ]\n", |
407 |
|
(long long)relative_addr, (long long)odata); |
408 |
#endif |
#endif |
409 |
memory_writemax64(cpu, data, len, odata); |
memory_writemax64(cpu, data, len, odata); |
410 |
} |
} |
443 |
|
|
444 |
memory_device_register(mem, "sgi_gbe", baseaddr, DEV_SGI_GBE_LENGTH, |
memory_device_register(mem, "sgi_gbe", baseaddr, DEV_SGI_GBE_LENGTH, |
445 |
dev_sgi_gbe_access, d, DM_DEFAULT, NULL); |
dev_sgi_gbe_access, d, DM_DEFAULT, NULL); |
446 |
machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18); |
machine_add_tickfunction(machine, dev_sgi_gbe_tick, d, 18, 0.0); |
447 |
} |
} |
448 |
|
|