OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [drivers/] [scr_ecospcsvga.c] - Blame information for rev 365

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//=============================================================================
2
//
3
//      scr_ecospcsvga.c
4
//
5
//      eCos support for a PC display using SVGA/VESA
6
//
7
//=============================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//=============================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    bartv
44
// Date:         2002-04-19
45
// Purpose:      Implement a screen driver for PC's with a VESA video BIOS
46
//
47
//    PC graphics cards are problematical. Many graphic cards are still more
48
//    or less compatible with ancient VGA hardware, but this provides access
49
//    only to rather low resolutions. There is no other hardware compatibility,
50
//    and many different graphics card all needing their own driver.
51
//
52
//    Each graphics card comes with a video BIOS @ 0x000C0000, which can be
53
//    invoked via int 0x10 to do useful operations like querying the
54
//    available video modes and setting the desired one. However the video
55
//    BIOS can normally only be called in x86 real mode, not protected mode,
56
//    Currently eCos only runs in protected mode, and has no support for
57
//    briefly switching back into real mode.
58
//
59
//    Current VESA VBE2 compliant graphics cards do offer some protected
60
//    mode entry points, but not enough to perform mode switches etc.
61
//    VBE3 is supposed to provide additional support for protected mode
62
//    applications, but does not appear to be widely implemented yet.
63
//
64
//    So for now the only solution is to perform the mode switching
65
//    during bootstrap, and specifically inside RedBoot. This is controlled
66
//    by an option in the RedBoot configuration, which has the side
67
//    effect of disabling RedBoot's own use of the screen and keyboard.
68
//    SVGA graphics modes are not completely standardized, so it is the
69
//    user's responsibility to pick a suitable mode.
70
//
71
//    Because RedBoot is a separate application, it is not guaranteed
72
//    that the appropriate mode switch has actually occurred by the
73
//    time this code runs. Therefore RedBoot also places the main SVGA
74
//    info block at location 0x000A0000, normally a window into video
75
//    memory, since that memory is not being used for anything else
76
//    right now. Similarly the mode info block for the current mode
77
//    is placed @ 0x000A0200, and to make it easier to find out what
78
//    modes are available on the current hardware and allow RedBoot to
79
//    be reconfigured appropriately, all the mode info blocks are
80
//    stored @ 0x000A0400 at 256-byte boundaries. The main info block
81
//    can be used to find out which modes are actually available.
82
//
83
//####DESCRIPTIONEND####
84
//=============================================================================
85
 
86
 
87
#include <pkgconf/system.h>
88
#include <pkgconf/microwindows.h>
89
#include <cyg/infra/cyg_ass.h>
90
#include <cyg/infra/diag.h>
91
#include <microwin/device.h>
92
 
93
#define VTSWITCH 0
94
#include "fb.h"
95
#include "genfont.h"
96
#include "genmem.h"
97
 
98
// ----------------------------------------------------------------------------
99
// Information about the current mode and all available video modes,
100
// should have been provided by RedBoot.
101
struct VBESVGAInfoBlock {
102
    unsigned char   signature[4];      /* VESA */
103
    unsigned short  version;
104
    char*           oem_string_ptr;
105
    unsigned char   capabilities[4];
106
    unsigned short* video_mode_ptr;
107
    unsigned short  total_memory;
108
    unsigned short  oem_software_rev;
109
    char*           oem_vendor_name_ptr;
110
    char*           oem_product_name_ptr;
111
    char*           oem_product_rev_ptr;
112
    /* Reserved data here */
113
} __attribute__((packed));
114
 
