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