Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3706 → Rev 3707

/trunk/kernel/genarch/include/fb/font-8x16.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
35,11 → 35,14
#ifndef KERN_FONT_8X16_H_
#define KERN_FONT_8X16_H_
 
#define FONT_GLIPHS 256
#define FONT_SCANLINES 16
#define FONT_GLYPHS 256
#define FONT_WIDTH 8
#define FONT_SCANLINES 16
 
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES];
#include <arch/types.h>
 
extern uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES];
 
#endif
 
/** @}
/trunk/kernel/genarch/include/fb/visuals.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
35,15 → 35,15
#ifndef KERN_VISUALS_H_
#define KERN_VISUALS_H_
 
#define VISUAL_INDIRECT_8 0
#define VISUAL_INDIRECT_8 0
 
#define VISUAL_RGB_5_5_5 1
#define VISUAL_RGB_5_6_5 2
#define VISUAL_RGB_8_8_8 3
#define VISUAL_RGB_8_8_8_0 4
#define VISUAL_RGB_0_8_8_8 5
#define VISUAL_RGB_5_5_5 1
#define VISUAL_RGB_5_6_5 2
#define VISUAL_RGB_8_8_8 3
#define VISUAL_RGB_8_8_8_0 4
#define VISUAL_RGB_0_8_8_8 5
 
#define VISUAL_BGR_0_8_8_8 6
#define VISUAL_BGR_0_8_8_8 6
 
#endif
 
/trunk/kernel/genarch/include/fb/fb.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
65,6 → 65,8
} fb_properties_t;
 
SPINLOCK_EXTERN(fb_lock);
 
void fb_redraw(void);
void fb_init(fb_properties_t *props);
 
#endif
/trunk/kernel/genarch/src/fb/helenos.xbm
File deleted
/trunk/kernel/genarch/src/fb/fb.c
1,4 → 1,5
/*
* Copyright (c) 2008 Martin Decky
* Copyright (c) 2006 Ondrej Palkovsky
* All rights reserved.
*
26,7 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch
/** @addtogroup genarch
* @{
*/
/** @file
39,6 → 40,7
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <mm/slab.h>
#include <align.h>
#include <panic.h>
#include <memstr.h>
#include <config.h>
47,137 → 49,109
#include <ddi/ddi.h>
#include <arch/types.h>
 
#include "helenos.xbm"
SPINLOCK_INITIALIZE(fb_lock);
 
static parea_t fb_parea; /**< Physical memory area for fb. */
/**< Physical memory area for fb. */
static parea_t fb_parea;
 
SPINLOCK_INITIALIZE(fb_lock);
static uint8_t *fb_addr;
static uint8_t *backbuf;
static uint8_t *glyphs;
 
static uint8_t *fbaddress = NULL;
static void *bgpixel;
 
static uint8_t *blankline = NULL;
static uint8_t *dbbuffer = NULL; /* Buffer for fast scrolling console */
static index_t dboffset;
static unsigned int xres;
static unsigned int yres;
 
static unsigned int xres = 0;
static unsigned int yres = 0;
static unsigned int scanline = 0;
static unsigned int pixelbytes = 0;
#ifdef FB_INVERT_COLORS
static bool invert_colors = true;
#else
static bool invert_colors = false;
#endif
static unsigned int scanline;
static unsigned int glyphscanline;
 
static unsigned int pixelbytes;
static unsigned int glyphbytes;
 
static unsigned int cols;
static unsigned int rows;
static unsigned int position = 0;
static unsigned int columns = 0;
static unsigned int rows = 0;
 
#define COL_WIDTH 8
#define ROW_BYTES (scanline * FONT_SCANLINES)
#define BG_COLOR 0x000080
#define FG_COLOR 0xffff00
 
#define BGCOLOR 0x000080
#define FGCOLOR 0xffff00
#define LOGOCOLOR 0x2020b0
#define CURSOR 219
 
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
 
#define POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes)
#define COL2X(col) ((col) * FONT_WIDTH)
#define ROW2Y(row) ((row) * FONT_SCANLINES)
 
/***************************************************************/
/* Pixel specific fuctions */
#define X2COL(x) ((x) / FONT_WIDTH)
#define Y2ROW(y) ((y) / FONT_SCANLINES)
 
static void (*rgb2scr)(void *, int);
static int (*scr2rgb)(void *);
#define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes)
#define BB_POS(col, row) ((row) * cols + (col))
#define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline)
 
static inline int COLOR(int color)
{
return invert_colors ? ~color : color;
}
 
/* Conversion routines between different color representations */
static void rgb_byte0888(void *dst, int rgb)
{
*((int *) dst) = rgb;
}
static void (*rgb_conv)(void *, uint32_t);
 
static int byte0888_rgb(void *src)
{
return (*((int *) src)) & 0xffffff;
}
 
static void bgr_byte0888(void *dst, int rgb)
/** ARGB 8:8:8:8 conversion
*
*/
static void rgb_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
RED(rgb, 8);
*((uint32_t *) dst) = rgb & 0xffffff;
}
 
static int byte0888_bgr(void *src)
 
/** ABGR 8:8:8:8 conversion
*
*/
static void bgr_0888(void *dst, uint32_t rgb)
{
int color = *(uint32_t *)(src);
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
((color >> 16) & 0xff);
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
}
 
static void rgb_byte888(void *dst, int rgb)
 
/** BGR 8:8:8 conversion
*
*/
static void rgb_888(void *dst, uint32_t rgb)
{
uint8_t *scr = (uint8_t *) dst;
#if defined(FB_INVERT_ENDIAN)
scr[0] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[2] = BLUE(rgb, 8);
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8)
| (*((uint32_t *) dst) & 0xff0000);
#else
scr[2] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[0] = BLUE(rgb, 8);
*((uint32_t *) dst)
= (rgb & 0xffffff) | (*((uint32_t *) dst) & 0xff0000);
#endif
}
 
static int byte888_rgb(void *src)
{
uint8_t *scr = (uint8_t *) src;
#if defined(FB_INVERT_ENDIAN)
return scr[0] << 16 | scr[1] << 8 | scr[2];
#else
return scr[2] << 16 | scr[1] << 8 | scr[0];
#endif
}
 
/** 16-bit depth (5:5:5) */
static void rgb_byte555(void *dst, int rgb)
/** RGB 5:5:5 conversion
*
*/
static void rgb_555(void *dst, uint32_t rgb)
{
/* 5-bit, 5-bits, 5-bits */
*((uint16_t *) dst) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
BLUE(rgb, 5);
*((uint16_t *) dst)
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
}
 