115
struct VBEModeInfoBlock {
116
    unsigned short  mode_attributes;
117
    unsigned char   win_a_atributes;
118
    unsigned char   win_b_attributes;
119
    unsigned short  win_granularity;
120
    unsigned short  win_size;
121
    unsigned short  win_a_segment;
122
    unsigned short  win_b_segment;
123
    unsigned int    win_func_ptr;
124
    unsigned short  bytes_per_scanline;
125
    unsigned short  x_resolution;
126
    unsigned short  y_resolution;
127
    unsigned char   x_char_size;
128
    unsigned char   y_char_size;
129
    unsigned char   number_of_planes;
130
    unsigned char   bits_per_pixel;
131
    unsigned char   number_of_banks;
132
    unsigned char   memory_model;
133
    unsigned char   bank_size;
134
    unsigned char   number_of_image_pages;
135
    unsigned char   reserved;
136
    unsigned char   red_mask_size;
137
    unsigned char   red_field_position;
138
    unsigned char   green_mask_size;
139
    unsigned char   green_field_position;
140
    unsigned char   blue_mask_size;
141
    unsigned char   blue_field_position;
142
    unsigned char   reserved_mask_size;
143
    unsigned char   reserved_field_position;
144
    unsigned char   direct_color_mode_info;
145
    void*           physical_base_ptr;
146
    unsigned int    offscreen_memory_offset;
147
    unsigned short  offscreen_memory_size;
148
} __attribute__((packed));
149
 
150
#if defined(CYGDBG_MICROWINDOWS_PCSVGA_VERBOSE)
151
static void*
152
segoff_to_phys(void* addr)
153
{
154
    int x       = (int) addr;
155
    int segment = (x >> 12) & 0x0FFFF0;
156
    int offset  = x & 0x0FFFF;
157
    return (void*) (segment | offset);
158
}
159
#endif
160
 
161
// ----------------------------------------------------------------------------
162
static PSD  ecos_pcsvga_open(PSD);
163
static void ecos_pcsvga_close(PSD);
164
static void ecos_pcsvga_setportrait(PSD, int);
165
static void ecos_pcsvga_setpalette(PSD, int, int, MWPALENTRY*);
166
static void ecos_pcsvga_getscreeninfo(PSD , PMWSCREENINFO);
167
 
168
SCREENDEVICE scrdev = {
169
    xres:               0,
170
    yres:               0,
171
    xvirtres:           0,
172
    yvirtres:           0,
173
    planes:             1,
174
    linelen:            0,
175
    size:               0,
176
#if defined(CYGIMP_MICROWINDOWS_PCSVGA32)
177
    bpp:                32,
178
    ncolors:            1 << 24,
179
    pixtype:            MWPF_TRUECOLOR0888,
180
#elif defined(CYGIMP_MICROWINDOWS_PCSVGA16)
181
    bpp:                16,
182
    ncolors:            1 << 16,
183
    pixtype:            MWPF_TRUECOLOR565,
184
#else
185
# error Unsupported video mode.    
186
#endif    
187
    flags:              PSF_SCREEN | PSF_HAVEBLIT,
188
    addr:               0,
189
 
190
    Open:               &ecos_pcsvga_open,
191
    Close:              &ecos_pcsvga_close,
192
    GetScreenInfo:      &ecos_pcsvga_getscreeninfo,
193
    SetPalette:         &ecos_pcsvga_setpalette,
194
    DrawPixel:          NULL,
195
    ReadPixel:          NULL,
196
    DrawHorzLine:       NULL,
197
    DrawVertLine:       NULL,
198
    FillRect:           NULL,
199
    builtin_fonts:      gen_fonts,
200
    Blit:               NULL,
201
    PreSelect:          NULL,
202
    DrawArea:           NULL,
203
    SetIOPermissions:   NULL,
204
    AllocateMemGC:      &gen_allocatememgc,
205
    MapMemGC:           &fb_mapmemgc,
206
    FreeMemGC:          &gen_freememgc,
207
    StretchBlit:        NULL,
208
    SetPortrait:        &ecos_pcsvga_setportrait,
209
    portrait:           MWPORTRAIT_NONE,
210
    orgsubdriver:       NULL
211
};
212
 
