Subversion Repositories HelenOS-historic

Rev

Rev 1565 | Rev 1640 | 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. #include <stdlib.h>
  29. #include <unistd.h>
  30. #include <align.h>
  31. #include <async.h>
  32. #include <ipc/ipc.h>
  33. #include <errno.h>
  34. #include <stdio.h>
  35. #include <ddi.h>
  36. #include <sysinfo.h>
  37. #include <as.h>
  38. #include <ipc/fb.h>
  39. #include <ipc/ipc.h>
  40. #include <ipc/ns.h>
  41. #include <ipc/services.h>
  42.  
  43. #include "ega.h"
  44. #include "../console/screenbuffer.h"
  45. #include "main.h"
  46.  
  47. #define MAX_SAVED_SCREENS 256
  48. typedef struct saved_screen {
  49.     short *data;
  50. } saved_screen;
  51.  
  52. saved_screen saved_screens[MAX_SAVED_SCREENS];
  53.  
  54.  
  55. #define EGA_IO_ADDRESS 0x3d4
  56. #define EGA_IO_SIZE 2
  57.  
  58. typedef unsigned char u8;
  59. typedef unsigned short u16;
  60. typedef unsigned int u32;
  61.  
  62.  
  63. /* Allow only 1 connection */
  64. static int client_connected = 0;
  65.  
  66. static unsigned int scr_width;
  67. static unsigned int scr_height;
  68. static char *scr_addr;
  69.  
  70. static unsigned int style = 0x1e;
  71.  
  72. static inline void outb(u16 port, u8 b)
  73. {
  74.     asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port));
  75. }
  76.  
  77. static inline void outw(u16 port, u16 w)
  78. {
  79.     asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port));
  80. }
  81.  
  82. static inline void outl(u16 port, u32 l)
  83. {
  84.     asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port));
  85. }
  86.  
  87. static inline u8 inb(u16 port)
  88. {
  89.     u8 val;
  90.  
  91.     asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port));
  92.     return val;
  93. }
  94.  
  95. static inline u16 inw(u16 port)
  96. {
  97.     u16 val;
  98.  
  99.     asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port));
  100.     return val;
  101. }
  102.  
  103. static inline u32 inl(u16 port)
  104. {
  105.     u32 val;
  106.  
  107.     asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port));
  108.     return val;
  109. }
  110.  
  111.  
  112.  
  113.  
  114. static void clrscr(void)
  115. {
  116.     int i;
  117.    
  118.     for (i=0; i < scr_width*scr_height; i++) {
  119.         scr_addr[i*2] = ' ';
  120.         scr_addr[i*2+1] = style;
  121.     }
  122. }
  123.  
  124. static void cursor_goto(unsigned int row, unsigned int col)
  125. {
  126.     int ega_cursor;
  127.  
  128.     ega_cursor=col+scr_width*row;
  129.    
  130.     outb(EGA_IO_ADDRESS    , 0xe);
  131.     outb(EGA_IO_ADDRESS + 1, (ega_cursor >>8) & 0xff);
  132.     outb(EGA_IO_ADDRESS    , 0xf);
  133.     outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff);
  134. }
  135.  
  136. static void cursor_disable(void)
  137. {
  138.     u8 stat;
  139.     outb(EGA_IO_ADDRESS , 0xa);
  140.     stat=inb(EGA_IO_ADDRESS + 1);
  141.     outb(EGA_IO_ADDRESS , 0xa);
  142.     outb(EGA_IO_ADDRESS +1 ,stat | (1<<5) );
  143. }
  144.  
  145. static void cursor_enable(void)
  146. {
  147.     u8 stat;
  148.     outb(EGA_IO_ADDRESS , 0xa);
  149.     stat=inb(EGA_IO_ADDRESS + 1);
  150.     outb(EGA_IO_ADDRESS , 0xa);
  151.     outb(EGA_IO_ADDRESS +1 ,stat & (~(1<<5)) );
  152. }
  153.  
  154. static void scroll(int rows)
  155. {
  156.     int i;
  157.     if (rows > 0) {
  158.         memcpy (scr_addr,((char *)scr_addr) + rows * scr_width * 2, scr_width * scr_height * 2 - rows * scr_width * 2);
  159.         for (i = 0; i < rows * scr_width ; i ++)
  160.             (((short *)scr_addr) + scr_width * scr_height - rows * scr_width) [i] = ((style << 8) + ' ');
  161.     } else if (rows < 0) {
  162.  
  163.         memcpy (((char *)scr_addr) - rows * scr_width * 2 ,scr_addr ,scr_width * scr_height * 2 + rows * scr_width * 2);
  164.         for (i = 0; i < - rows * scr_width ; i++)
  165.             ((short *)scr_addr) [i] = ((style << 8 ) + ' ');
  166.     }
  167. }
  168.  
  169. static void printchar(char c, unsigned int row, unsigned int col)
  170. {
  171.     scr_addr[(row*scr_width + col)*2] = c;
  172.     scr_addr[(row*scr_width + col)*2+1] = style;
  173.    
  174.     cursor_goto(row,col+1);
  175. }
  176.  
  177. static void draw_text_data(keyfield_t *data)
  178. {
  179.     int i;
  180.  
  181.     for (i=0; i < scr_width*scr_height; i++) {
  182.         scr_addr[i*2] = data[i].character;
  183.         if (data[i].style.fg_color > data[i].style.bg_color)
  184.             scr_addr[i*2+1] = 0x1e;
  185.         else
  186.             scr_addr[i*2+1] = 0xe1;
  187.     }
  188. }
  189.  
  190. static int save_screen(void)
  191. {
  192.     int i;
  193.     short *mem;
  194.     for (i=0 ;( i < MAX_SAVED_SCREENS ) && (saved_screens[i].data); i++);
  195.     if (i == MAX_SAVED_SCREENS)
  196.         return EINVAL;
  197.     if (!(saved_screens[i].data=malloc( 2 * scr_width*scr_height )))
  198.         return ENOMEM;
  199.     memcpy (saved_screens[i].data ,scr_addr ,2 * scr_width * scr_height)
  200.         ;
  201.     return i;
  202. }
  203.  
  204. static int print_screen(int i)
  205. {
  206.     if (saved_screens[i].data)
  207.             memcpy (scr_addr,saved_screens[i].data, 2 * scr_width * scr_height);
  208.     else return EINVAL;
  209.     return i;
  210. }
  211.  
  212.  
  213. static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  214. {
  215.     int retval;
  216.     ipc_callid_t callid;
  217.     ipc_call_t call;
  218.     char c;
  219.     unsigned int row, col;
  220.     int bgcolor,fgcolor;
  221.     keyfield_t *interbuf = NULL;
  222.     size_t intersize = 0;
  223.     int i;
  224.  
  225.     if (client_connected) {
  226.         ipc_answer_fast(iid, ELIMIT, 0,0);
  227.         return;
  228.     }
  229.     client_connected = 1;
  230.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  231.  
  232.     while (1) {
  233.         callid = async_get_call(&call);
  234.         switch (IPC_GET_METHOD(call)) {
  235.         case IPC_M_PHONE_HUNGUP:
  236.             client_connected = 0;
  237.             ipc_answer_fast(callid,0,0,0);
  238.             return; /* Exit thread */
  239.         case IPC_M_AS_AREA_SEND:
  240.             /* We accept one area for data interchange */
  241.             intersize = IPC_GET_ARG2(call);
  242.             if (intersize >= scr_width*scr_height*sizeof(*interbuf)) {
  243.                 receive_comm_area(callid,&call,(void **)&interbuf);
  244.                 continue;
  245.             }
  246.             retval = EINVAL;
  247.             break;
  248.         case FB_DRAW_TEXT_DATA:
  249.             if (!interbuf) {
  250.                 retval = EINVAL;
  251.                 break;
  252.             }
  253.             draw_text_data(interbuf);
  254.             retval = 0;
  255.             break;
  256.         case FB_GET_CSIZE:
  257.             ipc_answer_fast(callid, 0, scr_height, scr_width);
  258.             continue;
  259.         case FB_CLEAR:
  260.             clrscr();
  261.             retval = 0;
  262.             break;
  263.         case FB_PUTCHAR:
  264.             c = IPC_GET_ARG1(call);
  265.             row = IPC_GET_ARG2(call);
  266.             col = IPC_GET_ARG3(call);
  267.             if (col >= scr_width || row >= scr_height) {
  268.                 retval = EINVAL;
  269.                 break;
  270.             }
  271.             printchar(c,row,col);
  272.             retval = 0;
  273.             break;
  274.         case FB_CURSOR_GOTO:
  275.             row = IPC_GET_ARG1(call);
  276.             col = IPC_GET_ARG2(call);
  277.             if (row >= scr_height || col >= scr_width) {
  278.                 retval = EINVAL;
  279.                 break;
  280.             }
  281.             cursor_goto(row,col);
  282.             retval = 0;
  283.             break;
  284.         case FB_SCROLL:
  285.             i = IPC_GET_ARG1(call);
  286.             if (i > scr_height || i < (- (int)scr_height)) {
  287.                 retval = EINVAL;
  288.                 break;
  289.             }
  290.             scroll(i);
  291.             retval = 0;
  292.             break;
  293.         case FB_CURSOR_VISIBILITY:
  294.             if(IPC_GET_ARG1(call))
  295.                 cursor_enable();
  296.             else
  297.                 cursor_disable();
  298.             retval = 0;
  299.             break;
  300.         case FB_SET_STYLE:
  301.             fgcolor = IPC_GET_ARG1(call);
  302.             bgcolor = IPC_GET_ARG2(call);
  303.             if (fgcolor > bgcolor)
  304.                 style = 0x1e;
  305.             else
  306.                 style = 0xe1;
  307.             break;
  308.         case FB_VP_DRAW_PIXMAP:
  309.             i = IPC_GET_ARG2(call);
  310.             retval = print_screen(i);
  311.             break;
  312.         case FB_VP2PIXMAP:
  313.             retval = save_screen();
  314.             break;
  315.         case FB_DROP_PIXMAP:
  316.             i = IPC_GET_ARG1(call);
  317.             if (i >= MAX_SAVED_SCREENS) {
  318.                 retval = EINVAL;
  319.                 break;
  320.             }
  321.             if (saved_screens[i].data) {
  322.                 free(saved_screens[i].data);
  323.                 saved_screens[i].data = NULL;
  324.             }
  325.             break;
  326.  
  327.         default:
  328.             retval = ENOENT;
  329.         }
  330.         ipc_answer_fast(callid,retval,0,0);
  331.     }
  332. }
  333.  
  334. int ega_init(void)
  335. {
  336.     void *ega_ph_addr;
  337.     size_t sz;
  338.  
  339.  
  340.     ega_ph_addr=(void *)sysinfo_value("fb.address.physical");
  341.     scr_width=sysinfo_value("fb.width");
  342.     scr_height=sysinfo_value("fb.height");
  343.     iospace_enable(task_get_id(),(void *)EGA_IO_ADDRESS,2);
  344.  
  345.     sz = scr_width*scr_height*2;
  346.     scr_addr = as_get_mappable_page(sz);
  347.  
  348.     map_physmem(ega_ph_addr, scr_addr, ALIGN_UP(sz,PAGE_SIZE)>>PAGE_WIDTH,
  349.             AS_AREA_READ | AS_AREA_WRITE);
  350.  
  351.     async_set_client_connection(ega_client_connection);
  352.  
  353.     return 0;
  354. }
  355.  
  356.