source: mainline/kernel/genarch/src/fb/fb.c@ c43b1db2

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

overhaul pareas: use one single physical area for the physical address space not belonging to physical memory

  • Property mode set to 100644
File size: 11.8 KB
Line 
1/*
2 * Copyright (c) 2008 Martin Decky
3 * Copyright (c) 2006 Ondrej Palkovsky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup genarch
31 * @{
32 */
33/** @file
34 */
35
36#include <genarch/fb/font-8x16.h>
37#include <genarch/fb/logo-196x66.h>
38#include <genarch/fb/visuals.h>
39#include <genarch/fb/fb.h>
40#include <console/chardev.h>
41#include <console/console.h>
42#include <sysinfo/sysinfo.h>
43#include <mm/slab.h>
44#include <align.h>
45#include <panic.h>
46#include <memstr.h>
47#include <config.h>
48#include <bitops.h>
49#include <print.h>
50#include <ddi/ddi.h>
51#include <arch/types.h>
52
53SPINLOCK_INITIALIZE(fb_lock);
54
55static uint8_t *fb_addr;
56static uint8_t *backbuf;
57static uint8_t *glyphs;
58static uint8_t *bgscan;
59
60static unsigned int xres;
61static unsigned int yres;
62
63static unsigned int ylogo;
64static unsigned int ytrim;
65static unsigned int rowtrim;
66
67static unsigned int scanline;
68static unsigned int glyphscanline;
69
70static unsigned int pixelbytes;
71static unsigned int glyphbytes;
72static unsigned int bgscanbytes;
73
74static unsigned int cols;
75static unsigned int rows;
76static unsigned int position = 0;
77
78#define BG_COLOR 0x000080
79#define FG_COLOR 0xffff00
80
81#define CURSOR 219
82
83#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
84#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
85#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
86
87#define COL2X(col) ((col) * FONT_WIDTH)
88#define ROW2Y(row) ((row) * FONT_SCANLINES)
89
90#define X2COL(x) ((x) / FONT_WIDTH)
91#define Y2ROW(y) ((y) / FONT_SCANLINES)
92
93#define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes)
94#define BB_POS(col, row) ((row) * cols + (col))
95#define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline)
96
97
98static void (*rgb_conv)(void *, uint32_t);
99
100
101/** ARGB 8:8:8:8 conversion
102 *
103 */
104static void rgb_0888(void *dst, uint32_t rgb)
105{
106 *((uint32_t *) dst) = rgb & 0xffffff;
107}
108
109
110/** ABGR 8:8:8:8 conversion
111 *
112 */
113static void bgr_0888(void *dst, uint32_t rgb)
114{
115 *((uint32_t *) dst)
116 = (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
117}
118
119
120/** RGB 8:8:8 conversion
121 *
122 */
123static void rgb_888(void *dst, uint32_t rgb)
124{
125 ((uint8_t *) dst)[0] = BLUE(rgb, 8);
126 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
127 ((uint8_t *) dst)[2] = RED(rgb, 8);
128}
129
130
131/** BGR 8:8:8 conversion
132 *
133 */
134static void bgr_888(void *dst, uint32_t rgb)
135{
136 ((uint8_t *) dst)[0] = RED(rgb, 8);
137 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
138 ((uint8_t *) dst)[2] = BLUE(rgb, 8);
139}
140
141
142/** RGB 5:5:5 conversion
143 *
144 */
145static void rgb_555(void *dst, uint32_t rgb)
146{
147 *((uint16_t *) dst)
148 = (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
149}
150
151
152/** RGB 5:6:5 conversion
153 *
154 */
155static void rgb_565(void *dst, uint32_t rgb)
156{
157 *((uint16_t *) dst)
158 = (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
159}
160
161
162/** RGB 3:2:3
163 *
164 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
165 * will most likely use a color palette. The color appearance
166 * will be pretty random and depend on the default installed
167 * palette. This could be fixed by supporting custom palette
168 * and setting it to simulate the 8-bit truecolor.
169 *
170 * Currently we set the palette on the ia32, amd64 and sparc64 port.
171 *
172 * Note that the byte is being inverted by this function. The reason is
173 * that we would like to use a color palette where the white color code
174 * is 0 and the black color code is 255, as some machines (Sun Blade 1500)
175 * use these codes for black and white and prevent to set codes
176 * 0 and 255 to other colors.
177 *
178 */
179static void rgb_323(void *dst, uint32_t rgb)
180{
181 *((uint8_t *) dst)
182 = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
183}
184
185
186/** Hide logo and refresh screen
187 *
188 */
189static void logo_hide(bool silent)
190{
191 ylogo = 0;
192 ytrim = yres;
193 rowtrim = rows;
194 if (!silent)
195 fb_redraw();
196}
197
198
199/** Draw character at given position
200 *
201 */
202static void glyph_draw(uint8_t glyph, unsigned int col, unsigned int row, bool silent)
203{
204 unsigned int x = COL2X(col);
205 unsigned int y = ROW2Y(row);
206 unsigned int yd;
207
208 if (y >= ytrim)
209 logo_hide(silent);
210
211 backbuf[BB_POS(col, row)] = glyph;
212
213 if (!silent) {
214 for (yd = 0; yd < FONT_SCANLINES; yd++)
215 memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)],
216 &glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
217 }
218}
219
220
221/** Scroll screen down by one row
222 *
223 *
224 */
225static void screen_scroll(bool silent)
226{
227 if (ylogo > 0) {
228 logo_hide(silent);
229 return;
230 }
231
232 if (!silent) {
233 unsigned int row;
234
235 for (row = 0; row < rows; row++) {
236 unsigned int y = ROW2Y(row);
237 unsigned int yd;
238
239 for (yd = 0; yd < FONT_SCANLINES; yd++) {
240 unsigned int x;
241 unsigned int col;
242
243 for (col = 0, x = 0; col < cols; col++,
244 x += FONT_WIDTH) {
245 uint8_t glyph;
246
247 if (row < rows - 1) {
248 if (backbuf[BB_POS(col, row)] ==
249 backbuf[BB_POS(col, row + 1)])
250 continue;
251
252 glyph = backbuf[BB_POS(col, row + 1)];
253 } else
254 glyph = 0;
255
256 memcpy(&fb_addr[FB_POS(x, y + yd)],
257 &glyphs[GLYPH_POS(glyph, yd)],
258 glyphscanline);
259 }
260 }
261 }
262 }
263
264 memmove(backbuf, backbuf + cols, cols * (rows - 1));
265 memsetb(&backbuf[BB_POS(0, rows - 1)], cols, 0);
266}
267
268
269static void cursor_put(bool silent)
270{
271 glyph_draw(CURSOR, position % cols, position / cols, silent);
272}
273
274
275static void cursor_remove(bool silent)
276{
277 glyph_draw(0, position % cols, position / cols, silent);
278}
279
280
281/** Print character to screen
282 *
283 * Emulate basic terminal commands.
284 *
285 */
286static void fb_putchar(chardev_t *dev, char ch, bool silent)
287{
288 spinlock_lock(&fb_lock);
289
290 switch (ch) {
291 case '\n':
292 cursor_remove(silent);
293 position += cols;
294 position -= position % cols;
295 break;
296 case '\r':
297 cursor_remove(silent);
298 position -= position % cols;
299 break;
300 case '\b':
301 cursor_remove(silent);
302 if (position % cols)
303 position--;
304 break;
305 case '\t':
306 cursor_remove(silent);
307 do {
308 glyph_draw((uint8_t) ' ', position % cols,
309 position / cols, silent);
310 position++;
311 } while ((position % 8) && (position < cols * rows));
312 break;
313 default:
314 glyph_draw((uint8_t) ch, position % cols,
315 position / cols, silent);
316 position++;
317 }
318
319 if (position >= cols * rows) {
320 position -= cols;
321 screen_scroll(silent);
322 }
323
324 cursor_put(silent);
325
326 spinlock_unlock(&fb_lock);
327}
328
329static chardev_t framebuffer;
330static chardev_operations_t fb_ops = {
331 .write = fb_putchar,
332};
333
334
335/** Render glyphs
336 *
337 * Convert glyphs from device independent font
338 * description to current visual representation.
339 *
340 */
341static void glyphs_render(void)
342{
343 /* Prerender glyphs */
344 unsigned int glyph;
345
346 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
347 unsigned int y;
348
349 for (y = 0; y < FONT_SCANLINES; y++) {
350 unsigned int x;
351
352 for (x = 0; x < FONT_WIDTH; x++) {
353 void *dst = &glyphs[GLYPH_POS(glyph, y) +
354 x * pixelbytes];
355 uint32_t rgb = (fb_font[ROW2Y(glyph) + y] &
356 (1 << (7 - x))) ? FG_COLOR : BG_COLOR;
357 rgb_conv(dst, rgb);
358 }
359 }
360 }
361
362 /* Prerender background scanline */
363 unsigned int x;
364
365 for (x = 0; x < xres; x++)
366 rgb_conv(&bgscan[x * pixelbytes], BG_COLOR);
367}
368
369
370/** Refresh the screen
371 *
372 */
373void fb_redraw(void)
374{
375 if (ylogo > 0) {
376 unsigned int y;
377
378 for (y = 0; y < LOGO_HEIGHT; y++) {
379 unsigned int x;
380
381 for (x = 0; x < xres; x++)
382 rgb_conv(&fb_addr[FB_POS(x, y)],
383 (x < LOGO_WIDTH) ?
384 fb_logo[y * LOGO_WIDTH + x] :
385 LOGO_COLOR);
386 }
387 }
388
389 unsigned int row;
390
391 for (row = 0; row < rowtrim; row++) {
392 unsigned int y = ylogo + ROW2Y(row);
393 unsigned int yd;
394
395 for (yd = 0; yd < FONT_SCANLINES; yd++) {
396 unsigned int x;
397 unsigned int col;
398
399 for (col = 0, x = 0; col < cols;
400 col++, x += FONT_WIDTH) {
401 void *d = &fb_addr[FB_POS(x, y + yd)];
402 void *s = &glyphs[GLYPH_POS(backbuf[BB_POS(col,
403 row)], yd)];
404 memcpy(d, s, glyphscanline);
405 }
406 }
407 }
408
409 if (COL2X(cols) < xres) {
410 unsigned int y;
411 unsigned int size = (xres - COL2X(cols)) * pixelbytes;
412
413 for (y = ylogo; y < yres; y++)
414 memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size);
415 }
416
417 if (ROW2Y(rowtrim) + ylogo < yres) {
418 unsigned int y;
419
420 for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++)
421 memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes);
422 }
423}
424
425
426/** Initialize framebuffer as a chardev output device
427 *
428 * @param addr Physical address of the framebuffer
429 * @param x Screen width in pixels
430 * @param y Screen height in pixels
431 * @param scan Bytes per one scanline
432 * @param visual Color model
433 *
434 */
435void fb_init(fb_properties_t *props)
436{
437 switch (props->visual) {
438 case VISUAL_INDIRECT_8:
439 rgb_conv = rgb_323;
440 pixelbytes = 1;
441 break;
442 case VISUAL_RGB_5_5_5:
443 rgb_conv = rgb_555;
444 pixelbytes = 2;
445 break;
446 case VISUAL_RGB_5_6_5:
447 rgb_conv = rgb_565;
448 pixelbytes = 2;
449 break;
450 case VISUAL_RGB_8_8_8:
451 rgb_conv = rgb_888;
452 pixelbytes = 3;
453 break;
454 case VISUAL_BGR_8_8_8:
455 rgb_conv = bgr_888;
456 pixelbytes = 3;
457 break;
458 case VISUAL_RGB_8_8_8_0:
459 rgb_conv = rgb_888;
460 pixelbytes = 4;
461 break;
462 case VISUAL_RGB_0_8_8_8:
463 rgb_conv = rgb_0888;
464 pixelbytes = 4;
465 break;
466 case VISUAL_BGR_0_8_8_8:
467 rgb_conv = bgr_0888;
468 pixelbytes = 4;
469 break;
470 default:
471 panic("Unsupported visual.");
472 }
473
474 xres = props->x;
475 yres = props->y;
476 scanline = props->scan;
477
478 cols = X2COL(xres);
479 rows = Y2ROW(yres);
480
481 if (yres > ylogo) {
482 ylogo = LOGO_HEIGHT;
483 rowtrim = rows - Y2ROW(ylogo);
484 if (ylogo % FONT_SCANLINES > 0)
485 rowtrim--;
486 ytrim = ROW2Y(rowtrim);
487 } else {
488 ylogo = 0;
489 ytrim = yres;
490 rowtrim = rows;
491 }
492
493 glyphscanline = FONT_WIDTH * pixelbytes;
494 glyphbytes = ROW2Y(glyphscanline);
495 bgscanbytes = xres * pixelbytes;
496
497 unsigned int fbsize = scanline * yres;
498 unsigned int bbsize = cols * rows;
499 unsigned int glyphsize = FONT_GLYPHS * glyphbytes;
500
501 backbuf = (uint8_t *) malloc(bbsize, 0);
502 if (!backbuf)
503 panic("Unable to allocate backbuffer.");
504
505 glyphs = (uint8_t *) malloc(glyphsize, 0);
506 if (!glyphs)
507 panic("Unable to allocate glyphs.");
508
509 bgscan = malloc(bgscanbytes, 0);
510 if (!bgscan)
511 panic("Unable to allocate background pixel.");
512
513 memsetb(backbuf, bbsize, 0);
514
515 glyphs_render();
516
517 fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
518
519 sysinfo_set_item_val("fb", NULL, true);
520 sysinfo_set_item_val("fb.kind", NULL, 1);
521 sysinfo_set_item_val("fb.width", NULL, xres);
522 sysinfo_set_item_val("fb.height", NULL, yres);
523 sysinfo_set_item_val("fb.scanline", NULL, scanline);
524 sysinfo_set_item_val("fb.visual", NULL, props->visual);
525 sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
526
527 fb_redraw();
528
529 chardev_initialize("fb", &framebuffer, &fb_ops);
530 stdout = &framebuffer;
531}
532
533/** @}
534 */
Note: See TracBrowser for help on using the repository browser.