Ignore:
File:
1 edited

Legend:

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

    r369a5f8 rb3d513f  
    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>
    5554#include <sys/types.h>
    5655
    5756#include "ega.h"
     57#include "../console/screenbuffer.h"
    5858#include "main.h"
    5959
    60 #define MAX_SAVED_SCREENS  256
    61 
     60#define MAX_SAVED_SCREENS 256
    6261typedef struct saved_screen {
    6362        short *data;
     
    6665saved_screen saved_screens[MAX_SAVED_SCREENS];
    6766
    68 #define EGA_IO_BASE  ((ioport8_t *) 0x3d4)
    69 #define EGA_IO_SIZE  2
     67#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
     68#define EGA_IO_SIZE 2
     69
     70int ega_normal_color = 0x0f;
     71int ega_inverted_color = 0xf0;
     72
     73#define NORMAL_COLOR            ega_normal_color
     74#define INVERTED_COLOR          ega_inverted_color
    7075
    7176/* Allow only 1 connection */
    7277static int client_connected = 0;
    7378
    74 static sysarg_t scr_width;
    75 static sysarg_t scr_height;
     79static unsigned int scr_width;
     80static unsigned int scr_height;
    7681static uint8_t *scr_addr;
    7782
    78 static uint8_t style_normal = 0xf0;
    79 static uint8_t style_inverted = 0x0f;
    80 static uint8_t style;
    81 
    82 static 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 
    96 static 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 
    107 static uint8_t rgb_to_ega_style(uint32_t fg, uint32_t bg)
    108 {
    109         return (fg > bg) ? style_inverted : style_normal;
    110 }
    111 
    112 static 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 
    127 static uint8_t ega_glyph(wchar_t ch)
    128 {
    129         if (ch >= 0 && ch < 128)
    130                 return ch;
    131        
    132         return '?';
    133 }
     83static unsigned int style;
     84
     85static unsigned attr_to_ega_style(const attrs_t *a);
     86static uint8_t ega_glyph(wchar_t ch);
    13487
    13588static void clrscr(void)
     
    14396}
    14497
    145 static void cursor_goto(sysarg_t col, sysarg_t row)
    146 {
    147         sysarg_t cursor = col + scr_width * row;
     98static void cursor_goto(unsigned int col, unsigned int row)
     99{
     100        int ega_cursor;
     101
     102        ega_cursor = col + scr_width * row;
    148103       
    149104        pio_write_8(EGA_IO_BASE, 0xe);
    150         pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
     105        pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff);
    151106        pio_write_8(EGA_IO_BASE, 0xf);
    152         pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
     107        pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff);
    153108}
    154109
    155110static void cursor_disable(void)
    156111{
     112        uint8_t stat;
     113
    157114        pio_write_8(EGA_IO_BASE, 0xa);
    158        
    159         uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
    160        
     115        stat = pio_read_8(EGA_IO_BASE + 1);
    161116        pio_write_8(EGA_IO_BASE, 0xa);
    162117        pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
     
    165120static void cursor_enable(void)
    166121{
     122        uint8_t stat;
     123
    167124        pio_write_8(EGA_IO_BASE, 0xa);
    168        
    169         uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
    170        
     125        stat = pio_read_8(EGA_IO_BASE + 1);
    171126        pio_write_8(EGA_IO_BASE, 0xa);
    172127        pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
    173128}
    174129
    175 static void scroll(ssize_t rows)
    176 {
    177         size_t i;
    178        
     130static void scroll(int rows)
     131{
     132        unsigned i;
     133
    179134        if (rows > 0) {
    180135                memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
     
    187142                    scr_width * scr_height * 2 + rows * scr_width * 2);
    188143                for (i = 0; i < -rows * scr_width; i++)
    189                         ((short *) scr_addr)[i] = ((style << 8 ) + ' ');
    190         }
    191 }
    192 
    193 static void printchar(wchar_t c, sysarg_t col, sysarg_t row)
     144                        ((short *)scr_addr)[i] = ((style << 8 ) + ' ');
     145        }
     146}
     147
     148static void printchar(wchar_t c, unsigned int col, unsigned int row)
    194149{
    195150        scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
     
    203158 * @param vport Viewport id
    204159 * @param data  Text data.
    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  *
     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.
    210164 */
    211 static 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;
     165static 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;
    216169        keyfield_t *field;
    217170        uint8_t *dp;
    218        
     171
    219172        for (j = 0; j < h; j++) {
    220173                for (i = 0; i < w; i++) {
    221174                        field = &data[j * w + i];
    222175                        dp = &scr_addr[2 * ((y + j) * scr_width + (x + i))];
    223                        
     176
    224177                        dp[0] = ega_glyph(field->character);
    225178                        dp[1] = attr_to_ega_style(&field->attrs);
     
    230183static int save_screen(void)
    231184{
    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)
     185        int i;
     186
     187        for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++)
     188                ;
     189        if (i == MAX_SAVED_SCREENS)
    238190                return EINVAL;
    239        
    240         if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
     191        if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
    241192                return ENOMEM;
    242        
    243193        memcpy(saved_screens[i].data, scr_addr, 2 * scr_width * scr_height);
    244         return (int) i;
    245 }
    246 
    247 static int print_screen(ipcarg_t i)
    248 {
    249         if ((i >= MAX_SAVED_SCREENS) || (saved_screens[i].data))
     194
     195        return i;
     196}
     197
     198static int print_screen(int i)
     199{
     200        if (saved_screens[i].data)
    250201                memcpy(scr_addr, saved_screens[i].data, 2 * scr_width *
    251202                    scr_height);
    252203        else
    253204                return EINVAL;
    254        
    255         return (int) i;
     205        return i;
     206}
     207
     208static 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
     226static 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
     237static unsigned int rgb_to_ega_style(uint32_t fg, uint32_t bg)
     238{
     239        return (fg > bg) ? NORMAL_COLOR : INVERTED_COLOR;
     240}
     241
     242static 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
     257static uint8_t ega_glyph(wchar_t ch)
     258{
     259        if (ch >= 0 && ch < 128)
     260                return ch;
     261
     262        return '?';
    256263}
    257264
    258265static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    259266{
     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;
     274        keyfield_t *interbuf = NULL;
    260275        size_t intersize = 0;
    261         keyfield_t *interbuf = NULL;
    262        
     276        int i;
     277
    263278        if (client_connected) {
    264279                ipc_answer_0(iid, ELIMIT);
    265280                return;
    266281        }
    267        
    268         /* Accept connection */
    269282        client_connected = 1;
    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)) {
     283        ipc_answer_0(iid, EOK); /* Accept connection */
     284
     285        while (1) {
     286                callid = async_get_call(&call);
     287                switch (IPC_GET_METHOD(call)) {
    296288                case IPC_M_PHONE_HUNGUP:
    297289                        client_connected = 0;
    298290                        ipc_answer_0(callid, EOK);
    299                        
    300                         /* Exit thread */
    301                         return;
     291                        return; /* Exit thread */
    302292                case IPC_M_SHARE_OUT:
    303293                        /* We accept one area for data interchange */
     
    309299                                continue;
    310300                        }
    311                        
    312301                        retval = EINVAL;
    313302                        break;
    314303                case FB_DRAW_TEXT_DATA:
    315                         if (!interbuf) {
    316                                 retval = EINVAL;
    317                                 break;
    318                         }
    319                        
    320304                        col = IPC_GET_ARG1(call);
    321305                        row = IPC_GET_ARG2(call);
    322306                        w = IPC_GET_ARG3(call);
    323307                        h = IPC_GET_ARG4(call);
    324                        
    325                         if ((col + w > scr_width) || (row + h > scr_height)) {
    326                                 retval = EINVAL;
    327                                 break;
    328                         }
    329                        
     308                        if (!interbuf) {
     309                                retval = EINVAL;
     310                                break;
     311                        }
     312                        if (col + w > scr_width || row + h > scr_height) {
     313                                retval = EINVAL;
     314                                break;
     315                        }
    330316                        draw_text_data(interbuf, col, row, w, h);
    331317                        retval = 0;
     
    345331                        col = IPC_GET_ARG2(call);
    346332                        row = IPC_GET_ARG3(call);
    347                        
    348                         if ((col >= scr_width) || (row >= scr_height)) {
    349                                 retval = EINVAL;
    350                                 break;
    351                         }
    352                        
     333                        if (col >= scr_width || row >= scr_height) {
     334                                retval = EINVAL;
     335                                break;
     336                        }
    353337                        printchar(c, col, row);
    354338                        retval = 0;
    355339                        break;
    356                 case FB_CURSOR_GOTO:
    357                         col = IPC_GET_ARG1(call);
     340                case FB_CURSOR_GOTO:
     341                        col = IPC_GET_ARG1(call);
    358342                        row = IPC_GET_ARG2(call);
    359                        
    360                         if ((row >= scr_height) || (col >= scr_width)) {
    361                                 retval = EINVAL;
    362                                 break;
    363                         }
    364                        
     343                        if (row >= scr_height || col >= scr_width) {
     344                                retval = EINVAL;
     345                                break;
     346                        }
    365347                        cursor_goto(col, row);
    366                         retval = 0;
    367                         break;
     348                        retval = 0;
     349                        break;
    368350                case FB_SCROLL:
    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);
     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);
    384357                        retval = 0;
    385358                        break;
     
    389362                        else
    390363                                cursor_disable();
    391                        
    392364                        retval = 0;
    393365                        break;
     
    400372                        bg_color = IPC_GET_ARG2(call);
    401373                        attr = IPC_GET_ARG3(call);
    402                        
    403374                        style = color_to_ega_style(fg_color, bg_color, attr);
    404375                        retval = 0;
     
    407378                        fg_rgb = IPC_GET_ARG1(call);
    408379                        bg_rgb = IPC_GET_ARG2(call);
    409                        
    410380                        style = rgb_to_ega_style(fg_rgb, bg_rgb);
    411381                        retval = 0;
    412382                        break;
    413383                case FB_VP_DRAW_PIXMAP:
    414                         scr = IPC_GET_ARG2(call);
    415                         retval = print_screen(scr);
     384                        i = IPC_GET_ARG2(call);
     385                        retval = print_screen(i);
    416386                        break;
    417387                case FB_VP2PIXMAP:
     
    419389                        break;
    420390                case FB_DROP_PIXMAP:
    421                         scr = IPC_GET_ARG1(call);
    422                        
    423                         if (scr >= MAX_SAVED_SCREENS) {
    424                                 retval = EINVAL;
    425                                 break;
    426                         }
    427                        
    428                         if (saved_screens[scr].data) {
    429                                 free(saved_screens[scr].data);
    430                                 saved_screens[scr].data = NULL;
    431                         }
    432                        
     391                        i = IPC_GET_ARG1(call);
     392                        if (i >= MAX_SAVED_SCREENS) {
     393                                retval = EINVAL;
     394                                break;
     395                        }
     396                        if (saved_screens[i].data) {
     397                                free(saved_screens[i].data);
     398                                saved_screens[i].data = NULL;
     399                        }
    433400                        retval = 0;
    434401                        break;
     
    446413int ega_init(void)
    447414{
    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        
     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
    470429        iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2);
    471        
    472         size_t sz = scr_width * scr_height * 2;
     430
     431        sz = scr_width * scr_height * 2;
    473432        scr_addr = as_get_mappable_page(sz);
    474        
     433
    475434        if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
    476435            PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
    477436                return -1;
    478        
     437
    479438        async_set_client_connection(ega_client_connection);
    480        
     439
    481440        return 0;
    482441}
     442
    483443
    484444/**
Note: See TracChangeset for help on using the changeset viewer.