/** 16-bit depth (5:5:5) */
static int byte555_rgb(void *src)
{
int color = *(uint16_t *)(src);
return (((color >> 10) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
}
 
/** 16-bit depth (5:6:5) */
static void rgb_byte565(void *dst, int rgb)
/** RGB 5:6:5 conversion
*
*/
static void rgb_565(void *dst, uint32_t rgb)
{
/* 5-bit, 6-bits, 5-bits */
*((uint16_t *) dst) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
BLUE(rgb, 5);
*((uint16_t *) dst)
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
}
 
/** 16-bit depth (5:6:5) */
static int byte565_rgb(void *src)
{
int color = *(uint16_t *)(src);
return (((color >> 11) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
}
 
/** Put pixel - 8-bit depth (color palette/3:2:3, inverted)
/** RGB 3:2:3
*
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
* will most likely use a color palette. The color appearance
185,7 → 159,7
* palette. This could be fixed by supporting custom palette
* and setting it to simulate the 8-bit truecolor.
*
* Currently we set the palette on the sparc64 port.
* Currently we set the palette on the ia32 and sparc64 port.
*
* Note that the byte is being inverted by this function. The reason is
* that we would like to use a color palette where the white color code
193,207 → 167,84
* use these codes for black and white and prevent to set codes
* 0 and 255 to other colors.
*/
static void rgb_byte8(void *dst, int rgb)
static void rgb_323(void *dst, uint32_t rgb)
{
*((uint8_t *) dst) = 255 - (RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 |
BLUE(rgb, 3));
*((uint8_t *) dst)
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
}
 
/** Return pixel color - 8-bit depth (color palette/3:2:3)
 
/** Draw character at given position
*
* See the comment for rgb_byte().
*/
static int byte8_rgb(void *src)
static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row)
{
int color = 255 - (*(uint8_t *)src);
return (((color >> 5) & 0x7) << (16 + 5)) |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
unsigned int x = COL2X(col);
unsigned int y = ROW2Y(row);
unsigned int yd;
backbuf[BB_POS(col, row)] = glyph;
for (yd = 0; yd < FONT_SCANLINES; yd++)
memcpy(&fb_addr[FB_POS(x, y + yd)],
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
}
 
static void putpixel(unsigned int x, unsigned int y, int color)
{
(*rgb2scr)(&fbaddress[POINTPOS(x, y)], COLOR(color));
 
if (dbbuffer) {
int dline = (y + dboffset) % yres;
(*rgb2scr)(&dbbuffer[POINTPOS(x, dline)], COLOR(color));
}
}
 
/** Get pixel from viewport */
static int getpixel(unsigned int x, unsigned int y)
{
if (dbbuffer) {
int dline = (y + dboffset) % yres;
return COLOR((*scr2rgb)(&dbbuffer[POINTPOS(x, dline)]));
}
return COLOR((*scr2rgb)(&fbaddress[POINTPOS(x, y)]));
}
 
 
/** Fill screen with background color */
static void clear_screen(void)
{
unsigned int y;
 
for (y = 0; y < yres; y++) {
memcpy(&fbaddress[scanline * y], blankline, xres * pixelbytes);
if (dbbuffer)
memcpy(&dbbuffer[scanline * y], blankline,
xres * pixelbytes);
}
}
 
 
/** Scroll screen one row up */
/** Scroll screen down by one row
*
*
*/
static void scroll_screen(void)
{
if (dbbuffer) {
count_t first;
unsigned int row;
for (row = 0; row < rows; row++) {
unsigned int y = ROW2Y(row);
unsigned int yd;
/* Clear the last row */
memcpy(&dbbuffer[dboffset * scanline], blankline, ROW_BYTES);
dboffset = (dboffset + FONT_SCANLINES) % yres;
first = yres - dboffset;
/* Move all rows one row up */
if (xres * pixelbytes == scanline) {
memcpy(fbaddress, &dbbuffer[dboffset * scanline],
first * scanline);
memcpy(&fbaddress[first * scanline], dbbuffer,
dboffset * scanline);
} else {
/*
* When the scanline is bigger than number of bytes
* in the X-resolution, chances are that the
* frame buffer memory past the X-resolution is special
* in some way. For example, the SUNW,ffb framebuffer
* wraps this area around the beginning of the same
* line. To avoid troubles, copy only memory as
* specified by the resolution.
*/
unsigned int i;
 
for (i = 0; i < first; i++)
memcpy(&fbaddress[i * scanline],
&dbbuffer[(dboffset + i) * scanline],
xres * pixelbytes);
for (i = 0; i < dboffset; i++)
memcpy(&fbaddress[(first + i) * scanline],
&dbbuffer[i * scanline], xres * pixelbytes);
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = 0; col < cols; col++, x += FONT_WIDTH) {
uint8_t glyph;
if (row < rows - 1) {
if (backbuf[BB_POS(col, row)] == backbuf[BB_POS(col, row + 1)])
continue;
glyph = backbuf[BB_POS(col, row + 1)];
} else
glyph = 0;
memcpy(&fb_addr[FB_POS(x, y + yd)],
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
}
}
} else {
uint8_t *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
if (xres * pixelbytes == scanline) {
/* Move all rows one row up */
memcpy((void *) fbaddress,
(void *) &fbaddress[ROW_BYTES],
scanline * yres - ROW_BYTES);
/* Clear the last row */
memcpy((void *) lastline, (void *) blankline,
ROW_BYTES);
} else {
/*
* See the comment in the dbbuffer case.
*/
unsigned int i;
 
/* Move all rows one row up */
for (i = 0; i < yres - FONT_SCANLINES; i++)
memcpy(&fbaddress[i * scanline],
&fbaddress[(i + FONT_SCANLINES) * scanline],
xres * pixelbytes);
/* Clear the last row */
for (i = 0; i < FONT_SCANLINES; i++)
memcpy(&lastline[i * scanline],
&blankline[i * scanline],
xres * pixelbytes);
}
}
memcpy(backbuf, backbuf + cols, cols * (rows - 1));
memsetb(&backbuf[BB_POS(0, rows - 1)], cols, 0);
}
 
 
static void invert_pixel(unsigned int x, unsigned int y)
static void cursor_put(void)
{
putpixel(x, y, ~getpixel(x, y));
draw_glyph(CURSOR, position % cols, position / cols);
}
 
 
/** Draw one line of glyph at a given position */
static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
static void cursor_remove(void)
{
unsigned int i;
 
for (i = 0; i < 8; i++)
if (glline & (1 << (7 - i))) {
putpixel(x + i, y, FGCOLOR);
} else
putpixel(x + i, y, BGCOLOR);
draw_glyph(0, position % cols, position / cols);
}
 
/***************************************************************/
/* Character-console functions */
 
/** Draw character at given position */
static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row)
{
unsigned int y;
 
for (y = 0; y < FONT_SCANLINES; y++)
draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y],
col * COL_WIDTH, row * FONT_SCANLINES + y);
}
 
/** Invert character at given position */
static void invert_char(unsigned int col, unsigned int row)
{
unsigned int x;
unsigned int y;
 
for (x = 0; x < COL_WIDTH; x++)
for (y = 0; y < FONT_SCANLINES; y++)
invert_pixel(col * COL_WIDTH + x,
row * FONT_SCANLINES + y);
}
 
/** Draw character at default position */
static void draw_char(char chr)
{
draw_glyph(chr, position % columns, position / columns);
}
 
static void draw_logo(unsigned int startx, unsigned int starty)
{
unsigned int x;
unsigned int y;
unsigned int byte;
unsigned int rowbytes;
 
rowbytes = (helenos_width - 1) / 8 + 1;
 
for (y = 0; y < helenos_height; y++)
for (x = 0; x < helenos_width; x++) {
byte = helenos_bits[rowbytes * y + x / 8];
byte >>= x % 8;
if (byte & 1)
putpixel(startx + x, starty + y,
COLOR(LOGOCOLOR));
}
}
 
/***************************************************************/
/* Stdout specific functions */
 
static void invert_cursor(void)
{
invert_char(position % columns, position / columns);
}
 
/** Print character to screen
*
* Emulate basic terminal commands
* Emulate basic terminal commands.
*
*/
static void fb_putchar(chardev_t *dev, char ch)
{
401,37 → 252,37
switch (ch) {
case '\n':
invert_cursor();
position += columns;
position -= position % columns;
cursor_remove();
position += cols;
position -= position % cols;
break;
case '\r':
invert_cursor();
position -= position % columns;
cursor_remove();
position -= position % cols;
break;
case '\b':
invert_cursor();
if (position % columns)
cursor_remove();
if (position % cols)
position--;
break;
case '\t':
invert_cursor();
cursor_remove();
do {
draw_char(' ');
draw_glyph((uint8_t) ' ', position % cols, position / cols);
position++;
} while ((position % 8) && position < columns * rows);
} while ((position % 8) && (position < cols * rows));
break;
default:
draw_char(ch);
draw_glyph((uint8_t) ch, position % cols, position / cols);
position++;
}
if (position >= columns * rows) {
position -= columns;
if (position >= cols * rows) {
position -= cols;
scroll_screen();
}
invert_cursor();
cursor_put();
spinlock_unlock(&fb_lock);
}
442,46 → 293,116
};
 
 
/** Render glyphs
*
* Convert glyphs from device independent font
* description to current visual representation.
*
*/
static void render_glyphs(void)
{
unsigned int glyph;
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
unsigned int y;
for (y = 0; y < FONT_SCANLINES; y++) {
unsigned int x;
for (x = 0; x < FONT_WIDTH; x++)
rgb_conv(&glyphs[GLYPH_POS(glyph, y) + x * pixelbytes],
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) ? FG_COLOR : BG_COLOR);
}
}
rgb_conv(bgpixel, BG_COLOR);
}
 
 
/** Refresh the screen
*
*/
void fb_redraw(void)
{
unsigned int row;
for (row = 0; row < rows; row++) {
unsigned int y = ROW2Y(row);
unsigned int yd;
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = 0; col < cols; col++, x += FONT_WIDTH)
memcpy(&fb_addr[FB_POS(x, y + yd)],
&glyphs[GLYPH_POS(backbuf[BB_POS(col, row)], yd)],
glyphscanline);
}
}
if (COL2X(cols) < xres) {
unsigned int y;
for (y = 0; y < yres; y++) {
unsigned int x;
for (x = COL2X(cols); x < xres; x++)
memcpy(&fb_addr[FB_POS(x, y)], bgpixel, pixelbytes);
}
}
if (ROW2Y(rows) < yres) {
unsigned int y;
for (y = ROW2Y(rows); y < yres; y++) {
unsigned int x;
for (x = 0; x < xres; x++)
memcpy(&fb_addr[FB_POS(x, y)], bgpixel, pixelbytes);
}
}
}
 
 
/** Initialize framebuffer as a chardev output device
*
* @param props Properties of the framebuffer device.
* @param addr Physical address of the framebuffer
* @param x Screen width in pixels
* @param y Screen height in pixels
* @param scan Bytes per one scanline
* @param visual Color model
*
*/
void fb_init(fb_properties_t *props)
{
switch (props->visual) {
case VISUAL_INDIRECT_8:
rgb2scr = rgb_byte8;
scr2rgb = byte8_rgb;
rgb_conv = rgb_323;
pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5:
rgb2scr = rgb_byte555;
scr2rgb = byte555_rgb;
rgb_conv = rgb_555;
pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5:
rgb2scr = rgb_byte565;
scr2rgb = byte565_rgb;
rgb_conv = rgb_565;
pixelbytes = 2;
break;
case VISUAL_RGB_8_8_8:
rgb2scr = rgb_byte888;
scr2rgb = byte888_rgb;
rgb_conv = rgb_888;
pixelbytes = 3;
break;
case VISUAL_RGB_8_8_8_0:
rgb2scr = rgb_byte888;
scr2rgb = byte888_rgb;
rgb_conv = rgb_888;
pixelbytes = 4;
break;
case VISUAL_RGB_0_8_8_8:
rgb2scr = rgb_byte0888;
scr2rgb = byte0888_rgb;
rgb_conv = rgb_0888;
pixelbytes = 4;
break;
case VISUAL_BGR_0_8_8_8:
rgb2scr = bgr_byte0888;
scr2rgb = byte0888_bgr;
rgb_conv = bgr_0888;
pixelbytes = 4;
break;
default:
488,60 → 409,56
panic("Unsupported visual.\n");
}
unsigned int fbsize = props->scan * props->y;
/* Map the framebuffer */
fbaddress = (uint8_t *) hw_map((uintptr_t) props->addr,
fbsize + props->offset);
fbaddress += props->offset;
xres = props->x;
yres = props->y;
scanline = props->scan;
rows = props->y / FONT_SCANLINES;
columns = props->x / COL_WIDTH;
 
cols = xres / FONT_WIDTH;
rows = yres / FONT_SCANLINES;
glyphscanline = FONT_WIDTH * pixelbytes;
glyphbytes = glyphscanline * FONT_SCANLINES;
unsigned int fbsize = scanline * yres;
unsigned int bbsize = cols * rows;
unsigned int glyphsize = FONT_GLYPHS * glyphbytes;
backbuf = (uint8_t *) malloc(bbsize, 0);
if (!backbuf)
panic("Unable to allocate backbuffer.\n");
glyphs = (uint8_t *) malloc(glyphsize, 0);
if (!glyphs)
panic("Unable to allocate glyphs.\n");
bgpixel = malloc(pixelbytes, 0);
if (!bgpixel)
panic("Unable to allocate background pixel.\n");
memsetb(backbuf, bbsize, 0);
memsetb(glyphs, glyphsize, 0);
memsetb(bgpixel, pixelbytes, 0);
render_glyphs();
fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
fb_parea.pbase = (uintptr_t) props->addr + props->offset;
fb_parea.vbase = (uintptr_t) fbaddress;
fb_parea.vbase = (uintptr_t) fb_addr;
fb_parea.frames = SIZE2FRAMES(fbsize);
fb_parea.cacheable = false;
ddi_parea_register(&fb_parea);
 
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 1);
sysinfo_set_item_val("fb.width", NULL, xres);
sysinfo_set_item_val("fb.height", NULL, yres);
sysinfo_set_item_val("fb.scanline", NULL, props->scan);
sysinfo_set_item_val("fb.scanline", NULL, scanline);
sysinfo_set_item_val("fb.visual", NULL, props->visual);
sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
sysinfo_set_item_val("fb.offset", NULL, props->offset);
sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors);
 
/* Allocate double buffer */
unsigned int order = fnzb(SIZE2FRAMES(fbsize) - 1) + 1;
dbbuffer = (uint8_t *) frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
if (!dbbuffer)
printf("Failed to allocate scroll buffer.\n");
dboffset = 0;
 
/* Initialized blank line */
blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC);
if (!blankline)
panic("Failed to allocate blank line for framebuffer.");
unsigned int x, y;
for (y = 0; y < FONT_SCANLINES; y++)
for (x = 0; x < xres; x++)
(*rgb2scr)(&blankline[POINTPOS(x, y)], COLOR(BGCOLOR));
clear_screen();
 
/* Update size of screen to match text area */
yres = rows * FONT_SCANLINES;
 
draw_logo(xres - helenos_width, 0);
invert_cursor();
 
fb_redraw();
chardev_initialize("fb", &framebuffer, &fb_ops);
stdout = &framebuffer;
}
/trunk/kernel/genarch/src/fb/font-8x16.c
34,7 → 34,7
 
#include <genarch/fb/font-8x16.h>
 
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = {
uint8_t fb_font[FONT_GLYPHS * FONT_SCANLINES] = {
 
/* 0 0x00 '^@' */
0x00, /* 00000000 */
/trunk/kernel/genarch/src/mm/asid.c
32,7 → 32,7
 
/**
* @file
* @brief ASID management.
* @brief ASID management.
*
* Modern processor architectures optimize TLB utilization
* by using ASIDs (a.k.a. memory contexts on sparc64 and
/trunk/kernel/genarch/src/acpi/acpi.c
49,8 → 49,12
struct acpi_rsdt *acpi_rsdt = NULL;
struct acpi_xsdt *acpi_xsdt = NULL;
 
struct acpi_signature_map signature_map[] = {
{ (uint8_t *)"APIC", (void *) &acpi_madt, "Multiple APIC Description Table" }
struct acpi_signature_map signature_map[] = {
{
(uint8_t *) "APIC",
(void *) &acpi_madt,
"Multiple APIC Description Table"
}
};
 
static int rsdp_check(uint8_t *rsdp) {
105,7 → 109,7
if (!acpi_sdt_check((uint8_t *) h))
goto next;
*signature_map[j].sdt_ptr = h;
printf("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
}
}
next:
126,7 → 130,7
if (!acpi_sdt_check((uint8_t *) h))
goto next;
*signature_map[j].sdt_ptr = h;
printf("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
LOG("%p: ACPI %s\n", *signature_map[j].sdt_ptr, signature_map[j].description);
}
}
next:
160,7 → 164,7
return;
 
rsdp_found:
printf("%p: ACPI Root System Description Pointer\n", acpi_rsdp);
LOG("%p: ACPI Root System Description Pointer\n", acpi_rsdp);
 
acpi_rsdt = (struct acpi_rsdt *) (unative_t) acpi_rsdp->rsdt_address;
if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address);
/trunk/kernel/generic/include/console/kconsole.h
87,7 → 87,8
extern link_t cmd_head;
 
extern void kconsole_init(void);
extern void kconsole(void *prompt);
extern void kconsole(char *prompt, char *msg, bool kcon);
extern void kconsole_thread(void *data);
 
extern int cmd_register(cmd_info_t *cmd);
 
/trunk/kernel/generic/src/main/kinit.c
82,8 → 82,11
*/
void kinit(void *arg)
{
thread_t *t;
 
#if defined(CONFIG_SMP) || defined(CONFIG_KCONSOLE)
thread_t *thread;
#endif
 
/*
* Detach kinit as nobody will call thread_join_timeout() on it.
*/
100,23 → 103,19
* not mess together with kcpulb threads.
* Just a beautification.
*/
if ((t = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED,
"kmp", true))) {
spinlock_lock(&t->lock);
t->cpu = &cpus[0];
spinlock_unlock(&t->lock);
thread_ready(t);
thread = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED, "kmp", true);
if (thread != NULL) {
spinlock_lock(&thread->lock);
thread->cpu = &cpus[0];
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
panic("thread_create/kmp\n");
thread_join(t);
thread_detach(t);
panic("Unable to create kmp thread\n");
thread_join(thread);
thread_detach(thread);
}
#endif /* CONFIG_SMP */
/*
* Now that all CPUs are up, we can report what we've found.
*/
cpu_list();
 
#ifdef CONFIG_SMP
if (config.cpu_count > 1) {
count_t i;
125,35 → 124,37
* For each CPU, create its load balancing thread.
*/
for (i = 0; i < config.cpu_count; i++) {
 
if ((t = thread_create(kcpulb, NULL, TASK,
THREAD_FLAG_WIRED, "kcpulb", true))) {
spinlock_lock(&t->lock);
t->cpu = &cpus[i];
spinlock_unlock(&t->lock);
thread_ready(t);
thread = thread_create(kcpulb, NULL, TASK, THREAD_FLAG_WIRED, "kcpulb", true);
if (thread != NULL) {
spinlock_lock(&thread->lock);
thread->cpu = &cpus[i];
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
panic("thread_create/kcpulb\n");
printf("Unable to create kcpulb thread for cpu" PRIc "\n", i);
 
}
}
#endif /* CONFIG_SMP */
 
/*
* At this point SMP, if present, is configured.
*/
arch_post_smp_init();
 
/*
* Create kernel console.
*/
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole",
false);
if (t)
thread_ready(t);
else
panic("thread_create/kconsole\n");
 
#ifdef CONFIG_KCONSOLE
if (stdin) {
/*
* Create kernel console.
*/
thread = thread_create(kconsole_thread, NULL, TASK, 0, "kconsole", false);
if (thread != NULL)
thread_ready(thread);
else
printf("Unable to create kconsole thread\n");
}
#endif /* CONFIG_KCONSOLE */
interrupts_enable();
/*
164,14 → 165,14
for (i = 0; i < init.cnt; i++) {
if (init.tasks[i].addr % FRAME_SIZE) {
printf("init[%" PRIc "].addr is not frame aligned", i);
printf("init[%" PRIc "].addr is not frame aligned\n", i);
continue;
}
 
int rc = program_create_from_image((void *) init.tasks[i].addr,
"init-bin", &programs[i]);
 
if (rc == 0 && programs[i].task != NULL) {
if ((rc == 0) && (programs[i].task != NULL)) {
/*
* Set capabilities to init userspace tasks.
*/
184,12 → 185,10
/* It was the program loader and was registered */
} else {
/* RAM disk image */
int rd = init_rd((rd_header_t *) init.tasks[i].addr,
init.tasks[i].size);
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %" PRIc " not used, error "
"code %d.\n", i, rd);
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
}
}
203,12 → 202,18
}
}
 
