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