Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/drivers/video/vesa.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * vesa.c
3
 *
4
 * VESA linear frame buffer handling.
5
 */
6
7
#include <xen/init.h>
8
#include <xen/lib.h>
9
#include <xen/xmalloc.h>
10
#include <xen/kernel.h>
11
#include <xen/vga.h>
12
#include <asm/io.h>
13
#include <asm/page.h>
14
#include "font.h"
15
#include "lfb.h"
16
17
0
#define vlfb_info    vga_console_info.u.vesa_lfb
18
19
static void lfb_flush(void);
20
21
static unsigned char *lfb;
22
static const struct font_desc *font;
23
static bool_t vga_compat;
24
25
static unsigned int vram_total;
26
integer_param("vesa-ram", vram_total);
27
28
static unsigned int vram_remap;
29
integer_param("vesa-map", vram_remap);
30
31
static int font_height;
32
static int __init parse_font_height(const char *s)
33
0
{
34
0
    if ( simple_strtoul(s, &s, 10) == 8 && (*s++ == 'x') )
35
0
        font_height = simple_strtoul(s, &s, 10);
36
0
    if ( *s != '\0' )
37
0
        font_height = 0;
38
0
39
0
    return 0;
40
0
}
41
custom_param("font", parse_font_height);
42
43
void __init vesa_early_init(void)
44
0
{
45
0
    unsigned int vram_vmode;
46
0
47
0
    vga_compat = !(vga_console_info.u.vesa_lfb.gbl_caps & 2);
48
0
49
0
    if ( (vlfb_info.bits_per_pixel < 8) || (vlfb_info.bits_per_pixel > 32) )
50
0
        return;
51
0
52
0
    if ( font_height == 0 ) /* choose a sensible default */
53
0
        font = ((vlfb_info.height <= 600) ? &font_vga_8x8 :
54
0
                (vlfb_info.height <= 768) ? &font_vga_8x14 : &font_vga_8x16);
55
0
    else if ( font_height <= 8 )
56
0
        font = &font_vga_8x8;
57
0
    else if ( font_height <= 14 )
58
0
        font = &font_vga_8x14;
59
0
    else
60
0
        font = &font_vga_8x16;
61
0
62
0
    /*   vram_vmode -- that is the amount of memory needed for the
63
0
     *                 used video mode, i.e. the minimum amount of
64
0
     *                 memory we need. */
65
0
    vram_vmode = vlfb_info.height * vlfb_info.bytes_per_line;
66
0
67
0
    /*   vram_total -- all video memory we have. Used for mtrr
68
0
     *                 entries. */
69
0
    vram_total = vram_total ? (vram_total << 20) : (vlfb_info.lfb_size << 16);
70
0
    vram_total = max_t(unsigned int, vram_total, vram_vmode);
71
0
72
0
    /*   vram_remap -- the amount of video memory we are going to
73
0
     *                 use for vesafb.  With modern cards it is no
74
0
     *                 option to simply use vram_total as that
75
0
     *                 wastes plenty of kernel address space. */
76
0
    vram_remap = (vram_remap ?
77
0
                  (vram_remap << 20) :
78
0
                  ((vram_vmode + (1 << L2_PAGETABLE_SHIFT) - 1) &
79
0
                   ~((1 << L2_PAGETABLE_SHIFT) - 1)));
80
0
    vram_remap = max_t(unsigned int, vram_remap, vram_vmode);
81
0
    vram_remap = min_t(unsigned int, vram_remap, vram_total);
82
0
}
83
84
void __init vesa_init(void)
85
1
{
86
1
    struct lfb_prop lfbp;
87
1
88
1
    if ( !font )
89
1
        return;
90
1
91
0
    lfbp.font = font;
92
0
    lfbp.bits_per_pixel = vlfb_info.bits_per_pixel;
93
0
    lfbp.bytes_per_line = vlfb_info.bytes_per_line;
94
0
    lfbp.width = vlfb_info.width;
95
0
    lfbp.height = vlfb_info.height;
96
0
    lfbp.flush = lfb_flush;
97
0
    lfbp.text_columns = vlfb_info.width / font->width;
98
0
    lfbp.text_rows = vlfb_info.height / font->height;
99
0
100
0
    lfbp.lfb = lfb = ioremap(vlfb_info.lfb_base, vram_remap);
101
0
    if ( !lfb )
102
0
        return;
103
0
104
0
    memset(lfb, 0, vram_remap);
105
0
106
0
    printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, "
107
0
           "using %uk, total %uk\n",
108
0
           vlfb_info.lfb_base, lfb,
109
0
           vram_remap >> 10, vram_total >> 10);