#ifdef CONFIG_KCONSOLE
if (!stdin) {
printf("kinit: No stdin\nKernel alive: ");
uint64_t i = 0;
while (1) {
printf(PRIu64 " ", i);
thread_sleep(1);
printf("kinit... ");
i++;
}
}
#endif /* CONFIG_KCONSOLE */
}
 
/** @}
/trunk/kernel/generic/src/main/main.c
191,8 → 191,6
{
/* Keep this the first thing. */
the_initialize(THE);
 
LOG();
version_print();
200,8 → 198,8
"\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs,
config.base, config.kernel_size, config.stack_base,
config.stack_size);
 
#ifdef CONFIG_KCONSOLE
/*
* kconsole data structures must be initialized very early
* because other subsystems will register their respective
208,6 → 206,7
* commands.
*/
LOG_EXEC(kconsole_init());
#endif
/*
* Exception handler initialization, before architecture
252,7 → 251,7
if (init.cnt > 0) {
count_t i;
for (i = 0; i < init.cnt; i++)
printf("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
271,8 → 270,8
/*
* Create the first thread.
*/
thread_t *kinit_thread = thread_create(kinit, NULL, kernel, 0, "kinit",
true);
thread_t *kinit_thread
= thread_create(kinit, NULL, kernel, 0, "kinit", true);
if (!kinit_thread)
panic("Can't create kinit thread\n");
LOG_EXEC(thread_ready(kinit_thread));
/trunk/kernel/generic/src/cpu/cpu.c
86,7 → 86,7
}
#endif /* CONFIG_SMP */
 
CPU = &cpus[config.cpu_active-1];
CPU = &cpus[config.cpu_active - 1];
CPU->active = 1;
CPU->tlb_active = 1;
/trunk/kernel/generic/src/interrupt/interrupt.c
109,8 → 109,10
panic("Unhandled exception %d.", n);
}
 
#ifdef CONFIG_KCONSOLE
 
/** kconsole cmd - print all exceptions */
static int exc_print_cmd(cmd_arg_t *argv)
static int cmd_exc_print(cmd_arg_t *argv)
{
#if (IVT_ITEMS > 0)
unsigned int i;
158,15 → 160,18
return 1;
}
 
 
static cmd_info_t exc_info = {
.name = "exc",
.description = "Print exception table.",
.func = exc_print_cmd,
.func = cmd_exc_print,
.help = NULL,
.argc = 0,
.argv = NULL
};
 
#endif
 
/** Initialize generic exception handling support */
void exc_init(void)
{
175,9 → 180,11
for (i = 0; i < IVT_ITEMS; i++)
exc_register(i, "undef", (iroutine) exc_undef);
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&exc_info);
if (!cmd_register(&exc_info))
panic("could not register command %s\n", exc_info.name);
printf("Cannot register command %s\n", exc_info.name);
#endif
}
 
/** @}
/trunk/kernel/generic/src/console/console.c
167,7 → 167,7
printf("cpu%u: ", CPU->id);
else
printf("cpu: ");
printf("halted - no kconsole\n");
printf("halted (no kconsole)\n");
cpu_halt();
}
 
/trunk/kernel/generic/src/console/cmd.c
501,7 → 501,7
for (i = 0; basic_commands[i]; i++) {
cmd_initialize(basic_commands[i]);
if (!cmd_register(basic_commands[i]))
panic("could not register command %s\n", basic_commands[i]->name);
printf("Cannot register command %s\n", basic_commands[i]->name);
}
}
 
/trunk/kernel/generic/src/console/kconsole.c
401,11 → 401,15
return current;
}
 
/** Kernel console managing thread.
/** Kernel console prompt.
*
* @param prompt Kernel console prompt (e.g kconsole/panic).
* @param msg Message to display in the beginning.
* @param kcon Wait for keypress to show the prompt
* and never exit.
*
*/
void kconsole(void *prompt)
void kconsole(char *prompt, char *msg, bool kcon)
{
cmd_info_t *cmd_info;
count_t len;
412,25 → 416,42
char *cmdline;
 
if (!stdin) {
printf("%s: no stdin\n", __func__);
LOG("No stdin for kernel console");
return;
}
if (msg)
printf("%s", msg);
if (kcon)
_getc(stdin);
while (true) {
cmdline = clever_readline((char *) prompt, stdin);
len = strlen(cmdline);
if (!len)
continue;
cmd_info = parse_cmdline(cmdline, len);
if (!cmd_info)
continue;
if (strncmp(cmd_info->name, "exit",
min(strlen(cmd_info->name), 5)) == 0)
if ((!kcon)
&& (strncmp(cmd_info->name, "exit", min(strlen(cmd_info->name), 5)) == 0))
break;
(void) cmd_info->func(cmd_info->argv);
}
}
 
/** Kernel console managing thread.
*
*/
void kconsole_thread(void *data)
{
kconsole("kconsole", "Kernel console ready (press any key to activate)\n", true);
}
 
static int parse_int_arg(char *text, size_t len, unative_t *result)
{
static char symname[MAX_SYMBOL_NAME];
/trunk/kernel/generic/src/lib/func.c
55,8 → 55,6
#ifdef CONFIG_DEBUG
bool rundebugger = false;
 
// TODO test_and_set not defined on all arches
// if (!test_and_set(&haltstate))
if (!atomic_get(&haltstate)) {
atomic_set(&haltstate, 1);
rundebugger = true;
66,12 → 64,12
#endif
 
interrupts_disable();
#ifdef CONFIG_DEBUG
if (rundebugger) {
printf("\n");
kconsole("panic"); /* Run kconsole as a last resort to user */
}
#endif
#if (defined(CONFIG_DEBUG)) && (defined(CONFIG_KCONSOLE))
if (rundebugger)
kconsole("panic", "\nLast resort kernel console ready\n", false);
#endif
if (CPU)
printf("cpu%u: halted\n", CPU->id);
else
/trunk/kernel/generic/src/mm/as.c
146,8 → 146,12
AS_KERNEL = as_create(FLAG_AS_KERNEL);
if (!AS_KERNEL)
panic("can't create kernel address space\n");
panic("Cannot create kernel address space\n");
/* Make sure the kernel address space
* reference count never drops to zero.
*/
atomic_set(&AS_KERNEL->refcount, 1);
}
 
/** Create address space.
176,7 → 180,7
#else
page_table_create(flags);
#endif
 
return as;
}
 
769,11 → 773,12
* In order for this to work properly, this may copy the data
* into private anonymous memory (unless it's already there).
*
* @param as Address space.
* @param flags Flags of the area memory.
* @param address Address withing the area to be changed.
* @param as Address space.
* @param flags Flags of the area memory.
* @param address Address within the area to be changed.
*
* @return Zero on success or a value from @ref errno.h on failure.
* @return Zero on success or a value from @ref errno.h on failure.
*
*/
int as_area_change_flags(as_t *as, int flags, uintptr_t address)
{
785,7 → 790,7
uintptr_t *old_frame;
index_t frame_idx;
count_t used_pages;
 
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
 
799,7 → 804,7
return ENOENT;
}
 
if (area->sh_info || area->backend != &anon_backend) {
if ((area->sh_info) || (area->backend != &anon_backend)) {
/* Copying shared areas not supported yet */
/* Copying non-anonymous memory not supported yet */
mutex_unlock(&area->lock);
870,6 → 875,7
*/
 
tlb_invalidate_pages(as->asid, area->base, area->pages);
/*
* Invalidate potential software translation caches (e.g. TSB on
* sparc64).
/trunk/kernel/generic/src/syscall/syscall.c
92,8 → 92,12
/** Tell kernel to get keyboard/console access again */
static unative_t sys_debug_enable_console(void)
{
#ifdef CONFIG_KCONSOLE
arch_grab_console();
return 0;
return true;
#else
return false;
#endif
}
 
/** Dispatch system call */
/trunk/kernel/arch/amd64/src/debugger.c
54,6 → 54,8
static bpinfo_t breakpoints[BKPOINTS_MAX];
SPINLOCK_INITIALIZE(bkpoint_lock);
 
#ifdef CONFIG_KCONSOLE
 
static int cmd_print_breakpoints(cmd_arg_t *argv);
static cmd_info_t bkpts_info = {
.name = "bkpts",
99,44 → 101,9
.argv = &addw_argv
};
 
#endif
#endif /* CONFIG_DEBUG_AS_WATCHPOINT */
#endif /* CONFIG_KCONSOLE */
 
/** Print table of active breakpoints */
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused)))
{
unsigned int i;
char *symbol;
 
#ifdef __32_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ---------- ---------\n");
#endif
 
#ifdef __64_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ------------------ ---------\n");
#endif
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
 
#ifdef __32_BITS__
printf("%-2u %-5d %#10zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
#ifdef __64_BITS__
printf("%-2u %-5d %#18zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
}
return 1;
}
 
/* Setup DR register according to table */
static void setup_dr(int curidx)
{
267,10 → 234,12
}
printf("Reached breakpoint %d:%lx(%s)\n", slot, getip(istate),
get_symtab_entry(getip(istate)));
printf("***Type 'exit' to exit kconsole.\n");
atomic_set(&haltstate,1);
kconsole((void *) "debug");
atomic_set(&haltstate,0);
 
#ifdef CONFIG_KCONSOLE
atomic_set(&haltstate, 1);
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false);
atomic_set(&haltstate, 0);
#endif
}
 
void breakpoint_del(int slot)
299,42 → 268,8
#endif
}
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
 
/** Remove breakpoint from table */
int cmd_del_breakpoint(cmd_arg_t *argv)
{
unative_t bpno = argv->intval;
if (bpno > BKPOINTS_MAX) {
printf("Invalid breakpoint number.\n");
return 0;
}
breakpoint_del(argv->intval);
return 1;
}
 
/** Add new breakpoint to table */
static int cmd_add_breakpoint(cmd_arg_t *argv)
{
int flags;
int id;
 
if (argv == &add_argv) {
flags = BKPOINT_INSTR;
} else { /* addwatchp */
flags = BKPOINT_WRITE;
}
printf("Adding breakpoint on address: %p\n", argv->intval);
id = breakpoint_add((void *)argv->intval, flags, -1);
if (id < 0)
printf("Add breakpoint failed.\n");
else
printf("Added breakpoint %d.\n", id);
return 1;
}
#endif
 
static void debug_exception(int n __attribute__((unused)), istate_t *istate)
{
unative_t dr6;
379,24 → 314,26
 
for (i = 0; i < BKPOINTS_MAX; i++)
breakpoints[i].address = NULL;
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&bkpts_info);
if (!cmd_register(&bkpts_info))
panic("could not register command %s\n", bkpts_info.name);
printf("Cannot register command %s\n", bkpts_info.name);
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
cmd_initialize(&delbkpt_info);
if (!cmd_register(&delbkpt_info))
panic("could not register command %s\n", delbkpt_info.name);
printf("Cannot register command %s\n", delbkpt_info.name);
 
cmd_initialize(&addbkpt_info);
if (!cmd_register(&addbkpt_info))
panic("could not register command %s\n", addbkpt_info.name);
printf("Cannot register command %s\n", addbkpt_info.name);
 
