Annotation of kernel/bsd/dev/i386/VGAConsole.c, revision 1.1

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:                           &currentSegment);
        !           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:                           &currentSegment);
        !           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, &currentSegment);
        !          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, &currentSegment);
        !          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: //

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.