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