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