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