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 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 52 static vr_clear_t vga_txtclear; 53 static vr_draw_border_t vga_txtborder; 54 static vr_draw_t vga_txtdraw; 55 static vr_set_cursor_t vga_txtcursor_shape; 56 static vr_draw_cursor_t vga_txtcursor; 57 static vr_blink_cursor_t vga_txtblink; 58 #ifndef SC_NO_CUTPASTE 59 static 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 65 static vr_clear_t vga_pxlclear; 66 static vr_draw_border_t vga_pxlborder; 67 static vr_draw_t vga_egadraw; 68 static vr_draw_t vga_vgadraw; 69 static vr_set_cursor_t vga_pxlcursor_shape; 70 static vr_draw_cursor_t vga_pxlcursor; 71 static vr_blink_cursor_t vga_pxlblink; 72 #ifndef SC_NO_CUTPASTE 73 static 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 80 static vr_draw_border_t vga_grborder; 81 #endif 82 83 static void vga_nop(scr_stat *scp, ...); 84 85 static struct linker_set vga_set; 86 87 static 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 }; 97 RENDERER(mda, 0, txtrndrsw, vga_set); 98 RENDERER(cga, 0, txtrndrsw, vga_set); 99 RENDERER(ega, 0, txtrndrsw, vga_set); 100 RENDERER(vga, 0, txtrndrsw, vga_set); 101 102 #ifdef SC_PIXEL_MODE 103 static 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 }; 113 RENDERER(ega, PIXEL_MODE, egarndrsw, vga_set); 114 115 static 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 }; 125 RENDERER(vga, PIXEL_MODE, vgarndrsw, vga_set); 126 #endif /* SC_PIXEL_MODE */ 127 128 #ifndef SC_NO_MODE_CHANGE 129 static 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 }; 139 RENDERER(cga, GRAPHICS_MODE, grrndrsw, vga_set); 140 RENDERER(ega, GRAPHICS_MODE, grrndrsw, vga_set); 141 RENDERER(vga, GRAPHICS_MODE, grrndrsw, vga_set); 142 #endif /* SC_NO_MODE_CHANGE */ 143 144 RENDERER_MODULE(vga, vga_set); 145 146 #ifndef SC_NO_CUTPASTE 147 static 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 }; 151 static 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 157 static void 158 vga_nop(scr_stat *scp, ...) 159 { 160 } 161 162 /* text mode renderer */ 163 164 static void 165 vga_txtclear(scr_stat *scp, int c, int attr) 166 { 167 sc_vtb_clear(&scp->scr, c, attr); 168 } 169 170 static void 171 vga_txtborder(scr_stat *scp, int color) 172 { 173 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 174 } 175 176 static void 177 vga_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 199 static void 200 vga_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 214 static void 215 vga_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 275 static void 276 vga_txtblink(scr_stat *scp, int at, int flip) 277 { 278 } 279 280 #ifndef SC_NO_CUTPASTE 281 282 static void 283 draw_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 365 static void 366 remove_txtmouse(scr_stat *scp, int x, int y) 367 { 368 } 369 370 static void 371 vga_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 385 static void 386 vga_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 411 static void 412 vga_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 449 static void 450 vga_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 511 static void 512 vga_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 574 static void 575 vga_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 586 static void 587 draw_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 638 static void 639 vga_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 658 static void 659 vga_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 674 static void 675 draw_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 749 static void 750 remove_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 806 static void 807 vga_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 822 static void 823 vga_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