Subversion Repositories HelenOS-historic

Rev

Rev 1551 | Rev 1564 | 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) return EINVAL;
  196.     if(!(saved_screens[i].data=malloc(2*scr_width*scr_height))) return ENOMEM;
  197.     memcpy(saved_screens[i].data,scr_addr,2*scr_width*scr_height);
  198.     return i;
  199. }
  200.  
  201. static int print_screen(int i)
  202. {
  203.     if(saved_screens[i].data)
  204.             memcpy(scr_addr,saved_screens[i].data,2*scr_width*scr_height);
  205.     else return EINVAL;
  206.     return i;
  207. }
  208.  
  209.  
  210. static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  211. {
  212.     int retval;
  213.     ipc_callid_t callid;
  214.     ipc_call_t call;
  215.     char c;
  216.     unsigned int row, col;
  217.     int bgcolor,fgcolor;
  218.     keyfield_t *interbuf = NULL;
  219.     size_t intersize = 0;
  220.     int i;
  221.  
  222.     if (client_connected) {
  223.         ipc_answer_fast(iid, ELIMIT, 0,0);
  224.         return;
  225.     }
  226.     client_connected = 1;
  227.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  228.  
  229.     while (1) {
  230.         callid = async_get_call(&call);
  231.         switch (IPC_GET_METHOD(call)) {
  232.         case IPC_M_PHONE_HUNGUP:
  233.             client_connected = 0;
  234.             ipc_answer_fast(callid,0,0,0);
  235.             return; /* Exit thread */
  236.         case IPC_M_AS_AREA_SEND:
  237.             /* We accept one area for data interchange */
  238.             intersize = IPC_GET_ARG2(call);
  239.             if (intersize >= scr_width*scr_height*sizeof(*interbuf)) {
  240.                 receive_comm_area(callid,&call,(void **)&interbuf);
  241.                 continue;
  242.             }
  243.             retval = EINVAL;
  244.             break;
  245.         case FB_DRAW_TEXT_DATA:
  246.             if (!interbuf) {
  247.                 retval = EINVAL;
  248.                 break;
  249.             }
  250.             draw_text_data(interbuf);
  251.             retval = 0;
  252.             break;
  253.         case FB_GET_CSIZE:
  254.             ipc_answer_fast(callid, 0, scr_height, scr_width);
  255.             continue;
  256.         case FB_CLEAR:
  257.             clrscr();
  258.             retval = 0;
  259.             break;
  260.         case FB_PUTCHAR:
  261.             c = IPC_GET_ARG1(call);
  262.             row = IPC_GET_ARG2(call);
  263.             col = IPC_GET_ARG3(call);
  264.             if (col >= scr_width || row >= scr_height) {
  265.                 retval = EINVAL;
  266.                 break;
  267.             }
  268.             printchar(c,row,col);
  269.             retval = 0;
  270.             break;
  271.         case FB_CURSOR_GOTO:
  272.             row = IPC_GET_ARG1(call);
  273.             col = IPC_GET_ARG2(call);
  274.             if (row >= scr_height || col >= scr_width) {
  275.                 retval = EINVAL;
  276.                 break;
  277.             }
  278.             cursor_goto(row,col);
  279.             retval = 0;
  280.             break;
  281.         case FB_SCROLL:
  282.             i = IPC_GET_ARG1(call);
  283.             if (i > scr_height || i < (- (int)scr_height)) {
  284.                 retval = EINVAL;
  285.                 break;
  286.             }
  287.             scroll(i);
  288.             retval = 0;
  289.             break;
  290.         case FB_CURSOR_VISIBILITY:
  291.             if(IPC_GET_ARG1(call))
  292.                 cursor_enable();
  293.             else
  294.                 cursor_disable();
  295.             retval = 0;
  296.             break;
  297.         case FB_SET_STYLE:
  298.             fgcolor = IPC_GET_ARG1(call);
  299.             bgcolor = IPC_GET_ARG2(call);
  300.             if (fgcolor > bgcolor)
  301.                 style = 0x1e;
  302.             else
  303.                 style = 0xe1;
  304.  
  305.         case FB_VP_DRAW_PIXMAP:
  306.             i = IPC_GET_ARG2(call);
  307.             retval = print_screen(i);
  308.             break;
  309.         case FB_VP2PIXMAP:
  310.             retval = save_screen();
  311.             break;
  312.         case FB_DROP_PIXMAP:
  313.             i = IPC_GET_ARG1(call);
  314.             if (i >= MAX_SAVED_SCREENS) {
  315.                 retval = EINVAL;
  316.                 break;
  317.             }
  318.             if (saved_screens[i].data) {
  319.                 free(saved_screens[i].data);
  320.                 saved_screens[i].data = NULL;
  321.             }
  322.             break;
  323.  
  324.         default:
  325.             retval = ENOENT;
  326.         }
  327.         ipc_answer_fast(callid,retval,0,0);
  328.     }
  329. }
  330.  
  331. int ega_init(void)
  332. {
  333.     void *ega_ph_addr;
  334.     size_t sz;
  335.  
  336.  
  337.     ega_ph_addr=(void *)sysinfo_value("fb.address.physical");
  338.     scr_width=sysinfo_value("fb.width");
  339.     scr_height=sysinfo_value("fb.height");
  340.     iospace_enable(task_get_id(),(void *)EGA_IO_ADDRESS,2);
  341.  
  342.     sz = scr_width*scr_height*2;
  343.     scr_addr = as_get_mappable_page(sz);
  344.  
  345.     map_physmem(ega_ph_addr, scr_addr, ALIGN_UP(sz,PAGE_SIZE)>>PAGE_WIDTH,
  346.             AS_AREA_READ | AS_AREA_WRITE);
  347.  
  348.     async_set_client_connection(ega_client_connection);
  349.  
  350.     return 0;
  351. }
  352.  
  353.