acxcontrol(8) is gone.
[dragonfly.git] / usr.bin / doscmd / video.c
blobbae3d6f9a0f4d43b43216cd7955004ee3cd4e452
1 /*
2 * Copyright (c) 2001 The FreeBSD Project, Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY The FreeBSD Project, Inc. AND CONTRIBUTORS
15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL The FreeBSD Project, Inc. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/usr.bin/doscmd/video.c,v 1.5.2.1 2002/04/25 11:04:51 tg Exp $
27 * $DragonFly: src/usr.bin/doscmd/video.c,v 1.3 2003/10/04 20:36:43 hmp Exp $
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <err.h>
33 #include <paths.h>
34 #include <unistd.h>
36 #include "doscmd.h"
37 #include "AsyncIO.h"
38 #include "tty.h"
39 #include "video.h"
40 #include "vparams.h"
43 * Global variables
46 /* VGA registers */
47 u_int8_t VGA_CRTC[CRTC_Size];
48 u_int8_t VGA_ATC[ATC_Size];
49 u_int8_t VGA_TSC[TSC_Size];
50 u_int8_t VGA_GDC[GDC_Size];
52 /* VGA status information */
53 u_int8_t vga_status[64];
55 /* Table of supported video modes. */
56 vmode_t vmodelist[] = {
57 {0x00, 0x17, TEXT, 16, 8, 2, 0xb8000, FONT8x16},
58 {0x01, 0x17, TEXT, 16, 8, 2, 0xb8000, FONT8x16},
59 {0x02, 0x18, TEXT, 16, 8, 2, 0xb8000, FONT8x16},
60 {0x03, 0x18, TEXT, 16, 8, 2, 0xb8000, FONT8x16},
61 {0x04, 0x04, GRAPHICS, 4, 1, 0, 0xb8000, FONT8x8},
62 {0x05, 0x05, GRAPHICS, 4, 1, 0, 0xb8000, FONT8x8},
63 {0x06, 0x06, GRAPHICS, 2, 1, 0, 0xb8000, FONT8x8},
64 {0x07, 0x19, TEXT, 1, 8, 2, 0xb0000, FONT8x16},
65 {0x08, 0x08, NOMODE, 0, 0, 0, 0, 0},
66 {0x09, 0x09, NOMODE, 0, 0, 0, 0, 0},
67 {0x0a, 0x0a, NOMODE, 0, 0, 0, 0, 0},
68 {0x0b, 0x0b, NOMODE, 0, 0, 0, 0, 0},
69 {0x0c, 0x0c, NOMODE, 0, 0, 0, 0, 0},
70 {0x0d, 0x0d, GRAPHICS, 16, 8, 0, 0xa0000, FONT8x8},
71 {0x0e, 0x0e, GRAPHICS, 16, 4, 0, 0xa0000, FONT8x8},
72 {0x0f, 0x11, GRAPHICS, 1, 2, 1, 0xa0000, FONT8x14},
73 {0x10, 0x12, GRAPHICS, 16, 2, 1, 0xa0000, FONT8x14},
74 {0x11, 0x1a, GRAPHICS, 2, 1, 3, 0xa0000, FONT8x16},
75 {0x12, 0x1b, GRAPHICS, 16, 1, 3, 0xa0000, FONT8x16},
76 /* {0x13, 0x1c, GRAPHICS, 256, 1, 0, 0xa0000, FONT8x8}, */
79 #define NUMMODES (sizeof(vmodelist) / sizeof(vmode_t))
82 * Local functions
84 static void init_vga(void);
85 static u_int8_t video_inb(int);
86 static void video_outb(int, u_int8_t);
89 * Local types and variables
92 /* Save Table and assorted variables */
93 struct VideoSaveTable {
94 u_short video_parameter_table[2];
95 u_short parameter_dynamic_save_area[2]; /* Not used */
96 u_short alphanumeric_character_set_override[2]; /* Not used */
97 u_short graphics_character_set_override[2]; /* Not used */
98 u_short secondary_save_table[2]; /* Not used */
99 u_short mbz[4];
102 struct SecondaryVideoSaveTable {
103 u_short length;
104 u_short display_combination_code_table[2];
105 u_short alphanumeric_character_set_override[2]; /* Not used */
106 u_short user_palette_profile_table[2]; /* Not used */
107 u_short mbz[6];
110 struct VideoSaveTable *vsp;
111 struct SecondaryVideoSaveTable *svsp;
114 * Read and write the VGA port
117 /* Save the selected index register */
118 static u_int8_t crtc_index, atc_index, tsc_index, gdc_index;
119 /* Toggle between index and data on port ATC_WritePort */
120 static u_int8_t set_atc_index = 1;
122 static u_int8_t
123 video_inb(int port)
125 switch(port) {
126 case CRTC_DataPortColor:
127 return VGA_CRTC[crtc_index];
128 case CRTC_IndexPortColor:
129 return crtc_index;
130 case ATC_ReadPort:
131 return VGA_ATC[atc_index];
132 case TSC_DataPort:
133 return VGA_TSC[tsc_index];
134 case TSC_IndexPort:
135 return tsc_index;
136 case GDC_DataPort:
137 return VGA_GDC[gdc_index];
138 case GDC_IndexPort:
139 return gdc_index;
140 case VGA_InputStatus1Port:
141 set_atc_index = 1;
142 VGA_InputStatus1 = (VGA_InputStatus1 + 1) & 15;
143 return VGA_InputStatus1;
144 default:
145 return 0;
149 static void
150 video_outb(int port, u_int8_t value)
152 /* XXX */
153 #define row (CursRow0)
154 #define col (CursCol0)
156 int cp;
158 switch (port) {
159 case CRTC_IndexPortColor:
160 crtc_index = value;
161 break;
162 case CRTC_DataPortColor:
163 VGA_CRTC[crtc_index] = value;
164 switch (crtc_index) {
165 case CRTC_CurLocHi: /* Update cursor position in BIOS */
166 cp = row * DpyCols + col;
167 cp &= 0xff;
168 cp |= value << 8;
169 row = cp / DpyCols;
170 col = cp % DpyCols;
171 break;
172 case CRTC_CurLocLo: /* Update cursor position in BIOS */
173 cp = row * DpyCols + col;
174 cp &= 0xff00;
175 cp |= value;
176 row = cp / DpyCols;
177 col = cp % DpyCols;
178 break;
179 default:
180 debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
181 port, value, crtc_index);
182 break;
184 case CRTC_IndexPortMono: /* Not used */
185 break;
186 case CRTC_DataPortMono: /* Not used */
187 break;
188 case ATC_WritePort:
189 if (set_atc_index)
190 atc_index = value;
191 else {
192 VGA_ATC[atc_index] = value;
193 switch (atc_index) {
194 default:
195 debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
196 port, value, crtc_index);
197 break;
200 set_atc_index = 1 - set_atc_index;
201 break;
202 case TSC_IndexPort:
203 tsc_index = value;
204 break;
205 case TSC_DataPort:
206 VGA_TSC[tsc_index] = value;
207 switch (tsc_index) {
208 default:
209 debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
210 port, value, crtc_index);
211 break;
213 break;
214 case GDC_IndexPort:
215 gdc_index = value;
216 break;
217 case GDC_DataPort:
218 VGA_GDC[gdc_index] = value;
219 #if 0
220 switch (gdc_index) {
221 default:
222 debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
223 port, value, crtc_index);
225 break;
227 #endif
228 break;
229 default:
230 debug(D_ALWAYS, "VGA: Unknown port 0x%4x\n", port);
231 break;
234 return;
235 #undef row
236 #undef col
239 void
240 video_init(void)
242 /* If we are running under X, get a connection to the X server and create
243 an empty window of size (1, 1). It makes a couple of init functions a
244 lot easier. */
245 if (xmode) {
246 init_window();
248 /* Set VGA emulator to a sane state */
249 init_vga();
251 /* Initialize mode 3 (text, 80x25, 16 colors) */
252 init_mode(3);
255 /* Define all known I/O port handlers */
256 if (!raw_kbd) {
257 define_input_port_handler(CRTC_IndexPortColor, video_inb);
258 define_input_port_handler(CRTC_DataPortColor, video_inb);
259 define_input_port_handler(ATC_ReadPort, video_inb);
260 define_input_port_handler(TSC_IndexPort, video_inb);
261 define_input_port_handler(TSC_DataPort, video_inb);
262 define_input_port_handler(GDC_IndexPort, video_inb);
263 define_input_port_handler(GDC_DataPort, video_inb);
264 define_input_port_handler(VGA_InputStatus1Port, video_inb);
266 define_output_port_handler(CRTC_IndexPortColor, video_outb);
267 define_output_port_handler(CRTC_DataPortColor, video_outb);
268 define_output_port_handler(ATC_WritePort, video_outb);
269 define_output_port_handler(TSC_IndexPort, video_outb);
270 define_output_port_handler(TSC_DataPort, video_outb);
271 define_output_port_handler(GDC_IndexPort, video_outb);
272 define_output_port_handler(GDC_DataPort, video_outb);
275 redirect0 = isatty(0) == 0 || !xmode ;
276 redirect1 = isatty(1) == 0 || !xmode ;
277 redirect2 = isatty(2) == 0 || !xmode ;
279 return;
282 void
283 video_bios_init(void)
285 u_char *p;
286 u_long vec;
288 if (raw_kbd)
289 return;
292 * Put the Video Save Table Pointer @ C000:0000
293 * Put the Secondary Video Save Table Pointer @ C000:0020
294 * Put the Display Combination Code table @ C000:0040
295 * Put the Video Parameter table @ C000:1000 - C000:2FFF
297 BIOS_SaveTablePointer = 0xC0000000;
299 vsp = (struct VideoSaveTable *)0xC0000L;
300 memset(vsp, 0, sizeof(struct VideoSaveTable));
301 svsp = (struct SecondaryVideoSaveTable *)0xC0020L;
303 vsp->video_parameter_table[0] = 0x1000;
304 vsp->video_parameter_table[1] = 0xC000;
306 vsp->secondary_save_table[0] = 0x0020;
307 vsp->secondary_save_table[1] = 0xC000;
309 svsp->display_combination_code_table[0] = 0x0040;
310 svsp->display_combination_code_table[1] = 0xC000;
312 p = (u_char *)0xC0040;
313 *p++ = 2; /* Only support 2 combinations currently */
314 *p++ = 1; /* Version # */
315 *p++ = 8; /* We won't use more than type 8 */
316 *p++ = 0; /* Reserved */
317 *p++ = 0; *p++ = 0; /* No Display No Display */
318 *p++ = 0; *p++ = 8; /* No Display VGA Color */
320 memcpy((void *)0xC1000, videoparams, sizeof(videoparams));
321 ivec[0x1d] = 0xC0001000L; /* Video Parameter Table */
323 ivec[0x42] = ivec[0x10]; /* Copy of video interrupt */
325 /* Put the current font at C000:3000; the pixels are copied in
326 'tty.c:load_font()'. */
327 ivec[0x1f] = 0xC0003000L;
328 ivec[0x43] = 0xC0003000L;
330 BIOSDATA[0x8a] = 1; /* Index into DCC table */
332 vec = insert_softint_trampoline();
333 ivec[0x10] = vec;
334 register_callback(vec, int10, "int 10");
337 /* Initialize the VGA emulator
339 XXX This is not nearly finished right now.
341 static void
342 init_vga(void)
344 int i;
346 /* Zero-fill 'dac_rgb' on allocation; the default (EGA) table has only
347 64 entries. */
348 dac_rgb = (struct dac_colors *)calloc(256, sizeof(struct dac_colors));
349 if (dac_rgb == NULL)
350 err(1, "Get memory for dac_rgb");
352 /* Copy the default DAC table to a working copy we can trash. */
353 for (i = 0; i < 64; i++)
354 dac_rgb[i] = dac_default64[i]; /* Structure copy */
356 /* Point 'palette[]' to the Attribute Controller space. We will only use
357 the first 16 slots. */
358 palette = VGA_ATC;
360 /* Get memory for the video RAM and adjust the plane pointers. */
361 vram = calloc(256 * 1024, 1); /* XXX */
362 if (vram == NULL)
363 warn("Could not get video memory; graphics modes not available.");
365 /* XXX There is probably a more efficient memory layout... */
366 vplane0 = vram;
367 vplane1 = vram + 0x10000;
368 vplane2 = vram + 0x20000;
369 vplane3 = vram + 0x30000;
371 VGA_InputStatus1 = 0;
375 * Initialize the requested video mode.
378 /* Indices into the video parameter table. We will use that array to
379 initialize the registers on startup and when the video mode changes. */
380 #define CRTC_Ofs 10
381 #define ATC_Ofs 35
382 #define TSC_Ofs 5
383 #define GDC_Ofs 55
384 #define MiscOutput_Ofs 9
386 void
387 init_mode(int mode)
389 vmode_t vmode;
390 int idx; /* Index into vmode */
391 int pidx; /* Index into videoparams */
393 debug(D_VIDEO, "VGA: Set video mode to 0x%02x\n", mode);
395 idx = find_vmode(mode & 0x7f);
396 if (idx == -1 || vmodelist[idx].type == NOMODE)
397 err(1, "Mode 0x%02x is not supported", mode);
398 vmode = vmodelist[idx];
399 pidx = vmode.paramindex;
401 /* Preset VGA registers. */
402 memcpy(VGA_CRTC, (u_int8_t *)&videoparams[pidx][CRTC_Ofs],
403 sizeof(VGA_CRTC));
404 memcpy(VGA_ATC, (u_int8_t *)&videoparams[pidx][ATC_Ofs],
405 sizeof(VGA_ATC));
406 /* Warning: the video parameter table does not contain the Sequencer's
407 Reset register. Its default value is 0x03.*/
408 VGA_TSC[TSC_Reset] = 0x03;
409 memcpy(VGA_TSC + 1, (u_int8_t *)&videoparams[pidx][TSC_Ofs],
410 sizeof(VGA_TSC) - 1);
411 memcpy(VGA_GDC, (u_int8_t *)&videoparams[pidx][GDC_Ofs],
412 sizeof(VGA_GDC));
413 VGA_MiscOutput = videoparams[pidx][MiscOutput_Ofs];
415 /* Paranoia */
416 if ((VGA_ATC[ATC_ModeCtrl] & 1) == 1 && vmode.type == TEXT)
417 err(1, "Text mode requested, but ATC switched to graphics mode!");
418 if ((VGA_ATC[ATC_ModeCtrl] & 1) == 0 && vmode.type == GRAPHICS)
419 err(1, "Graphics mode requested, but ATC switched to text mode!");
421 VideoMode = mode & 0x7f;
422 DpyCols = (u_int16_t)videoparams[pidx][0];
423 DpyPageSize = *(u_int16_t *)&videoparams[pidx][3];
424 ActivePageOfs = 0;
425 CursCol0 = 0;
426 CursRow0 = 0;
427 CursCol1 = 0;
428 CursRow1 = 0;
429 CursCol2 = 0;
430 CursRow2 = 0;
431 CursCol3 = 0;
432 CursRow3 = 0;
433 CursCol4 = 0;
434 CursRow4 = 0;
435 CursCol5 = 0;
436 CursRow5 = 0;
437 CursCol6 = 0;
438 CursRow6 = 0;
439 CursCol7 = 0;
440 CursRow7 = 0;
441 CursStart = VGA_CRTC[CRTC_CursStart];
442 CursEnd = VGA_CRTC[CRTC_CursEnd];
443 ActivePage = 0;
444 DpyRows = videoparams[pidx][1];
445 CharHeight = videoparams[pidx][2];
447 CRTCPort = vmode.numcolors > 1 ? CRTC_IndexPortColor : CRTC_IndexPortMono;
448 NumColors = vmode.numcolors;
449 NumPages = vmode.numpages;
450 VertResolution = vmode.vrescode;
451 vmem = (u_int16_t *)vmode.vmemaddr;
453 /* Copy VGA related BIOS variables from 'vga_status'. */
454 memcpy(&BIOS_VideoMode, &VideoMode, 33);
455 BIOS_DpyRows = DpyRows;
456 BIOS_CharHeight = CharHeight;
458 /* Load 'pixels[]' from default DAC values. */
459 update_pixels();
461 /* Update font. */
462 xfont = vmode.fontname;
463 load_font();
465 /* Resize window if necessary. */
466 resize_window();
468 /* Mmap video memory for the graphics modes. Write access to 0xa0000 -
469 0xaffff will generate a T_PAGEFAULT trap in VM86 mode (aside: why not a
470 SIGSEGV?), which is handled in 'trap.c:sigbus()'. */
471 if (vmode.type == GRAPHICS) {
472 vmem = mmap((void *)0xa0000, 64 * 1024, PROT_NONE,
473 MAP_ANON | MAP_FIXED | MAP_SHARED, -1, 0);
474 if (vmem == NULL)
475 fatal("Could not mmap() video memory");
477 /* Create an XImage to display the graphics screen. */
478 get_ximage();
479 } else {
480 int i;
482 get_lines();
483 if (mode & 0x80)
484 return;
485 /* Initialize video memory with black background, white foreground */
486 vattr = 0x0700;
487 for (i = 0; i < DpyPageSize / 2; ++i)
488 vmem[i] = vattr;
491 return;
494 /* Find the requested mode in the 'vmodelist' table. This function returns the
495 index into this table; we will also use the index for accessing the
496 'videoparams' array. */
497 int find_vmode(int mode)
499 unsigned i;
501 for (i = 0; i < NUMMODES; i++)
502 if (vmodelist[i].modenumber == mode)
503 return i;
505 return -1;
508 /* Handle access to the graphics memory.
510 Simply changing the protection for the memory is not enough, unfortunately.
511 It would only work for the 256 color modes, where a memory byte contains
512 the color value of one pixel. The 16 color modes (and 4 color modes) make
513 use of four bit planes which overlay the first 64K of video memory. The
514 bits are distributed into these bit planes according to the GDC state, so
515 we will have to emulate the CPU instructions (see 'cpu.c:emu_instr()').
517 Handling the 256 color modes will be a bit easier, once we support those at
518 all. */
520 vmem_pageflt(struct sigframe *sf)
522 regcontext_t *REGS = (regcontext_t *)(&sf->sf_uc.uc_mcontext);
524 /* The ATC's Mode Control register tells us whether 4 or 8 color bits are
525 used */
526 if (VGA_ATC[ATC_ModeCtrl] & (1 << 6)) {
527 /* 256 colors, allow writes; the protection will be set back to
528 PROT_READ at the next display update */
529 mprotect(vmem, 64 * 1024, PROT_READ | PROT_WRITE);
530 return 0;
533 /* There's no need to change the protection in the 16 color modes, we will
534 write to 'vram'. Just emulate the next instruction. */
535 return emu_instr(REGS);
538 /* We need to keep track of the latches' contents.*/
539 static u_int8_t latch0, latch1, latch2, latch3;
541 /* Read a byte from the video memory. 'vga_read()' is called from
542 'cpu.c:read_byte()' and will emulate the VGA read modes. */
543 u_int8_t
544 vga_read(u_int32_t addr)
546 u_int32_t dst;
548 /* 'addr' lies between 0xa0000 and 0xaffff. */
549 dst = addr - 0xa0000;
551 /* Fill latches. */
552 latch0 = vplane0[dst];
553 latch1 = vplane1[dst];
554 latch2 = vplane2[dst];
555 latch3 = vplane3[dst];
557 /* Select read mode. */
558 if ((VGA_GDC[GDC_Mode] & 0x80) == 0)
559 /* Read Mode 0; return the byte from the selected bit plane. */
560 return vram[dst + (VGA_GDC[GDC_ReadMapSelect] & 3) * 0x10000];
562 /* Read Mode 1 */
563 debug(D_ALWAYS, "VGA: Read Mode 1 not implemented\n");
564 return 0;
567 /* Write a byte to the video memory. 'vga_write()' is called from
568 'cpu.c:write_word()' and will emulate the VGA write modes. Not all four
569 modes are implemented yet, nor are the addressing modes (odd/even, chain4).
570 (NB: I think the latter will have to be done in 'tty_graphics_update()').
572 void
573 vga_write(u_int32_t addr, u_int8_t val)
575 u_int32_t dst;
576 u_int8_t c0, c1, c2, c3;
577 u_int8_t m0, m1, m2, m3;
578 u_int8_t mask;
580 #if 0
581 unsigned i;
583 debug(D_VIDEO, "VGA: Write 0x%02x to 0x%x\n", val, addr);
584 debug(D_VIDEO, " GDC: ");
585 for (i = 0; i < sizeof(VGA_GDC); i++)
586 debug(D_VIDEO, "%02x ", VGA_GDC[i]);
587 debug(D_VIDEO, "\n");
588 debug(D_VIDEO, " TSC: ");
589 for (i = 0; i < sizeof(VGA_TSC); i++)
590 debug(D_VIDEO, "%02x ", VGA_TSC[i]);
591 debug(D_VIDEO, "\n");
592 #endif
594 /* 'addr' lies between 0xa0000 and 0xaffff. */
595 dst = addr - 0xa0000;
597 c0 = latch0;
598 c1 = latch1;
599 c2 = latch2;
600 c3 = latch3;
602 /* Select write mode. */
603 switch (VGA_GDC[GDC_Mode] & 3) {
604 case 0:
605 mask = VGA_GDC[GDC_BitMask];
607 if (VGA_GDC[GDC_DataRotate] & 7)
608 debug(D_ALWAYS, "VGA: Data Rotate != 0\n");
610 /* Select function. */
611 switch (VGA_GDC[GDC_DataRotate] & 0x18) {
612 case 0x00: /* replace */
613 m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
614 m1 = VGA_GDC[GDC_SetReset] & 2 ? mask : 0x00;
615 m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
616 m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
618 c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 & ~mask : val & ~mask;
619 c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 & ~mask : val & ~mask;
620 c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 & ~mask : val & ~mask;
621 c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 & ~mask : val & ~mask;
623 c0 |= m0;
624 c1 |= m1;
625 c2 |= m2;
626 c3 |= m3;
627 break;
628 case 0x08: /* AND */
629 m0 = VGA_GDC[GDC_SetReset] & 1 ? 0xff : ~mask;
630 m1 = VGA_GDC[GDC_SetReset] & 2 ? 0xff : ~mask;
631 m2 = VGA_GDC[GDC_SetReset] & 4 ? 0xff : ~mask;
632 m3 = VGA_GDC[GDC_SetReset] & 8 ? 0xff : ~mask;
634 c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 & m0 : val & m0;
635 c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 & m1 : val & m1;
636 c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 & m2 : val & m2;
637 c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 & m3 : val & m3;
638 break;
639 case 0x10: /* OR */
640 m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
641 m1 = VGA_GDC[GDC_SetReset] & 2 ? mask : 0x00;
642 m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
643 m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
645 c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 | m0 : val | m0;
646 c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 | m1 : val | m1;
647 c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 | m2 : val | m2;
648 c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 | m3 : val | m3;
649 break;
650 case 0x18: /* XOR */
651 m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
652 m1 = VGA_GDC[GDC_SetReset] & 2 ? mask : 0x00;
653 m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
654 m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
656 c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 ^ m0 : val ^ m0;
657 c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 ^ m1 : val ^ m1;
658 c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 ^ m2 : val ^ m2;
659 c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 ^ m3 : val ^ m3;
660 break;
662 break;
663 case 1:
664 /* Just copy the latches' content to the desired destination
665 address. */
666 break;
667 case 2:
668 mask = VGA_GDC[GDC_BitMask];
670 /* select function */
671 switch (VGA_GDC[GDC_DataRotate] & 0x18) {
672 case 0x00: /* replace */
673 m0 = (val & 1 ? 0xff : 0x00) & mask;
674 m1 = (val & 2 ? 0xff : 0x00) & mask;
675 m2 = (val & 4 ? 0xff : 0x00) & mask;
676 m3 = (val & 8 ? 0xff : 0x00) & mask;
678 c0 &= ~mask;
679 c1 &= ~mask;
680 c2 &= ~mask;
681 c3 &= ~mask;
683 c0 |= m0;
684 c1 |= m1;
685 c2 |= m2;
686 c3 |= m3;
687 break;
688 case 0x08: /* AND */
689 m0 = (val & 1 ? 0xff : 0x00) | ~mask;
690 m1 = (val & 2 ? 0xff : 0x00) | ~mask;
691 m2 = (val & 4 ? 0xff : 0x00) | ~mask;
692 m3 = (val & 8 ? 0xff : 0x00) | ~mask;
694 c0 &= m0;
695 c1 &= m1;
696 c2 &= m2;
697 c3 &= m3;
698 break;
699 case 0x10: /* OR */
700 m0 = (val & 1 ? 0xff : 0x00) & mask;
701 m1 = (val & 2 ? 0xff : 0x00) & mask;
702 m2 = (val & 4 ? 0xff : 0x00) & mask;
703 m3 = (val & 8 ? 0xff : 0x00) & mask;
705 c0 |= m0;
706 c1 |= m1;
707 c2 |= m2;
708 c3 |= m3;
709 break;
710 case 0x18: /* XOR */
711 m0 = (val & 1 ? 0xff : 0x00) & mask;
712 m1 = (val & 2 ? 0xff : 0x00) & mask;
713 m2 = (val & 4 ? 0xff : 0x00) & mask;
714 m3 = (val & 8 ? 0xff : 0x00) & mask;
716 c0 ^= m0;
717 c1 ^= m1;
718 c2 ^= m2;
719 c3 ^= m3;
720 break;
722 break;
723 case 3:
724 /* not yet */
725 debug(D_ALWAYS, "VGA: Write Mode 3 not implemented\n");
726 break;
729 /* Write back changed byte, depending on Map Mask register. */
730 if (VGA_TSC[TSC_MapMask] & 1)
731 vplane0[dst] = c0;
732 if (VGA_TSC[TSC_MapMask] & 2)
733 vplane1[dst] = c1;
734 if (VGA_TSC[TSC_MapMask] & 4)
735 vplane2[dst] = c2;
736 if (VGA_TSC[TSC_MapMask] & 8)
737 vplane3[dst] = c3;
739 return;