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

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b83c5e4 was e037cf37, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Show kernel console again when its physical area is unmapped

It's good to be able to see the stack trace if e.g. display server
crashes.

  • Property mode set to 100644
File size: 18.1 KB
RevLine 
[bbf5657]1/*
[76fca31]2 * Copyright (c) 2008 Martin Decky
[df4ed85]3 * Copyright (c) 2006 Ondrej Palkovsky
[bbf5657]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
[6404aca]30/** @addtogroup kernel_genarch
[b45c443]31 * @{
32 */
33/** @file
34 */
35
[63e27ef]36#include <assert.h>
37#include <debug.h>
[fe050b7]38#include <genarch/fb/font-8x16.h>
39#include <genarch/fb/fb.h>
[bbf5657]40#include <console/chardev.h>
41#include <console/console.h>
[2666daa]42#include <sysinfo/sysinfo.h>
[d4673296]43#include <mm/km.h>
[aafed15]44#include <stdlib.h>
[76fca31]45#include <align.h>
[fcbca14f]46#include <panic.h>
[44a7ee5]47#include <mem.h>
[74d1d66]48#include <config.h>
[6eb96fce]49#include <bitops.h>
[19f857a]50#include <str.h>
[f8ddd17]51#include <ddi/ddi.h>
[d99c1d2]52#include <typedefs.h>
[30885b9]53#include <byteorder.h>
[bbf5657]54
[d2b66d4]55#define BG_COLOR 0x001620
56#define FG_COLOR 0xf3cf65
[a71c158]57#define INV_COLOR 0xaaaaaa
[6e71a9d8]58
[7ddc2c7]59#define FB_PAGES 8
60
[a71c158]61#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
62#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
63#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
[76fca31]64
[a71c158]65#define COL2X(col) ((col) * FONT_WIDTH)
66#define ROW2Y(row) ((row) * FONT_SCANLINES)
[bbf5657]67
[a71c158]68#define X2COL(x) ((x) / FONT_WIDTH)
69#define Y2ROW(y) ((y) / FONT_SCANLINES)
[bbf5657]70
[a71c158]71#define FB_POS(instance, x, y) \
72 ((y) * (instance)->scanline + (x) * (instance)->pixelbytes)
[a2c4445]73
[a71c158]74#define BB_POS(instance, col, row) \
[7ddc2c7]75 ((((instance)->start_row + (row)) % (instance)->rows) * \
76 (instance)->cols + (col))
[a2c4445]77
[ca645a2]78#define BB_NEXT_COL(pos) (++(pos))
79
[a71c158]80#define GLYPH_POS(instance, glyph, y) \
81 ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
[95c7526]82
[3bacee1]83typedef void (*rgb_conv_t)(void *, uint32_t);
[bbf5657]84
[a71c158]85typedef struct {
[c263c77]86 SPINLOCK_DECLARE(lock);
[a35b458]87
[b366a6f4]88 parea_t parea;
[a35b458]89
[a71c158]90 uint8_t *addr;
91 uint16_t *backbuf;
92 uint8_t *glyphs;
93 uint8_t *bgscan;
[a35b458]94
[a71c158]95 rgb_conv_t rgb_conv;
[a35b458]96
[a71c158]97 unsigned int xres;
98 unsigned int yres;
[a35b458]99
[7ddc2c7]100 /** Number of rows that fit on framebuffer */
[a71c158]101 unsigned int rowtrim;
[a35b458]102
[a71c158]103 unsigned int scanline;
104 unsigned int glyphscanline;
[a35b458]105
[a71c158]106 unsigned int pixelbytes;
107 unsigned int glyphbytes;
108 unsigned int bgscanbytes;
[a35b458]109
[7ddc2c7]110 /** Number of columns in the backbuffer */
[a71c158]111 unsigned int cols;
[7ddc2c7]112 /** Number of rows in the backbuffer */
[a71c158]113 unsigned int rows;
[a35b458]114
[7ddc2c7]115 /** Starting row in the cyclic backbuffer */
116 unsigned int start_row;
[a35b458]117
[7ddc2c7]118 /** Top-most visible row (relative to start_row) */
119 unsigned int offset_row;
[a35b458]120
[7ddc2c7]121 /** Current backbuffer position */
[a71c158]122 unsigned int position;
123} fb_instance_t;
[fcbca14f]124
[28a5ebd]125static void fb_putuchar(outdev_t *, char32_t);
[7ddc2c7]126static void fb_redraw(outdev_t *);
127static void fb_scroll_up(outdev_t *);
128static void fb_scroll_down(outdev_t *);
[253f35a1]129
[a71c158]130static outdev_operations_t fbdev_ops = {
[28a5ebd]131 .write = fb_putuchar,
[7ddc2c7]132 .redraw = fb_redraw,
133 .scroll_up = fb_scroll_up,
134 .scroll_down = fb_scroll_down
[a71c158]135};
[95c7526]136
[30885b9]137/*
138 * RGB conversion functions.
[76fca31]139 *
[30885b9]140 * These functions write an RGB value to some memory in some predefined format.
141 * The naming convention corresponds to the format created by these functions.
142 * The functions use the so called network order (i.e. big endian) with respect
143 * to their names.
[76fca31]144 */
[30885b9]145
[76fca31]146static void rgb_0888(void *dst, uint32_t rgb)
[ccb0cbc]147{
[30885b9]148 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
149 (RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
[ccb0cbc]150}
151
[76fca31]152static void bgr_0888(void *dst, uint32_t rgb)
[ccb0cbc]153{
[30885b9]154 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
155 (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
[ccb0cbc]156}
157
[6ac14a70]158static void rgb_8880(void *dst, uint32_t rgb)
159{
[30885b9]160 *((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
161 (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
[6ac14a70]162}
163
[30885b9]164static void bgr_8880(void *dst, uint32_t rgb)
165{
166 *((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
167 (GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
168}
[76fca31]169
170static void rgb_888(void *dst, uint32_t rgb)
[fcbca14f]171{
[30885b9]172 ((uint8_t *) dst)[0] = RED(rgb, 8);
[6e71a9d8]173 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]174 ((uint8_t *) dst)[2] = BLUE(rgb, 8);
[95b9963]175}
176
177static void bgr_888(void *dst, uint32_t rgb)
178{
[30885b9]179 ((uint8_t *) dst)[0] = BLUE(rgb, 8);
[95b9963]180 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]181 ((uint8_t *) dst)[2] = RED(rgb, 8);
[fcbca14f]182}
183
[19490ce]184static void rgb_555_be(void *dst, uint32_t rgb)
[2bc137c2]185{
[19490ce]186 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
187 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
[2bc137c2]188}
189
[19490ce]190static void rgb_555_le(void *dst, uint32_t rgb)
[fcbca14f]191{
[19490ce]192 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
193 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
194}
195
196static void rgb_565_be(void *dst, uint32_t rgb)
197{
198 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
199 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
200}
201
202static void rgb_565_le(void *dst, uint32_t rgb)
203{
204 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
205 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
[fcbca14f]206}
207
[30885b9]208/** BGR 3:2:3
[b4fa652]209 *
210 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
211 * will most likely use a color palette. The color appearance
212 * will be pretty random and depend on the default installed
213 * palette. This could be fixed by supporting custom palette
214 * and setting it to simulate the 8-bit truecolor.
[925fdd7]215 *
[a71c158]216 * Currently we set the palette on the ia32, amd64, ppc32 and sparc64 port.
[925fdd7]217 *
218 * Note that the byte is being inverted by this function. The reason is
219 * that we would like to use a color palette where the white color code
[882d7a8]220 * is 0 and the black color code is 255, as some machines (Sun Blade 1500)
[925fdd7]221 * use these codes for black and white and prevent to set codes
222 * 0 and 255 to other colors.
[882d7a8]223 *
[b4fa652]224 */
[30885b9]225static void bgr_323(void *dst, uint32_t rgb)
[fcbca14f]226{
[3bacee1]227 *((uint8_t *) dst) =
228 ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
[fcbca14f]229}
230
[76fca31]231/** Draw character at given position
[b4fa652]232 *
233 */
[a71c158]234static void glyph_draw(fb_instance_t *instance, uint16_t glyph,
[b366a6f4]235 unsigned int col, unsigned int row, bool overlay)
[bbf5657]236{
[c8bf88d]237 if (!overlay)
[a71c158]238 instance->backbuf[BB_POS(instance, col, row)] = glyph;
[a35b458]239
[7ddc2c7]240 /* Do not output if the framebuffer is used by user space */
241 if ((instance->parea.mapped) && (!console_override))
242 return;
[a35b458]243
[7ddc2c7]244 /* Check whether the glyph should be visible */
245 if (row < instance->offset_row)
246 return;
[a35b458]247
[7ddc2c7]248 unsigned int rel_row = row - instance->offset_row;
249 if (rel_row >= instance->rowtrim)
250 return;
[a35b458]251
[7ddc2c7]252 unsigned int x = COL2X(col);
253 unsigned int y = ROW2Y(rel_row);
[a35b458]254
[7ddc2c7]255 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++)
256 memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
257 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
258 instance->glyphscanline);
[bbf5657]259}
260
[76fca31]261/** Scroll screen down by one row
262 *
263 */
[b366a6f4]264static void screen_scroll(fb_instance_t *instance)
[bbf5657]265{
[b366a6f4]266 if ((!instance->parea.mapped) || (console_override)) {
[7ddc2c7]267 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
268 unsigned int y = ROW2Y(rel_row);
269 unsigned int row = rel_row + instance->offset_row;
[a35b458]270
[7ddc2c7]271 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
[516ff92]272 unsigned int x;
273 unsigned int col;
[ca645a2]274 size_t bb_pos = BB_POS(instance, 0, row);
275 size_t bb_pos1 = BB_POS(instance, 0, row + 1);
[a35b458]276
[a71c158]277 for (col = 0, x = 0; col < instance->cols;
278 col++, x += FONT_WIDTH) {
[dcdc31d]279 uint16_t glyph;
[a35b458]280
[a71c158]281 if (row < instance->rows - 1) {
[ca645a2]282 if (instance->backbuf[bb_pos] ==
283 instance->backbuf[bb_pos1])
284 goto skip;
[a35b458]285
[ca645a2]286 glyph = instance->backbuf[bb_pos1];
[516ff92]287 } else
288 glyph = 0;
[a35b458]289
[a71c158]290 memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
291 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
292 instance->glyphscanline);
[ca645a2]293 skip:
294 BB_NEXT_COL(bb_pos);
295 BB_NEXT_COL(bb_pos1);
[516ff92]296 }
[76fca31]297 }
[51baa8a]298 }
[6eb96fce]299 }
[a35b458]300
[7ddc2c7]301 /*
302 * Implement backbuffer scrolling by wrapping around
303 * the cyclic buffer.
304 */
[a35b458]305
[7ddc2c7]306 instance->start_row++;
307 if (instance->start_row == instance->rows)
308 instance->start_row = 0;
[a35b458]309
[a71c158]310 memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
311 instance->cols, 0);
[a2c4445]312}
313
[b366a6f4]314static void cursor_put(fb_instance_t *instance)
[bbf5657]315{
[a71c158]316 unsigned int col = instance->position % instance->cols;
317 unsigned int row = instance->position / instance->cols;
[a35b458]318
[b366a6f4]319 glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
[bbf5657]320}
321
[b366a6f4]322static void cursor_remove(fb_instance_t *instance)
[bbf5657]323{
[a71c158]324 unsigned int col = instance->position % instance->cols;
325 unsigned int row = instance->position / instance->cols;
[a35b458]326
[a71c158]327 glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
[b366a6f4]328 col, row, true);
[bbf5657]329}
330
[76fca31]331/** Render glyphs
332 *
333 * Convert glyphs from device independent font
334 * description to current visual representation.
335 *
336 */
[a71c158]337static void glyphs_render(fb_instance_t *instance)
[76fca31]338{
[6e71a9d8]339 /* Prerender glyphs */
[dcdc31d]340 uint16_t glyph;
[a35b458]341
[76fca31]342 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
[98895c5c]343 uint32_t fg_color;
[a35b458]344
[98895c5c]345 if (glyph == FONT_GLYPHS - 1)
346 fg_color = INV_COLOR;
347 else
348 fg_color = FG_COLOR;
[a35b458]349
[76fca31]350 unsigned int y;
[a35b458]351
[76fca31]352 for (y = 0; y < FONT_SCANLINES; y++) {
353 unsigned int x;
[a35b458]354
[edf5774]355 for (x = 0; x < FONT_WIDTH; x++) {
[a71c158]356 void *dst =
357 &instance->glyphs[GLYPH_POS(instance, glyph, y) +
358 x * instance->pixelbytes];
[dcdc31d]359 uint32_t rgb = (fb_font[glyph][y] &
[98895c5c]360 (1 << (7 - x))) ? fg_color : BG_COLOR;
[a71c158]361 instance->rgb_conv(dst, rgb);
[edf5774]362 }
[76fca31]363 }
364 }
[a35b458]365
[6e71a9d8]366 /* Prerender background scanline */
367 unsigned int x;
[a35b458]368
[a71c158]369 for (x = 0; x < instance->xres; x++)
370 instance->rgb_conv(&instance->bgscan[x * instance->pixelbytes], BG_COLOR);
[76fca31]371}
372
[7ddc2c7]373static void fb_redraw_internal(fb_instance_t *instance)
374{
375 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
376 unsigned int y = ROW2Y(rel_row);
377 unsigned int row = rel_row + instance->offset_row;
[a35b458]378
[7ddc2c7]379 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
380 unsigned int x;
381 unsigned int col;
[ca645a2]382 size_t bb_pos = BB_POS(instance, 0, row);
[a35b458]383
[7ddc2c7]384 for (col = 0, x = 0; col < instance->cols;
385 col++, x += FONT_WIDTH) {
386 uint16_t glyph =
[ca645a2]387 instance->backbuf[bb_pos];
[7ddc2c7]388 void *dst = &instance->addr[FB_POS(instance, x, y + yd)];
389 void *src = &instance->glyphs[GLYPH_POS(instance, glyph, yd)];
390 memcpy(dst, src, instance->glyphscanline);
[ca645a2]391 BB_NEXT_COL(bb_pos);
[7ddc2c7]392 }
393 }
394 }
[a35b458]395
[7ddc2c7]396 if (COL2X(instance->cols) < instance->xres) {
397 unsigned int y;
398 unsigned int size =
399 (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
[a35b458]400
[7ddc2c7]401 for (y = 0; y < instance->yres; y++)
402 memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
403 instance->bgscan, size);
404 }
[a35b458]405
[7ddc2c7]406 if (ROW2Y(instance->rowtrim) < instance->yres) {
407 unsigned int y;
[a35b458]408
[7ddc2c7]409 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
410 memcpy(&instance->addr[FB_POS(instance, 0, y)],
411 instance->bgscan, instance->bgscanbytes);
412 }
413}
414
[a71c158]415/** Print character to screen
416 *
417 * Emulate basic terminal commands.
[76fca31]418 *
419 */
[28a5ebd]420static void fb_putuchar(outdev_t *dev, char32_t ch)
[76fca31]421{
[a71c158]422 fb_instance_t *instance = (fb_instance_t *) dev->data;
[c263c77]423 spinlock_lock(&instance->lock);
[a35b458]424
[a71c158]425 switch (ch) {
426 case '\n':
[b366a6f4]427 cursor_remove(instance);
[a71c158]428 instance->position += instance->cols;
429 instance->position -= instance->position % instance->cols;
430 break;
431 case '\r':
[b366a6f4]432 cursor_remove(instance);
[a71c158]433 instance->position -= instance->position % instance->cols;
434 break;
435 case '\b':
[b366a6f4]436 cursor_remove(instance);
[a71c158]437 if (instance->position % instance->cols)
438 instance->position--;
439 break;
440 case '\t':
[b366a6f4]441 cursor_remove(instance);
[a71c158]442 do {
443 glyph_draw(instance, fb_font_glyph(' '),
444 instance->position % instance->cols,
[b366a6f4]445 instance->position / instance->cols, false);
[a71c158]446 instance->position++;
[f061e404]447 } while (((instance->position % instance->cols) % 8 != 0) &&
448 (instance->position < instance->cols * instance->rows));
[a71c158]449 break;
450 default:
451 glyph_draw(instance, fb_font_glyph(ch),
452 instance->position % instance->cols,
[b366a6f4]453 instance->position / instance->cols, false);
[a71c158]454 instance->position++;
455 }
[a35b458]456
[a71c158]457 if (instance->position >= instance->cols * instance->rows) {
458 instance->position -= instance->cols;
[b366a6f4]459 screen_scroll(instance);
[a71c158]460 }
[a35b458]461
[b366a6f4]462 cursor_put(instance);
[a35b458]463
[c263c77]464 spinlock_unlock(&instance->lock);
[a71c158]465}
466
[7ddc2c7]467/** Scroll the framebuffer up
468 *
469 */
470static void fb_scroll_up(outdev_t *dev)
[a71c158]471{
[7ddc2c7]472 fb_instance_t *instance = (fb_instance_t *) dev->data;
473 spinlock_lock(&instance->lock);
[a35b458]474
[7ddc2c7]475 if (instance->offset_row >= instance->rowtrim / 2)
476 instance->offset_row -= instance->rowtrim / 2;
477 else
478 instance->offset_row = 0;
[a35b458]479
[7ddc2c7]480 fb_redraw_internal(instance);
481 cursor_put(instance);
[a35b458]482
[7ddc2c7]483 spinlock_unlock(&instance->lock);
484}
485
486/** Scroll the framebuffer down
487 *
488 */
489static void fb_scroll_down(outdev_t *dev)
490{
491 fb_instance_t *instance = (fb_instance_t *) dev->data;
492 spinlock_lock(&instance->lock);
[a35b458]493
[7ddc2c7]494 if (instance->offset_row + instance->rowtrim / 2 <=
495 instance->rows - instance->rowtrim)
496 instance->offset_row += instance->rowtrim / 2;
497 else
498 instance->offset_row = instance->rows - instance->rowtrim;
[a35b458]499
[7ddc2c7]500 fb_redraw_internal(instance);
501 cursor_put(instance);
[a35b458]502
[7ddc2c7]503 spinlock_unlock(&instance->lock);
[76fca31]504}
505
[a71c158]506/** Refresh the screen
507 *
508 */
509static void fb_redraw(outdev_t *dev)
510{
511 fb_instance_t *instance = (fb_instance_t *) dev->data;
[a35b458]512
[c263c77]513 spinlock_lock(&instance->lock);
[a71c158]514 fb_redraw_internal(instance);
[c263c77]515 spinlock_unlock(&instance->lock);
[a71c158]516}
[76fca31]517
[e037cf37]518/** Framebuffer was mapped or unmapped.
519 *
520 * @param arg Framebuffer instance
521 */
522static void fb_mapped_changed(void *arg)
523{
524 fb_instance_t *instance = (fb_instance_t *) arg;
525
526 if (!instance->parea.mapped) {
527 spinlock_lock(&instance->lock);
528 fb_redraw_internal(instance);
529 spinlock_unlock(&instance->lock);
530 }
531}
532
[a0e1b48]533/** Initialize framebuffer as a output character device
[76fca31]534 *
[bbf5657]535 */
[a71c158]536outdev_t *fb_init(fb_properties_t *props)
[bbf5657]537{
[63e27ef]538 assert(props);
539 assert(props->x > 0);
540 assert(props->y > 0);
541 assert(props->scan > 0);
[a35b458]542
[a71c158]543 rgb_conv_t rgb_conv;
544 unsigned int pixelbytes;
[a35b458]545
[965dc18]546 switch (props->visual) {
[2bc137c2]547 case VISUAL_INDIRECT_8:
[30885b9]548 rgb_conv = bgr_323;
[d6f270f]549 pixelbytes = 1;
550 break;
[19490ce]551 case VISUAL_RGB_5_5_5_LE:
552 rgb_conv = rgb_555_le;
553 pixelbytes = 2;
554 break;
555 case VISUAL_RGB_5_5_5_BE:
556 rgb_conv = rgb_555_be;
557 pixelbytes = 2;
558 break;
559 case VISUAL_RGB_5_6_5_LE:
560 rgb_conv = rgb_565_le;
[2bc137c2]561 pixelbytes = 2;
562 break;
[19490ce]563 case VISUAL_RGB_5_6_5_BE:
564 rgb_conv = rgb_565_be;
[d6f270f]565 pixelbytes = 2;
566 break;
[2bc137c2]567 case VISUAL_RGB_8_8_8:
[76fca31]568 rgb_conv = rgb_888;
[2bc137c2]569 pixelbytes = 3;
570 break;
[95b9963]571 case VISUAL_BGR_8_8_8:
572 rgb_conv = bgr_888;
573 pixelbytes = 3;
574 break;
[2bc137c2]575 case VISUAL_RGB_8_8_8_0:
[6ac14a70]576 rgb_conv = rgb_8880;
[2bc137c2]577 pixelbytes = 4;
[d6f270f]578 break;
[2bc137c2]579 case VISUAL_RGB_0_8_8_8:
[76fca31]580 rgb_conv = rgb_0888;
[d6f270f]581 pixelbytes = 4;
582 break;
[ccb0cbc]583 case VISUAL_BGR_0_8_8_8:
[76fca31]584 rgb_conv = bgr_0888;
[ccb0cbc]585 pixelbytes = 4;
586 break;
[30885b9]587 case VISUAL_BGR_8_8_8_0:
588 rgb_conv = bgr_8880;
589 pixelbytes = 4;
590 break;
[d6f270f]591 default:
[00a020d]592 LOG("Unsupported visual.");
[a71c158]593 return NULL;
[fcbca14f]594 }
[a35b458]595
[11b285d]596 outdev_t *fbdev = malloc(sizeof(outdev_t));
[a71c158]597 if (!fbdev)
598 return NULL;
[a35b458]599
[11b285d]600 fb_instance_t *instance = malloc(sizeof(fb_instance_t));
[a71c158]601 if (!instance) {
602 free(fbdev);
603 return NULL;
604 }
[a35b458]605
[a71c158]606 outdev_initialize("fbdev", fbdev, &fbdev_ops);
607 fbdev->data = instance;
[a35b458]608
[c263c77]609 spinlock_initialize(&instance->lock, "*fb.instance.lock");
[a35b458]610
[a71c158]611 instance->rgb_conv = rgb_conv;
612 instance->pixelbytes = pixelbytes;
613 instance->xres = props->x;
614 instance->yres = props->y;
615 instance->scanline = props->scan;
[a35b458]616
[7ddc2c7]617 instance->rowtrim = Y2ROW(instance->yres);
[a35b458]618
[a71c158]619 instance->cols = X2COL(instance->xres);
[7ddc2c7]620 instance->rows = FB_PAGES * instance->rowtrim;
[a35b458]621
[7ddc2c7]622 instance->start_row = instance->rows - instance->rowtrim;
623 instance->offset_row = instance->start_row;
624 instance->position = instance->start_row * instance->cols;
[a35b458]625
[a71c158]626 instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
627 instance->glyphbytes = ROW2Y(instance->glyphscanline);
628 instance->bgscanbytes = instance->xres * instance->pixelbytes;
[a35b458]629
[a71c158]630 size_t fbsize = instance->scanline * instance->yres;
631 size_t bbsize = instance->cols * instance->rows * sizeof(uint16_t);
632 size_t glyphsize = FONT_GLYPHS * instance->glyphbytes;
[a35b458]633
[adec5b45]634 instance->addr = (uint8_t *) km_map((uintptr_t) props->addr, fbsize,
[a1b9f63]635 KM_NATURAL_ALIGNMENT, PAGE_WRITE | PAGE_NOT_CACHEABLE);
[a71c158]636 if (!instance->addr) {
[00a020d]637 LOG("Unable to map framebuffer.");
[a71c158]638 free(instance);
639 free(fbdev);
640 return NULL;
[00a020d]641 }
[a35b458]642
[11b285d]643 instance->backbuf = (uint16_t *) malloc(bbsize);
[a71c158]644 if (!instance->backbuf) {
[00a020d]645 LOG("Unable to allocate backbuffer.");
[a71c158]646 free(instance);
647 free(fbdev);
648 return NULL;
[00a020d]649 }
[a35b458]650
[11b285d]651 instance->glyphs = (uint8_t *) malloc(glyphsize);
[a71c158]652 if (!instance->glyphs) {
[00a020d]653 LOG("Unable to allocate glyphs.");
[a71c158]654 free(instance->backbuf);
655 free(instance);
656 free(fbdev);
657 return NULL;
[00a020d]658 }
[a35b458]659
[11b285d]660 instance->bgscan = malloc(instance->bgscanbytes);
[a71c158]661 if (!instance->bgscan) {
[00a020d]662 LOG("Unable to allocate background pixel.");
[a71c158]663 free(instance->glyphs);
664 free(instance->backbuf);
665 free(instance);
666 free(fbdev);
667 return NULL;
[00a020d]668 }
[a35b458]669
[a71c158]670 memsetw(instance->backbuf, instance->cols * instance->rows, 0);
671 glyphs_render(instance);
[a35b458]672
[6f7071b]673 ddi_parea_init(&instance->parea);
[b366a6f4]674 instance->parea.pbase = props->addr;
675 instance->parea.frames = SIZE2FRAMES(fbsize);
676 instance->parea.unpriv = false;
677 instance->parea.mapped = false;
[e037cf37]678 instance->parea.mapped_changed = fb_mapped_changed;
679 instance->parea.arg = (void *) instance;
[b366a6f4]680 ddi_parea_register(&instance->parea);
[a35b458]681
[a71c158]682 if (!fb_exported) {
683 /*
[b366a6f4]684 * We export the kernel framebuffer for uspace usage.
685 * This is used in the case the uspace framebuffer
686 * driver is not self-sufficient.
[a71c158]687 */
688 sysinfo_set_item_val("fb", NULL, true);
689 sysinfo_set_item_val("fb.kind", NULL, 1);
690 sysinfo_set_item_val("fb.width", NULL, instance->xres);
691 sysinfo_set_item_val("fb.height", NULL, instance->yres);
692 sysinfo_set_item_val("fb.scanline", NULL, instance->scanline);
693 sysinfo_set_item_val("fb.visual", NULL, props->visual);
694 sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
[a35b458]695
[a71c158]696 fb_exported = true;
697 }
[a35b458]698
[a71c158]699 fb_redraw(fbdev);
700 return fbdev;
[bbf5657]701}
[b45c443]702
[94d614e]703/** @}
[b45c443]704 */
Note: See TracBrowser for help on using the repository browser.