dev_bt459.cc Source File

Back to the index.

dev_bt459.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-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: Brooktree BT459, used by TURBOchannel graphics cards
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "cpu.h"
36 #include "devices.h"
37 #include "machine.h"
38 #include "memory.h"
39 #include "misc.h"
40 #include "x11.h"
41 
42 #include "thirdparty/bt459.h"
43 
44 
45 #ifdef WITH_X11
46 #include <X11/Xlib.h>
47 #include <X11/Xutil.h>
48 #endif
49 
50 extern int quiet_mode;
51 
52 
53 /* #define BT459_DEBUG */
54 /* #define WITH_CURSOR_DEBUG */
55 #define BT459_TICK_SHIFT 14
56 
57 struct bt459_data {
59 
60  unsigned char cur_addr_hi;
61  unsigned char cur_addr_lo;
62 
63  int planes;
64  int type;
65 
66  struct interrupt irq;
70 
73 
75 
77  int cursor_on;
78  int cursor_x;
79  int cursor_y;
82 
83  int palette_sub_offset; /* 0, 1, or 2 */
84 
85  struct vfb_data *vfb_data;
86 
87  /*
88  * There is one pointer to the framebuffer's RGB palette,
89  * and then a local copy of the palette. 256 * 3 bytes (r,g,b).
90  * The reason for this is that when we need to blank the screen
91  * (ie video_on = 0), we can set the framebuffer's palette to all
92  * zeroes, but keep our own copy intact, to be reused later again
93  * when the screen is unblanked.
94  */
95  int video_on;
96  unsigned char *rgb_palette; /* 256 * 3 (r,g,b) */
97  unsigned char local_rgb_palette[256 * 3];
98 };
99 
100 
101 /*
102  * bt459_update_X_cursor():
103  *
104  * This routine takes the color values in the cursor RAM area, and put them
105  * in the framebuffer window's cursor_pixels.
106  *
107  * d->cursor_xsize and ysize are also updated.
108  */
109 static void bt459_update_X_cursor(struct cpu *cpu, struct bt459_data *d)
110 {
111  int i, x,y, xmax=0, ymax=0;
112  int bw_only = 1;
113 
114  /* First, let's calculate the size of the cursor: */
115  for (y=0; y<64; y++)
116  for (x=0; x<64; x+=4) {
117  int reg = BT459_REG_CRAM_BASE + y*16 + x/4;
118  unsigned char data = d->bt459_reg[reg];
119 
120  if (data)
121  ymax = y;
122 
123  for (i=0; i<4; i++) {
124  int color = (data >> (6-2*i)) & 3;
125  if (color != 0)
126  xmax = x + i;
127  if (color != 0 && color != 3)
128  bw_only = 0;
129  }
130  }
131 
132  d->cursor_xsize = xmax + 1;
133  d->cursor_ysize = ymax + 1;
134 
135  /*
136  * The 'bw_only' hack is because it is nicer to have the b/w
137  * text cursor invert whatever it is standing on, not just overwrite
138  * it with a big white box.
139  *
140  * The following seems to work with NetBSD/OpenBSD/Ultrix/Sprite:
141  * 0 = transparent, 1 and 2 = use the color specified by
142  * BT459_REG_CCOLOR_2, 3 = reverse of color 1/2.
143  */
144 
145 #ifdef WITH_X11
146  if (cpu->machine->x11_md.in_use && d->vfb_data->fb_window != NULL) {
147  for (y=0; y<=ymax; y++) {
148  for (x=0; x<=xmax; x+=4) {
149  struct fb_window *win = d->vfb_data->fb_window;
150  int reg = BT459_REG_CRAM_BASE + y*16 + x/4;
151  unsigned char data = d->bt459_reg[reg];
152 
153  for (i=0; i<4; i++) {
154  int color = (data >> (6-2*i)) & 3;
155  int pixelvalue;
156 
157  if (bw_only) {
158  if (color)
159  pixelvalue =
161  else
162  pixelvalue = 0;
163  } else {
164  pixelvalue =
166  switch (color) {
167  case 1:
168  case 2: pixelvalue = (d->
169  bt459_reg[
171  >> 4) & 0xf;
172  break;
173  case 3: pixelvalue = 15 -
174  ((d->bt459_reg[
176  >> 4) & 0xf);
177  break;
178  }
179  }
180 
181  win->cursor_pixels[y][x+i] =
182  pixelvalue;
183 #ifdef WITH_CURSOR_DEBUG
184 printf("%i", color);
185 #endif
186  }
187  }
188 #ifdef WITH_CURSOR_DEBUG
189 printf("\n");
190 #endif
191  }
192 #ifdef WITH_CURSOR_DEBUG
193 printf("color 1,2,3 = 0x%02x, 0x%02x, 0x%02x\n",
197 printf("\n");
198 #endif
199  /*
200  * Make sure the cursor is redrawn, if it is on:
201  *
202  * How does this work? Well, 0 is off, and non-zero is on,
203  * but if the old and new differ, the cursor is redrawn.
204  * (Hopefully this will "never" overflow.)
205  */
206  if (d->cursor_on)
207  d->cursor_on ++;
208  }
209 #endif
210 }
211 
212 
213 /*
214  * bt459_update_cursor_position():
215  */
216 static void bt459_update_cursor_position(struct bt459_data *d,
217  int old_cursor_on)
218 {
219  int new_cursor_x = (d->bt459_reg[BT459_REG_CXLO] & 255) +
220  ((d->bt459_reg[BT459_REG_CXHI] & 255) << 8) - d->cursor_x_add;
221  int new_cursor_y = (d->bt459_reg[BT459_REG_CYLO] & 255) +
222  ((d->bt459_reg[BT459_REG_CYHI] & 255) << 8) - d->cursor_y_add;
223 
224  if (new_cursor_x != d->cursor_x || new_cursor_y != d->cursor_y ||
225  d->cursor_on != old_cursor_on) {
226  int on;
227 
228  d->cursor_x = new_cursor_x;
229  d->cursor_y = new_cursor_y;
230 
231  if (!quiet_mode)
232  debug("[ bt459: cursor = %03i,%03i ]\n",
233  d->cursor_x, d->cursor_y);
234 
235  on = d->cursor_on;
236  if (d->cursor_xsize == 0 || d->cursor_ysize == 0)
237  on = 0;
238 
240  on, d->cursor_xsize, d->cursor_ysize);
241  }
242 }
243 
244 
246 {
247  struct bt459_data *d = (struct bt459_data *) extra;
248  int old_cursor_on = d->cursor_on;
249 
252  bt459_update_X_cursor(cpu, d);
253  bt459_update_cursor_position(d, old_cursor_on);
254  }
255 
257  d->vfb_data->update_x1 = 0;
258  d->vfb_data->update_x2 = d->vfb_data->xsize - 1;
259  d->vfb_data->update_y1 = 0;
260  d->vfb_data->update_y2 = d->vfb_data->ysize - 1;
262  }
263 
264  /*
265  * Vertical retrace interrupts. (This hack is kind of ugly.)
266  * Once every 'interrupt_time_reset_value', the interrupt is
267  * asserted. It is acked either manually (by someone reading
268  * a normal BT459 register or the Interrupt ack register),
269  * or after another tick has passed. (This is to prevent
270  * lockups from unhandled interrupts.)
271  */
272  if (d->type != BT459_PX && d->interrupts_enable) {
273  d->interrupt_time --;
274  if (d->interrupt_time < 0) {
276  INTERRUPT_ASSERT(d->irq);
277  } else
279  }
280 }
281 
282 
283 DEVICE_ACCESS(bt459_irq)
284 {
285  struct bt459_data *d = (struct bt459_data *) extra;
286  uint64_t idata = 0, odata = 0;
287 
288  if (writeflag == MEM_WRITE)
289  idata = memory_readmax64(cpu, data, len);
290 
291 #ifdef BT459_DEBUG
292  fatal("[ bt459: IRQ ack ]\n");
293 #endif
294 
295  d->interrupts_enable = 1;
296 
298 
299  if (writeflag == MEM_READ)
300  memory_writemax64(cpu, data, len, odata);
301 
302  return 1;
303 }
304 
305 
307 {
308  struct bt459_data *d = (struct bt459_data *) extra;
309  uint64_t idata = 0, odata = 0;
310  int btaddr, old_cursor_on = d->cursor_on, modified;
311 
312  idata = memory_readmax64(cpu, data, len);
313 
314 #ifdef BT459_DEBUG
315  if (writeflag == MEM_WRITE)
316  fatal("[ bt459: write to addr 0x%02x: %08x ]\n",
317  (int)relative_addr, (int)idata);
318 #endif
319 
320  /*
321  * Vertical retrace interrupts are acked either by
322  * accessing a normal BT459 register, or the irq register,
323  * or by simply "missing" it.
324  */
326 
327  /* ID register is read-only, should always be 0x4a or 0x4a4a4a: */
328  if (d->planes == 24)
329  d->bt459_reg[BT459_REG_ID] = 0x4a4a4a;
330  else {
331  /*
332  * TODO: Is it really 0x4a, or 0x4a0000?
333  * Ultrix panics with a "bad VDAC ID" message if 0x4a
334  * is returned.
335  */
336  d->bt459_reg[BT459_REG_ID] = 0x4a0000;
337  }
338 
339  btaddr = ((d->cur_addr_hi << 8) + d->cur_addr_lo) % DEV_BT459_NREGS;
340 
341  /* Read from/write to the bt459: */
342  switch (relative_addr) {
343  case 0x00: /* Low byte of address: */
344  if (writeflag == MEM_WRITE) {
345  if (!quiet_mode)
346  debug("[ bt459: write to Low Address Byte, "
347  "0x%02x ]\n", (int)idata);
348  d->cur_addr_lo = idata;
349  d->palette_sub_offset = 0;
350  } else {
351  odata = d->cur_addr_lo;
352  if (!quiet_mode)
353  debug("[ bt459: read from Low Address Byte: "
354  "0x%0x ]\n", (int)odata);
355  }
356  break;
357  case 0x04: /* High byte of address: */
358  if (writeflag == MEM_WRITE) {
359  if (!quiet_mode)
360  debug("[ bt459: write to High Address Byte, "
361  "0x%02x ]\n", (int)idata);
362  d->cur_addr_hi = idata;
363  d->palette_sub_offset = 0;
364  } else {
365  odata = d->cur_addr_hi;
366  if (!quiet_mode)
367  debug("[ bt459: read from High Address Byte: "
368  "0x%0x ]\n", (int)odata);
369  }
370  break;
371  case 0x08: /* Register access: */
372  if (writeflag == MEM_WRITE) {
373  if (!quiet_mode)
374  debug("[ bt459: write to BT459 register "
375  "0x%04x, value 0x%02x ]\n", btaddr,
376  (int)idata);
377  modified = (d->bt459_reg[btaddr] != idata);
378  d->bt459_reg[btaddr] = idata;
379 
380  switch (btaddr) {
381  case BT459_REG_CCOLOR_1:
382  case BT459_REG_CCOLOR_2:
383  case BT459_REG_CCOLOR_3:
384  if (modified)
386  break;
387  case BT459_REG_PRM:
388  /*
389  * NetBSD writes 0x00 to this register to
390  * blank the screen (video off), and 0xff
391  * to turn the screen on.
392  */
393  switch (idata & 0xff) {
394  case 0: d->video_on = 0;
395  memset(d->rgb_palette, 0, 256*3);
397  debug("[ bt459: video OFF ]\n");
398  break;
399  default:d->video_on = 1;
400  memcpy(d->rgb_palette,
401  d->local_rgb_palette, 256*3);
403  debug("[ bt459: video ON ]\n");
404  }
405  break;
406  case BT459_REG_CCR:
407  /* Cursor control register: */
408  switch (idata & 0xff) {
409  case 0x00: d->cursor_on = 0; break;
410  case 0xc0:
411  case 0xc1: d->cursor_on = 1; break;
412  default:
413  fatal("[ bt459: unimplemented CCR "
414  "value 0x%08x ]\n", (int)idata);
415  }
416  if (modified)
418  break;
419  default:
420  if (btaddr < 0x100)
421  fatal("[ bt459: write to BT459 "
422  "register 0x%04x, value 0x%02x ]\n",
423  btaddr, (int)idata);
424  }
425 
426  /* Write to cursor bitmap: */
427  if (btaddr >= BT459_REG_CRAM_BASE && modified)
429  } else {
430  odata = d->bt459_reg[btaddr];
431 
432  /* Perhaps this hack is not necessary: */
433  if (btaddr == BT459_REG_ID && len==1)
434  odata = (odata >> 16) & 255;
435 
436  if (!quiet_mode)
437  debug("[ bt459: read from BT459 register "
438  "0x%04x, value 0x%02x ]\n", btaddr,
439  (int)odata);
440  }
441 
442  /* Go to next register: */
443  d->cur_addr_lo ++;
444  if (d->cur_addr_lo == 0)
445  d->cur_addr_hi ++;
446  break;
447  case 0xc: /* Color map: */
448  if (writeflag == MEM_WRITE) {
449  idata &= 255;
450  if (!quiet_mode)
451  debug("[ bt459: write to BT459 colormap "
452  "0x%04x subaddr %i, value 0x%02x ]\n",
453  btaddr, d->palette_sub_offset, (int)idata);
454 
455  if (btaddr < 0x100) {
456  if (d->video_on &&
457  d->local_rgb_palette[(btaddr & 0xff) * 3
458  + d->palette_sub_offset] != idata)
460 
461  /*
462  * Actually, the palette should only be
463  * updated after the third write,
464  * but this should probably work fine too:
465  */
466  d->local_rgb_palette[(btaddr & 0xff) * 3
467  + d->palette_sub_offset] = idata;
468 
469  if (d->video_on)
470  d->rgb_palette[(btaddr & 0xff) * 3
471  + d->palette_sub_offset] = idata;
472  }
473  } else {
474  if (btaddr < 0x100)
475  odata = d->local_rgb_palette[(btaddr & 0xff)
476  * 3 + d->palette_sub_offset];
477  if (!quiet_mode)
478  debug("[ bt459: read from BT459 colormap "
479  "0x%04x subaddr %i, value 0x%02x ]\n",
480  btaddr, d->palette_sub_offset, (int)odata);
481  }
482 
483  d->palette_sub_offset ++;
484  if (d->palette_sub_offset >= 3) {
485  d->palette_sub_offset = 0;
486 
487  d->cur_addr_lo ++;
488  if (d->cur_addr_lo == 0)
489  d->cur_addr_hi ++;
490  }
491 
492  break;
493  default:
494  if (writeflag == MEM_WRITE) {
495  debug("[ bt459: unimplemented write to address 0x%x, "
496  "data=0x%02x ]\n", (int)relative_addr, (int)idata);
497  } else {
498  debug("[ bt459: unimplemented read from address "
499  "0x%x ]\n", (int)relative_addr);
500  }
501  }
502 
503 
504  bt459_update_cursor_position(d, old_cursor_on);
505 
506  if (writeflag == MEM_READ)
507  memory_writemax64(cpu, data, len, odata);
508 
509 #ifdef BT459_DEBUG
510  if (writeflag == MEM_READ)
511  fatal("[ bt459: read from addr 0x%02x: %08x ]\n",
512  (int)relative_addr, (int)idata);
513 #endif
514 
515  return 1;
516 }
517 
518 
519 /*
520  * dev_bt459_init():
521  */
522 void dev_bt459_init(struct machine *machine, struct memory *mem,
523  uint64_t baseaddr, uint64_t baseaddr_irq, struct vfb_data *vfb_data,
524  int planes, const char *irq_path, int type)
525 {
526  struct bt459_data *d;
527 
528  CHECK_ALLOCATION(d = (struct bt459_data *) malloc(sizeof(struct bt459_data)));
529  memset(d, 0, sizeof(struct bt459_data));
530 
531  INTERRUPT_CONNECT(irq_path, d->irq);
532 
533  d->vfb_data = vfb_data;
534  d->rgb_palette = vfb_data->rgb_palette;
535  d->planes = planes;
536  d->type = type;
537  d->cursor_x = -1;
538  d->cursor_y = -1;
539  d->cursor_xsize = d->cursor_ysize = 0; /* anything */
540  d->video_on = 1;
541 
542  /*
543  * These offsets are based on those mentioned in NetBSD,
544  * and then adjusted to look good with both NetBSD and
545  * Ultrix:
546  */
547  switch (d->type) {
548  case BT459_PX:
549  d->cursor_x_add = 370;
550  d->cursor_y_add = 37;
551  break;
552  case BT459_BA:
553  d->cursor_x_add = 220;
554  d->cursor_y_add = 35;
555  break;
556  case BT459_BBA:
557  if (vfb_data->xsize == 1280) {
558  /* 1280x1024: */
559  d->cursor_x_add = 368;
560  d->cursor_y_add = 38;
561  } else {
562  /* 1024x864: */
563  d->cursor_x_add = 220;
564  d->cursor_y_add = 35;
565  }
566  break;
567  }
568 
570 
571  memory_device_register(mem, "bt459", baseaddr, DEV_BT459_LENGTH,
572  dev_bt459_access, (void *)d, DM_DEFAULT, NULL);
573 
574  if (baseaddr_irq != 0)
575  memory_device_register(mem, "bt459_irq", baseaddr_irq, 0x10000,
576  dev_bt459_irq_access, (void *)d, DM_DEFAULT, NULL);
577 
578  machine_add_tickfunction(machine, dev_bt459_tick, d,
580 }
581 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
#define CURSOR_COLOR_INVERT
Definition: x11.h:46
void fatal(const char *fmt,...)
Definition: main.cc:152
#define DM_DEFAULT
Definition: memory.h:130
int update_x2
Definition: devices.h:220
#define CURSOR_COLOR_TRANSPARENT
Definition: x11.h:45
#define BT459_REG_CYHI
Definition: bt459.h:143
int palette_sub_offset
Definition: dev_bt459.cc:83
int xsize
Definition: devices.h:204
struct machine * machine
Definition: cpu.h:328
#define BT459_REG_CCOLOR_3
Definition: bt459.h:122
#define MEM_READ
Definition: memory.h:116
#define BT459_REG_ID
Definition: bt459.h:123
Definition: x11.h:50
#define BT459_PX
Definition: devices.h:147
int cursor_y_add
Definition: dev_bt459.cc:72
int interrupts_enable
Definition: dev_bt459.cc:67
#define DEV_BT459_NREGS
Definition: devices.h:146
int cursor_x
Definition: dev_bt459.cc:78
#define reg(x)
int cursor_ysize
Definition: dev_bt459.cc:81
int update_y1
Definition: devices.h:220
unsigned char cur_addr_lo
Definition: dev_bt459.cc:61
#define BT459_REG_CCR
Definition: bt459.h:139
#define BT459_REG_PRM
Definition: bt459.h:127
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
int need_to_redraw_whole_screen
Definition: dev_bt459.cc:74
#define BT459_BBA
Definition: devices.h:149
DEVICE_ACCESS(bt459_irq)
Definition: dev_bt459.cc:283
int interrupt_time_reset_value
Definition: dev_bt459.cc:69
int cursor_xsize
Definition: dev_bt459.cc:80
struct vfb_data * vfb_data
Definition: dev_bt459.cc:85
int cursor_on
Definition: dev_bt459.cc:77
u_short data
Definition: siireg.h:79
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
int dev_bt459_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
struct fb_window * fb_window
Definition: devices.h:232
unsigned char * rgb_palette
Definition: dev_bt459.cc:96
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
int update_x1
Definition: devices.h:220
#define MEM_WRITE
Definition: memory.h:117
int video_on
Definition: dev_bt459.cc:95
#define BT459_BA
Definition: devices.h:148
#define BT459_REG_CYLO
Definition: bt459.h:142
unsigned char cur_addr_hi
Definition: dev_bt459.cc:60
struct x11_md x11_md
Definition: machine.h:179
#define debug
Definition: dev_adb.cc:57
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
int need_to_update_cursor_shape
Definition: dev_bt459.cc:76
DEVICE_TICK(bt459)
Definition: dev_bt459.cc:245
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
#define BT459_REG_CRAM_BASE
Definition: bt459.h:153
#define BT459_REG_CXLO
Definition: bt459.h:140
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
#define DEV_BT459_LENGTH
Definition: devices.h:145
int in_use
Definition: machine.h:82
int interrupt_time
Definition: dev_bt459.cc:68
struct interrupt irq
Definition: dev_bt459.cc:66
int planes
Definition: dev_bt459.cc:63
Definition: memory.h:75
int cursor_y
Definition: dev_bt459.cc:79
addr & if(addr >=0x24 &&page !=NULL)
unsigned char local_rgb_palette[256 *3]
Definition: dev_bt459.cc:97
int quiet_mode
Definition: main.cc:78
#define BT459_REG_CCOLOR_1
Definition: bt459.h:120
int cursor_pixels[CURSOR_MAXY][CURSOR_MAXX]
Definition: x11.h:71
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
uint32_t bt459_reg[DEV_BT459_NREGS]
Definition: dev_bt459.cc:58
int update_y2
Definition: devices.h:220
#define BT459_TICK_SHIFT
Definition: dev_bt459.cc:55
#define BT459_REG_CXHI
Definition: bt459.h:141
unsigned char rgb_palette[256 *3]
Definition: devices.h:223
#define BT459_REG_CCOLOR_2
Definition: bt459.h:121
void dev_fb_setcursor(struct vfb_data *d, int cursor_x, int cursor_y, int on, int cursor_xsize, int cursor_ysize)
Definition: dev_fb.cc:193
int cursor_x_add
Definition: dev_bt459.cc:71
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
int ysize
Definition: devices.h:205

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13