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