source: mainline/genarch/src/fb/fb.c@ 0ee077ee

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0ee077ee was c1982e45, checked in by Martin Decky <martin@…>, 19 years ago

make hardware memory mapping more generic

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * Copyright (C) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <genarch/fb/font-8x16.h>
30#include <genarch/fb/fb.h>
31#include <console/chardev.h>
32#include <console/console.h>
33#include <sysinfo/sysinfo.h>
34#include <mm/slab.h>
35#include <align.h>
36#include <panic.h>
37#include <memstr.h>
38#include <config.h>
39
40#include "helenos.xbm"
41
42SPINLOCK_INITIALIZE(fb_lock);
43
44static __u8 *fbaddress = NULL;
45
46static __u8 *blankline = NULL;
47
48static unsigned int xres = 0;
49static unsigned int yres = 0;
50static unsigned int scanline = 0;
51static unsigned int bitspp = 0;
52static unsigned int pixelbytes = 0;
53
54static unsigned int position = 0;
55static unsigned int columns = 0;
56static unsigned int rows = 0;
57
58
59#define COL_WIDTH 8
60#define ROW_BYTES (scanline * FONT_SCANLINES)
61
62#define BGCOLOR 0x000080
63#define FGCOLOR 0xffff00
64#define LOGOCOLOR 0x2020b0
65
66#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
67#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
68#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
69
70#define POINTPOS(x, y) (y * scanline + x * pixelbytes)
71
72/***************************************************************/
73/* Pixel specific fuctions */
74
75static void (*putpixel)(unsigned int x, unsigned int y, int color);
76static int (*getpixel)(unsigned int x, unsigned int y);
77
78/** Put pixel - 24-bit depth, 1 free byte */
79static void putpixel_4byte(unsigned int x, unsigned int y, int color)
80{
81 *((__u32 *)(fbaddress + POINTPOS(x, y))) = color;
82}
83
84/** Return pixel color - 24-bit depth, 1 free byte */
85static int getpixel_4byte(unsigned int x, unsigned int y)
86{
87 return *((__u32 *)(fbaddress + POINTPOS(x, y))) & 0xffffff;
88}
89
90/** Put pixel - 24-bit depth */
91static void putpixel_3byte(unsigned int x, unsigned int y, int color)
92{
93 unsigned int startbyte = POINTPOS(x, y);
94
95#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
96 fbaddress[startbyte] = RED(color, 8);
97 fbaddress[startbyte + 1] = GREEN(color, 8);
98 fbaddress[startbyte + 2] = BLUE(color, 8);
99#else
100 fbaddress[startbyte + 2] = RED(color, 8);
101 fbaddress[startbyte + 1] = GREEN(color, 8);
102 fbaddress[startbyte + 0] = BLUE(color, 8);
103#endif
104}
105
106/** Return pixel color - 24-bit depth */
107static int getpixel_3byte(unsigned int x, unsigned int y)
108{
109 unsigned int startbyte = POINTPOS(x, y);
110
111#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
112 return fbaddress[startbyte] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 2];
113#else
114 return fbaddress[startbyte + 2] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 0];
115#endif
116}
117
118/** Put pixel - 16-bit depth (5:6:6) */
119static void putpixel_2byte(unsigned int x, unsigned int y, int color)
120{
121 /* 5-bit, 5-bits, 5-bits */
122 *((__u16 *)(fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
123}
124
125/** Return pixel color - 16-bit depth (5:6:6) */
126static int getpixel_2byte(unsigned int x, unsigned int y)
127{
128 int color = *((__u16 *)(fbaddress + POINTPOS(x, y)));
129 return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
130}
131
132/** Put pixel - 8-bit depth (3:2:3) */
133static void putpixel_1byte(unsigned int x, unsigned int y, int color)
134{
135 fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
136}
137
138/** Return pixel color - 8-bit depth (3:2:3) */
139static int getpixel_1byte(unsigned int x, unsigned int y)
140{
141 int color = fbaddress[POINTPOS(x, y)];
142 return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
143}
144
145/** Fill line with color BGCOLOR */
146static void clear_line(unsigned int y)
147{
148 unsigned int x;
149
150 for (x = 0; x < xres; x++)
151 (*putpixel)(x, y, BGCOLOR);
152}
153
154
155/** Fill screen with background color */
156static void clear_screen(void)
157{
158 unsigned int y;
159
160 for (y = 0; y < yres; y++)
161 clear_line(y);
162}
163
164
165/** Scroll screen one row up */
166static void scroll_screen(void)
167{
168 unsigned int i;
169 __u8 *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
170
171 memcpy((void *) fbaddress, (void *) &fbaddress[ROW_BYTES], scanline * yres - ROW_BYTES);
172
173 /* Clear last row */
174 if (blankline) {
175 memcpy((void *) lastline, (void *) blankline, ROW_BYTES);
176 } else {
177 for (i = 0; i < FONT_SCANLINES; i++)
178 clear_line((rows - 1) * FONT_SCANLINES + i);
179
180 if (config.mm_initialized) {
181 /* Save a blank line aside. */
182 blankline = (__u8 *) malloc(ROW_BYTES, FRAME_ATOMIC);
183 if (blankline)
184 memcpy((void *) blankline, (void *) lastline, ROW_BYTES);
185 }
186 }
187}
188
189
190static void invert_pixel(unsigned int x, unsigned int y)
191{
192 (*putpixel)(x, y, ~(*getpixel)(x, y));
193}
194
195
196/** Draw one line of glyph at a given position */
197static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
198{
199 unsigned int i;
200
201 for (i = 0; i < 8; i++)
202 if (glline & (1 << (7 - i))) {
203 (*putpixel)(x + i, y, FGCOLOR);
204 } else
205 (*putpixel)(x + i, y, BGCOLOR);
206}
207
208/***************************************************************/
209/* Character-console functions */
210
211/** Draw character at given position */
212static void draw_glyph(__u8 glyph, unsigned int col, unsigned int row)
213{
214 unsigned int y;
215
216 for (y = 0; y < FONT_SCANLINES; y++)
217 draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
218}
219
220/** Invert character at given position */
221static void invert_char(unsigned int col, unsigned int row)
222{
223 unsigned int x;
224 unsigned int y;
225
226 for (x = 0; x < COL_WIDTH; x++)
227 for (y = 0; y < FONT_SCANLINES; y++)
228 invert_pixel(col * COL_WIDTH + x, row * FONT_SCANLINES + y);
229}
230
231/** Draw character at default position */
232static void draw_char(char chr)
233{
234 draw_glyph(chr, position % columns, position / columns);
235}
236
237static void draw_logo(unsigned int startx, unsigned int starty)
238{
239 unsigned int x;
240 unsigned int y;
241 unsigned int byte;
242 unsigned int rowbytes;
243
244 rowbytes = (helenos_width - 1) / 8 + 1;
245
246 for (y = 0; y < helenos_height; y++)
247 for (x = 0; x < helenos_width; x++) {
248 byte = helenos_bits[rowbytes * y + x / 8];
249 byte >>= x % 8;
250 if (byte & 1)
251 (*putpixel)(startx + x, starty + y, LOGOCOLOR);
252 }
253}
254
255/***************************************************************/
256/* Stdout specific functions */
257
258static void invert_cursor(void)
259{
260 invert_char(position % columns, position / columns);
261}
262
263/** Print character to screen
264 *
265 * Emulate basic terminal commands
266 */
267static void fb_putchar(chardev_t *dev, char ch)
268{
269 spinlock_lock(&fb_lock);
270
271 switch (ch) {
272 case '\n':
273 invert_cursor();
274 position += columns;
275 position -= position % columns;
276 break;
277 case '\r':
278 invert_cursor();
279 position -= position % columns;
280 break;
281 case '\b':
282 invert_cursor();
283 if (position % columns)
284 position--;
285 break;
286 case '\t':
287 invert_cursor();
288 do {
289 draw_char(' ');
290 position++;
291 } while ((position % 8) && position < columns * rows);
292 break;
293 default:
294 draw_char(ch);
295 position++;
296 }
297
298 if (position >= columns * rows) {
299 position -= columns;
300 scroll_screen();
301 }
302
303 invert_cursor();
304
305 spinlock_unlock(&fb_lock);
306}
307
308static chardev_t framebuffer;
309static chardev_operations_t fb_ops = {
310 .write = fb_putchar,
311};
312
313
314/** Initialize framebuffer as a chardev output device
315 *
316 * @param addr Physical address of the framebuffer
317 * @param x Screen width in pixels
318 * @param y Screen height in pixels
319 * @param bpp Bits per pixel (8, 16, 24, 32)
320 * @param scan Bytes per one scanline
321 *
322 */
323void fb_init(__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan)
324{
325 switch (bpp) {
326 case 8:
327 putpixel = putpixel_1byte;
328 getpixel = getpixel_1byte;
329 pixelbytes = 1;
330 break;
331 case 16:
332 putpixel = putpixel_2byte;
333 getpixel = getpixel_2byte;
334 pixelbytes = 2;
335 break;
336 case 24:
337 putpixel = putpixel_3byte;
338 getpixel = getpixel_3byte;
339 pixelbytes = 3;
340 break;
341 case 32:
342 putpixel = putpixel_4byte;
343 getpixel = getpixel_4byte;
344 pixelbytes = 4;
345 break;
346 default:
347 panic("Unsupported bpp");
348 }
349
350 unsigned int fbsize = scan * y;
351
352 /* Map the framebuffer */
353 fbaddress = (__u8 *) hw_map((__address) addr, fbsize);
354
355 xres = x;
356 yres = y;
357 bitspp = bpp;
358 scanline = scan;
359
360 rows = y / FONT_SCANLINES;
361 columns = x / COL_WIDTH;
362
363 clear_screen();
364 draw_logo(xres - helenos_width, 0);
365 invert_cursor();
366
367 chardev_initialize("fb", &framebuffer, &fb_ops);
368 stdout = &framebuffer;
369
370 sysinfo_set_item_val("fb", NULL, true);
371 sysinfo_set_item_val("fb.width", NULL, x);
372 sysinfo_set_item_val("fb.height", NULL, y);
373 sysinfo_set_item_val("fb.bpp", NULL, bpp);
374 sysinfo_set_item_val("fb.scanline", NULL, scan);
375 sysinfo_set_item_val("fb.address.physical", NULL, addr);
376}
Note: See TracBrowser for help on using the repository browser.