cmd_initialize(&addwatchp_info);
if (!cmd_register(&addwatchp_info))
panic("could not register command %s\n", addwatchp_info.name);
#endif
printf("Cannot register command %s\n", addwatchp_info.name);
#endif /* CONFIG_DEBUG_AS_WATCHPOINT */
#endif /* CONFIG_KCONSOLE */
exc_register(VECTOR_DEBUG, "debugger", debug_exception);
#ifdef CONFIG_SMP
404,5 → 341,79
#endif
}
 
#ifdef CONFIG_KCONSOLE
/** Print table of active breakpoints */
int cmd_print_breakpoints(cmd_arg_t *argv __attribute__((unused)))
{
unsigned int i;
char *symbol;
 
#ifdef __32_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ---------- ---------\n");
#endif
 
#ifdef __64_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ------------------ ---------\n");
#endif
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
 
#ifdef __32_BITS__
printf("%-2u %-5d %#10zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
#ifdef __64_BITS__
printf("%-2u %-5d %#18zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
}
return 1;
}
 
#ifndef CONFIG_DEBUG_AS_WATCHPOINT
 
/** Remove breakpoint from table */
int cmd_del_breakpoint(cmd_arg_t *argv)
{
unative_t bpno = argv->intval;
if (bpno > BKPOINTS_MAX) {
printf("Invalid breakpoint number.\n");
return 0;
}
breakpoint_del(argv->intval);
return 1;
}
 
/** Add new breakpoint to table */
static int cmd_add_breakpoint(cmd_arg_t *argv)
{
int flags;
int id;
 
if (argv == &add_argv) {
flags = BKPOINT_INSTR;
} else { /* addwatchp */
flags = BKPOINT_WRITE;
}
printf("Adding breakpoint on address: %p\n", argv->intval);
id = breakpoint_add((void *)argv->intval, flags, -1);
if (id < 0)
printf("Add breakpoint failed.\n");
else
printf("Added breakpoint %d.\n", id);
return 1;
}
#endif /* CONFIG_DEBUG_AS_WATCHPOINT */
#endif /* CONFIG_KCONSOLE */
 
/** @}
*/
/trunk/kernel/arch/mips32/src/exception.c
45,7 → 45,6
#include <print.h>
#include <interrupt.h>
#include <func.h>
#include <console/kconsole.h>
#include <ddi/irq.h>
#include <arch/debugger.h>
 
/trunk/kernel/arch/mips32/src/cpu/cpu.c
48,7 → 48,7
{ "MIPS", "R2000" }, /* 0x01 */
{ "MIPS", "R3000" }, /* 0x02 */
{ "MIPS", "R6000" }, /* 0x03 */
{ "MIPS", " R4000/R4400" }, /* 0x04 */
{ "MIPS", "R4000/R4400" }, /* 0x04 */
{ "LSI Logic", "R3000" }, /* 0x05 */
{ "MIPS", "R6000A" }, /* 0x06 */
{ "IDT", "3051/3052" }, /* 0x07 */
123,9 → 123,9
data = &imp_data[m->arch.imp_num];
}
 
printf("cpu%d: %s %s (rev=%d.%d, imp=%d)\n",
printf("cpu%u: %s %s (rev=%d.%d, imp=%d)\n",
m->id, data->vendor, data->model, m->arch.rev_num >> 4,
m->arch.rev_num & 0xf, m->arch.imp_num);
m->arch.rev_num & 0x0f, m->arch.imp_num);
}
 
/** @}
/trunk/kernel/arch/mips32/src/debugger.c
47,6 → 47,8
bpinfo_t breakpoints[BKPOINTS_MAX];
SPINLOCK_INITIALIZE(bkpoint_lock);
 
#ifdef CONFIG_KCONSOLE
 
static int cmd_print_breakpoints(cmd_arg_t *argv);
static cmd_info_t bkpts_info = {
.name = "bkpts",
123,10 → 125,12
{0, 0} /* EndOfTable */
};
 
 
/** Test, if the given instruction is a jump or branch instruction
*
* @param instr Instruction code
* @return true - it is jump instruction, false otherwise
*
*/
static bool is_jump(unative_t instr)
{
267,6 → 271,8
return 1;
}
 
#endif
 
/** Initialize debugger */
void debugger_init()
{
274,22 → 280,24
 
for (i = 0; i < BKPOINTS_MAX; i++)
breakpoints[i].address = NULL;
 
#ifdef CONFIG_KCONSOLE
cmd_initialize(&bkpts_info);
if (!cmd_register(&bkpts_info))
panic("could not register command %s\n", bkpts_info.name);
printf("Cannot register command %s\n", bkpts_info.name);
 
cmd_initialize(&delbkpt_info);
if (!cmd_register(&delbkpt_info))
panic("could not register command %s\n", delbkpt_info.name);
printf("Cannot register command %s\n", delbkpt_info.name);
 
cmd_initialize(&addbkpt_info);
if (!cmd_register(&addbkpt_info))
panic("could not register command %s\n", addbkpt_info.name);
printf("Cannot register command %s\n", addbkpt_info.name);
 
cmd_initialize(&addbkpte_info);
if (!cmd_register(&addbkpte_info))
panic("could not register command %s\n", addbkpte_info.name);
printf("Cannot register command %s\n", addbkpte_info.name);
#endif
}
 
/** Handle breakpoint
367,19 → 375,20
if (cur->bkfunc)
cur->bkfunc(cur, istate);
} else {
printf("***Type 'exit' to exit kconsole.\n");
#ifdef CONFIG_KCONSOLE
/* This disables all other processors - we are not SMP,
* actually this gets us to cpu_halt, if scheduler() is run
* - we generally do not want scheduler to be run from debug,
* so this is a good idea
*/
atomic_set(&haltstate,1);
atomic_set(&haltstate, 1);
spinlock_unlock(&bkpoint_lock);
 
kconsole("debug");
 
kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false);
spinlock_lock(&bkpoint_lock);
atomic_set(&haltstate,0);
atomic_set(&haltstate, 0);
#endif
}
if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
/* Remove one-shot breakpoint */
/trunk/kernel/arch/ia32/include/drivers/ega.h
40,6 → 40,7
#define ROWS 25
#define SCREEN (ROW * ROWS)
 
extern void ega_redraw(void);
extern void ega_init(void);
 
#endif
/trunk/kernel/arch/ia32/include/drivers/vesa.h
36,6 → 36,7
#define KERN_ia32_VESA_H_
 
extern int vesa_present(void);
extern void vesa_redraw(void);
extern void vesa_init(void);
 
#endif
/trunk/kernel/arch/ia32/src/ia32.c
93,7 → 93,7
vesa_init();
else
#endif
ega_init(); /* video */
ega_init(); /* video */
/* Enable debugger */
debugger_init();
159,8 → 159,15
*/
void arch_grab_console(void)
{
#ifdef CONFIG_FB
vesa_redraw();
#else
ega_redraw();
#endif
i8042_grab();
}
 
/** Return console to userspace
*
*/
/trunk/kernel/arch/ia32/src/cpu/cpu.c
65,8 → 65,8
 
static char *vendor_str[] = {
"Unknown Vendor",
"AuthenticAMD",
"GenuineIntel"
"AMD",
"Intel"
};
 
void fpu_disable(void)
77,7 → 77,7
"mov %%eax,%%cr0;"
:
:
:"%eax"
: "%eax"
);
}
 
89,7 → 89,7
"mov %%eax,%%cr0;"
:
:
:"%eax"
: "%eax"
);
}
 
140,29 → 140,31
/*
* Check for AMD processor.
*/
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) {
if ((info.cpuid_ebx == AMD_CPUID_EBX)
&& (info.cpuid_ecx == AMD_CPUID_ECX)
&& (info.cpuid_edx == AMD_CPUID_EDX))
CPU->arch.vendor = VendorAMD;
}
 
/*
* Check for Intel processor.
*/
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) {
if ((info.cpuid_ebx == INTEL_CPUID_EBX)
&& (info.cpuid_ecx == INTEL_CPUID_ECX)
&& (info.cpuid_edx == INTEL_CPUID_EDX))
CPU->arch.vendor = VendorIntel;
}
cpuid(1, &info);
CPU->arch.family = (info.cpuid_eax>>8)&0xf;
CPU->arch.model = (info.cpuid_eax>>4)&0xf;
CPU->arch.stepping = (info.cpuid_eax>>0)&0xf;
CPU->arch.family = (info.cpuid_eax >> 8) & 0x0f;
CPU->arch.model = (info.cpuid_eax >> 4) & 0x0f;
CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0f;
}
}
 
void cpu_print_report(cpu_t* m)
void cpu_print_report(cpu_t* cpu)
{
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n",
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping,
m->frequency_mhz);
printf("cpu%u: (%s family=%u model=%u stepping=%u) %" PRIu16 " MHz\n",
cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family,
cpu->arch.model, cpu->arch.stepping, cpu->frequency_mhz);
}
 
/** @}
/trunk/kernel/arch/ia32/src/drivers/vesa.c
97,6 → 97,11
fb_init(&vesa_props);
}
 
void vesa_redraw(void)
{
fb_redraw();
}
 
#endif
 
/** @}
/trunk/uspace/lib/libc/include/ipc/fb.h
51,7 → 51,6
FB_GET_RESOLUTION,
FB_DRAW_TEXT_DATA,
FB_FLUSH,
FB_VIEWPORT_DB,
FB_DRAW_PPM,
FB_PREPARE_SHM,
FB_DROP_SHM,
59,7 → 58,6
FB_VP_DRAW_PIXMAP,
FB_VP2PIXMAP,
FB_DROP_PIXMAP,
FB_TRANS_PUTCHAR,
FB_ANIM_CREATE,
FB_ANIM_DROP,
FB_ANIM_ADDPIXMAP,
/trunk/uspace/srv/console/console.c
86,10 → 86,7
* faster virtual console
* switching */
 
static int kernel_pixmap = -1; /**< Number of fb pixmap, where kernel
* console is stored */
 
 
/** Find unused virtual console.
*
*/
187,114 → 184,80
}
 
/** Save current screen to pixmap, draw old pixmap
*
* @param oldpixmap Old pixmap
* @return ID of pixmap of current screen
*/
static int switch_screens(int oldpixmap)
{
int newpmap;
/* Save screen */
newpmap = async_req_0_0(fb_info.phone, FB_VP2PIXMAP);
if (newpmap < 0)
return -1;
 
if (oldpixmap != -1) {
/* Show old screen */
async_msg_2(fb_info.phone, FB_VP_DRAW_PIXMAP, 0, oldpixmap);
/* Drop old pixmap */
async_msg_1(fb_info.phone, FB_DROP_PIXMAP, oldpixmap);
}
return newpmap;
}
 
/** Switch to new console */
static void change_console(int newcons)
{
connection_t *conn;
static int console_pixmap = -1;
int i, j, rc;
keyfield_t *field;
style_t *style;
 
if (newcons == active_console)
return;
 
if (newcons == KERNEL_CONSOLE) {
async_serialize_start();
curs_visibility(0);
gcons_in_kernel();
async_serialize_end();
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE))
active_console = KERNEL_CONSOLE;
else
newcons == active_console;
}
if (newcons != KERNEL_CONSOLE) {
async_serialize_start();
if (active_console == KERNEL_CONSOLE)
return;
active_console = KERNEL_CONSOLE;
gcons_redraw_console();
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
set_style(&conn->screenbuffer.style);
curs_visibility(0);
 
async_serialize_start();
if (kernel_pixmap == -1) {
/* store/restore unsupported */
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
if (interbuffer) {
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++) {
unsigned int size_x;
size_x = conn->screenbuffer.size_x;
interbuffer[i + j * size_x] =
*get_field_at(&conn->screenbuffer, i, j);
}
/* This call can preempt, but we are already at the end */
rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);
}
if ((!interbuffer) || (rc != 0)) {
set_style(&conn->screenbuffer.style);
clrscr();
} else {
gcons_in_kernel();
console_pixmap = switch_screens(kernel_pixmap);
kernel_pixmap = -1;
style = &conn->screenbuffer.style;
for (j = 0; j < conn->screenbuffer.size_y; j++)
for (i = 0; i < conn->screenbuffer.size_x; i++) {
field = get_field_at(&conn->screenbuffer, i, j);
if (!style_same(*style, field->style))
set_style(&field->style);
style = &field->style;
if ((field->character == ' ') &&
(style_same(field->style,
conn->screenbuffer.style)))
continue;
prtchr(field->character, j, i);
}
}
curs_goto(conn->screenbuffer.position_y,
conn->screenbuffer.position_x);
curs_visibility(conn->screenbuffer.is_cursor_visible);
async_serialize_end();
 
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
return;
}
async_serialize_start();
 
if (console_pixmap != -1) {
kernel_pixmap = switch_screens(console_pixmap);
console_pixmap = -1;
}
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
 
