|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 26: * ! 27: * VGAConsole.c - VGA Mode 0x12 console implementation. ! 28: * ! 29: * ! 30: * HISTORY ! 31: * 02 Feb 93 Peter Graffagnino ! 32: * Created from FBConsole.c ! 33: */ ! 34: ! 35: // ! 36: // Notes: ! 37: // * Considerations for supporting other VGA modes: ! 38: // This code uses off screen memory for the save behind area. This ! 39: // permits the use of write mode 1 to save the data resulting in ! 40: // a flicker-free restore, and makes the coding somewhat simpler. Care ! 41: // should be taken that there is enough memory there in other modes, ! 42: // or allocated storage. ! 43: // ! 44: // Since mode 12 fits comfortably in 64K/plane, no bank switching is ! 45: // currently done in this code. Higher res modes will need this. ! 46: // ! 47: // * This module implements the console functionality required by the ! 48: // ConsoleSupport protocol. ! 49: // * To find things that need to be fixed, search for FIX, to find questions ! 50: // to be resolved, search for ASK, to find stuff that still needs to be ! 51: // done, search for TO DO. ! 52: ! 53: #import <sys/syslog.h> ! 54: #import <bsd/dev/i386/VGAConsole.h> ! 55: #import <bsd/dev/i386/VGAConsPriv.h> ! 56: #import <driverkit/i386/displayRegisters.h> ! 57: #import <architecture/ascii_codes.h> ! 58: ! 59: #define NIL (0) ! 60: ! 61: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320) ! 62: #define SIREG "e" ! 63: #else ! 64: #define SIREG "S" ! 65: #endif ! 66: ! 67: /* Window margins */ ! 68: #define BG_MARGIN 2 // pixels of background to leave as margin ! 69: #define FG_MARGIN 1 // pixels of foreground to leave as margin ! 70: #define TOTAL_MARGIN (BG_MARGIN + FG_MARGIN) ! 71: ! 72: #define SVGA_SAVE_BITS (2 * SVGA_ROWBYTES * SVGA_HEIGHT) ! 73: ! 74: /* ! 75: * Ansi sequence state. ! 76: */ ! 77: typedef enum { ! 78: AS_NORMAL, ! 79: AS_ESCAPE, ! 80: AS_BRACKET, ! 81: AS_R ! 82: } ansi_state_t; ! 83: ! 84: #define ANSI_STACK_SIZE 3 ! 85: #define ANSI_STACK_MAX 2 ! 86: ! 87: typedef struct _t_VGARegisters { ! 88: unsigned char GC[VGA_NUM_GC_REGS]; ! 89: unsigned char SEQ[VGA_NUM_SEQ_REGS]; ! 90: } VGARegisters; ! 91: ! 92: typedef struct _t_Console { ! 93: ScreenMode window_type; ! 94: ! 95: IODisplayInfo display; ! 96: ! 97: // ! 98: // The remaining fields are window parameters. These are only ! 99: // meaningful for text-type windows (window_type == SCM_TEXT or ! 100: // SCM_ALERT). ! 101: // ! 102: ! 103: // ! 104: // Current window origin in pixels, relative to origin of screen. ! 105: // ! 106: int window_origin_x; ! 107: int window_origin_y; ! 108: ! 109: // ! 110: // Window size information, in pixels and in characters. ! 111: // ! 112: int chars_per_row; ! 113: int pixels_per_row; ! 114: int chars_per_column; ! 115: int pixels_per_column; ! 116: ! 117: // ! 118: // Cursor location, in characters. Origin is top ! 119: // left corner of window = {0,0}. ! 120: // ! 121: int curr_row; // in characters ! 122: int curr_column; // in characters ! 123: ! 124: // ! 125: // Misc. video parameters. The background and foreground fields ! 126: // are slightly dependent on the hardware implementation; they'll ! 127: // work as long as bits per pixel <= 32. ! 128: // ! 129: unsigned int baseground; // bits for base color ! 130: unsigned int background; // bits for background pixel ! 131: unsigned int foreground; // bits for foreground pixel ! 132: unsigned int dark_grey; // bits for dark grey ! 133: unsigned int light_grey; // bits for light grey ! 134: boolean_t has_title; ! 135: ! 136: // ! 137: // Storage for saved region under an alert panel. ! 138: // ! 139: unsigned char *saveBits; ! 140: int saveHeight; ! 141: int saveRowBytes; ! 142: int saveBytes; ! 143: unsigned char *saveLocation; ! 144: VGARegisters savedRegisters; // save for Restore ! 145: VGARegisters tempRegisters; // save between operations ! 146: ! 147: ansi_state_t ansi_state; // track ansi escape sequence state ! 148: u_char ansi_stack[ANSI_STACK_SIZE]; ! 149: u_char *ansi_stack_p; ! 150: ! 151: boolean_t isSVGA; // use SVGA methods ! 152: } ConsoleRep, *ConsolePtr; ! 153: ! 154: #define PLANE_MASK 0x0F // By default, use all planes ! 155: #define PIXEL_MASK 0xFF // By default, all pixels ! 156: #define RW_MODE 0x00 // Default VGA read/write mode ! 157: ! 158: // ! 159: // BEGIN: Private utility routines ! 160: // ! 161: ! 162: static inline int isTextMode(ConsolePtr console) ! 163: { ! 164: return ((console->window_type == SCM_TEXT) || ! 165: (console->window_type == SCM_ALERT)); ! 166: } ! 167: ! 168: static void SwapForegroundAndBackground(ConsolePtr console) ! 169: { ! 170: int temp_color; ! 171: ! 172: temp_color = console->foreground; ! 173: console->foreground = console->background; ! 174: console->background = temp_color; ! 175: } ! 176: ! 177: static inline int rread(int port, int index) ! 178: { ! 179: outb(port, index); ! 180: return(inb(port + 1)); ! 181: } ! 182: ! 183: ! 184: static inline void SaveVGARegs(VGARegisters *saved) ! 185: { ! 186: int i; ! 187: ! 188: for (i = 0; i < VGA_NUM_GC_REGS; i++) ! 189: saved->GC[i] = rread(VGA_GC_ADDR,i); ! 190: #if defined(SAVE_ALL_SEQ_REGS) ! 191: for (i = 0; i < VGA_NUM_SEQ_REGS; i++) ! 192: saved->SEQ[i] = rread(VGA_SEQ_ADDR,i); ! 193: #else /* defined(SAVE_ALL_SEQ_REGS) */ ! 194: saved->SEQ[2] = rread(VGA_SEQ_ADDR,2); ! 195: #endif /* defined(SAVE_ALL_SEQ_REGS) */ ! 196: } ! 197: ! 198: static inline void RestoreVGARegs(VGARegisters *saved) ! 199: { ! 200: int i; ! 201: ! 202: for (i = 0; i < VGA_NUM_GC_REGS; i++) ! 203: IOWriteRegister(VGA_GC_ADDR,i, saved->GC[i]); ! 204: #if defined(SAVE_ALL_SEQ_REGS) ! 205: for (i = 0; i < VGA_NUM_SEQ_REGS; i++) ! 206: IOWriteRegister(VGA_SEQ_ADDR,i, saved->SEQ[i]); ! 207: #else /* defined(SAVE_ALL_SEQ_REGS) */ ! 208: IOWriteRegister(VGA_SEQ_ADDR, 2, saved->SEQ[2]); ! 209: #endif /* defined(SAVE_ALL_SEQ_REGS) */ ! 210: } ! 211: ! 212: static void FlipCursor(ConsolePtr console) ! 213: // Description: Turn cursor on/off. This just inverts every pixel at the ! 214: // character at (curr_rown, curr_column). ! 215: { ! 216: ! 217: int y; ! 218: // Screen-relative pixel coordinates of bounds of current character. ! 219: int start_y = console->window_origin_y + ! 220: console->curr_row * CHAR_H; ! 221: int end_y = start_y + CHAR_H; ! 222: int start_x = console->window_origin_x + ! 223: console->curr_column * CHAR_W; ! 224: unsigned char *cp; ! 225: volatile char mask; ! 226: ! 227: IOWriteRegister(VGA_GC_ADDR, 7, 0x0f); /* enable cdc planes */ ! 228: IOWriteRegister(VGA_GC_ADDR, 5, 0x08); /* set read mode 1 */ ! 229: IOWriteRegister(VGA_GC_ADDR, 2, console->background); /* setup color compare */ ! 230: cp = (unsigned char *)console->display.frameBuffer + ! 231: start_y*console->display.rowBytes + (start_x >> 3); ! 232: for (y=start_y; y < end_y; y++) { ! 233: mask = *cp; ! 234: IOWriteRegister(VGA_GC_ADDR, 0, console->background); /* set color */ ! 235: IOWriteRegister(VGA_GC_ADDR, 8, ~mask); /* set pixel mask */ ! 236: *cp = 0xff; ! 237: IOWriteRegister(VGA_GC_ADDR, 0, console->foreground); /* set color */ ! 238: IOWriteRegister(VGA_GC_ADDR, 8, mask); /* set pixel mask */ ! 239: mask = *cp; ! 240: *cp = 0xff; ! 241: cp += console->display.rowBytes; ! 242: } ! 243: ! 244: IOWriteRegister(VGA_GC_ADDR, 5, RW_MODE); /* set read mode 0 */ ! 245: IOWriteRegister(VGA_GC_ADDR, 8, PIXEL_MASK); /* set pixel mask */ ! 246: ! 247: } ! 248: ! 249: /* ! 250: * Bank switching is currently not supported. ! 251: */ ! 252: ! 253: static inline char SVGASegmentForAddress(register void *addr) ! 254: { ! 255: #if NOTYET ! 256: register char segment; ! 257: register int offset; ! 258: ! 259: offset = ((int)addr) - ((int)SVGA_FRAMEBUFFER_ADDRESS); ! 260: segment = offset % SVGABANKBYTES; ! 261: return(segment); ! 262: #else NOTYET ! 263: return 0; ! 264: #endif NOTYET ! 265: } ! 266: ! 267: static inline void SVGASelectSegment(char segment) ! 268: { ! 269: #if NOTYET ! 270: outb(VGA_GCR_SEGS, segment << 4 | segment); ! 271: #endif NOTYET ! 272: } ! 273: ! 274: static inline void SVGASelectSegmentForAddressIfNecessary( ! 275: unsigned char *addr, ! 276: char *currentSegmentPtr ! 277: ) ! 278: { ! 279: #if NOTYET ! 280: char segment; ! 281: ! 282: segment = SVGASegmentForAddress(addr); ! 283: ! 284: if (segment != *currentSegmentPtr) { ! 285: SVGASelectSegment(segment); ! 286: *currentSegmentPtr = segment; ! 287: } ! 288: #endif NOTYET ! 289: } ! 290: ! 291: ! 292: static unsigned char leftMaskArray[] = ! 293: {0xff, 0x7f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0x1}; ! 294: ! 295: static unsigned char rightMaskArray[] = ! 296: {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; ! 297: ! 298: ! 299: ! 300: static void rect(ConsolePtr console, int x, int y, int w, int h, int c) ! 301: { ! 302: int first_byte, last_byte; ! 303: unsigned char lmask, rmask; ! 304: int k, midcnt; ! 305: int x2 = x + w; ! 306: volatile unsigned char *rowptr; ! 307: int rowBytes = console->display.rowBytes; ! 308: ! 309: IOWriteRegister(VGA_GC_ADDR, 0, c); /* set color */ ! 310: outb(VGA_GC_ADDR, 8); /* point to pixel mask reg */ ! 311: first_byte = x >> 3; ! 312: last_byte = x2 >> 3; ! 313: lmask = leftMaskArray[x & 7]; ! 314: rmask = rightMaskArray[x2 & 7]; ! 315: ! 316: rowptr = (unsigned char *)console->display.frameBuffer + ! 317: y*rowBytes + first_byte; ! 318: ! 319: midcnt = last_byte - first_byte - 1; ! 320: if (midcnt == -1) { /* i.e. first_word == last_word */ ! 321: outb(VGA_GC_ADDR + 1, rmask & lmask); ! 322: for(; --h >= 0;rowptr += rowBytes) { ! 323: volatile char forceReadByte = *rowptr; ! 324: *rowptr = 0xff; ! 325: } ! 326: } else { ! 327: for(; --h >= 0; rowptr += rowBytes) { ! 328: volatile unsigned char *p = rowptr; ! 329: volatile char foo = *p; ! 330: outb(VGA_GC_ADDR + 1, lmask); ! 331: *p++ = 0xff; ! 332: outb(VGA_GC_ADDR + 1, 0xff); ! 333: for(k = midcnt; --k >= 0;) ! 334: *p++ = 0xff; // no need to latch data. ! 335: outb(VGA_GC_ADDR + 1, rmask); ! 336: foo = *p; ! 337: *p = 0xff; ! 338: } ! 339: } ! 340: outb(VGA_GC_ADDR + 1, PIXEL_MASK); ! 341: ! 342: } ! 343: ! 344: ! 345: static void ClearWindow(ConsolePtr console) ! 346: // Description: Set contents of entire current window to background. ! 347: // Preconditions: ! 348: // * Cursor is off on entry and will remain so on exit. ! 349: { ! 350: rect(console, console->window_origin_x, console->window_origin_y, ! 351: console->pixels_per_row, console->pixels_per_column, ! 352: console->background); ! 353: } ! 354: ! 355: static void WipeScreen(ConsolePtr console, const unsigned pixel) ! 356: // Description: Fill the screen with specific pixel value. ! 357: { ! 358: rect(console, 0, 0, console->display.totalWidth, ! 359: console->display.height, pixel); ! 360: } ! 361: ! 362: static void ClearToEOL(ConsolePtr console) ! 363: // Description: Clear to end of line (within window), including current pos. ! 364: // Preconditions: ! 365: // * Cursor is 'off' on entry and will remain so on exit. ! 366: { ! 367: unsigned pixel_count; ! 368: int starting_x; // window-relative 'x' coordinate ! 369: int y; ! 370: ! 371: starting_x = console->window_origin_x + ! 372: (console->curr_column * CHAR_W); ! 373: y = console->window_origin_y + (console->curr_row * CHAR_H); ! 374: ! 375: pixel_count = console->pixels_per_row - ! 376: (starting_x - console->window_origin_x); ! 377: ! 378: rect(console, starting_x, y, pixel_count, CHAR_H , console->background); ! 379: ! 380: } ! 381: ! 382: static void Erase(ConsolePtr console) ! 383: // Description: Erase current cursor location. ! 384: { ! 385: // Screen-relative pixel coordinates of bounds of current character. ! 386: int start_y = console->window_origin_y + ! 387: console->curr_row * CHAR_H; ! 388: int start_x = console->window_origin_x + ! 389: console->curr_column * CHAR_W; ! 390: ! 391: rect(console, start_x, start_y, CHAR_W, CHAR_H, console->background); ! 392: } ! 393: ! 394: #define ENCODEBASE ' ' ! 395: ! 396: static void BltChar(ConsolePtr console, const char c) ! 397: // Description: Paint one character at (curr_column, curr_row). ! 398: { ! 399: unsigned char *glyphbase; // the glyph we're rendering ! 400: int x,y; // location of upper left corner of glyph ! 401: int source_y; ! 402: volatile int tmp; ! 403: unsigned char *cp; ! 404: ! 405: // Erase current contents of {curr_row, curr_column}. ! 406: Erase(console); ! 407: ! 408: // Skip non-printing characters. ! 409: if (c < ENCODEBASE) { ! 410: return; ! 411: } ! 412: ! 413: glyphbase = ohlfs12[c - ENCODEBASE]; ! 414: x = console->window_origin_x + console->curr_column * CHAR_W; ! 415: y = console->window_origin_y + console->curr_row * CHAR_H; ! 416: ! 417: IOWriteRegister(VGA_GC_ADDR, 0, console->foreground);/* set color */ ! 418: cp = (unsigned char *)console->display.frameBuffer + ! 419: y*console->display.rowBytes + (x >> 3); ! 420: outb(VGA_GC_ADDR, 8); /* point to pixel mask reg */ ! 421: ! 422: for (source_y = CHAR_H; source_y != 0; source_y--) { ! 423: outb(VGA_GC_ADDR + 1, *glyphbase++); ! 424: tmp = *cp; ! 425: *cp = 0xff; ! 426: cp += console->display.rowBytes; ! 427: } ! 428: outb(VGA_GC_ADDR + 1, PIXEL_MASK); /* restore to default */ ! 429: ! 430: console->curr_column++; ! 431: return; ! 432: } ! 433: ! 434: /* ! 435: * Use bytemove as opposed to memmove. 32bit bus cycles seem to confuse ! 436: * the VGA. ! 437: */ ! 438: static inline void bytemove(char *dst, char *src, int cnt) ! 439: { ! 440: #if DONT_USE_ASM ! 441: while(cnt--) ! 442: *dst++ = *src++; ! 443: #else DONT_USE_ASM ! 444: asm("rep; movsb" ! 445: : /* no outputs */ ! 446: : "&c" (cnt), "D" (dst), SIREG (src) ! 447: : "ecx", "esi", "edi"); ! 448: #endif DONT_USE_ASM ! 449: } ! 450: ! 451: static void FBPutC(ConsolePtr console, char c) ! 452: // Write one character to screen. Cursor is 'on' on entry and exit. ! 453: { ! 454: int repeat; ! 455: int i; ! 456: ! 457: if (!isTextMode(console)) ! 458: return; ! 459: ! 460: /* ! 461: * First deal with ANSI escape sequences. ! 462: * This is a very bizarre implementation, copied from the m68k ! 463: * version. ! 464: */ ! 465: switch(console->ansi_state) { ! 466: case AS_NORMAL: ! 467: if(c == esc) { ! 468: console->ansi_state = AS_ESCAPE; ! 469: return; ! 470: } ! 471: else { ! 472: break; // continue ! 473: } ! 474: ! 475: case AS_ESCAPE: ! 476: switch(c) { ! 477: case '[': ! 478: console->ansi_state = AS_BRACKET; ! 479: return; ! 480: default: ! 481: console->ansi_state = AS_NORMAL; ! 482: break; // continue ! 483: } ! 484: ! 485: case AS_BRACKET: ! 486: if(c >= '0' && c <= '9') { ! 487: *console->ansi_stack_p = ! 488: *console->ansi_stack_p * 10 + (c - '0'); ! 489: return; ! 490: } ! 491: else if (c == ';') { ! 492: if(console->ansi_stack_p < ! 493: &console->ansi_stack[ANSI_STACK_MAX]) { ! 494: console->ansi_stack_p++; ! 495: } ! 496: return; ! 497: } ! 498: else { ! 499: for(i=0; i<ANSI_STACK_SIZE; i++) { ! 500: if (console->ansi_stack[i] == 0) { ! 501: console->ansi_stack[i] = 1; ! 502: } ! 503: } ! 504: repeat = *console->ansi_stack_p; ! 505: FlipCursor(console); // cursor off ! 506: switch (c) { ! 507: ! 508: case 'A': ! 509: while (repeat--) { ! 510: if(console->curr_row) { ! 511: console->curr_row--; ! 512: } ! 513: } ! 514: break; ! 515: ! 516: case 'B': ! 517: while (repeat--) { ! 518: console->curr_row++; ! 519: } ! 520: break; ! 521: ! 522: case 'C': // non destructive space ! 523: while (repeat--) { ! 524: console->curr_column++; ! 525: } ! 526: break; ! 527: ! 528: case 'D': // not in termcap ! 529: while (repeat--) { ! 530: if(console->curr_column) { ! 531: console->curr_column--; ! 532: } ! 533: } ! 534: break; ! 535: ! 536: case 'E': // not in termcap ! 537: console->curr_column = 0; ! 538: while (repeat--) { ! 539: console->curr_row++; ! 540: } ! 541: break; ! 542: ! 543: case 'H': // should be home ! 544: case 'f': // not in termcap ! 545: console->curr_column = ! 546: *console->ansi_stack_p - 1; ! 547: console->ansi_stack_p--; ! 548: console->curr_row = ! 549: *console->ansi_stack_p - 1; ! 550: console->ansi_stack_p--; ! 551: break; ! 552: ! 553: case 'K': ! 554: ClearToEOL(console); ! 555: break; ! 556: ! 557: case 'm': /* FIXME */ ! 558: console->ansi_stack_p--; ! 559: console->ansi_stack_p--; ! 560: ! 561: /* prevent washout */ ! 562: if(console->background == ! 563: console->foreground) { ! 564: console->background = VGA_WHITE; ! 565: console->foreground = VGA_BLACK; ! 566: } ! 567: break; ! 568: } ! 569: } ! 570: console->ansi_stack_p = &console->ansi_stack[1]; ! 571: for(i=0; i<ANSI_STACK_SIZE; i++) ! 572: console->ansi_stack[i] = 0; ! 573: console->ansi_state = AS_NORMAL; ! 574: goto proceed; ! 575: case AS_R: ! 576: // FIXME ! 577: break; ! 578: } ! 579: ! 580: FlipCursor(console); // cursor off ! 581: switch(c) { ! 582: case '\r': // Carriage return ! 583: console->curr_column = 0; ! 584: break; ! 585: ! 586: case '\n': // line feed ! 587: console->curr_column = 0; ! 588: console->curr_row++; ! 589: break; ! 590: ! 591: case '\b': // backspace ! 592: if (console->curr_column == 0) ! 593: break; ! 594: console->curr_column--; ! 595: break; ! 596: ! 597: case '\t': ! 598: // tab. Erase all characters up to and including the ! 599: // next tab stop. ! 600: { ! 601: int col, num_cols; ! 602: ! 603: num_cols = TAB_SIZE - (console->curr_column % TAB_SIZE); ! 604: FlipCursor(console); // cursor on ! 605: for (col = 0; col<num_cols; col++) { ! 606: FBPutC(console, ' '); // cursor on at return ! 607: } ! 608: FlipCursor(console); // cursor off ! 609: break; ! 610: } ! 611: ! 612: case np: // aka ff, form feed ! 613: console->curr_row = console->curr_column = 0; ! 614: ClearWindow(console); ! 615: break; ! 616: ! 617: case del: ! 618: console->curr_column++; ! 619: break; ! 620: ! 621: default: ! 622: // Normal case. ! 623: BltChar(console, c); ! 624: break; ! 625: } ! 626: ! 627: // Cursor is off. ! 628: proceed: ! 629: if (console->curr_column >= console->chars_per_row) { ! 630: // End-of-line wrap. ! 631: console->curr_column = 0; ! 632: console->curr_row++; ! 633: } ! 634: ! 635: if (console->curr_row >= console->chars_per_column) { ! 636: // ! 637: // Screen scroll. Copy the whole window down in memory ! 638: // (pixels_per_row * CHAR_H) pixels, starting at ! 639: // the first character in row 1. ! 640: // ! 641: unsigned char *src; ! 642: unsigned char *dst; ! 643: int source_y; ! 644: ! 645: console->curr_row = console->chars_per_column - 1; ! 646: ! 647: /* ! 648: * for screen-to-screen scrolling in graphics mode, we use ! 649: * write mode 1, and pretend its a 1 bit display. We also ! 650: * exploit the fact the the scrolling area begins and ends ! 651: * on a 0 mod 8 pixel address. ! 652: */ ! 653: ! 654: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */ ! 655: src = (unsigned char *)console->display.frameBuffer + ! 656: (console->window_origin_y + CHAR_H)*console->display.rowBytes + ! 657: (console->window_origin_x >> 3); ! 658: dst = src - CHAR_H*console->display.rowBytes; ! 659: for (source_y = CHAR_H; // top, row 1 ! 660: source_y < console->pixels_per_column; // bottom ! 661: source_y++) { ! 662: ! 663: bytemove(dst, src, console->pixels_per_row>>3); ! 664: src += console->display.rowBytes; ! 665: dst += console->display.rowBytes; ! 666: } ! 667: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); // restore write mode ! 668: ! 669: console->curr_column = 0; ! 670: ClearToEOL(console); ! 671: } ! 672: ! 673: // Cursor back on. ! 674: FlipCursor(console); ! 675: } ! 676: ! 677: static void SetTitle(ConsolePtr console, const char *title) ! 678: // Description: Draw title bar if none exists, write specified title into it. ! 679: // Drawing a title bar involves snarfing up row 0 of the window ! 680: // and decreasing the usable size of the window by one row. ! 681: // Preconditions: ! 682: // * Cursor is 'on' on entry and will remain so on exit. ! 683: { ! 684: int saved_curr_row = console->curr_row; ! 685: int saved_curr_column = console->curr_column; ! 686: int saved_origin_y; ! 687: int title_len = strlen(title); ! 688: int pixel_num; ! 689: ! 690: if ((title_len == 0) || (title_len > console->chars_per_row)) { ! 691: IOLog("console: Illegal title length (%d)\n", title_len); ! 692: return; ! 693: } ! 694: FlipCursor(console); // old cursor off ! 695: if (console->has_title) { ! 696: // First grow window by two rows - this absorbs the existing ! 697: // title bar. ! 698: console->window_origin_y -= CHAR_H * 2; ! 699: console->chars_per_column += 2; ! 700: console->pixels_per_column += CHAR_H * 2; ! 701: saved_curr_row += 2; ! 702: } ! 703: ! 704: // Clear row 0, center new title in it. ! 705: console->curr_row = 0; ! 706: rect(console, ! 707: console->window_origin_x, ! 708: console->window_origin_y, ! 709: CHAR_W * console->chars_per_row, ! 710: CHAR_H * 2 - BG_MARGIN, ! 711: console->foreground); ! 712: saved_origin_y = console->window_origin_y; ! 713: console->window_origin_y += CHAR_H / 2; ! 714: console->curr_column = (console->chars_per_row - title_len) / 2; ! 715: FlipCursor(console); // new cursor on ! 716: SwapForegroundAndBackground(console); ! 717: while (*title) { ! 718: FBPutC(console, *title++); ! 719: } ! 720: SwapForegroundAndBackground(console); ! 721: FlipCursor(console); // new cursor off ! 722: console->window_origin_y = saved_origin_y; ! 723: ! 724: // Draw grey lines one pixel away from border of title bar. ! 725: // Origin is currently at first pixel in top line of title bar. ! 726: ! 727: rect(console, // inside top ! 728: console->window_origin_x - BG_MARGIN, ! 729: console->window_origin_y - BG_MARGIN, ! 730: console->pixels_per_row + (BG_MARGIN * 2), ! 731: BG_MARGIN, ! 732: console->light_grey); ! 733: rect(console, // inside bottom ! 734: console->window_origin_x - BG_MARGIN, ! 735: console->window_origin_y + CHAR_H * 2 - TOTAL_MARGIN - BG_MARGIN, ! 736: console->pixels_per_row + BG_MARGIN * 2, ! 737: BG_MARGIN, ! 738: console->dark_grey); ! 739: for (pixel_num = 0; pixel_num < BG_MARGIN; pixel_num++) { ! 740: rect(console, // left ! 741: console->window_origin_x - BG_MARGIN + pixel_num, ! 742: console->window_origin_y - BG_MARGIN + pixel_num, ! 743: 1, ! 744: CHAR_H * 2 - 1 - (pixel_num * 2), ! 745: console->light_grey); ! 746: } ! 747: for (pixel_num = 1; pixel_num <= BG_MARGIN; pixel_num++) { ! 748: rect(console, // right ! 749: console->window_origin_x + console->pixels_per_row + pixel_num - 1, ! 750: console->window_origin_y - pixel_num, ! 751: 1, ! 752: CHAR_H * 2 - 1 - (BG_MARGIN - pixel_num) * 2, ! 753: console->dark_grey); ! 754: } ! 755: rect(console, // outside bottom ! 756: console->window_origin_x - TOTAL_MARGIN, ! 757: console->window_origin_y + CHAR_H * 2 - FG_MARGIN - BG_MARGIN, ! 758: console->pixels_per_row + TOTAL_MARGIN * 2, ! 759: FG_MARGIN, ! 760: console->foreground); ! 761: ! 762: // Diminish window size by two rows. ! 763: console->window_origin_y += CHAR_H * 2; ! 764: console->chars_per_column -= 2; ! 765: console->pixels_per_column -= CHAR_H * 2; ! 766: ! 767: ! 768: // Restore old cursor. Careful, the y axis just changed... ! 769: console->curr_column = saved_curr_column; ! 770: if (saved_curr_row > 0) { ! 771: console->curr_row = saved_curr_row - 2; ! 772: } ! 773: else { ! 774: // New row 0 - clear it. ! 775: ClearToEOL(console); ! 776: } ! 777: FlipCursor(console); // old cursor on ! 778: console->has_title = TRUE; ! 779: } ! 780: ! 781: static void UpdateWindowChars(ConsolePtr console) ! 782: // Description: Calculate window size in characters. Used when either window ! 783: // size or font changes. ! 784: { ! 785: console->chars_per_row = console->pixels_per_row / CHAR_W; ! 786: console->chars_per_column = ! 787: console->pixels_per_column / CHAR_H; ! 788: } ! 789: ! 790: ! 791: static void InitWindow(ConsolePtr console, ! 792: int width, ! 793: int height, ! 794: const char *title, ! 795: boolean_t initWindow, ! 796: boolean_t saveUnder) ! 797: // Description: Initialize window parameters. If initWindow is TRUE, an empty ! 798: // window is drawn in the screen, else we assume that a window ! 799: // already exists. Screen and font parameters must be valid on ! 800: // entry. ! 801: { ! 802: ! 803: // Truncate specified size to integral mutliple of character size ! 804: // in both dimensions. ! 805: width /= CHAR_W; // now in chars ! 806: height /= CHAR_H; ! 807: width *= CHAR_W; // now in pixels ! 808: height *= CHAR_H; ! 809: ! 810: // Ensure there's enough room for a border. ! 811: if (width > (console->display.width - TOTAL_MARGIN * 2)) ! 812: width = console->display.width - TOTAL_MARGIN * 2; ! 813: if (height > (console->display.height - TOTAL_MARGIN * 2)) ! 814: height = console->display.height - TOTAL_MARGIN * 2; ! 815: ! 816: // ! 817: // Init console window variables. The window is centered in the ! 818: // screen, minus a pixel or two to guarantee double word alignment ! 819: // for the first pixel of a row (until further developments...when ! 820: // we do alert panels, we can enumerate some cases here...). ! 821: // ! 822: console->window_origin_x = (console->display.width - width) / 2; ! 823: console->window_origin_y = (console->display.height - height) / 2; ! 824: console->pixels_per_row = width; ! 825: console->pixels_per_column = height; ! 826: (unsigned)console->window_origin_x &= ~0x07; ! 827: ! 828: UpdateWindowChars(console); ! 829: ! 830: console->curr_column = 0; ! 831: console->has_title = FALSE; ! 832: ! 833: if (initWindow) { ! 834: // Before we start drawing anything, save under if needed ! 835: if (saveUnder) { ! 836: int i; ! 837: unsigned char *save, *sp; ! 838: /* ! 839: * in saveUnder mode, we take care to preserve the VGA ! 840: * state we'll mess with during console operations. This ! 841: * consists of the 9 graphics controller registers ! 842: * and 5 sequencer registers in the VGA. ! 843: * We already did this in Init(). ! 844: */ ! 845: ! 846: /* ! 847: * load a default set of registers for mode 12 ! 848: */ ! 849: for(i = 0; i < VGA_NUM_GC_REGS; i++) ! 850: IOWriteRegister(VGA_GC_ADDR,i, defaultGCRegisters[i]); ! 851: ! 852: if (console->isSVGA) { ! 853: char currentSegment = 0; ! 854: ! 855: SaveVGARegs(&console->tempRegisters); ! 856: /* ! 857: * for SVGA, we use read mode 0 and copy the data to ! 858: * a global array, not off-screen display memory as with VGA ! 859: * mode 0x12. ! 860: */ ! 861: console->saveHeight = height + TOTAL_MARGIN * 2; ! 862: console->saveRowBytes = width/8 + ((TOTAL_MARGIN + 7) / 8) * 2; ! 863: console->saveBytes = console->saveHeight*console->saveRowBytes; ! 864: /* saveBits was allocated when we allocated the console */ ! 865: save = console->saveBits; ! 866: ! 867: // Read mode 0 ! 868: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x8, 0x0); ! 869: ! 870: // Copy the window contents into the save under. ! 871: ! 872: // Plane 0. ! 873: IOReadModifyWriteRegister(VGA_GC_ADDR, 4, ~0x3, 0x0); ! 874: ! 875: sp = console->saveLocation = ! 876: (unsigned char *)console->display.frameBuffer + ! 877: (console->window_origin_y - TOTAL_MARGIN) * ! 878: console->display.rowBytes + ! 879: (console->window_origin_x>>3) - 1; ! 880: SVGASelectSegment(currentSegment); ! 881: for (i = console->saveHeight; i != 0; i--) { ! 882: SVGASelectSegmentForAddressIfNecessary(sp, ! 883: ¤tSegment); ! 884: bytemove(save, sp, console->saveRowBytes); ! 885: sp += console->display.rowBytes; ! 886: save += console->saveRowBytes; ! 887: } ! 888: ! 889: // Plane 1. ! 890: IOReadModifyWriteRegister(VGA_GC_ADDR, 4, ~0x3, 0x1); ! 891: sp = console->saveLocation = ! 892: (unsigned char *)console->display.frameBuffer + ! 893: (console->window_origin_y - TOTAL_MARGIN) * ! 894: console->display.rowBytes + ! 895: (console->window_origin_x>>3) - 1; ! 896: for (i = console->saveHeight; i != 0; i--) { ! 897: SVGASelectSegmentForAddressIfNecessary(sp, ! 898: ¤tSegment); ! 899: bytemove(save, sp, console->saveRowBytes); ! 900: sp += console->display.rowBytes; ! 901: save += console->saveRowBytes; ! 902: } ! 903: SVGASelectSegment(currentSegment = 0); ! 904: // restore wr. mode ! 905: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); ! 906: ! 907: RestoreVGARegs(&console->tempRegisters); ! 908: } else { ! 909: /* ! 910: * for vga, we use write mode 1 and copy the data to ! 911: * off-screen memory. We save and extra byte on either side ! 912: * of the popup. ! 913: */ ! 914: console->saveHeight = height + TOTAL_MARGIN * 2; ! 915: console->saveRowBytes = width/8 + ((TOTAL_MARGIN + 7) / 8) * 2; ! 916: console->saveBytes = console->saveHeight*console->saveRowBytes; ! 917: save = console->saveBits; ! 918: ! 919: sp = console->saveLocation = ! 920: (unsigned char *)console->display.frameBuffer + ! 921: (console->window_origin_y - TOTAL_MARGIN) * ! 922: console->display.rowBytes + ! 923: (console->window_origin_x>>3) - 1; ! 924: ! 925: // Copy the window contents into the save under ! 926: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */ ! 927: for (i = console->saveHeight; i != 0; i--) { ! 928: bytemove(save, sp, console->saveRowBytes); ! 929: sp += console->display.rowBytes; ! 930: save += console->saveRowBytes; ! 931: } ! 932: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); /* restore wr. mode*/ ! 933: } ! 934: } ! 935: ! 936: // New window - cursor at origin. ! 937: console->curr_row = 0; ! 938: console->has_title = FALSE; ! 939: ! 940: // Draw the border. The border goes outside of the specified ! 941: // window. Outside lines are black; inside lines are ! 942: // half-tone. ! 943: ! 944: rect(console, // outside top ! 945: console->window_origin_x - TOTAL_MARGIN, ! 946: console->window_origin_y - TOTAL_MARGIN, ! 947: width + TOTAL_MARGIN * 2, ! 948: FG_MARGIN, ! 949: console->foreground); ! 950: rect(console, // inside top ! 951: console->window_origin_x - BG_MARGIN, ! 952: console->window_origin_y - BG_MARGIN, ! 953: width + BG_MARGIN * 2, ! 954: BG_MARGIN, ! 955: console->background); ! 956: rect(console, // inside bottom ! 957: console->window_origin_x - BG_MARGIN, ! 958: console->window_origin_y + height, ! 959: width + BG_MARGIN * 2, ! 960: BG_MARGIN, ! 961: console->background); ! 962: rect(console, // outside bottom ! 963: console->window_origin_x - TOTAL_MARGIN, ! 964: console->window_origin_y + height + BG_MARGIN, ! 965: width + TOTAL_MARGIN * 2, ! 966: FG_MARGIN, ! 967: console->foreground); ! 968: rect(console, // outside left ! 969: console->window_origin_x - TOTAL_MARGIN, ! 970: console->window_origin_y - TOTAL_MARGIN, ! 971: FG_MARGIN, ! 972: height + TOTAL_MARGIN * 2, ! 973: console->foreground); ! 974: rect(console, // inside left ! 975: console->window_origin_x - BG_MARGIN, ! 976: console->window_origin_y - BG_MARGIN, ! 977: BG_MARGIN, ! 978: height + BG_MARGIN * 2, ! 979: console->background); ! 980: rect(console, // inside right ! 981: console->window_origin_x + width, ! 982: console->window_origin_y - BG_MARGIN, ! 983: BG_MARGIN, ! 984: height + BG_MARGIN * 2, ! 985: console->background); ! 986: rect(console, // outside right ! 987: console->window_origin_x + width + BG_MARGIN, ! 988: console->window_origin_y - TOTAL_MARGIN, ! 989: FG_MARGIN, ! 990: height + TOTAL_MARGIN * 2, ! 991: console->foreground); ! 992: ! 993: // Clear the contents of the window and draw a cursor. ! 994: ClearWindow(console); ! 995: FlipCursor(console); // cursor on ! 996: SetTitle(console, title); ! 997: } ! 998: else { ! 999: /* Leave current window contents, just updating title. ! 1000: * We'll do a newline to make sure we have room for ! 1001: * our font and proceed.Initial cursor will be at ! 1002: * lower left corner. ! 1003: */ ! 1004: console->curr_row = console->chars_per_column - 1; ! 1005: SetTitle(console, title); ! 1006: FBPutC(console, '\n'); ! 1007: } ! 1008: return; ! 1009: } ! 1010: ! 1011: // ! 1012: // END: Private utility routines ! 1013: // ! 1014: ! 1015: // ! 1016: // BEGIN: Implementation of IOConsoleInfo functions ! 1017: // ! 1018: static void Free(IOConsoleInfo *cso) ! 1019: // Description: Free a FB Console object ! 1020: { ! 1021: ConsolePtr console = (ConsolePtr)cso->priv; ! 1022: if (console->isSVGA) ! 1023: IOFree(console->saveBits, SVGA_SAVE_BITS); ! 1024: IOFree(console, sizeof(ConsoleRep)); ! 1025: IOFree(cso, sizeof(IOConsoleInfo)); ! 1026: } ! 1027: ! 1028: static void Init( ! 1029: IOConsoleInfo *cso, ! 1030: ScreenMode mode, ! 1031: boolean_t initScreen, ! 1032: boolean_t initWindow, ! 1033: const char *title) ! 1034: { ! 1035: ConsolePtr console = (ConsolePtr)cso->priv; ! 1036: int i; ! 1037: ! 1038: ! 1039: console->background = VGA_WHITE; ! 1040: console->light_grey = VGA_LTGRAY; ! 1041: console->dark_grey = VGA_DKGRAY; ! 1042: console->foreground = VGA_BLACK; ! 1043: console->baseground = console->dark_grey; ! 1044: ! 1045: console->ansi_state = AS_NORMAL; ! 1046: for(i=0; i<ANSI_STACK_SIZE; i++) { ! 1047: console->ansi_stack[i] = 0; ! 1048: } ! 1049: console->ansi_stack_p = &console->ansi_stack[1]; // FIXME - why not 0? ! 1050: ! 1051: // Save these for later in case we need them for Restore(). ! 1052: SaveVGARegs(&console->savedRegisters); ! 1053: ! 1054: // In case the display is not in the mode we want... ! 1055: if ((mode == SCM_TEXT || mode == SCM_GRAPHIC) && initScreen) ! 1056: VGASetGraphicsMode(); ! 1057: ! 1058: // Set up VGA registers the way we want them. ! 1059: // Enable all planes in mask register. ! 1060: IOWriteRegister(VGA_SEQ_ADDR, 2, PLANE_MASK); ! 1061: for(i = 0; i < VGA_NUM_GC_REGS; i++) ! 1062: IOWriteRegister(VGA_GC_ADDR,i, defaultGCRegisters[i]); ! 1063: ! 1064: console->window_type = mode; ! 1065: ! 1066: // Initialize the screen, if appropriate. ! 1067: if (initScreen && (console->window_type != SCM_ALERT)) { ! 1068: WipeScreen(console, console->baseground); ! 1069: } ! 1070: ! 1071: switch(console->window_type) { ! 1072: case SCM_TEXT: ! 1073: InitWindow(console, TEXT_WIN_WIDTH, TEXT_WIN_HEIGHT, ! 1074: title, initWindow, 0 /* Don't save under */); ! 1075: break; ! 1076: case SCM_ALERT: ! 1077: InitWindow(console, ALERT_WIN_WIDTH, ALERT_WIN_HEIGHT, ! 1078: title, initWindow, 1 /* Save under */); ! 1079: break; ! 1080: case SCM_GRAPHIC: ! 1081: /* do nothing */ ! 1082: break; ! 1083: default: ! 1084: panic("VGAConsole/VGAInitConsole: can't init"); ! 1085: } ! 1086: return; ! 1087: } ! 1088: ! 1089: static int Restore(IOConsoleInfo *cso) ! 1090: { ! 1091: ConsolePtr console = (ConsolePtr)cso->priv; ! 1092: unsigned char *save, *dp; ! 1093: int i; ! 1094: ! 1095: if (console->window_type != SCM_ALERT) { ! 1096: IOLog("VGAConsole: bogus restore, mode %d\n", console->window_type); ! 1097: return -1; ! 1098: } ! 1099: ! 1100: if (console->isSVGA) { ! 1101: char currentSegment; ! 1102: ! 1103: // Copy save under bits back onto screen ! 1104: save = console->saveBits; ! 1105: ! 1106: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x0); /* write mode 0 */ ! 1107: IOWriteRegister(VGA_GC_ADDR, 1, 0x0); /* disable set/reset write */ ! 1108: IOWriteRegister(VGA_GC_ADDR, 8, 0xff); /* set pixel mask */ ! 1109: ! 1110: // Plane 0. ! 1111: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x1); /* map mask for plane 0 */ ! 1112: dp = console->saveLocation; ! 1113: SVGASelectSegment(currentSegment = 0); ! 1114: for (i = console->saveHeight; i != 0; i--) { ! 1115: SVGASelectSegmentForAddressIfNecessary(dp, ¤tSegment); ! 1116: bytemove(dp, save, console->saveRowBytes); ! 1117: dp += console->display.rowBytes; ! 1118: save += console->saveRowBytes; ! 1119: } ! 1120: ! 1121: // Plane 1. ! 1122: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x2); /* map mask for plane 1 */ ! 1123: dp = console->saveLocation; ! 1124: for (i = console->saveHeight; i != 0; i--) { ! 1125: SVGASelectSegmentForAddressIfNecessary(dp, ¤tSegment); ! 1126: bytemove(dp, save, console->saveRowBytes); ! 1127: dp += console->display.rowBytes; ! 1128: save += console->saveRowBytes; ! 1129: } ! 1130: SVGASelectSegment(currentSegment = 0); ! 1131: ! 1132: } else { ! 1133: // Copy save under bits back onto screen ! 1134: save = console->saveBits; ! 1135: dp = console->saveLocation; ! 1136: IOReadModifyWriteRegister(VGA_GC_ADDR, 5, ~0x3, 0x1); /* write mode 1 */ ! 1137: for (i = console->saveHeight; i != 0; i--) { ! 1138: bytemove(dp, save, console->saveRowBytes); ! 1139: dp += console->display.rowBytes; ! 1140: save += console->saveRowBytes; ! 1141: } ! 1142: } ! 1143: ! 1144: RestoreVGARegs(&console->savedRegisters); ! 1145: ! 1146: console->window_type = SCM_UNINIT; ! 1147: ! 1148: return 0; ! 1149: } ! 1150: ! 1151: ! 1152: static void ! 1153: vga_write_bpp2packd32_to_bpp4planar(unsigned int *dst, unsigned short *fb) ! 1154: { ! 1155: unsigned int i, dstvalue; ! 1156: unsigned short fbvalue; ! 1157: unsigned char fblo, fbhi; ! 1158: ! 1159: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x02); // select plane 1 ! 1160: ! 1161: dstvalue = *dst; ! 1162: i = dstvalue & 0xAAAA; ! 1163: ! 1164: fblo = 0xff ^ ! 1165: (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) | ! 1166: ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) | ! 1167: ((i & 0x0080) >> 3) | ((i & 0x0020) ) | ! 1168: ((i & 0x0008) << 3) | ((i & 0x0002) << 6)); ! 1169: i = (dstvalue >> 16) & 0xAAAA; ! 1170: fbhi = 0xff ^ ! 1171: (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) | ! 1172: ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) | ! 1173: ((i & 0x0080) >> 3) | ((i & 0x0020) ) | ! 1174: ((i & 0x0008) << 3) | ((i & 0x0002) << 6)); ! 1175: fbvalue = (((unsigned short)fbhi) << 8) | fblo; ! 1176: *fb = fbvalue; ! 1177: ! 1178: IOWriteRegister(VGA_SEQ_ADDR, 2, 0x01); // select plane 0 ! 1179: ! 1180: dstvalue = *dst; ! 1181: i = dstvalue & 0x5555; ! 1182: fblo = 0xff ^ ! 1183: (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) | ! 1184: ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) | ! 1185: ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) | ! 1186: ((i & 0x0004) << 4) | ((i & 0x0001) << 7)); ! 1187: i = (dstvalue >> 16) & 0x5555; ! 1188: fbhi = 0xff ^ ! 1189: (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) | ! 1190: ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) | ! 1191: ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) | ! 1192: ((i & 0x0004) << 4) | ((i & 0x0001) << 7)); ! 1193: fbvalue = (((unsigned short)fbhi) << 8) | fblo; ! 1194: *fb = fbvalue; ! 1195: ! 1196: // restore default plane mask ! 1197: IOWriteRegister(VGA_SEQ_ADDR, 2, PLANE_MASK); ! 1198: } ! 1199: ! 1200: ! 1201: // VGABlitRect blits a rect onto the VGA mode 0x12 screen. ! 1202: // No error checking is done. The screen must be in the proper video ! 1203: // mode, the data must be in 2 bit format, on a 4 pixel boundary, and ! 1204: // a multiple of 4 pixels wide. Anything other than 16 pixel boundaries ! 1205: // is padded with light gray. -sam ! 1206: static int VGABlitRect( ! 1207: IOConsoleInfo *cso, ! 1208: unsigned char *data, ! 1209: struct km_drawrect *rect ! 1210: ) ! 1211: { ! 1212: ConsolePtr console = (ConsolePtr)cso->priv; ! 1213: int pixel; /* Starting pixel in screen */ ! 1214: int i, x, y; ! 1215: unsigned char value; ! 1216: unsigned char *dst = (unsigned char *)console->display.frameBuffer; ! 1217: unsigned short *tfb; ! 1218: unsigned int final_value; ! 1219: int extraLeftBytes; ! 1220: ! 1221: pixel = rect->x + (rect->y * console->display.width); ! 1222: ! 1223: extraLeftBytes = (rect->x % 16) / 4; ! 1224: pixel -= extraLeftBytes * 4; ! 1225: ! 1226: dst += pixel / 8; ! 1227: ! 1228: for ( y = 0; y < rect->height; ++y ) ! 1229: { ! 1230: int bitShift = 30; ! 1231: final_value = 0; ! 1232: ! 1233: tfb = (unsigned short *) dst; ! 1234: for ( x = 0; x < rect->width; ) ! 1235: { ! 1236: if (x == 0) ! 1237: { ! 1238: for (i=0; i<extraLeftBytes; i++) ! 1239: { ! 1240: final_value = final_value << 8; ! 1241: final_value |= 0x55; ! 1242: bitShift -= 8; ! 1243: } ! 1244: } ! 1245: ! 1246: value = *data++; ! 1247: ! 1248: for ( i = 0; i < 8; i += 2 ) ! 1249: { ! 1250: final_value |= (((value>>(6-i)) & 3) << (30-bitShift)); ! 1251: bitShift -= 2; ! 1252: } ! 1253: ! 1254: x += 4; ! 1255: ! 1256: if (bitShift < 0 || x >= rect->width) ! 1257: { ! 1258: for (; bitShift >= 0; bitShift -= 2) ! 1259: final_value |= (0x01 << (30-bitShift)); ! 1260: vga_write_bpp2packd32_to_bpp4planar(&final_value, tfb++); ! 1261: bitShift = 30; ! 1262: final_value = 0; ! 1263: } ! 1264: ! 1265: } ! 1266: dst += 80; ! 1267: } ! 1268: ! 1269: return(0); ! 1270: } ! 1271: ! 1272: /* ! 1273: * DrawRect assumes that the caller has copied in any data from user space, ! 1274: * so this function is safe to call directly during kernel shutdown. ! 1275: */ ! 1276: ! 1277: static int DrawRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect) ! 1278: { ! 1279: ConsolePtr console = (ConsolePtr)cso->priv; ! 1280: long size; // Size in bytes corresponding to a given 2bpp area ! 1281: struct km_drawrect *rect = (struct km_drawrect *) km_rect; ! 1282: int ret = 0; ! 1283: ! 1284: if (console->window_type != SCM_GRAPHIC) { ! 1285: return( -1 ); ! 1286: } ! 1287: ! 1288: /* Sanity check */ ! 1289: if ((rect->width > console->display.width) || ! 1290: (rect->height) > console->display.height) { ! 1291: return( -1 ); ! 1292: } ! 1293: ! 1294: rect->x &= ~3; // Trunc to 4 pixel bound ! 1295: rect->width = (rect->width) & ~3; // Round down for safety ! 1296: ! 1297: size = (rect->width >> 2) * rect->height; /* size in bytes. */ ! 1298: if ( size <= 0 ) ! 1299: return( -1 ); ! 1300: ! 1301: IOWriteRegister(VGA_GC_ADDR, 1, 0x00); ! 1302: VGABlitRect(cso, rect->data.bits, rect); ! 1303: IOWriteRegister(VGA_GC_ADDR, 1, PLANE_MASK); ! 1304: ! 1305: return(ret); ! 1306: } ! 1307: ! 1308: static int EraseRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect) ! 1309: { ! 1310: ConsolePtr console = (ConsolePtr)cso->priv; ! 1311: if (km_rect->x + km_rect->width > console->display.width || ! 1312: km_rect->y + km_rect->height > console->display.height) ! 1313: return -1; ! 1314: rect(console, km_rect->x, km_rect->y, ! 1315: km_rect->width, km_rect->height, 3 - (km_rect->data.fill & 3)); ! 1316: return 0; ! 1317: } ! 1318: ! 1319: static void PutC(IOConsoleInfo *cso, char c) ! 1320: // Write one character to screen. Cursor is 'on' on entry and exit. ! 1321: { ! 1322: FBPutC((ConsolePtr)cso->priv, c); ! 1323: } ! 1324: ! 1325: static void GetSize(IOConsoleInfo *cso, struct ConsoleSize *s) ! 1326: // Return the screen size in pixels. ! 1327: { ! 1328: ConsolePtr console = (ConsolePtr)cso->priv; ! 1329: s->cols = console->chars_per_row; ! 1330: s->rows = console->chars_per_column; ! 1331: s->pixel_width = console->display.width; ! 1332: s->pixel_height = console->display.height; ! 1333: } ! 1334: // ! 1335: // END: Implementation of IOConsoleInfo functions ! 1336: // ! 1337: ! 1338: ! 1339: // ! 1340: // BEGIN: Exported routines ! 1341: // ! 1342: ! 1343: IOConsoleInfo *_VGAAllocateConsole(IODisplayInfo *display, boolean_t isSVGA) ! 1344: { ! 1345: IOConsoleInfo *cso = (IOConsoleInfo *)IOMalloc(sizeof(IOConsoleInfo)); ! 1346: ConsolePtr console = (ConsolePtr)IOMalloc(sizeof(ConsoleRep)); ! 1347: ! 1348: if (cso == NIL) ! 1349: return NIL; ! 1350: cso->priv = console; ! 1351: if (cso->priv == NIL) { ! 1352: IOFree(cso, sizeof(IOConsoleInfo)); ! 1353: return NIL; ! 1354: } ! 1355: cso->Free = Free; ! 1356: cso->Init = Init; ! 1357: cso->Restore = Restore; ! 1358: cso->DrawRect = DrawRect; ! 1359: cso->EraseRect = EraseRect; ! 1360: cso->PutC = PutC; ! 1361: cso->GetSize = GetSize; ! 1362: console->display = *display; ! 1363: console->isSVGA = isSVGA; ! 1364: ! 1365: // Fill in the rest of the display structure... ! 1366: if (isSVGA) { ! 1367: // Until the implementation of bank switching support is complete, ! 1368: // use only top LINESPERBANK lines and thus avoid bank switching. ! 1369: console->display.height = SVGA_LINESPERBANK; ! 1370: console->display.frameBuffer = (void *)FRAMEBUFFER_ADDRESS; ! 1371: console->display.totalWidth = SVGA_TOTALWIDTH; ! 1372: console->display.rowBytes = SVGA_ROWBYTES; ! 1373: console->saveBits = (unsigned char *)IOMalloc(SVGA_SAVE_BITS); ! 1374: if (console->saveBits == NIL) { ! 1375: IOFree(cso, sizeof(IOConsoleInfo)); ! 1376: IOFree(console, sizeof(ConsoleRep)); ! 1377: return NIL; ! 1378: } ! 1379: } else { ! 1380: console->display.frameBuffer = (void *)FRAMEBUFFER_ADDRESS; ! 1381: console->display.totalWidth = VGA_TOTALWIDTH; ! 1382: console->display.rowBytes = VGA_ROWBYTES; ! 1383: console->saveBits = ! 1384: (unsigned char *)console->display.frameBuffer + ! 1385: console->display.rowBytes * console->display.height; ! 1386: } ! 1387: ! 1388: console->window_type = SCM_UNINIT; ! 1389: return cso; ! 1390: } ! 1391: ! 1392: IOConsoleInfo *SVGAAllocateConsole(IODisplayInfo *display) ! 1393: { ! 1394: return _VGAAllocateConsole(display, TRUE); ! 1395: } ! 1396: IOConsoleInfo *VGAAllocateConsole(IODisplayInfo *display) ! 1397: { ! 1398: return _VGAAllocateConsole(display, FALSE); ! 1399: } ! 1400: ! 1401: // ! 1402: // END: Exported routines ! 1403: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.