1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 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 as 10 * the first lines of this file unmodified. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include "opt_syscons.h" 30 #include "opt_vga.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/fbio.h> 36 #include <sys/consio.h> 37 38 #include <machine/bus.h> 39 40 #include <dev/fb/fbreg.h> 41 #include <dev/fb/vgareg.h> 42 #include <dev/syscons/syscons.h> 43 44 #include <isa/isareg.h> 45 46 #ifndef SC_RENDER_DEBUG 47 #define SC_RENDER_DEBUG 0 48 #endif 49 50 static vr_clear_t vga_txtclear; 51 static vr_draw_border_t vga_txtborder; 52 static vr_draw_t vga_txtdraw; 53 static vr_set_cursor_t vga_txtcursor_shape; 54 static vr_draw_cursor_t vga_txtcursor; 55 static vr_blink_cursor_t vga_txtblink; 56 #ifndef SC_NO_CUTPASTE 57 static vr_draw_mouse_t vga_txtmouse; 58 #else 59 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop 60 #endif 61 62 #ifdef SC_PIXEL_MODE 63 static vr_clear_t vga_pxlclear; 64 static vr_draw_border_t vga_pxlborder; 65 static vr_draw_t vga_egadraw; 66 static vr_draw_t vga_vgadraw; 67 static vr_set_cursor_t vga_pxlcursor_shape; 68 static vr_draw_cursor_t vga_pxlcursor; 69 static vr_blink_cursor_t vga_pxlblink; 70 #ifndef SC_NO_CUTPASTE 71 static vr_draw_mouse_t vga_pxlmouse; 72 #else 73 #define vga_pxlmouse (vr_draw_mouse_t *)vga_nop 74 #endif 75 #endif /* SC_PIXEL_MODE */ 76 77 #ifndef SC_NO_MODE_CHANGE 78 static vr_draw_border_t vga_grborder; 79 #endif 80 81 static void vga_nop(scr_stat *scp, ...); 82 83 static sc_rndr_sw_t txtrndrsw = { 84 vga_txtclear, 85 vga_txtborder, 86 vga_txtdraw, 87 vga_txtcursor_shape, 88 vga_txtcursor, 89 vga_txtblink, 90 (vr_set_mouse_t *)vga_nop, 91 vga_txtmouse, 92 }; 93 RENDERER(mda, 0, txtrndrsw, vga_set); 94 RENDERER(cga, 0, txtrndrsw, vga_set); 95 RENDERER(ega, 0, txtrndrsw, vga_set); 96 RENDERER(vga, 0, txtrndrsw, vga_set); 97 98 #ifdef SC_PIXEL_MODE 99 static sc_rndr_sw_t egarndrsw = { 100 vga_pxlclear, 101 vga_pxlborder, 102 vga_egadraw, 103 vga_pxlcursor_shape, 104 vga_pxlcursor, 105 vga_pxlblink, 106 (vr_set_mouse_t *)vga_nop, 107 vga_pxlmouse, 108 }; 109 RENDERER(ega, PIXEL_MODE, egarndrsw, vga_set); 110 111 static sc_rndr_sw_t vgarndrsw = { 112 vga_pxlclear, 113 vga_pxlborder, 114 vga_vgadraw, 115 vga_pxlcursor_shape, 116 vga_pxlcursor, 117 vga_pxlblink, 118 (vr_set_mouse_t *)vga_nop, 119 vga_pxlmouse, 120 }; 121 RENDERER(vga, PIXEL_MODE, vgarndrsw, vga_set); 122 #endif /* SC_PIXEL_MODE */ 123 124 #ifndef SC_NO_MODE_CHANGE 125 static sc_rndr_sw_t grrndrsw = { 126 (vr_clear_t *)vga_nop, 127 vga_grborder, 128 (vr_draw_t *)vga_nop, 129 (vr_set_cursor_t *)vga_nop, 130 (vr_draw_cursor_t *)vga_nop, 131 (vr_blink_cursor_t *)vga_nop, 132 (vr_set_mouse_t *)vga_nop, 133 (vr_draw_mouse_t *)vga_nop, 134 }; 135 RENDERER(cga, GRAPHICS_MODE, grrndrsw, vga_set); 136 RENDERER(ega, GRAPHICS_MODE, grrndrsw, vga_set); 137 RENDERER(vga, GRAPHICS_MODE, grrndrsw, vga_set); 138 #endif /* SC_NO_MODE_CHANGE */ 139 140 RENDERER_MODULE(vga, vga_set); 141 142 #ifndef SC_NO_CUTPASTE 143 #if !defined(SC_ALT_MOUSE_IMAGE) || defined(SC_PIXEL_MODE) 144 static u_short mouse_and_mask[16] = { 145 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 146 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000 147 }; 148 static u_short mouse_or_mask[16] = { 149 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800, 150 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 151 }; 152 #endif 153 #endif 154 155 static void 156 vga_nop(scr_stat *scp, ...) 157 { 158 } 159 160 /* text mode renderer */ 161 162 static void 163 vga_txtclear(scr_stat *scp, int c, int attr) 164 { 165 sc_vtb_clear(&scp->scr, c, attr); 166 } 167 168 static void 169 vga_txtborder(scr_stat *scp, int color) 170 { 171 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 172 } 173 174 static void 175 vga_txtdraw(scr_stat *scp, int from, int count, int flip) 176 { 177 vm_offset_t p; 178 int c; 179 int a; 180 181 if (from + count > scp->xsize*scp->ysize) 182 count = scp->xsize*scp->ysize - from; 183 184 if (flip) { 185 for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) { 186 c = sc_vtb_getc(&scp->vtb, from); 187 a = sc_vtb_geta(&scp->vtb, from); 188 a = (a & 0x8800) | ((a & 0x7000) >> 4) 189 | ((a & 0x0700) << 4); 190 p = sc_vtb_putchar(&scp->scr, p, c, a); 191 } 192 } else { 193 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count); 194 } 195 } 196 197 static void 198 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink) 199 { 200 if (base < 0 || base >= scp->font_size) 201 return; 202 /* the caller may set height <= 0 in order to disable the cursor */ 203 #if 0 204 scp->curs_attr.base = base; 205 scp->curs_attr.height = height; 206 #endif 207 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp, 208 base, height, 209 scp->font_size, blink); 210 } 211 212 static void 213 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip) 214 { 215 sc_softc_t *sc; 216 217 sc = scp->sc; 218 scp->cursor_saveunder_char = c; 219 scp->cursor_saveunder_attr = a; 220 221 #ifndef SC_NO_FONT_LOADING 222 if (scp->curs_attr.flags & CONS_CHAR_CURSOR) { 223 unsigned char *font; 224 int h; 225 int i; 226 227 if (scp->font_size < 14) { 228 font = sc->font_8; 229 h = 8; 230 } else if (scp->font_size >= 16) { 231 font = sc->font_16; 232 h = 16; 233 } else { 234 font = sc->font_14; 235 h = 14; 236 } 237 if (scp->curs_attr.base >= h) 238 return; 239 if (flip) 240 a = (a & 0x8800) 241 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 242 bcopy(font + c*h, font + sc->cursor_char*h, h); 243 font = font + sc->cursor_char*h; 244 for (i = imax(h - scp->curs_attr.base - scp->curs_attr.height, 0); 245 i < h - scp->curs_attr.base; ++i) { 246 font[i] ^= 0xff; 247 } 248 /* XXX */ 249 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font, 250 sc->cursor_char, 1); 251 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a); 252 } else 253 #endif /* SC_NO_FONT_LOADING */ 254 { 255 if ((a & 0x7000) == 0x7000) { 256 a &= 0x8f00; 257 if ((a & 0x0700) == 0) 258 a |= 0x0700; 259 } else { 260 a |= 0x7000; 261 if ((a & 0x0700) == 0x0700) 262 a &= 0xf000; 263 } 264 if (flip) 265 a = (a & 0x8800) 266 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 267 sc_vtb_putc(&scp->scr, at, c, a); 268 } 269 } 270 271 static void 272 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip) 273 { 274 video_adapter_t *adp; 275 int cursor_attr; 276 277 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 278 return; 279 280 adp = scp->sc->adp; 281 if (blink) { 282 scp->status |= VR_CURSOR_BLINK; 283 if (on) { 284 scp->status |= VR_CURSOR_ON; 285 (*vidsw[adp->va_index]->set_hw_cursor)(adp, 286 at%scp->xsize, 287 at/scp->xsize); 288 } else { 289 if (scp->status & VR_CURSOR_ON) 290 (*vidsw[adp->va_index]->set_hw_cursor)(adp, 291 -1, -1); 292 scp->status &= ~VR_CURSOR_ON; 293 } 294 } else { 295 scp->status &= ~VR_CURSOR_BLINK; 296 if (on) { 297 scp->status |= VR_CURSOR_ON; 298 draw_txtcharcursor(scp, at, 299 sc_vtb_getc(&scp->scr, at), 300 sc_vtb_geta(&scp->scr, at), 301 flip); 302 } else { 303 cursor_attr = scp->cursor_saveunder_attr; 304 if (flip) 305 cursor_attr = (cursor_attr & 0x8800) 306 | ((cursor_attr & 0x7000) >> 4) 307 | ((cursor_attr & 0x0700) << 4); 308 if (scp->status & VR_CURSOR_ON) 309 sc_vtb_putc(&scp->scr, at, 310 scp->cursor_saveunder_char, 311 cursor_attr); 312 scp->status &= ~VR_CURSOR_ON; 313 } 314 } 315 } 316 317 static void 318 vga_txtblink(scr_stat *scp, int at, int flip) 319 { 320 } 321 322 #ifndef SC_NO_CUTPASTE 323 324 static void 325 draw_txtmouse(scr_stat *scp, int x, int y) 326 { 327 #ifndef SC_ALT_MOUSE_IMAGE 328 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) { 329 u_char font_buf[128]; 330 u_short cursor[32]; 331 u_char c; 332 int pos; 333 int xoffset, yoffset; 334 int crtc_addr; 335 int i; 336 337 /* prepare mousepointer char's bitmaps */ 338 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 339 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size, 340 &font_buf[0], scp->font_size); 341 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size, 342 &font_buf[32], scp->font_size); 343 bcopy(scp->font 344 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size, 345 &font_buf[64], scp->font_size); 346 bcopy(scp->font 347 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size, 348 &font_buf[96], scp->font_size); 349 for (i = 0; i < scp->font_size; ++i) { 350 cursor[i] = font_buf[i]<<8 | font_buf[i+32]; 351 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96]; 352 } 353 354 /* now and-or in the mousepointer image */ 355 xoffset = x%8; 356 yoffset = y%scp->font_size; 357 for (i = 0; i < 16; ++i) { 358 cursor[i + yoffset] = 359 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset)) 360 | (mouse_or_mask[i] >> xoffset); 361 } 362 for (i = 0; i < scp->font_size; ++i) { 363 font_buf[i] = (cursor[i] & 0xff00) >> 8; 364 font_buf[i + 32] = cursor[i] & 0xff; 365 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8; 366 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff; 367 } 368 369 #if 1 370 /* wait for vertical retrace to avoid jitter on some videocards */ 371 crtc_addr = scp->sc->adp->va_crtc_addr; 372 while (!(inb(crtc_addr + 6) & 0x08)) /* idle */ ; 373 #endif 374 c = scp->sc->mouse_char; 375 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf, 376 c, 4); 377 378 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos)); 379 /* FIXME: may be out of range! */ 380 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2, 381 sc_vtb_geta(&scp->scr, pos + scp->xsize)); 382 if (x < (scp->xsize - 1)*8) { 383 sc_vtb_putc(&scp->scr, pos + 1, c + 1, 384 sc_vtb_geta(&scp->scr, pos + 1)); 385 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3, 386 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1)); 387 } 388 } else 389 #endif /* SC_ALT_MOUSE_IMAGE */ 390 { 391 /* Red, magenta and brown are mapped to green to to keep it readable */ 392 static const int col_conv[16] = { 393 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14 394 }; 395 int pos; 396 int color; 397 int a; 398 399 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 400 a = sc_vtb_geta(&scp->scr, pos); 401 if (scp->sc->adp->va_flags & V_ADP_COLOR) 402 color = (col_conv[(a & 0xf000) >> 12] << 12) 403 | ((a & 0x0f00) | 0x0800); 404 else 405 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4); 406 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color); 407 } 408 } 409 410 static void 411 remove_txtmouse(scr_stat *scp, int x, int y) 412 { 413 } 414 415 static void 416 vga_txtmouse(scr_stat *scp, int x, int y, int on) 417 { 418 if (on) 419 draw_txtmouse(scp, x, y); 420 else 421 remove_txtmouse(scp, x, y); 422 } 423 424 #endif /* SC_NO_CUTPASTE */ 425 426 #ifdef SC_PIXEL_MODE 427 428 /* pixel (raster text) mode renderer */ 429 430 static void 431 vga_pxlclear(scr_stat *scp, int c, int attr) 432 { 433 vm_offset_t p; 434 int line_width; 435 int lines; 436 int i; 437 438 /* XXX: we are just filling the screen with the background color... */ 439 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 440 outw(GDCIDX, 0x0003); /* data rotate/function select */ 441 outw(GDCIDX, 0x0f01); /* set/reset enable */ 442 outw(GDCIDX, 0xff08); /* bit mask */ 443 outw(GDCIDX, ((attr & 0xf000) >> 4) | 0x00); /* set/reset */ 444 line_width = scp->sc->adp->va_line_width; 445 lines = scp->ysize*scp->font_size; 446 p = scp->sc->adp->va_window + line_width*scp->yoff*scp->font_size 447 + scp->xoff; 448 for (i = 0; i < lines; ++i) { 449 bzero_io((void *)p, scp->xsize); 450 p += line_width; 451 } 452 outw(GDCIDX, 0x0000); /* set/reset */ 453 outw(GDCIDX, 0x0001); /* set/reset enable */ 454 } 455 456 static void 457 vga_pxlborder(scr_stat *scp, int color) 458 { 459 vm_offset_t p; 460 int line_width; 461 int x; 462 int y; 463 int i; 464 465 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 466 467 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 468 outw(GDCIDX, 0x0003); /* data rotate/function select */ 469 outw(GDCIDX, 0x0f01); /* set/reset enable */ 470 outw(GDCIDX, 0xff08); /* bit mask */ 471 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 472 line_width = scp->sc->adp->va_line_width; 473 p = scp->sc->adp->va_window; 474 if (scp->yoff > 0) 475 bzero_io((void *)p, line_width*scp->yoff*scp->font_size); 476 y = (scp->yoff + scp->ysize)*scp->font_size; 477 if (scp->ypixel > y) 478 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y)); 479 y = scp->yoff*scp->font_size; 480 x = scp->xpixel/8 - scp->xoff - scp->xsize; 481 for (i = 0; i < scp->ysize*scp->font_size; ++i) { 482 if (scp->xoff > 0) 483 bzero_io((void *)(p + line_width*(y + i)), scp->xoff); 484 if (x > 0) 485 bzero_io((void *)(p + line_width*(y + i) 486 + scp->xoff + scp->xsize), x); 487 } 488 outw(GDCIDX, 0x0000); /* set/reset */ 489 outw(GDCIDX, 0x0001); /* set/reset enable */ 490 } 491 492 static void 493 vga_egadraw(scr_stat *scp, int from, int count, int flip) 494 { 495 vm_offset_t d; 496 vm_offset_t e; 497 u_char *f; 498 u_short bg; 499 u_short col1, col2; 500 int line_width; 501 int i, j; 502 int a; 503 u_char c; 504 505 line_width = scp->sc->adp->va_line_width; 506 d = scp->sc->adp->va_window 507 + scp->xoff 508 + scp->yoff*scp->font_size*line_width 509 + (from%scp->xsize) 510 + scp->font_size*line_width*(from/scp->xsize); 511 512 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 513 outw(GDCIDX, 0x0003); /* data rotate/function select */ 514 outw(GDCIDX, 0x0f01); /* set/reset enable */ 515 bg = -1; 516 if (from + count > scp->xsize*scp->ysize) 517 count = scp->xsize*scp->ysize - from; 518 for (i = from; count-- > 0; ++i) { 519 a = sc_vtb_geta(&scp->vtb, i); 520 if (flip) { 521 col1 = ((a & 0x7000) >> 4) | (a & 0x0800); 522 col2 = ((a & 0x8000) >> 4) | (a & 0x0700); 523 } else { 524 col1 = (a & 0x0f00); 525 col2 = (a & 0xf000) >> 4; 526 } 527 /* set background color in EGA/VGA latch */ 528 if (bg != col2) { 529 bg = col2; 530 outw(GDCIDX, bg | 0x00); /* set/reset */ 531 outw(GDCIDX, 0xff08); /* bit mask */ 532 writeb(d, 0); 533 c = readb(d); /* set bg color in the latch */ 534 } 535 /* foreground color */ 536 outw(GDCIDX, col1 | 0x00); /* set/reset */ 537 e = d; 538 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]); 539 for (j = 0; j < scp->font_size; ++j, ++f) { 540 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ 541 writeb(e, 0); 542 e += line_width; 543 } 544 ++d; 545 if ((i % scp->xsize) == scp->xsize - 1) 546 d += scp->xoff*2 547 + (scp->font_size - 1)*line_width; 548 } 549 outw(GDCIDX, 0x0000); /* set/reset */ 550 outw(GDCIDX, 0x0001); /* set/reset enable */ 551 outw(GDCIDX, 0xff08); /* bit mask */ 552 } 553 554 static void 555 vga_vgadraw(scr_stat *scp, int from, int count, int flip) 556 { 557 vm_offset_t d; 558 vm_offset_t e; 559 u_char *f; 560 u_short bg; 561 u_short col1, col2; 562 int line_width; 563 int i, j; 564 int a; 565 u_char c; 566 567 line_width = scp->sc->adp->va_line_width; 568 d = scp->sc->adp->va_window 569 + scp->xoff 570 + scp->yoff*scp->font_size*line_width 571 + (from%scp->xsize) 572 + scp->font_size*line_width*(from/scp->xsize); 573 574 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 575 outw(GDCIDX, 0x0003); /* data rotate/function select */ 576 outw(GDCIDX, 0x0f01); /* set/reset enable */ 577 outw(GDCIDX, 0xff08); /* bit mask */ 578 bg = -1; 579 if (from + count > scp->xsize*scp->ysize) 580 count = scp->xsize*scp->ysize - from; 581 for (i = from; count-- > 0; ++i) { 582 a = sc_vtb_geta(&scp->vtb, i); 583 if (flip) { 584 col1 = ((a & 0x7000) >> 4) | (a & 0x0800); 585 col2 = ((a & 0x8000) >> 4) | (a & 0x0700); 586 } else { 587 col1 = (a & 0x0f00); 588 col2 = (a & 0xf000) >> 4; 589 } 590 /* set background color in EGA/VGA latch */ 591 if (bg != col2) { 592 bg = col2; 593 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 594 outw(GDCIDX, bg | 0x00); /* set/reset */ 595 writeb(d, 0); 596 c = readb(d); /* set bg color in the latch */ 597 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 598 } 599 /* foreground color */ 600 outw(GDCIDX, col1 | 0x00); /* set/reset */ 601 e = d; 602 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]); 603 for (j = 0; j < scp->font_size; ++j, ++f) { 604 writeb(e, *f); 605 e += line_width; 606 } 607 ++d; 608 if ((i % scp->xsize) == scp->xsize - 1) 609 d += scp->xoff*2 610 + (scp->font_size - 1)*line_width; 611 } 612 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 613 outw(GDCIDX, 0x0000); /* set/reset */ 614 outw(GDCIDX, 0x0001); /* set/reset enable */ 615 } 616 617 static void 618 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink) 619 { 620 if (base < 0 || base >= scp->font_size) 621 return; 622 /* the caller may set height <= 0 in order to disable the cursor */ 623 #if 0 624 scp->curs_attr.base = base; 625 scp->curs_attr.height = height; 626 #endif 627 } 628 629 static void 630 draw_pxlcursor(scr_stat *scp, int at, int on, int flip) 631 { 632 vm_offset_t d; 633 u_char *f; 634 int line_width; 635 int height; 636 int col; 637 int a; 638 int i; 639 u_char c; 640 641 line_width = scp->sc->adp->va_line_width; 642 d = scp->sc->adp->va_window 643 + scp->xoff 644 + scp->yoff*scp->font_size*line_width 645 + (at%scp->xsize) 646 + scp->font_size*line_width*(at/scp->xsize) 647 + (scp->font_size - scp->curs_attr.base - 1)*line_width; 648 649 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 650 outw(GDCIDX, 0x0003); /* data rotate/function select */ 651 outw(GDCIDX, 0x0f01); /* set/reset enable */ 652 /* set background color in EGA/VGA latch */ 653 a = sc_vtb_geta(&scp->vtb, at); 654 if (flip) 655 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 656 else 657 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 658 outw(GDCIDX, col | 0x00); /* set/reset */ 659 outw(GDCIDX, 0xff08); /* bit mask */ 660 writeb(d, 0); 661 c = readb(d); /* set bg color in the latch */ 662 /* foreground color */ 663 if (flip) 664 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 665 else 666 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 667 outw(GDCIDX, col | 0x00); /* set/reset */ 668 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size 669 + scp->font_size - scp->curs_attr.base - 1]); 670 height = imin(scp->curs_attr.height, scp->font_size); 671 for (i = 0; i < height; ++i, --f) { 672 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ 673 writeb(d, 0); 674 d -= line_width; 675 } 676 outw(GDCIDX, 0x0000); /* set/reset */ 677 outw(GDCIDX, 0x0001); /* set/reset enable */ 678 outw(GDCIDX, 0xff08); /* bit mask */ 679 } 680 681 static int pxlblinkrate = 0; 682 683 static void 684 vga_pxlcursor(scr_stat *scp, int at, int blink, int on, int flip) 685 { 686 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 687 return; 688 689 if (on) { 690 if (!blink) { 691 scp->status |= VR_CURSOR_ON; 692 draw_pxlcursor(scp, at, on, flip); 693 } else if (++pxlblinkrate & 4) { 694 pxlblinkrate = 0; 695 scp->status ^= VR_CURSOR_ON; 696 draw_pxlcursor(scp, at, 697 scp->status & VR_CURSOR_ON, 698 flip); 699 } 700 } else { 701 if (scp->status & VR_CURSOR_ON) 702 draw_pxlcursor(scp, at, on, flip); 703 scp->status &= ~VR_CURSOR_ON; 704 } 705 if (blink) 706 scp->status |= VR_CURSOR_BLINK; 707 else 708 scp->status &= ~VR_CURSOR_BLINK; 709 } 710 711 static void 712 vga_pxlblink(scr_stat *scp, int at, int flip) 713 { 714 if (!(scp->status & VR_CURSOR_BLINK)) 715 return; 716 if (!(++pxlblinkrate & 4)) 717 return; 718 pxlblinkrate = 0; 719 scp->status ^= VR_CURSOR_ON; 720 draw_pxlcursor(scp, at, scp->status & VR_CURSOR_ON, flip); 721 } 722 723 #ifndef SC_NO_CUTPASTE 724 725 static void 726 draw_pxlmouse(scr_stat *scp, int x, int y) 727 { 728 vm_offset_t p; 729 int line_width; 730 int xoff, yoff; 731 int ymax; 732 u_short m; 733 int i, j; 734 735 line_width = scp->sc->adp->va_line_width; 736 xoff = (x - scp->xoff*8)%8; 737 yoff = y - (y/line_width)*line_width; 738 ymax = imin(y + 16, scp->ypixel); 739 740 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */ 741 outw(GDCIDX, 0x0001); /* set/reset enable */ 742 outw(GDCIDX, 0x0002); /* color compare */ 743 outw(GDCIDX, 0x0007); /* color don't care */ 744 outw(GDCIDX, 0xff08); /* bit mask */ 745 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */ 746 p = scp->sc->adp->va_window + line_width*y + x/8; 747 if (x < scp->xpixel - 8) { 748 for (i = y, j = 0; i < ymax; ++i, ++j) { 749 m = ~(mouse_and_mask[j] >> xoff); 750 #ifdef __i386__ 751 *(u_char *)p &= m >> 8; 752 *(u_char *)(p + 1) &= m; 753 #elif defined(__alpha__) 754 writeb(p, readb(p) & (m >> 8)); 755 writeb(p + 1, readb(p + 1) & (m >> 8)); 756 #endif 757 p += line_width; 758 } 759 } else { 760 xoff += 8; 761 for (i = y, j = 0; i < ymax; ++i, ++j) { 762 m = ~(mouse_and_mask[j] >> xoff); 763 #ifdef __i386__ 764 *(u_char *)p &= m; 765 #elif defined(__alpha__) 766 writeb(p, readb(p) & (m >> 8)); 767 #endif 768 p += line_width; 769 } 770 } 771 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */ 772 p = scp->sc->adp->va_window + line_width*y + x/8; 773 if (x < scp->xpixel - 8) { 774 for (i = y, j = 0; i < ymax; ++i, ++j) { 775 m = mouse_or_mask[j] >> xoff; 776 #ifdef __i386__ 777 *(u_char *)p &= m >> 8; 778 *(u_char *)(p + 1) &= m; 779 #elif defined(__alpha__) 780 writeb(p, readb(p) & (m >> 8)); 781 writeb(p + 1, readb(p + 1) & (m >> 8)); 782 #endif 783 p += line_width; 784 } 785 } else { 786 for (i = y, j = 0; i < ymax; ++i, ++j) { 787 m = mouse_or_mask[j] >> xoff; 788 #ifdef __i386__ 789 *(u_char *)p &= m; 790 #elif defined(__alpha__) 791 writeb(p, readb(p) & (m >> 8)); 792 #endif 793 p += line_width; 794 } 795 } 796 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 797 outw(GDCIDX, 0x0003); /* data rotate/function select */ 798 } 799 800 static void 801 remove_pxlmouse(scr_stat *scp, int x, int y) 802 { 803 vm_offset_t p; 804 int col, row; 805 int pos; 806 int line_width; 807 int ymax; 808 int i; 809 810 /* erase the mouse cursor image */ 811 col = x/8 - scp->xoff; 812 row = y/scp->font_size - scp->yoff; 813 pos = row*scp->xsize + col; 814 i = (col < scp->xsize - 1) ? 2 : 1; 815 (*scp->rndr->draw)(scp, pos, i, FALSE); 816 if (row < scp->ysize - 1) 817 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); 818 819 /* paint border if necessary */ 820 line_width = scp->sc->adp->va_line_width; 821 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 822 outw(GDCIDX, 0x0003); /* data rotate/function select */ 823 outw(GDCIDX, 0x0f01); /* set/reset enable */ 824 outw(GDCIDX, 0xff08); /* bit mask */ 825 outw(GDCIDX, (scp->border << 8) | 0x00); /* set/reset */ 826 if (row == scp->ysize - 1) { 827 i = (scp->ysize + scp->yoff)*scp->font_size; 828 ymax = imin(i + scp->font_size, scp->ypixel); 829 p = scp->sc->adp->va_window + i*line_width + scp->xoff + col; 830 if (col < scp->xsize - 1) { 831 for (; i < ymax; ++i) { 832 writeb(p, 0); 833 writeb(p + 1, 0); 834 p += line_width; 835 } 836 } else { 837 for (; i < ymax; ++i) { 838 writeb(p, 0); 839 p += line_width; 840 } 841 } 842 } 843 if ((col == scp->xsize - 1) && (scp->xoff > 0)) { 844 i = (row + scp->yoff)*scp->font_size; 845 ymax = imin(i + scp->font_size*2, scp->ypixel); 846 p = scp->sc->adp->va_window + i*line_width 847 + scp->xoff + scp->xsize; 848 for (; i < ymax; ++i) { 849 writeb(p, 0); 850 p += line_width; 851 } 852 } 853 outw(GDCIDX, 0x0000); /* set/reset */ 854 outw(GDCIDX, 0x0001); /* set/reset enable */ 855 } 856 857 static void 858 vga_pxlmouse(scr_stat *scp, int x, int y, int on) 859 { 860 if (on) 861 draw_pxlmouse(scp, x, y); 862 else 863 remove_pxlmouse(scp, x, y); 864 } 865 866 #endif /* SC_NO_CUTPASTE */ 867 #endif /* SC_PIXEL_MODE */ 868 869 #ifndef SC_NO_MODE_CHANGE 870 871 /* graphics mode renderer */ 872 873 static void 874 vga_grborder(scr_stat *scp, int color) 875 { 876 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 877 } 878 879 #endif 880