1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Copyright 2018 Joyent, Inc.
31 */
32
33
34 #include <sys/param.h>
35
36 #include <assert.h>
37 #include <pthread.h>
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include <machine/vmm.h>
44
45 #include "bhyvegc.h"
46 #include "console.h"
47 #include "inout.h"
48 #include "mem.h"
49 #include "vga.h"
50
51 #define KB (1024UL)
52 #define MB (1024 * 1024UL)
53
54 struct vga_softc {
55 struct mem_range mr;
56
57 struct bhyvegc *gc;
58 int gc_width;
59 int gc_height;
60 struct bhyvegc_image *gc_image;
61
62 uint8_t *vga_ram;
63
64 /*
65 * General registers
66 */
67 uint8_t vga_misc;
68 uint8_t vga_sts1;
69
70 /*
71 * Sequencer
72 */
73 struct {
74 int seq_index;
75 uint8_t seq_reset;
76 uint8_t seq_clock_mode;
77 int seq_cm_dots;
78 uint8_t seq_map_mask;
79 uint8_t seq_cmap_sel;
80 int seq_cmap_pri_off;
81 int seq_cmap_sec_off;
82 uint8_t seq_mm;
83 } vga_seq;
84
85 /*
86 * CRT Controller
87 */
88 struct {
89 int crtc_index;
90 uint8_t crtc_mode_ctrl;
91 uint8_t crtc_horiz_total;
92 uint8_t crtc_horiz_disp_end;
93 uint8_t crtc_start_horiz_blank;
94 uint8_t crtc_end_horiz_blank;
95 uint8_t crtc_start_horiz_retrace;
96 uint8_t crtc_end_horiz_retrace;
97 uint8_t crtc_vert_total;
98 uint8_t crtc_overflow;
99 uint8_t crtc_present_row_scan;
100 uint8_t crtc_max_scan_line;
101 uint8_t crtc_cursor_start;
102 uint8_t crtc_cursor_on;
103 uint8_t crtc_cursor_end;
104 uint8_t crtc_start_addr_high;
105 uint8_t crtc_start_addr_low;
106 uint16_t crtc_start_addr;
107 uint8_t crtc_cursor_loc_low;
108 uint8_t crtc_cursor_loc_high;
109 uint16_t crtc_cursor_loc;
110 uint8_t crtc_vert_retrace_start;
111 uint8_t crtc_vert_retrace_end;
112 uint8_t crtc_vert_disp_end;
113 uint8_t crtc_offset;
114 uint8_t crtc_underline_loc;
115 uint8_t crtc_start_vert_blank;
116 uint8_t crtc_end_vert_blank;
117 uint8_t crtc_line_compare;
118 } vga_crtc;
119
120 /*
121 * Graphics Controller
122 */
123 struct {
124 int gc_index;
125 uint8_t gc_set_reset;
126 uint8_t gc_enb_set_reset;
127 uint8_t gc_color_compare;
128 uint8_t gc_rotate;
129 uint8_t gc_op;
130 uint8_t gc_read_map_sel;
131 uint8_t gc_mode;
132 bool gc_mode_c4; /* chain 4 */
133 bool gc_mode_oe; /* odd/even */
134 uint8_t gc_mode_rm; /* read mode */
135 uint8_t gc_mode_wm; /* write mode */
136 uint8_t gc_misc;
137 uint8_t gc_misc_gm; /* graphics mode */
138 uint8_t gc_misc_mm; /* memory map */
139 uint8_t gc_color_dont_care;
140 uint8_t gc_bit_mask;
141 uint8_t gc_latch0;
142 uint8_t gc_latch1;
143 uint8_t gc_latch2;
144 uint8_t gc_latch3;
145 } vga_gc;
146
147 /*
148 * Attribute Controller
149 */
150 struct {
151 int atc_flipflop;
152 int atc_index;
153 uint8_t atc_palette[16];
154 uint8_t atc_mode;
155 uint8_t atc_overscan_color;
156 uint8_t atc_color_plane_enb;
157 uint8_t atc_horiz_pixel_panning;
158 uint8_t atc_color_select;
159 uint8_t atc_color_select_45;
160 uint8_t atc_color_select_67;
161 } vga_atc;
162
163 /*
164 * DAC
165 */
166 struct {
167 uint8_t dac_state;
168 uint8_t dac_rd_index;
169 uint8_t dac_rd_subindex;
170 uint8_t dac_wr_index;
171 uint8_t dac_wr_subindex;
172 uint8_t dac_palette[3 * 256];
173 uint32_t dac_palette_rgb[256];
174 } vga_dac;
175 };
176
177 static bool
vga_in_reset(struct vga_softc * sc)178 vga_in_reset(struct vga_softc *sc)
179 {
180 return (((sc->vga_seq.seq_clock_mode & SEQ_CM_SO) != 0) ||
181 ((sc->vga_seq.seq_reset & SEQ_RESET_ASYNC) == 0) ||
182 ((sc->vga_seq.seq_reset & SEQ_RESET_SYNC) == 0) ||
183 ((sc->vga_crtc.crtc_mode_ctrl & CRTC_MC_TE) == 0));
184 }
185
186 static void
vga_check_size(struct bhyvegc * gc,struct vga_softc * sc)187 vga_check_size(struct bhyvegc *gc, struct vga_softc *sc)
188 {
189 int old_width, old_height;
190
191 if (vga_in_reset(sc))
192 return;
193
194 //old_width = sc->gc_width;
195 //old_height = sc->gc_height;
196 old_width = sc->gc_image->width;
197 old_height = sc->gc_image->height;
198
199 /*
200 * Horizontal Display End: For text modes this is the number
201 * of characters. For graphics modes this is the number of
202 * pixels per scanlines divided by the number of pixels per
203 * character clock.
204 */
205 sc->gc_width = (sc->vga_crtc.crtc_horiz_disp_end + 1) *
206 sc->vga_seq.seq_cm_dots;
207
208 sc->gc_height = (sc->vga_crtc.crtc_vert_disp_end |
209 (((sc->vga_crtc.crtc_overflow & CRTC_OF_VDE8) >> CRTC_OF_VDE8_SHIFT) << 8) |
210 (((sc->vga_crtc.crtc_overflow & CRTC_OF_VDE9) >> CRTC_OF_VDE9_SHIFT) << 9)) + 1;
211
212 if (old_width != sc->gc_width || old_height != sc->gc_height)
213 bhyvegc_resize(gc, sc->gc_width, sc->gc_height);
214 }
215
216 static uint32_t
vga_get_pixel(struct vga_softc * sc,int x,int y)217 vga_get_pixel(struct vga_softc *sc, int x, int y)
218 {
219 int offset;
220 int bit;
221 uint8_t data;
222 uint8_t idx;
223
224 offset = (y * sc->gc_width / 8) + (x / 8);
225 bit = 7 - (x % 8);
226
227 data = (((sc->vga_ram[offset + 0 * 64*KB] >> bit) & 0x1) << 0) |
228 (((sc->vga_ram[offset + 1 * 64*KB] >> bit) & 0x1) << 1) |
229 (((sc->vga_ram[offset + 2 * 64*KB] >> bit) & 0x1) << 2) |
230 (((sc->vga_ram[offset + 3 * 64*KB] >> bit) & 0x1) << 3);
231
232 data &= sc->vga_atc.atc_color_plane_enb;
233
234 if (sc->vga_atc.atc_mode & ATC_MC_IPS) {
235 idx = sc->vga_atc.atc_palette[data] & 0x0f;
236 idx |= sc->vga_atc.atc_color_select_45;
237 } else {
238 idx = sc->vga_atc.atc_palette[data];
239 }
240 idx |= sc->vga_atc.atc_color_select_67;
241
242 return (sc->vga_dac.dac_palette_rgb[idx]);
243 }
244
245 static void
vga_render_graphics(struct vga_softc * sc)246 vga_render_graphics(struct vga_softc *sc)
247 {
248 int x, y;
249
250 for (y = 0; y < sc->gc_height; y++) {
251 for (x = 0; x < sc->gc_width; x++) {
252 int offset;
253
254 offset = y * sc->gc_width + x;
255 sc->gc_image->data[offset] = vga_get_pixel(sc, x, y);
256 }
257 }
258 }
259
260 static uint32_t
vga_get_text_pixel(struct vga_softc * sc,int x,int y)261 vga_get_text_pixel(struct vga_softc *sc, int x, int y)
262 {
263 int dots, offset, bit, font_offset;
264 uint8_t ch, attr, font;
265 uint8_t idx;
266
267 dots = sc->vga_seq.seq_cm_dots;
268
269 offset = 2 * sc->vga_crtc.crtc_start_addr;
270 offset += (y / 16 * sc->gc_width / dots) * 2 + (x / dots) * 2;
271
272 bit = 7 - (x % dots > 7 ? 7 : x % dots);
273
274 ch = sc->vga_ram[offset + 0 * 64*KB];
275 attr = sc->vga_ram[offset + 1 * 64*KB];
276
277 if (sc->vga_crtc.crtc_cursor_on &&
278 (offset == (sc->vga_crtc.crtc_cursor_loc * 2)) &&
279 ((y % 16) >= (sc->vga_crtc.crtc_cursor_start & CRTC_CS_CS)) &&
280 ((y % 16) <= (sc->vga_crtc.crtc_cursor_end & CRTC_CE_CE))) {
281 idx = sc->vga_atc.atc_palette[attr & 0xf];
282 return (sc->vga_dac.dac_palette_rgb[idx]);
283 }
284
285 if ((sc->vga_seq.seq_mm & SEQ_MM_EM) &&
286 sc->vga_seq.seq_cmap_pri_off != sc->vga_seq.seq_cmap_sec_off) {
287 if (attr & 0x8)
288 font_offset = sc->vga_seq.seq_cmap_pri_off +
289 (ch << 5) + y % 16;
290 else
291 font_offset = sc->vga_seq.seq_cmap_sec_off +
292 (ch << 5) + y % 16;
293 attr &= ~0x8;
294 } else {
295 font_offset = (ch << 5) + y % 16;
296 }
297
298 font = sc->vga_ram[font_offset + 2 * 64*KB];
299
300 if (font & (1 << bit))
301 idx = sc->vga_atc.atc_palette[attr & 0xf];
302 else
303 idx = sc->vga_atc.atc_palette[attr >> 4];
304
305 return (sc->vga_dac.dac_palette_rgb[idx]);
306 }
307
308 static void
vga_render_text(struct vga_softc * sc)309 vga_render_text(struct vga_softc *sc)
310 {
311 int x, y;
312
313 for (y = 0; y < sc->gc_height; y++) {
314 for (x = 0; x < sc->gc_width; x++) {
315 int offset;
316
317 offset = y * sc->gc_width + x;
318 sc->gc_image->data[offset] = vga_get_text_pixel(sc, x, y);
319 }
320 }
321 }
322
323 void
vga_render(struct bhyvegc * gc,void * arg)324 vga_render(struct bhyvegc *gc, void *arg)
325 {
326 struct vga_softc *sc = arg;
327
328 vga_check_size(gc, sc);
329
330 if (vga_in_reset(sc)) {
331 memset(sc->gc_image->data, 0,
332 sc->gc_image->width * sc->gc_image->height *
333 sizeof (uint32_t));
334 return;
335 }
336
337 if (sc->vga_gc.gc_misc_gm && (sc->vga_atc.atc_mode & ATC_MC_GA))
338 vga_render_graphics(sc);
339 else
340 vga_render_text(sc);
341 }
342
343 static uint64_t
vga_mem_rd_handler(uint64_t addr,void * arg1)344 vga_mem_rd_handler(uint64_t addr, void *arg1)
345 {
346 struct vga_softc *sc = arg1;
347 uint8_t map_sel;
348 int offset;
349
350 offset = addr;
351 switch (sc->vga_gc.gc_misc_mm) {
352 case 0x0:
353 /*
354 * extended mode: base 0xa0000 size 128k
355 */
356 offset -=0xa0000;
357 offset &= (128 * KB - 1);
358 break;
359 case 0x1:
360 /*
361 * EGA/VGA mode: base 0xa0000 size 64k
362 */
363 offset -=0xa0000;
364 offset &= (64 * KB - 1);
365 break;
366 case 0x2:
367 /*
368 * monochrome text mode: base 0xb0000 size 32kb
369 */
370 #ifdef __FreeBSD__
371 assert(0);
372 #else
373 abort();
374 #endif
375 case 0x3:
376 /*
377 * color text mode and CGA: base 0xb8000 size 32kb
378 */
379 offset -=0xb8000;
380 offset &= (32 * KB - 1);
381 break;
382 }
383
384 /* Fill latches. */
385 sc->vga_gc.gc_latch0 = sc->vga_ram[offset + 0*64*KB];
386 sc->vga_gc.gc_latch1 = sc->vga_ram[offset + 1*64*KB];
387 sc->vga_gc.gc_latch2 = sc->vga_ram[offset + 2*64*KB];
388 sc->vga_gc.gc_latch3 = sc->vga_ram[offset + 3*64*KB];
389
390 if (sc->vga_gc.gc_mode_rm) {
391 /* read mode 1 */
392 assert(0);
393 }
394
395 map_sel = sc->vga_gc.gc_read_map_sel;
396 if (sc->vga_gc.gc_mode_oe) {
397 map_sel |= (offset & 1);
398 offset &= ~1;
399 }
400
401 /* read mode 0: return the byte from the selected plane. */
402 offset += map_sel * 64*KB;
403
404 return (sc->vga_ram[offset]);
405 }
406
407 static void
vga_mem_wr_handler(uint64_t addr,uint8_t val,void * arg1)408 vga_mem_wr_handler(uint64_t addr, uint8_t val, void *arg1)
409 {
410 struct vga_softc *sc = arg1;
411 uint8_t c0, c1, c2, c3;
412 uint8_t m0, m1, m2, m3;
413 uint8_t set_reset;
414 uint8_t enb_set_reset;
415 uint8_t mask;
416 int offset;
417
418 offset = addr;
419 switch (sc->vga_gc.gc_misc_mm) {
420 case 0x0:
421 /*
422 * extended mode: base 0xa0000 size 128kb
423 */
424 offset -=0xa0000;
425 offset &= (128 * KB - 1);
426 break;
427 case 0x1:
428 /*
429 * EGA/VGA mode: base 0xa0000 size 64kb
430 */
431 offset -=0xa0000;
432 offset &= (64 * KB - 1);
433 break;
434 case 0x2:
435 /*
436 * monochrome text mode: base 0xb0000 size 32kb
437 */
438 #ifdef __FreeBSD__
439 assert(0);
440 #else
441 abort();
442 #endif
443 case 0x3:
444 /*
445 * color text mode and CGA: base 0xb8000 size 32kb
446 */
447 offset -=0xb8000;
448 offset &= (32 * KB - 1);
449 break;
450 }
451
452 set_reset = sc->vga_gc.gc_set_reset;
453 enb_set_reset = sc->vga_gc.gc_enb_set_reset;
454
455 c0 = sc->vga_gc.gc_latch0;
456 c1 = sc->vga_gc.gc_latch1;
457 c2 = sc->vga_gc.gc_latch2;
458 c3 = sc->vga_gc.gc_latch3;
459
460 switch (sc->vga_gc.gc_mode_wm) {
461 case 0:
462 /* write mode 0 */
463 mask = sc->vga_gc.gc_bit_mask;
464
465 val = (val >> sc->vga_gc.gc_rotate) |
466 (val << (8 - sc->vga_gc.gc_rotate));
467
468 switch (sc->vga_gc.gc_op) {
469 case 0x00: /* replace */
470 m0 = (set_reset & 1) ? mask : 0x00;
471 m1 = (set_reset & 2) ? mask : 0x00;
472 m2 = (set_reset & 4) ? mask : 0x00;
473 m3 = (set_reset & 8) ? mask : 0x00;
474
475 c0 = (enb_set_reset & 1) ? (c0 & ~mask) : (val & mask);
476 c1 = (enb_set_reset & 2) ? (c1 & ~mask) : (val & mask);
477 c2 = (enb_set_reset & 4) ? (c2 & ~mask) : (val & mask);
478 c3 = (enb_set_reset & 8) ? (c3 & ~mask) : (val & mask);
479
480 c0 |= m0;
481 c1 |= m1;
482 c2 |= m2;
483 c3 |= m3;
484 break;
485 case 0x08: /* AND */
486 m0 = set_reset & 1 ? 0xff : ~mask;
487 m1 = set_reset & 2 ? 0xff : ~mask;
488 m2 = set_reset & 4 ? 0xff : ~mask;
489 m3 = set_reset & 8 ? 0xff : ~mask;
490
491 c0 = enb_set_reset & 1 ? c0 & m0 : val & m0;
492 c1 = enb_set_reset & 2 ? c1 & m1 : val & m1;
493 c2 = enb_set_reset & 4 ? c2 & m2 : val & m2;
494 c3 = enb_set_reset & 8 ? c3 & m3 : val & m3;
495 break;
496 case 0x10: /* OR */
497 m0 = set_reset & 1 ? mask : 0x00;
498 m1 = set_reset & 2 ? mask : 0x00;
499 m2 = set_reset & 4 ? mask : 0x00;
500 m3 = set_reset & 8 ? mask : 0x00;
501
502 c0 = enb_set_reset & 1 ? c0 | m0 : val | m0;
503 c1 = enb_set_reset & 2 ? c1 | m1 : val | m1;
504 c2 = enb_set_reset & 4 ? c2 | m2 : val | m2;
505 c3 = enb_set_reset & 8 ? c3 | m3 : val | m3;
506 break;
507 case 0x18: /* XOR */
508 m0 = set_reset & 1 ? mask : 0x00;
509 m1 = set_reset & 2 ? mask : 0x00;
510 m2 = set_reset & 4 ? mask : 0x00;
511 m3 = set_reset & 8 ? mask : 0x00;
512
513 c0 = enb_set_reset & 1 ? c0 ^ m0 : val ^ m0;
514 c1 = enb_set_reset & 2 ? c1 ^ m1 : val ^ m1;
515 c2 = enb_set_reset & 4 ? c2 ^ m2 : val ^ m2;
516 c3 = enb_set_reset & 8 ? c3 ^ m3 : val ^ m3;
517 break;
518 }
519 break;
520 case 1:
521 /* write mode 1 */
522 break;
523 case 2:
524 /* write mode 2 */
525 mask = sc->vga_gc.gc_bit_mask;
526
527 switch (sc->vga_gc.gc_op) {
528 case 0x00: /* replace */
529 m0 = (val & 1 ? 0xff : 0x00) & mask;
530 m1 = (val & 2 ? 0xff : 0x00) & mask;
531 m2 = (val & 4 ? 0xff : 0x00) & mask;
532 m3 = (val & 8 ? 0xff : 0x00) & mask;
533
534 c0 &= ~mask;
535 c1 &= ~mask;
536 c2 &= ~mask;
537 c3 &= ~mask;
538
539 c0 |= m0;
540 c1 |= m1;
541 c2 |= m2;
542 c3 |= m3;
543 break;
544 case 0x08: /* AND */
545 m0 = (val & 1 ? 0xff : 0x00) | ~mask;
546 m1 = (val & 2 ? 0xff : 0x00) | ~mask;
547 m2 = (val & 4 ? 0xff : 0x00) | ~mask;
548 m3 = (val & 8 ? 0xff : 0x00) | ~mask;
549
550 c0 &= m0;
551 c1 &= m1;
552 c2 &= m2;
553 c3 &= m3;
554 break;
555 case 0x10: /* OR */
556 m0 = (val & 1 ? 0xff : 0x00) & mask;
557 m1 = (val & 2 ? 0xff : 0x00) & mask;
558 m2 = (val & 4 ? 0xff : 0x00) & mask;
559 m3 = (val & 8 ? 0xff : 0x00) & mask;
560
561 c0 |= m0;
562 c1 |= m1;
563 c2 |= m2;
564 c3 |= m3;
565 break;
566 case 0x18: /* XOR */
567 m0 = (val & 1 ? 0xff : 0x00) & mask;
568 m1 = (val & 2 ? 0xff : 0x00) & mask;
569 m2 = (val & 4 ? 0xff : 0x00) & mask;
570 m3 = (val & 8 ? 0xff : 0x00) & mask;
571
572 c0 ^= m0;
573 c1 ^= m1;
574 c2 ^= m2;
575 c3 ^= m3;
576 break;
577 }
578 break;
579 case 3:
580 /* write mode 3 */
581 mask = sc->vga_gc.gc_bit_mask & val;
582
583 val = (val >> sc->vga_gc.gc_rotate) |
584 (val << (8 - sc->vga_gc.gc_rotate));
585
586 switch (sc->vga_gc.gc_op) {
587 case 0x00: /* replace */
588 m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
589 m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
590 m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
591 m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
592
593 c0 &= ~mask;
594 c1 &= ~mask;
595 c2 &= ~mask;
596 c3 &= ~mask;
597
598 c0 |= m0;
599 c1 |= m1;
600 c2 |= m2;
601 c3 |= m3;
602 break;
603 case 0x08: /* AND */
604 m0 = (set_reset & 1 ? 0xff : 0x00) | ~mask;
605 m1 = (set_reset & 2 ? 0xff : 0x00) | ~mask;
606 m2 = (set_reset & 4 ? 0xff : 0x00) | ~mask;
607 m3 = (set_reset & 8 ? 0xff : 0x00) | ~mask;
608
609 c0 &= m0;
610 c1 &= m1;
611 c2 &= m2;
612 c3 &= m3;
613 break;
614 case 0x10: /* OR */
615 m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
616 m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
617 m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
618 m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
619
620 c0 |= m0;
621 c1 |= m1;
622 c2 |= m2;
623 c3 |= m3;
624 break;
625 case 0x18: /* XOR */
626 m0 = (set_reset & 1 ? 0xff : 0x00) & mask;
627 m1 = (set_reset & 2 ? 0xff : 0x00) & mask;
628 m2 = (set_reset & 4 ? 0xff : 0x00) & mask;
629 m3 = (set_reset & 8 ? 0xff : 0x00) & mask;
630
631 c0 ^= m0;
632 c1 ^= m1;
633 c2 ^= m2;
634 c3 ^= m3;
635 break;
636 }
637 break;
638 }
639
640 if (sc->vga_gc.gc_mode_oe) {
641 if (offset & 1) {
642 offset &= ~1;
643 if (sc->vga_seq.seq_map_mask & 2)
644 sc->vga_ram[offset + 1*64*KB] = c1;
645 if (sc->vga_seq.seq_map_mask & 8)
646 sc->vga_ram[offset + 3*64*KB] = c3;
647 } else {
648 if (sc->vga_seq.seq_map_mask & 1)
649 sc->vga_ram[offset + 0*64*KB] = c0;
650 if (sc->vga_seq.seq_map_mask & 4)
651 sc->vga_ram[offset + 2*64*KB] = c2;
652 }
653 } else {
654 if (sc->vga_seq.seq_map_mask & 1)
655 sc->vga_ram[offset + 0*64*KB] = c0;
656 if (sc->vga_seq.seq_map_mask & 2)
657 sc->vga_ram[offset + 1*64*KB] = c1;
658 if (sc->vga_seq.seq_map_mask & 4)
659 sc->vga_ram[offset + 2*64*KB] = c2;
660 if (sc->vga_seq.seq_map_mask & 8)
661 sc->vga_ram[offset + 3*64*KB] = c3;
662 }
663 }
664
665 static int
vga_mem_handler(struct vcpu * vcpu __unused,int dir,uint64_t addr,int size,uint64_t * val,void * arg1,long arg2 __unused)666 vga_mem_handler(struct vcpu *vcpu __unused, int dir, uint64_t addr, int size,
667 uint64_t *val, void *arg1, long arg2 __unused)
668 {
669 if (dir == MEM_F_WRITE) {
670 switch (size) {
671 case 1:
672 vga_mem_wr_handler(addr, *val, arg1);
673 break;
674 case 2:
675 vga_mem_wr_handler(addr, *val, arg1);
676 vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
677 break;
678 case 4:
679 vga_mem_wr_handler(addr, *val, arg1);
680 vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
681 vga_mem_wr_handler(addr + 2, *val >> 16, arg1);
682 vga_mem_wr_handler(addr + 3, *val >> 24, arg1);
683 break;
684 case 8:
685 vga_mem_wr_handler(addr, *val, arg1);
686 vga_mem_wr_handler(addr + 1, *val >> 8, arg1);
687 vga_mem_wr_handler(addr + 2, *val >> 16, arg1);
688 vga_mem_wr_handler(addr + 3, *val >> 24, arg1);
689 vga_mem_wr_handler(addr + 4, *val >> 32, arg1);
690 vga_mem_wr_handler(addr + 5, *val >> 40, arg1);
691 vga_mem_wr_handler(addr + 6, *val >> 48, arg1);
692 vga_mem_wr_handler(addr + 7, *val >> 56, arg1);
693 break;
694 }
695 } else {
696 switch (size) {
697 case 1:
698 *val = vga_mem_rd_handler(addr, arg1);
699 break;
700 case 2:
701 *val = vga_mem_rd_handler(addr, arg1);
702 *val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
703 break;
704 case 4:
705 *val = vga_mem_rd_handler(addr, arg1);
706 *val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
707 *val |= vga_mem_rd_handler(addr + 2, arg1) << 16;
708 *val |= vga_mem_rd_handler(addr + 3, arg1) << 24;
709 break;
710 case 8:
711 *val = vga_mem_rd_handler(addr, arg1);
712 *val |= vga_mem_rd_handler(addr + 1, arg1) << 8;
713 *val |= vga_mem_rd_handler(addr + 2, arg1) << 16;
714 *val |= vga_mem_rd_handler(addr + 3, arg1) << 24;
715 *val |= vga_mem_rd_handler(addr + 4, arg1) << 32;
716 *val |= vga_mem_rd_handler(addr + 5, arg1) << 40;
717 *val |= vga_mem_rd_handler(addr + 6, arg1) << 48;
718 *val |= vga_mem_rd_handler(addr + 7, arg1) << 56;
719 break;
720 }
721 }
722
723 return (0);
724 }
725
726 static int
vga_port_in_handler(struct vmctx * ctx,int in,int port,int bytes,uint8_t * val,void * arg)727 vga_port_in_handler(struct vmctx *ctx, int in, int port, int bytes,
728 uint8_t *val, void *arg)
729 {
730 struct vga_softc *sc = arg;
731
732 switch (port) {
733 case CRTC_IDX_MONO_PORT:
734 case CRTC_IDX_COLOR_PORT:
735 *val = sc->vga_crtc.crtc_index;
736 break;
737 case CRTC_DATA_MONO_PORT:
738 case CRTC_DATA_COLOR_PORT:
739 switch (sc->vga_crtc.crtc_index) {
740 case CRTC_HORIZ_TOTAL:
741 *val = sc->vga_crtc.crtc_horiz_total;
742 break;
743 case CRTC_HORIZ_DISP_END:
744 *val = sc->vga_crtc.crtc_horiz_disp_end;
745 break;
746 case CRTC_START_HORIZ_BLANK:
747 *val = sc->vga_crtc.crtc_start_horiz_blank;
748 break;
749 case CRTC_END_HORIZ_BLANK:
750 *val = sc->vga_crtc.crtc_end_horiz_blank;
751 break;
752 case CRTC_START_HORIZ_RETRACE:
753 *val = sc->vga_crtc.crtc_start_horiz_retrace;
754 break;
755 case CRTC_END_HORIZ_RETRACE:
756 *val = sc->vga_crtc.crtc_end_horiz_retrace;
757 break;
758 case CRTC_VERT_TOTAL:
759 *val = sc->vga_crtc.crtc_vert_total;
760 break;
761 case CRTC_OVERFLOW:
762 *val = sc->vga_crtc.crtc_overflow;
763 break;
764 case CRTC_PRESET_ROW_SCAN:
765 *val = sc->vga_crtc.crtc_present_row_scan;
766 break;
767 case CRTC_MAX_SCAN_LINE:
768 *val = sc->vga_crtc.crtc_max_scan_line;
769 break;
770 case CRTC_CURSOR_START:
771 *val = sc->vga_crtc.crtc_cursor_start;
772 break;
773 case CRTC_CURSOR_END:
774 *val = sc->vga_crtc.crtc_cursor_end;
775 break;
776 case CRTC_START_ADDR_HIGH:
777 *val = sc->vga_crtc.crtc_start_addr_high;
778 break;
779 case CRTC_START_ADDR_LOW:
780 *val = sc->vga_crtc.crtc_start_addr_low;
781 break;
782 case CRTC_CURSOR_LOC_HIGH:
783 *val = sc->vga_crtc.crtc_cursor_loc_high;
784 break;
785 case CRTC_CURSOR_LOC_LOW:
786 *val = sc->vga_crtc.crtc_cursor_loc_low;
787 break;
788 case CRTC_VERT_RETRACE_START:
789 *val = sc->vga_crtc.crtc_vert_retrace_start;
790 break;
791 case CRTC_VERT_RETRACE_END:
792 *val = sc->vga_crtc.crtc_vert_retrace_end;
793 break;
794 case CRTC_VERT_DISP_END:
795 *val = sc->vga_crtc.crtc_vert_disp_end;
796 break;
797 case CRTC_OFFSET:
798 *val = sc->vga_crtc.crtc_offset;
799 break;
800 case CRTC_UNDERLINE_LOC:
801 *val = sc->vga_crtc.crtc_underline_loc;
802 break;
803 case CRTC_START_VERT_BLANK:
804 *val = sc->vga_crtc.crtc_start_vert_blank;
805 break;
806 case CRTC_END_VERT_BLANK:
807 *val = sc->vga_crtc.crtc_end_vert_blank;
808 break;
809 case CRTC_MODE_CONTROL:
810 *val = sc->vga_crtc.crtc_mode_ctrl;
811 break;
812 case CRTC_LINE_COMPARE:
813 *val = sc->vga_crtc.crtc_line_compare;
814 break;
815 default:
816 //printf("XXX VGA CRTC: inb 0x%04x at index %d\n", port, sc->vga_crtc.crtc_index);
817 assert(0);
818 break;
819 }
820 break;
821 case ATC_IDX_PORT:
822 *val = sc->vga_atc.atc_index;
823 break;
824 case ATC_DATA_PORT:
825 switch (sc->vga_atc.atc_index) {
826 case ATC_PALETTE0 ... ATC_PALETTE15:
827 *val = sc->vga_atc.atc_palette[sc->vga_atc.atc_index];
828 break;
829 case ATC_MODE_CONTROL:
830 *val = sc->vga_atc.atc_mode;
831 break;
832 case ATC_OVERSCAN_COLOR:
833 *val = sc->vga_atc.atc_overscan_color;
834 break;
835 case ATC_COLOR_PLANE_ENABLE:
836 *val = sc->vga_atc.atc_color_plane_enb;
837 break;
838 case ATC_HORIZ_PIXEL_PANNING:
839 *val = sc->vga_atc.atc_horiz_pixel_panning;
840 break;
841 case ATC_COLOR_SELECT:
842 *val = sc->vga_atc.atc_color_select;
843 break;
844 default:
845 //printf("XXX VGA ATC inb 0x%04x at index %d\n", port , sc->vga_atc.atc_index);
846 assert(0);
847 break;
848 }
849 break;
850 case SEQ_IDX_PORT:
851 *val = sc->vga_seq.seq_index;
852 break;
853 case SEQ_DATA_PORT:
854 switch (sc->vga_seq.seq_index) {
855 case SEQ_RESET:
856 *val = sc->vga_seq.seq_reset;
857 break;
858 case SEQ_CLOCKING_MODE:
859 *val = sc->vga_seq.seq_clock_mode;
860 break;
861 case SEQ_MAP_MASK:
862 *val = sc->vga_seq.seq_map_mask;
863 break;
864 case SEQ_CHAR_MAP_SELECT:
865 *val = sc->vga_seq.seq_cmap_sel;
866 break;
867 case SEQ_MEMORY_MODE:
868 *val = sc->vga_seq.seq_mm;
869 break;
870 default:
871 //printf("XXX VGA SEQ: inb 0x%04x at index %d\n", port, sc->vga_seq.seq_index);
872 assert(0);
873 break;
874 }
875 break;
876 case DAC_DATA_PORT:
877 *val = sc->vga_dac.dac_palette[3 * sc->vga_dac.dac_rd_index +
878 sc->vga_dac.dac_rd_subindex];
879 sc->vga_dac.dac_rd_subindex++;
880 if (sc->vga_dac.dac_rd_subindex == 3) {
881 sc->vga_dac.dac_rd_index++;
882 sc->vga_dac.dac_rd_subindex = 0;
883 }
884 break;
885 case GC_IDX_PORT:
886 *val = sc->vga_gc.gc_index;
887 break;
888 case GC_DATA_PORT:
889 switch (sc->vga_gc.gc_index) {
890 case GC_SET_RESET:
891 *val = sc->vga_gc.gc_set_reset;
892 break;
893 case GC_ENABLE_SET_RESET:
894 *val = sc->vga_gc.gc_enb_set_reset;
895 break;
896 case GC_COLOR_COMPARE:
897 *val = sc->vga_gc.gc_color_compare;
898 break;
899 case GC_DATA_ROTATE:
900 *val = sc->vga_gc.gc_rotate;
901 break;
902 case GC_READ_MAP_SELECT:
903 *val = sc->vga_gc.gc_read_map_sel;
904 break;
905 case GC_MODE:
906 *val = sc->vga_gc.gc_mode;
907 break;
908 case GC_MISCELLANEOUS:
909 *val = sc->vga_gc.gc_misc;
910 break;
911 case GC_COLOR_DONT_CARE:
912 *val = sc->vga_gc.gc_color_dont_care;
913 break;
914 case GC_BIT_MASK:
915 *val = sc->vga_gc.gc_bit_mask;
916 break;
917 default:
918 //printf("XXX VGA GC: inb 0x%04x at index %d\n", port, sc->vga_crtc.crtc_index);
919 assert(0);
920 break;
921 }
922 break;
923 case GEN_MISC_OUTPUT_PORT:
924 *val = sc->vga_misc;
925 break;
926 case GEN_INPUT_STS0_PORT:
927 assert(0);
928 break;
929 case GEN_INPUT_STS1_MONO_PORT:
930 case GEN_INPUT_STS1_COLOR_PORT:
931 sc->vga_atc.atc_flipflop = 0;
932 #ifdef __FreeBSD__
933 sc->vga_sts1 = GEN_IS1_VR | GEN_IS1_DE;
934 //sc->vga_sts1 ^= (GEN_IS1_VR | GEN_IS1_DE);
935 #else
936 /*
937 * During the bhyve bring-up process, a guest image was failing
938 * to successfully boot. It appeared to be spinning, waiting
939 * for this value to be toggled. Until it can be ruled out
940 * that this is unnecessary (and documentation seems to
941 * indicate that it should be present), the toggle should
942 * remain.
943 */
944 sc->vga_sts1 ^= (GEN_IS1_VR | GEN_IS1_DE);
945 #endif
946 *val = sc->vga_sts1;
947 break;
948 case GEN_FEATURE_CTRL_PORT:
949 // OpenBSD calls this with bytes = 1
950 //assert(0);
951 *val = 0;
952 break;
953 case 0x3c3:
954 *val = 0;
955 break;
956 default:
957 printf("XXX vga_port_in_handler() unhandled port 0x%x\n", port);
958 //assert(0);
959 return (-1);
960 }
961
962 return (0);
963 }
964
965 static int
vga_port_out_handler(struct vmctx * ctx,int in,int port,int bytes,uint8_t val,void * arg)966 vga_port_out_handler(struct vmctx *ctx, int in, int port, int bytes,
967 uint8_t val, void *arg)
968 {
969 struct vga_softc *sc = arg;
970
971 switch (port) {
972 case CRTC_IDX_MONO_PORT:
973 case CRTC_IDX_COLOR_PORT:
974 sc->vga_crtc.crtc_index = val;
975 break;
976 case CRTC_DATA_MONO_PORT:
977 case CRTC_DATA_COLOR_PORT:
978 switch (sc->vga_crtc.crtc_index) {
979 case CRTC_HORIZ_TOTAL:
980 sc->vga_crtc.crtc_horiz_total = val;
981 break;
982 case CRTC_HORIZ_DISP_END:
983 sc->vga_crtc.crtc_horiz_disp_end = val;
984 break;
985 case CRTC_START_HORIZ_BLANK:
986 sc->vga_crtc.crtc_start_horiz_blank = val;
987 break;
988 case CRTC_END_HORIZ_BLANK:
989 sc->vga_crtc.crtc_end_horiz_blank = val;
990 break;
991 case CRTC_START_HORIZ_RETRACE:
992 sc->vga_crtc.crtc_start_horiz_retrace = val;
993 break;
994 case CRTC_END_HORIZ_RETRACE:
995 sc->vga_crtc.crtc_end_horiz_retrace = val;
996 break;
997 case CRTC_VERT_TOTAL:
998 sc->vga_crtc.crtc_vert_total = val;
999 break;
1000 case CRTC_OVERFLOW:
1001 sc->vga_crtc.crtc_overflow = val;
1002 break;
1003 case CRTC_PRESET_ROW_SCAN:
1004 sc->vga_crtc.crtc_present_row_scan = val;
1005 break;
1006 case CRTC_MAX_SCAN_LINE:
1007 sc->vga_crtc.crtc_max_scan_line = val;
1008 break;
1009 case CRTC_CURSOR_START:
1010 sc->vga_crtc.crtc_cursor_start = val;
1011 sc->vga_crtc.crtc_cursor_on = (val & CRTC_CS_CO) == 0;
1012 break;
1013 case CRTC_CURSOR_END:
1014 sc->vga_crtc.crtc_cursor_end = val;
1015 break;
1016 case CRTC_START_ADDR_HIGH:
1017 sc->vga_crtc.crtc_start_addr_high = val;
1018 sc->vga_crtc.crtc_start_addr &= 0x00ff;
1019 sc->vga_crtc.crtc_start_addr |= (val << 8);
1020 break;
1021 case CRTC_START_ADDR_LOW:
1022 sc->vga_crtc.crtc_start_addr_low = val;
1023 sc->vga_crtc.crtc_start_addr &= 0xff00;
1024 sc->vga_crtc.crtc_start_addr |= (val & 0xff);
1025 break;
1026 case CRTC_CURSOR_LOC_HIGH:
1027 sc->vga_crtc.crtc_cursor_loc_high = val;
1028 sc->vga_crtc.crtc_cursor_loc &= 0x00ff;
1029 sc->vga_crtc.crtc_cursor_loc |= (val << 8);
1030 break;
1031 case CRTC_CURSOR_LOC_LOW:
1032 sc->vga_crtc.crtc_cursor_loc_low = val;
1033 sc->vga_crtc.crtc_cursor_loc &= 0xff00;
1034 sc->vga_crtc.crtc_cursor_loc |= (val & 0xff);
1035 break;
1036 case CRTC_VERT_RETRACE_START:
1037 sc->vga_crtc.crtc_vert_retrace_start = val;
1038 break;
1039 case CRTC_VERT_RETRACE_END:
1040 sc->vga_crtc.crtc_vert_retrace_end = val;
1041 break;
1042 case CRTC_VERT_DISP_END:
1043 sc->vga_crtc.crtc_vert_disp_end = val;
1044 break;
1045 case CRTC_OFFSET:
1046 sc->vga_crtc.crtc_offset = val;
1047 break;
1048 case CRTC_UNDERLINE_LOC:
1049 sc->vga_crtc.crtc_underline_loc = val;
1050 break;
1051 case CRTC_START_VERT_BLANK:
1052 sc->vga_crtc.crtc_start_vert_blank = val;
1053 break;
1054 case CRTC_END_VERT_BLANK:
1055 sc->vga_crtc.crtc_end_vert_blank = val;
1056 break;
1057 case CRTC_MODE_CONTROL:
1058 sc->vga_crtc.crtc_mode_ctrl = val;
1059 break;
1060 case CRTC_LINE_COMPARE:
1061 sc->vga_crtc.crtc_line_compare = val;
1062 break;
1063 default:
1064 //printf("XXX VGA CRTC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_crtc.crtc_index);
1065 assert(0);
1066 break;
1067 }
1068 break;
1069 case ATC_IDX_PORT:
1070 if (sc->vga_atc.atc_flipflop == 0) {
1071 if (sc->vga_atc.atc_index & 0x20)
1072 assert(0);
1073 sc->vga_atc.atc_index = val & ATC_IDX_MASK;
1074 } else {
1075 switch (sc->vga_atc.atc_index) {
1076 case ATC_PALETTE0 ... ATC_PALETTE15:
1077 sc->vga_atc.atc_palette[sc->vga_atc.atc_index] = val & 0x3f;
1078 break;
1079 case ATC_MODE_CONTROL:
1080 sc->vga_atc.atc_mode = val;
1081 break;
1082 case ATC_OVERSCAN_COLOR:
1083 sc->vga_atc.atc_overscan_color = val;
1084 break;
1085 case ATC_COLOR_PLANE_ENABLE:
1086 sc->vga_atc.atc_color_plane_enb = val;
1087 break;
1088 case ATC_HORIZ_PIXEL_PANNING:
1089 sc->vga_atc.atc_horiz_pixel_panning = val;
1090 break;
1091 case ATC_COLOR_SELECT:
1092 sc->vga_atc.atc_color_select = val;
1093 sc->vga_atc.atc_color_select_45 =
1094 (val & ATC_CS_C45) << 4;
1095 sc->vga_atc.atc_color_select_67 =
1096 ((val & ATC_CS_C67) >> 2) << 6;
1097 break;
1098 default:
1099 //printf("XXX VGA ATC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_atc.atc_index);
1100 assert(0);
1101 break;
1102 }
1103 }
1104 sc->vga_atc.atc_flipflop ^= 1;
1105 break;
1106 case ATC_DATA_PORT:
1107 break;
1108 case SEQ_IDX_PORT:
1109 sc->vga_seq.seq_index = val & 0x1f;
1110 break;
1111 case SEQ_DATA_PORT:
1112 switch (sc->vga_seq.seq_index) {
1113 case SEQ_RESET:
1114 sc->vga_seq.seq_reset = val;
1115 break;
1116 case SEQ_CLOCKING_MODE:
1117 sc->vga_seq.seq_clock_mode = val;
1118 sc->vga_seq.seq_cm_dots = (val & SEQ_CM_89) ? 8 : 9;
1119 break;
1120 case SEQ_MAP_MASK:
1121 sc->vga_seq.seq_map_mask = val;
1122 break;
1123 case SEQ_CHAR_MAP_SELECT:
1124 sc->vga_seq.seq_cmap_sel = val;
1125
1126 sc->vga_seq.seq_cmap_pri_off = ((((val & SEQ_CMS_SA) >> SEQ_CMS_SA_SHIFT) * 2) + ((val & SEQ_CMS_SAH) >> SEQ_CMS_SAH_SHIFT)) * 8 * KB;
1127 sc->vga_seq.seq_cmap_sec_off = ((((val & SEQ_CMS_SB) >> SEQ_CMS_SB_SHIFT) * 2) + ((val & SEQ_CMS_SBH) >> SEQ_CMS_SBH_SHIFT)) * 8 * KB;
1128 break;
1129 case SEQ_MEMORY_MODE:
1130 sc->vga_seq.seq_mm = val;
1131 /* Windows queries Chain4 */
1132 //assert((sc->vga_seq.seq_mm & SEQ_MM_C4) == 0);
1133 break;
1134 default:
1135 //printf("XXX VGA SEQ: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_seq.seq_index);
1136 assert(0);
1137 break;
1138 }
1139 break;
1140 case DAC_MASK:
1141 break;
1142 case DAC_IDX_RD_PORT:
1143 sc->vga_dac.dac_rd_index = val;
1144 sc->vga_dac.dac_rd_subindex = 0;
1145 break;
1146 case DAC_IDX_WR_PORT:
1147 sc->vga_dac.dac_wr_index = val;
1148 sc->vga_dac.dac_wr_subindex = 0;
1149 break;
1150 case DAC_DATA_PORT:
1151 sc->vga_dac.dac_palette[3 * sc->vga_dac.dac_wr_index +
1152 sc->vga_dac.dac_wr_subindex] = val;
1153 sc->vga_dac.dac_wr_subindex++;
1154 if (sc->vga_dac.dac_wr_subindex == 3) {
1155 sc->vga_dac.dac_palette_rgb[sc->vga_dac.dac_wr_index] =
1156 ((((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] << 2) |
1157 ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] & 0x1) << 1) |
1158 (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 0] & 0x1)) << 16) |
1159 (((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] << 2) |
1160 ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] & 0x1) << 1) |
1161 (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 1] & 0x1)) << 8) |
1162 (((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] << 2) |
1163 ((sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] & 0x1) << 1) |
1164 (sc->vga_dac.dac_palette[3*sc->vga_dac.dac_wr_index + 2] & 0x1)) << 0));
1165
1166 sc->vga_dac.dac_wr_index++;
1167 sc->vga_dac.dac_wr_subindex = 0;
1168 }
1169 break;
1170 case GC_IDX_PORT:
1171 sc->vga_gc.gc_index = val;
1172 break;
1173 case GC_DATA_PORT:
1174 switch (sc->vga_gc.gc_index) {
1175 case GC_SET_RESET:
1176 sc->vga_gc.gc_set_reset = val;
1177 break;
1178 case GC_ENABLE_SET_RESET:
1179 sc->vga_gc.gc_enb_set_reset = val;
1180 break;
1181 case GC_COLOR_COMPARE:
1182 sc->vga_gc.gc_color_compare = val;
1183 break;
1184 case GC_DATA_ROTATE:
1185 sc->vga_gc.gc_rotate = val;
1186 sc->vga_gc.gc_op = (val >> 3) & 0x3;
1187 break;
1188 case GC_READ_MAP_SELECT:
1189 sc->vga_gc.gc_read_map_sel = val;
1190 break;
1191 case GC_MODE:
1192 sc->vga_gc.gc_mode = val;
1193 sc->vga_gc.gc_mode_c4 = (val & GC_MODE_C4) != 0;
1194 assert(!sc->vga_gc.gc_mode_c4);
1195 sc->vga_gc.gc_mode_oe = (val & GC_MODE_OE) != 0;
1196 sc->vga_gc.gc_mode_rm = (val >> 3) & 0x1;
1197 sc->vga_gc.gc_mode_wm = val & 0x3;
1198
1199 if (sc->gc_image)
1200 sc->gc_image->vgamode = 1;
1201 break;
1202 case GC_MISCELLANEOUS:
1203 sc->vga_gc.gc_misc = val;
1204 sc->vga_gc.gc_misc_gm = val & GC_MISC_GM;
1205 sc->vga_gc.gc_misc_mm = (val & GC_MISC_MM) >>
1206 GC_MISC_MM_SHIFT;
1207 break;
1208 case GC_COLOR_DONT_CARE:
1209 sc->vga_gc.gc_color_dont_care = val;
1210 break;
1211 case GC_BIT_MASK:
1212 sc->vga_gc.gc_bit_mask = val;
1213 break;
1214 default:
1215 //printf("XXX VGA GC: outb 0x%04x, 0x%02x at index %d\n", port, val, sc->vga_gc.gc_index);
1216 assert(0);
1217 break;
1218 }
1219 break;
1220 case GEN_INPUT_STS0_PORT:
1221 /* write to Miscellaneous Output Register */
1222 sc->vga_misc = val;
1223 break;
1224 case GEN_INPUT_STS1_MONO_PORT:
1225 case GEN_INPUT_STS1_COLOR_PORT:
1226 /* write to Feature Control Register */
1227 break;
1228 // case 0x3c3:
1229 // break;
1230 default:
1231 printf("XXX vga_port_out_handler() unhandled port 0x%x, val 0x%x\n", port, val);
1232 //assert(0);
1233 return (-1);
1234 }
1235 return (0);
1236 }
1237
1238 static int
vga_port_handler(struct vmctx * ctx,int in,int port,int bytes,uint32_t * eax,void * arg)1239 vga_port_handler(struct vmctx *ctx, int in, int port,
1240 int bytes, uint32_t *eax, void *arg)
1241 {
1242 uint8_t val;
1243 int error;
1244
1245 switch (bytes) {
1246 case 1:
1247 if (in) {
1248 *eax &= ~0xff;
1249 error = vga_port_in_handler(ctx, in, port, 1,
1250 &val, arg);
1251 if (!error) {
1252 *eax |= val & 0xff;
1253 }
1254 } else {
1255 val = *eax & 0xff;
1256 error = vga_port_out_handler(ctx, in, port, 1,
1257 val, arg);
1258 }
1259 break;
1260 case 2:
1261 if (in) {
1262 *eax &= ~0xffff;
1263 error = vga_port_in_handler(ctx, in, port, 1,
1264 &val, arg);
1265 if (!error) {
1266 *eax |= val & 0xff;
1267 }
1268 error = vga_port_in_handler(ctx, in, port + 1, 1,
1269 &val, arg);
1270 if (!error) {
1271 *eax |= (val & 0xff) << 8;
1272 }
1273 } else {
1274 val = *eax & 0xff;
1275 error = vga_port_out_handler(ctx, in, port, 1,
1276 val, arg);
1277 val = (*eax >> 8) & 0xff;
1278 error =vga_port_out_handler(ctx, in, port + 1, 1,
1279 val, arg);
1280 }
1281 break;
1282 default:
1283 assert(0);
1284 return (-1);
1285 }
1286
1287 return (error);
1288 }
1289
1290 void *
vga_init(int io_only)1291 vga_init(int io_only)
1292 {
1293 struct inout_port iop;
1294 struct vga_softc *sc;
1295 int port, error;
1296
1297 sc = calloc(1, sizeof(struct vga_softc));
1298
1299 bzero(&iop, sizeof(struct inout_port));
1300 iop.name = "VGA";
1301 for (port = VGA_IOPORT_START; port <= VGA_IOPORT_END; port++) {
1302 iop.port = port;
1303 iop.size = 1;
1304 iop.flags = IOPORT_F_INOUT;
1305 iop.handler = vga_port_handler;
1306 iop.arg = sc;
1307
1308 error = register_inout(&iop);
1309 assert(error == 0);
1310 }
1311
1312 sc->gc_image = console_get_image();
1313
1314 /* only handle io ports; vga graphics is disabled */
1315 if (io_only)
1316 return(sc);
1317
1318 sc->mr.name = "VGA memory";
1319 sc->mr.flags = MEM_F_RW;
1320 sc->mr.base = 640 * KB;
1321 sc->mr.size = 128 * KB;
1322 sc->mr.handler = vga_mem_handler;
1323 sc->mr.arg1 = sc;
1324 error = register_mem_fallback(&sc->mr);
1325 assert(error == 0);
1326
1327 sc->vga_ram = malloc(256 * KB);
1328 memset(sc->vga_ram, 0, 256 * KB);
1329
1330 {
1331 static uint8_t palette[] = {
1332 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
1333 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
1334 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f,
1335 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
1336 };
1337 int i;
1338
1339 memcpy(sc->vga_dac.dac_palette, palette, 16 * 3 * sizeof (uint8_t));
1340 for (i = 0; i < 16; i++) {
1341 sc->vga_dac.dac_palette_rgb[i] =
1342 ((((sc->vga_dac.dac_palette[3*i + 0] << 2) |
1343 ((sc->vga_dac.dac_palette[3*i + 0] & 0x1) << 1) |
1344 (sc->vga_dac.dac_palette[3*i + 0] & 0x1)) << 16) |
1345 (((sc->vga_dac.dac_palette[3*i + 1] << 2) |
1346 ((sc->vga_dac.dac_palette[3*i + 1] & 0x1) << 1) |
1347 (sc->vga_dac.dac_palette[3*i + 1] & 0x1)) << 8) |
1348 (((sc->vga_dac.dac_palette[3*i + 2] << 2) |
1349 ((sc->vga_dac.dac_palette[3*i + 2] & 0x1) << 1) |
1350 (sc->vga_dac.dac_palette[3*i + 2] & 0x1)) << 0));
1351 }
1352 }
1353
1354 return (sc);
1355 }
1356