110
0
    printk(XENLOG_INFO "vesafb: mode is %dx%dx%u, linelength=%d, font %ux%u\n",
111
0
           vlfb_info.width, vlfb_info.height,
112
0
           vlfb_info.bits_per_pixel, vlfb_info.bytes_per_line,
113
0
           font->width, font->height);
114
0
    printk(XENLOG_INFO "vesafb: %scolor: size=%d:%d:%d:%d, "
115
0
           "shift=%d:%d:%d:%d\n",
116
0
           vlfb_info.bits_per_pixel > 8 ? "True" :
117
0
           vga_compat ? "Pseudo" : "Static Pseudo",
118
0
           vlfb_info.rsvd_size, vlfb_info.red_size,
119
0
           vlfb_info.green_size, vlfb_info.blue_size,
120
0
           vlfb_info.rsvd_pos, vlfb_info.red_pos,
121
0
           vlfb_info.green_pos, vlfb_info.blue_pos);
122
0
123
0
    if ( vlfb_info.bits_per_pixel > 8 )
124
0
    {
125
0
        /* Light grey in truecolor. */
126
0
        unsigned int grey = 0xaaaaaaaa;
127
0
        lfbp.pixel_on =
128
0
            ((grey >> (32 - vlfb_info.  red_size)) << vlfb_info.  red_pos) |
129
0
            ((grey >> (32 - vlfb_info.green_size)) << vlfb_info.green_pos) |
130
0
            ((grey >> (32 - vlfb_info. blue_size)) << vlfb_info. blue_pos);
131
0
    }
132
0
    else
133
0
    {
134
0
        /* White(ish) in default pseudocolor palette. */
135
0
        lfbp.pixel_on = 7;
136
0
    }
137
0
138
0
    if ( lfb_init(&lfbp) < 0 )
139
0
        return;
140
0
    video_puts = lfb_redraw_puts;
141
0
}
142
143
#include <asm/mtrr.h>
144
145
static unsigned int vesa_mtrr;
146
integer_param("vesa-mtrr", vesa_mtrr);
147
148
void __init vesa_mtrr_init(void)
149
1
{
150
1
    static const int mtrr_types[] = {
151
1
        0, MTRR_TYPE_UNCACHABLE, MTRR_TYPE_WRBACK,
152
1
        MTRR_TYPE_WRCOMB, MTRR_TYPE_WRTHROUGH };
153
1
    unsigned int size_total;
154
1
    int rc, type;
155
1
156
1
    if ( !lfb || (vesa_mtrr == 0) || (vesa_mtrr >= ARRAY_SIZE(mtrr_types)) )
157
1
        return;
158
1
159
0
    type = mtrr_types[vesa_mtrr];
160
0
    if ( !type )
161
0
        return;
162
0
163
0
    /* Find the largest power-of-two */
164
0
    size_total = vram_total;
165
0
    while ( size_total & (size_total - 1) )
166
0
        size_total &= size_total - 1;
167
0
168
0
    /* Try and find a power of two to add */
169
0
    do {
170
0
        rc = mtrr_add(vlfb_info.lfb_base, size_total, type, 1);
171
0
        size_total >>= 1;
172
0
    } while ( (size_total >= PAGE_SIZE) && (rc == -EINVAL) );
173
0
}
174
175
static void lfb_flush(void)
176
0
{
177
0
    if ( vesa_mtrr == 3 )
178
0
        __asm__ __volatile__ ("sfence" : : : "memory");
179
0
}
180
181
void __init vesa_endboot(bool_t keep)
182
0
{
183
0
    if ( keep )
184
0
    {
185
0
        video_puts = lfb_scroll_puts;
186
0
        lfb_carriage_return();
187
0
    }
188
0
    else
189
0
    {
190
0
        unsigned int i, bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
191
0
        for ( i = 0; i < vlfb_info.height; i++ )
192
0
            memset(lfb + i * vlfb_info.bytes_per_line, 0,
193
0
                   vlfb_info.width * bpp);
194
0
        lfb_flush();
195
0
        lfb_free();
196
0
    }
197
0
}