/[gxemul]/upstream/0.4.4/src/devices/dev_px.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 /upstream/0.4.4/src/devices/dev_px.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (show annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 22880 byte(s)
0.4.4
1 /*
2 * Copyright (C) 2004-2007 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_px.c,v 1.36 2006/12/30 13:30:59 debug Exp $
29 *
30 * TURBOchannel Pixelstamp graphics device.
31 *
32 * PMAG-CA = PX
33 * PMAG-DA = PXG
34 * PMAG-EA = PXG+
35 * PMAG-FA = PXG+ TURBO
36 *
37 * See include/pxreg.h (and NetBSD's arch/pmax/dev/px.c) for more information.
38 *
39 * The emulation of this device is far from complete. Different pixelstamp
40 * boards are recognizes under different names depending on operating system:
41 *
42 * NetBSD/pmax: (works fine both with and without console on framebuffer)
43 * PMAG-CA: px0 at tc0 slot 0 offset 0x0: 2D, 4x1 stamp,
44 * 8 plane
45 * PMAG-DA: px0 at tc0 slot 0 offset 0x0: 3D, 4x1 stamp,
46 * 8 plane, 128KB SRAM
47 * PMAG-EA: (not supported)
48 * PMAG-FA: px0 at tc0 slot 0 offset 0x0: 3D, 5x2 stamp,
49 * 24 plane, 128KB SRAM
50 *
51 * Ultrix 4.2A rev 47: (usually crashes if the device is installed, but
52 * serial console is used)
53 * PMAG-CA: px0 at ibus0, pa0 (5x1 8+8+0+0)
54 * PMAG-DA: px0 at ibus0, pq0 (5x1 16+16+16+0 128KB)
55 * or (5x1 0+0+16+0 128KB)
56 * PMAG-EA: (not supported)
57 * PMAG-FA: px0 at ibus0, pq0 (5x2 24+24+16+16 128KB)
58 *
59 * Ultrix 4.2 rev 85: (usually crashes if the device is installed,
60 * but serial console is used)
61 * PMAG-CA: ga0 at ibus0, ga0 ( 8 planes 4x1 stamp )
62 * PMAG-DA: gq0 at ibus0, gq0 ( 8+8+16Z+0X plane 4x1 stamp )
63 * PMAG-EA: (not supported)
64 * PMAG-FA: gq0 at ibus0, gq0 ( 24+24+24Z+24X plane
65 * 5x2 stamp ) (crashes in serial console mode)
66 *
67 * TODO: A lot of stuff:
68 *
69 * Read http://www.mit.edu/afs/athena/system/pmax_ul3/srvd.73/sys/
70 * io/tc/gq.h
71 * and try to figure out the interrupt and memory management stuff.
72 *
73 * Color support: foreground, background, 8-bit palette?
74 * 2D and 3D stuff: polygons? shading?
75 * Don't use so many hardcoded values.
76 * Actually interpret the values in each command, don't just
77 * assume NetBSD/Ultrix usage.
78 * Factor out the DMA read (main memory vs sram).
79 * Interrupts?
80 * Make sure that everything works with both NetBSD and Ultrix.
81 */
82
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86
87 #include "cpu.h"
88 #include "devices.h"
89 #include "machine.h"
90 #include "memory.h"
91 #include "misc.h"
92
93 #include "pxreg.h"
94
95 #define PX_XSIZE 1280
96 #define PX_YSIZE 1024
97
98 /* #define PX_DEBUG */
99
100
101 /*
102 * dev_px_tick():
103 */
104 void dev_px_tick(struct cpu *cpu, void *extra)
105 {
106 #if 0
107 struct px_data *d = extra;
108
109 if (d->intr & STIC_INT_P_EN) /* or _WE ? */
110 INTERRUPT_ASSERT(d->irq);
111 #endif
112 }
113
114
115 /*
116 * px_readword():
117 *
118 * Helper function to read 32-bit words from DMA memory,
119 * to allow both little and big endian accesses.
120 * (DECstations probably only use little endian access,
121 * but endianness-independance is probably nice to have anyway.)
122 */
123 uint32_t px_readword(struct cpu *cpu, unsigned char *dma_buf, int ofs)
124 {
125 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
126 return dma_buf[ofs+0] + (dma_buf[ofs+1] << 8) +
127 (dma_buf[ofs+2] << 16) + (dma_buf[ofs+3] << 24);
128 else
129 return dma_buf[ofs+3] + (dma_buf[ofs+2] << 8) +
130 (dma_buf[ofs+1] << 16) + (dma_buf[ofs+0] << 24);
131 }
132
133
134 /*
135 * dev_px_dma():
136 *
137 * This routine performs a (fake) DMA transfer of STAMP commands
138 * and executes them.
139 *
140 * For the "PX" board, read from main memory (cpu->mem). For all other
141 * boards, read from the i860 SRAM portion of the device (d->sram).
142 */
143 void dev_px_dma(struct cpu *cpu, uint32_t sys_addr, struct px_data *d)
144 {
145 unsigned char dma_buf[32768];
146 size_t dma_len = sizeof(dma_buf);
147 int bytesperpixel;
148 uint32_t cmdword;
149
150 bytesperpixel = d->bitdepth >> 3;
151
152 dma_len = 56 * 4; /* TODO: this is just enough for NetBSD's
153 putchar */
154
155 if (d->type == DEV_PX_TYPE_PX) {
156 cpu->memory_rw(cpu, cpu->mem, sys_addr, dma_buf,
157 dma_len, MEM_READ, NO_EXCEPTIONS | PHYSICAL);
158 } else {
159 /* TODO: past end of sram? */
160 memmove(dma_buf, &d->sram[sys_addr & 0x1ffff], dma_len);
161 }
162
163 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
164 cmdword = dma_buf[0] + (dma_buf[1] << 8) +
165 (dma_buf[2] << 16) + (dma_buf[3] << 24);
166 else
167 cmdword = dma_buf[3] + (dma_buf[2] << 8) +
168 (dma_buf[1] << 16) + (dma_buf[0] << 24);
169
170 #ifdef PX_DEBUG
171 debug("[ px: dma from 0x%08x: ", (int)sys_addr);
172
173 debug("cmd=");
174 switch (cmdword & 0xf) {
175 case STAMP_CMD_POINTS: debug("points"); break;
176 case STAMP_CMD_LINES: debug("lines"); break;
177 case STAMP_CMD_TRIANGLES: debug("triangles"); break;
178 case STAMP_CMD_COPYSPANS: debug("copyspans"); break;
179 case STAMP_CMD_READSPANS: debug("readspans"); break;
180 case STAMP_CMD_WRITESPANS: debug("writespans"); break;
181 case STAMP_CMD_VIDEO: debug("video"); break;
182 default:
183 debug("0x%x (?)", cmdword & 0xf);
184 }
185
186 debug(",rgb=");
187 switch (cmdword & 0x30) {
188 case STAMP_RGB_NONE: debug("none"); break;
189 case STAMP_RGB_CONST: debug("const"); break;
190 case STAMP_RGB_FLAT: debug("flat"); break;
191 case STAMP_RGB_SMOOTH: debug("smooth"); break;
192 default:
193 debug("0x%x (?)", cmdword & 0x30);
194 }
195
196 debug(",z=");
197 switch (cmdword & 0xc0) {
198 case STAMP_Z_NONE: debug("none"); break;
199 case STAMP_Z_CONST: debug("const"); break;
200 case STAMP_Z_FLAT: debug("flat"); break;
201 case STAMP_Z_SMOOTH: debug("smooth"); break;
202 default:
203 debug("0x%x (?)", cmdword & 0xc0);
204 }
205
206 debug(",xy=");
207 switch (cmdword & 0x300) {
208 case STAMP_XY_NONE: debug("none"); break;
209 case STAMP_XY_PERPACKET: debug("perpacket"); break;
210 case STAMP_XY_PERPRIMATIVE: debug("perprimative"); break;
211 default:
212 debug("0x%x (?)", cmdword & 0x300);
213 }
214
215 debug(",lw=");
216 switch (cmdword & 0xc00) {
217 case STAMP_LW_NONE: debug("none"); break;
218 case STAMP_LW_PERPACKET: debug("perpacket"); break;
219 case STAMP_LW_PERPRIMATIVE: debug("perprimative"); break;
220 default:
221 debug("0x%x (?)", cmdword & 0xc00);
222 }
223
224 if (cmdword & STAMP_CLIPRECT)
225 debug(",CLIPRECT");
226 if (cmdword & STAMP_MESH)
227 debug(",MESH");
228 if (cmdword & STAMP_AALINE)
229 debug(",AALINE");
230 if (cmdword & STAMP_HS_EQUALS)
231 debug(",HS_EQUALS");
232
233 {
234 size_t i;
235 for (i=0; i<dma_len; i++)
236 debug(" %02x", dma_buf[i]);
237 }
238
239 debug(" ]\n");
240 #endif /* PX_DEBUG */
241
242 /* NetBSD and Ultrix copyspans */
243 if (cmdword == 0x405) {
244 uint32_t nspans, lw;
245 uint32_t spannr, ofs;
246 uint32_t span_len, span_src, span_dst;
247 /* unsigned char pixels[PX_XSIZE * 3]; */
248
249 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
250 nspans = dma_buf[4] + (dma_buf[5] << 8) +
251 (dma_buf[6] << 16) + (dma_buf[7] << 24);
252 else
253 nspans = dma_buf[7] + (dma_buf[6] << 8) +
254 (dma_buf[5] << 16) + (dma_buf[4] << 24);
255
256 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
257 lw = dma_buf[16] + (dma_buf[17] << 8) +
258 (dma_buf[18] << 16) + (dma_buf[19] << 24);
259 else
260 lw = dma_buf[19] + (dma_buf[18] << 8) +
261 (dma_buf[17] << 16) + (dma_buf[16] << 24);
262
263 nspans >>= 24;
264 /* Why not this? lw = (lw + 1) >> 2; */
265
266 #ifdef PX_DEBUG
267 debug("[ px: copyspans: nspans = %i, lw = %i ]\n", nspans, lw);
268 #endif
269
270 /* Reread copyspans command if it wasn't completely read: */
271 if (dma_len < 4*(5 + nspans*3)) {
272 dma_len = 4 * (5+nspans*3);
273 if (d->type == DEV_PX_TYPE_PX)
274 cpu->memory_rw(cpu, cpu->mem, sys_addr,
275 dma_buf, dma_len, MEM_READ,
276 NO_EXCEPTIONS | PHYSICAL);
277 else
278 memmove(dma_buf, &d->sram[sys_addr & 0x1ffff],
279 dma_len); /* TODO: past end of sram? */
280 }
281
282 ofs = 4*5;
283 for (spannr=0; spannr<nspans; spannr++) {
284 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
285 span_len = dma_buf[ofs+0] + (dma_buf[ofs+1] <<
286 8) + (dma_buf[ofs+2] << 16) +
287 (dma_buf[ofs+3] << 24);
288 else
289 span_len = dma_buf[ofs+3] + (dma_buf[ofs+2] <<
290 8) + (dma_buf[ofs+1] << 16) +
291 (dma_buf[ofs+0] << 24);
292 ofs += 4;
293
294 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
295 span_src = dma_buf[ofs+0] + (dma_buf[ofs+1] <<
296 8) + (dma_buf[ofs+2] << 16) +
297 (dma_buf[ofs+3] << 24);
298 else
299 span_src = dma_buf[ofs+3] + (dma_buf[ofs+2] <<
300 8) + (dma_buf[ofs+1] << 16) +
301 (dma_buf[ofs+0] << 24);
302 ofs += 4;
303
304 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
305 span_dst = dma_buf[ofs+0] + (dma_buf[ofs+1] <<
306 8) + (dma_buf[ofs+2] << 16) +
307 (dma_buf[ofs+3] << 24);
308 else
309 span_dst = dma_buf[ofs+3] + (dma_buf[ofs+2] <<
310 8) + (dma_buf[ofs+1] << 16) +
311 (dma_buf[ofs+0] << 24);
312 ofs += 4;
313
314 span_len >>= 3;
315 span_dst >>= 3;
316 span_src >>= 3;
317
318 if (span_len > PX_XSIZE)
319 span_len = PX_XSIZE;
320
321 /* debug(" span %i: len=%i src=%i dst=%i\n",
322 spannr, span_len, span_src, span_dst); */
323
324 memmove(d->vfb_data->framebuffer + span_dst *
325 PX_XSIZE * bytesperpixel, d->vfb_data->framebuffer
326 + span_src * PX_XSIZE * bytesperpixel, span_len *
327 bytesperpixel);
328
329 d->vfb_data->update_x1 = 0; d->vfb_data->update_x2 =
330 PX_XSIZE-1;
331 if ((int32_t)span_dst < d->vfb_data->update_y1)
332 d->vfb_data->update_y1 = span_dst;
333 if ((int32_t)span_dst > d->vfb_data->update_y2)
334 d->vfb_data->update_y2 = span_dst;
335 if ((int32_t)span_src < d->vfb_data->update_y1)
336 d->vfb_data->update_y1 = span_src;
337 if ((int32_t)span_src > d->vfb_data->update_y2)
338 d->vfb_data->update_y2 = span_src;
339 }
340 }
341
342 /* NetBSD and Ultrix erasecols/eraserows */
343 if (cmdword == 0x411) {
344 uint32_t v1, v2, attr;
345 int32_t lw;
346 int x,y,x2,y2;
347 int fb_y;
348 int bg_r, bg_g, bg_b;
349 unsigned char pixels[PX_XSIZE * 3];
350
351 lw = px_readword(cpu, dma_buf, 16);
352 attr = px_readword(cpu, dma_buf, 20);
353 v1 = px_readword(cpu, dma_buf, 24);
354 v2 = px_readword(cpu, dma_buf, 28);
355 #if 0
356 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
357 lw = dma_buf[16] + (dma_buf[17] << 8) +
358 (dma_buf[18] << 16) + (dma_buf[19] << 24);
359 else
360 lw = dma_buf[19] + (dma_buf[18] << 8) +
361 (dma_buf[17] << 16) + (dma_buf[16] << 24);
362
363 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
364 v1 = dma_buf[24] + (dma_buf[25] << 8) +
365 (dma_buf[26] << 16) + (dma_buf[27] << 24);
366 else
367 v1 = dma_buf[27] + (dma_buf[26] << 8) +
368 (dma_buf[25] << 16) + (dma_buf[24] << 24);
369
370 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
371 v2 = dma_buf[28] + (dma_buf[29] << 8) +
372 (dma_buf[30] << 16) + (dma_buf[31] << 24);
373 else
374 v2 = dma_buf[31] + (dma_buf[30] << 8) +
375 (dma_buf[29] << 16) + (dma_buf[28] << 24);
376 #endif
377 bg_r = (attr >> 16) & 255;
378 bg_g = (attr >> 8) & 255;
379 bg_b = attr & 255;
380 if (bg_r == 0)
381 bg_r = bg_g = bg_b = 0;
382 else
383 if (bg_r == 7)
384 bg_r = bg_g = bg_b = 192;
385 else
386 bg_r = bg_g = bg_b = 255;
387
388 v1 -= lw;
389 v2 -= lw;
390
391 x = (v1 >> 19) & 2047;
392 y = (v1 >> 3) & 1023;
393 x2 = (v2 >> 19) & 2047;
394 y2 = (v2 >> 3) & 1023;
395
396 lw = (lw + 1) >> 2;
397
398 if (x2 - x > PX_XSIZE)
399 x2 = PX_XSIZE;
400
401 #ifdef PX_DEBUG
402 debug("[ px: clear/fill: v1 = 0x%08x v2 = 0x%08x "
403 "lw=%i x=%i y=%i x2=%i y2=%i ]\n", (int)v1, (int)v2,
404 lw, x,y, x2,y2);
405 #endif
406 if (bytesperpixel == 3) {
407 int xi;
408 for (xi=0; xi<x2-x; xi++) {
409 /* TODO: rgb order? */
410 pixels[xi*3 + 0] = bg_r;
411 pixels[xi*3 + 1] = bg_g;
412 pixels[xi*3 + 2] = bg_b;
413 }
414 } else
415 memset(pixels, attr, (x2 - x) * bytesperpixel);
416
417 if (x < d->vfb_data->update_x1)
418 d->vfb_data->update_x1 = x;
419 if (x2 > d->vfb_data->update_x2)
420 d->vfb_data->update_x2 = x2;
421
422 for (fb_y=y; fb_y < y2 + lw; fb_y ++) {
423 memcpy(d->vfb_data->framebuffer + (fb_y * PX_XSIZE + x)
424 * bytesperpixel, pixels, (x2-x)*bytesperpixel);
425
426 if (fb_y < d->vfb_data->update_y1)
427 d->vfb_data->update_y1 = fb_y;
428 if (fb_y > d->vfb_data->update_y2)
429 d->vfb_data->update_y2 = fb_y;
430 }
431 }
432
433 /* NetBSD and Ultrix putchar */
434 if (cmdword == 0xa21) {
435 /* Ugly test code: */
436 unsigned char pixels[16 * 3];
437 int pixels_len = 16;
438 uint32_t v1, v2, fgcolor, bgcolor;
439 int x, y, x2,y2, i, maxi;
440 int xbit;
441 int suby;
442 int fg_r, fg_g, fg_b;
443 int bg_r, bg_g, bg_b;
444
445 v1 = px_readword(cpu, dma_buf, 52);
446 v2 = px_readword(cpu, dma_buf, 56);
447 fgcolor = px_readword(cpu, dma_buf, 16 * 4);
448 bgcolor = px_readword(cpu, dma_buf, 29 * 4);
449
450 /*
451 * TODO: Which one is r, which one is g, and which one is b?
452 * TODO 2: Use the BT459 palette, these values are hardcoded
453 * for NetBSD and Ultrix grayscale only.
454 */
455 fg_r = (fgcolor >> 16) & 255;
456 fg_g = (fgcolor >> 8) & 255;
457 fg_b = fgcolor & 255;
458 if (fg_r == 0)
459 fg_r = fg_g = fg_b = 0;
460 else
461 if (fg_r == 7)
462 fg_r = fg_g = fg_b = 192;
463 else
464 fg_r = fg_g = fg_b = 255;
465
466 bg_r = (bgcolor >> 16) & 255;
467 bg_g = (bgcolor >> 8) & 255;
468 bg_b = bgcolor & 255;
469 if (bg_r == 0)
470 bg_r = bg_g = bg_b = 0;
471 else
472 if (bg_r == 7)
473 bg_r = bg_g = bg_b = 192;
474 else
475 bg_r = bg_g = bg_b = 255;
476
477 x = (v1 >> 19) & 2047;
478 y = ((v1 - 63) >> 3) & 1023;
479 x2 = (v2 >> 19) & 2047;
480 y2 = ((v2 - 63) >> 3) & 1023;
481
482 #ifdef PX_DEBUG
483 debug("[ px putchar: v1 = 0x%08x v2 = 0x%08x x=%i y=%i ]\n",
484 (int)v1, (int)v2, x,y, x2,y2);
485 #endif
486 x %= PX_XSIZE;
487 y %= PX_YSIZE;
488 x2 %= PX_XSIZE;
489 y2 %= PX_YSIZE;
490
491 pixels_len = x2 - x;
492
493 suby = 0;
494 maxi = 12;
495 maxi = 33;
496
497 for (i=4; i<maxi; i++) {
498 int j;
499
500 if (i == 12)
501 i = 30;
502
503 for (j=0; j<2; j++) {
504 for (xbit = 0; xbit < 8; xbit ++) {
505 if (bytesperpixel == 3) {
506 /* 24-bit: */
507 /* TODO: Which one is r,
508 which one is g, and b? */
509 pixels[xbit * 3 + 0] =
510 (dma_buf[i*4 + j*2 + 0] &
511 (1 << xbit))? fg_r : bg_r;
512 pixels[xbit * 3 + 1] =
513 (dma_buf[i*4 + j*2 + 0] &
514 (1 << xbit))? fg_g : bg_g;
515 pixels[xbit * 3 + 2] =
516 (dma_buf[i*4 + j*2 + 0] &
517 (1 << xbit))? fg_b : bg_b;
518 pixels[(xbit + 8) * 3 + 0] =
519 (dma_buf[i*4 + j*2 + 1] &
520 (1 << xbit))? fg_r : bg_r;
521 pixels[(xbit + 8) * 3 + 1] =
522 (dma_buf[i*4 + j*2 + 1] &
523 (1 << xbit))? fg_g : bg_g;
524 pixels[(xbit + 8) * 3 + 2] =
525 (dma_buf[i*4 + j*2 + 1] &
526 (1 << xbit))? fg_b : bg_b;
527 } else {
528 /* 8-bit: */
529 pixels[xbit] = (dma_buf[i*4 +
530 j*2 + 0] & (1 << xbit))?
531 (fgcolor & 255) :
532 (bgcolor & 255);
533 pixels[xbit + 8] = (dma_buf[i*4
534 + j*2 + 1] & (1 << xbit))?
535 (fgcolor & 255) :
536 (bgcolor & 255);
537 }
538 }
539
540 memcpy(d->vfb_data->framebuffer + ((y+suby)
541 * PX_XSIZE + x) * bytesperpixel,
542 pixels, pixels_len * bytesperpixel);
543
544 if (y+suby < d->vfb_data->update_y1)
545 d->vfb_data->update_y1 = y+suby;
546 if (y+suby > d->vfb_data->update_y2)
547 d->vfb_data->update_y2 = y+suby;
548
549 suby ++;
550 }
551
552 if (x < d->vfb_data->update_x1)
553 d->vfb_data->update_x1 = x;
554 if (x2 > d->vfb_data->update_x2)
555 d->vfb_data->update_x2 = x2;
556 }
557 }
558 }
559
560
561 /*
562 * dev_px_access():
563 */
564 DEVICE_ACCESS(px)
565 {
566 uint64_t idata = 0, odata = 0;
567 struct px_data *d = extra;
568 size_t i;
569
570 if (writeflag == MEM_WRITE)
571 idata = memory_readmax64(cpu, data, len);
572
573 if (relative_addr < 0x0c0000) {
574 /*
575 * DMA poll: a read from this address should start a DMA
576 * transfer, and return 1 in odata while the DMA is in
577 * progress (STAMP_BUSY), and then 0 (STAMP_OK) once we're
578 * done.
579 *
580 * According to NetBSD's pxreg.h, the following formula gets
581 * us from system address to DMA address: (v is the system
582 * address)
583 *
584 * dma_addr = ( ( ((v & ~0x7fff) << 3) |
585 * (v & 0x7fff) ) & 0x1ffff800) >> 9;
586 *
587 * Hopefully, this is a good enough reversal of that formula:
588 *
589 * sys_addr = ((dma_addr << 9) & 0x7800) +
590 * ((dma_addr << 6) & 0xffff8000);
591 *
592 * If the board type is "PX" then the system address is an
593 * address in host memory. Otherwise, it is relative to
594 * 0x200000 (the i860's memory space on the board).
595 */
596 uint32_t sys_addr; /* system address for DMA transfers */
597 sys_addr = ((relative_addr << 9) & 0x7800) +
598 ((relative_addr << 6) & 0xffff8000);
599
600 /*
601 * If the system address is sane enough, then start a DMA
602 * transfer: (for the "PX" board type, don't allow obviously
603 * too-low physical addresses)
604 */
605 if (sys_addr >= 0x4000 || d->type != DEV_PX_TYPE_PX)
606 dev_px_dma(cpu, sys_addr, d);
607
608 /* Pretend that it was always OK: */
609 odata = STAMP_OK;
610 }
611
612 /* N10 sram: */
613 if (relative_addr >= 0x200000 && relative_addr < 0x280000) {
614 if (d->type == DEV_PX_TYPE_PX)
615 fatal("WARNING: the vdac should be at this "
616 "address. overlap problems?\n");
617
618 if (writeflag == MEM_WRITE) {
619 for (i=0; i<len; i++)
620 d->sram[relative_addr - 0x200000 + i] = data[i];
621 /* NOTE: this return here supresses debug output
622 (which would be printed if we continue) */
623 return 1;
624 } else {
625 /*
626 * Huh? Why have I commented out this? TODO
627 */
628 /* for (i=0; i<len; i++)
629 data[i] = d->sram[relative_addr - 0x200000
630 + i]; */
631 odata = 1;
632 }
633 }
634
635 /* TODO: Most of these aren't implemented yet. */
636
637 switch (relative_addr) {
638 case 0x180008: /* hsync */
639 if (writeflag==MEM_READ) {
640 debug("[ px: read from hsync: 0x%08llx ]\n",
641 (long long)odata);
642 } else {
643 debug("[ px: write to hsync: 0x%08llx ]\n",
644 (long long)idata);
645 }
646 break;
647 case 0x18000c: /* hsync2 */
648 if (writeflag==MEM_READ) {
649 debug("[ px: read from hsync2: 0x%08llx ]\n",
650 (long long)odata);
651 } else {
652 debug("[ px: write to hsync2: 0x%08llx ]\n",
653 (long long)idata);
654 }
655 break;
656 case 0x180010: /* hblank */
657 if (writeflag==MEM_READ) {
658 debug("[ px: read from hblank: 0x%08llx ]\n",
659 (long long)odata);
660 } else {
661 debug("[ px: write to hblank: 0x%08llx ]\n",
662 (long long)idata);
663 }
664 break;
665 case 0x180014: /* vsync */
666 if (writeflag==MEM_READ) {
667 debug("[ px: read from vsync: 0x%08llx ]\n",
668 (long long)odata);
669 } else {
670 debug("[ px: write to vsync: 0x%08llx ]\n",
671 (long long)idata);
672 }
673 break;
674 case 0x180018: /* vblank */
675 if (writeflag==MEM_READ) {
676 debug("[ px: read from vblank: 0x%08llx ]\n",
677 (long long)odata);
678 } else {
679 debug("[ px: write to vblank: 0x%08llx ]\n",
680 (long long)idata);
681 }
682 break;
683 case 0x180020: /* ipdvint */
684 if (writeflag==MEM_READ) {
685 odata = d->intr;
686
687 /* TODO: how do interrupts work on the pixelstamp boards? */
688 odata = random();
689
690 debug("[ px: read from ipdvint: 0x%08llx ]\n",
691 (long long)odata);
692 } else {
693 d->intr = idata;
694 if (idata & STIC_INT_E_WE)
695 d->intr &= ~STIC_INT_E;
696 if (idata & STIC_INT_V_WE)
697 d->intr &= ~STIC_INT_V;
698 if (idata & STIC_INT_P_WE)
699 d->intr &= ~STIC_INT_P;
700 debug("[ px: write to ipdvint: 0x%08llx ]\n",
701 (long long)idata);
702 }
703 break;
704 case 0x180028: /* sticsr */
705 if (writeflag==MEM_READ) {
706 debug("[ px: read from sticsr: 0x%08llx ]\n",
707 (long long)odata);
708 } else {
709 debug("[ px: write to sticsr: 0x%08llx ]\n",
710 (long long)idata);
711 }
712 break;
713 case 0x180038: /* buscsr */
714 if (writeflag==MEM_READ) {
715 debug("[ px: read from buscsr: 0x%08llx ]\n",
716 (long long)odata);
717 } else {
718 debug("[ px: write to buscsr: 0x%08llx ]\n",
719 (long long)idata);
720 }
721 break;
722 case 0x18003c: /* modcl */
723 if (writeflag==MEM_READ) {
724 odata = (d->type << 12) + (d->xconfig << 11) +
725 (d->yconfig << 9);
726 debug("[ px: read from modcl: 0x%llx ]\n",
727 (long long)odata);
728 } else {
729 debug("[ px: write to modcl: 0x%llx ]\n",
730 (long long)idata);
731 }
732 break;
733 default:
734 if (writeflag==MEM_READ) {
735 debug("[ px: read from addr 0x%x: 0x%llx ]\n",
736 (int)relative_addr, (long long)odata);
737 } else {
738 debug("[ px: write to addr 0x%x: 0x%llx ]\n",
739 (int)relative_addr, (long long)idata);
740 }
741 }
742
743 if (writeflag == MEM_READ)
744 memory_writemax64(cpu, data, len, odata);
745
746 return 1;
747 }
748
749
750 /*
751 * dev_px_init():
752 */
753 void dev_px_init(struct machine *machine, struct memory *mem,
754 uint64_t baseaddr, int px_type, char *irq_path)
755 {
756 struct px_data *d;
757
758 d = malloc(sizeof(struct px_data));
759 if (d == NULL) {
760 fprintf(stderr, "out of memory\n");
761 exit(1);
762 }
763 memset(d, 0, sizeof(struct px_data));
764
765 d->type = px_type;
766
767 INTERRUPT_CONNECT(irq_path, d->irq);
768
769 d->xconfig = d->yconfig = 0; /* 4x1 */
770
771 d->bitdepth = 24;
772 d->px_name = "(invalid)";
773
774 switch (d->type) {
775 case DEV_PX_TYPE_PX:
776 d->bitdepth = 8;
777 d->px_name = "PX";
778 break;
779 case DEV_PX_TYPE_PXG:
780 d->bitdepth = 8;
781 d->px_name = "PXG";
782 break;
783 case DEV_PX_TYPE_PXGPLUS:
784 d->px_name = "PXG+";
785 break;
786 case DEV_PX_TYPE_PXGPLUSTURBO:
787 d->px_name = "PXG+ TURBO";
788 d->xconfig = d->yconfig = 1; /* 5x2 */
789 break;
790 default:
791 fatal("dev_px_init(): unimplemented px_type\n");
792 }
793
794 d->fb_mem = memory_new(PX_XSIZE * PX_YSIZE * d->bitdepth / 8,
795 machine->arch);
796 if (d->fb_mem == NULL) {
797 fprintf(stderr, "dev_px_init(): out of memory (1)\n");
798 exit(1);
799 }
800
801 d->vfb_data = dev_fb_init(machine, d->fb_mem, 0, VFB_GENERIC,
802 PX_XSIZE, PX_YSIZE, PX_XSIZE, PX_YSIZE, d->bitdepth, d->px_name);
803 if (d->vfb_data == NULL) {
804 fprintf(stderr, "dev_px_init(): out of memory (2)\n");
805 exit(2);
806 }
807
808 switch (d->type) {
809 case DEV_PX_TYPE_PX:
810 dev_bt459_init(machine, mem, baseaddr + 0x200000, 0,
811 d->vfb_data, 8, irq_path, BT459_PX);
812 break;
813 case DEV_PX_TYPE_PXG:
814 case DEV_PX_TYPE_PXGPLUS:
815 case DEV_PX_TYPE_PXGPLUSTURBO:
816 dev_bt459_init(machine, mem, baseaddr + 0x300000, 0,
817 d->vfb_data, d->bitdepth, irq_path, BT459_PX);
818 break;
819 default:
820 fatal("dev_px_init(): unimplemented px_type\n");
821 }
822
823 memory_device_register(mem, "px", baseaddr, DEV_PX_LENGTH,
824 dev_px_access, d, DM_DEFAULT, NULL);
825 machine_add_tickfunction(machine, dev_px_tick, d, 14, 0.0);
826 }
827

  ViewVC Help
Powered by ViewVC 1.1.26