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