Subversion Repositories HelenOS

Rev

Rev 1547 | Rev 1562 | 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. #include <align.h>
  30. #include <async.h>
  31. #include <ipc/ipc.h>
  32. #include <errno.h>
  33. #include <stdio.h>
  34. #include <ddi.h>
  35. #include <sysinfo.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.  
  42. #include "ega.h"
  43. #include "../console/screenbuffer.h"
  44. #include "main.h"
  45.  
  46.  
  47. #define EGA_IO_ADDRESS 0x3d4
  48. #define EGA_IO_SIZE 2
  49.  
  50. typedef unsigned char u8;
  51. typedef unsigned short u16;
  52. typedef unsigned int u32;
  53.  
  54.  
  55. /* Allow only 1 connection */
  56. static int client_connected = 0;
  57.  
  58. static unsigned int scr_width;
  59. static unsigned int scr_height;
  60. static char *scr_addr;
  61.  
  62. static unsigned int style = 0x0f;
  63.  
  64. static inline void outb(u16 port, u8 b)
  65. {
  66.     asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port));
  67. }
  68.  
  69. static inline void outw(u16 port, u16 w)
  70. {
  71.     asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port));
  72. }
  73.  
  74. static inline void outl(u16 port, u32 l)
  75. {
  76.     asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port));
  77. }
  78.  
  79. static inline u8 inb(u16 port)
  80. {
  81.     u8 val;
  82.  
  83.     asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port));
  84.     return val;
  85. }
  86.  
  87. static inline u16 inw(u16 port)
  88. {
  89.     u16 val;
  90.  
  91.     asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port));
  92.     return val;
  93. }
  94.  
  95. static inline u32 inl(u16 port)
  96. {
  97.     u32 val;
  98.  
  99.     asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port));
  100.     return val;
  101. }
  102.  
  103.  
  104.  
  105.  
  106. static void clrscr(void)
  107. {
  108.     int i;
  109.    
  110.     for (i=0; i < scr_width*scr_height; i++) {
  111.         scr_addr[i*2] = ' ';
  112.         scr_addr[i*2+1] = style;
  113.     }
  114. }
  115.  
  116. void cursor_goto(unsigned int row, unsigned int col)
  117. {
  118.     int ega_cursor;
  119.  
  120.     ega_cursor=col+scr_width*row;
  121.    
  122.     outb(EGA_IO_ADDRESS    , 0xe);
  123.     outb(EGA_IO_ADDRESS + 1, (ega_cursor >>8) & 0xff);
  124.     outb(EGA_IO_ADDRESS    , 0xf);
  125.     outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff);
  126. }
  127.  
  128. void cursor_disable(void)
  129. {
  130.     u8 stat;
  131.     outb(EGA_IO_ADDRESS , 0xa);
  132.     stat=inb(EGA_IO_ADDRESS + 1);
  133.     outb(EGA_IO_ADDRESS , 0xa);
  134.     outb(EGA_IO_ADDRESS +1 ,stat | (1<<5) );
  135. }
  136.  
  137. void cursor_enable(void)
  138. {
  139.     u8 stat;
  140.     outb(EGA_IO_ADDRESS , 0xa);
  141.     stat=inb(EGA_IO_ADDRESS + 1);
  142.     outb(EGA_IO_ADDRESS , 0xa);
  143.     outb(EGA_IO_ADDRESS +1 ,stat & (~(1<<5)) );
  144. }
  145.  
  146. static void printchar(char c, unsigned int row, unsigned int col)
  147. {
  148.     scr_addr[(row*scr_width + col)*2] = c;
  149.     scr_addr[(row*scr_width + col)*2+1] = style;
  150.    
  151.     cursor_goto(row,col+1);
  152. }
  153.  
  154. static void draw_text_data(keyfield_t *data)
  155. {
  156.     int i;
  157.  
  158.     for (i=0; i < scr_width*scr_height; i++) {
  159.         scr_addr[i*2] = data[i].character;
  160.         if (data[i].style.fg_color > data[i].style.bg_color)
  161.             scr_addr[i*2+1] = 0x0f;
  162.         else
  163.             scr_addr[i*2+1] = 0xf0;
  164.     }
  165. }
  166.  
  167. static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
  168. {
  169.     int retval;
  170.     ipc_callid_t callid;
  171.     ipc_call_t call;
  172.     char c;
  173.     unsigned int row, col;
  174.     int bgcolor,fgcolor;
  175.     keyfield_t *interbuf = NULL;
  176.     size_t intersize = 0;
  177.  
  178.     if (client_connected) {
  179.         ipc_answer_fast(iid, ELIMIT, 0,0);
  180.         return;
  181.     }
  182.     client_connected = 1;
  183.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  184.  
  185.     while (1) {
  186.         callid = async_get_call(&call);
  187.         switch (IPC_GET_METHOD(call)) {
  188.         case IPC_M_PHONE_HUNGUP:
  189.             client_connected = 0;
  190.             ipc_answer_fast(callid,0,0,0);
  191.             return; /* Exit thread */
  192.         case IPC_M_AS_AREA_SEND:
  193.             /* We accept one area for data interchange */
  194.             intersize = IPC_GET_ARG2(call);
  195.             if (intersize >= scr_width*scr_height*sizeof(*interbuf)) {
  196.                 receive_comm_area(callid,&call,(void **)&interbuf);
  197.                 continue;
  198.             }
  199.             retval = EINVAL;
  200.             break;
  201.         case FB_DRAW_TEXT_DATA:
  202.             if (!interbuf) {
  203.                 retval = EINVAL;
  204.                 break;
  205.             }
  206.             draw_text_data(interbuf);
  207.             retval = 0;
  208.             break;
  209.         case FB_GET_CSIZE:
  210.             ipc_answer_fast(callid, 0, scr_height, scr_width);
  211.             continue;
  212.         case FB_CLEAR:
  213.             clrscr();
  214.             retval = 0;
  215.             break;
  216.         case FB_PUTCHAR:
  217.             c = IPC_GET_ARG1(call);
  218.             row = IPC_GET_ARG2(call);
  219.             col = IPC_GET_ARG3(call);
  220.             if (col >= scr_width || row >= scr_height) {
  221.                 retval = EINVAL;
  222.                 break;
  223.             }
  224.             printchar(c,row,col);
  225.             retval = 0;
  226.             break;
  227.         case FB_CURSOR_GOTO:
  228.             row = IPC_GET_ARG1(call);
  229.             col = IPC_GET_ARG2(call);
  230.             if (row >= scr_height || col >= scr_width) {
  231.                 retval = EINVAL;
  232.                 break;
  233.             }
  234.             cursor_goto(row,col);
  235.             retval = 0;
  236.             break;
  237.         case FB_CURSOR_VISIBILITY:
  238.             if(IPC_GET_ARG1(call))
  239.                 cursor_enable();
  240.             else
  241.                 cursor_disable();
  242.             retval = 0;
  243.             break;
  244.         case FB_SET_STYLE:
  245.             fgcolor = IPC_GET_ARG1(call);
  246.             bgcolor = IPC_GET_ARG2(call);
  247.             if (fgcolor > bgcolor)
  248.                 style = 0x0f;
  249.             else
  250.                 style = 0xf0;
  251.         default:
  252.             retval = ENOENT;
  253.         }
  254.         ipc_answer_fast(callid,retval,0,0);
  255.     }
  256. }
  257.  
  258. int ega_init(void)
  259. {
  260.     void *ega_ph_addr;
  261.     size_t sz;
  262.  
  263.  
  264.     ega_ph_addr=(void *)sysinfo_value("fb.address.physical");
  265.     scr_width=sysinfo_value("fb.width");
  266.     scr_height=sysinfo_value("fb.height");
  267.     iospace_enable(task_get_id(),(void *)EGA_IO_ADDRESS,2);
  268.  
  269.     sz = scr_width*scr_height*2;
  270.     scr_addr = as_get_mappable_page(sz);
  271.  
  272.     map_physmem(ega_ph_addr, scr_addr, ALIGN_UP(sz,PAGE_SIZE)>>PAGE_WIDTH,
  273.             AS_AREA_READ | AS_AREA_WRITE);
  274.  
  275.     async_set_client_connection(ega_client_connection);
  276.  
  277.     clrscr();
  278.  
  279.     return 0;
  280. }
  281.  
  282.