set_style(&conn->screenbuffer.style);
curs_visibility(0);
if (interbuffer) {
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++) {
unsigned int size_x;
 
size_x = conn->screenbuffer.size_x;
interbuffer[i + j * size_x] =
*get_field_at(&conn->screenbuffer, i, j);
}
/* This call can preempt, but we are already at the end */
rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);
}
if ((!interbuffer) || (rc != 0)) {
set_style(&conn->screenbuffer.style);
clrscr();
style = &conn->screenbuffer.style;
 
for (j = 0; j < conn->screenbuffer.size_y; j++)
for (i = 0; i < conn->screenbuffer.size_x; i++) {
field = get_field_at(&conn->screenbuffer, i, j);
if (!style_same(*style, field->style))
set_style(&field->style);
style = &field->style;
if ((field->character == ' ') &&
(style_same(field->style,
conn->screenbuffer.style)))
continue;
 
prtchr(field->character, j, i);
}
}
curs_goto(conn->screenbuffer.position_y,
conn->screenbuffer.position_x);
curs_visibility(conn->screenbuffer.is_cursor_visible);
 
async_serialize_end();
}
 
/** Handler for keyboard */
497,7 → 460,6
async_new_connection(phonehash, 0, NULL, keyboard_events);
/* Connect to framebuffer driver */
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0);
while (fb_info.phone < 0) {
usleep(10000);
504,15 → 466,10
fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0, 0);
}
/* Save old kernel screen */
kernel_pixmap = switch_screens(-1);
 
/* Initialize gcons */
gcons_init(fb_info.phone);
/* Synchronize, the gcons can have something in queue */
async_req_0_0(fb_info.phone, FB_FLUSH);
/* Enable double buffering */
async_msg_2(fb_info.phone, FB_VIEWPORT_DB, (sysarg_t) -1, 1);
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
&fb_info.cols);
/trunk/uspace/srv/console/gcons.c
81,7 → 81,7
 
static void vp_switch(int vp)
{
async_msg_1(fbphone,FB_VIEWPORT_SWITCH, vp);
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
}
 
/** Create view port */
105,7 → 105,7
/** Transparent putchar */
static void tran_putch(char c, int row, int col)
{
async_msg_3(fbphone, FB_TRANS_PUTCHAR, c, row, col);
async_msg_3(fbphone, FB_PUTCHAR, c, row, col);
}
 
/** Redraw the button showing state of a given console */
189,10 → 189,10
console_state[consnum] = CONS_DISCONNECTED_SEL;
else
console_state[consnum] = CONS_DISCONNECTED;
 
if (active_console == KERNEL_CONSOLE)
return;
 
redraw_state(consnum);
vp_switch(console_vp);
}
217,16 → 217,10
/** Change to kernel console */
void gcons_in_kernel(void)
{
if (console_state[active_console] == CONS_DISCONNECTED_SEL)
console_state[active_console] = CONS_DISCONNECTED;
else
console_state[active_console] = CONS_IDLE;
redraw_state(active_console);
 
if (animation != -1)
async_msg_1(fbphone, FB_ANIM_STOP, animation);
 
active_console = KERNEL_CONSOLE; /* Set to kernel console */
active_console = KERNEL_CONSOLE;
vp_switch(0);
}
 
342,11 → 336,12
extern int _binary_helenos_ppm_size;
extern char _binary_nameic_ppm_start[0];
extern int _binary_nameic_ppm_size;
/** Redraws console graphics */
static void gcons_redraw_console(void)
 
/** Redraws console graphics */
void gcons_redraw_console(void)
{
int i;
 
if (!use_gcons)
return;
357,7 → 352,7
(size_t) &_binary_helenos_ppm_size, xres - 66, 2);
draw_pixmap(_binary_nameic_ppm_start,
(size_t) &_binary_nameic_ppm_size, 5, 17);
 
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
vp_switch(console_vp);
459,16 → 454,16
int rc;
int i;
int status_start = STATUS_START;
 
fbphone = phone;
 
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
if (rc)
return;
if (xres < 800 || yres < 600)
if ((xres < 800) || (yres < 600))
return;
 
/* create console viewport */
/* Align width & height to character size */
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
506,13 → 501,12
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
make_anim();
 
use_gcons = 1;
console_state[0] = CONS_DISCONNECTED_SEL;
console_state[KERNEL_CONSOLE] = CONS_KERNEL;
gcons_redraw_console();
}
 
/** @}
*/
 
/trunk/uspace/srv/console/gcons.h
36,6 → 36,7
#define _GCONS_H_
 
void gcons_init(int phone);
void gcons_redraw_console(void);
void gcons_change_console(int consnum);
void gcons_notify_char(int consnum);
void gcons_in_kernel(void);
/trunk/uspace/srv/console/screenbuffer.h
35,13 → 35,14
#ifndef __SCREENBUFFER_H__
#define __SCREENBUFFER_H__
 
#include <stdint.h>
 
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
 
typedef struct {
unsigned int bg_color; /**< background color */
unsigned int fg_color; /**< foreground color */
uint32_t bg_color; /**< background color */
uint32_t fg_color; /**< foreground color */
} style_t;
 
/** One field on screen. It contain one character and its attributes. */
/trunk/uspace/srv/fb/font-8x16.c
28,7 → 28,7
 
#include "font-8x16.h"
 
unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = {
unsigned char fb_font[FONT_GLYPHS * FONT_SCANLINES] = {
 
/* 0 0x00 '^@' */
0x00, /* 00000000 */
/trunk/uspace/srv/fb/font-8x16.h
29,9 → 29,11
#ifndef FB_FONT_8X16_H_
#define FB_FONT_8X16_H_
 
#define FONT_GLIPHS 256
#define FONT_SCANLINES 16
#define FONT_GLYPHS 256
#define FONT_WIDTH 8
#define FONT_SCANLINES 16
 
extern unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES];
 
extern unsigned char fb_font[FONT_GLYPHS * FONT_SCANLINES];
 
#endif
/trunk/uspace/srv/fb/main.c
46,7 → 46,7
void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area)
{
void *dest;
 
dest = as_get_mappable_page(IPC_GET_ARG2(*call));
if (ipc_answer_1(callid, EOK, (sysarg_t) dest) == 0) {
if (*area)
61,12 → 61,12
ipcarg_t phonead;
bool initialized = false;
 
#ifdef FB_ENABLED
if (sysinfo_value("fb.kind") == 1) {
if (fb_init() == 0)
initialized = true;
}
}
#endif
#ifdef EGA_ENABLED
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) {
89,12 → 89,13
 
if (!initialized)
return -1;
 
if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0)
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
/* Never reached */
return 0;
}
/trunk/uspace/srv/fb/fb.c
1,4 → 1,5
/*
* Copyright (c) 2008 Martin Decky
* Copyright (c) 2006 Jakub Vana
* Copyright (c) 2006 Ondrej Palkovsky
* All rights reserved.
32,7 → 33,7
* @brief HelenOS graphical framebuffer.
* @ingroup fbs
* @{
*/
*/
 
/** @file
*/
62,428 → 63,323
#include "pointer.xbm"
#include "pointer_mask.xbm"
 
#define DEFAULT_BGCOLOR 0xf0f0f0
#define DEFAULT_FGCOLOR 0x0
#define DEFAULT_BGCOLOR 0xf0f0f0
#define DEFAULT_FGCOLOR 0x000000
 
/***************************************************************/
/* Pixel specific fuctions */
#define MAX_ANIM_LEN 8
#define MAX_ANIMATIONS 4
#define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */
#define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */
 
typedef void (*conv2scr_fn_t)(void *, int);
typedef int (*conv2rgb_fn_t)(void *);
typedef void (*rgb_conv_t)(void *, uint32_t);
 
struct {
uint8_t *fbaddress;
 
uint8_t *fb_addr;
unsigned int xres;
unsigned int yres;
unsigned int scanline;
unsigned int glyphscanline;
unsigned int pixelbytes;
unsigned int invert_colors;
 
conv2scr_fn_t rgb2scr;
conv2rgb_fn_t scr2rgb;
unsigned int glyphbytes;
rgb_conv_t rgb_conv;
} screen;
 
typedef struct {
int initialized;
unsigned int x, y;
unsigned int width, height;
 
bool initialized;
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
/* Text support in window */
unsigned int rows, cols;
/* Style for text printing */
unsigned int cols;
unsigned int rows;
/* Style and glyphs for text printing */
style_t style;
uint8_t *glyphs;
uint8_t *bgpixel;
/* Auto-cursor position */
int cursor_active, cur_col, cur_row;
int cursor_shown;
/* Double buffering */
uint8_t *dbdata;
unsigned int dboffset;
unsigned int paused;
bool cursor_active;
unsigned int cur_col;
unsigned int cur_row;
bool cursor_shown;
/* Back buffer */
unsigned int bbsize;
uint8_t *backbuf;
} viewport_t;
 
#define MAX_ANIM_LEN 8
#define MAX_ANIMATIONS 4
typedef struct {
int initialized;
int enabled;
bool initialized;
bool enabled;
unsigned int vp;
 
unsigned int pos;
unsigned int animlen;
unsigned int pixmaps[MAX_ANIM_LEN];
} animation_t;
 
static animation_t animations[MAX_ANIMATIONS];
static int anims_enabled;
static bool anims_enabled;
 
/** Maximum number of saved pixmaps
* Pixmap is a saved rectangle
*/
#define MAX_PIXMAPS 256
typedef struct {
unsigned int width;
unsigned int height;
uint8_t *data;
} pixmap_t;
 
static pixmap_t pixmaps[MAX_PIXMAPS];
 
/* Viewport is a rectangular area on the screen */
#define MAX_VIEWPORTS 128
static viewport_t viewports[128];
 
/* Allow only 1 connection */
static int client_connected = 0;
static bool client_connected = false; /**< Allow only 1 connection */
 
#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
 
#define COL_WIDTH 8
#define ROW_BYTES (screen.scanline * FONT_SCANLINES)
#define COL2X(col) ((col) * FONT_WIDTH)
#define ROW2Y(row) ((row) * FONT_SCANLINES)
 
#define POINTPOS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes)
#define X2COL(x) ((x) / FONT_WIDTH)
#define Y2ROW(y) ((y) / FONT_SCANLINES)
 
static inline int COLOR(int color)
{
return screen.invert_colors ? ~color : color;
}
#define FB_POS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes)
#define BB_POS(vport, col, row) ((row) * vport->cols + (col))
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline)
 
/* Conversion routines between different color representations */
static void
rgb_byte0888(void *dst, int rgb)
{
*(int *)dst = rgb;
}
 
static int
byte0888_rgb(void *src)
/** ARGB 8:8:8:8 conversion
*
*/
static void rgb_0888(void *dst, uint32_t rgb)
{
return (*(int *)src) & 0xffffff;
*((uint32_t *) dst) = rgb & 0xffffff;
}
 
