1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The DragonFly Project 6 * by Sascha Wildner <saw@online.de> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer as 13 * the first lines of this file unmodified. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $ 30 * $DragonFly: src/sys/dev/misc/syscons/scvgarndr.c,v 1.17 2008/08/10 19:45:01 swildner Exp $ 31 */ 32 33 #include "opt_syscons.h" 34 #include "opt_vga.h" 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/video/fb/fbreg.h> 43 #include <dev/video/fb/vgareg.h> 44 #include "syscons.h" 45 46 #include <bus/isa/isareg.h> 47 48 static vr_draw_border_t vga_txtborder; 49 static vr_draw_t vga_txtdraw; 50 static vr_set_cursor_t vga_txtcursor_shape; 51 static vr_draw_cursor_t vga_txtcursor; 52 static vr_blink_cursor_t vga_txtblink; 53 #ifndef SC_NO_CUTPASTE 54 static vr_draw_mouse_t vga_txtmouse; 55 #else 56 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop 57 #endif 58 59 #ifdef SC_PIXEL_MODE 60 static vr_draw_border_t vga_pxlborder_direct; 61 static vr_draw_border_t vga_pxlborder_packed; 62 static vr_draw_border_t vga_pxlborder_planar; 63 static vr_draw_t vga_vgadraw_direct; 64 static vr_draw_t vga_vgadraw_packed; 65 static vr_draw_t vga_vgadraw_planar; 66 static vr_set_cursor_t vga_pxlcursor_shape; 67 static vr_draw_cursor_t vga_pxlcursor_direct; 68 static vr_draw_cursor_t vga_pxlcursor_packed; 69 static vr_draw_cursor_t vga_pxlcursor_planar; 70 static vr_blink_cursor_t vga_pxlblink_direct; 71 static vr_blink_cursor_t vga_pxlblink_packed; 72 static vr_blink_cursor_t vga_pxlblink_planar; 73 #ifndef SC_NO_CUTPASTE 74 static vr_draw_mouse_t vga_pxlmouse_direct; 75 static vr_draw_mouse_t vga_pxlmouse_packed; 76 static vr_draw_mouse_t vga_pxlmouse_planar; 77 #else 78 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop 79 #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop 80 #define vga_pxlmouse_planar (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_txtborder, 92 vga_txtdraw, 93 vga_txtcursor_shape, 94 vga_txtcursor, 95 vga_txtblink, 96 vga_txtmouse, 97 }; 98 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set); 99 100 #ifdef SC_PIXEL_MODE 101 static sc_rndr_sw_t directrndrsw = { 102 vga_pxlborder_direct, 103 vga_vgadraw_direct, 104 vga_pxlcursor_shape, 105 vga_pxlcursor_direct, 106 vga_pxlblink_direct, 107 vga_pxlmouse_direct, 108 }; 109 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set); 110 111 static sc_rndr_sw_t packedrndrsw = { 112 vga_pxlborder_packed, 113 vga_vgadraw_packed, 114 vga_pxlcursor_shape, 115 vga_pxlcursor_packed, 116 vga_pxlblink_packed, 117 vga_pxlmouse_packed, 118 }; 119 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set); 120 121 static sc_rndr_sw_t planarrndrsw = { 122 vga_pxlborder_planar, 123 vga_vgadraw_planar, 124 vga_pxlcursor_shape, 125 vga_pxlcursor_planar, 126 vga_pxlblink_planar, 127 vga_pxlmouse_planar, 128 }; 129 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set); 130 #endif /* SC_PIXEL_MODE */ 131 132 #ifndef SC_NO_MODE_CHANGE 133 static sc_rndr_sw_t grrndrsw = { 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_draw_mouse_t *)vga_nop, 140 }; 141 RENDERER(vga, V_INFO_MM_OTHER, 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_txtborder(scr_stat *scp, int color) 166 { 167 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 168 } 169 170 static void 171 vga_txtdraw(scr_stat *scp, int from, int count, int flip) 172 { 173 uint16_t *p; 174 int c; 175 int a; 176 177 if (from + count > scp->xsize*scp->ysize) 178 count = scp->xsize*scp->ysize - from; 179 180 if (flip) { 181 for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) { 182 c = sc_vtb_getc(&scp->vtb, from); 183 a = sc_vtb_geta(&scp->vtb, from); 184 a = (a & 0x8800) | ((a & 0x7000) >> 4) 185 | ((a & 0x0700) << 4); 186 p = sc_vtb_putchar(&scp->scr, p, c, a); 187 } 188 } else { 189 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count); 190 } 191 } 192 193 static void 194 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink) 195 { 196 if (base < 0 || base >= scp->font_size) 197 return; 198 /* the caller may set height <= 0 in order to disable the cursor */ 199 #if 0 200 scp->cursor_base = base; 201 scp->cursor_height = height; 202 #endif 203 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp, 204 base, height, 205 scp->font_size, blink); 206 } 207 208 static void 209 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip) 210 { 211 sc_softc_t *sc; 212 213 sc = scp->sc; 214 scp->cursor_saveunder_char = c; 215 scp->cursor_saveunder_attr = a; 216 217 #ifndef SC_NO_FONT_LOADING 218 if (sc->flags & SC_CHAR_CURSOR) { 219 unsigned char *font; 220 int h; 221 int i; 222 223 if (scp->font_size < 14) { 224 font = sc->font_8; 225 h = 8; 226 } else if (scp->font_size >= 16) { 227 font = sc->font_16; 228 h = 16; 229 } else { 230 font = sc->font_14; 231 h = 14; 232 } 233 if (scp->cursor_base >= h) 234 return; 235 if (flip) 236 a = (a & 0x8800) 237 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 238 bcopy(font + c*h, font + sc->cursor_char*h, h); 239 font = font + sc->cursor_char*h; 240 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0); 241 i < h - scp->cursor_base; ++i) { 242 font[i] ^= 0xff; 243 } 244 sc->font_loading_in_progress = TRUE; 245 /* XXX */ 246 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font, 247 sc->cursor_char, 1); 248 sc->font_loading_in_progress = FALSE; 249 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a); 250 } else 251 #endif /* SC_NO_FONT_LOADING */ 252 { 253 if ((a & 0x7000) == 0x7000) { 254 a &= 0x8f00; 255 if ((a & 0x0700) == 0) 256 a |= 0x0700; 257 } else { 258 a |= 0x7000; 259 if ((a & 0x0700) == 0x0700) 260 a &= 0xf000; 261 } 262 if (flip) 263 a = (a & 0x8800) 264 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 265 sc_vtb_putc(&scp->scr, at, c, a); 266 } 267 } 268 269 static void 270 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip) 271 { 272 video_adapter_t *adp; 273 int cursor_attr; 274 275 if (scp->cursor_height <= 0) /* the text cursor is disabled */ 276 return; 277 278 adp = scp->sc->adp; 279 if (blink) { 280 scp->status |= VR_CURSOR_BLINK; 281 if (on) { 282 scp->status |= VR_CURSOR_ON; 283 (*vidsw[adp->va_index]->set_hw_cursor)(adp, 284 at%scp->xsize, 285 at/scp->xsize); 286 } else { 287 if (scp->status & VR_CURSOR_ON) 288 (*vidsw[adp->va_index]->set_hw_cursor)(adp, 289 -1, -1); 290 scp->status &= ~VR_CURSOR_ON; 291 } 292 } else { 293 scp->status &= ~VR_CURSOR_BLINK; 294 if (on) { 295 scp->status |= VR_CURSOR_ON; 296 draw_txtcharcursor(scp, at, 297 sc_vtb_getc(&scp->scr, at), 298 sc_vtb_geta(&scp->scr, at), 299 flip); 300 } else { 301 cursor_attr = scp->cursor_saveunder_attr; 302 if (flip) 303 cursor_attr = (cursor_attr & 0x8800) 304 | ((cursor_attr & 0x7000) >> 4) 305 | ((cursor_attr & 0x0700) << 4); 306 if (scp->status & VR_CURSOR_ON) 307 sc_vtb_putc(&scp->scr, at, 308 scp->cursor_saveunder_char, 309 cursor_attr); 310 scp->status &= ~VR_CURSOR_ON; 311 } 312 } 313 } 314 315 static void 316 vga_txtblink(scr_stat *scp, int at, int flip) 317 { 318 } 319 320 #ifndef SC_NO_CUTPASTE 321 322 static void 323 draw_txtmouse(scr_stat *scp, int x, int y) 324 { 325 #ifndef SC_ALT_MOUSE_IMAGE 326 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) { 327 u_char font_buf[128]; 328 u_short cursor[32]; 329 u_char c; 330 int pos; 331 int xoffset, yoffset; 332 int i; 333 334 /* prepare mousepointer char's bitmaps */ 335 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 336 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size, 337 &font_buf[0], scp->font_size); 338 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size, 339 &font_buf[32], scp->font_size); 340 bcopy(scp->font 341 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size, 342 &font_buf[64], scp->font_size); 343 bcopy(scp->font 344 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size, 345 &font_buf[96], scp->font_size); 346 for (i = 0; i < scp->font_size; ++i) { 347 cursor[i] = font_buf[i]<<8 | font_buf[i+32]; 348 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96]; 349 } 350 351 /* now and-or in the mousepointer image */ 352 xoffset = x%8; 353 yoffset = y%scp->font_size; 354 for (i = 0; i < 16; ++i) { 355 cursor[i + yoffset] = 356 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset)) 357 | (mouse_or_mask[i] >> xoffset); 358 } 359 for (i = 0; i < scp->font_size; ++i) { 360 font_buf[i] = (cursor[i] & 0xff00) >> 8; 361 font_buf[i + 32] = cursor[i] & 0xff; 362 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8; 363 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff; 364 } 365 366 #if 1 367 /* wait for vertical retrace to avoid jitter on some videocards */ 368 while (!(inb(CRTC + 6) & 0x08)) /* idle */ ; 369 #endif 370 c = scp->sc->mouse_char; 371 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf, 372 c, 4); 373 374 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos)); 375 /* FIXME: may be out of range! */ 376 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2, 377 sc_vtb_geta(&scp->scr, pos + scp->xsize)); 378 if (x < (scp->xsize - 1)*8) { 379 sc_vtb_putc(&scp->scr, pos + 1, c + 1, 380 sc_vtb_geta(&scp->scr, pos + 1)); 381 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3, 382 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1)); 383 } 384 } else 385 #endif /* SC_ALT_MOUSE_IMAGE */ 386 { 387 /* Red, magenta and brown are mapped to green to to keep it readable */ 388 static const int col_conv[16] = { 389 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14 390 }; 391 int pos; 392 int color; 393 int a; 394 395 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 396 a = sc_vtb_geta(&scp->scr, pos); 397 if (scp->sc->adp->va_flags & V_ADP_COLOR) 398 color = (col_conv[(a & 0xf000) >> 12] << 12) 399 | ((a & 0x0f00) | 0x0800); 400 else 401 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4); 402 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color); 403 } 404 } 405 406 static void 407 remove_txtmouse(scr_stat *scp, int x, int y) 408 { 409 } 410 411 static void 412 vga_txtmouse(scr_stat *scp, int x, int y, int on) 413 { 414 if (on) 415 draw_txtmouse(scp, x, y); 416 else 417 remove_txtmouse(scp, x, y); 418 } 419 420 #endif /* SC_NO_CUTPASTE */ 421 422 #ifdef SC_PIXEL_MODE 423 424 /* pixel (raster text) mode renderer */ 425 426 static void 427 vga_pxlborder_direct(scr_stat *scp, int color) 428 { 429 int i, x, y; 430 int line_width, pixel_size; 431 uint32_t u32 = 0; 432 vm_offset_t draw_pos, draw_end, p; 433 434 line_width = scp->sc->adp->va_line_width; 435 pixel_size = scp->sc->adp->va_info.vi_pixel_size; 436 437 for (i = 0; i < 4 / pixel_size; ++i) 438 u32 += scp->ega_palette[color] << (i * 8 * pixel_size); 439 440 if (scp->yoff > 0) { 441 draw_pos = scp->sc->adp->va_window; 442 draw_end = draw_pos + line_width * scp->yoff * scp->font_size; 443 444 for (p = draw_pos; p < draw_end; p += 4) 445 writel(p, u32); 446 } 447 448 y = (scp->yoff + scp->ysize) * scp->font_size; 449 450 if (scp->ypixel > y) { 451 draw_pos = scp->sc->adp->va_window + line_width * y; 452 draw_end = draw_pos + line_width * (scp->ypixel - y); 453 454 for (p = draw_pos; p < draw_end; p += 4) 455 writel(p, u32); 456 } 457 458 y = scp->yoff * scp->font_size; 459 x = scp->xpixel / 8 - scp->xoff - scp->xsize; 460 461 for (i = 0; i < scp->ysize * scp->font_size; ++i) { 462 if (scp->xoff > 0) { 463 draw_pos = scp->sc->adp->va_window + 464 line_width * (y + i); 465 draw_end = draw_pos + scp->xoff * 8 * pixel_size; 466 467 for (p = draw_pos; p < draw_end; p += 4) 468 writel(p, u32); 469 } 470 471 if (x > 0) { 472 draw_pos = scp->sc->adp->va_window + 473 line_width * (y + i) + 474 scp->xoff * 8 * pixel_size + 475 scp->xsize * 8 * pixel_size; 476 draw_end = draw_pos + x * 8 * pixel_size; 477 478 for (p = draw_pos; p < draw_end; p += 4) 479 writel(p, u32); 480 } 481 } 482 } 483 484 static void 485 vga_pxlborder_packed(scr_stat *scp, int color) 486 { 487 int i, x, y; 488 int line_width; 489 uint32_t u32; 490 vm_offset_t draw_pos, draw_end, p; 491 492 line_width = scp->sc->adp->va_line_width; 493 u32 = (color << 24) + (color << 16) + (color << 8) + color; 494 495 if (scp->yoff > 0) { 496 draw_pos = scp->sc->adp->va_window; 497 draw_end = draw_pos + line_width * scp->yoff * scp->font_size; 498 499 for (p = draw_pos; p < draw_end; p += 4) 500 writel(p, u32); 501 } 502 503 y = (scp->yoff + scp->ysize) * scp->font_size; 504 505 if (scp->ypixel > y) { 506 draw_pos = scp->sc->adp->va_window + line_width * y; 507 draw_end = draw_pos + line_width * (scp->ypixel - y); 508 509 for (p = draw_pos; p < draw_end; p += 4) 510 writel(p, u32); 511 } 512 513 y = scp->yoff * scp->font_size; 514 x = scp->xpixel / 8 - scp->xoff - scp->xsize; 515 516 for (i = 0; i < scp->ysize * scp->font_size; ++i) { 517 if (scp->xoff > 0) { 518 draw_pos = scp->sc->adp->va_window + 519 line_width * (y + i); 520 draw_end = draw_pos + scp->xoff * 8; 521 522 for (p = draw_pos; p < draw_end; p += 4) 523 writel(p, u32); 524 } 525 526 if (x > 0) { 527 draw_pos = scp->sc->adp->va_window + 528 line_width * (y + i) + scp->xoff * 8 + 529 scp->xsize * 8; 530 draw_end = draw_pos + x * 8; 531 532 for (p = draw_pos; p < draw_end; p += 4) 533 writel(p, u32); 534 } 535 } 536 } 537 538 static void 539 vga_pxlborder_planar(scr_stat *scp, int color) 540 { 541 vm_offset_t p; 542 int line_width; 543 int x; 544 int y; 545 int i; 546 547 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 548 549 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 550 outw(GDCIDX, 0x0003); /* data rotate/function select */ 551 outw(GDCIDX, 0x0f01); /* set/reset enable */ 552 outw(GDCIDX, 0xff08); /* bit mask */ 553 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 554 line_width = scp->sc->adp->va_line_width; 555 p = scp->sc->adp->va_window; 556 if (scp->yoff > 0) 557 bzero_io((void *)p, line_width*scp->yoff*scp->font_size); 558 y = (scp->yoff + scp->ysize)*scp->font_size; 559 if (scp->ypixel > y) 560 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y)); 561 y = scp->yoff*scp->font_size; 562 x = scp->xpixel/8 - scp->xoff - scp->xsize; 563 for (i = 0; i < scp->ysize*scp->font_size; ++i) { 564 if (scp->xoff > 0) 565 bzero_io((void *)(p + line_width*(y + i)), scp->xoff); 566 if (x > 0) 567 bzero_io((void *)(p + line_width*(y + i) 568 + scp->xoff + scp->xsize), x); 569 } 570 outw(GDCIDX, 0x0000); /* set/reset */ 571 outw(GDCIDX, 0x0001); /* set/reset enable */ 572 } 573 574 static void 575 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip) 576 { 577 int line_width, pixel_size; 578 int a, i, j, k, l, pos; 579 uint32_t fg, bg, u32; 580 unsigned char *char_data; 581 vm_offset_t draw_pos, p; 582 583 line_width = scp->sc->adp->va_line_width; 584 pixel_size = scp->sc->adp->va_info.vi_pixel_size; 585 586 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size); 587 588 if (from + count > scp->xsize * scp->ysize) 589 count = scp->xsize * scp->ysize - from; 590 591 for (i = from; count-- > 0; ++i) { 592 a = sc_vtb_geta(&scp->vtb, i); 593 594 if (flip) { 595 fg = scp->ega_palette[(((a & 0x7000) >> 4) | 596 (a & 0x0800)) >> 8]; 597 bg = scp->ega_palette[(((a & 0x8000) >> 4) | 598 (a & 0x0700)) >> 8]; 599 } else { 600 fg = scp->ega_palette[(a & 0x0f00) >> 8]; 601 bg = scp->ega_palette[(a & 0xf000) >> 12]; 602 } 603 604 p = draw_pos; 605 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * 606 scp->font_size]); 607 608 for (j = 0; j < scp->font_size; ++j, ++char_data) { 609 pos = 7; 610 611 for (k = 0; k < 2 * pixel_size; ++k) { 612 u32 = 0; 613 614 for (l = 0; l < 4 / pixel_size; ++l) { 615 u32 += (*char_data & (1 << pos--) ? 616 fg : bg) << (l * 8 * pixel_size); 617 } 618 619 writel(p, u32); 620 p += 4; 621 } 622 623 p += line_width - 8 * pixel_size; 624 } 625 626 draw_pos += 8 * pixel_size; 627 628 if ((i % scp->xsize) == scp->xsize - 1) 629 draw_pos += scp->xoff * 16 * pixel_size + 630 (scp->font_size - 1) * line_width; 631 } 632 } 633 634 static void 635 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip) 636 { 637 int line_width; 638 int a, i, j; 639 uint32_t fg, bg, u32; 640 unsigned char *char_data; 641 vm_offset_t draw_pos, p; 642 643 line_width = scp->sc->adp->va_line_width; 644 645 draw_pos = VIDEO_MEMORY_POS(scp, from, 8); 646 647 if (from + count > scp->xsize * scp->ysize) 648 count = scp->xsize * scp->ysize - from; 649 650 for (i = from; count-- > 0; ++i) { 651 a = sc_vtb_geta(&scp->vtb, i); 652 653 if (flip) { 654 fg = ((a & 0xf000) >> 4) >> 8; 655 bg = (a & 0x0f00) >> 8; 656 } else { 657 fg = (a & 0x0f00) >> 8; 658 bg = ((a & 0xf000) >> 4) >> 8; 659 } 660 661 p = draw_pos; 662 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * 663 scp->font_size]); 664 665 for (j = 0; j < scp->font_size; ++j, ++char_data) { 666 u32 = ((*char_data & 1 ? fg : bg) << 24) + 667 ((*char_data & 2 ? fg : bg) << 16) + 668 ((*char_data & 4 ? fg : bg) << 8) + 669 (*char_data & 8 ? fg : bg); 670 writel(p + 4, u32); 671 672 u32 = ((*char_data & 16 ? fg : bg) << 24) + 673 ((*char_data & 32 ? fg : bg) << 16) + 674 ((*char_data & 64 ? fg : bg) << 8) + 675 (*char_data & 128 ? fg : bg); 676 writel(p, u32); 677 678 p += line_width; 679 } 680 681 draw_pos += 8; 682 683 if ((i % scp->xsize) == scp->xsize - 1) 684 draw_pos += scp->xoff * 16 + 685 (scp->font_size - 1) * line_width; 686 } 687 } 688 689 static void 690 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip) 691 { 692 vm_offset_t d; 693 vm_offset_t e; 694 u_char *f; 695 u_short bg; 696 u_short col1, col2; 697 int line_width; 698 int i, j; 699 int a; 700 u_char c; 701 702 d = VIDEO_MEMORY_POS(scp, from, 1); 703 704 line_width = scp->sc->adp->va_line_width; 705 706 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 707 outw(GDCIDX, 0x0003); /* data rotate/function select */ 708 outw(GDCIDX, 0x0f01); /* set/reset enable */ 709 outw(GDCIDX, 0xff08); /* bit mask */ 710 bg = -1; 711 if (from + count > scp->xsize*scp->ysize) 712 count = scp->xsize*scp->ysize - from; 713 for (i = from; count-- > 0; ++i) { 714 a = sc_vtb_geta(&scp->vtb, i); 715 if (flip) { 716 col1 = ((a & 0x7000) >> 4) | (a & 0x0800); 717 col2 = ((a & 0x8000) >> 4) | (a & 0x0700); 718 } else { 719 col1 = (a & 0x0f00); 720 col2 = (a & 0xf000) >> 4; 721 } 722 /* set background color in EGA/VGA latch */ 723 if (bg != col2) { 724 bg = col2; 725 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 726 outw(GDCIDX, bg | 0x00); /* set/reset */ 727 writeb(d, 0); 728 c = readb(d); /* set bg color in the latch */ 729 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 730 } 731 /* foreground color */ 732 outw(GDCIDX, col1 | 0x00); /* set/reset */ 733 e = d; 734 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]); 735 for (j = 0; j < scp->font_size; ++j, ++f) { 736 writeb(e, *f); 737 e += line_width; 738 } 739 ++d; 740 if ((i % scp->xsize) == scp->xsize - 1) 741 d += scp->xoff*2 742 + (scp->font_size - 1)*line_width; 743 } 744 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 745 outw(GDCIDX, 0x0000); /* set/reset */ 746 outw(GDCIDX, 0x0001); /* set/reset enable */ 747 } 748 749 static void 750 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink) 751 { 752 if (base < 0 || base >= scp->font_size) 753 return; 754 /* the caller may set height <= 0 in order to disable the cursor */ 755 #if 0 756 scp->cursor_base = base; 757 scp->cursor_height = height; 758 #endif 759 } 760 761 static void 762 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip) 763 { 764 int line_width, pixel_size, height; 765 int a, i, j, k, pos; 766 uint32_t fg, bg, u32; 767 unsigned char *char_data; 768 vm_offset_t draw_pos; 769 770 line_width = scp->sc->adp->va_line_width; 771 pixel_size = scp->sc->adp->va_info.vi_pixel_size; 772 773 draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) + 774 (scp->font_size - scp->cursor_base - 1) * line_width; 775 776 a = sc_vtb_geta(&scp->vtb, at); 777 778 if (flip) { 779 fg = scp->ega_palette[((on) ? (a & 0x0f00) : 780 ((a & 0xf000) >> 4)) >> 8]; 781 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : 782 (a & 0x0f00)) >> 8]; 783 } else { 784 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : 785 (a & 0x0f00)) >> 8]; 786 bg = scp->ega_palette[((on) ? (a & 0x0f00) : 787 ((a & 0xf000) >> 4)) >> 8]; 788 } 789 790 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size + 791 scp->font_size - scp->cursor_base - 1]); 792 793 height = imin(scp->cursor_height, scp->font_size); 794 795 for (i = 0; i < height; ++i, --char_data) { 796 pos = 7; 797 798 for (j = 0; j < 2 * pixel_size; ++j) { 799 u32 = 0; 800 801 for (k = 0; k < 4 / pixel_size; ++k) { 802 u32 += (*char_data & (1 << pos--) ? 803 fg : bg) << (k * 8 * pixel_size); 804 } 805 806 writel(draw_pos, u32); 807 draw_pos += 4; 808 } 809 810 draw_pos -= line_width + 8 * pixel_size; 811 } 812 } 813 814 static void 815 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip) 816 { 817 int line_width, height; 818 int a, i; 819 uint32_t fg, bg, u32; 820 unsigned char *char_data; 821 vm_offset_t draw_pos; 822 823 line_width = scp->sc->adp->va_line_width; 824 825 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) + 826 (scp->font_size - scp->cursor_base - 1) * line_width; 827 828 a = sc_vtb_geta(&scp->vtb, at); 829 830 if (flip) { 831 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; 832 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; 833 } else { 834 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; 835 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; 836 } 837 838 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size + 839 scp->font_size - scp->cursor_base - 1]); 840 841 height = imin(scp->cursor_height, scp->font_size); 842 843 for (i = 0; i < height; ++i, --char_data) { 844 u32 = ((*char_data & 1 ? fg : bg) << 24) + 845 ((*char_data & 2 ? fg : bg) << 16) + 846 ((*char_data & 4 ? fg : bg) << 8) + 847 (*char_data & 8 ? fg : bg); 848 writel(draw_pos + 4, u32); 849 850 u32 = ((*char_data & 16 ? fg : bg) << 24) + 851 ((*char_data & 32 ? fg : bg) << 16) + 852 ((*char_data & 64 ? fg : bg) << 8) + 853 (*char_data & 128 ? fg : bg); 854 writel(draw_pos, u32); 855 856 draw_pos -= line_width; 857 } 858 } 859 860 static void 861 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip) 862 { 863 vm_offset_t d; 864 u_char *f; 865 int line_width; 866 int height; 867 int col; 868 int a; 869 int i; 870 u_char c; 871 872 line_width = scp->sc->adp->va_line_width; 873 874 d = VIDEO_MEMORY_POS(scp, at, 1) + 875 (scp->font_size - scp->cursor_base - 1) * line_width; 876 877 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 878 outw(GDCIDX, 0x0003); /* data rotate/function select */ 879 outw(GDCIDX, 0x0f01); /* set/reset enable */ 880 /* set background color in EGA/VGA latch */ 881 a = sc_vtb_geta(&scp->vtb, at); 882 if (flip) 883 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 884 else 885 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 886 outw(GDCIDX, col | 0x00); /* set/reset */ 887 outw(GDCIDX, 0xff08); /* bit mask */ 888 writeb(d, 0); 889 c = readb(d); /* set bg color in the latch */ 890 /* foreground color */ 891 if (flip) 892 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 893 else 894 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 895 outw(GDCIDX, col | 0x00); /* set/reset */ 896 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size 897 + scp->font_size - scp->cursor_base - 1]); 898 height = imin(scp->cursor_height, scp->font_size); 899 for (i = 0; i < height; ++i, --f) { 900 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ 901 writeb(d, 0); 902 d -= line_width; 903 } 904 outw(GDCIDX, 0x0000); /* set/reset */ 905 outw(GDCIDX, 0x0001); /* set/reset enable */ 906 outw(GDCIDX, 0xff08); /* bit mask */ 907 } 908 909 static int pxlblinkrate = 0; 910 911 static void 912 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip) 913 { 914 if (scp->cursor_height <= 0) /* the text cursor is disabled */ 915 return; 916 917 if (on) { 918 if (!blink) { 919 scp->status |= VR_CURSOR_ON; 920 draw_pxlcursor_direct(scp, at, on, flip); 921 } else if (++pxlblinkrate & 4) { 922 pxlblinkrate = 0; 923 scp->status ^= VR_CURSOR_ON; 924 draw_pxlcursor_direct(scp, at, 925 scp->status & VR_CURSOR_ON, 926 flip); 927 } 928 } else { 929 if (scp->status & VR_CURSOR_ON) 930 draw_pxlcursor_direct(scp, at, on, flip); 931 scp->status &= ~VR_CURSOR_ON; 932 } 933 if (blink) 934 scp->status |= VR_CURSOR_BLINK; 935 else 936 scp->status &= ~VR_CURSOR_BLINK; 937 } 938 939 static void 940 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip) 941 { 942 if (scp->cursor_height <= 0) /* the text cursor is disabled */ 943 return; 944 945 if (on) { 946 if (!blink) { 947 scp->status |= VR_CURSOR_ON; 948 draw_pxlcursor_packed(scp, at, on, flip); 949 } else if (++pxlblinkrate & 4) { 950 pxlblinkrate = 0; 951 scp->status ^= VR_CURSOR_ON; 952 draw_pxlcursor_packed(scp, at, 953 scp->status & VR_CURSOR_ON, 954 flip); 955 } 956 } else { 957 if (scp->status & VR_CURSOR_ON) 958 draw_pxlcursor_packed(scp, at, on, flip); 959 scp->status &= ~VR_CURSOR_ON; 960 } 961 if (blink) 962 scp->status |= VR_CURSOR_BLINK; 963 else 964 scp->status &= ~VR_CURSOR_BLINK; 965 } 966 967 static void 968 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip) 969 { 970 if (scp->cursor_height <= 0) /* the text cursor is disabled */ 971 return; 972 973 if (on) { 974 if (!blink) { 975 scp->status |= VR_CURSOR_ON; 976 draw_pxlcursor_planar(scp, at, on, flip); 977 } else if (++pxlblinkrate & 4) { 978 pxlblinkrate = 0; 979 scp->status ^= VR_CURSOR_ON; 980 draw_pxlcursor_planar(scp, at, 981 scp->status & VR_CURSOR_ON, 982 flip); 983 } 984 } else { 985 if (scp->status & VR_CURSOR_ON) 986 draw_pxlcursor_planar(scp, at, on, flip); 987 scp->status &= ~VR_CURSOR_ON; 988 } 989 if (blink) 990 scp->status |= VR_CURSOR_BLINK; 991 else 992 scp->status &= ~VR_CURSOR_BLINK; 993 } 994 995 static void 996 vga_pxlblink_direct(scr_stat *scp, int at, int flip) 997 { 998 if (!(scp->status & VR_CURSOR_BLINK)) 999 return; 1000 if (!(++pxlblinkrate & 4)) 1001 return; 1002 pxlblinkrate = 0; 1003 scp->status ^= VR_CURSOR_ON; 1004 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip); 1005 } 1006 1007 static void 1008 vga_pxlblink_packed(scr_stat *scp, int at, int flip) 1009 { 1010 if (!(scp->status & VR_CURSOR_BLINK)) 1011 return; 1012 if (!(++pxlblinkrate & 4)) 1013 return; 1014 pxlblinkrate = 0; 1015 scp->status ^= VR_CURSOR_ON; 1016 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip); 1017 } 1018 1019 static void 1020 vga_pxlblink_planar(scr_stat *scp, int at, int flip) 1021 { 1022 if (!(scp->status & VR_CURSOR_BLINK)) 1023 return; 1024 if (!(++pxlblinkrate & 4)) 1025 return; 1026 pxlblinkrate = 0; 1027 scp->status ^= VR_CURSOR_ON; 1028 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip); 1029 } 1030 1031 #ifndef SC_NO_CUTPASTE 1032 1033 static void 1034 draw_pxlmouse_direct(scr_stat *scp, int x, int y) 1035 { 1036 int line_width, pixel_size; 1037 int xend, yend; 1038 int i, j; 1039 vm_offset_t draw_pos; 1040 1041 line_width = scp->sc->adp->va_line_width; 1042 pixel_size = scp->sc->adp->va_info.vi_pixel_size; 1043 1044 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize)); 1045 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize)); 1046 1047 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size; 1048 1049 for (i = 0; i < (yend - y); i++) { 1050 for (j = (xend - x - 1); j >= 0; j--) { 1051 switch (scp->sc->adp->va_info.vi_depth) { 1052 case 32: 1053 if (mouse_or_mask[i] & 1 << (15 - j)) 1054 writel(draw_pos + 4 * j, 1055 scp->ega_palette[15]); 1056 else if (mouse_and_mask[i] & 1 << (15 - j)) 1057 writel(draw_pos + 4 * j, 1058 scp->ega_palette[0]); 1059 break; 1060 case 16: 1061 /* FALLTHROUGH */ 1062 case 15: 1063 if (mouse_or_mask[i] & 1 << (15 - j)) 1064 writew(draw_pos + 2 * j, 1065 scp->ega_palette[15]); 1066 else if (mouse_and_mask[i] & 1 << (15 - j)) 1067 writew(draw_pos + 2 * j, 1068 scp->ega_palette[0]); 1069 break; 1070 } 1071 } 1072 1073 draw_pos += line_width; 1074 } 1075 } 1076 1077 static void 1078 draw_pxlmouse_packed(scr_stat *scp, int x, int y) 1079 { 1080 int line_width; 1081 int xend, yend; 1082 int i, j; 1083 vm_offset_t draw_pos; 1084 1085 line_width = scp->sc->adp->va_line_width; 1086 1087 xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel)); 1088 yend = imin(scp->font_size * (scp->yoff + scp->ysize), 1089 imin(y + 16, scp->ypixel)); 1090 1091 draw_pos = scp->sc->adp->va_window + y * line_width + x; 1092 1093 for (i = 0; i < (yend - y); i++) { 1094 for (j = (xend - x - 1); j >= 0; j--) { 1095 if (mouse_or_mask[i] & 1 << (15 - j)) 1096 writeb(draw_pos + j, 15); 1097 else if (mouse_and_mask[i] & 1 << (15 - j)) 1098 writeb(draw_pos + j, 0); 1099 } 1100 1101 draw_pos += line_width; 1102 } 1103 } 1104 1105 static void 1106 draw_pxlmouse_planar(scr_stat *scp, int x, int y) 1107 { 1108 vm_offset_t p; 1109 int line_width; 1110 int xoff; 1111 int ymax; 1112 u_short m; 1113 int i, j; 1114 1115 line_width = scp->sc->adp->va_line_width; 1116 xoff = (x - scp->xoff*8)%8; 1117 ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize)); 1118 1119 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */ 1120 outw(GDCIDX, 0x0001); /* set/reset enable */ 1121 outw(GDCIDX, 0x0002); /* color compare */ 1122 outw(GDCIDX, 0x0007); /* color don't care */ 1123 outw(GDCIDX, 0xff08); /* bit mask */ 1124 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */ 1125 p = scp->sc->adp->va_window + line_width*y + x/8; 1126 if (x < 8 * (scp->xoff + scp->xsize) - 8) { 1127 for (i = y, j = 0; i < ymax; ++i, ++j) { 1128 m = ~(mouse_and_mask[j] >> xoff); 1129 *(u_char *)p &= m >> 8; 1130 *(u_char *)(p + 1) &= m; 1131 p += line_width; 1132 } 1133 } else { 1134 xoff += 8; 1135 for (i = y, j = 0; i < ymax; ++i, ++j) { 1136 m = ~(mouse_and_mask[j] >> xoff); 1137 *(u_char *)p &= m; 1138 p += line_width; 1139 } 1140 } 1141 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */ 1142 p = scp->sc->adp->va_window + line_width*y + x/8; 1143 if (x < 8 * (scp->xoff + scp->xsize) - 8) { 1144 for (i = y, j = 0; i < ymax; ++i, ++j) { 1145 m = mouse_or_mask[j] >> xoff; 1146 *(u_char *)p &= m >> 8; 1147 *(u_char *)(p + 1) &= m; 1148 p += line_width; 1149 } 1150 } else { 1151 for (i = y, j = 0; i < ymax; ++i, ++j) { 1152 m = mouse_or_mask[j] >> xoff; 1153 *(u_char *)p &= m; 1154 p += line_width; 1155 } 1156 } 1157 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 1158 outw(GDCIDX, 0x0003); /* data rotate/function select */ 1159 } 1160 1161 static void 1162 remove_pxlmouse(scr_stat *scp, int x, int y) 1163 { 1164 int col, row; 1165 int pos; 1166 int i; 1167 1168 /* erase the mouse cursor image */ 1169 col = x/8 - scp->xoff; 1170 row = y/scp->font_size - scp->yoff; 1171 pos = row*scp->xsize + col; 1172 i = (col < scp->xsize - 1) ? 2 : 1; 1173 (*scp->rndr->draw)(scp, pos, i, FALSE); 1174 if (row < scp->ysize - 1) 1175 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); 1176 } 1177 1178 static void 1179 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) 1180 { 1181 if (on) 1182 draw_pxlmouse_direct(scp, x, y); 1183 else 1184 remove_pxlmouse(scp, x, y); 1185 } 1186 1187 static void 1188 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on) 1189 { 1190 if (on) 1191 draw_pxlmouse_packed(scp, x, y); 1192 else 1193 remove_pxlmouse(scp, x, y); 1194 } 1195 1196 static void 1197 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on) 1198 { 1199 if (on) 1200 draw_pxlmouse_planar(scp, x, y); 1201 else 1202 remove_pxlmouse(scp, x, y); 1203 } 1204 1205 #endif /* SC_NO_CUTPASTE */ 1206 #endif /* SC_PIXEL_MODE */ 1207 1208 #ifndef SC_NO_MODE_CHANGE 1209 1210 /* graphics mode renderer */ 1211 1212 static void 1213 vga_grborder(scr_stat *scp, int color) 1214 { 1215 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); 1216 } 1217 1218 #endif 1219