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