| 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 | */ |
| 31 | |
| 32 | #include "opt_syscons.h" |
| 33 | #include "opt_vga.h" |
| 34 | |
| 35 | #include <sys/param.h> |
| 36 | #include <sys/systm.h> |
| 37 | #include <sys/kernel.h> |
| 38 | #include <sys/thread.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_height) |
| 197 | return; |
| 198 | |
| 199 | /* the caller may set height <= 0 in order to disable the cursor */ |
| 200 | #if 0 |
| 201 | scp->cursor_base = base; |
| 202 | scp->cursor_height = height; |
| 203 | #endif |
| 204 | (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp, |
| 205 | base, height, |
| 206 | scp->font_height, |
| 207 | blink); |
| 208 | |
| 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_height < 14) { |
| 227 | font = sc->font_8; |
| 228 | h = 8; |
| 229 | } else if (scp->font_height >= 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 | int sc_txtmouse_no_retrace_wait; |
| 324 | |
| 325 | #ifndef SC_NO_CUTPASTE |
| 326 | |
| 327 | static void |
| 328 | draw_txtmouse(scr_stat *scp, int x, int y) |
| 329 | { |
| 330 | #ifndef SC_ALT_MOUSE_IMAGE |
| 331 | if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) { |
| 332 | u_char font_buf[128]; |
| 333 | u_short cursor[32]; |
| 334 | u_char c; |
| 335 | int pos; |
| 336 | int xoffset, yoffset; |
| 337 | int i; |
| 338 | |
| 339 | /* prepare mousepointer char's bitmaps */ |
| 340 | pos = (y / scp->font_height - scp->yoff) * scp->xsize + |
| 341 | x / scp->font_width - scp->xoff; |
| 342 | bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height, |
| 343 | &font_buf[0], scp->font_height); |
| 344 | bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height, |
| 345 | &font_buf[32], scp->font_height); |
| 346 | bcopy(scp->font |
| 347 | + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height, |
| 348 | &font_buf[64], scp->font_height); |
| 349 | bcopy(scp->font + |
| 350 | sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height, |
| 351 | &font_buf[96], scp->font_height); |
| 352 | for (i = 0; i < scp->font_height; ++i) { |
| 353 | cursor[i] = (font_buf[i]<<8) | font_buf[i+32]; |
| 354 | cursor[i + scp->font_height] = (font_buf[i+64]<<8) | |
| 355 | font_buf[i+96]; |
| 356 | } |
| 357 | |
| 358 | /* now and-or in the mousepointer image */ |
| 359 | xoffset = x % scp->font_width; |
| 360 | yoffset = y % scp->font_height; |
| 361 | for (i = 0; i < 16; ++i) { |
| 362 | cursor[i + yoffset] = |
| 363 | (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset)) |
| 364 | | (mouse_or_mask[i] >> xoffset); |
| 365 | } |
| 366 | for (i = 0; i < scp->font_height; ++i) { |
| 367 | font_buf[i] = (cursor[i] & 0xff00) >> 8; |
| 368 | font_buf[i + 32] = cursor[i] & 0xff; |
| 369 | font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8; |
| 370 | font_buf[i + 96] = cursor[i + scp->font_height] & 0xff; |
| 371 | } |
| 372 | |
| 373 | #if 1 |
| 374 | /* wait for vertical retrace to avoid jitter on some videocards */ |
| 375 | while (!sc_txtmouse_no_retrace_wait && |
| 376 | !(inb(CRTC + 6) & 0x08)) |
| 377 | /* idle */ ; |
| 378 | #endif |
| 379 | c = scp->sc->mouse_char; |
| 380 | (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf, |
| 381 | c, 4); |
| 382 | |
| 383 | sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos)); |
| 384 | /* FIXME: may be out of range! */ |
| 385 | sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2, |
| 386 | sc_vtb_geta(&scp->scr, pos + scp->xsize)); |
| 387 | if (x < (scp->xsize - 1)*8) { |
| 388 | sc_vtb_putc(&scp->scr, pos + 1, c + 1, |
| 389 | sc_vtb_geta(&scp->scr, pos + 1)); |
| 390 | sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3, |
| 391 | sc_vtb_geta(&scp->scr, pos + scp->xsize + 1)); |
| 392 | } |
| 393 | } else |
| 394 | #endif /* SC_ALT_MOUSE_IMAGE */ |
| 395 | { |
| 396 | /* Red, magenta and brown are mapped to green to to keep it readable */ |
| 397 | static const int col_conv[16] = { |
| 398 | 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14 |
| 399 | }; |
| 400 | int pos; |
| 401 | int color; |
| 402 | int a; |
| 403 | |
| 404 | pos = (y / scp->font_height - scp->yoff)* |
| 405 | scp->xsize + x / scp->font_width - scp->xoff; |
| 406 | a = sc_vtb_geta(&scp->scr, pos); |
| 407 | if (scp->sc->adp->va_flags & V_ADP_COLOR) |
| 408 | color = (col_conv[(a & 0xf000) >> 12] << 12) |
| 409 | | ((a & 0x0f00) | 0x0800); |
| 410 | else |
| 411 | color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4); |
| 412 | sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color); |
| 413 | } |
| 414 | |
| 415 | } |
| 416 | |
| 417 | static void |
| 418 | remove_txtmouse(scr_stat *scp, int x, int y) |
| 419 | { |
| 420 | } |
| 421 | |
| 422 | static void |
| 423 | vga_txtmouse(scr_stat *scp, int x, int y, int on) |
| 424 | { |
| 425 | if (on) |
| 426 | draw_txtmouse(scp, x, y); |
| 427 | else |
| 428 | remove_txtmouse(scp, x, y); |
| 429 | } |
| 430 | |
| 431 | #endif /* SC_NO_CUTPASTE */ |
| 432 | |
| 433 | #ifdef SC_PIXEL_MODE |
| 434 | |
| 435 | /* pixel (raster text) mode renderer */ |
| 436 | |
| 437 | static void |
| 438 | vga_pxlborder_direct(scr_stat *scp, int color) |
| 439 | { |
| 440 | int i, x, y; |
| 441 | int line_width, pixel_size; |
| 442 | uint32_t u32 = 0; |
| 443 | vm_offset_t draw_pos, draw_end, p; |
| 444 | |
| 445 | line_width = scp->sc->adp->va_line_width; |
| 446 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; |
| 447 | |
| 448 | for (i = 0; i < 4 / pixel_size; ++i) |
| 449 | u32 += scp->ega_palette[color] << (i * 8 * pixel_size); |
| 450 | |
| 451 | if (scp->yoff > 0) { |
| 452 | draw_pos = scp->sc->adp->va_window; |
| 453 | draw_end = draw_pos + line_width * scp->yoff * scp->font_height; |
| 454 | |
| 455 | for (p = draw_pos; p < draw_end; p += 4) |
| 456 | writel(p, u32); |
| 457 | } |
| 458 | |
| 459 | y = (scp->yoff + scp->ysize) * scp->font_height; |
| 460 | |
| 461 | if (scp->ypixel > y) { |
| 462 | draw_pos = scp->sc->adp->va_window + line_width * y; |
| 463 | draw_end = draw_pos + line_width * (scp->ypixel - y); |
| 464 | |
| 465 | for (p = draw_pos; p < draw_end; p += 4) |
| 466 | writel(p, u32); |
| 467 | } |
| 468 | |
| 469 | y = scp->yoff * scp->font_height; |
| 470 | x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize; |
| 471 | |
| 472 | for (i = 0; i < scp->ysize * scp->font_height; ++i) { |
| 473 | if (scp->xoff > 0) { |
| 474 | draw_pos = scp->sc->adp->va_window + |
| 475 | line_width * (y + i); |
| 476 | draw_end = draw_pos + |
| 477 | scp->xoff * scp->font_width * pixel_size; |
| 478 | |
| 479 | for (p = draw_pos; p < draw_end; p += 4) |
| 480 | writel(p, u32); |
| 481 | } |
| 482 | |
| 483 | if (x > 0) { |
| 484 | draw_pos = scp->sc->adp->va_window + |
| 485 | line_width * (y + i) + |
| 486 | scp->xoff * 8 * pixel_size + |
| 487 | scp->xsize * 8 * pixel_size; |
| 488 | draw_end = draw_pos + x * 8 * pixel_size; |
| 489 | |
| 490 | for (p = draw_pos; p < draw_end; p += 4) |
| 491 | writel(p, u32); |
| 492 | } |
| 493 | } |
| 494 | } |
| 495 | |
| 496 | static void |
| 497 | vga_pxlborder_packed(scr_stat *scp, int color) |
| 498 | { |
| 499 | int i, x, y; |
| 500 | int line_width; |
| 501 | uint32_t u32; |
| 502 | vm_offset_t draw_pos, draw_end, p; |
| 503 | |
| 504 | line_width = scp->sc->adp->va_line_width; |
| 505 | u32 = (color << 24) + (color << 16) + (color << 8) + color; |
| 506 | |
| 507 | if (scp->yoff > 0) { |
| 508 | draw_pos = scp->sc->adp->va_window; |
| 509 | draw_end = draw_pos + line_width * scp->yoff * scp->font_height; |
| 510 | |
| 511 | for (p = draw_pos; p < draw_end; p += 4) |
| 512 | writel(p, u32); |
| 513 | } |
| 514 | |
| 515 | y = (scp->yoff + scp->ysize) * scp->font_height; |
| 516 | |
| 517 | if (scp->ypixel > y) { |
| 518 | draw_pos = scp->sc->adp->va_window + line_width * y; |
| 519 | draw_end = draw_pos + line_width * (scp->ypixel - y); |
| 520 | |
| 521 | for (p = draw_pos; p < draw_end; p += 4) |
| 522 | writel(p, u32); |
| 523 | } |
| 524 | |
| 525 | y = scp->yoff * scp->font_height; |
| 526 | x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize; |
| 527 | |
| 528 | for (i = 0; i < scp->ysize * scp->font_height; ++i) { |
| 529 | if (scp->xoff > 0) { |
| 530 | draw_pos = scp->sc->adp->va_window + |
| 531 | line_width * (y + i); |
| 532 | draw_end = draw_pos + scp->xoff * scp->font_width; |
| 533 | |
| 534 | for (p = draw_pos; p < draw_end; p += 4) |
| 535 | writel(p, u32); |
| 536 | } |
| 537 | |
| 538 | if (x > 0) { |
| 539 | draw_pos = scp->sc->adp->va_window + |
| 540 | line_width * (y + i) + scp->xoff * 8 + |
| 541 | scp->xsize * 8; |
| 542 | draw_end = draw_pos + x * 8; |
| 543 | |
| 544 | for (p = draw_pos; p < draw_end; p += 4) |
| 545 | writel(p, u32); |
| 546 | } |
| 547 | } |
| 548 | } |
| 549 | |
| 550 | static void |
| 551 | vga_pxlborder_planar(scr_stat *scp, int color) |
| 552 | { |
| 553 | vm_offset_t p; |
| 554 | int line_width; |
| 555 | int x; |
| 556 | int y; |
| 557 | int i; |
| 558 | |
| 559 | lwkt_gettoken(&vga_token); |
| 560 | |
| 561 | (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); |
| 562 | |
| 563 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ |
| 564 | outw(GDCIDX, 0x0003); /* data rotate/function select */ |
| 565 | outw(GDCIDX, 0x0f01); /* set/reset enable */ |
| 566 | outw(GDCIDX, 0xff08); /* bit mask */ |
| 567 | outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ |
| 568 | line_width = scp->sc->adp->va_line_width; |
| 569 | p = scp->sc->adp->va_window; |
| 570 | if (scp->yoff > 0) |
| 571 | bzero_io((void *)p, line_width*scp->yoff*scp->font_height); |
| 572 | y = (scp->yoff + scp->ysize)*scp->font_height; |
| 573 | if (scp->ypixel > y) |
| 574 | bzero_io((void *)(p + line_width*y), |
| 575 | line_width*(scp->ypixel - y)); |
| 576 | y = scp->yoff*scp->font_height; |
| 577 | x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize; |
| 578 | for (i = 0; i < scp->ysize*scp->font_height; ++i) { |
| 579 | if (scp->xoff > 0) |
| 580 | bzero_io((void *)(p + line_width*(y + i)), scp->xoff); |
| 581 | if (x > 0) |
| 582 | bzero_io((void *)(p + line_width*(y + i) |
| 583 | + scp->xoff + scp->xsize), x); |
| 584 | } |
| 585 | outw(GDCIDX, 0x0000); /* set/reset */ |
| 586 | outw(GDCIDX, 0x0001); /* set/reset enable */ |
| 587 | lwkt_reltoken(&vga_token); |
| 588 | } |
| 589 | |
| 590 | static void |
| 591 | vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip) |
| 592 | { |
| 593 | int line_width, pixel_size; |
| 594 | int a, i, j, k, l, pos; |
| 595 | uint32_t fg, bg, u32; |
| 596 | unsigned char *char_data; |
| 597 | vm_offset_t draw_pos, p; |
| 598 | |
| 599 | line_width = scp->sc->adp->va_line_width; |
| 600 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; |
| 601 | |
| 602 | draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size); |
| 603 | |
| 604 | if (from + count > scp->xsize * scp->ysize) |
| 605 | count = scp->xsize * scp->ysize - from; |
| 606 | |
| 607 | for (i = from; count-- > 0; ++i) { |
| 608 | a = sc_vtb_geta(&scp->vtb, i); |
| 609 | |
| 610 | if (flip) { |
| 611 | fg = scp->ega_palette[(((a & 0x7000) >> 4) | |
| 612 | (a & 0x0800)) >> 8]; |
| 613 | bg = scp->ega_palette[(((a & 0x8000) >> 4) | |
| 614 | (a & 0x0700)) >> 8]; |
| 615 | } else { |
| 616 | fg = scp->ega_palette[(a & 0x0f00) >> 8]; |
| 617 | bg = scp->ega_palette[(a & 0xf000) >> 12]; |
| 618 | } |
| 619 | |
| 620 | p = draw_pos; |
| 621 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * |
| 622 | scp->font_height]); |
| 623 | |
| 624 | for (j = 0; j < scp->font_height; ++j, ++char_data) { |
| 625 | pos = 7; |
| 626 | |
| 627 | for (k = 0; k < 2 * pixel_size; ++k) { |
| 628 | u32 = 0; |
| 629 | |
| 630 | for (l = 0; l < 4 / pixel_size; ++l) { |
| 631 | u32 += (*char_data & (1 << pos--) ? |
| 632 | fg : bg) << (l * 8 * pixel_size); |
| 633 | } |
| 634 | |
| 635 | writel(p, u32); |
| 636 | p += 4; |
| 637 | } |
| 638 | |
| 639 | p += line_width - 8 * pixel_size; |
| 640 | } |
| 641 | |
| 642 | draw_pos += 8 * pixel_size; |
| 643 | |
| 644 | if ((i % scp->xsize) == scp->xsize - 1) |
| 645 | draw_pos += scp->xoff * 16 * pixel_size + |
| 646 | (scp->font_height - 1) * line_width; |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | static void |
| 651 | vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip) |
| 652 | { |
| 653 | int line_width; |
| 654 | int a, i, j; |
| 655 | uint32_t fg, bg, u32; |
| 656 | unsigned char *char_data; |
| 657 | vm_offset_t draw_pos, p; |
| 658 | |
| 659 | line_width = scp->sc->adp->va_line_width; |
| 660 | |
| 661 | draw_pos = VIDEO_MEMORY_POS(scp, from, 8); |
| 662 | |
| 663 | if (from + count > scp->xsize * scp->ysize) |
| 664 | count = scp->xsize * scp->ysize - from; |
| 665 | |
| 666 | for (i = from; count-- > 0; ++i) { |
| 667 | a = sc_vtb_geta(&scp->vtb, i); |
| 668 | |
| 669 | if (flip) { |
| 670 | fg = ((a & 0xf000) >> 4) >> 8; |
| 671 | bg = (a & 0x0f00) >> 8; |
| 672 | } else { |
| 673 | fg = (a & 0x0f00) >> 8; |
| 674 | bg = ((a & 0xf000) >> 4) >> 8; |
| 675 | } |
| 676 | |
| 677 | p = draw_pos; |
| 678 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * |
| 679 | scp->font_height]); |
| 680 | |
| 681 | for (j = 0; j < scp->font_height; ++j, ++char_data) { |
| 682 | u32 = ((*char_data & 1 ? fg : bg) << 24) + |
| 683 | ((*char_data & 2 ? fg : bg) << 16) + |
| 684 | ((*char_data & 4 ? fg : bg) << 8) + |
| 685 | (*char_data & 8 ? fg : bg); |
| 686 | writel(p + 4, u32); |
| 687 | |
| 688 | u32 = ((*char_data & 16 ? fg : bg) << 24) + |
| 689 | ((*char_data & 32 ? fg : bg) << 16) + |
| 690 | ((*char_data & 64 ? fg : bg) << 8) + |
| 691 | (*char_data & 128 ? fg : bg); |
| 692 | writel(p, u32); |
| 693 | |
| 694 | p += line_width; |
| 695 | } |
| 696 | |
| 697 | draw_pos += scp->font_width; |
| 698 | |
| 699 | if ((i % scp->xsize) == scp->xsize - 1) |
| 700 | draw_pos += scp->xoff * 16 + |
| 701 | (scp->font_height - 1) * line_width; |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | static void |
| 706 | vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip) |
| 707 | { |
| 708 | vm_offset_t d; |
| 709 | vm_offset_t e; |
| 710 | u_char *f; |
| 711 | u_short bg; |
| 712 | u_short col1, col2; |
| 713 | int line_width; |
| 714 | int i, j; |
| 715 | int a; |
| 716 | u_char c; |
| 717 | |
| 718 | d = VIDEO_MEMORY_POS(scp, from, 1); |
| 719 | |
| 720 | line_width = scp->sc->adp->va_line_width; |
| 721 | |
| 722 | outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ |
| 723 | outw(GDCIDX, 0x0003); /* data rotate/function select */ |
| 724 | outw(GDCIDX, 0x0f01); /* set/reset enable */ |
| 725 | outw(GDCIDX, 0xff08); /* bit mask */ |
| 726 | bg = -1; |
| 727 | if (from + count > scp->xsize*scp->ysize) |
| 728 | count = scp->xsize*scp->ysize - from; |
| 729 | for (i = from; count-- > 0; ++i) { |
| 730 | a = sc_vtb_geta(&scp->vtb, i); |
| 731 | if (flip) { |
| 732 | col1 = ((a & 0x7000) >> 4) | (a & 0x0800); |
| 733 | col2 = ((a & 0x8000) >> 4) | (a & 0x0700); |
| 734 | } else { |
| 735 | col1 = (a & 0x0f00); |
| 736 | col2 = (a & 0xf000) >> 4; |
| 737 | } |
| 738 | /* set background color in EGA/VGA latch */ |
| 739 | if (bg != col2) { |
| 740 | bg = col2; |
| 741 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ |
| 742 | outw(GDCIDX, bg | 0x00); /* set/reset */ |
| 743 | writeb(d, 0); |
| 744 | c = readb(d); /* set bg color in the latch */ |
| 745 | outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ |
| 746 | } |
| 747 | /* foreground color */ |
| 748 | outw(GDCIDX, col1 | 0x00); /* set/reset */ |
| 749 | e = d; |
| 750 | f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]); |
| 751 | for (j = 0; j < scp->font_height; ++j, ++f) { |
| 752 | writeb(e, *f); |
| 753 | e += line_width; |
| 754 | } |
| 755 | ++d; |
| 756 | if ((i % scp->xsize) == scp->xsize - 1) |
| 757 | d += scp->xoff*2 |
| 758 | + (scp->font_height - 1)*line_width; |
| 759 | } |
| 760 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ |
| 761 | outw(GDCIDX, 0x0000); /* set/reset */ |
| 762 | outw(GDCIDX, 0x0001); /* set/reset enable */ |
| 763 | } |
| 764 | |
| 765 | static void |
| 766 | vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink) |
| 767 | { |
| 768 | if (base < 0 || base >= scp->font_height) |
| 769 | return; |
| 770 | /* the caller may set height <= 0 in order to disable the cursor */ |
| 771 | #if 0 |
| 772 | scp->cursor_base = base; |
| 773 | scp->cursor_height = height; |
| 774 | #endif |
| 775 | } |
| 776 | |
| 777 | static void |
| 778 | draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip) |
| 779 | { |
| 780 | int line_width, pixel_size, height; |
| 781 | int a, i, j, k, pos; |
| 782 | uint32_t fg, bg, u32; |
| 783 | unsigned char *char_data; |
| 784 | vm_offset_t draw_pos; |
| 785 | |
| 786 | line_width = scp->sc->adp->va_line_width; |
| 787 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; |
| 788 | |
| 789 | draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) + |
| 790 | (scp->font_height - scp->cursor_base - 1) * line_width; |
| 791 | |
| 792 | a = sc_vtb_geta(&scp->vtb, at); |
| 793 | |
| 794 | if (flip) { |
| 795 | fg = scp->ega_palette[((on) ? (a & 0x0f00) : |
| 796 | ((a & 0xf000) >> 4)) >> 8]; |
| 797 | bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : |
| 798 | (a & 0x0f00)) >> 8]; |
| 799 | } else { |
| 800 | fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : |
| 801 | (a & 0x0f00)) >> 8]; |
| 802 | bg = scp->ega_palette[((on) ? (a & 0x0f00) : |
| 803 | ((a & 0xf000) >> 4)) >> 8]; |
| 804 | } |
| 805 | |
| 806 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height + |
| 807 | scp->font_height - scp->cursor_base - 1]); |
| 808 | |
| 809 | height = imin(scp->cursor_height, scp->font_height); |
| 810 | |
| 811 | for (i = 0; i < height; ++i, --char_data) { |
| 812 | pos = 7; |
| 813 | |
| 814 | for (j = 0; j < 2 * pixel_size; ++j) { |
| 815 | u32 = 0; |
| 816 | |
| 817 | for (k = 0; k < 4 / pixel_size; ++k) { |
| 818 | u32 += (*char_data & (1 << pos--) ? |
| 819 | fg : bg) << (k * 8 * pixel_size); |
| 820 | } |
| 821 | |
| 822 | writel(draw_pos, u32); |
| 823 | draw_pos += 4; |
| 824 | } |
| 825 | |
| 826 | draw_pos -= line_width + 8 * pixel_size; |
| 827 | } |
| 828 | } |
| 829 | |
| 830 | static void |
| 831 | draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip) |
| 832 | { |
| 833 | int line_width, height; |
| 834 | int a, i; |
| 835 | uint32_t fg, bg, u32; |
| 836 | unsigned char *char_data; |
| 837 | vm_offset_t draw_pos; |
| 838 | |
| 839 | line_width = scp->sc->adp->va_line_width; |
| 840 | |
| 841 | draw_pos = VIDEO_MEMORY_POS(scp, at, 8) + |
| 842 | (scp->font_height - scp->cursor_base - 1) * line_width; |
| 843 | |
| 844 | a = sc_vtb_geta(&scp->vtb, at); |
| 845 | |
| 846 | if (flip) { |
| 847 | fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; |
| 848 | bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; |
| 849 | } else { |
| 850 | fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; |
| 851 | bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; |
| 852 | } |
| 853 | |
| 854 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height + |
| 855 | scp->font_height - scp->cursor_base - 1]); |
| 856 | |
| 857 | height = imin(scp->cursor_height, scp->font_height); |
| 858 | |
| 859 | for (i = 0; i < height; ++i, --char_data) { |
| 860 | u32 = ((*char_data & 1 ? fg : bg) << 24) + |
| 861 | ((*char_data & 2 ? fg : bg) << 16) + |
| 862 | ((*char_data & 4 ? fg : bg) << 8) + |
| 863 | (*char_data & 8 ? fg : bg); |
| 864 | writel(draw_pos + 4, u32); |
| 865 | |
| 866 | u32 = ((*char_data & 16 ? fg : bg) << 24) + |
| 867 | ((*char_data & 32 ? fg : bg) << 16) + |
| 868 | ((*char_data & 64 ? fg : bg) << 8) + |
| 869 | (*char_data & 128 ? fg : bg); |
| 870 | writel(draw_pos, u32); |
| 871 | |
| 872 | draw_pos -= line_width; |
| 873 | } |
| 874 | } |
| 875 | |
| 876 | static void |
| 877 | draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip) |
| 878 | { |
| 879 | vm_offset_t d; |
| 880 | u_char *f; |
| 881 | int line_width; |
| 882 | int height; |
| 883 | int col; |
| 884 | int a; |
| 885 | int i; |
| 886 | u_char c; |
| 887 | |
| 888 | line_width = scp->sc->adp->va_line_width; |
| 889 | |
| 890 | d = VIDEO_MEMORY_POS(scp, at, 1) + |
| 891 | (scp->font_height - scp->cursor_base - 1) * line_width; |
| 892 | |
| 893 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ |
| 894 | outw(GDCIDX, 0x0003); /* data rotate/function select */ |
| 895 | outw(GDCIDX, 0x0f01); /* set/reset enable */ |
| 896 | /* set background color in EGA/VGA latch */ |
| 897 | a = sc_vtb_geta(&scp->vtb, at); |
| 898 | if (flip) |
| 899 | col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); |
| 900 | else |
| 901 | col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); |
| 902 | outw(GDCIDX, col | 0x00); /* set/reset */ |
| 903 | outw(GDCIDX, 0xff08); /* bit mask */ |
| 904 | writeb(d, 0); |
| 905 | c = readb(d); /* set bg color in the latch */ |
| 906 | /* foreground color */ |
| 907 | if (flip) |
| 908 | col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); |
| 909 | else |
| 910 | col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); |
| 911 | outw(GDCIDX, col | 0x00); /* set/reset */ |
| 912 | f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height |
| 913 | + scp->font_height - scp->cursor_base - 1]); |
| 914 | height = imin(scp->cursor_height, scp->font_height); |
| 915 | for (i = 0; i < height; ++i, --f) { |
| 916 | outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ |
| 917 | writeb(d, 0); |
| 918 | d -= line_width; |
| 919 | } |
| 920 | outw(GDCIDX, 0x0000); /* set/reset */ |
| 921 | outw(GDCIDX, 0x0001); /* set/reset enable */ |
| 922 | outw(GDCIDX, 0xff08); /* bit mask */ |
| 923 | } |
| 924 | |
| 925 | static int pxlblinkrate = 0; |
| 926 | |
| 927 | static void |
| 928 | vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip) |
| 929 | { |
| 930 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ |
| 931 | return; |
| 932 | |
| 933 | if (on) { |
| 934 | if (!blink) { |
| 935 | scp->status |= VR_CURSOR_ON; |
| 936 | draw_pxlcursor_direct(scp, at, on, flip); |
| 937 | } else if (++pxlblinkrate & 4) { |
| 938 | pxlblinkrate = 0; |
| 939 | scp->status ^= VR_CURSOR_ON; |
| 940 | draw_pxlcursor_direct(scp, at, |
| 941 | scp->status & VR_CURSOR_ON, |
| 942 | flip); |
| 943 | } |
| 944 | } else { |
| 945 | if (scp->status & VR_CURSOR_ON) |
| 946 | draw_pxlcursor_direct(scp, at, on, flip); |
| 947 | scp->status &= ~VR_CURSOR_ON; |
| 948 | } |
| 949 | if (blink) |
| 950 | scp->status |= VR_CURSOR_BLINK; |
| 951 | else |
| 952 | scp->status &= ~VR_CURSOR_BLINK; |
| 953 | } |
| 954 | |
| 955 | static void |
| 956 | vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip) |
| 957 | { |
| 958 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ |
| 959 | return; |
| 960 | |
| 961 | if (on) { |
| 962 | if (!blink) { |
| 963 | scp->status |= VR_CURSOR_ON; |
| 964 | draw_pxlcursor_packed(scp, at, on, flip); |
| 965 | } else if (++pxlblinkrate & 4) { |
| 966 | pxlblinkrate = 0; |
| 967 | scp->status ^= VR_CURSOR_ON; |
| 968 | draw_pxlcursor_packed(scp, at, |
| 969 | scp->status & VR_CURSOR_ON, |
| 970 | flip); |
| 971 | } |
| 972 | } else { |
| 973 | if (scp->status & VR_CURSOR_ON) |
| 974 | draw_pxlcursor_packed(scp, at, on, flip); |
| 975 | scp->status &= ~VR_CURSOR_ON; |
| 976 | } |
| 977 | if (blink) |
| 978 | scp->status |= VR_CURSOR_BLINK; |
| 979 | else |
| 980 | scp->status &= ~VR_CURSOR_BLINK; |
| 981 | } |
| 982 | |
| 983 | static void |
| 984 | vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip) |
| 985 | { |
| 986 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ |
| 987 | return; |
| 988 | |
| 989 | if (on) { |
| 990 | if (!blink) { |
| 991 | scp->status |= VR_CURSOR_ON; |
| 992 | draw_pxlcursor_planar(scp, at, on, flip); |
| 993 | } else if (++pxlblinkrate & 4) { |
| 994 | pxlblinkrate = 0; |
| 995 | scp->status ^= VR_CURSOR_ON; |
| 996 | draw_pxlcursor_planar(scp, at, |
| 997 | scp->status & VR_CURSOR_ON, |
| 998 | flip); |
| 999 | } |
| 1000 | } else { |
| 1001 | if (scp->status & VR_CURSOR_ON) |
| 1002 | draw_pxlcursor_planar(scp, at, on, flip); |
| 1003 | scp->status &= ~VR_CURSOR_ON; |
| 1004 | } |
| 1005 | if (blink) |
| 1006 | scp->status |= VR_CURSOR_BLINK; |
| 1007 | else |
| 1008 | scp->status &= ~VR_CURSOR_BLINK; |
| 1009 | } |
| 1010 | |
| 1011 | static void |
| 1012 | vga_pxlblink_direct(scr_stat *scp, int at, int flip) |
| 1013 | { |
| 1014 | if (!(scp->status & VR_CURSOR_BLINK)) |
| 1015 | return; |
| 1016 | if (!(++pxlblinkrate & 4)) |
| 1017 | return; |
| 1018 | pxlblinkrate = 0; |
| 1019 | scp->status ^= VR_CURSOR_ON; |
| 1020 | draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip); |
| 1021 | } |
| 1022 | |
| 1023 | static void |
| 1024 | vga_pxlblink_packed(scr_stat *scp, int at, int flip) |
| 1025 | { |
| 1026 | if (!(scp->status & VR_CURSOR_BLINK)) |
| 1027 | return; |
| 1028 | if (!(++pxlblinkrate & 4)) |
| 1029 | return; |
| 1030 | pxlblinkrate = 0; |
| 1031 | scp->status ^= VR_CURSOR_ON; |
| 1032 | draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip); |
| 1033 | } |
| 1034 | |
| 1035 | static void |
| 1036 | vga_pxlblink_planar(scr_stat *scp, int at, int flip) |
| 1037 | { |
| 1038 | if (!(scp->status & VR_CURSOR_BLINK)) |
| 1039 | return; |
| 1040 | if (!(++pxlblinkrate & 4)) |
| 1041 | return; |
| 1042 | pxlblinkrate = 0; |
| 1043 | scp->status ^= VR_CURSOR_ON; |
| 1044 | draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip); |
| 1045 | } |
| 1046 | |
| 1047 | #ifndef SC_NO_CUTPASTE |
| 1048 | |
| 1049 | static void |
| 1050 | draw_pxlmouse_direct(scr_stat *scp, int x, int y) |
| 1051 | { |
| 1052 | int line_width, pixel_size; |
| 1053 | int xend, yend; |
| 1054 | int i, j; |
| 1055 | vm_offset_t draw_pos; |
| 1056 | |
| 1057 | line_width = scp->sc->adp->va_line_width; |
| 1058 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; |
| 1059 | |
| 1060 | xend = imin(x + 8, 8 * (scp->xoff + scp->xsize)); |
| 1061 | yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize)); |
| 1062 | |
| 1063 | draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size; |
| 1064 | |
| 1065 | for (i = 0; i < (yend - y); i++) { |
| 1066 | for (j = (xend - x - 1); j >= 0; j--) { |
| 1067 | switch (scp->sc->adp->va_info.vi_depth) { |
| 1068 | case 32: |
| 1069 | if (mouse_or_mask[i] & 1 << (15 - j)) |
| 1070 | writel(draw_pos + 4 * j, |
| 1071 | scp->ega_palette[15]); |
| 1072 | else if (mouse_and_mask[i] & 1 << (15 - j)) |
| 1073 | writel(draw_pos + 4 * j, |
| 1074 | scp->ega_palette[0]); |
| 1075 | break; |
| 1076 | case 16: |
| 1077 | /* FALLTHROUGH */ |
| 1078 | case 15: |
| 1079 | if (mouse_or_mask[i] & 1 << (15 - j)) |
| 1080 | writew(draw_pos + 2 * j, |
| 1081 | scp->ega_palette[15]); |
| 1082 | else if (mouse_and_mask[i] & 1 << (15 - j)) |
| 1083 | writew(draw_pos + 2 * j, |
| 1084 | scp->ega_palette[0]); |
| 1085 | break; |
| 1086 | } |
| 1087 | } |
| 1088 | |
| 1089 | draw_pos += line_width; |
| 1090 | } |
| 1091 | } |
| 1092 | |
| 1093 | static void |
| 1094 | draw_pxlmouse_packed(scr_stat *scp, int x, int y) |
| 1095 | { |
| 1096 | int line_width; |
| 1097 | int xend, yend; |
| 1098 | int i, j; |
| 1099 | vm_offset_t draw_pos; |
| 1100 | |
| 1101 | line_width = scp->sc->adp->va_line_width; |
| 1102 | |
| 1103 | xend = imin(scp->font_width * (scp->xoff + scp->xsize), |
| 1104 | imin(x + 16, scp->xpixel)); |
| 1105 | yend = imin(scp->font_height * (scp->yoff + scp->ysize), |
| 1106 | imin(y + 16, scp->ypixel)); |
| 1107 | |
| 1108 | draw_pos = scp->sc->adp->va_window + y * line_width + x; |
| 1109 | |
| 1110 | for (i = 0; i < (yend - y); i++) { |
| 1111 | for (j = (xend - x - 1); j >= 0; j--) { |
| 1112 | if (mouse_or_mask[i] & 1 << (15 - j)) |
| 1113 | writeb(draw_pos + j, 15); |
| 1114 | else if (mouse_and_mask[i] & 1 << (15 - j)) |
| 1115 | writeb(draw_pos + j, 0); |
| 1116 | } |
| 1117 | |
| 1118 | draw_pos += line_width; |
| 1119 | } |
| 1120 | } |
| 1121 | |
| 1122 | static void |
| 1123 | draw_pxlmouse_planar(scr_stat *scp, int x, int y) |
| 1124 | { |
| 1125 | vm_offset_t p; |
| 1126 | int line_width; |
| 1127 | int xoff; |
| 1128 | int ymax; |
| 1129 | u_short m; |
| 1130 | int i, j; |
| 1131 | |
| 1132 | line_width = scp->sc->adp->va_line_width; |
| 1133 | xoff = (x - scp->xoff*8)%8; |
| 1134 | ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize)); |
| 1135 | |
| 1136 | outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */ |
| 1137 | outw(GDCIDX, 0x0001); /* set/reset enable */ |
| 1138 | outw(GDCIDX, 0x0002); /* color compare */ |
| 1139 | outw(GDCIDX, 0x0007); /* color don't care */ |
| 1140 | outw(GDCIDX, 0xff08); /* bit mask */ |
| 1141 | outw(GDCIDX, 0x0803); /* data rotate/function select (and) */ |
| 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_and_mask[j] >> xoff); |
| 1146 | *(u_char *)p &= m >> 8; |
| 1147 | *(u_char *)(p + 1) &= m; |
| 1148 | p += line_width; |
| 1149 | } |
| 1150 | } else { |
| 1151 | xoff += 8; |
| 1152 | for (i = y, j = 0; i < ymax; ++i, ++j) { |
| 1153 | m = ~(mouse_and_mask[j] >> xoff); |
| 1154 | *(u_char *)p &= m; |
| 1155 | p += line_width; |
| 1156 | } |
| 1157 | } |
| 1158 | outw(GDCIDX, 0x1003); /* data rotate/function select (or) */ |
| 1159 | p = scp->sc->adp->va_window + line_width*y + x/8; |
| 1160 | if (x < 8 * (scp->xoff + scp->xsize) - 8) { |
| 1161 | for (i = y, j = 0; i < ymax; ++i, ++j) { |
| 1162 | m = mouse_or_mask[j] >> xoff; |
| 1163 | *(u_char *)p &= m >> 8; |
| 1164 | *(u_char *)(p + 1) &= m; |
| 1165 | p += line_width; |
| 1166 | } |
| 1167 | } else { |
| 1168 | for (i = y, j = 0; i < ymax; ++i, ++j) { |
| 1169 | m = mouse_or_mask[j] >> xoff; |
| 1170 | *(u_char *)p &= m; |
| 1171 | p += line_width; |
| 1172 | } |
| 1173 | } |
| 1174 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ |
| 1175 | outw(GDCIDX, 0x0003); /* data rotate/function select */ |
| 1176 | } |
| 1177 | |
| 1178 | static void |
| 1179 | remove_pxlmouse(scr_stat *scp, int x, int y) |
| 1180 | { |
| 1181 | int col, row; |
| 1182 | int pos; |
| 1183 | int i; |
| 1184 | |
| 1185 | /* erase the mouse cursor image */ |
| 1186 | col = x / scp->font_width - scp->xoff; |
| 1187 | row = y / scp->font_height - scp->yoff; |
| 1188 | pos = row * scp->xsize + col; |
| 1189 | i = (col < scp->xsize - 1) ? 2 : 1; |
| 1190 | (*scp->rndr->draw)(scp, pos, i, FALSE); |
| 1191 | if (row < scp->ysize - 1) |
| 1192 | (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); |
| 1193 | } |
| 1194 | |
| 1195 | static void |
| 1196 | vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) |
| 1197 | { |
| 1198 | if (on) |
| 1199 | draw_pxlmouse_direct(scp, x, y); |
| 1200 | else |
| 1201 | remove_pxlmouse(scp, x, y); |
| 1202 | } |
| 1203 | |
| 1204 | static void |
| 1205 | vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on) |
| 1206 | { |
| 1207 | if (on) |
| 1208 | draw_pxlmouse_packed(scp, x, y); |
| 1209 | else |
| 1210 | remove_pxlmouse(scp, x, y); |
| 1211 | } |
| 1212 | |
| 1213 | static void |
| 1214 | vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on) |
| 1215 | { |
| 1216 | if (on) |
| 1217 | draw_pxlmouse_planar(scp, x, y); |
| 1218 | else |
| 1219 | remove_pxlmouse(scp, x, y); |
| 1220 | } |
| 1221 | |
| 1222 | #endif /* SC_NO_CUTPASTE */ |
| 1223 | #endif /* SC_PIXEL_MODE */ |
| 1224 | |
| 1225 | #ifndef SC_NO_MODE_CHANGE |
| 1226 | |
| 1227 | /* graphics mode renderer */ |
| 1228 | |
| 1229 | static void |
| 1230 | vga_grborder(scr_stat *scp, int color) |
| 1231 | { |
| 1232 | lwkt_gettoken(&vga_token); |
| 1233 | (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); |
| 1234 | lwkt_reltoken(&vga_token); |
| 1235 | } |
| 1236 | |
| 1237 | #endif |