static void
bgr_byte0888(void *dst, int rgb)
{
*((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
RED(rgb, 8);
}
 
static int
byte0888_bgr(void *src)
/** ABGR 8:8:8:8 conversion
*
*/
static void bgr_0888(void *dst, uint32_t rgb)
{
int color = *(uint32_t *)(src);
return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
((color >> 16) & 0xff);
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
}
 
static void
rgb_byte888(void *dst, int rgb)
 
/** BGR 8:8:8 conversion
*
*/
static void rgb_888(void *dst, uint32_t rgb)
{
uint8_t *scr = dst;
#if defined(FB_INVERT_ENDIAN)
scr[0] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[2] = BLUE(rgb, 8);
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8)
| (*((uint32_t *) dst) & 0xff0000);
#else
scr[2] = RED(rgb, 8);
scr[1] = GREEN(rgb, 8);
scr[0] = BLUE(rgb, 8);
*((uint32_t *) dst)
= (rgb & 0xffffff) | (*((uint32_t *) dst) & 0xff0000);
#endif
}
 
static int
byte888_rgb(void *src)
{
uint8_t *scr = src;
#if defined(FB_INVERT_ENDIAN)
return scr[0] << 16 | scr[1] << 8 | scr[2];
#else
return scr[2] << 16 | scr[1] << 8 | scr[0];
#endif
}
 
/** 16-bit depth (5:5:5) */
static void
rgb_byte555(void *dst, int rgb)
/** RGB 5:5:5 conversion
*
*/
static void rgb_555(void *dst, uint32_t rgb)
{
/* 5-bit, 5-bits, 5-bits */
*((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
BLUE(rgb, 5);
*((uint16_t *) dst)
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
}
 
/** 16-bit depth (5:5:5) */
static int
byte555_rgb(void *src)
{
int color = *(uint16_t *)(src);
return (((color >> 10) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
}
 
/** 16-bit depth (5:6:5) */
static void
rgb_byte565(void *dst, int rgb)
/** RGB 5:6:5 conversion
*
*/
static void rgb_565(void *dst, uint32_t rgb)
{
/* 5-bit, 6-bits, 5-bits */
*((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
BLUE(rgb, 5);
*((uint16_t *) dst)
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
}
 
/** 16-bit depth (5:6:5) */
static int
byte565_rgb(void *src)
{
int color = *(uint16_t *)(src);
return (((color >> 11) & 0x1f) << (16 + 3)) |
(((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
}
 
/** Put pixel - 8-bit depth (3:2:3) */
static void
rgb_byte8(void *dst, int rgb)
/** RGB 3:2:3
*
*/
static void rgb_323(void *dst, uint32_t rgb)
{
*(uint8_t *)dst = 255 - (RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 |
BLUE(rgb, 3));
*((uint8_t *) dst)
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
}
 
/** Return pixel color - 8-bit depth (3:2:3) */
static int
byte8_rgb(void *src)
{
int color = 255 - (*(uint8_t *)src);
return (((color >> 5) & 0x7) << (16 + 5)) |
(((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
}
 
/** Put pixel into viewport
/** Redraw viewport
*
* @param vport Viewport identification
* @param x X coord relative to viewport
* @param y Y coord relative to viewport
* @param color RGB color
* @param vport Viewport to redraw
*
*/
static void
putpixel(viewport_t *vport, unsigned int x, unsigned int y, int color)
static void vport_redraw(viewport_t *vport)
{
int dx = vport->x + x;
int dy = vport->y + y;
 
if (! (vport->paused && vport->dbdata))
(*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)],
COLOR(color));
 
if (vport->dbdata) {
int dline = (y + vport->dboffset) % vport->height;
int doffset = screen.pixelbytes * (dline * vport->width + x);
(*screen.rgb2scr)(&vport->dbdata[doffset], COLOR(color));
unsigned int row;
for (row = 0; row < vport->rows; row++) {
unsigned int y = vport->y + ROW2Y(row);
unsigned int yd;
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH)
memcpy(&screen.fb_addr[FB_POS(x, y + yd)],
&vport->glyphs[GLYPH_POS(vport->backbuf[BB_POS(vport, col, row)], yd, false)],
screen.glyphscanline);
}
}
}
 
/** Get pixel from viewport */
static int
getpixel(viewport_t *vport, unsigned int x, unsigned int y)
{
int dx = vport->x + x;
int dy = vport->y + y;
 
return COLOR((*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx, dy)]));
}
 
static inline void
putpixel_mem(char *mem, unsigned int x, unsigned int y, int color)
{
(*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color));
}
 
static void
draw_rectangle(viewport_t *vport, unsigned int sx, unsigned int sy,
unsigned int width, unsigned int height, int color)
{
unsigned int x, y;
static void *tmpline;
 
if (!tmpline)
tmpline = malloc(screen.scanline * screen.pixelbytes);
 
/* Clear first line */
for (x = 0; x < width; x++)
putpixel_mem(tmpline, x, 0, color);
 
if (!vport->paused) {
/* Recompute to screen coords */
sx += vport->x;
sy += vport->y;
/* Copy the rest */
for (y = sy;y < sy+height; y++)
memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline,
screen.pixelbytes * width);
if (COL2X(vport->cols) < vport->width) {
unsigned int y;
for (y = 0; y < vport->height; y++) {
unsigned int x;
for (x = COL2X(vport->cols); x < vport->width; x++)
memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes);
}
}
if (vport->dbdata) {
for (y = sy; y < sy + height; y++) {
int rline = (y + vport->dboffset) % vport->height;
int rpos = (rline * vport->width + sx) *
screen.pixelbytes;
memcpy(&vport->dbdata[rpos], tmpline,
screen.pixelbytes * width);
if (ROW2Y(vport->rows) < vport->height) {
unsigned int y;
for (y = ROW2Y(vport->rows); y < vport->height; y++) {
unsigned int x;
for (x = 0; x < vport->width; x++)
memcpy(&screen.fb_addr[FB_POS(x, y)], vport->bgpixel, screen.pixelbytes);
}
}
 
}
 
/** Fill viewport with background color */
static void
clear_port(viewport_t *vport)
 
/** Clear viewport
*
* @param vport Viewport to clear
*
*/
static void vport_clear(viewport_t *vport)
{
draw_rectangle(vport, 0, 0, vport->width, vport->height,
vport->style.bg_color);
memset(vport->backbuf, 0, vport->bbsize);
vport_redraw(vport);
}
 
/** Scroll unbuffered viewport up/down
 
/** Scroll viewport by given number of lines
*
* @param vport Viewport to scroll
* @param lines Positive number - scroll up, negative - scroll down
* @param lines Number of lines to scroll
*
*/
static void
scroll_port_nodb(viewport_t *vport, int lines)
static void vport_scroll(viewport_t *vport, int lines)
{
int y;
 
if (lines > 0) {
for (y = vport->y; y < vport->y+vport->height - lines; y++)
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
&screen.fbaddress[POINTPOS(vport->x,y + lines)],
screen.pixelbytes * vport->width);
draw_rectangle(vport, 0, vport->height - lines, vport->width,
lines, vport->style.bg_color);
} else if (lines < 0) {
lines = -lines;
for (y = vport->y + vport->height-1; y >= vport->y + lines; y--)
memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
&screen.fbaddress[POINTPOS(vport->x,y - lines)],
screen.pixelbytes * vport->width);
draw_rectangle(vport, 0, 0, vport->width, lines,
vport->style.bg_color);
unsigned int row;
for (row = 0; row < vport->rows; row++) {
unsigned int y = vport->y + ROW2Y(row);
unsigned int yd;
for (yd = 0; yd < FONT_SCANLINES; yd++) {
unsigned int x;
unsigned int col;
for (col = 0, x = vport->x; col < vport->cols; col++, x += FONT_WIDTH) {
uint8_t glyph;
if ((row + lines >= 0) && (row + lines < vport->rows)) {
if (vport->backbuf[BB_POS(vport, col, row)] == vport->backbuf[BB_POS(vport, col, row + lines)])
continue;
glyph = vport->backbuf[BB_POS(vport, col, row + lines)];
} else
glyph = 0;
memcpy(&screen.fb_addr[FB_POS(x, y + yd)],
&vport->glyphs[GLYPH_POS(glyph, yd, false)], screen.glyphscanline);
}
}
}
}
 
/** Refresh given viewport from double buffer */
static void
refresh_viewport_db(viewport_t *vport)
{
unsigned int y, srcy, srcoff, dsty, dstx;
 
for (y = 0; y < vport->height; y++) {
srcy = (y + vport->dboffset) % vport->height;
srcoff = (vport->width * srcy) * screen.pixelbytes;
 
dstx = vport->x;
dsty = vport->y + y;
 
memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)],
&vport->dbdata[srcoff], vport->width * screen.pixelbytes);
}
}
 
/** Scroll viewport that has double buffering enabled */
static void
scroll_port_db(viewport_t *vport, int lines)
{
++vport->paused;
if (lines > 0) {
draw_rectangle(vport, 0, 0, vport->width, lines,
vport->style.bg_color);
vport->dboffset += lines;
vport->dboffset %= vport->height;
} else if (lines < 0) {
lines = -lines;
draw_rectangle(vport, 0, vport->height-lines, vport->width,
lines, vport->style.bg_color);
 
if (vport->dboffset < lines)
vport->dboffset += vport->height;
vport->dboffset -= lines;
memcpy(vport->backbuf, vport->backbuf + vport->cols * lines, vport->cols * (vport->rows - lines));
memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], 0, vport->cols * lines);
} else {
memcpy(vport->backbuf - vport->cols * lines, vport->backbuf, vport->cols * (vport->rows + lines));
memset(vport->backbuf, 0, - vport->cols * lines);
}
--vport->paused;
refresh_viewport_db(vport);
}
 
/** Scrolls viewport given number of lines */
static void
scroll_port(viewport_t *vport, int lines)
{
if (vport->dbdata)
scroll_port_db(vport, lines);
else
scroll_port_nodb(vport, lines);
}
 
static void
invert_pixel(viewport_t *vport, unsigned int x, unsigned int y)
{
putpixel(vport, x, y, ~getpixel(vport, x, y));
}
 
 
/***************************************************************/
/* Character-console functions */
 
/** Draw character at given position
/** Render glyphs
*
* @param vport Viewport where the character is printed
* @param sx Coordinates of top-left of the character
* @param sy Coordinates of top-left of the character
* @param style Color of the character
* @param transparent If false, print background color
* Convert glyphs from device independent font
* description to current visual representation.
*
* @param vport Viewport
*
*/
static void
draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy,
style_t style, int transparent)
static void render_glyphs(viewport_t* vport)
{
int i;
unsigned int y;
unsigned int glline;
 
for (y = 0; y < FONT_SCANLINES; y++) {
glline = fb_font[glyph * FONT_SCANLINES + y];
for (i = 0; i < 8; i++) {
if (glline & (1 << (7 - i)))
putpixel(vport, sx + i, sy + y, style.fg_color);
else if (!transparent)
putpixel(vport, sx + i, sy + y, style.bg_color);
unsigned int glyph;
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
unsigned int y;
for (y = 0; y < FONT_SCANLINES; y++) {
unsigned int x;
for (x = 0; x < FONT_WIDTH; x++) {
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes],
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x)))
? vport->style.fg_color : vport->style.bg_color);
uint32_t curcolor;
if (y < FONT_SCANLINES - 2)
curcolor =
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x)))
? vport->style.fg_color : vport->style.bg_color;
else
curcolor = vport->style.fg_color;
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], curcolor);
}
}
}
screen.rgb_conv(vport->bgpixel, vport->style.bg_color);
}
 
/** Invert character at given position */
static void
invert_char(viewport_t *vport,unsigned int row, unsigned int col)
{
unsigned int x;
unsigned int y;
 
for (x = 0; x < COL_WIDTH; x++)
for (y = 0; y < FONT_SCANLINES; y++)
invert_pixel(vport, col * COL_WIDTH + x, row *
FONT_SCANLINES + y);
}
 
/***************************************************************/
/* Stdout specific functions */
 
 
/** Create new viewport
*
* @return New viewport number
* @param x Origin of the viewport (x).
* @param y Origin of the viewport (y).
* @param width Width of the viewport.
* @param height Height of the viewport.
*
* @return New viewport number.
*
*/
static int
viewport_create(unsigned int x, unsigned int y,unsigned int width,
unsigned int height)
static int vport_create(unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{
int i;
 
unsigned int i;
for (i = 0; i < MAX_VIEWPORTS; i++) {
if (!viewports[i].initialized)
break;
490,76 → 386,102
}
if (i == MAX_VIEWPORTS)
return ELIMIT;
 
unsigned int cols = width / FONT_WIDTH;
unsigned int rows = height / FONT_SCANLINES;
unsigned int bbsize = cols * rows;
unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;
uint8_t *backbuf = (uint8_t *) malloc(bbsize);
if (!backbuf)
return ENOMEM;
uint8_t *glyphs = (uint8_t *) malloc(glyphsize);
if (!glyphs) {
free(backbuf);
return ENOMEM;
}
uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes);
if (!bgpixel) {
free(glyphs);
free(backbuf);
return ENOMEM;
}
memset(backbuf, 0, bbsize);
memset(glyphs, 0, glyphsize);
memset(bgpixel, 0, screen.pixelbytes);
viewports[i].x = x;
viewports[i].y = y;
viewports[i].width = width;
viewports[i].height = height;
viewports[i].rows = height / FONT_SCANLINES;
viewports[i].cols = width / COL_WIDTH;
 
viewports[i].cols = cols;
viewports[i].rows = rows;
viewports[i].style.bg_color = DEFAULT_BGCOLOR;
viewports[i].style.fg_color = DEFAULT_FGCOLOR;
viewports[i].glyphs = glyphs;
viewports[i].bgpixel = bgpixel;
viewports[i].cur_col = 0;
viewports[i].cur_row = 0;
viewports[i].cursor_active = 0;
 
viewports[i].initialized = 1;
 
viewports[i].cursor_active = false;
viewports[i].cursor_shown = false;
viewports[i].bbsize = bbsize;
viewports[i].backbuf = backbuf;
viewports[i].initialized = true;
render_glyphs(&viewports[i]);
return i;
}
 
 
/** Initialize framebuffer as a chardev output device
*
* @param addr Address of theframebuffer
* @param xres Screen width in pixels
* @param yres Screen height in pixels
* @param visual Bits per pixel (8, 16, 24, 32)
* @param scan Bytes per one scanline
* @param invert_colors Inverted colors.
* @param addr Address of the framebuffer
* @param xres Screen width in pixels
* @param yres Screen height in pixels
* @param visual Bits per pixel (8, 16, 24, 32)
* @param scan Bytes per one scanline
*
*/
static bool
screen_init(void *addr, unsigned int offset, unsigned int xres,
unsigned int yres, unsigned int scan, unsigned int visual,
bool invert_colors)
static bool screen_init(void *addr, unsigned int xres, unsigned int yres,
unsigned int scan, unsigned int visual)
{
switch (visual) {
case VISUAL_INDIRECT_8:
screen.rgb2scr = rgb_byte8;
screen.scr2rgb = byte8_rgb;
screen.rgb_conv = rgb_323;
screen.pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5:
screen.rgb2scr = rgb_byte555;
screen.scr2rgb = byte555_rgb;
screen.rgb_conv = rgb_555;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5:
screen.rgb2scr = rgb_byte565;
screen.scr2rgb = byte565_rgb;
screen.rgb_conv = rgb_565;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_8_8_8:
screen.rgb2scr = rgb_byte888;
screen.scr2rgb = byte888_rgb;
screen.rgb_conv = rgb_888;
screen.pixelbytes = 3;
break;
case VISUAL_RGB_8_8_8_0:
screen.rgb2scr = rgb_byte888;
screen.scr2rgb = byte888_rgb;
screen.rgb_conv = rgb_888;
screen.pixelbytes = 4;
break;
case VISUAL_RGB_0_8_8_8:
screen.rgb2scr = rgb_byte0888;
screen.scr2rgb = byte0888_rgb;
screen.rgb_conv = rgb_0888;
screen.pixelbytes = 4;
break;
case VISUAL_BGR_0_8_8_8:
screen.rgb2scr = bgr_byte0888;
screen.scr2rgb = byte0888_bgr;
screen.rgb_conv = bgr_0888;
screen.pixelbytes = 4;
break;
default:
566,72 → 488,105
return false;
}
 
screen.fbaddress = (unsigned char *) (((uintptr_t) addr));
screen.fb_addr = (unsigned char *) addr;
screen.xres = xres;
screen.yres = yres;
screen.scanline = scan;
screen.invert_colors = invert_colors;
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes;
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES;
/* Create first viewport */
viewport_create(0, 0, xres, yres);
vport_create(0, 0, xres, yres);
return true;
}
 
