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