Subversion Repositories HelenOS-historic

Rev

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