Subversion Repositories HelenOS-historic

Rev

Rev 1501 | Rev 1509 | 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.  
  44. #include "font-8x16.h"
  45. #include "helenos.xbm"
  46. #include "fb.h"
  47. #include "main.h"
  48. #include "../console/screenbuffer.h"
  49.  
  50. #define DEFAULT_BGCOLOR                0x000080
  51. #define DEFAULT_FGCOLOR                0xffff00
  52.  
  53. /***************************************************************/
  54. /* Pixel specific fuctions */
  55.  
  56. typedef void (*putpixel_fn_t)(unsigned int x, unsigned int y, int color);
  57. typedef int (*getpixel_fn_t)(unsigned int x, unsigned int y);
  58.  
  59. struct {
  60.     __u8 *fbaddress ;
  61.  
  62.     unsigned int xres ;
  63.     unsigned int yres ;
  64.     unsigned int scanline ;
  65.     unsigned int pixelbytes ;
  66.  
  67.     putpixel_fn_t putpixel;
  68.     getpixel_fn_t getpixel;
  69. } screen;
  70.  
  71. typedef struct {
  72.     int initialized;
  73.     unsigned int x, y;
  74.     unsigned int width, height;
  75.  
  76.     /* Text support in window */
  77.     unsigned int rows, cols;
  78.     /* Style for text printing */
  79.     int bgcolor, fgcolor;
  80.     /* Auto-cursor position */
  81.     int cursor_active, cur_col, cur_row;
  82.     int cursor_shown;
  83. } viewport_t;
  84.  
  85. #define MAX_VIEWPORTS 128
  86. static viewport_t viewports[128];
  87.  
  88. /* Allow only 1 connection */
  89. static int client_connected = 0;
  90.  
  91. #define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
  92. #define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
  93. #define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
  94.  
  95. #define COL_WIDTH   8
  96. #define ROW_BYTES   (screen.scanline * FONT_SCANLINES)
  97.  
  98. #define POINTPOS(x, y)  ((y) * screen.scanline + (x) * screen.pixelbytes)
  99.  
  100. /** Put pixel - 24-bit depth, 1 free byte */
  101. static void putpixel_4byte(unsigned int x, unsigned int y, int color)
  102. {
  103.     *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) = color;
  104. }
  105.  
  106. /** Return pixel color - 24-bit depth, 1 free byte */
  107. static int getpixel_4byte(unsigned int x, unsigned int y)
  108. {
  109.     return *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) & 0xffffff;
  110. }
  111.  
  112. /** Put pixel - 24-bit depth */
  113. static void putpixel_3byte(unsigned int x, unsigned int y, int color)
  114. {
  115.     unsigned int startbyte = POINTPOS(x, y);
  116.  
  117. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  118.     screen.fbaddress[startbyte] = RED(color, 8);
  119.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  120.     screen.fbaddress[startbyte + 2] = BLUE(color, 8);
  121. #else
  122.     screen.fbaddress[startbyte + 2] = RED(color, 8);
  123.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  124.     screen.fbaddress[startbyte + 0] = BLUE(color, 8);
  125. #endif
  126.  
  127. }
  128.  
  129. /** Return pixel color - 24-bit depth */
  130. static int getpixel_3byte(unsigned int x, unsigned int y)
  131. {
  132.     unsigned int startbyte = POINTPOS(x, y);
  133.  
  134.  
  135.  
  136. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  137.     return screen.fbaddress[startbyte] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 2];
  138. #else
  139.     return screen.fbaddress[startbyte + 2] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 0];
  140. #endif
  141.                                
  142.  
  143. }
  144.  
  145. /** Put pixel - 16-bit depth (5:6:5) */
  146. static void putpixel_2byte(unsigned int x, unsigned int y, int color)
  147. {
  148.     /* 5-bit, 6-bits, 5-bits */
  149.     *((__u16 *)(screen.fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
  150. }
  151.  
  152. /** Return pixel color - 16-bit depth (5:6:5) */
  153. static int getpixel_2byte(unsigned int x, unsigned int y)
  154. {
  155.     int color = *((__u16 *)(screen.fbaddress + POINTPOS(x, y)));
  156.     return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
  157. }
  158.  
  159. /** Put pixel - 8-bit depth (3:2:3) */
  160. static void putpixel_1byte(unsigned int x, unsigned int y, int color)
  161. {
  162.     screen.fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
  163. }
  164.  
  165. /** Return pixel color - 8-bit depth (3:2:3) */
  166. static int getpixel_1byte(unsigned int x, unsigned int y)
  167. {
  168.     int color = screen.fbaddress[POINTPOS(x, y)];
  169.     return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
  170. }
  171.  
  172. /** Put pixel into viewport
  173.  *
  174.  * @param vp Viewport identification
  175.  * @param x X coord relative to viewport
  176.  * @param y Y coord relative to viewport
  177.  * @param color RGB color
  178.  */
  179. static void putpixel(int vp, unsigned int x, unsigned int y, int color)
  180. {
  181.     screen.putpixel(viewports[vp].x + x, viewports[vp].y + y, color);
  182. }
  183. /** Get pixel from viewport */
  184. static int getpixel(int vp, unsigned int x, unsigned int y)
  185. {
  186.     return screen.getpixel(viewports[vp].x + x, viewports[vp].y + y);
  187. }
  188.  
  189. /** Fill line with color BGCOLOR */
  190. static void clear_line(int vp, unsigned int y)
  191. {
  192.     unsigned int x;
  193.     for (x = 0; x < viewports[vp].width; x++)
  194.         putpixel(vp, x, y, viewports[vp].bgcolor);
  195. }
  196.  
  197. /** Fill viewport with background color */
  198. static void clear_port(int vp)
  199. {
  200.     unsigned int y;
  201.  
  202.     clear_line(vp, 0);
  203.     for (y = viewports[vp].y+1; y < viewports[vp].y+viewports[vp].height; y++) {
  204.         memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  205.                &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  206.                screen.pixelbytes * viewports[vp].width);
  207.     }  
  208. }
  209.  
  210. /** Scroll port up/down
  211.  *
  212.  * @param vp Viewport to scroll
  213.  * @param rows Positive number - scroll up, negative - scroll down
  214.  */
  215. static void scroll_port(int vp, int rows)
  216. {
  217.     int y;
  218.     int startline;
  219.     int endline;
  220.    
  221.     if (rows > 0) {
  222.         for (y=viewports[vp].y; y < viewports[vp].y+viewports[vp].height - rows*FONT_SCANLINES; y++)
  223.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  224.                    &screen.fbaddress[POINTPOS(viewports[vp].x,y + rows*FONT_SCANLINES)],
  225.                    screen.pixelbytes * viewports[vp].width);
  226.         /* Clear last row */
  227.         startline = viewports[vp].y+FONT_SCANLINES*(viewports[vp].rows-1);
  228.         endline = viewports[vp].y + viewports[vp].height;
  229.         clear_line(vp, startline);
  230.         for (y=startline+1;y < endline; y++)
  231.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  232.                    &screen.fbaddress[POINTPOS(viewports[vp].x,startline)],
  233.                    screen.pixelbytes * viewports[vp].width);
  234.                  
  235.     } else if (rows < 0) {
  236.         rows = -rows;
  237.         for (y=viewports[vp].y + viewports[vp].height-1; y >= viewports[vp].y + rows*FONT_SCANLINES; y--)
  238.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  239.                 &screen.fbaddress[POINTPOS(viewports[vp].x,y - rows*FONT_SCANLINES)],
  240.                 screen.pixelbytes * viewports[vp].width);
  241.         /* Clear first row */
  242.         clear_line(0, viewports[vp].bgcolor);
  243.         for (y=1;y < rows*FONT_SCANLINES; y++)
  244.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y+y)],
  245.                    &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  246.                    screen.pixelbytes * viewports[vp].width);
  247.     }
  248. }
  249.  
  250. static void invert_pixel(int vp,unsigned int x, unsigned int y)
  251. {
  252.     putpixel(vp, x, y, ~getpixel(vp, x, y));
  253. }
  254.  
  255.  
  256. /** Draw one line of glyph at a given position */
  257. static void draw_glyph_line(int vp,unsigned int glline, unsigned int x, unsigned int y)
  258. {
  259.     unsigned int i;
  260.  
  261.     for (i = 0; i < 8; i++)
  262.         if (glline & (1 << (7 - i))) {
  263.             putpixel(vp, x + i, y, viewports[vp].fgcolor);
  264.         } else
  265.             putpixel(vp, x + i, y, viewports[vp].bgcolor);
  266. }
  267.  
  268. /***************************************************************/
  269. /* Character-console functions */
  270.  
  271. /** Draw character at given position */
  272. static void draw_glyph(int vp,__u8 glyph, unsigned int sx, unsigned int sy)
  273. {
  274.     unsigned int y;
  275.  
  276.     for (y = 0; y < FONT_SCANLINES; y++)
  277.         draw_glyph_line(vp ,fb_font[glyph * FONT_SCANLINES + y], sx, sy + y);
  278. }
  279.  
  280. /** Invert character at given position */
  281. static void invert_char(int vp,unsigned int row, unsigned int col)
  282. {
  283.     unsigned int x;
  284.     unsigned int y;
  285.  
  286.     for (x = 0; x < COL_WIDTH; x++)
  287.         for (y = 0; y < FONT_SCANLINES; y++)
  288.             invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y);
  289. }
  290.  
  291. static void draw_logo(int vp,unsigned int startx, unsigned int starty)
  292. {
  293.     unsigned int x;
  294.     unsigned int y;
  295.     unsigned int byte;
  296.     unsigned int rowbytes;
  297.  
  298.     rowbytes = (helenos_width - 1) / 8 + 1;
  299.  
  300.     for (y = 0; y < helenos_height; y++)
  301.         for (x = 0; x < helenos_width; x++) {
  302.             byte = helenos_bits[rowbytes * y + x / 8];
  303.             byte >>= x % 8;
  304.             if (byte & 1)
  305.                 putpixel(vp ,startx + x, starty + y, viewports[vp].fgcolor);
  306.         }
  307. }
  308.  
  309. /***************************************************************/
  310. /* Stdout specific functions */
  311.  
  312.  
  313. /** Create new viewport
  314.  *
  315.  * @return New viewport number
  316.  */
  317. static int viewport_create(unsigned int x, unsigned int y,unsigned int width,
  318.                unsigned int height)
  319. {
  320.     int i;
  321.  
  322. for (i=0; i < MAX_VIEWPORTS; i++) {
  323.         if (!viewports[i].initialized)
  324.             break;
  325.     }
  326.     if (i == MAX_VIEWPORTS)
  327.         return ELIMIT;
  328.  
  329.     if (width ==0 || height == 0 ||
  330.         x+width > screen.xres || y+height > screen.yres)
  331.         return EINVAL;
  332.     if (width < FONT_SCANLINES || height < COL_WIDTH)
  333.         return EINVAL;
  334.  
  335.     viewports[i].x = x;
  336.     viewports[i].y = y;
  337.     viewports[i].width = width;
  338.     viewports[i].height = height;
  339.    
  340.     viewports[i].rows = height / FONT_SCANLINES;
  341.     viewports[i].cols = width / COL_WIDTH;
  342.  
  343.     viewports[i].bgcolor = DEFAULT_BGCOLOR;
  344.     viewports[i].fgcolor = DEFAULT_FGCOLOR;
  345.    
  346.     viewports[i].cur_col = 0;
  347.     viewports[i].cur_row = 0;
  348.     viewports[i].cursor_active = 0;
  349.  
  350.     viewports[i].initialized = 1;
  351.  
  352.     return i;
  353. }
  354.  
  355.  
  356. /** Initialize framebuffer as a chardev output device
  357.  *
  358.  * @param addr Address of theframebuffer
  359.  * @param x    Screen width in pixels
  360.  * @param y    Screen height in pixels
  361.  * @param bpp  Bits per pixel (8, 16, 24, 32)
  362.  * @param scan Bytes per one scanline
  363.  *
  364.  */
  365. static void screen_init(void *addr, unsigned int xres, unsigned int yres, unsigned int bpp, unsigned int scan)
  366. {
  367.     switch (bpp) {
  368.         case 8:
  369.             screen.putpixel = putpixel_1byte;
  370.             screen.getpixel = getpixel_1byte;
  371.             screen.pixelbytes = 1;
  372.             break;
  373.         case 16:
  374.             screen.putpixel = putpixel_2byte;
  375.             screen.getpixel = getpixel_2byte;
  376.             screen.pixelbytes = 2;
  377.             break;
  378.         case 24:
  379.             screen.putpixel = putpixel_3byte;
  380.             screen.getpixel = getpixel_3byte;
  381.             screen.pixelbytes = 3;
  382.             break;
  383.         case 32:
  384.             screen.putpixel = putpixel_4byte;
  385.             screen.getpixel = getpixel_4byte;
  386.             screen.pixelbytes = 4;
  387.             break;
  388.     }
  389.  
  390.        
  391.     screen.fbaddress = (unsigned char *) addr;
  392.     screen.xres = xres;
  393.     screen.yres = yres;
  394.     screen.scanline = scan;
  395.    
  396.     /* Create first viewport */
  397.     viewport_create(0,0,xres,yres);
  398.  
  399.     clear_port(0);
  400. }
  401.  
  402. static void cursor_hide(int vp)
  403. {
  404.     viewport_t *vport = &viewports[vp];
  405.  
  406.     if (vport->cursor_active && vport->cursor_shown) {
  407.         invert_char(vp, vport->cur_row, vport->cur_col);
  408.         vport->cursor_shown = 0;
  409.     }
  410. }
  411.  
  412. static void cursor_print(int vp)
  413. {
  414.     viewport_t *vport = &viewports[vp];
  415.  
  416.     /* Do not check for cursor_shown */
  417.     if (vport->cursor_active) {
  418.         invert_char(vp, vport->cur_row, vport->cur_col);
  419.         vport->cursor_shown = 1;
  420.     }
  421. }
  422.  
  423. static void cursor_blink(int vp)
  424. {
  425.     viewport_t *vport = &viewports[vp];
  426.  
  427.     if (vport->cursor_shown)
  428.         cursor_hide(vp);
  429.     else
  430.         cursor_print(vp);
  431. }
  432.  
  433. /** Draw character at given position relative to viewport
  434.  *
  435.  * @param vp Viewport identification
  436.  * @param c Character to print
  437.  * @param row Screen position relative to viewport
  438.  * @param col Screen position relative to viewport
  439.  */
  440. static void draw_char(int vp, char c, unsigned int row, unsigned int col)
  441. {
  442.     viewport_t *vport = &viewports[vp];
  443.  
  444.     /* Optimize - do not hide cursor if we are going to overwrite it */
  445.     if (vport->cursor_active && vport->cursor_shown &&
  446.         (vport->cur_col != col || vport->cur_row != row))
  447.         invert_char(vp, vport->cur_row, vport->cur_col);
  448.    
  449.     draw_glyph(vp, c, col * COL_WIDTH, row * FONT_SCANLINES);
  450.  
  451.     vport->cur_col = col;
  452.     vport->cur_row = row;
  453.  
  454.     vport->cur_col++;
  455.     if (vport->cur_col>= vport->cols) {
  456.         vport->cur_col = 0;
  457.         vport->cur_row++;
  458.         if (vport->cur_row >= vport->rows)
  459.             vport->cur_row--;
  460.     }
  461.     cursor_print(vp);
  462. }
  463.  
  464. static void draw_text_data(int vp, keyfield_t *data)
  465. {
  466.     viewport_t *vport = &viewports[vp];
  467.     int i;
  468.     char c;
  469.  
  470.     clear_port(vp);
  471.     for (i=0; i < vport->cols * vport->rows; i++) {
  472.         if (data[i].character == ' ') /* TODO: && data[i].style==vport->style */
  473.             continue;
  474.         draw_char(vp, data[i].character, i/vport->rows, i % vport->cols);
  475.     }
  476.     cursor_print(vp);
  477. }
  478.  
  479.  
  480. /** Function for handling connections to FB
  481.  *
  482.  */
  483. static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  484. {
  485.     ipc_callid_t callid;
  486.     ipc_call_t call;
  487.     int retval;
  488.     int i;
  489.     unsigned int row,col;
  490.     char c;
  491.     keyfield_t *interbuffer = NULL;
  492.     size_t intersize = 0;
  493.  
  494.     int vp = 0;
  495.     viewport_t *vport = &viewports[0];
  496.  
  497.     if (client_connected) {
  498.         ipc_answer_fast(iid, ELIMIT, 0,0);
  499.         return;
  500.     }
  501.     client_connected = 1;
  502.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  503.  
  504.     while (1) {
  505.         callid = async_get_call_timeout(&call,250000);
  506.         if (!callid) {
  507.             cursor_blink(vp);
  508.             continue;
  509.         }
  510.         switch (IPC_GET_METHOD(call)) {
  511.         case IPC_M_PHONE_HUNGUP:
  512.             client_connected = 0;
  513.             /* cleanup other viewports */
  514.             for (i=1; i < MAX_VIEWPORTS; i++)
  515.                 vport->initialized = 0;
  516.             ipc_answer_fast(callid,0,0,0);
  517.             return; /* Exit thread */
  518.         case IPC_M_AS_AREA_SEND:
  519.             /* We accept one area for data interchange */
  520.             intersize = IPC_GET_ARG2(call);
  521.             receive_comm_area(callid,&call,(void **)&interbuffer,
  522.                       sizeof(*interbuffer)*viewports[0].cols*viewports[0].rows);
  523.             continue;
  524.  
  525.         case FB_DRAW_TEXT_DATA:
  526.             if (!interbuffer) {
  527.                 retval = EINVAL;
  528.                 break;
  529.             }
  530.             if (intersize < vport->cols*vport->rows*sizeof(*interbuffer)) {
  531.                 retval = EINVAL;
  532.                 break;
  533.             }
  534.             draw_text_data(vp, interbuffer);
  535.             retval = 0;
  536.             break;
  537.         case FB_PUTCHAR:
  538.             c = IPC_GET_ARG1(call);
  539.             row = IPC_GET_ARG2(call);
  540.             col = IPC_GET_ARG3(call);
  541.             if (row >= vport->rows || col >= vport->cols) {
  542.                 retval = EINVAL;
  543.                 break;
  544.             }
  545.             ipc_answer_fast(callid,0,0,0);
  546.  
  547.             draw_char(vp, c, row, col);
  548.             continue; /* msg already answered */
  549.         case FB_CLEAR:
  550.             clear_port(vp);
  551.             cursor_print(vp);
  552.             retval = 0;
  553.             break;
  554.         case FB_CURSOR_GOTO:
  555.             row = IPC_GET_ARG1(call);
  556.             col = IPC_GET_ARG2(call);
  557.             if (row >= vport->rows || col >= vport->cols) {
  558.                 retval = EINVAL;
  559.                 break;
  560.             }
  561.             retval = 0;
  562.             cursor_hide(vp);
  563.             vport->cur_col = col;
  564.             vport->cur_row = row;
  565.             cursor_print(vp);
  566.             break;
  567.         case FB_CURSOR_VISIBILITY:
  568.             cursor_hide(vp);
  569.             vport->cursor_active = IPC_GET_ARG1(call);
  570.             cursor_print(vp);
  571.             retval = 0;
  572.             break;
  573.         case FB_GET_CSIZE:
  574.             ipc_answer_fast(callid, 0, vport->rows, vport->cols);
  575.             continue;
  576.         case FB_SCROLL:
  577.             i = IPC_GET_ARG1(call);
  578.             if (i > vport->rows || i < (- (int)vport->rows)) {
  579.                 retval = EINVAL;
  580.                 break;
  581.             }
  582.             cursor_hide(vp);
  583.             scroll_port(vp, i);
  584.             cursor_print(vp);
  585.             retval = 0;
  586.             break;
  587.         case FB_VIEWPORT_SWITCH:
  588.             i = IPC_GET_ARG1(call);
  589.             if (i < 0 || i >= MAX_VIEWPORTS) {
  590.                 retval = EINVAL;
  591.                 break;
  592.             }
  593.             if (! viewports[i].initialized ) {
  594.                 retval = EADDRNOTAVAIL;
  595.                 break;
  596.             }
  597.             cursor_hide(vp);
  598.             vp = i;
  599.             vport = &viewports[vp];
  600.             cursor_print(vp);
  601.             retval = 0;
  602.             break;
  603.         case FB_VIEWPORT_CREATE:
  604.             retval = viewport_create(IPC_GET_ARG1(call) >> 16,
  605.                          IPC_GET_ARG1(call) & 0xffff,
  606.                          IPC_GET_ARG2(call) >> 16,
  607.                          IPC_GET_ARG2(call) & 0xffff);
  608.             break;
  609.         case FB_VIEWPORT_DELETE:
  610.             i = IPC_GET_ARG1(call);
  611.             if (i < 0 || i >= MAX_VIEWPORTS) {
  612.                 retval = EINVAL;
  613.                 break;
  614.             }
  615.             if (! viewports[i].initialized ) {
  616.                 retval = EADDRNOTAVAIL;
  617.                 break;
  618.             }
  619.             viewports[i].initialized = 0;
  620.             retval = 0;
  621.             break;
  622.         case FB_SET_STYLE:
  623.             vport->fgcolor = IPC_GET_ARG1(call);
  624.             vport->bgcolor = IPC_GET_ARG2(call);
  625.             retval = 0;
  626.             break;
  627.         case FB_GET_RESOLUTION:
  628.             ipc_answer_fast(callid, 0, screen.xres,screen.yres);
  629.             continue;
  630.         default:
  631.             retval = ENOENT;
  632.         }
  633.         ipc_answer_fast(callid,retval,0,0);
  634.     }
  635. }
  636.  
  637. /** Initialization of framebuffer */
  638. int fb_init(void)
  639. {
  640.     void *fb_ph_addr;
  641.     unsigned int fb_width;
  642.     unsigned int fb_height;
  643.     unsigned int fb_bpp;
  644.     unsigned int fb_scanline;
  645.     void *fb_addr;
  646.     size_t asz;
  647.  
  648.     async_set_client_connection(fb_client_connection);
  649.  
  650.     fb_ph_addr=(void *)sysinfo_value("fb.address.physical");
  651.     fb_width=sysinfo_value("fb.width");
  652.     fb_height=sysinfo_value("fb.height");
  653.     fb_bpp=sysinfo_value("fb.bpp");
  654.     fb_scanline=sysinfo_value("fb.scanline");
  655.  
  656.     asz = fb_scanline*fb_height;
  657.     fb_addr = as_get_mappable_page(asz);
  658.    
  659.     map_physmem(fb_ph_addr, fb_addr, ALIGN_UP(asz,PAGE_SIZE) >>PAGE_WIDTH,
  660.             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
  661.    
  662.     screen_init(fb_addr, fb_width, fb_height, fb_bpp, fb_scanline);
  663.  
  664.     return 0;
  665. }
  666.  
  667.