source: mainline/kernel/genarch/src/fb/fb.c@ 323a5aaf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 323a5aaf was 2057572, checked in by Jakub Jermar <jakub@…>, 18 years ago

The Ultimate Solution To Illegal Virtual Aliases.
It is better to avoid them completely than to fight them.
Switch the sparc64 port to 16K pages. The TLBs and TSBs
continue to operate with 8K pages only. Page tables and
other generic parts operate with 16K pages.

Because the MMU doesn't support 16K directly, each 16K
page is emulated by a pair of 8K pages. With 16K pages,
illegal aliases cannot be created in 16K D-cache.

  • Property mode set to 100644
File size: 13.5 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/** @addtogroup genarch
30 * @{
31 */
32/** @file
33 */
34
35#include <genarch/fb/font-8x16.h>
36#include <genarch/fb/visuals.h>
37#include <genarch/fb/fb.h>
38#include <console/chardev.h>
39#include <console/console.h>
40#include <sysinfo/sysinfo.h>
41#include <mm/slab.h>
42#include <panic.h>
43#include <memstr.h>
44#include <config.h>
45#include <bitops.h>
46#include <print.h>
47#include <ddi/ddi.h>
48#include <arch/types.h>
49
50#include "helenos.xbm"
51
52static parea_t fb_parea; /**< Physical memory area for fb. */
53
54SPINLOCK_INITIALIZE(fb_lock);
55
56static uint8_t *fbaddress = NULL;
57
58static uint8_t *blankline = NULL;
59static uint8_t *dbbuffer = NULL; /* Buffer for fast scrolling console */
60static index_t dboffset;
61
62static unsigned int xres = 0;
63static unsigned int yres = 0;
64static unsigned int scanline = 0;
65static unsigned int pixelbytes = 0;
66#ifdef FB_INVERT_COLORS
67static bool invert_colors = true;
68#else
69static bool invert_colors = false;
70#endif
71
72static unsigned int position = 0;
73static unsigned int columns = 0;
74static unsigned int rows = 0;
75
76#define COL_WIDTH 8
77#define ROW_BYTES (scanline * FONT_SCANLINES)
78
79#define BGCOLOR 0x000080
80#define FGCOLOR 0xffff00
81#define LOGOCOLOR 0x2020b0
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 POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes)
88
89/***************************************************************/
90/* Pixel specific fuctions */
91
92static void (*rgb2scr)(void *, int);
93static int (*scr2rgb)(void *);
94
95static inline int COLOR(int color)
96{
97 return invert_colors ? ~color : color;
98}
99
100/* Conversion routines between different color representations */
101static void rgb_byte0888(void *dst, int rgb)
102{
103 *((int *) dst) = rgb;
104}
105
106static int byte0888_rgb(void *src)
107{
108 return (*((int *) src)) & 0xffffff;
109}
110
111static void bgr_byte0888(void *dst, int rgb)
112{
113 *((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
114 RED(rgb, 8);
115}
116
117static int byte0888_bgr(void *src)
118{
119 int color = *(uint32_t *)(src);
120 return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
121 ((color >> 16) & 0xff);
122}
123
124static void rgb_byte888(void *dst, int rgb)
125{
126 uint8_t *scr = (uint8_t *) dst;
127#if defined(FB_INVERT_ENDIAN)
128 scr[0] = RED(rgb, 8);
129 scr[1] = GREEN(rgb, 8);
130 scr[2] = BLUE(rgb, 8);
131#else
132 scr[2] = RED(rgb, 8);
133 scr[1] = GREEN(rgb, 8);
134 scr[0] = BLUE(rgb, 8);
135#endif
136}
137
138static int byte888_rgb(void *src)
139{
140 uint8_t *scr = (uint8_t *) src;
141#if defined(FB_INVERT_ENDIAN)
142 return scr[0] << 16 | scr[1] << 8 | scr[2];
143#else
144 return scr[2] << 16 | scr[1] << 8 | scr[0];
145#endif
146}
147
148/** 16-bit depth (5:5:5) */
149static void rgb_byte555(void *dst, int rgb)
150{
151 /* 5-bit, 5-bits, 5-bits */
152 *((uint16_t *) dst) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
153 BLUE(rgb, 5);
154}
155
156/** 16-bit depth (5:5:5) */
157static int byte555_rgb(void *src)
158{
159 int color = *(uint16_t *)(src);
160 return (((color >> 10) & 0x1f) << (16 + 3)) |
161 (((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
162}
163
164/** 16-bit depth (5:6:5) */
165static void rgb_byte565(void *dst, int rgb)
166{
167 /* 5-bit, 6-bits, 5-bits */
168 *((uint16_t *) dst) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
169 BLUE(rgb, 5);
170}
171
172/** 16-bit depth (5:6:5) */
173static int byte565_rgb(void *src)
174{
175 int color = *(uint16_t *)(src);
176 return (((color >> 11) & 0x1f) << (16 + 3)) |
177 (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
178}
179
180/** Put pixel - 8-bit depth (color palette/3:2:3)
181 *
182 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
183 * will most likely use a color palette. The color appearance
184 * will be pretty random and depend on the default installed
185 * palette. This could be fixed by supporting custom palette
186 * and setting it to simulate the 8-bit truecolor.
187 */
188static void rgb_byte8(void *dst, int rgb)
189{
190 *((uint8_t *) dst) = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 |
191 BLUE(rgb, 3);
192}
193
194/** Return pixel color - 8-bit depth (color palette/3:2:3)
195 *
196 * See the comment for rgb_byte().
197 */
198static int byte8_rgb(void *src)
199{
200 int color = *(uint8_t *)src;
201 return (((color >> 5) & 0x7) << (16 + 5)) |
202 (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
203}
204
205static void putpixel(unsigned int x, unsigned int y, int color)
206{
207 (*rgb2scr)(&fbaddress[POINTPOS(x, y)], COLOR(color));
208
209 if (dbbuffer) {
210 int dline = (y + dboffset) % yres;
211 (*rgb2scr)(&dbbuffer[POINTPOS(x, dline)], COLOR(color));
212 }
213}
214
215/** Get pixel from viewport */
216static int getpixel(unsigned int x, unsigned int y)
217{
218 if (dbbuffer) {
219 int dline = (y + dboffset) % yres;
220 return COLOR((*scr2rgb)(&dbbuffer[POINTPOS(x, dline)]));
221 }
222 return COLOR((*scr2rgb)(&fbaddress[POINTPOS(x, y)]));
223}
224
225
226/** Fill screen with background color */
227static void clear_screen(void)
228{
229 unsigned int y;
230
231 for (y = 0; y < yres; y++) {
232 memcpy(&fbaddress[scanline * y], blankline, xres * pixelbytes);
233 if (dbbuffer)
234 memcpy(&dbbuffer[scanline * y], blankline,
235 xres * pixelbytes);
236 }
237}
238
239
240/** Scroll screen one row up */
241static void scroll_screen(void)
242{
243 if (dbbuffer) {
244 count_t first;
245
246 /* Clear the last row */
247 memcpy(&dbbuffer[dboffset * scanline], blankline, ROW_BYTES);
248
249 dboffset = (dboffset + FONT_SCANLINES) % yres;
250 first = yres - dboffset;
251
252 /* Move all rows one row up */
253 if (xres * pixelbytes == scanline) {
254 memcpy(fbaddress, &dbbuffer[dboffset * scanline],
255 first * scanline);
256 memcpy(&fbaddress[first * scanline], dbbuffer,
257 dboffset * scanline);
258 } else {
259 /*
260 * When the scanline is bigger than number of bytes
261 * in the X-resolution, chances are that the
262 * frame buffer memory past the X-resolution is special
263 * in some way. For example, the SUNW,ffb framebuffer
264 * wraps this area around the beginning of the same
265 * line. To avoid troubles, copy only memory as
266 * specified by the resolution.
267 */
268 unsigned int i;
269
270 for (i = 0; i < first; i++)
271 memcpy(&fbaddress[i * scanline],
272 &dbbuffer[(dboffset + i) * scanline],
273 xres * pixelbytes);
274 for (i = 0; i < dboffset; i++)
275 memcpy(&fbaddress[(first + i) * scanline],
276 &dbbuffer[i * scanline], xres * pixelbytes);
277 }
278 } else {
279 uint8_t *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
280
281 if (xres * pixelbytes == scanline) {
282 /* Move all rows one row up */
283 memcpy((void *) fbaddress,
284 (void *) &fbaddress[ROW_BYTES],
285 scanline * yres - ROW_BYTES);
286 /* Clear the last row */
287 memcpy((void *) lastline, (void *) blankline,
288 ROW_BYTES);
289 } else {
290 /*
291 * See the comment in the dbbuffer case.
292 */
293 unsigned int i;
294
295 /* Move all rows one row up */
296 for (i = 0; i < yres - FONT_SCANLINES; i++)
297 memcpy(&fbaddress[i * scanline],
298 &fbaddress[(i + FONT_SCANLINES) * scanline],
299 xres * pixelbytes);
300 /* Clear the last row */
301 for (i = 0; i < FONT_SCANLINES; i++)
302 memcpy(&lastline[i * scanline],
303 &blankline[i * scanline],
304 xres * pixelbytes);
305 }
306 }
307}
308
309
310static void invert_pixel(unsigned int x, unsigned int y)
311{
312 putpixel(x, y, ~getpixel(x, y));
313}
314
315
316/** Draw one line of glyph at a given position */
317static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
318{
319 unsigned int i;
320
321 for (i = 0; i < 8; i++)
322 if (glline & (1 << (7 - i))) {
323 putpixel(x + i, y, FGCOLOR);
324 } else
325 putpixel(x + i, y, BGCOLOR);
326}
327
328/***************************************************************/
329/* Character-console functions */
330
331/** Draw character at given position */
332static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row)
333{
334 unsigned int y;
335
336 for (y = 0; y < FONT_SCANLINES; y++)
337 draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y],
338 col * COL_WIDTH, row * FONT_SCANLINES + y);
339}
340
341/** Invert character at given position */
342static void invert_char(unsigned int col, unsigned int row)
343{
344 unsigned int x;
345 unsigned int y;
346
347 for (x = 0; x < COL_WIDTH; x++)
348 for (y = 0; y < FONT_SCANLINES; y++)
349 invert_pixel(col * COL_WIDTH + x,
350 row * FONT_SCANLINES + y);
351}
352
353/** Draw character at default position */
354static void draw_char(char chr)
355{
356 draw_glyph(chr, position % columns, position / columns);
357}
358
359static void draw_logo(unsigned int startx, unsigned int starty)
360{
361 unsigned int x;
362 unsigned int y;
363 unsigned int byte;
364 unsigned int rowbytes;
365
366 rowbytes = (helenos_width - 1) / 8 + 1;
367
368 for (y = 0; y < helenos_height; y++)
369 for (x = 0; x < helenos_width; x++) {
370 byte = helenos_bits[rowbytes * y + x / 8];
371 byte >>= x % 8;
372 if (byte & 1)
373 putpixel(startx + x, starty + y,
374 COLOR(LOGOCOLOR));
375 }
376}
377
378/***************************************************************/
379/* Stdout specific functions */
380
381static void invert_cursor(void)
382{
383 invert_char(position % columns, position / columns);
384}
385
386/** Print character to screen
387 *
388 * Emulate basic terminal commands
389 */
390static void fb_putchar(chardev_t *dev, char ch)
391{
392 spinlock_lock(&fb_lock);
393
394 switch (ch) {
395 case '\n':
396 invert_cursor();
397 position += columns;
398 position -= position % columns;
399 break;
400 case '\r':
401 invert_cursor();
402 position -= position % columns;
403 break;
404 case '\b':
405 invert_cursor();
406 if (position % columns)
407 position--;
408 break;
409 case '\t':
410 invert_cursor();
411 do {
412 draw_char(' ');
413 position++;
414 } while ((position % 8) && position < columns * rows);
415 break;
416 default:
417 draw_char(ch);
418 position++;
419 }
420
421 if (position >= columns * rows) {
422 position -= columns;
423 scroll_screen();
424 }
425
426 invert_cursor();
427
428 spinlock_unlock(&fb_lock);
429}
430
431static chardev_t framebuffer;
432static chardev_operations_t fb_ops = {
433 .write = fb_putchar,
434};
435
436
437/** Initialize framebuffer as a chardev output device
438 *
439 * @param addr Physical address of the framebuffer
440 * @param x Screen width in pixels
441 * @param y Screen height in pixels
442 * @param scan Bytes per one scanline
443 * @param visual Color model
444 *
445 */
446void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan,
447 unsigned int visual)
448{
449 switch (visual) {
450 case VISUAL_INDIRECT_8:
451 rgb2scr = rgb_byte8;
452 scr2rgb = byte8_rgb;
453 pixelbytes = 1;
454 break;
455 case VISUAL_RGB_5_5_5:
456 rgb2scr = rgb_byte555;
457 scr2rgb = byte555_rgb;
458 pixelbytes = 2;
459 break;
460 case VISUAL_RGB_5_6_5:
461 rgb2scr = rgb_byte565;
462 scr2rgb = byte565_rgb;
463 pixelbytes = 2;
464 break;
465 case VISUAL_RGB_8_8_8:
466 rgb2scr = rgb_byte888;
467 scr2rgb = byte888_rgb;
468 pixelbytes = 3;
469 break;
470 case VISUAL_RGB_8_8_8_0:
471 rgb2scr = rgb_byte888;
472 scr2rgb = byte888_rgb;
473 pixelbytes = 4;
474 break;
475 case VISUAL_RGB_0_8_8_8:
476 rgb2scr = rgb_byte0888;
477 scr2rgb = byte0888_rgb;
478 pixelbytes = 4;
479 break;
480 case VISUAL_BGR_0_8_8_8:
481 rgb2scr = bgr_byte0888;
482 scr2rgb = byte0888_bgr;
483 pixelbytes = 4;
484 break;
485 default:
486 panic("Unsupported visual.\n");
487 }
488
489 unsigned int fbsize = scan * y;
490
491 /* Map the framebuffer */
492 fbaddress = (uint8_t *) hw_map((uintptr_t) addr, fbsize);
493
494 xres = x;
495 yres = y;
496 scanline = scan;
497
498 rows = y / FONT_SCANLINES;
499 columns = x / COL_WIDTH;
500
501 fb_parea.pbase = (uintptr_t) addr;
502 fb_parea.vbase = (uintptr_t) fbaddress;
503 fb_parea.frames = SIZE2FRAMES(fbsize);
504 fb_parea.cacheable = false;
505 ddi_parea_register(&fb_parea);
506
507 sysinfo_set_item_val("fb", NULL, true);
508 sysinfo_set_item_val("fb.kind", NULL, 1);
509 sysinfo_set_item_val("fb.width", NULL, xres);
510 sysinfo_set_item_val("fb.height", NULL, yres);
511 sysinfo_set_item_val("fb.scanline", NULL, scan);
512 sysinfo_set_item_val("fb.visual", NULL, visual);
513 sysinfo_set_item_val("fb.address.physical", NULL, addr);
514 sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors);
515
516 /* Allocate double buffer */
517 unsigned int order = fnzb(SIZE2FRAMES(fbsize) - 1) + 1;
518 dbbuffer = (uint8_t *) frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
519 if (!dbbuffer)
520 printf("Failed to allocate scroll buffer.\n");
521 dboffset = 0;
522
523 /* Initialized blank line */
524 blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC);
525 if (!blankline)
526 panic("Failed to allocate blank line for framebuffer.");
527 for (y = 0; y < FONT_SCANLINES; y++)
528 for (x = 0; x < xres; x++)
529 (*rgb2scr)(&blankline[POINTPOS(x, y)], COLOR(BGCOLOR));
530
531 clear_screen();
532
533 /* Update size of screen to match text area */
534 yres = rows * FONT_SCANLINES;
535
536 draw_logo(xres - helenos_width, 0);
537 invert_cursor();
538
539 chardev_initialize("fb", &framebuffer, &fb_ops);
540 stdout = &framebuffer;
541}
542
543/** @}
544 */
Note: See TracBrowser for help on using the repository browser.