/** Hide cursor if it is shown */
static void
cursor_hide(viewport_t *vport)
 
/** Draw glyph at given position relative to viewport
*
* @param vport Viewport identification
* @param cursor Draw glyph with cursor
* @param col Screen position relative to viewport
* @param row Screen position relative to viewport
*
*/
static void draw_glyph(viewport_t *vport, bool cursor, unsigned int col, unsigned int row)
{
if (vport->cursor_active && vport->cursor_shown) {
invert_char(vport, vport->cur_row, vport->cur_col);
vport->cursor_shown = 0;
unsigned int x = vport->x + COL2X(col);
unsigned int y = vport->y + ROW2Y(row);
unsigned int yd;
uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)];
for (yd = 0; yd < FONT_SCANLINES; yd++)
memcpy(&screen.fb_addr[FB_POS(x, y + yd)],
&vport->glyphs[GLYPH_POS(glyph, yd, cursor)], screen.glyphscanline);
}
 
 
/** Hide cursor if it is shown
*
*/
static void cursor_hide(viewport_t *vport)
{
if ((vport->cursor_active) && (vport->cursor_shown)) {
draw_glyph(vport, false, vport->cur_col, vport->cur_row);
vport->cursor_shown = false;
}
}
 
/** Show cursor if cursor showing is enabled */
static void
cursor_print(viewport_t *vport)
 
/** Show cursor if cursor showing is enabled
*
*/
static void cursor_show(viewport_t *vport)
{
/* Do not check for cursor_shown */
if (vport->cursor_active) {
invert_char(vport, vport->cur_row, vport->cur_col);
vport->cursor_shown = 1;
draw_glyph(vport, true, vport->cur_col, vport->cur_row);
vport->cursor_shown = true;
}
}
 
/** Invert cursor, if it is enabled */
static void
cursor_blink(viewport_t *vport)
 
/** Invert cursor, if it is enabled
*
*/
static void cursor_blink(viewport_t *vport)
{
if (vport->cursor_shown)
cursor_hide(vport);
else
cursor_print(vport);
cursor_show(vport);
}
 
/** Draw character at given position relative to viewport
*
* @param vport Viewport identification
* @param c Character to print
* @param row Screen position relative to viewport
* @param col Screen position relative to viewport
* @param transparent If false, print background color with character
 
/** Draw character at given position relative to viewport
*
* @param vport Viewport identification
* @param c Character to draw
* @param col Screen position relative to viewport
* @param row Screen position relative to viewport
*
*/
static void
draw_char(viewport_t *vport, char c, unsigned int row, unsigned int col,
style_t style, int transparent)
static void draw_char(viewport_t *vport, uint8_t c, unsigned int col, unsigned int row)
{
/* Optimize - do not hide cursor if we are going to overwrite it */
if (vport->cursor_active && vport->cursor_shown &&
(vport->cur_col != col || vport->cur_row != row))
invert_char(vport, vport->cur_row, vport->cur_col);
/* Do not hide cursor if we are going to overwrite it */
if ((vport->cursor_active) && (vport->cursor_shown) &&
((vport->cur_col != col) || (vport->cur_row != row)))
cursor_hide(vport);
draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style,
transparent);
 
uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)];
if (glyph != c) {
vport->backbuf[BB_POS(vport, col, row)] = c;
draw_glyph(vport, false, col, row);
}
vport->cur_col = col;
vport->cur_row = row;
 
vport->cur_col++;
if (vport->cur_col >= vport->cols) {
vport->cur_col = 0;
639,65 → 594,85
if (vport->cur_row >= vport->rows)
vport->cur_row--;
}
cursor_print(vport);
cursor_show(vport);
}
 
 
/** Draw text data to viewport
*
* @param vport Viewport id
* @param data Text data fitting exactly into viewport
* @param data Text data fitting exactly into viewport
*
*/
static void
draw_text_data(viewport_t *vport, keyfield_t *data)
static void draw_text_data(viewport_t *vport, keyfield_t *data)
{
int i;
int col,row;
 
clear_port(vport);
unsigned int i;
for (i = 0; i < vport->cols * vport->rows; i++) {
if (data[i].character == ' ' && style_same(data[i].style,
vport->style))
continue;
col = i % vport->cols;
row = i / vport->cols;
draw_glyph(vport, data[i].character, col * COL_WIDTH, row *
FONT_SCANLINES, data[i].style, style_same(data[i].style,
vport->style));
unsigned int col = i % vport->cols;
unsigned int row = i / vport->cols;
uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)];
// TODO: use data[i].style
if (glyph != data[i].character) {
vport->backbuf[BB_POS(vport, col, row)] = data[i].character;
draw_glyph(vport, false, col, row);
}
}
cursor_print(vport);
cursor_show(vport);
}
 
/** Return first free pixmap */
static int
find_free_pixmap(void)
 
static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
{
int i;
int pm = *((int *) data);
pixmap_t *pmap = &pixmaps[pm];
unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
for (i = 0;i < MAX_PIXMAPS;i++)
screen.rgb_conv(&pmap->data[pos], color);
}
 
 
static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
{
viewport_t *vport = (viewport_t *) data;
unsigned int dx = vport->x + x;
unsigned int dy = vport->y + y;
screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color);
}
 
 
/** Return first free pixmap
*
*/
static int find_free_pixmap(void)
{
unsigned int i;
for (i = 0; i < MAX_PIXMAPS; i++)
if (!pixmaps[i].data)
return i;
return -1;
}
 
static void
putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color)
{
pixmap_t *pmap = &pixmaps[pm];
int pos = (y * pmap->width + x) * screen.pixelbytes;
 
(*screen.rgb2scr)(&pmap->data[pos],COLOR(color));
}
 
/** Create a new pixmap and return appropriate ID */
static int
shm2pixmap(unsigned char *shm, size_t size)
/** Create a new pixmap and return appropriate ID
*
*/
static int shm2pixmap(unsigned char *shm, size_t size)
{
int pm;
pixmap_t *pmap;
 
pm = find_free_pixmap();
if (pm == -1)
return ELIMIT;
pmap = &pixmaps[pm];
if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
706,19 → 681,19
pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
if (!pmap->data)
return ENOMEM;
 
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height,
(putpixel_cb_t)putpixel_pixmap, (void *)pm);
 
ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
return pm;
}
 
 
/** Handle shared memory communication calls
*
* Protocol for drawing pixmaps:
* - FB_PREPARE_SHM(client shm identification)
* - IPC_M_AS_AREA_SEND
* - FB_DRAW_PPM(startx,starty)
* - FB_DRAW_PPM(startx, starty)
* - FB_DROP_SHM
*
* Protocol for text drawing
726,28 → 701,30
* - FB_DRAW_TEXT_DATA
*
* @param callid Callid of the current call
* @param call Current call data
* @param vp Active viewport
* @return 0 if the call was not handled byt this function, 1 otherwise
* @param call Current call data
* @param vp Active viewport
*
* note: this function is not threads safe, you would have
* @return false if the call was not handled byt this function, true otherwise
*
* Note: this function is not threads safe, you would have
* to redefine static variables with __thread
*
*/
static int
shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
{
static keyfield_t *interbuffer = NULL;
static size_t intersize = 0;
 
static unsigned char *shm = NULL;
static ipcarg_t shm_id = 0;
static size_t shm_size;
 
int handled = 1;
int retval = 0;
bool handled = true;
int retval = EOK;
viewport_t *vport = &viewports[vp];
unsigned int x, y;
 
unsigned int x;
unsigned int y;
switch (IPC_GET_METHOD(*call)) {
case IPC_M_SHARE_OUT:
/* We accept one area for data interchange */
754,19 → 731,20
if (IPC_GET_ARG1(*call) == shm_id) {
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
shm_size = IPC_GET_ARG2(*call);
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
shm = dest;
else
shm_id = 0;
if (shm[0] != 'P')
while (1)
;
return 1;
return false;
return true;
} else {
intersize = IPC_GET_ARG2(*call);
receive_comm_area(callid, call, (void *) &interbuffer);
}
return 1;
return true;
case FB_PREPARE_SHM:
if (shm_id)
retval = EBUSY;
781,7 → 759,7
}
shm_id = 0;
break;
 
case FB_SHM2PIXMAP:
if (!shm) {
retval = EINVAL;
796,14 → 774,14
}
x = IPC_GET_ARG1(*call);
y = IPC_GET_ARG2(*call);
if (x > vport->width || y > vport->height) {
if ((x > vport->width) || (y > vport->height)) {
retval = EINVAL;
break;
}
ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
IPC_GET_ARG2(*call), vport->width - x, vport->height - y,
(putpixel_cb_t)putpixel, vport);
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
break;
case FB_DRAW_TEXT_DATA:
if (!interbuffer) {
810,8 → 788,7
retval = EINVAL;
break;
}
if (intersize < vport->cols * vport->rows *
sizeof(*interbuffer)) {
if (intersize < vport->cols * vport->rows * sizeof(*interbuffer)) {
retval = EINVAL;
break;
}
818,7 → 795,7
draw_text_data(vport, interbuffer);
break;
default:
handled = 0;
handled = false;
}
if (handled)
826,41 → 803,39
return handled;
}
 
static void
copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
 
static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
{
int y;
int tmp, srcrowsize;
int realwidth, realheight, realrowsize;
int width = vport->width;
int height = vport->height;
 
unsigned int width = vport->width;
unsigned int height = vport->height;
if (width + vport->x > screen.xres)
width = screen.xres - vport->x;
if (height + vport->y > screen.yres)
height = screen.yres - vport->y;
realwidth = pmap->width <= width ? pmap->width : width;
realheight = pmap->height <= height ? pmap->height : height;
 
srcrowsize = vport->width * screen.pixelbytes;
realrowsize = realwidth * screen.pixelbytes;
unsigned int realwidth = pmap->width <= width ? pmap->width : width;
unsigned int realheight = pmap->height <= height ? pmap->height : height;
unsigned int srcrowsize = vport->width * screen.pixelbytes;
unsigned int realrowsize = realwidth * screen.pixelbytes;
unsigned int y;
for (y = 0; y < realheight; y++) {
tmp = (vport->y + y) * screen.scanline +
vport->x * screen.pixelbytes;
memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp,
realrowsize);
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
}
}
 
/** Save viewport to pixmap */
static int
save_vp_to_pixmap(viewport_t *vport)
 
/** Save viewport to pixmap
*
*/
static int save_vp_to_pixmap(viewport_t *vport)
{
int pm;
pixmap_t *pmap;
 
pm = find_free_pixmap();
if (pm == -1)
return ELIMIT;
869,58 → 844,60
pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
if (!pmap->data)
return ENOMEM;
 
pmap->width = vport->width;
pmap->height = vport->height;
 
copy_vp_to_pixmap(vport, pmap);
return pm;
}
 
 
/** Draw pixmap on screen
*
* @param vp Viewport to draw on
* @param pm Pixmap identifier
*
*/
static int draw_pixmap(int vp, int pm)
{
pixmap_t *pmap = &pixmaps[pm];
viewport_t *vport = &viewports[vp];
int y;
int tmp, srcrowsize;
int realwidth, realheight, realrowsize;
int width = vport->width;
int height = vport->height;
 
unsigned int width = vport->width;
unsigned int height = vport->height;
if (width + vport->x > screen.xres)
width = screen.xres - vport->x;
if (height + vport->y > screen.yres)
height = screen.yres - vport->y;
 
if (!pmap->data)
return EINVAL;
 
realwidth = pmap->width <= width ? pmap->width : width;
realheight = pmap->height <= height ? pmap->height : height;
 
srcrowsize = vport->width * screen.pixelbytes;
realrowsize = realwidth * screen.pixelbytes;
 
unsigned int realwidth = pmap->width <= width ? pmap->width : width;
unsigned int realheight = pmap->height <= height ? pmap->height : height;
unsigned int srcrowsize = vport->width * screen.pixelbytes;
unsigned int realrowsize = realwidth * screen.pixelbytes;
unsigned int y;
for (y = 0; y < realheight; y++) {
tmp = (vport->y + y) * screen.scanline +
vport->x * screen.pixelbytes;
memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize,
realrowsize);
unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
}
return 0;
return EOK;
}
 
