dev_px.cc Source File

Back to the index.

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

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17