213
static PSD
214
ecos_pcsvga_open(PSD psd)
215
{
216
    struct VBESVGAInfoBlock*    vesa_info_block;
217
    struct VBEModeInfoBlock*    vesa_current_mode;
218
 
219
    // Detect repeated invocations. The information in the video
220
    // memory will be blown away after the first call, so can
221
    // only be consulted once.
222
    static int  opened  = 0;
223
    static PSD  result  = NULL;
224
    if (opened) {
225
        return result;
226
    }
227
    opened = 1;
228
 
229
    // First make sure that there is valid video information in video
230
    // memory, i.e. that the system was booted by means of a suitable
231
    // RedBoot instance, that nothing has overwritten video memory
232
    // yet, and that we are running at the desired screen depth.
233
    vesa_info_block   = (struct VBESVGAInfoBlock*) 0x000A0000;
234
    vesa_current_mode = (struct VBEModeInfoBlock*) 0x000A0200;
235
    if (('V' != vesa_info_block->signature[0]) || ('E' != vesa_info_block->signature[1]) ||
236
        ('S' != vesa_info_block->signature[2]) || ('A' != vesa_info_block->signature[3])) {
237
        EPRINTF("No Video BIOS information at location 0x000A0000\n"
238
                "Please use a suitably configured RedBoot for bootstrap\n");
239
        return NULL;
240
    }
241
 
242
    // Optionally, provide lots of information about the graphics card,
243
    // the various modes available, and the current mode.
244
#ifdef CYGDBG_MICROWINDOWS_PCSVGA_VERBOSE
245
    {
246
        diag_printf("VESA info: %c%c%c%c\n", vesa_info_block->signature[0], vesa_info_block->signature[1],
247
                    vesa_info_block->signature[2], vesa_info_block->signature[3]);
248
        diag_printf("Version %04x\n", vesa_info_block->version);
249
        if (NULL != vesa_info_block->oem_string_ptr) {
250
            vesa_info_block->oem_string_ptr = segoff_to_phys(vesa_info_block->oem_string_ptr);
251
            diag_printf("OEM %s\n", vesa_info_block->oem_string_ptr);
252
        }
253
        diag_printf("Total memory %dK\n", 64 * vesa_info_block->total_memory);
254
        diag_printf("OEM software rev %04x\n", vesa_info_block->oem_software_rev);
255
        if (NULL != vesa_info_block->oem_vendor_name_ptr) {
256
            vesa_info_block->oem_vendor_name_ptr = segoff_to_phys(vesa_info_block->oem_vendor_name_ptr);
257
            diag_printf("OEM vendor %s\n", vesa_info_block->oem_vendor_name_ptr);
258
        }
259
        if (NULL != vesa_info_block->oem_product_name_ptr) {
260
            vesa_info_block->oem_product_name_ptr = segoff_to_phys(vesa_info_block->oem_product_name_ptr);
261
            diag_printf("OEM product name %s\n", vesa_info_block->oem_product_name_ptr);
262
        }
263
        if (NULL != vesa_info_block->oem_product_rev_ptr) {
264
            vesa_info_block->oem_product_rev_ptr = segoff_to_phys(vesa_info_block->oem_product_rev_ptr);
265
            diag_printf("OEM product revision %s\n", vesa_info_block->oem_product_rev_ptr);
266
        }
267
        diag_printf("Capabilities: %02x, %02x, %02x, %02x\n",
268
                    vesa_info_block->capabilities[0], vesa_info_block->capabilities[1],
269
                    vesa_info_block->capabilities[2], vesa_info_block->capabilities[3]);
270
        vesa_info_block->video_mode_ptr = (unsigned short*) segoff_to_phys((char*) vesa_info_block->video_mode_ptr);
271
        for (i = 0; 0x0FFFF != vesa_info_block->video_mode_ptr[i]; i++) {
272
            int mode = vesa_info_block->video_mode_ptr[i];
273
            struct VBEModeInfoBlock*   mode_data   = (struct VBEModeInfoBlock*) (0x0A0400 + (0x100 * i));
274
            diag_printf("Mode %04x: %4d*%4d @ %2dbpp, %4d bytes/line, fb %s 0x%08x\n", mode,
275
                        mode_data->x_resolution, mode_data->y_resolution, mode_data->bits_per_pixel,
276
                        mode_data->bytes_per_scanline,
277
                        (0 == (mode_data->mode_attributes & 0x0080)) ? "no " : "yes",
278
                        mode_data->physical_base_ptr);
279
            if (32 == mode_data->bits_per_pixel) {
280
                diag_printf("    red %d bits << %d, green %d bits << %d, blue %d bits << %d, reserved %d bits << %d\n",
281
                            mode_data->red_mask_size, mode_data->red_field_position,
282
                            mode_data->green_mask_size, mode_data->green_field_position,
283
                            mode_data->blue_mask_size, mode_data->blue_field_position,
284
                            mode_data->reserved_mask_size, mode_data->reserved_field_position);
285
            }
286
        }
287
 
288
        diag_printf("Current mode: %4d*%4d @ %2dbpp, %4d bytes/line, fb %s 0x%08x\n",
289
                    vesa_current_mode->x_resolution, vesa_current_mode->y_resolution, vesa_current_mode->bits_per_pixel,
290
                    vesa_current_mode->bytes_per_scanline,
291
                    (0 == (vesa_current_mode->mode_attributes & 0x0080)) ? "no" : "yes",
292
                    vesa_current_mode->physical_base_ptr);
293
        if (32 == vesa_current_mode->bits_per_pixel) {
294
            diag_printf("    red %d bits << %d, green %d bits << %d, blue %d bits << %d, reserved %d bits << %d\n",
295
                        vesa_current_mode->red_mask_size, vesa_current_mode->red_field_position,
296
                        vesa_current_mode->green_mask_size, vesa_current_mode->green_field_position,
297
                        vesa_current_mode->blue_mask_size, vesa_current_mode->blue_field_position,
298
                        vesa_current_mode->reserved_mask_size, vesa_current_mode->reserved_field_position);
299
        }
300
    }
301
#endif
302
 
303
#if defined(CYGIMP_MICROWINDOWS_PCSVGA32)    
304
    // A 32-bit displays, 0888
305
    if ((32 != vesa_current_mode->bits_per_pixel) ||
306
        (8 != vesa_current_mode->red_mask_size)   || (16 != vesa_current_mode->red_field_position) ||
307
        (8 != vesa_current_mode->green_mask_size) || ( 8 != vesa_current_mode->green_field_position) ||
308
        (8 != vesa_current_mode->blue_mask_size)  || ( 0 != vesa_current_mode->blue_field_position)) {
309
 
310
        EPRINTF("RedBoot has not set up a valid initial graphics mode.\n"
311
                "This screen driver requires 32 bits per pixel, 0RGB.\n",
312
                "Configuration option CYGDBG_MICROWINDOWS_PCSVGA_VERBOSE can be used to\n"
313
                "get information about the available video modes.\n");
314
        return NULL;
315
    }
316
#elif defined(CYGIMP_MICROWINDOWS_PCSVGA16)
317
    // A 16-bit display, 565
318
    if ((16 != vesa_current_mode->bits_per_pixel) ||
319
        (5 != vesa_current_mode->red_mask_size)   || (11 != vesa_current_mode->red_field_position) ||
320
        (6 != vesa_current_mode->green_mask_size) || ( 5 != vesa_current_mode->green_field_position) ||
321
        (5 != vesa_current_mode->blue_mask_size)  || ( 0 != vesa_current_mode->blue_field_position)) {
322
 
323
        EPRINTF("RedBoot has not set up a valid initial graphics mode.\n"
324
                "This screen driver requires 16 bits per pixel, RGB=565.\n",
325
                "Configuration option CYGDBG_MICROWINDOWS_PCSVGA_VERBOSE can be used to\n"
326
                "get information about the available video modes.\n");
327
        return NULL;
328
    }
329
#endif
330
 
331
    if ((0 == (vesa_current_mode->mode_attributes & 0x0080)) || (NULL == vesa_current_mode->physical_base_ptr)) {
332
        EPRINTF("RedBoot has not set up a valid initial graphics mode.\n"
333
                "The frame buffer is not linearly accessible.\n");
334
        return NULL;
335
    }
336
 
337
 
338
    // OK, we are at the expected depth. Fill in the resolution etc. based
339
    // on the current video mode.
340
    psd->xres       = vesa_current_mode->x_resolution;
341
    psd->yres       = vesa_current_mode->y_resolution;
342
    psd->xvirtres   = vesa_current_mode->x_resolution;
343
    psd->yvirtres   = vesa_current_mode->y_resolution;
344
    psd->linelen    = vesa_current_mode->bytes_per_scanline;
345
    psd->addr       = vesa_current_mode->physical_base_ptr;
346
    // The remaining parameters in the structure are statically
347
    // initialized for now, e.g. 32bpp, pixtype TRUECOLOR0888
348
 
349
    // Use one of the standard framebuffer subdrivers.
350
    psd->orgsubdriver  = select_fb_subdriver(psd);
351
    if (NULL == psd->orgsubdriver) {
352
        EPRINTF("There is no standard framebuffer driver for the current video mode.\n");
353
        return NULL;
354
    }
355
    if (!set_subdriver(psd, psd->orgsubdriver, TRUE)) {
356
        EPRINTF("Framebuffer subdriver initialization failed.\n");
357
        return NULL;
358
    }
359
 
360
    // That should be all for now.
361
    result = psd;
362
    return result;
363
}
364
 
