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