/[gxemul]/trunk/src/devices/dev_bt459.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 /trunk/src/devices/dev_bt459.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17079 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26