365
// Close is a no-op, no resources have been allocated.
366
// The open() code detects multiple invocations.
367
static void
368
ecos_pcsvga_close(PSD psd)
369
{
370
    CYG_UNUSED_PARAM(PSD, psd);
371
}
372
 
373
// Setting the palette is a no-op for now since only true color
374
// modes are supported.
375
static void
376
ecos_pcsvga_setpalette(PSD psd, int first, int count, MWPALENTRY* pal)
377
{
378
    CYG_UNUSED_PARAM(PSD, psd);
379
    CYG_UNUSED_PARAM(int, first);
380
    CYG_UNUSED_PARAM(int, count);
381
    CYG_UNUSED_PARAM(MWPALENTRY*, pal);
382
}
383
 
384
// Setting the portrait mode. There are standard subdrivers to
385
// cope with this, manipulating the arguments and then calling
386
// the original subdriver.
387
 
388
extern SUBDRIVER fbportrait_left, fbportrait_right, fbportrait_down;
389
 
390
static void
391
ecos_pcsvga_setportrait(PSD psd, int portrait_mode)
392
{
393
    psd->portrait   = portrait_mode;
394
    if (portrait_mode & (MWPORTRAIT_LEFT | MWPORTRAIT_RIGHT)) {
395
        psd->xvirtres   = psd->yres;
396
        psd->yvirtres   = psd->xres;
397
    } else {
398
        psd->xvirtres   = psd->xres;
399
        psd->yvirtres   = psd->yres;
400
    }
401
 
402
    if (portrait_mode == MWPORTRAIT_LEFT) {
403
        set_subdriver(psd, &fbportrait_left, FALSE);
404
    } else if (portrait_mode == MWPORTRAIT_RIGHT) {
405
        set_subdriver(psd, &fbportrait_right, FALSE);
406
    } else if (portrait_mode == MWPORTRAIT_DOWN) {
407
        set_subdriver(psd, &fbportrait_down, FALSE);
408
    } else {
409
        set_subdriver(psd, psd->orgsubdriver, FALSE);
410
    }
411
}
412
 
