Subversion Repositories HelenOS-historic

Rev

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