Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/fb/ega.c

    rb3d513f r369a5f8  
    2828
    2929/** @defgroup egafb EGA framebuffer
    30  * @brief       HelenOS EGA framebuffer.
     30 * @brief HelenOS EGA framebuffer.
    3131 * @ingroup fbs
    3232 * @{
    33  */ 
     33 */
    3434/** @file
    3535 */
     
    5252#include <io/style.h>
    5353#include <io/color.h>
     54#include <io/screenbuffer.h>
    5455#include <sys/types.h>
    5556
    5657#include "ega.h"
    57 #include "../console/screenbuffer.h"
    5858#include "main.h"
    5959
    60 #define MAX_SAVED_SCREENS 256
     60#define MAX_SAVED_SCREENS  256
     61
    6162typedef struct saved_screen {
    6263        short *data;
     
    6566saved_screen saved_screens[MAX_SAVED_SCREENS];
    6667
    67 #define EGA_IO_BASE ((ioport8_t *) 0x3d4)
    68 #define EGA_IO_SIZE 2
    69 
    70 int ega_normal_color = 0x0f;
    71 int ega_inverted_color = 0xf0;
    72 
    73 #define NORMAL_COLOR            ega_normal_color
    74 #define INVERTED_COLOR          ega_inverted_color
     68#define EGA_IO_BASE  ((ioport8_t *) 0x3d4)
     69#define EGA_IO_SIZE  2
    7570
    7671/* Allow only 1 connection */
    7772static int client_connected = 0;
    7873
    79 static unsigned int scr_width;
    80 static unsigned int scr_height;
     74static sysarg_t scr_width;
     75static sysarg_t scr_height;
    8176static uint8_t *scr_addr;
    8277
    83 static unsigned int style;
    84 
    85 static unsigned attr_to_ega_style(const attrs_t *a);
    86 static uint8_t ega_glyph(wchar_t ch);
     78static uint8_t style_normal = 0xf0;
     79static uint8_t style_inverted = 0x0f;
     80static uint8_t style;
     81
     82static uint8_t style_to_ega_style(uint8_t style)
     83{
     84        switch (style) {
     85        case STYLE_EMPHASIS:
     86                return (style_normal | 0x04);
     87        case STYLE_SELECTED:
     88                return (style_inverted | 0x40);
     89        case STYLE_INVERTED:
     90                return style_inverted;
     91        }
     92       
     93        return style_normal;
     94}
     95
     96static uint8_t color_to_ega_style(uint8_t fg_color, uint8_t bg_color,
     97    uint8_t attr)
     98{
     99        uint8_t style = (fg_color & 7) | ((bg_color & 7) << 4);
     100       
     101        if (attr & CATTR_BRIGHT)
     102                style |= 0x08;
     103       
     104        return style;
     105}
     106
     107static uint8_t rgb_to_ega_style(uint32_t fg, uint32_t bg)
     108{
     109        return (fg > bg) ? style_inverted : style_normal;
     110}
     111
     112static uint8_t attr_to_ega_style(const attrs_t *attr)
     113{
     114        switch (attr->t) {
     115        case at_style:
     116                return style_to_ega_style(attr->a.s.style);
     117        case at_idx:
     118                return color_to_ega_style(attr->a.i.fg_color,
     119                    attr->a.i.bg_color, attr->a.i.flags);
     120        case at_rgb:
     121                return rgb_to_ega_style(attr->a.r.fg_color, attr->a.r.bg_color);
     122        default:
     123                return style_normal;
     124        }
     125}
     126
     127static uint8_t ega_glyph(wchar_t ch)
     128{
     129        if (ch >= 0 && ch < 128)
     130                return ch;
     131       
     132        return '?';
     133}
    87134
    88135static void clrscr(void)
     
    96143}
    97144
    98 static void cursor_goto(unsigned int col, unsigned int row)
    99 {
    100         int ega_cursor;
    101 
    102         ega_cursor = col + scr_width * row;
     145static void cursor_goto(sysarg_t col, sysarg_t row)
     146{
     147        sysarg_t cursor = col + scr_width * row;
    103148       
    104149        pio_write_8(EGA_IO_BASE, 0xe);
    105         pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff);
     150        pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
    106151        pio_write_8(EGA_IO_BASE, 0xf);
    107         pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff);
     152        pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
    108153}
    109154
    110155static void cursor_disable(void)
    111156{
    112         uint8_t stat;
    113 
    114157        pio_write_8(EGA_IO_BASE, 0xa);
    115         stat = pio_read_8(EGA_IO_BASE + 1);
     158       
     159        uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
     160       
    116161        pio_write_8(EGA_IO_BASE, 0xa);
    117162        pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
     
    120165static void cursor_enable(void)
    121166{
    122         uint8_t stat;
    123 
    124167        pio_write_8(EGA_IO_BASE, 0xa);
    125         stat = pio_read_8(EGA_IO_BASE + 1);
     168       
     169        uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
     170       
    126171        pio_write_8(EGA_IO_BASE, 0xa);
    127172        pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
    128173}
    129174
    130 static void scroll(int rows)
    131 {
    132         unsigned i;
    133 
     175static void scroll(ssize_t rows)
     176{
     177        size_t i;
     178       
    134179        if (rows > 0) {
    135180                memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
     
    142187                    scr_width * scr_height * 2 + rows * scr_width * 2);
    143188                for (i = 0; i < -rows * scr_width; i++)
    144                         ((short *)scr_addr)[i] = ((style << 8 ) + ' ');
    145         }
    146 }
    147 
    148 static void printchar(wchar_t c, unsigned int col, unsigned int row)
     189                        ((short *) scr_addr)[i] = ((style << 8 ) + ' ');
     190        }
     191}
     192
     193static void printchar(wchar_t c, sysarg_t col, sysarg_t row)
    149194{
    150195        scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
     
    158203 * @param vport Viewport id
    159204 * @param data  Text data.
    160  * @param x     Leftmost column of the area.
    161  * @param y     Topmost row of the area.
    162  * @param w     Number of rows.
    163  * @param h     Number of columns.
     205 * @param x     Leftmost column of the area.
     206 * @param y     Topmost row of the area.
     207 * @param w     Number of rows.
     208 * @param h     Number of columns.
     209 *
    164210 */
    165 static void draw_text_data(keyfield_t *data, unsigned int x,
    166     unsigned int y, unsigned int w, unsigned int h)
    167 {
    168         unsigned int i, j;
     211static void draw_text_data(keyfield_t *data, sysarg_t x, sysarg_t y,
     212    sysarg_t w, sysarg_t h)
     213{
     214        sysarg_t i;
     215        sysarg_t j;
    169216        keyfield_t *field;
    170217        uint8_t *dp;
    171 
     218       
    172219        for (j = 0; j < h; j++) {
    173220                for (i = 0; i < w; i++) {
    174221                        field = &data[j * w + i];
    175222                        dp = &scr_addr[2 * ((y + j) * scr_width + (x + i))];
    176 
     223                       
    177224                        dp[0] = ega_glyph(field->character);
    178225                        dp[1] = attr_to_ega_style(&field->attrs);
     
    183230static int save_screen(void)
    184231{
    185         int i;
    186 
    187         for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++)
    188                 ;
    189         if (i == MAX_SAVED_SCREENS)
     232        ipcarg_t i;
     233       
     234        /* Find empty screen */
     235        for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++);
     236       
     237        if (i == MAX_SAVED_SCREENS)
    190238                return EINVAL;
    191         if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
     239       
     240        if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
    192241                return ENOMEM;
     242       
    193243        memcpy(saved_screens[i].data, scr_addr, 2 * scr_width * scr_height);
    194 
    195         return i;
    196 }
    197 
    198 static int print_screen(int i)
    199 {
    200         if (saved_screens[i].data)
     244        return (int) i;
     245}
     246
     247static int print_screen(ipcarg_t i)
     248{
     249        if ((i >= MAX_SAVED_SCREENS) || (saved_screens[i].data))
    201250                memcpy(scr_addr, saved_screens[i].data, 2 * scr_width *
    202251                    scr_height);
    203252        else
    204253                return EINVAL;
    205         return i;
    206 }
    207 
    208 static int style_to_ega_style(int style)
    209 {
    210         unsigned int ega_style;
    211 
    212         switch (style) {
    213         case STYLE_NORMAL:
    214                 ega_style = INVERTED_COLOR;
    215                 break;
    216         case STYLE_EMPHASIS:
    217                 ega_style = INVERTED_COLOR | 4;
    218                 break;
    219         default:
    220                 return INVERTED_COLOR;
    221         }
    222 
    223         return ega_style;
    224 }
    225 
    226 static unsigned int color_to_ega_style(int fg_color, int bg_color, int attr)
    227 {
    228         unsigned int style;
    229 
    230         style = (fg_color & 7) | ((bg_color & 7) << 4);
    231         if (attr & CATTR_BRIGHT)
    232                 style = style | 0x08;
    233 
    234         return style;
    235 }
    236 
    237 static unsigned int rgb_to_ega_style(uint32_t fg, uint32_t bg)
    238 {
    239         return (fg > bg) ? NORMAL_COLOR : INVERTED_COLOR;
    240 }
    241 
    242 static unsigned attr_to_ega_style(const attrs_t *a)
    243 {
    244         switch (a->t) {
    245         case at_style:
    246                 return style_to_ega_style(a->a.s.style);
    247         case at_rgb:
    248                 return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
    249         case at_idx:
    250                 return color_to_ega_style(a->a.i.fg_color,
    251                     a->a.i.bg_color, a->a.i.flags);
    252         default:
    253                 return INVERTED_COLOR;
    254         }
    255 }
    256 
    257 static uint8_t ega_glyph(wchar_t ch)
    258 {
    259         if (ch >= 0 && ch < 128)
    260                 return ch;
    261 
    262         return '?';
     254       
     255        return (int) i;
    263256}
    264257
    265258static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    266259{
    267         int retval;
    268         ipc_callid_t callid;
    269         ipc_call_t call;
    270         wchar_t c;
    271         unsigned int row, col, w, h;
    272         int bg_color, fg_color, attr;
    273         uint32_t bg_rgb, fg_rgb;
     260        size_t intersize = 0;
    274261        keyfield_t *interbuf = NULL;
    275         size_t intersize = 0;
    276         int i;
    277 
     262       
    278263        if (client_connected) {
    279264                ipc_answer_0(iid, ELIMIT);
    280265                return;
    281266        }
     267       
     268        /* Accept connection */
    282269        client_connected = 1;
    283         ipc_answer_0(iid, EOK); /* Accept connection */
    284 
    285         while (1) {
    286                 callid = async_get_call(&call);
    287                 switch (IPC_GET_METHOD(call)) {
     270        ipc_answer_0(iid, EOK);
     271       
     272        while (true) {
     273                ipc_call_t call;
     274                ipc_callid_t callid = async_get_call(&call);
     275               
     276                wchar_t c;
     277               
     278                ipcarg_t col;
     279                ipcarg_t row;
     280                ipcarg_t w;
     281                ipcarg_t h;
     282               
     283                ssize_t rows;
     284               
     285                uint8_t bg_color;
     286                uint8_t fg_color;
     287                uint8_t attr;
     288               
     289                uint32_t fg_rgb;
     290                uint32_t bg_rgb;
     291               
     292                ipcarg_t scr;
     293                int retval;
     294               
     295                switch (IPC_GET_METHOD(call)) {
    288296                case IPC_M_PHONE_HUNGUP:
    289297                        client_connected = 0;
    290298                        ipc_answer_0(callid, EOK);
    291                         return; /* Exit thread */
     299                       
     300                        /* Exit thread */
     301                        return;
    292302                case IPC_M_SHARE_OUT:
    293303                        /* We accept one area for data interchange */
     
    299309                                continue;
    300310                        }
     311                       
    301312                        retval = EINVAL;
    302313                        break;
    303314                case FB_DRAW_TEXT_DATA:
     315                        if (!interbuf) {
     316                                retval = EINVAL;
     317                                break;
     318                        }
     319                       
    304320                        col = IPC_GET_ARG1(call);
    305321                        row = IPC_GET_ARG2(call);
    306322                        w = IPC_GET_ARG3(call);
    307323                        h = IPC_GET_ARG4(call);
    308                         if (!interbuf) {
     324                       
     325                        if ((col + w > scr_width) || (row + h > scr_height)) {
    309326                                retval = EINVAL;
    310327                                break;
    311328                        }
    312                         if (col + w > scr_width || row + h > scr_height) {
    313                                 retval = EINVAL;
    314                                 break;
    315                         }
     329                       
    316330                        draw_text_data(interbuf, col, row, w, h);
    317331                        retval = 0;
     
    331345                        col = IPC_GET_ARG2(call);
    332346                        row = IPC_GET_ARG3(call);
    333                         if (col >= scr_width || row >= scr_height) {
     347                       
     348                        if ((col >= scr_width) || (row >= scr_height)) {
    334349                                retval = EINVAL;
    335350                                break;
    336351                        }
     352                       
    337353                        printchar(c, col, row);
    338354                        retval = 0;
    339355                        break;
    340                 case FB_CURSOR_GOTO:
    341                         col = IPC_GET_ARG1(call);
     356                case FB_CURSOR_GOTO:
     357                        col = IPC_GET_ARG1(call);
    342358                        row = IPC_GET_ARG2(call);
    343                         if (row >= scr_height || col >= scr_width) {
     359                       
     360                        if ((row >= scr_height) || (col >= scr_width)) {
    344361                                retval = EINVAL;
    345362                                break;
    346363                        }
     364                       
    347365                        cursor_goto(col, row);
    348                         retval = 0;
    349                         break;
     366                        retval = 0;
     367                        break;
    350368                case FB_SCROLL:
    351                         i = IPC_GET_ARG1(call);
    352                         if (i > (int) scr_height || i < -((int) scr_height)) {
    353                                 retval = EINVAL;
    354                                 break;
    355                         }
    356                         scroll(i);
     369                        rows = IPC_GET_ARG1(call);
     370                       
     371                        if (rows >= 0) {
     372                                if ((ipcarg_t) rows > scr_height) {
     373                                        retval = EINVAL;
     374                                        break;
     375                                }
     376                        } else {
     377                                if ((ipcarg_t) (-rows) > scr_height) {
     378                                        retval = EINVAL;
     379                                        break;
     380                                }
     381                        }
     382                       
     383                        scroll(rows);
    357384                        retval = 0;
    358385                        break;
     
    362389                        else
    363390                                cursor_disable();
     391                       
    364392                        retval = 0;
    365393                        break;
     
    372400                        bg_color = IPC_GET_ARG2(call);
    373401                        attr = IPC_GET_ARG3(call);
     402                       
    374403                        style = color_to_ega_style(fg_color, bg_color, attr);
    375404                        retval = 0;
     
    378407                        fg_rgb = IPC_GET_ARG1(call);
    379408                        bg_rgb = IPC_GET_ARG2(call);
     409                       
    380410                        style = rgb_to_ega_style(fg_rgb, bg_rgb);
    381411                        retval = 0;
    382412                        break;
    383413                case FB_VP_DRAW_PIXMAP:
    384                         i = IPC_GET_ARG2(call);
    385                         retval = print_screen(i);
     414                        scr = IPC_GET_ARG2(call);
     415                        retval = print_screen(scr);
    386416                        break;
    387417                case FB_VP2PIXMAP:
     
    389419                        break;
    390420                case FB_DROP_PIXMAP:
    391                         i = IPC_GET_ARG1(call);
    392                         if (i >= MAX_SAVED_SCREENS) {
     421                        scr = IPC_GET_ARG1(call);
     422                       
     423                        if (scr >= MAX_SAVED_SCREENS) {
    393424                                retval = EINVAL;
    394425                                break;
    395426                        }
    396                         if (saved_screens[i].data) {
    397                                 free(saved_screens[i].data);
    398                                 saved_screens[i].data = NULL;
    399                         }
     427                       
     428                        if (saved_screens[scr].data) {
     429                                free(saved_screens[scr].data);
     430                                saved_screens[scr].data = NULL;
     431                        }
     432                       
    400433                        retval = 0;
    401434                        break;
     
    413446int ega_init(void)
    414447{
    415         void *ega_ph_addr;
    416         size_t sz;
    417 
    418         ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
    419         scr_width = sysinfo_value("fb.width");
    420         scr_height = sysinfo_value("fb.height");
    421 
    422         if (sysinfo_value("fb.blinking")) {
    423                 ega_normal_color &= 0x77;
    424                 ega_inverted_color &= 0x77;
    425         }
    426 
    427         style = NORMAL_COLOR;
    428 
     448        sysarg_t paddr;
     449        if (sysinfo_get_value("fb.address.physical", &paddr) != EOK)
     450                return -1;
     451       
     452        if (sysinfo_get_value("fb.width", &scr_width) != EOK)
     453                return -1;
     454       
     455        if (sysinfo_get_value("fb.height", &scr_height) != EOK)
     456                return -1;
     457       
     458        sysarg_t blinking;
     459        if (sysinfo_get_value("fb.blinking", &blinking) != EOK)
     460                blinking = false;
     461       
     462        void *ega_ph_addr = (void *) paddr;
     463        if (blinking) {
     464                style_normal &= 0x77;
     465                style_inverted &= 0x77;
     466        }
     467       
     468        style = style_normal;
     469       
    429470        iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2);
    430 
    431         sz = scr_width * scr_height * 2;
     471       
     472        size_t sz = scr_width * scr_height * 2;
    432473        scr_addr = as_get_mappable_page(sz);
    433 
     474       
    434475        if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
    435476            PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
    436477                return -1;
    437 
     478       
    438479        async_set_client_connection(ega_client_connection);
    439 
     480       
    440481        return 0;
    441482}
    442 
    443483
    444484/**
Note: See TracChangeset for help on using the changeset viewer.