Subversion Repositories HelenOS-historic

Rev

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

  1. /*
  2.  * Copyright (C) 2006 Ondrej Palkovsky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @defgroup egafb EGA framebuffer
  30.  * @brief   HelenOS EGA framebuffer.
  31.  * @ingroup fbs
  32.  * @{
  33.  */
  34. /** @file
  35.  */
  36.  
  37.  
  38. #include <stdlib.h>
  39. #include <unistd.h>
  40. #include <align.h>
  41. #include <async.h>
  42. #include <ipc/ipc.h>
  43. #include <errno.h>
  44. #include <stdio.h>
  45. #include <ddi.h>
  46. #include <sysinfo.h>
  47. #include <as.h>
  48. #include <ipc/fb.h>
  49. #include <ipc/ipc.h>
  50. #include <ipc/ns.h>
  51. #include <ipc/services.h>
  52.  
  53. #include "ega.h"
  54. #include "../console/screenbuffer.h"
  55. #include "main.h"
  56.  
  57. #define MAX_SAVED_SCREENS 256
  58. typedef struct saved_screen {
  59.     short *data;
  60. } saved_screen;
  61.  
  62. saved_screen saved_screens[MAX_SAVED_SCREENS];
  63.  
  64.  
  65. #define EGA_IO_ADDRESS 0x3d4
  66. #define EGA_IO_SIZE 2
  67.  
  68. #define NORMAL_COLOR       0x0f
  69. #define INVERTED_COLOR     0xf0
  70.  
  71. #define EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR)
  72.  
  73. typedef unsigned char u8;
  74. typedef unsigned short u16;
  75. typedef unsigned int u32;
  76.  
  77.  
  78. /* Allow only 1 connection */
  79. static int client_connected = 0;
  80.  
  81. static unsigned int scr_width;
  82. static unsigned int scr_height;
  83. static char *scr_addr;
  84.  
  85. static unsigned int style = NORMAL_COLOR;
  86.  
  87. static inline void outb(u16 port, u8 b)
  88. {
  89.     asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port));
  90. }
  91.  
  92. static inline void outw(u16 port, u16 w)
  93. {
  94.     asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port));
  95. }
  96.  
  97. static inline void outl(u16 port, u32 l)
  98. {
  99.     asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port));
  100. }
  101.  
  102. static inline u8 inb(u16 port)
  103. {
  104.     u8 val;
  105.  
  106.     asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port));
  107.     return val;
  108. }
  109.  
  110. static inline u16 inw(u16 port)
  111. {
  112.     u16 val;
  113.  
  114.     asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port));
  115.     return val;
  116. }
  117.  
  118. static inline u32 inl(u16 port)
  119. {
  120.     u32 val;
  121.  
  122.     asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port));
  123.     return val;
  124. }
  125.  
  126.  
  127.  
  128.  
  129. static void clrscr(void)
  130. {
  131.     int i;
  132.    
  133.     for (i=0; i < scr_width*scr_height; i++) {
  134.         scr_addr[i*2] = ' ';
  135.         scr_addr[i*2+1] = style;
  136.     }
  137. }
  138.  
  139. static void cursor_goto(unsigned int row, unsigned int col)
  140. {
  141.     int ega_cursor;
  142.  
  143.     ega_cursor=col+scr_width*row;
  144.    
  145.     outb(EGA_IO_ADDRESS    , 0xe);
  146.     outb(EGA_IO_ADDRESS + 1, (ega_cursor >>8) & 0xff);
  147.     outb(EGA_IO_ADDRESS    , 0xf);
  148.     outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff);
  149. }
  150.  
  151. static void cursor_disable(void)
  152. {
  153.     u8 stat;
  154.     outb(EGA_IO_ADDRESS , 0xa);
  155.     stat=inb(EGA_IO_ADDRESS + 1);
  156.     outb(EGA_IO_ADDRESS , 0xa);
  157.     outb(EGA_IO_ADDRESS +1 ,stat | (1<<5) );
  158. }
  159.  
  160. static void cursor_enable(void)
  161. {
  162.     u8 stat;
  163.     outb(EGA_IO_ADDRESS , 0xa);
  164.     stat=inb(EGA_IO_ADDRESS + 1);
  165.     outb(EGA_IO_ADDRESS , 0xa);
  166.     outb(EGA_IO_ADDRESS +1 ,stat & (~(1<<5)) );
  167. }
  168.  
  169. static void scroll(int rows)
  170. {
  171.     int i;
  172.     if (rows > 0) {
  173.         memcpy (scr_addr,((char *)scr_addr) + rows * scr_width * 2, scr_width * scr_height * 2 - rows * scr_width * 2);
  174.         for (i = 0; i < rows * scr_width ; i ++)
  175.             (((short *)scr_addr) + scr_width * scr_height - rows * scr_width) [i] = ((style << 8) + ' ');
  176.     } else if (rows < 0) {
  177.  
  178.         memcpy (((char *)scr_addr) - rows * scr_width * 2 ,scr_addr ,scr_width * scr_height * 2 + rows * scr_width * 2);
  179.         for (i = 0; i < - rows * scr_width ; i++)
  180.             ((short *)scr_addr) [i] = ((style << 8 ) + ' ');
  181.     }
  182. }
  183.  
  184. static void printchar(char c, unsigned int row, unsigned int col)
  185. {
  186.     scr_addr[(row*scr_width + col)*2] = c;
  187.     scr_addr[(row*scr_width + col)*2+1] = style;
  188.    
  189.     cursor_goto(row,col+1);
  190. }
  191.  
  192. static void draw_text_data(keyfield_t *data)
  193. {
  194.     int i;
  195.  
  196.     for (i=0; i < scr_width*scr_height; i++) {
  197.         scr_addr[i*2] = data[i].character;
  198.         scr_addr[i*2+1] = EGA_STYLE(data[i].style.fg_color, data[i].style.bg_color);
  199.     }
  200. }
  201.  
  202. static int save_screen(void)
  203. {
  204.     int i;
  205.     short *mem;
  206.     for (i=0 ;( i < MAX_SAVED_SCREENS ) && (saved_screens[i].data); i++);
  207.     if (i == MAX_SAVED_SCREENS)
  208.         return EINVAL;
  209.     if (!(saved_screens[i].data=malloc( 2 * scr_width*scr_height )))
  210.         return ENOMEM;
  211.     memcpy (saved_screens[i].data ,scr_addr ,2 * scr_width * scr_height)
  212.         ;
  213.     return i;
  214. }
  215.  
  216. static int print_screen(int i)
  217. {
  218.     if (saved_screens[i].data)
  219.             memcpy (scr_addr,saved_screens[i].data, 2 * scr_width * scr_height);
  220.     else return EINVAL;
  221.     return i;
  222. }
  223.  
  224.  
  225. static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  226. {
  227.     int retval;
  228.     ipc_callid_t callid;
  229.     ipc_call_t call;
  230.     char c;
  231.     unsigned int row, col;
  232.     int bgcolor,fgcolor;
  233.     keyfield_t *interbuf = NULL;
  234.     size_t intersize = 0;
  235.     int i;
  236.  
  237.     if (client_connected) {
  238.         ipc_answer_fast(iid, ELIMIT, 0,0);
  239.         return;
  240.     }
  241.     client_connected = 1;
  242.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  243.  
  244.     while (1) {
  245.         callid = async_get_call(&call);
  246.         switch (IPC_GET_METHOD(call)) {
  247.         case IPC_M_PHONE_HUNGUP:
  248.             client_connected = 0;
  249.             ipc_answer_fast(callid,0,0,0);
  250.             return; /* Exit thread */
  251.         case IPC_M_AS_AREA_SEND:
  252.             /* We accept one area for data interchange */
  253.             intersize = IPC_GET_ARG2(call);
  254.             if (intersize >= scr_width*scr_height*sizeof(*interbuf)) {
  255.                 receive_comm_area(callid,&call,(void **)&interbuf);
  256.                 continue;
  257.             }
  258.             retval = EINVAL;
  259.             break;
  260.         case FB_DRAW_TEXT_DATA:
  261.             if (!interbuf) {
  262.                 retval = EINVAL;
  263.                 break;
  264.             }
  265.             draw_text_data(interbuf);
  266.             retval = 0;
  267.             break;
  268.         case FB_GET_CSIZE:
  269.             ipc_answer_fast(callid, 0, scr_height, scr_width);
  270.             continue;
  271.         case FB_CLEAR:
  272.             clrscr();
  273.             retval = 0;
  274.             break;
  275.         case FB_PUTCHAR:
  276.             c = IPC_GET_ARG1(call);
  277.             row = IPC_GET_ARG2(call);
  278.             col = IPC_GET_ARG3(call);
  279.             if (col >= scr_width || row >= scr_height) {
  280.                 retval = EINVAL;
  281.                 break;
  282.             }
  283.             printchar(c,row,col);
  284.             retval = 0;
  285.             break;
  286.         case FB_CURSOR_GOTO:
  287.             row = IPC_GET_ARG1(call);
  288.             col = IPC_GET_ARG2(call);
  289.             if (row >= scr_height || col >= scr_width) {
  290.                 retval = EINVAL;
  291.                 break;
  292.             }
  293.             cursor_goto(row,col);
  294.             retval = 0;
  295.             break;
  296.         case FB_SCROLL:
  297.             i = IPC_GET_ARG1(call);
  298.             if (i > scr_height || i < (- (int)scr_height)) {
  299.                 retval = EINVAL;
  300.                 break;
  301.             }
  302.             scroll(i);
  303.             retval = 0;
  304.             break;
  305.         case FB_CURSOR_VISIBILITY:
  306.             if(IPC_GET_ARG1(call))
  307.                 cursor_enable();
  308.             else
  309.                 cursor_disable();
  310.             retval = 0;
  311.             break;
  312.         case FB_SET_STYLE:
  313.             fgcolor = IPC_GET_ARG1(call);
  314.             bgcolor = IPC_GET_ARG2(call);
  315.             style = EGA_STYLE(fgcolor, bgcolor);
  316.             break;
  317.         case FB_VP_DRAW_PIXMAP:
  318.             i = IPC_GET_ARG2(call);
  319.             retval = print_screen(i);
  320.             break;
  321.         case FB_VP2PIXMAP:
  322.             retval = save_screen();
  323.             break;
  324.         case FB_DROP_PIXMAP:
  325.             i = IPC_GET_ARG1(call);
  326.             if (i >= MAX_SAVED_SCREENS) {
  327.                 retval = EINVAL;
  328.                 break;
  329.             }
  330.             if (saved_screens[i].data) {
  331.                 free(saved_screens[i].data);
  332.                 saved_screens[i].data = NULL;
  333.             }
  334.             break;
  335.  
  336.         default:
  337.             retval = ENOENT;
  338.         }
  339.         ipc_answer_fast(callid,retval,0,0);
  340.     }
  341. }
  342.  
  343. int ega_init(void)
  344. {
  345.     void *ega_ph_addr;
  346.     size_t sz;
  347.  
  348.  
  349.     ega_ph_addr=(void *)sysinfo_value("fb.address.physical");
  350.     scr_width=sysinfo_value("fb.width");
  351.     scr_height=sysinfo_value("fb.height");
  352.     iospace_enable(task_get_id(),(void *)EGA_IO_ADDRESS,2);
  353.  
  354.     sz = scr_width*scr_height*2;
  355.     scr_addr = as_get_mappable_page(sz);
  356.  
  357.     map_physmem(ega_ph_addr, scr_addr, ALIGN_UP(sz,PAGE_SIZE)>>PAGE_WIDTH,
  358.             AS_AREA_READ | AS_AREA_WRITE);
  359.  
  360.     async_set_client_connection(ega_client_connection);
  361.  
  362.     return 0;
  363. }
  364.  
  365.  
  366. /**
  367.  * @}
  368.  */
  369.