/** Tick animation one step forward */
static void
anims_tick(void)
 
/** Tick animation one step forward
*
*/
static void anims_tick(void)
{
int i;
unsigned int i;
static int counts = 0;
/* Limit redrawing */
929,37 → 906,36
return;
 
for (i = 0; i < MAX_ANIMATIONS; i++) {
if (!animations[i].animlen || !animations[i].initialized ||
!animations[i].enabled)
if ((!animations[i].animlen) || (!animations[i].initialized) ||
(!animations[i].enabled))
continue;
draw_pixmap(animations[i].vp,
animations[i].pixmaps[animations[i].pos]);
animations[i].pos = (animations[i].pos + 1) %
animations[i].animlen;
draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
}
}
 
 
static int pointer_x, pointer_y;
static int pointer_shown, pointer_enabled;
static unsigned int pointer_x;
static unsigned int pointer_y;
static bool pointer_shown, pointer_enabled;
static int pointer_vport = -1;
static int pointer_pixmap = -1;
 
static void
mouse_show(void)
 
static void mouse_show(void)
{
int i, j;
int visibility;
int color;
int bytepos;
 
if (pointer_shown || !pointer_enabled)
if ((pointer_shown) || (!pointer_enabled))
return;
 
/* Save image under the cursor */
if (pointer_vport == -1) {
pointer_vport = viewport_create(pointer_x, pointer_y,
pointer_width, pointer_height);
pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height);
if (pointer_vport < 0)
return;
} else {
966,13 → 942,12
viewports[pointer_vport].x = pointer_x;
viewports[pointer_vport].y = pointer_y;
}
 
if (pointer_pixmap == -1)
pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
else
copy_vp_to_pixmap(&viewports[pointer_vport],
&pixmaps[pointer_pixmap]);
 
copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
/* Draw cursor */
for (i = 0; i < pointer_height; i++)
for (j = 0; j < pointer_width; j++) {
991,8 → 966,8
pointer_shown = 1;
}
 
static void
mouse_hide(void)
 
static void mouse_hide(void)
{
/* Restore image under the cursor */
if (pointer_shown) {
1001,8 → 976,8
}
}
 
static void
mouse_move(unsigned int x, unsigned int y)
 
static void mouse_move(unsigned int x, unsigned int y)
{
mouse_hide();
pointer_x = x;
1010,14 → 985,14
mouse_show();
}
 
static int
anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
 
static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
{
int handled = 1;
int retval = 0;
int i,nvp;
bool handled = true;
int retval = EOK;
int i, nvp;
int newval;
 
switch (IPC_GET_METHOD(*call)) {
case FB_ANIM_CREATE:
nvp = IPC_GET_ARG1(*call);
1107,14 → 1082,16
return handled;
}
 
/** Handler for messages concerning pixmap handling */
static int
pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
 
/** Handler for messages concerning pixmap handling
*
*/
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
{
int handled = 1;
int retval = 0;
int i,nvp;
 
bool handled = true;
int retval = EOK;
int i, nvp;
switch (IPC_GET_METHOD(*call)) {
case FB_VP_DRAW_PIXMAP:
nvp = IPC_GET_ARG1(*call);
1152,7 → 1129,7
default:
handled = 0;
}
 
if (handled)
ipc_answer_0(callid, retval);
return handled;
1162,32 → 1139,34
/** Function for handling connections to FB
*
*/
static void
fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
int i;
unsigned int row,col;
char c;
 
int vp = 0;
viewport_t *vport = &viewports[0];
 
unsigned int vp = 0;
viewport_t *vport = &viewports[vp];
if (client_connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
client_connected = 1;
ipc_answer_0(iid, EOK); /* Accept connection */
 
while (1) {
if (vport->cursor_active || anims_enabled)
/* Accept connection */
client_connected = true;
ipc_answer_0(iid, EOK);
while (true) {
ipc_callid_t callid;
ipc_call_t call;
int retval;
unsigned int i;
int scroll;
uint8_t glyph;
unsigned int row, col;
if ((vport->cursor_active) || (anims_enabled))
callid = async_get_call_timeout(&call, 250000);
else
callid = async_get_call(&call);
 
mouse_hide();
if (!callid) {
cursor_blink(vport);
1195,105 → 1174,89
mouse_show();
continue;
}
if (shm_handle(callid, &call, vp))
continue;
if (pixmap_handle(callid, &call, vp))
continue;
if (anim_handle(callid, &call, vp))
continue;
 
switch (IPC_GET_METHOD(call)) {
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
client_connected = 0;
/* cleanup other viewports */
client_connected = false;
/* Cleanup other viewports */
for (i = 1; i < MAX_VIEWPORTS; i++)
vport->initialized = 0;
return; /* Exit thread */
 
vport->initialized = false;
/* Exit thread */
return;
case FB_PUTCHAR:
case FB_TRANS_PUTCHAR:
c = IPC_GET_ARG1(call);
glyph = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if (row >= vport->rows || col >= vport->cols) {
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
break;
}
ipc_answer_0(callid, EOK);
 
draw_char(vport, c, row, col, vport->style,
IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR);
continue; /* msg already answered */
draw_char(vport, glyph, col, row);
/* Message already answered */
continue;
case FB_CLEAR:
clear_port(vport);
cursor_print(vport);
retval = 0;
vport_clear(vport);
cursor_show(vport);
retval = EOK;
break;
case FB_CURSOR_GOTO:
case FB_CURSOR_GOTO:
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
if (row >= vport->rows || col >= vport->cols) {
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
break;
}
retval = 0;
retval = EOK;
cursor_hide(vport);
vport->cur_col = col;
vport->cur_row = row;
cursor_print(vport);
break;
cursor_show(vport);
break;
case FB_CURSOR_VISIBILITY:
cursor_hide(vport);
vport->cursor_active = IPC_GET_ARG1(call);
cursor_print(vport);
retval = 0;
cursor_show(vport);
retval = EOK;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, vport->rows, vport->cols);
continue;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if (i > vport->rows || i < (- (int)vport->rows)) {
scroll = IPC_GET_ARG1(call);
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) {
retval = EINVAL;
break;
}
cursor_hide(vport);
scroll_port(vport, i*FONT_SCANLINES);
cursor_print(vport);
retval = 0;
vport_scroll(vport, scroll);
cursor_show(vport);
retval = EOK;
break;
case FB_VIEWPORT_DB:
/* Enable double buffering */
i = IPC_GET_ARG1(call);
if (i == -1)
i = vp;
if (i < 0 || i >= MAX_VIEWPORTS) {
retval = EINVAL;
break;
}
if (!viewports[i].initialized ) {
retval = EADDRNOTAVAIL;
break;
}
viewports[i].dboffset = 0;
if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata)
viewports[i].dbdata =
malloc(screen.pixelbytes *
viewports[i].width * viewports[i].height);
else if (IPC_GET_ARG2(call) == 0 &&
viewports[i].dbdata) {
free(viewports[i].dbdata);
viewports[i].dbdata = NULL;
}
retval = 0;
break;
case FB_VIEWPORT_SWITCH:
i = IPC_GET_ARG1(call);
if (i < 0 || i >= MAX_VIEWPORTS) {
if (i >= MAX_VIEWPORTS) {
retval = EINVAL;
break;
}
if (! viewports[i].initialized ) {
if (!viewports[i].initialized) {
retval = EADDRNOTAVAIL;
break;
}
1300,11 → 1263,11
cursor_hide(vport);
vp = i;
vport = &viewports[vp];
cursor_print(vport);
retval = 0;
cursor_show(vport);
retval = EOK;
break;
case FB_VIEWPORT_CREATE:
retval = viewport_create(IPC_GET_ARG1(call) >> 16,
retval = vport_create(IPC_GET_ARG1(call) >> 16,
IPC_GET_ARG1(call) & 0xffff,
IPC_GET_ARG2(call) >> 16,
IPC_GET_ARG2(call) & 0xffff);
1311,33 → 1274,36
break;
case FB_VIEWPORT_DELETE:
i = IPC_GET_ARG1(call);
if (i < 0 || i >= MAX_VIEWPORTS) {
if (i >= MAX_VIEWPORTS) {
retval = EINVAL;
break;
}
if (! viewports[i].initialized ) {
if (!viewports[i].initialized) {
retval = EADDRNOTAVAIL;
break;
}
viewports[i].initialized = 0;
if (viewports[i].dbdata) {
free(viewports[i].dbdata);
viewports[i].dbdata = NULL;
}
retval = 0;
viewports[i].initialized = false;
if (viewports[i].glyphs)
free(viewports[i].glyphs);
if (viewports[i].bgpixel)
free(viewports[i].bgpixel);
if (viewports[i].backbuf)
free(viewports[i].backbuf);
retval = EOK;
break;
case FB_SET_STYLE:
vport->style.fg_color = IPC_GET_ARG1(call);
vport->style.bg_color = IPC_GET_ARG2(call);
retval = 0;
render_glyphs(vport);
retval = EOK;
break;
case FB_GET_RESOLUTION:
ipc_answer_2(callid, EOK, screen.xres, screen.yres);
continue;
case FB_POINTER_MOVE:
pointer_enabled = 1;
pointer_enabled = true;
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
retval = 0;
retval = EOK;
break;
default:
retval = ENOENT;
1346,43 → 1312,32
}
}
 
/** Initialization of framebuffer */
int
fb_init(void)
/** Initialization of framebuffer
*
*/
int fb_init(void)
{
void *fb_ph_addr;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_scanline;
unsigned int fb_visual;
unsigned int fb_offset;
bool fb_invert_colors;
void *fb_addr;
size_t asz;
 
async_set_client_connection(fb_client_connection);
 
fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
fb_offset = sysinfo_value("fb.offset");
fb_width = sysinfo_value("fb.width");
fb_height = sysinfo_value("fb.height");
fb_scanline = sysinfo_value("fb.scanline");
fb_visual = sysinfo_value("fb.visual");
fb_invert_colors = sysinfo_value("fb.invert-colors");
 
asz = fb_scanline * fb_height;
fb_addr = as_get_mappable_page(asz);
physmem_map(fb_ph_addr + fb_offset, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >>
PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
 
if (screen_init(fb_addr, fb_offset, fb_width, fb_height, fb_scanline, fb_visual,
fb_invert_colors))
void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
unsigned int fb_offset = sysinfo_value("fb.offset");
unsigned int fb_width = sysinfo_value("fb.width");
unsigned int fb_height = sysinfo_value("fb.height");
unsigned int fb_scanline = sysinfo_value("fb.scanline");
unsigned int fb_visual = sysinfo_value("fb.visual");
unsigned int fbsize = fb_scanline * fb_height;
void *fb_addr = as_get_mappable_page(fbsize);
physmem_map(fb_ph_addr + fb_offset, fb_addr,
ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
return 0;
return -1;
}
 
/**
/**
* @}
*/
/trunk/uspace/srv/fb/ppm.c
92,23 → 92,23
int i;
unsigned int color;
unsigned int coef;
 
/* Read magic */
if (data[0] != 'P' || data[1] != '6')
if ((data[0] != 'P') || (data[1] != '6'))
return EINVAL;
 
data+=2;
data += 2;
skip_whitespace(&data);
read_num(&data, &width);
skip_whitespace(&data);
read_num(&data,&height);
read_num(&data, &height);
skip_whitespace(&data);
read_num(&data,&maxcolor);
read_num(&data, &maxcolor);
data++;
 
if (maxcolor == 0 || maxcolor > 255 || width * height > datasz) {
if ((maxcolor == 0) || (maxcolor > 255) || (width * height > datasz))
return EINVAL;
}
coef = 255 / maxcolor;
if (coef * maxcolor > 255)
coef -= 1;
125,6 → 125,6
(*putpixel)(vport, sx + (i % width), sy + (i / width), color);
data += 3;
}
 
return 0;
}
/trunk/uspace/srv/fb/fb.h
29,7 → 29,7
/** @addtogroup fb
* @ingroup fbs
* @{
*/
*/
/** @file
*/
 
36,8 → 36,10
#ifndef FB_FB_H_
#define FB_FB_H_
 
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, int);
#include <stdint.h>
 
typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t);
 
extern int fb_init(void);
 
#endif