413
// Getting screen info. It is not clear why this is part of the driver
414
// since nearly all the information is already available in psd.
415
static void
416
ecos_pcsvga_getscreeninfo(PSD psd, PMWSCREENINFO psi)
417
{
418
    psi->rows       = psd->yvirtres;
419
    psi->cols       = psd->xvirtres;
420
    psi->planes     = psd->planes;
421
    psi->bpp        = psd->bpp;
422
    psi->ncolors    = psd->ncolors;
423
    psi->portrait   = psd->portrait;
424
    psi->fbdriver   = TRUE;
425
    psi->pixtype    = psd->pixtype;
426
#if defined(CYGIMP_MICROWINDOWS_PCSVGA32)
427
    psi->rmask      = 0x00FF0000;
428
    psi->gmask      = 0x0000FF00;
429
    psi->bmask      = 0x000000FF;
430
#elif defined(CYGIMP_MICROWINDOWS_PCSVGA16)
431
    psi->rmask      = 0x0000F800;
432
    psi->gmask      = 0x000007E0;
433
    psi->bmask      = 0x0000001F;
434
#endif    
435
 
436
    // The screen dimensions are not readily available.
437
    // Assume an 18' monitor (actual visible diameter),
438
    // which corresponds ~ to 36cm by 28cm
439
    psi->xdpcm      = psd->xres / 36;
440
    psi->ydpcm      = psd->yres / 28;
441
 
442
    psi->fonts      = NUMBER_FONTS;
443
 
444
    // Remaining information such as keyboard modifiers etc. cannot be
445
    // known here.
446
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.