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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 22871 byte(s)
0.3.1
1 /*
2 * Copyright (C) 2004-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_px.c,v 1.26 2005/02/18 07:29:56 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 cpu_interrupt(cpu, d->irq_nr);
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 int 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 int 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 int 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 (span_dst < d->vfb_data->update_y1)
332 d->vfb_data->update_y1 = span_dst;
333 if (span_dst > d->vfb_data->update_y2)
334 d->vfb_data->update_y2 = span_dst;
335 if (span_src < d->vfb_data->update_y1)
336 d->vfb_data->update_y1 = span_src;
337 if (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, lw, attr;
345 int x,y,x2,y2;
346 int fb_y;
347 int bg_r, bg_g, bg_b;
348 unsigned char pixels[PX_XSIZE * 3];
349
350 lw = px_readword(cpu, dma_buf, 16);
351 attr = px_readword(cpu, dma_buf, 20);
352 v1 = px_readword(cpu, dma_buf, 24);
353 v2 = px_readword(cpu, dma_buf, 28);
354 #if 0
355 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
356 lw = dma_buf[16] + (dma_buf[17] << 8) +
357 (dma_buf[18] << 16) + (dma_buf[19] << 24);
358 else
359 lw = dma_buf[19] + (dma_buf[18] << 8) +
360 (dma_buf[17] << 16) + (dma_buf[16] << 24);
361
362 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
363 v1 = dma_buf[24] + (dma_buf[25] << 8) +
364 (dma_buf[26] << 16) + (dma_buf[27] << 24);
365 else
366 v1 = dma_buf[27] + (dma_buf[26] << 8) +
367 (dma_buf[25] << 16) + (dma_buf[24] << 24);
368
369 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
370 v2 = dma_buf[28] + (dma_buf[29] << 8) +
371 (dma_buf[30] << 16) + (dma_buf[31] << 24);
372 else
373 v2 = dma_buf[31] + (dma_buf[30] << 8) +
374 (dma_buf[29] << 16) + (dma_buf[28] << 24);
375 #endif
376 bg_r = (attr >> 16) & 255;
377 bg_g = (attr >> 8) & 255;
378 bg_b = attr & 255;
379 if (bg_r == 0)
380 bg_r = bg_g = bg_b = 0;
381 else
382 if (bg_r == 7)
383 bg_r = bg_g = bg_b = 192;
384 else
385 bg_r = bg_g = bg_b = 255;
386
387 v1 -= lw;
388 v2 -= lw;
389
390 x = (v1 >> 19) & 2047;
391 y = (v1 >> 3) & 1023;
392 x2 = (v2 >> 19) & 2047;
393 y2 = (v2 >> 3) & 1023;
394
395 lw = (lw + 1) >> 2;
396
397 if (x2 - x > PX_XSIZE)
398 x2 = PX_XSIZE;
399
400 #ifdef PX_DEBUG
401 debug("[ px: clear/fill: v1 = 0x%08x v2 = 0x%08x "
402 "lw=%i x=%i y=%i x2=%i y2=%i ]\n", (int)v1, (int)v2,
403 lw, x,y, x2,y2);
404 #endif
405 if (bytesperpixel == 3) {
406 int xi;
407 for (xi=0; xi<x2-x; xi++) {
408 /* TODO: rgb order? */
409 pixels[xi*3 + 0] = bg_r;
410 pixels[xi*3 + 1] = bg_g;
411 pixels[xi*3 + 2] = bg_b;
412 }
413 } else
414 memset(pixels, attr, (x2 - x) * bytesperpixel);
415
416 if (x < d->vfb_data->update_x1)
417 d->vfb_data->update_x1 = x;
418 if (x2 > d->vfb_data->update_x2)
419 d->vfb_data->update_x2 = x2;
420
421 for (fb_y=y; fb_y < y2 + lw; fb_y ++) {
422 memcpy(d->vfb_data->framebuffer + (fb_y * PX_XSIZE + x)
423 * bytesperpixel, pixels, (x2-x)*bytesperpixel);
424
425 if (fb_y < d->vfb_data->update_y1)
426 d->vfb_data->update_y1 = fb_y;
427 if (fb_y > d->vfb_data->update_y2)
428 d->vfb_data->update_y2 = fb_y;
429 }
430 }
431
432 /* NetBSD and Ultrix putchar */
433 if (cmdword == 0xa21) {
434 /* Ugly test code: */
435 unsigned char pixels[16 * 3];
436 int pixels_len = 16;
437 uint32_t v1, v2, fgcolor, bgcolor;
438 int x, y, x2,y2, i, maxi;
439 int xbit;
440 int suby;
441 int fg_r, fg_g, fg_b;
442 int bg_r, bg_g, bg_b;
443
444 v1 = px_readword(cpu, dma_buf, 52);
445 v2 = px_readword(cpu, dma_buf, 56);
446 fgcolor = px_readword(cpu, dma_buf, 16 * 4);
447 bgcolor = px_readword(cpu, dma_buf, 29 * 4);
448
449 /*
450 * TODO: Which one is r, which one is g, and which one is b?
451 * TODO 2: Use the BT459 palette, these values are hardcoded
452 * for NetBSD and Ultrix grayscale only.
453 */
454 fg_r = (fgcolor >> 16) & 255;
455 fg_g = (fgcolor >> 8) & 255;
456 fg_b = fgcolor & 255;
457 if (fg_r == 0)
458 fg_r = fg_g = fg_b = 0;
459 else
460 if (fg_r == 7)
461 fg_r = fg_g = fg_b = 192;
462 else
463 fg_r = fg_g = fg_b = 255;
464
465 bg_r = (bgcolor >> 16) & 255;
466 bg_g = (bgcolor >> 8) & 255;
467 bg_b = bgcolor & 255;
468 if (bg_r == 0)
469 bg_r = bg_g = bg_b = 0;
470 else
471 if (bg_r == 7)
472 bg_r = bg_g = bg_b = 192;
473 else
474 bg_r = bg_g = bg_b = 255;
475
476 x = (v1 >> 19) & 2047;
477 y = ((v1 - 63) >> 3) & 1023;
478 x2 = (v2 >> 19) & 2047;
479 y2 = ((v2 - 63) >> 3) & 1023;
480
481 #ifdef PX_DEBUG
482 debug("[ px putchar: v1 = 0x%08x v2 = 0x%08x x=%i y=%i ]\n",
483 (int)v1, (int)v2, x,y, x2,y2);
484 #endif
485 x %= PX_XSIZE;
486 y %= PX_YSIZE;
487 x2 %= PX_XSIZE;
488 y2 %= PX_YSIZE;
489
490 pixels_len = x2 - x;
491
492 suby = 0;
493 maxi = 12;
494 maxi = 33;
495
496 for (i=4; i<maxi; i++) {
497 int j;
498
499 if (i == 12)
500 i = 30;
501
502 for (j=0; j<2; j++) {
503 for (xbit = 0; xbit < 8; xbit ++) {
504 if (bytesperpixel == 3) {
505 /* 24-bit: */
506 /* TODO: Which one is r,
507 which one is g, and b? */
508 pixels[xbit * 3 + 0] =
509 (dma_buf[i*4 + j*2 + 0] &
510 (1 << xbit))? fg_r : bg_r;
511 pixels[xbit * 3 + 1] =
512 (dma_buf[i*4 + j*2 + 0] &
513 (1 << xbit))? fg_g : bg_g;
514 pixels[xbit * 3 + 2] =
515 (dma_buf[i*4 + j*2 + 0] &
516 (1 << xbit))? fg_b : bg_b;
517 pixels[(xbit + 8) * 3 + 0] =
518 (dma_buf[i*4 + j*2 + 1] &
519 (1 << xbit))? fg_r : bg_r;
520 pixels[(xbit + 8) * 3 + 1] =
521 (dma_buf[i*4 + j*2 + 1] &
522 (1 << xbit))? fg_g : bg_g;
523 pixels[(xbit + 8) * 3 + 2] =
524 (dma_buf[i*4 + j*2 + 1] &
525 (1 << xbit))? fg_b : bg_b;
526 } else {
527 /* 8-bit: */
528 pixels[xbit] = (dma_buf[i*4 +
529 j*2 + 0] & (1 << xbit))?
530 (fgcolor & 255) :
531 (bgcolor & 255);
532 pixels[xbit + 8] = (dma_buf[i*4
533 + j*2 + 1] & (1 << xbit))?
534 (fgcolor & 255) :
535 (bgcolor & 255);
536 }
537 }
538
539 memcpy(d->vfb_data->framebuffer + ((y+suby)
540 * PX_XSIZE + x) * bytesperpixel,
541 pixels, pixels_len * bytesperpixel);
542
543 if (y+suby < d->vfb_data->update_y1)
544 d->vfb_data->update_y1 = y+suby;
545 if (y+suby > d->vfb_data->update_y2)
546 d->vfb_data->update_y2 = y+suby;
547
548 suby ++;
549 }
550
551 if (x < d->vfb_data->update_x1)
552 d->vfb_data->update_x1 = x;
553 if (x2 > d->vfb_data->update_x2)
554 d->vfb_data->update_x2 = x2;
555 }
556 }
557 }
558
559
560 /*
561 * dev_px_access():
562 */
563 int dev_px_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
564 unsigned char *data, size_t len, int writeflag, void *extra)
565 {
566 uint64_t idata = 0, odata = 0;
567 struct px_data *d = extra;
568 int i;
569
570 idata = memory_readmax64(cpu, data, len);
571
572 if (relative_addr < 0x0c0000) {
573 /*
574 * DMA poll: a read from this address should start a DMA
575 * transfer, and return 1 in odata while the DMA is in
576 * progress (STAMP_BUSY), and then 0 (STAMP_OK) once we're
577 * done.
578 *
579 * According to NetBSD's pxreg.h, the following formula gets
580 * us from system address to DMA address: (v is the system
581 * address)
582 *
583 * dma_addr = ( ( ((v & ~0x7fff) << 3) |
584 * (v & 0x7fff) ) & 0x1ffff800) >> 9;
585 *
586 * Hopefully, this is a good enough reversal of that formula:
587 *
588 * sys_addr = ((dma_addr << 9) & 0x7800) +
589 * ((dma_addr << 6) & 0xffff8000);
590 *
591 * If the board type is "PX" then the system address is an
592 * address in host memory. Otherwise, it is relative to
593 * 0x200000 (the i860's memory space on the board).
594 */
595 uint32_t sys_addr; /* system address for DMA transfers */
596 sys_addr = ((relative_addr << 9) & 0x7800) +
597 ((relative_addr << 6) & 0xffff8000);
598
599 /*
600 * If the system address is sane enough, then start a DMA
601 * transfer: (for the "PX" board type, don't allow obviously
602 * too-low physical addresses)
603 */
604 if (sys_addr >= 0x4000 || d->type != DEV_PX_TYPE_PX)
605 dev_px_dma(cpu, sys_addr, d);
606
607 /* Pretend that it was always OK: */
608 odata = STAMP_OK;
609 }
610
611 /* N10 sram: */
612 if (relative_addr >= 0x200000 && relative_addr < 0x280000) {
613 if (d->type == DEV_PX_TYPE_PX)
614 fatal("WARNING: the vdac should be at this "
615 "address. overlap problems?\n");
616
617 if (writeflag == MEM_WRITE) {
618 for (i=0; i<len; i++)
619 d->sram[relative_addr - 0x200000 + i] = data[i];
620 /* NOTE: this return here supresses debug output
621 (which would be printed if we continue) */
622 return 1;
623 } else {
624 /*
625 * Huh? Why have I commented out this? TODO
626 */
627 /* for (i=0; i<len; i++)
628 data[i] = d->sram[relative_addr - 0x200000
629 + i]; */
630 odata = 1;
631 }
632 }
633
634 /* TODO: Most of these aren't implemented yet. */
635
636 switch (relative_addr) {
637 case 0x180008: /* hsync */
638 if (writeflag==MEM_READ) {
639 debug("[ px: read from hsync: 0x%08llx ]\n",
640 (long long)odata);
641 } else {
642 debug("[ px: write to hsync: 0x%08llx ]\n",
643 (long long)idata);
644 }
645 break;
646 case 0x18000c: /* hsync2 */
647 if (writeflag==MEM_READ) {
648 debug("[ px: read from hsync2: 0x%08llx ]\n",
649 (long long)odata);
650 } else {
651 debug("[ px: write to hsync2: 0x%08llx ]\n",
652 (long long)idata);
653 }
654 break;
655 case 0x180010: /* hblank */
656 if (writeflag==MEM_READ) {
657 debug("[ px: read from hblank: 0x%08llx ]\n",
658 (long long)odata);
659 } else {
660 debug("[ px: write to hblank: 0x%08llx ]\n",
661 (long long)idata);
662 }
663 break;
664 case 0x180014: /* vsync */
665 if (writeflag==MEM_READ) {
666 debug("[ px: read from vsync: 0x%08llx ]\n",
667 (long long)odata);
668 } else {
669 debug("[ px: write to vsync: 0x%08llx ]\n",
670 (long long)idata);
671 }
672 break;
673 case 0x180018: /* vblank */
674 if (writeflag==MEM_READ) {
675 debug("[ px: read from vblank: 0x%08llx ]\n",
676 (long long)odata);
677 } else {
678 debug("[ px: write to vblank: 0x%08llx ]\n",
679 (long long)idata);
680 }
681 break;
682 case 0x180020: /* ipdvint */
683 if (writeflag==MEM_READ) {
684 odata = d->intr;
685
686 /* TODO: how do interrupts work on the pixelstamp boards? */
687 odata = random();
688
689 debug("[ px: read from ipdvint: 0x%08llx ]\n",
690 (long long)odata);
691 } else {
692 d->intr = idata;
693 if (idata & STIC_INT_E_WE)
694 d->intr &= ~STIC_INT_E;
695 if (idata & STIC_INT_V_WE)
696 d->intr &= ~STIC_INT_V;
697 if (idata & STIC_INT_P_WE)
698 d->intr &= ~STIC_INT_P;
699 debug("[ px: write to ipdvint: 0x%08llx ]\n",
700 (long long)idata);
701 }
702 break;
703 case 0x180028: /* sticsr */
704 if (writeflag==MEM_READ) {
705 debug("[ px: read from sticsr: 0x%08llx ]\n",
706 (long long)odata);
707 } else {
708 debug("[ px: write to sticsr: 0x%08llx ]\n",
709 (long long)idata);
710 }
711 break;
712 case 0x180038: /* buscsr */
713 if (writeflag==MEM_READ) {
714 debug("[ px: read from buscsr: 0x%08llx ]\n",
715 (long long)odata);
716 } else {
717 debug("[ px: write to buscsr: 0x%08llx ]\n",
718 (long long)idata);
719 }
720 break;
721 case 0x18003c: /* modcl */
722 if (writeflag==MEM_READ) {
723 odata = (d->type << 12) + (d->xconfig << 11) +
724 (d->yconfig << 9);
725 debug("[ px: read from modcl: 0x%llx ]\n",
726 (long long)odata);
727 } else {
728 debug("[ px: write to modcl: 0x%llx ]\n",
729 (long long)idata);
730 }
731 break;
732 default:
733 if (writeflag==MEM_READ) {
734 debug("[ px: read from addr 0x%x: 0x%llx ]\n",
735 (int)relative_addr, (long long)odata);
736 } else {
737 debug("[ px: write to addr 0x%x: 0x%llx ]\n",
738 (int)relative_addr, (long long)idata);
739 }
740 }
741
742 if (writeflag == MEM_READ)
743 memory_writemax64(cpu, data, len, odata);
744
745 return 1;
746 }
747
748
749 /*
750 * dev_px_init():
751 */
752 void dev_px_init(struct machine *machine, struct memory *mem,
753 uint64_t baseaddr, int px_type, int irq_nr)
754 {
755 struct px_data *d;
756
757 d = malloc(sizeof(struct px_data));
758 if (d == NULL) {
759 fprintf(stderr, "out of memory\n");
760 exit(1);
761 }
762 memset(d, 0, sizeof(struct px_data));
763
764 d->type = px_type;
765 d->irq_nr = irq_nr;
766
767 d->xconfig = d->yconfig = 0; /* 4x1 */
768
769 d->bitdepth = 24;
770 d->px_name = "(invalid)";
771
772 switch (d->type) {
773 case DEV_PX_TYPE_PX:
774 d->bitdepth = 8;
775 d->px_name = "PX";
776 break;
777 case DEV_PX_TYPE_PXG:
778 d->bitdepth = 8;
779 d->px_name = "PXG";
780 break;
781 case DEV_PX_TYPE_PXGPLUS:
782 d->px_name = "PXG+";
783 break;
784 case DEV_PX_TYPE_PXGPLUSTURBO:
785 d->px_name = "PXG+ TURBO";
786 d->xconfig = d->yconfig = 1; /* 5x2 */
787 break;
788 default:
789 fatal("dev_px_init(): unimplemented px_type\n");
790 }
791
792 d->fb_mem = memory_new(PX_XSIZE * PX_YSIZE * d->bitdepth / 8);
793 if (d->fb_mem == NULL) {
794 fprintf(stderr, "dev_px_init(): out of memory (1)\n");
795 exit(1);
796 }
797
798 d->vfb_data = dev_fb_init(machine, d->fb_mem, 0, VFB_GENERIC,
799 PX_XSIZE, PX_YSIZE, PX_XSIZE, PX_YSIZE, d->bitdepth, d->px_name, 1);
800 if (d->vfb_data == NULL) {
801 fprintf(stderr, "dev_px_init(): out of memory (2)\n");
802 exit(2);
803 }
804
805 switch (d->type) {
806 case DEV_PX_TYPE_PX:
807 dev_bt459_init(machine, mem, baseaddr + 0x200000, 0,
808 d->vfb_data, 8, irq_nr, BT459_PX);
809 break;
810 case DEV_PX_TYPE_PXG:
811 case DEV_PX_TYPE_PXGPLUS:
812 case DEV_PX_TYPE_PXGPLUSTURBO:
813 dev_bt459_init(machine, mem, baseaddr + 0x300000, 0,
814 d->vfb_data, d->bitdepth, irq_nr, BT459_PX);
815 break;
816 default:
817 fatal("dev_px_init(): unimplemented px_type\n");
818 }
819
820 memory_device_register(mem, "px", baseaddr, DEV_PX_LENGTH,
821 dev_px_access, d, MEM_DEFAULT, NULL);
822 machine_add_tickfunction(machine, dev_px_tick, d, 14);
823 }
824

  ViewVC Help
Powered by ViewVC 1.1.26