source: mainline/genarch/src/fb/fb.c@ 1068f6a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1068f6a was 7633b109, checked in by Jakub Jermar <jakub@…>, 19 years ago

Change the way the framebuffer is mapped so that sparc64 is usable again.

  • Property mode set to 100644
File size: 10.0 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 <bitops.h>
36#include <align.h>
37#include <panic.h>
38#include <memstr.h>
39#include <config.h>
40
41#include "helenos.xbm"
42
43SPINLOCK_INITIALIZE(fb_lock);
44
45static __u8 *fbaddress = NULL;
46
47static __u8 *blankline = NULL;
48
49static unsigned int xres = 0;
50static unsigned int yres = 0;
51static unsigned int scanline = 0;
52static unsigned int bitspp = 0;
53static unsigned int pixelbytes = 0;
54
55static unsigned int position = 0;
56static unsigned int columns = 0;
57static unsigned int rows = 0;
58
59
60#define COL_WIDTH 8
61#define ROW_BYTES (scanline * FONT_SCANLINES)
62
63#define BGCOLOR 0x000080
64#define FGCOLOR 0xffff00
65#define LOGOCOLOR 0x2020b0
66
67#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
68#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
69#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
70
71#define POINTPOS(x, y) (y * scanline + x * pixelbytes)
72
73/***************************************************************/
74/* Pixel specific fuctions */
75
76static void (*putpixel)(unsigned int x, unsigned int y, int color);
77static int (*getpixel)(unsigned int x, unsigned int y);
78
79/** Put pixel - 24-bit depth, 1 free byte */
80static void putpixel_4byte(unsigned int x, unsigned int y, int color)
81{
82 *((__u32 *)(fbaddress + POINTPOS(x, y))) = color;
83}
84
85/** Return pixel color - 24-bit depth, 1 free byte */
86static int getpixel_4byte(unsigned int x, unsigned int y)
87{
88 return *((__u32 *)(fbaddress + POINTPOS(x, y))) & 0xffffff;
89}
90
91/** Put pixel - 24-bit depth */
92static void putpixel_3byte(unsigned int x, unsigned int y, int color)
93{
94 unsigned int startbyte = POINTPOS(x, y);
95
96#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
97 fbaddress[startbyte] = RED(color, 8);
98 fbaddress[startbyte + 1] = GREEN(color, 8);
99 fbaddress[startbyte + 2] = BLUE(color, 8);
100#else
101 fbaddress[startbyte + 2] = RED(color, 8);
102 fbaddress[startbyte + 1] = GREEN(color, 8);
103 fbaddress[startbyte + 0] = BLUE(color, 8);
104#endif
105}
106
107/** Return pixel color - 24-bit depth */
108static int getpixel_3byte(unsigned int x, unsigned int y)
109{
110 unsigned int startbyte = POINTPOS(x, y);
111
112#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
113 return fbaddress[startbyte] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 2];
114#else
115 return fbaddress[startbyte + 2] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 0];
116#endif
117}
118
119/** Put pixel - 16-bit depth (5:6:6) */
120static void putpixel_2byte(unsigned int x, unsigned int y, int color)
121{
122 /* 5-bit, 5-bits, 5-bits */
123 *((__u16 *)(fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
124}
125
126/** Return pixel color - 16-bit depth (5:6:6) */
127static int getpixel_2byte(unsigned int x, unsigned int y)
128{
129 int color = *((__u16 *)(fbaddress + POINTPOS(x, y)));
130 return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
131}
132
133/** Put pixel - 8-bit depth (3:2:3) */
134static void putpixel_1byte(unsigned int x, unsigned int y, int color)
135{
136 fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
137}
138
139/** Return pixel color - 8-bit depth (3:2:3) */
140static int getpixel_1byte(unsigned int x, unsigned int y)
141{
142 int color = fbaddress[POINTPOS(x, y)];
143 return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
144}
145
146/** Fill line with color BGCOLOR */
147static void clear_line(unsigned int y)
148{
149 unsigned int x;
150
151 for (x = 0; x < xres; x++)
152 (*putpixel)(x, y, BGCOLOR);
153}
154
155
156/** Fill screen with background color */
157static void clear_screen(void)
158{
159 unsigned int y;
160
161 for (y = 0; y < yres; y++)
162 clear_line(y);
163}
164
165
166/** Scroll screen one row up */
167static void scroll_screen(void)
168{
169 unsigned int i;
170 __u8 *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
171
172 memcpy((void *) fbaddress, (void *) &fbaddress[ROW_BYTES], scanline * yres - ROW_BYTES);
173
174 /* Clear last row */
175 if (blankline) {
176 memcpy((void *) lastline, (void *) blankline, ROW_BYTES);
177 } else {
178 for (i = 0; i < FONT_SCANLINES; i++)
179 clear_line((rows - 1) * FONT_SCANLINES + i);
180
181 if (config.mm_initialized) {
182 /* Save a blank line aside. */
183 blankline = (__u8 *) malloc(ROW_BYTES, FRAME_ATOMIC);
184 if (blankline)
185 memcpy((void *) blankline, (void *) lastline, ROW_BYTES);
186 }
187 }
188}
189
190
191static void invert_pixel(unsigned int x, unsigned int y)
192{
193 (*putpixel)(x, y, ~(*getpixel)(x, y));
194}
195
196
197/** Draw one line of glyph at a given position */
198static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
199{
200 unsigned int i;
201
202 for (i = 0; i < 8; i++)
203 if (glline & (1 << (7 - i))) {
204 (*putpixel)(x + i, y, FGCOLOR);
205 } else
206 (*putpixel)(x + i, y, BGCOLOR);
207}
208
209/***************************************************************/
210/* Character-console functions */
211
212/** Draw character at given position */
213static void draw_glyph(__u8 glyph, unsigned int col, unsigned int row)
214{
215 unsigned int y;
216
217 for (y = 0; y < FONT_SCANLINES; y++)
218 draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
219}
220
221/** Invert character at given position */
222static void invert_char(unsigned int col, unsigned int row)
223{
224 unsigned int x;
225 unsigned int y;
226
227 for (x = 0; x < COL_WIDTH; x++)
228 for (y = 0; y < FONT_SCANLINES; y++)
229 invert_pixel(col * COL_WIDTH + x, row * FONT_SCANLINES + y);
230}
231
232/** Draw character at default position */
233static void draw_char(char chr)
234{
235 draw_glyph(chr, position % columns, position / columns);
236}
237
238static void draw_logo(unsigned int startx, unsigned int starty)
239{
240 unsigned int x;
241 unsigned int y;
242 unsigned int byte;
243 unsigned int rowbytes;
244
245 rowbytes = (helenos_width - 1) / 8 + 1;
246
247 for (y = 0; y < helenos_height; y++)
248 for (x = 0; x < helenos_width; x++) {
249 byte = helenos_bits[rowbytes * y + x / 8];
250 byte >>= x % 8;
251 if (byte & 1)
252 (*putpixel)(startx + x, starty + y, LOGOCOLOR);
253 }
254}
255
256/***************************************************************/
257/* Stdout specific functions */
258
259static void invert_cursor(void)
260{
261 invert_char(position % columns, position / columns);
262}
263
264/** Print character to screen
265 *
266 * Emulate basic terminal commands
267 */
268static void fb_putchar(chardev_t *dev, char ch)
269{
270 spinlock_lock(&fb_lock);
271
272 switch (ch) {
273 case '\n':
274 invert_cursor();
275 position += columns;
276 position -= position % columns;
277 break;
278 case '\r':
279 invert_cursor();
280 position -= position % columns;
281 break;
282 case '\b':
283 invert_cursor();
284 if (position % columns)
285 position--;
286 break;
287 case '\t':
288 invert_cursor();
289 do {
290 draw_char(' ');
291 position++;
292 } while ((position % 8) && position < columns * rows);
293 break;
294 default:
295 draw_char(ch);
296 position++;
297 }
298
299 if (position >= columns * rows) {
300 position -= columns;
301 scroll_screen();
302 }
303
304 invert_cursor();
305
306 spinlock_unlock(&fb_lock);
307}
308
309static chardev_t framebuffer;
310static chardev_operations_t fb_ops = {
311 .write = fb_putchar,
312};
313
314
315/** Initialize framebuffer as a chardev output device
316 *
317 * @param addr Physical address of the framebuffer
318 * @param x Screen width in pixels
319 * @param y Screen height in pixels
320 * @param bpp Bits per pixel (8, 16, 24, 32)
321 * @param scan Bytes per one scanline
322 *
323 */
324void fb_init(__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan)
325{
326 switch (bpp) {
327 case 8:
328 putpixel = putpixel_1byte;
329 getpixel = getpixel_1byte;
330 pixelbytes = 1;
331 break;
332 case 16:
333 putpixel = putpixel_2byte;
334 getpixel = getpixel_2byte;
335 pixelbytes = 2;
336 break;
337 case 24:
338 putpixel = putpixel_3byte;
339 getpixel = getpixel_3byte;
340 pixelbytes = 3;
341 break;
342 case 32:
343 putpixel = putpixel_4byte;
344 getpixel = getpixel_4byte;
345 pixelbytes = 4;
346 break;
347 default:
348 panic("Unsupported bpp");
349 }
350
351 unsigned int fbsize = scan * y;
352 unsigned int fborder;
353
354 if (fbsize <= FRAME_SIZE)
355 fborder = 0;
356 else
357 fborder = (fnzb32(fbsize - 1) + 1) - FRAME_WIDTH;
358
359 /* Map the framebuffer */
360 fbaddress = (__u8 *) PA2KA(PFN2ADDR(frame_alloc(fborder, FRAME_KA)));
361
362 fb_map_arch((__address) fbaddress, (__address) addr, fbsize);
363
364 xres = x;
365 yres = y;
366 bitspp = bpp;
367 scanline = scan;
368
369 rows = y / FONT_SCANLINES;
370 columns = x / COL_WIDTH;
371
372 clear_screen();
373 draw_logo(xres - helenos_width, 0);
374 invert_cursor();
375
376 chardev_initialize("fb", &framebuffer, &fb_ops);
377 stdout = &framebuffer;
378
379 sysinfo_set_item_val("fb", NULL, true);
380 sysinfo_set_item_val("fb.width", NULL, x);
381 sysinfo_set_item_val("fb.height", NULL, y);
382 sysinfo_set_item_val("fb.bpp", NULL, bpp);
383 sysinfo_set_item_val("fb.scanline", NULL, scan);
384 sysinfo_set_item_val("fb.address.physical", NULL, addr);
385}
Note: See TracBrowser for help on using the repository browser.