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 byte VGLSavePaletteRed[256]; 41 static byte VGLSavePaletteGreen[256]; 42 static byte VGLSavePaletteBlue[256]; 43 44 #define ABS(a) (((a)<0) ? -(a) : (a)) 45 #define SGN(a) (((a)<0) ? -1 : 1) 46 #define min(x, y) (((x) < (y)) ? (x) : (y)) 47 #define max(x, y) (((x) > (y)) ? (x) : (y)) 48 49 void 50 VGLSetXY(VGLBitmap *object, int x, int y, u_long color) 51 { 52 int offset; 53 54 VGLCheckSwitch(); 55 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) { 56 if (object->Type == MEMBUF || 57 !VGLMouseFreeze(x, y, 1, 1, 0x80000000 | color)) { 58 offset = (y * object->VXsize + x) * object->PixelBytes; 59 switch (object->Type) { 60 case VIDBUF8S: 61 case VIDBUF16S: 62 case VIDBUF24S: 63 case VIDBUF32S: 64 offset = VGLSetSegment(offset); 65 /* FALLTHROUGH */ 66 case MEMBUF: 67 case VIDBUF8: 68 case VIDBUF16: 69 case VIDBUF24: 70 case VIDBUF32: 71 color = htole32(color); 72 switch (object->PixelBytes) { 73 case 1: 74 memcpy(&object->Bitmap[offset], &color, 1); 75 break; 76 case 2: 77 memcpy(&object->Bitmap[offset], &color, 2); 78 break; 79 case 3: 80 memcpy(&object->Bitmap[offset], &color, 3); 81 break; 82 case 4: 83 memcpy(&object->Bitmap[offset], &color, 4); 84 break; 85 } 86 break; 87 case VIDBUF8X: 88 outb(0x3c4, 0x02); 89 outb(0x3c5, 0x01 << (x&0x3)); 90 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color); 91 break; 92 case VIDBUF4S: 93 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 94 goto set_planar; 95 case VIDBUF4: 96 offset = y*VGLAdpInfo.va_line_width + x/8; 97 set_planar: 98 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 99 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */ 100 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */ 101 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */ 102 object->Bitmap[offset] |= (byte)color; 103 } 104 } 105 if (object->Type != MEMBUF) 106 VGLMouseUnFreeze(); 107 } 108 } 109 110 static u_long 111 __VGLGetXY(VGLBitmap *object, int x, int y) 112 { 113 int offset; 114 int i; 115 u_long color; 116 byte mask; 117 118 offset = (y * object->VXsize + x) * object->PixelBytes; 119 switch (object->Type) { 120 case VIDBUF8S: 121 case VIDBUF16S: 122 case VIDBUF24S: 123 case VIDBUF32S: 124 offset = VGLSetSegment(offset); 125 /* FALLTHROUGH */ 126 case MEMBUF: 127 case VIDBUF8: 128 case VIDBUF16: 129 case VIDBUF24: 130 case VIDBUF32: 131 switch (object->PixelBytes) { 132 case 1: 133 memcpy(&color, &object->Bitmap[offset], 1); 134 return le32toh(color) & 0xff; 135 case 2: 136 memcpy(&color, &object->Bitmap[offset], 2); 137 return le32toh(color) & 0xffff; 138 case 3: 139 memcpy(&color, &object->Bitmap[offset], 3); 140 return le32toh(color) & 0xffffff; 141 case 4: 142 memcpy(&color, &object->Bitmap[offset], 4); 143 return le32toh(color); 144 } 145 break; 146 case VIDBUF8X: 147 outb(0x3ce, 0x04); outb(0x3cf, x & 0x3); 148 return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)]; 149 case VIDBUF4S: 150 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 151 goto get_planar; 152 case VIDBUF4: 153 offset = y*VGLAdpInfo.va_line_width + x/8; 154 get_planar: 155 color = 0; 156 mask = 0x80 >> (x%8); 157 for (i = 0; i < VGLModeInfo.vi_planes; i++) { 158 outb(0x3ce, 0x04); outb(0x3cf, i); 159 color |= (((volatile VGLBitmap *)object)->Bitmap[offset] & mask) ? 160 (1 << i) : 0; 161 } 162 return color; 163 } 164 return 0; /* XXX black? */ 165 } 166 167 u_long 168 VGLGetXY(VGLBitmap *object, int x, int y) 169 { 170 u_long color; 171 172 VGLCheckSwitch(); 173 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize) 174 return 0; 175 if (object->Type != MEMBUF) { 176 color = VGLMouseFreeze(x, y, 1, 1, 0x40000000); 177 if (color & 0x40000000) { 178 VGLMouseUnFreeze(); 179 return color & 0xffffff; 180 } 181 } 182 color = __VGLGetXY(object, x, y); 183 if (object->Type != MEMBUF) 184 VGLMouseUnFreeze(); 185 return color; 186 } 187 188 /* 189 * Symmetric Double Step Line Algorithm by Brian Wyvill from 190 * "Graphics Gems", Academic Press, 1990. 191 */ 192 193 #define SL_SWAP(a,b) {a^=b; b^=a; a^=b;} 194 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1))) 195 196 void 197 plot(VGLBitmap * object, int x, int y, int flag, u_long color) 198 { 199 /* non-zero flag indicates the pixels need swapping back. */ 200 if (flag) 201 VGLSetXY(object, y, x, color); 202 else 203 VGLSetXY(object, x, y, color); 204 } 205 206 207 void 208 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 209 { 210 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; 211 int sign_x, sign_y, step, reverse, i; 212 213 dx = SL_ABSOLUTE(x2, x1, sign_x); 214 dy = SL_ABSOLUTE(y2, y1, sign_y); 215 /* decide increment sign by the slope sign */ 216 if (sign_x == sign_y) 217 step = 1; 218 else 219 step = -1; 220 221 if (dy > dx) { /* chooses axis of greatest movement (make dx) */ 222 SL_SWAP(x1, y1); 223 SL_SWAP(x2, y2); 224 SL_SWAP(dx, dy); 225 reverse = 1; 226 } else 227 reverse = 0; 228 /* note error check for dx==0 should be included here */ 229 if (x1 > x2) { /* start from the smaller coordinate */ 230 x = x2; 231 y = y2; 232 /* x1 = x1; 233 y1 = y1; */ 234 } else { 235 x = x1; 236 y = y1; 237 x1 = x2; 238 y1 = y2; 239 } 240 241 242 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ 243 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ 244 /* In fact (dx-1)/4 as 2 pixels are already plotted */ 245 xend = (dx - 1) / 4; 246 pixels_left = (dx - 1) % 4; /* number of pixels left over at the 247 * end */ 248 plot(object, x, y, reverse, color); 249 if (pixels_left < 0) 250 return; /* plot only one pixel for zero length 251 * vectors */ 252 plot(object, x1, y1, reverse, color); /* plot first two points */ 253 incr2 = 4 * dy - 2 * dx; 254 if (incr2 < 0) { /* slope less than 1/2 */ 255 c = 2 * dy; 256 incr1 = 2 * c; 257 D = incr1 - dx; 258 259 for (i = 0; i < xend; i++) { /* plotting loop */ 260 ++x; 261 --x1; 262 if (D < 0) { 263 /* pattern 1 forwards */ 264 plot(object, x, y, reverse, color); 265 plot(object, ++x, y, reverse, color); 266 /* pattern 1 backwards */ 267 plot(object, x1, y1, reverse, color); 268 plot(object, --x1, y1, reverse, color); 269 D += incr1; 270 } else { 271 if (D < c) { 272 /* pattern 2 forwards */ 273 plot(object, x, y, reverse, color); 274 plot(object, ++x, y += step, reverse, 275 color); 276 /* pattern 2 backwards */ 277 plot(object, x1, y1, reverse, color); 278 plot(object, --x1, y1 -= step, reverse, 279 color); 280 } else { 281 /* pattern 3 forwards */ 282 plot(object, x, y += step, reverse, color); 283 plot(object, ++x, y, reverse, color); 284 /* pattern 3 backwards */ 285 plot(object, x1, y1 -= step, reverse, 286 color); 287 plot(object, --x1, y1, reverse, color); 288 } 289 D += incr2; 290 } 291 } /* end for */ 292 293 /* plot last pattern */ 294 if (pixels_left) { 295 if (D < 0) { 296 plot(object, ++x, y, reverse, color); /* pattern 1 */ 297 if (pixels_left > 1) 298 plot(object, ++x, y, reverse, color); 299 if (pixels_left > 2) 300 plot(object, --x1, y1, reverse, color); 301 } else { 302 if (D < c) { 303 plot(object, ++x, y, reverse, color); /* pattern 2 */ 304 if (pixels_left > 1) 305 plot(object, ++x, y += step, reverse, color); 306 if (pixels_left > 2) 307 plot(object, --x1, y1, reverse, color); 308 } else { 309 /* pattern 3 */ 310 plot(object, ++x, y += step, reverse, color); 311 if (pixels_left > 1) 312 plot(object, ++x, y, reverse, color); 313 if (pixels_left > 2) 314 plot(object, --x1, y1 -= step, reverse, color); 315 } 316 } 317 } /* end if pixels_left */ 318 } 319 /* end slope < 1/2 */ 320 else { /* slope greater than 1/2 */ 321 c = 2 * (dy - dx); 322 incr1 = 2 * c; 323 D = incr1 + dx; 324 for (i = 0; i < xend; i++) { 325 ++x; 326 --x1; 327 if (D > 0) { 328 /* pattern 4 forwards */ 329 plot(object, x, y += step, reverse, color); 330 plot(object, ++x, y += step, reverse, color); 331 /* pattern 4 backwards */ 332 plot(object, x1, y1 -= step, reverse, color); 333 plot(object, --x1, y1 -= step, reverse, color); 334 D += incr1; 335 } else { 336 if (D < c) { 337 /* pattern 2 forwards */ 338 plot(object, x, y, reverse, color); 339 plot(object, ++x, y += step, reverse, 340 color); 341 342 /* pattern 2 backwards */ 343 plot(object, x1, y1, reverse, color); 344 plot(object, --x1, y1 -= step, reverse, 345 color); 346 } else { 347 /* pattern 3 forwards */ 348 plot(object, x, y += step, reverse, color); 349 plot(object, ++x, y, reverse, color); 350 /* pattern 3 backwards */ 351 plot(object, x1, y1 -= step, reverse, color); 352 plot(object, --x1, y1, reverse, color); 353 } 354 D += incr2; 355 } 356 } /* end for */ 357 /* plot last pattern */ 358 if (pixels_left) { 359 if (D > 0) { 360 plot(object, ++x, y += step, reverse, color); /* pattern 4 */ 361 if (pixels_left > 1) 362 plot(object, ++x, y += step, reverse, 363 color); 364 if (pixels_left > 2) 365 plot(object, --x1, y1 -= step, reverse, 366 color); 367 } else { 368 if (D < c) { 369 plot(object, ++x, y, reverse, color); /* pattern 2 */ 370 if (pixels_left > 1) 371 plot(object, ++x, y += step, reverse, color); 372 if (pixels_left > 2) 373 plot(object, --x1, y1, reverse, color); 374 } else { 375 /* pattern 3 */ 376 plot(object, ++x, y += step, reverse, color); 377 if (pixels_left > 1) 378 plot(object, ++x, y, reverse, color); 379 if (pixels_left > 2) { 380 if (D > c) /* step 3 */ 381 plot(object, --x1, y1 -= step, reverse, color); 382 else /* step 2 */ 383 plot(object, --x1, y1, reverse, color); 384 } 385 } 386 } 387 } 388 } 389 } 390 391 void 392 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 393 { 394 VGLLine(object, x1, y1, x2, y1, color); 395 VGLLine(object, x2, y1, x2, y2, color); 396 VGLLine(object, x2, y2, x1, y2, color); 397 VGLLine(object, x1, y2, x1, y1, color); 398 } 399 400 void 401 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 402 { 403 int y; 404 405 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color); 406 } 407 408 static inline void 409 set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 410 { 411 if (x!=0) { 412 VGLSetXY(object, xc+x, yc+y, color); 413 VGLSetXY(object, xc-x, yc+y, color); 414 if (y!=0) { 415 VGLSetXY(object, xc+x, yc-y, color); 416 VGLSetXY(object, xc-x, yc-y, color); 417 } 418 } 419 else { 420 VGLSetXY(object, xc, yc+y, color); 421 if (y!=0) 422 VGLSetXY(object, xc, yc-y, color); 423 } 424 } 425 426 void 427 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 428 { 429 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 430 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 431 432 while (dx<dy) { 433 set4pixels(object, x, y, xc, yc, color); 434 if (d>0) { 435 y--; dy-=asq2; d-=dy; 436 } 437 x++; dx+=bsq2; d+=bsq+dx; 438 } 439 d+=(3*(asq-bsq)/2-(dx+dy))/2; 440 while (y>=0) { 441 set4pixels(object, x, y, xc, yc, color); 442 if (d<0) { 443 x++; dx+=bsq2; d+=dx; 444 } 445 y--; dy-=asq2; d+=asq-dy; 446 } 447 } 448 449 static inline void 450 set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 451 { 452 if (x!=0) { 453 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color); 454 if (y!=0) 455 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color); 456 } 457 else { 458 VGLLine(object, xc, yc+y, xc, yc-y, color); 459 } 460 } 461 462 void 463 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 464 { 465 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 466 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 467 468 while (dx<dy) { 469 set2lines(object, x, y, xc, yc, color); 470 if (d>0) { 471 y--; dy-=asq2; d-=dy; 472 } 473 x++; dx+=bsq2; d+=bsq+dx; 474 } 475 d+=(3*(asq-bsq)/2-(dx+dy))/2; 476 while (y>=0) { 477 set2lines(object, x, y, xc, yc, color); 478 if (d<0) { 479 x++; dx+=bsq2; d+=dx; 480 } 481 y--; dy-=asq2; d+=asq-dy; 482 } 483 } 484 485 void 486 VGLClear(VGLBitmap *object, u_long color) 487 { 488 VGLBitmap src; 489 int offset; 490 int len; 491 int i; 492 493 VGLCheckSwitch(); 494 if (object->Type != MEMBUF) 495 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color); 496 switch (object->Type) { 497 case MEMBUF: 498 case VIDBUF8: 499 case VIDBUF8S: 500 case VIDBUF16: 501 case VIDBUF16S: 502 case VIDBUF24: 503 case VIDBUF24S: 504 case VIDBUF32: 505 case VIDBUF32S: 506 src.Type = MEMBUF; 507 src.Xsize = object->Xsize; 508 src.VXsize = object->VXsize; 509 src.Ysize = 1; 510 src.VYsize = 1; 511 src.Xorigin = 0; 512 src.Yorigin = 0; 513 src.Bitmap = alloca(object->VXsize * object->PixelBytes); 514 src.PixelBytes = object->PixelBytes; 515 color = htole32(color); 516 for (i = 0; i < object->VXsize; i++) 517 bcopy(&color, src.Bitmap + i * object->PixelBytes, object->PixelBytes); 518 for (i = 0; i < object->VYsize; i++) 519 __VGLBitmapCopy(&src, 0, 0, object, 0, i, object->VXsize, 1); 520 break; 521 522 case VIDBUF8X: 523 /* XXX works only for Xsize % 4 = 0 */ 524 outb(0x3c6, 0xff); 525 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 526 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize); 527 break; 528 529 case VIDBUF4: 530 case VIDBUF4S: 531 /* XXX works only for Xsize % 8 = 0 */ 532 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 533 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */ 534 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 535 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 536 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) { 537 VGLSetSegment(offset); 538 len = min(object->VXsize*object->VYsize - offset, 539 VGLAdpInfo.va_window_size); 540 memset(object->Bitmap, (byte)color, len); 541 offset += len; 542 } 543 outb(0x3ce, 0x05); outb(0x3cf, 0x00); 544 break; 545 } 546 if (object->Type != MEMBUF) 547 VGLMouseUnFreeze(); 548 } 549 550 void 551 VGLRestorePalette() 552 { 553 int i; 554 555 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 556 return; 557 outb(0x3C6, 0xFF); 558 inb(0x3DA); 559 outb(0x3C8, 0x00); 560 for (i=0; i<256; i++) { 561 outb(0x3C9, VGLSavePaletteRed[i]); 562 inb(0x84); 563 outb(0x3C9, VGLSavePaletteGreen[i]); 564 inb(0x84); 565 outb(0x3C9, VGLSavePaletteBlue[i]); 566 inb(0x84); 567 } 568 inb(0x3DA); 569 outb(0x3C0, 0x20); 570 } 571 572 void 573 VGLSavePalette() 574 { 575 int i; 576 577 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 578 return; 579 outb(0x3C6, 0xFF); 580 inb(0x3DA); 581 outb(0x3C7, 0x00); 582 for (i=0; i<256; i++) { 583 VGLSavePaletteRed[i] = inb(0x3C9); 584 inb(0x84); 585 VGLSavePaletteGreen[i] = inb(0x3C9); 586 inb(0x84); 587 VGLSavePaletteBlue[i] = inb(0x3C9); 588 inb(0x84); 589 } 590 inb(0x3DA); 591 outb(0x3C0, 0x20); 592 } 593 594 void 595 VGLSetPalette(byte *red, byte *green, byte *blue) 596 { 597 int i; 598 599 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 600 return; 601 for (i=0; i<256; i++) { 602 VGLSavePaletteRed[i] = red[i]; 603 VGLSavePaletteGreen[i] = green[i]; 604 VGLSavePaletteBlue[i] = blue[i]; 605 } 606 VGLCheckSwitch(); 607 outb(0x3C6, 0xFF); 608 inb(0x3DA); 609 outb(0x3C8, 0x00); 610 for (i=0; i<256; i++) { 611 outb(0x3C9, VGLSavePaletteRed[i]); 612 inb(0x84); 613 outb(0x3C9, VGLSavePaletteGreen[i]); 614 inb(0x84); 615 outb(0x3C9, VGLSavePaletteBlue[i]); 616 inb(0x84); 617 } 618 inb(0x3DA); 619 outb(0x3C0, 0x20); 620 } 621 622 void 623 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue) 624 { 625 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 626 return; 627 VGLSavePaletteRed[color] = red; 628 VGLSavePaletteGreen[color] = green; 629 VGLSavePaletteBlue[color] = blue; 630 VGLCheckSwitch(); 631 outb(0x3C6, 0xFF); 632 inb(0x3DA); 633 outb(0x3C8, color); 634 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue); 635 inb(0x3DA); 636 outb(0x3C0, 0x20); 637 } 638 639 void 640 VGLSetBorder(byte color) 641 { 642 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) 643 return; 644 VGLCheckSwitch(); 645 inb(0x3DA); 646 outb(0x3C0,0x11); outb(0x3C0, color); 647 inb(0x3DA); 648 outb(0x3C0, 0x20); 649 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 650 ioctl(0, KDDISABIO, 0); 651 } 652 653 void 654 VGLBlankDisplay(int blank) 655 { 656 byte val; 657 658 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0)) 659 return; 660 VGLCheckSwitch(); 661 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01); 662 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF))); 663 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT) 664 ioctl(0, KDDISABIO, 0); 665 } 666