vga_support.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,450 行 · 第 1/3 页

C
1,450
字号
//==========================================================================////        vga_support.c////        NMI picasso - VGA support////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003 Gary Thomas <gary@mind.be>//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):     gthomas// Contributors:  gthomas// Date:          2001-11-03// Description:   Simple VGA support//####DESCRIPTIONEND#####include <pkgconf/hal.h>#include <cyg/infra/diag.h>#include <cyg/hal/hal_io.h>       // IO macros#include <cyg/hal/hal_if.h>       // Virtual vector support#include <cyg/hal/hal_arch.h>     // Register state info#include <cyg/hal/hal_intr.h>     // HAL interrupt macros#include <cyg/hal/vga_support.h>#include <cyg/hal/hal_cache.h>#include <cyg/hal/plx.h>          // Localbus I/O#include <string.h>#ifdef CYGPKG_ISOINFRA# include <pkgconf/isoinfra.h># ifdef CYGINT_ISO_STDIO_FORMATTED_IO#  include <stdio.h>  // sscanf# endif#endif#ifndef FALSE#define FALSE 0#define TRUE  1#endif// Logical layout#define VGA_WIDTH  640#define VGA_HEIGHT 480#define VGA_DEPTH    8static int bg = 0;static int fg = 1;static struct vga_info vga;struct VGA_ctlr {    unsigned short rev;    unsigned char  enable;    unsigned char  _fill1[13];    struct ADV471 {        unsigned short write_addr;        unsigned short data;        unsigned short pixel_read_mask;        unsigned short read_addr;        unsigned short overlay_data;        unsigned short _fill2[2];        unsigned short overlay_read_addr;    } clut;    unsigned char _fill3[0x100000-0x20];    unsigned char fb[1];};// Compute the location for a pixel within the framebufferstatic cyg_uint8 *vga_fb(int row, int col){    cyg_uint8 *res = (cyg_uint8 *)((char *)vga.fb+(row*vga.rlen)+(col*vga.stride));    return res;}voidvga_on(bool enable){    static bool on = false;    volatile struct VGA_ctlr *ctlr = vga.ctlr;    if (enable) {        if (!on) {            ctlr->enable = 1;        }        on = true;    } else {        ctlr->enable = 0;        on = false;    }}// Initialize VGA hardwarestatic voidvga_set_cmap(volatile struct VGA_ctlr *ctlr, int index,              int red, int green, int blue){    if (index > 255) {        // Invalid index        return;    }    ctlr->clut.write_addr = index;  // Select    ctlr->clut.data = red>>2;    ctlr->clut.data = green>>2;    ctlr->clut.data = blue>>2;}voidvga_init(cyg_uint32 *addr){    volatile struct VGA_ctlr *ctlr;    vga.ctlr = (struct VGA_ctlr *)ctlr = (struct VGA_ctlr *)addr;    vga.fb = ctlr->fb;    vga.bpp = VGA_DEPTH;    vga.height = VGA_HEIGHT;    vga.width = VGA_WIDTH;    vga.rlen = VGA_WIDTH;    vga.stride = 1;    vga.access_size = 1;    vga_set_cmap(ctlr, 0, 0x00, 0x00, 0x00);  // 0 -> black    vga_set_cmap(ctlr, 1, 0xFF, 0xFF, 0xFF);  // 1 -> white//    diag_printf("VGA init at %p/%p\n", vga.ctlr, vga.fb);    ctlr->enable = 1;}// Get information about the frame bufferintvga_getinfo(struct vga_info *info){    if (vga.bpp == 0) {        return 0;  // VGA not initialized    }    *info = vga;    return 1; // Information valid}// Clear screenvoidvga_clear(void){#if 0    cyg_uint32 *fb_row0, *fb_rown;    cyg_uint32 _bg = (bg<<16)|bg;    fb_row0 = vga_fb(0, 0);    fb_rown = vga_fb(vga_height, 0);    while (fb_row0 != fb_rown) {        *fb_row0++ = _bg;    }#endif}#ifdef CYGSEM_UE250_VGA_COMM//// Additional support for VGA/Keyboard as 'console' device//#ifdef CYGOPT_UE250_VGA_COMM_LOGO#include "banner.xpm"#endif#include "font.h"// Virtual screen infostatic int curX = 0;  // Last used positionstatic int curY = 0;//static int width = VGA_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);//static int height = VGA_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);#define SCREEN_PAN            20#define SCREEN_WIDTH          80#define SCREEN_HEIGHT         (VGA_HEIGHT/FONT_HEIGHT)#define VISIBLE_SCREEN_WIDTH  (VGA_WIDTH/FONT_WIDTH)#define VISIBLE_SCREEN_HEIGHT (VGA_HEIGHT/FONT_HEIGHT)static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];static int screen_height = SCREEN_HEIGHT;static int screen_width = SCREEN_WIDTH;static int screen_pan = 0;// Usable area on screen [logical pixel rows]static int screen_start = 0;                       static int screen_end = VGA_HEIGHT/FONT_HEIGHT;static bool cursor_enable = true;// Functionsstatic void vga_drawc(cyg_uint8 c, int x, int y);static __inline__ voidset_pixel(int row, int col, unsigned char val){    unsigned char *pix = (unsigned char *)vga_fb(row, col);    *pix = val;}#ifdef CYGOPT_UE250_VGA_COMM_LOGOstatic int_hexdigit(char c){    if ((c >= '0') && (c <= '9')) {        return c - '0';    } else {        if ((c >= 'A') && (c <= 'F')) {            return (c - 'A') + 0x0A;        } else {            if ((c >= 'a') && (c <= 'f')) {                return (c - 'a') + 0x0a;            }        }    }    return 0;}static int_hex(char *cp){    return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));}static voidparse_color(char *cp, int *red, int *green, int *blue){    *red = *green = *blue = 0xFF;    while (*cp && (*cp != 'c')) cp++;    if (cp) {        cp += 2;        if (*cp == '#') {            *red = _hex(cp+1);            *green = _hex(cp+3);            *blue = _hex(cp+5);        }    }}#ifndef CYGINT_ISO_STDIO_FORMATTED_IOstatic intget_int(unsigned char **_cp){    char *cp = *_cp;    char c;    int val = 0;        while ((c = *cp++) && (c != ' ')) {        if ((c >= '0') && (c <= '9')) {            val = val * 10 + (c - '0');        } else {            return -1;        }    }    *_cp = cp;    return val;}#endifstatic intshow_xpm(char *xpm[], int screen_pos){    int i, row, col, offset;    unsigned char *cp;    int nrows, ncols, nclrs, cwid;    short color_index;    int red, green, blue;//#define HORRIBLY_SLOW_COLOR_MAPPING#ifdef HORRIBLY_SLOW_COLOR_MAPPING    bool color_match;    short cmap[256][2];    int j;#else    // Caution - this is very GIMP specific    short cmap[256][3];  // Enough room for 256 colors    short cmap_col, cmap_row;    unsigned char std_cmap[] = " .+";#endif    cp = xpm[0];#ifdef CYGINT_ISO_STDIO_FORMATTED_IO    if (sscanf(cp, "%d %d %d %d", &ncols, &nrows, &nclrs, &cwid) != 4) {#else    if (((ncols = get_int(&cp)) < 0) ||        ((nrows = get_int(&cp)) < 0) ||        ((nclrs = get_int(&cp)) < 0) ||        ((cwid = get_int(&cp)) < 0)) {#endif        diag_printf("Can't parse XPM data, sorry\n");        return 0;    }//    diag_printf("%d rows, %d cols, %d colors %d chars/pixel\n", nrows, ncols, nclrs, cwid);    if (cwid > 2) {        diag_printf("Color map is too wide - %d\n", cwid);        return 0;    }    for (i = 0;  i < 256;  i++) {#ifdef HORRIBLY_SLOW_COLOR_MAPPING        cmap[i][0] = 0;  cmap[i][1] = 0;#else        cmap[i][0] = 0;  cmap[i][1] = 0;  cmap[i][2] = 0;#endif    }    color_index = 0;    for (i = 0;  i < nclrs;  i++) {        cp = xpm[i+1];#ifdef HORRIBLY_SLOW_COLOR_MAPPING        for (j = 0;  j < cwid;  j++) {            cmap[color_index][j] = cp[j];        }#else        if (cwid == 1) {            cmap_col = 0;        } else {            for (cmap_col = 0;  cmap_col < 3;  cmap_col++) {                if (cp[1] == std_cmap[cmap_col]) {                    break;                }            }        }        cmap_row = *cp;        cmap[cmap_row][cmap_col] = color_index;#endif        parse_color(cp+cwid, &red, &green, &blue);        //        diag_printf("Color[%d] = %02x/%02x/%02x\n", color_index, red, green, blue);        vga_set_cmap(vga.ctlr, color_index+2, red, green, blue);        color_index++;    }#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP    offset = screen_pos;#else    offset = screen_pos-nrows;#endif    for (row = 0;  row < nrows;  row++) {                    cp = xpm[nclrs+1+row];                for (col = 0;  col < ncols;  col++) {#ifdef HORRIBLY_SLOW_COLOR_MAPPING            // Horrible, but portable, way to map colors            for (color_index = 0;  color_index < nclrs;  color_index++) {                color_match = true;                for (j = 0;  j < cwid;  j++) {                    if (cmap[color_index][j] != cp[j]) {                        color_match = false;                    }                }                if (color_match) {                    break;                }            }#else            if (cwid == 1) {                cmap_col = 0;            } else {                for (cmap_col = 0;  cmap_col < 3;  cmap_col++) {                    if (cp[1] == std_cmap[cmap_col]) {                        break;                    }                }            }            cmap_row = *cp;            color_index = cmap[cmap_row][cmap_col];#endif            set_pixel(row+offset, col, color_index+2);            cp += cwid;        }    }#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;    screen_end = VGA_HEIGHT/FONT_HEIGHT;    return offset+nrows;#else        screen_start = 0;    screen_height = offset / FONT_HEIGHT;    screen_end = screen_height;    return offset;#endif}#endifvoidvga_screen_clear(void){    int row, col;#ifdef CYGOPT_UE250_VGA_COMM_LOGO    int pos;#endif    for (row = 0;  row < screen_height;  row++) {        for (col = 0;  col < screen_width;  col++) {            screen[row][col] = ' ';            vga_drawc(' ', col, row);        }    }#ifdef CYGOPT_UE250_VGA_COMM_LOGO    // Note: Row 0 seems to wrap incorrectly#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP    pos = 0;#else    pos = (VGA_HEIGHT-1);#endif    show_xpm(banner_xpm, pos);#endif // CYGOPT_UE250_VGA_COMM_LOGO    curX = 0;  curY = screen_start;    if (cursor_enable) {        vga_drawc(CURSOR_ON, curX-screen_pan, curY);    }}// Position cursorvoidvga_moveto(int X, int Y){    if (cursor_enable) {        vga_drawc(screen[curY][curX], curX-screen_pan, curY);    }    if (X < 0) X = 0;    if (X >= screen_width) X = screen_width-1;    curX = X;    if (Y < screen_start) Y = screen_start;    if (Y >= screen_height) Y = screen_height-1;    curY = Y;    if (cursor_enable) {        vga_drawc(CURSOR_ON, curX-screen_pan, curY);    }}static unsigned long _bitmap[] = {#ifdef FONT_LEFT_TO_RIGHT    0x00000000, 0x01000000, 0x00010000, 0x01010000,    0x00000100, 0x01000100, 0x00010100, 0x01010100,    0x00000001, 0x01000001, 0x00010001, 0x01010001,    0x00000101, 0x01000101, 0x00010101, 0x01010101,#else    0x00000000, 0x00000001, 0x00000100, 0x00000101,    0x00010000, 0x00010001, 0x00010100, 0x00010101,    0x01000000, 0x01000001, 0x01000100, 0x01000101,    0x01010000, 0x01010001, 0x01010100, 0x01010101#endif};// Render a character at position (X,Y) with current background/foregroundstatic voidvga_drawc(cyg_uint8 c, int x, int y){    cyg_uint8 bits;    int l, p;    int xoff, yoff;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?