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