1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991-1997 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <signal.h> 35 #include <sys/fbio.h> 36 #include <sys/kbio.h> 37 #include <sys/endian.h> 38 #include "vgl.h" 39 40 static int VGLBlank; 41 static byte VGLBorderColor; 42 static byte VGLSavePaletteRed[256]; 43 static byte VGLSavePaletteGreen[256]; 44 static byte VGLSavePaletteBlue[256]; 45 46 #define ABS(a) (((a)<0) ? -(a) : (a)) 47 #define SGN(a) (((a)<0) ? -1 : 1) 48 #define min(x, y) (((x) < (y)) ? (x) : (y)) 49 #define max(x, y) (((x) > (y)) ? (x) : (y)) 50 51 void 52 VGLSetXY(VGLBitmap *object, int x, int y, u_long color) 53 { 54 int offset, undermouse; 55 56 VGLCheckSwitch(); 57 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) { 58 if (object == VGLDisplay) { 59 undermouse = VGLMouseFreezeXY(x, y); 60 VGLSetXY(&VGLVDisplay, x, y, color); 61 } else if (object->Type != MEMBUF) 62 return; /* invalid */ 63 else 64 undermouse = 0; 65 if (!undermouse) { 66 offset = (y * object->VXsize + x) * object->PixelBytes; 67 switch (object->Type) { 68 case VIDBUF8S: 69 case VIDBUF16S: 70 case VIDBUF24S: 71 case VIDBUF32S: 72 offset = VGLSetSegment(offset); 73 /* FALLTHROUGH */ 74 case MEMBUF: 75 case VIDBUF8: 76 case VIDBUF16: 77 case VIDBUF24: 78 case VIDBUF32: 79 color = htole32(color); 80 switch (object->PixelBytes) { 81 case 1: 82 memcpy(&object->Bitmap[offset], &color, 1); 83 break; 84 case 2: 85 memcpy(&object->Bitmap[offset], &color, 2); 86 break; 87 case 3: 88 memcpy(&object->Bitmap[offset], &color, 3); 89 break; 90 case 4: 91 memcpy(&object->Bitmap[offset], &color, 4); 92 break; 93 } 94 break; 95 case VIDBUF8X: 96 outb(0x3c4, 0x02); 97 outb(0x3c5, 0x01 << (x&0x3)); 98 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color); 99 break; 100 case VIDBUF4S: 101 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 102 goto set_planar; 103 case VIDBUF4: 104 offset = y*VGLAdpInfo.va_line_width + x/8; 105 set_planar: 106 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 107 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */ 108 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */ 109 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */ 110 object->Bitmap[offset] |= (byte)color; 111 } 112 } 113 if (object == VGLDisplay) 114 VGLMouseUnFreeze(); 115 } 116 } 117 118 static u_long 119 __VGLGetXY(VGLBitmap *object, int x, int y) 120 { 121 int offset; 122 u_long color; 123 124 offset = (y * object->VXsize + x) * object->PixelBytes; 125 switch (object->PixelBytes) { 126 case 1: 127 memcpy(&color, &object->Bitmap[offset], 1); 128 return le32toh(color) & 0xff; 129 case 2: 130 memcpy(&color, &object->Bitmap[offset], 2); 131 return le32toh(color) & 0xffff; 132 case 3: 133 memcpy(&color, &object->Bitmap[offset], 3); 134 return le32toh(color) & 0xffffff; 135 case 4: 136 memcpy(&color, &object->Bitmap[offset], 4); 137 return le32toh(color); 138 } 139 return 0; /* invalid */ 140 } 141 142 u_long 143 VGLGetXY(VGLBitmap *object, int x, int y) 144 { 145 VGLCheckSwitch(); 146 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize) 147 return 0; 148 if (object == VGLDisplay) 149 object = &VGLVDisplay; 150 else if (object->Type != MEMBUF) 151 return 0; /* invalid */ 152 return __VGLGetXY(object, x, y); 153 } 154 155 /* 156 * Symmetric Double Step Line Algorithm by Brian Wyvill from 157 * "Graphics Gems", Academic Press, 1990. 158 */ 159 160 #define SL_SWAP(a,b) {a^=b; b^=a; a^=b;} 161 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1))) 162 163 void 164 plot(VGLBitmap * object, int x, int y, int flag, u_long color) 165 { 166 /* non-zero flag indicates the pixels need swapping back. */ 167 if (flag) 168 VGLSetXY(object, y, x, color); 169 else 170 VGLSetXY(object, x, y, color); 171 } 172 173 174 void 175 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 176 { 177 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; 178 int sign_x, sign_y, step, reverse, i; 179 180 dx = SL_ABSOLUTE(x2, x1, sign_x); 181 dy = SL_ABSOLUTE(y2, y1, sign_y); 182 /* decide increment sign by the slope sign */ 183 if (sign_x == sign_y) 184 step = 1; 185 else 186 step = -1; 187 188 if (dy > dx) { /* chooses axis of greatest movement (make dx) */ 189 SL_SWAP(x1, y1); 190 SL_SWAP(x2, y2); 191 SL_SWAP(dx, dy); 192 reverse = 1; 193 } else 194 reverse = 0; 195 /* note error check for dx==0 should be included here */ 196 if (x1 > x2) { /* start from the smaller coordinate */ 197 x = x2; 198 y = y2; 199 /* x1 = x1; 200 y1 = y1; */ 201 } else { 202 x = x1; 203 y = y1; 204 x1 = x2; 205 y1 = y2; 206 } 207 208 209 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ 210 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ 211 /* In fact (dx-1)/4 as 2 pixels are already plotted */ 212 xend = (dx - 1) / 4; 213 pixels_left = (dx - 1) % 4; /* number of pixels left over at the 214 * end */ 215 plot(object, x, y, reverse, color); 216 if (pixels_left < 0) 217 return; /* plot only one pixel for zero length 218 * vectors */ 219 plot(object, x1, y1, reverse, color); /* plot first two points */ 220 incr2 = 4 * dy - 2 * dx; 221 if (incr2 < 0) { /* slope less than 1/2 */ 222 c = 2 * dy; 223 incr1 = 2 * c; 224 D = incr1 - dx; 225 226 for (i = 0; i < xend; i++) { /* plotting loop */ 227 ++x; 228 --x1; 229 if (D < 0) { 230 /* pattern 1 forwards */ 231 plot(object, x, y, reverse, color); 232 plot(object, ++x, y, reverse, color); 233 /* pattern 1 backwards */ 234 plot(object, x1, y1, reverse, color); 235 plot(object, --x1, y1, reverse, color); 236 D += incr1; 237 } else { 238 if (D < c) { 239 /* pattern 2 forwards */ 240 plot(object, x, y, reverse, color); 241 plot(object, ++x, y += step, reverse, 242 color); 243 /* pattern 2 backwards */ 244 plot(object, x1, y1, reverse, color); 245 plot(object, --x1, y1 -= step, reverse, 246 color); 247 } else { 248 /* pattern 3 forwards */ 249 plot(object, x, y += step, reverse, color); 250 plot(object, ++x, y, reverse, color); 251 /* pattern 3 backwards */ 252 plot(object, x1, y1 -= step, reverse, 253 color); 254 plot(object, --x1, y1, reverse, color); 255 } 256 D += incr2; 257 } 258 } /* end for */ 259 260 /* plot last pattern */ 261 if (pixels_left) { 262 if (D < 0) { 263 plot(object, ++x, y, reverse, color); /* pattern 1 */ 264 if (pixels_left > 1) 265 plot(object, ++x, y, reverse, color); 266 if (pixels_left > 2) 267 plot(object, --x1, y1, reverse, color); 268 } else { 269 if (D < c) { 270 plot(object, ++x, y, reverse, color); /* pattern 2 */ 271 if (pixels_left > 1) 272 plot(object, ++x, y += step, reverse, color); 273 if (pixels_left > 2) 274 plot(object, --x1, y1, reverse, color); 275 } else { 276 /* pattern 3 */ 277 plot(object, ++x, y += step, reverse, color); 278 if (pixels_left > 1) 279 plot(object, ++x, y, reverse, color); 280 if (pixels_left > 2) 281 plot(object, --x1, y1 -= step, reverse, color); 282 } 283 } 284 } /* end if pixels_left */ 285 } 286 /* end slope < 1/2 */ 287 else { /* slope greater than 1/2 */ 288 c = 2 * (dy - dx); 289 incr1 = 2 * c; 290 D = incr1 + dx; 291 for (i = 0; i < xend; i++) { 292 ++x; 293 --x1; 294 if (D > 0) { 295 /* pattern 4 forwards */ 296 plot(object, x, y += step, reverse, color); 297 plot(object, ++x, y += step, reverse, color); 298 /* pattern 4 backwards */ 299 plot(object, x1, y1 -= step, reverse, color); 300 plot(object, --x1, y1 -= step, reverse, color); 301 D += incr1; 302 } else { 303 if (D < c) { 304 /* pattern 2 forwards */ 305 plot(object, x, y, reverse, color); 306 plot(object, ++x, y += step, reverse, 307 color); 308 309 /* pattern 2 backwards */ 310 plot(object, x1, y1, reverse, color); 311 plot(object, --x1, y1 -= step, reverse, 312 color); 313 } else { 314 /* pattern 3 forwards */ 315 plot(object, x, y += step, reverse, color); 316 plot(object, ++x, y, reverse, color); 317 /* pattern 3 backwards */ 318 plot(object, x1, y1 -= step, reverse, color); 319 plot(object, --x1, y1, reverse, color); 320 } 321 D += incr2; 322 } 323 } /* end for */ 324 /* plot last pattern */ 325 if (pixels_left) { 326 if (D > 0) { 327 plot(object, ++x, y += step, reverse, color); /* pattern 4 */ 328 if (pixels_left > 1) 329 plot(object, ++x, y += step, reverse, 330 color); 331 if (pixels_left > 2) 332 plot(object, --x1, y1 -= step, reverse, 333 color); 334 } else { 335 if (D < c) { 336 plot(object, ++x, y, reverse, color); /* pattern 2 */ 337 if (pixels_left > 1) 338 plot(object, ++x, y += step, reverse, color); 339 if (pixels_left > 2) 340 plot(object, --x1, y1, reverse, color); 341 } else { 342 /* pattern 3 */ 343 plot(object, ++x, y += step, reverse, color); 344 if (pixels_left > 1) 345 plot(object, ++x, y, reverse, color); 346 if (pixels_left > 2) { 347 if (D > c) /* step 3 */ 348 plot(object, --x1, y1 -= step, reverse, color); 349 else /* step 2 */ 350 plot(object, --x1, y1, reverse, color); 351 } 352 } 353 } 354 } 355 } 356 } 357 358 void 359 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 360 { 361 VGLLine(object, x1, y1, x2, y1, color); 362 VGLLine(object, x2, y1, x2, y2, color); 363 VGLLine(object, x2, y2, x1, y2, color); 364 VGLLine(object, x1, y2, x1, y1, color); 365 } 366 367 void 368 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 369 { 370 int y; 371 372 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color); 373 } 374 375 static inline void 376 set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 377 { 378 if (x!=0) { 379 VGLSetXY(object, xc+x, yc+y, color); 380 VGLSetXY(object, xc-x, yc+y, color); 381 if (y!=0) { 382 VGLSetXY(object, xc+x, yc-y, color); 383 VGLSetXY(object, xc-x, yc-y, color); 384 } 385 } 386 else { 387 VGLSetXY(object, xc, yc+y, color); 388 if (y!=0) 389 VGLSetXY(object, xc, yc-y, color); 390 } 391 } 392 393 void 394 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 395 { 396 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 397 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 398 399 while (dx<dy) { 400 set4pixels(object, x, y, xc, yc, color); 401 if (d>0) { 402 y--; dy-=asq2; d-=dy; 403 } 404 x++; dx+=bsq2; d+=bsq+dx; 405 } 406 d+=(3*(asq-bsq)/2-(dx+dy))/2; 407 while (y>=0) { 408 set4pixels(object, x, y, xc, yc, color); 409 if (d<0) { 410 x++; dx+=bsq2; d+=dx; 411 } 412 y--; dy-=asq2; d+=asq-dy; 413 } 414 } 415 416 static inline void 417 set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 418 { 419 if (x!=0) { 420 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color); 421 if (y!=0) 422 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color); 423 } 424 else { 425 VGLLine(object, xc, yc+y, xc, yc-y, color); 426 } 427 } 428 429 void 430 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 431 { 432 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 433 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 434 435 while (dx<dy) { 436 set2lines(object, x, y, xc, yc, color); 437 if (d>0) { 438 y--; dy-=asq2; d-=dy; 439 } 440 x++; dx+=bsq2; d+=bsq+dx; 441 } 442 d+=(3*(asq-bsq)/2-(dx+dy))/2; 443 while (y>=0) { 444 set2lines(object, x, y, xc, yc, color); 445 if (d<0) { 446 x++; dx+=bsq2; d+=dx; 447 } 448 y--; dy-=asq2; d+=asq-dy; 449 } 450 } 451 452 void 453 VGLClear(VGLBitmap *object, u_long color) 454 { 455 VGLBitmap src; 456 int i, len, mouseoverlap, offset; 457 458 VGLCheckSwitch(); 459 if (object == VGLDisplay) { 460 VGLMouseFreeze(); 461 mouseoverlap = VGLMouseOverlap(0, 0, object->Xsize, object->Ysize); 462 if (mouseoverlap) 463 VGLMousePointerHide(); 464 VGLClear(&VGLVDisplay, color); 465 } else if (object->Type != MEMBUF) 466 return; /* invalid */ 467 switch (object->Type) { 468 case MEMBUF: 469 case VIDBUF8: 470 case VIDBUF8S: 471 case VIDBUF16: 472 case VIDBUF16S: 473 case VIDBUF24: 474 case VIDBUF24S: 475 case VIDBUF32: 476 case VIDBUF32S: 477 src.Type = MEMBUF; 478 src.Xsize = object->Xsize; 479 src.VXsize = object->VXsize; 480 src.Ysize = 1; 481 src.VYsize = 1; 482 src.Xorigin = 0; 483 src.Yorigin = 0; 484 src.Bitmap = alloca(object->VXsize * object->PixelBytes); 485 src.PixelBytes = object->PixelBytes; 486 color = htole32(color); 487 for (i = 0; i < object->VXsize; i++) 488 bcopy(&color, src.Bitmap + i * object->PixelBytes, object->PixelBytes); 489 for (i = 0; i < object->VYsize; i++) 490 __VGLBitmapCopy(&src, 0, 0, object, 0, i, object->VXsize, 1); 491 break; 492 493 case VIDBUF8X: 494 /* XXX works only for Xsize % 4 = 0 */ 495 outb(0x3c6, 0xff); 496 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 497 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize); 498 break; 499 500 case VIDBUF4: 501 case VIDBUF4S: 502 /* XXX works only for Xsize % 8 = 0 */ 503 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 504 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */ 505 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 506 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 507 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) { 508 VGLSetSegment(offset); 509 len = min(object->VXsize*object->VYsize - offset, 510 VGLAdpInfo.va_window_size); 511 memset(object->Bitmap, (byte)color, len); 512 offset += len; 513 } 514 outb(0x3ce, 0x05); outb(0x3cf, 0x00); 515 break; 516 } 517 if (object == VGLDisplay) { 518 if (mouseoverlap) 519 VGLMousePointerShow(); 520 VGLMouseUnFreeze(); 521 } 522 } 523 524 static inline u_long 525 VGLrgbToNative(uint16_t r, uint16_t g, uint16_t b) 526 { 527 int nr, ng, nb; 528 529 nr = VGLModeInfo.vi_pixel_fsizes[2]; 530 ng = VGLModeInfo.vi_pixel_fsizes[1]; 531 nb = VGLModeInfo.vi_pixel_fsizes[0]; 532 return (r >> (16 - nr) << (ng + nb)) | (g >> (16 - ng) << nb) | 533 (b >> (16 - nb) << 0); 534 } 535 536 u_long 537 VGLrgb332ToNative(byte c) 538 { 539 uint16_t r, g, b; 540 541 /* 3:3:2 to 16:16:16 */ 542 r = ((c & 0xe0) >> 5) * 0xffff / 7; 543 g = ((c & 0x1c) >> 2) * 0xffff / 7; 544 b = ((c & 0x03) >> 0) * 0xffff / 3; 545 546 return VGLrgbToNative(r, g, b); 547 } 548 549 void 550 VGLRestorePalette() 551 { 552 int i; 553 554 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 555 return; 556 outb(0x3C6, 0xFF); 557 inb(0x3DA); 558 outb(0x3C8, 0x00); 559 for (i=0; i<256; i++) { 560 outb(0x3C9, VGLSavePaletteRed[i]); 561 inb(0x84); 562 outb(0x3C9, VGLSavePaletteGreen[i]); 563 inb(0x84); 564 outb(0x3C9, VGLSavePaletteBlue[i]); 565 inb(0x84); 566 } 567 inb(0x3DA); 568 outb(0x3C0, 0x20); 569 } 570 571 void 572 VGLSavePalette() 573 { 574 int i; 575 576 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 577 return; 578 outb(0x3C6, 0xFF); 579 inb(0x3DA); 580 outb(0x3C7, 0x00); 581 for (i=0; i<256; i++) { 582 VGLSavePaletteRed[i] = inb(0x3C9); 583 inb(0x84); 584 VGLSavePaletteGreen[i] = inb(0x3C9); 585 inb(0x84); 586 VGLSavePaletteBlue[i] = inb(0x3C9); 587 inb(0x84); 588 } 589 inb(0x3DA); 590 outb(0x3C0, 0x20); 591 } 592 593 void 594 VGLSetPalette(byte *red, byte *green, byte *blue) 595 { 596 int i; 597 598 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 599 return; 600 for (i=0; i<256; i++) { 601 VGLSavePaletteRed[i] = red[i]; 602 VGLSavePaletteGreen[i] = green[i]; 603 VGLSavePaletteBlue[i] = blue[i]; 604 } 605 VGLCheckSwitch(); 606 outb(0x3C6, 0xFF); 607 inb(0x3DA); 608 outb(0x3C8, 0x00); 609 for (i=0; i<256; i++) { 610 outb(0x3C9, VGLSavePaletteRed[i]); 611 inb(0x84); 612 outb(0x3C9, VGLSavePaletteGreen[i]); 613 inb(0x84); 614 outb(0x3C9, VGLSavePaletteBlue[i]); 615 inb(0x84); 616 } 617 inb(0x3DA); 618 outb(0x3C0, 0x20); 619 } 620 621 void 622 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue) 623 { 624 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 625 return; 626 VGLSavePaletteRed[color] = red; 627 VGLSavePaletteGreen[color] = green; 628 VGLSavePaletteBlue[color] = blue; 629 VGLCheckSwitch(); 630 outb(0x3C6, 0xFF); 631 inb(0x3DA); 632 outb(0x3C8, color); 633 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue); 634 inb(0x3DA); 635 outb(0x3C0, 0x20); 636 } 637 638 void 639 VGLRestoreBorder(void) 640 { 641 VGLSetBorder(VGLBorderColor); 642 } 643 644 void 645 VGLSetBorder(byte color) 646 { 647 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) 648 return; 649 VGLCheckSwitch(); 650 inb(0x3DA); 651 outb(0x3C0,0x11); outb(0x3C0, color); 652 inb(0x3DA); 653 outb(0x3C0, 0x20); 654 VGLBorderColor = color; 655 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 656 ioctl(0, KDDISABIO, 0); 657 } 658 659 void 660 VGLRestoreBlank(void) 661 { 662 VGLBlankDisplay(VGLBlank); 663 } 664 665 void 666 VGLBlankDisplay(int blank) 667 { 668 byte val; 669 670 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) 671 return; 672 VGLCheckSwitch(); 673 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01); 674 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF))); 675 VGLBlank = blank; 676 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 677 ioctl(0, KDDISABIO, 0); 678 } 679