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