Subversion Repositories HelenOS-historic

Rev

Rev 1500 | Rev 1505 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2006 Jakub Vana
  3.  * Copyright (C) 2006 Ondrej Palkovsky
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <string.h>
  33. #include <ddi.h>
  34. #include <sysinfo.h>
  35. #include <align.h>
  36. #include <as.h>
  37. #include <ipc/fb.h>
  38. #include <ipc/ipc.h>
  39. #include <ipc/ns.h>
  40. #include <ipc/services.h>
  41. #include <kernel/errno.h>
  42. #include <async.h>
  43. #include "font-8x16.h"
  44. #include "helenos.xbm"
  45. #include "fb.h"
  46.  
  47. #define DEFAULT_BGCOLOR                0x000080
  48. #define DEFAULT_FGCOLOR                0xffff00
  49.  
  50. /***************************************************************/
  51. /* Pixel specific fuctions */
  52.  
  53. typedef void (*putpixel_fn_t)(unsigned int x, unsigned int y, int color);
  54. typedef int (*getpixel_fn_t)(unsigned int x, unsigned int y);
  55.  
  56. struct {
  57.     __u8 *fbaddress ;
  58.  
  59.     unsigned int xres ;
  60.     unsigned int yres ;
  61.     unsigned int scanline ;
  62.     unsigned int pixelbytes ;
  63.  
  64.     putpixel_fn_t putpixel;
  65.     getpixel_fn_t getpixel;
  66. } screen;
  67.  
  68. typedef struct {
  69.     int initialized;
  70.     unsigned int x, y;
  71.     unsigned int width, height;
  72.  
  73.     /* Text support in window */
  74.     unsigned int rows, cols;
  75.     /* Style for text printing */
  76.     int bgcolor, fgcolor;
  77.     /* Auto-cursor position */
  78.     int cursor_active, cur_col, cur_row;
  79.     int cursor_shown;
  80. } viewport_t;
  81.  
  82. #define MAX_VIEWPORTS 128
  83. static viewport_t viewports[128];
  84.  
  85. /* Allow only 1 connection */
  86. static int client_connected = 0;
  87.  
  88. #define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
  89. #define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
  90. #define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
  91.  
  92. #define COL_WIDTH   8
  93. #define ROW_BYTES   (screen.scanline * FONT_SCANLINES)
  94.  
  95. #define POINTPOS(x, y)  ((y) * screen.scanline + (x) * screen.pixelbytes)
  96.  
  97. /** Put pixel - 24-bit depth, 1 free byte */
  98. static void putpixel_4byte(unsigned int x, unsigned int y, int color)
  99. {
  100.     *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) = color;
  101. }
  102.  
  103. /** Return pixel color - 24-bit depth, 1 free byte */
  104. static int getpixel_4byte(unsigned int x, unsigned int y)
  105. {
  106.     return *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) & 0xffffff;
  107. }
  108.  
  109. /** Put pixel - 24-bit depth */
  110. static void putpixel_3byte(unsigned int x, unsigned int y, int color)
  111. {
  112.     unsigned int startbyte = POINTPOS(x, y);
  113.  
  114. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  115.     screen.fbaddress[startbyte] = RED(color, 8);
  116.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  117.     screen.fbaddress[startbyte + 2] = BLUE(color, 8);
  118. #else
  119.     screen.fbaddress[startbyte + 2] = RED(color, 8);
  120.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  121.     screen.fbaddress[startbyte + 0] = BLUE(color, 8);
  122. #endif
  123.  
  124. }
  125.  
  126. /** Return pixel color - 24-bit depth */
  127. static int getpixel_3byte(unsigned int x, unsigned int y)
  128. {
  129.     unsigned int startbyte = POINTPOS(x, y);
  130.  
  131.  
  132.  
  133. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  134.     return screen.fbaddress[startbyte] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 2];
  135. #else
  136.     return screen.fbaddress[startbyte + 2] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 0];
  137. #endif
  138.                                
  139.  
  140. }
  141.  
  142. /** Put pixel - 16-bit depth (5:6:5) */
  143. static void putpixel_2byte(unsigned int x, unsigned int y, int color)
  144. {
  145.     /* 5-bit, 6-bits, 5-bits */
  146.     *((__u16 *)(screen.fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
  147. }
  148.  
  149. /** Return pixel color - 16-bit depth (5:6:5) */
  150. static int getpixel_2byte(unsigned int x, unsigned int y)
  151. {
  152.     int color = *((__u16 *)(screen.fbaddress + POINTPOS(x, y)));
  153.     return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
  154. }
  155.  
  156. /** Put pixel - 8-bit depth (3:2:3) */
  157. static void putpixel_1byte(unsigned int x, unsigned int y, int color)
  158. {
  159.     screen.fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
  160. }
  161.  
  162. /** Return pixel color - 8-bit depth (3:2:3) */
  163. static int getpixel_1byte(unsigned int x, unsigned int y)
  164. {
  165.     int color = screen.fbaddress[POINTPOS(x, y)];
  166.     return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
  167. }
  168.  
  169. /** Put pixel into viewport
  170.  *
  171.  * @param vp Viewport identification
  172.  * @param x X coord relative to viewport
  173.  * @param y Y coord relative to viewport
  174.  * @param color RGB color
  175.  */
  176. static void putpixel(int vp, unsigned int x, unsigned int y, int color)
  177. {
  178.     screen.putpixel(viewports[vp].x + x, viewports[vp].y + y, color);
  179. }
  180. /** Get pixel from viewport */
  181. static int getpixel(int vp, unsigned int x, unsigned int y)
  182. {
  183.     return screen.getpixel(viewports[vp].x + x, viewports[vp].y + y);
  184. }
  185.  
  186. /** Fill line with color BGCOLOR */
  187. static void clear_line(int vp, unsigned int y)
  188. {
  189.     unsigned int x;
  190.     for (x = 0; x < viewports[vp].width; x++)
  191.         putpixel(vp, x, y, viewports[vp].bgcolor);
  192. }
  193.  
  194. /** Fill viewport with background color */
  195. static void clear_port(int vp)
  196. {
  197.     unsigned int y;
  198.  
  199.     clear_line(vp, 0);
  200.     for (y = viewports[vp].y+1; y < viewports[vp].y+viewports[vp].height; y++) {
  201.         memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  202.                &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  203.                screen.pixelbytes * viewports[vp].width);
  204.     }  
  205. }
  206.  
  207. /** Scroll port up/down
  208.  *
  209.  * @param vp Viewport to scroll
  210.  * @param rows Positive number - scroll up, negative - scroll down
  211.  */
  212. static void scroll_port(int vp, int rows)
  213. {
  214.     int y;
  215.     int startline;
  216.     int endline;
  217.    
  218.     if (rows > 0) {
  219.         for (y=viewports[vp].y; y < viewports[vp].y+viewports[vp].height - rows*FONT_SCANLINES; y++)
  220.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  221.                    &screen.fbaddress[POINTPOS(viewports[vp].x,y + rows*FONT_SCANLINES)],
  222.                    screen.pixelbytes * viewports[vp].width);
  223.         /* Clear last row */
  224.         startline = viewports[vp].y+FONT_SCANLINES*(viewports[vp].rows-1);
  225.         endline = viewports[vp].y + viewports[vp].height;
  226.         clear_line(vp, startline);
  227.         for (y=startline+1;y < endline; y++)
  228.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  229.                    &screen.fbaddress[POINTPOS(viewports[vp].x,startline)],
  230.                    screen.pixelbytes * viewports[vp].width);
  231.                  
  232.     } else if (rows < 0) {
  233.         rows = -rows;
  234.         for (y=viewports[vp].y + viewports[vp].height-1; y >= viewports[vp].y + rows*FONT_SCANLINES; y--)
  235.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  236.                 &screen.fbaddress[POINTPOS(viewports[vp].x,y - rows*FONT_SCANLINES)],
  237.                 screen.pixelbytes * viewports[vp].width);
  238.         /* Clear first row */
  239.         clear_line(0, viewports[vp].bgcolor);
  240.         for (y=1;y < rows*FONT_SCANLINES; y++)
  241.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y+y)],
  242.                    &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  243.                    screen.pixelbytes * viewports[vp].width);
  244.     }
  245. }
  246.  
  247. static void invert_pixel(int vp,unsigned int x, unsigned int y)
  248. {
  249.     putpixel(vp, x, y, ~getpixel(vp, x, y));
  250. }
  251.  
  252.  
  253. /** Draw one line of glyph at a given position */
  254. static void draw_glyph_line(int vp,unsigned int glline, unsigned int x, unsigned int y)
  255. {
  256.     unsigned int i;
  257.  
  258.     for (i = 0; i < 8; i++)
  259.         if (glline & (1 << (7 - i))) {
  260.             putpixel(vp, x + i, y, viewports[vp].fgcolor);
  261.         } else
  262.             putpixel(vp, x + i, y, viewports[vp].bgcolor);
  263. }
  264.  
  265. /***************************************************************/
  266. /* Character-console functions */
  267.  
  268. /** Draw character at given position */
  269. static void draw_glyph(int vp,__u8 glyph, unsigned int sx, unsigned int sy)
  270. {
  271.     unsigned int y;
  272.  
  273.     for (y = 0; y < FONT_SCANLINES; y++)
  274.         draw_glyph_line(vp ,fb_font[glyph * FONT_SCANLINES + y], sx, sy + y);
  275. }
  276.  
  277. /** Invert character at given position */
  278. static void invert_char(int vp,unsigned int row, unsigned int col)
  279. {
  280.     unsigned int x;
  281.     unsigned int y;
  282.  
  283.     for (x = 0; x < COL_WIDTH; x++)
  284.         for (y = 0; y < FONT_SCANLINES; y++)
  285.             invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y);
  286. }
  287.  
  288. static void draw_logo(int vp,unsigned int startx, unsigned int starty)
  289. {
  290.     unsigned int x;
  291.     unsigned int y;
  292.     unsigned int byte;
  293.     unsigned int rowbytes;
  294.  
  295.     rowbytes = (helenos_width - 1) / 8 + 1;
  296.  
  297.     for (y = 0; y < helenos_height; y++)
  298.         for (x = 0; x < helenos_width; x++) {
  299.             byte = helenos_bits[rowbytes * y + x / 8];
  300.             byte >>= x % 8;
  301.             if (byte & 1)
  302.                 putpixel(vp ,startx + x, starty + y, viewports[vp].fgcolor);
  303.         }
  304. }
  305.  
  306. /***************************************************************/
  307. /* Stdout specific functions */
  308.  
  309.  
  310. /** Create new viewport
  311.  *
  312.  * @return New viewport number
  313.  */
  314. static int viewport_create(unsigned int x, unsigned int y,unsigned int width,
  315.                unsigned int height)
  316. {
  317.     int i;
  318.  
  319. for (i=0; i < MAX_VIEWPORTS; i++) {
  320.         if (!viewports[i].initialized)
  321.             break;
  322.     }
  323.     if (i == MAX_VIEWPORTS)
  324.         return ELIMIT;
  325.  
  326.     if (width ==0 || height == 0 ||
  327.         x+width > screen.xres || y+height > screen.yres)
  328.         return EINVAL;
  329.     if (width < FONT_SCANLINES || height < COL_WIDTH)
  330.         return EINVAL;
  331.  
  332.     viewports[i].x = x;
  333.     viewports[i].y = y;
  334.     viewports[i].width = width;
  335.     viewports[i].height = height;
  336.    
  337.     viewports[i].rows = height / FONT_SCANLINES;
  338.     viewports[i].cols = width / COL_WIDTH;
  339.  
  340.     viewports[i].bgcolor = DEFAULT_BGCOLOR;
  341.     viewports[i].fgcolor = DEFAULT_FGCOLOR;
  342.    
  343.     viewports[i].cur_col = 0;
  344.     viewports[i].cur_row = 0;
  345.     viewports[i].cursor_active = 0;
  346.  
  347.     viewports[i].initialized = 1;
  348.  
  349.     return i;
  350. }
  351.  
  352.  
  353. /** Initialize framebuffer as a chardev output device
  354.  *
  355.  * @param addr Address of theframebuffer
  356.  * @param x    Screen width in pixels
  357.  * @param y    Screen height in pixels
  358.  * @param bpp  Bits per pixel (8, 16, 24, 32)
  359.  * @param scan Bytes per one scanline
  360.  *
  361.  */
  362. static void screen_init(void *addr, unsigned int xres, unsigned int yres, unsigned int bpp, unsigned int scan)
  363. {
  364.     switch (bpp) {
  365.         case 8:
  366.             screen.putpixel = putpixel_1byte;
  367.             screen.getpixel = getpixel_1byte;
  368.             screen.pixelbytes = 1;
  369.             break;
  370.         case 16:
  371.             screen.putpixel = putpixel_2byte;
  372.             screen.getpixel = getpixel_2byte;
  373.             screen.pixelbytes = 2;
  374.             break;
  375.         case 24:
  376.             screen.putpixel = putpixel_3byte;
  377.             screen.getpixel = getpixel_3byte;
  378.             screen.pixelbytes = 3;
  379.             break;
  380.         case 32:
  381.             screen.putpixel = putpixel_4byte;
  382.             screen.getpixel = getpixel_4byte;
  383.             screen.pixelbytes = 4;
  384.             break;
  385.     }
  386.  
  387.        
  388.     screen.fbaddress = (unsigned char *) addr;
  389.     screen.xres = xres;
  390.     screen.yres = yres;
  391.     screen.scanline = scan;
  392.    
  393.     /* Create first viewport */
  394.     viewport_create(0,0,xres,yres);
  395.  
  396.     clear_port(0);
  397. }
  398.  
  399. static void cursor_hide(int vp)
  400. {
  401.     viewport_t *vport = &viewports[vp];
  402.  
  403.     if (vport->cursor_active && vport->cursor_shown) {
  404.         invert_char(vp, vport->cur_row, vport->cur_col);
  405.         vport->cursor_shown = 0;
  406.     }
  407. }
  408.  
  409. static void cursor_print(int vp)
  410. {
  411.     viewport_t *vport = &viewports[vp];
  412.  
  413.     /* Do not check for cursor_shown */
  414.     if (vport->cursor_active) {
  415.         invert_char(vp, vport->cur_row, vport->cur_col);
  416.         vport->cursor_shown = 1;
  417.     }
  418. }
  419.  
  420. static void cursor_blink(int vp)
  421. {
  422.     viewport_t *vport = &viewports[vp];
  423.  
  424.     if (vport->cursor_shown)
  425.         cursor_hide(vp);
  426.     else
  427.         cursor_print(vp);
  428. }
  429.  
  430. /** Draw character at given position relative to viewport
  431.  *
  432.  * @param vp Viewport identification
  433.  * @param c Character to print
  434.  * @param row Screen position relative to viewport
  435.  * @param col Screen position relative to viewport
  436.  */
  437. static void draw_char(int vp, char c, unsigned int row, unsigned int col)
  438. {
  439.     viewport_t *vport = &viewports[vp];
  440.  
  441.     /* Optimize - do not hide cursor if we are going to overwrite it */
  442.     if (vport->cursor_active && vport->cursor_shown &&
  443.         (vport->cur_col != col || vport->cur_row != row))
  444.         invert_char(vp, vport->cur_row, vport->cur_col);
  445.    
  446.     draw_glyph(vp, c, col * COL_WIDTH, row * FONT_SCANLINES);
  447.  
  448.     vport->cur_col = col;
  449.     vport->cur_row = row;
  450.  
  451.     vport->cur_col++;
  452.     if (vport->cur_col>= vport->cols) {
  453.         vport->cur_col = 0;
  454.         vport->cur_row++;
  455.         if (vport->cur_row >= vport->rows)
  456.             vport->cur_row--;
  457.     }
  458.     cursor_print(vp);
  459. }
  460.  
  461. /** Function for handling connections to FB
  462.  *
  463.  */
  464. static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  465. {
  466.     ipc_callid_t callid;
  467.     ipc_call_t call;
  468.     int retval;
  469.     int i;
  470.     unsigned int row,col;
  471.     char c;
  472.  
  473.     int vp = 0;
  474.     viewport_t *vport = &viewports[0];
  475.  
  476.     if (client_connected) {
  477.         ipc_answer_fast(iid, ELIMIT, 0,0);
  478.         return;
  479.     }
  480.     client_connected = 1;
  481.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  482.  
  483.     while (1) {
  484.         callid = async_get_call_timeout(&call,250000);
  485.         if (!callid) {
  486.             cursor_blink(vp);
  487.             continue;
  488.         }
  489.         switch (IPC_GET_METHOD(call)) {
  490.         case IPC_M_PHONE_HUNGUP:
  491.             client_connected = 0;
  492.             /* cleanup other viewports */
  493.             for (i=1; i < MAX_VIEWPORTS; i++)
  494.                 vport->initialized = 0;
  495.             ipc_answer_fast(callid,0,0,0);
  496.             return; /* Exit thread */
  497.         case FB_PUTCHAR:
  498.             c = IPC_GET_ARG1(call);
  499.             row = IPC_GET_ARG2(call);
  500.             col = IPC_GET_ARG3(call);
  501.             if (row >= vport->rows || col >= vport->cols) {
  502.                 retval = EINVAL;
  503.                 break;
  504.             }
  505.             ipc_answer_fast(callid,0,0,0);
  506.  
  507.             draw_char(vp, c, row, col);
  508.             continue; /* msg already answered */
  509.         case FB_CLEAR:
  510.             clear_port(vp);
  511.             cursor_print(vp);
  512.             retval = 0;
  513.             break;
  514.         case FB_CURSOR_GOTO:
  515.             row = IPC_GET_ARG1(call);
  516.             col = IPC_GET_ARG2(call);
  517.             if (row >= vport->rows || col >= vport->cols) {
  518.                 retval = EINVAL;
  519.                 break;
  520.             }
  521.             retval = 0;
  522.             cursor_hide(vp);
  523.             vport->cur_col = col;
  524.             vport->cur_row = row;
  525.             cursor_print(vp);
  526.             break;
  527.         case FB_CURSOR_VISIBILITY:
  528.             cursor_hide(vp);
  529.             vport->cursor_active = IPC_GET_ARG1(call);
  530.             cursor_print(vp);
  531.             retval = 0;
  532.             break;
  533.         case FB_GET_CSIZE:
  534.             ipc_answer_fast(callid, 0, vport->rows, vport->cols);
  535.             continue;
  536.         case FB_SCROLL:
  537.             i = IPC_GET_ARG1(call);
  538.             if (i > vport->rows || i < (- (int)vport->rows)) {
  539.                 retval = EINVAL;
  540.                 break;
  541.             }
  542.             cursor_hide(vp);
  543.             scroll_port(vp, i);
  544.             cursor_print(vp);
  545.             retval = 0;
  546.             break;
  547.         case FB_VIEWPORT_SWITCH:
  548.             i = IPC_GET_ARG1(call);
  549.             if (i < 0 || i >= MAX_VIEWPORTS) {
  550.                 retval = EINVAL;
  551.                 break;
  552.             }
  553.             if (! viewports[i].initialized ) {
  554.                 retval = EADDRNOTAVAIL;
  555.                 break;
  556.             }
  557.             cursor_hide(vp);
  558.             vp = i;
  559.             vport = &viewports[vp];
  560.             cursor_print(vp);
  561.             retval = 0;
  562.             break;
  563.         case FB_VIEWPORT_CREATE:
  564.             retval = viewport_create(IPC_GET_ARG1(call) >> 16,
  565.                          IPC_GET_ARG1(call) & 0xffff,
  566.                          IPC_GET_ARG2(call) >> 16,
  567.                          IPC_GET_ARG2(call) & 0xffff);
  568.             break;
  569.         case FB_VIEWPORT_DELETE:
  570.             i = IPC_GET_ARG1(call);
  571.             if (i < 0 || i >= MAX_VIEWPORTS) {
  572.                 retval = EINVAL;
  573.                 break;
  574.             }
  575.             if (! viewports[i].initialized ) {
  576.                 retval = EADDRNOTAVAIL;
  577.                 break;
  578.             }
  579.             viewports[i].initialized = 0;
  580.             retval = 0;
  581.             break;
  582.         case FB_SET_STYLE:
  583.             vport->fgcolor = IPC_GET_ARG1(call);
  584.             vport->bgcolor = IPC_GET_ARG2(call);
  585.             retval = 0;
  586.             break;
  587.         case FB_GET_RESOLUTION:
  588.             ipc_answer_fast(callid, 0, screen.xres,screen.yres);
  589.             continue;
  590.         default:
  591.             retval = ENOENT;
  592.         }
  593.         ipc_answer_fast(callid,retval,0,0);
  594.     }
  595. }
  596.  
  597. /** Initialization of framebuffer */
  598. int fb_init(void)
  599. {
  600.     void *fb_ph_addr;
  601.     unsigned int fb_width;
  602.     unsigned int fb_height;
  603.     unsigned int fb_bpp;
  604.     unsigned int fb_scanline;
  605.     void *fb_addr;
  606.     size_t asz;
  607.  
  608.     async_set_client_connection(fb_client_connection);
  609.  
  610.     fb_ph_addr=(void *)sysinfo_value("fb.address.physical");
  611.     fb_width=sysinfo_value("fb.width");
  612.     fb_height=sysinfo_value("fb.height");
  613.     fb_bpp=sysinfo_value("fb.bpp");
  614.     fb_scanline=sysinfo_value("fb.scanline");
  615.  
  616.     asz = fb_scanline*fb_height;
  617.     fb_addr = as_get_mappable_page(asz);
  618.    
  619.     map_physmem(fb_ph_addr, fb_addr, ALIGN_UP(asz,PAGE_SIZE) >>PAGE_WIDTH,
  620.             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
  621.    
  622.     screen_init(fb_addr, fb_width, fb_height, fb_bpp, fb_scanline);
  623.  
  624.     return 0;
  625. }
  626.  
  627.