Annotation of kernel/bsd/dev/i386/VGAConsole.c, revision 1.1.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.