/[gxemul]/upstream/0.4.0.1/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

Annotation of /upstream/0.4.0.1/src/devices/dev_px.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (hide annotations)
Mon Oct 8 16:20:18 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 22859 byte(s)
0.4.0.1
1 dpavlin 4 /*
2 dpavlin 22 * Copyright (C) 2004-2006 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 24 * $Id: dev_px.c,v 1.34 2006/03/04 12:38:48 debug Exp $
29 dpavlin 4 *
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 dpavlin 22 size_t dma_len = sizeof(dma_buf);
147 dpavlin 4 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 dpavlin 22 size_t i;
235 dpavlin 4 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 dpavlin 22 uint32_t spannr, ofs;
246 dpavlin 4 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 dpavlin 22 if ((int32_t)span_dst < d->vfb_data->update_y1)
332 dpavlin 4 d->vfb_data->update_y1 = span_dst;
333 dpavlin 22 if ((int32_t)span_dst > d->vfb_data->update_y2)
334 dpavlin 4 d->vfb_data->update_y2 = span_dst;
335 dpavlin 22 if ((int32_t)span_src < d->vfb_data->update_y1)
336 dpavlin 4 d->vfb_data->update_y1 = span_src;
337 dpavlin 22 if ((int32_t)span_src > d->vfb_data->update_y2)
338 dpavlin 4 d->vfb_data->update_y2 = span_src;
339     }
340     }
341    
342     /* NetBSD and Ultrix erasecols/eraserows */
343     if (cmdword == 0x411) {
344 dpavlin 22 uint32_t v1, v2, attr;
345     int32_t lw;
346 dpavlin 4 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 dpavlin 22 DEVICE_ACCESS(px)
565 dpavlin 4 {
566     uint64_t idata = 0, odata = 0;
567     struct px_data *d = extra;
568 dpavlin 22 size_t i;
569 dpavlin 4
570 dpavlin 18 if (writeflag == MEM_WRITE)
571     idata = memory_readmax64(cpu, data, len);
572 dpavlin 4
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, int irq_nr)
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     d->irq_nr = irq_nr;
767    
768     d->xconfig = d->yconfig = 0; /* 4x1 */
769    
770     d->bitdepth = 24;
771     d->px_name = "(invalid)";
772    
773     switch (d->type) {
774     case DEV_PX_TYPE_PX:
775     d->bitdepth = 8;
776     d->px_name = "PX";
777     break;
778     case DEV_PX_TYPE_PXG:
779     d->bitdepth = 8;
780     d->px_name = "PXG";
781     break;
782     case DEV_PX_TYPE_PXGPLUS:
783     d->px_name = "PXG+";
784     break;
785     case DEV_PX_TYPE_PXGPLUSTURBO:
786     d->px_name = "PXG+ TURBO";
787     d->xconfig = d->yconfig = 1; /* 5x2 */
788     break;
789     default:
790     fatal("dev_px_init(): unimplemented px_type\n");
791     }
792    
793 dpavlin 12 d->fb_mem = memory_new(PX_XSIZE * PX_YSIZE * d->bitdepth / 8,
794     machine->arch);
795 dpavlin 4 if (d->fb_mem == NULL) {
796     fprintf(stderr, "dev_px_init(): out of memory (1)\n");
797     exit(1);
798     }
799    
800     d->vfb_data = dev_fb_init(machine, d->fb_mem, 0, VFB_GENERIC,
801 dpavlin 12 PX_XSIZE, PX_YSIZE, PX_XSIZE, PX_YSIZE, d->bitdepth, d->px_name);
802 dpavlin 4 if (d->vfb_data == NULL) {
803     fprintf(stderr, "dev_px_init(): out of memory (2)\n");
804     exit(2);
805     }
806    
807     switch (d->type) {
808     case DEV_PX_TYPE_PX:
809     dev_bt459_init(machine, mem, baseaddr + 0x200000, 0,
810     d->vfb_data, 8, irq_nr, BT459_PX);
811     break;
812     case DEV_PX_TYPE_PXG:
813     case DEV_PX_TYPE_PXGPLUS:
814     case DEV_PX_TYPE_PXGPLUSTURBO:
815     dev_bt459_init(machine, mem, baseaddr + 0x300000, 0,
816     d->vfb_data, d->bitdepth, irq_nr, BT459_PX);
817     break;
818     default:
819     fatal("dev_px_init(): unimplemented px_type\n");
820     }
821    
822     memory_device_register(mem, "px", baseaddr, DEV_PX_LENGTH,
823 dpavlin 20 dev_px_access, d, DM_DEFAULT, NULL);
824 dpavlin 24 machine_add_tickfunction(machine, dev_px_tick, d, 14, 0.0);
825 dpavlin 4 }
826    

  ViewVC Help
Powered by ViewVC 1.1.26