Ignore:
Timestamp:
2009-08-22T10:48:00Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
04803bf
Parents:
1ea99cc (diff), a71c158 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/drivers/ega/ega.c

    r1ea99cc rb50b5af2  
    5656 */
    5757
    58 SPINLOCK_INITIALIZE(egalock);
    59 static uint32_t ega_cursor;
    60 static uint8_t *videoram;
    61 static uint8_t *backbuf;
    62 static ioport8_t *ega_base;
    63 
    6458#define SPACE  0x20
    6559#define STYLE  0x1e
     
    6862#define EMPTY_CHAR  ((STYLE << 8) | SPACE)
    6963
     64typedef struct {
     65        SPINLOCK_DECLARE(lock);
     66       
     67        uint32_t cursor;
     68        uint8_t *addr;
     69        uint8_t *backbuf;
     70        ioport8_t *base;
     71} ega_instance_t;
     72
     73static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent);
     74static void ega_redraw(outdev_t *dev);
     75
     76static outdev_operations_t egadev_ops = {
     77        .write = ega_putchar,
     78        .redraw = ega_redraw
     79};
     80
    7081static uint16_t ega_oem_glyph(const wchar_t ch)
    7182{
     
    427438 * This function takes care of scrolling.
    428439 */
    429 static void ega_check_cursor(bool silent)
    430 {
    431         if (ega_cursor < EGA_SCREEN)
     440static void ega_check_cursor(ega_instance_t *instance, bool silent)
     441{
     442        if (instance->cursor < EGA_SCREEN)
    432443                return;
    433444       
    434         memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
     445        memmove((void *) instance->backbuf,
     446            (void *) (instance->backbuf + EGA_COLS * 2),
    435447            (EGA_SCREEN - EGA_COLS) * 2);
    436         memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
     448        memsetw(instance->backbuf + (EGA_SCREEN - EGA_COLS) * 2,
     449            EGA_COLS, EMPTY_CHAR);
    437450       
    438451        if (!silent) {
    439                 memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
     452                memmove((void *) instance->addr,
     453                    (void *) (instance->addr + EGA_COLS * 2),
    440454                    (EGA_SCREEN - EGA_COLS) * 2);
    441                 memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
    442         }
    443        
    444         ega_cursor = ega_cursor - EGA_COLS;
    445 }
    446 
    447 static void ega_show_cursor(bool silent)
     455                memsetw(instance->addr + (EGA_SCREEN - EGA_COLS) * 2,
     456                    EGA_COLS, EMPTY_CHAR);
     457        }
     458       
     459        instance->cursor = instance->cursor - EGA_COLS;
     460}
     461
     462static void ega_show_cursor(ega_instance_t *instance, bool silent)
    448463{
    449464        if (!silent) {
    450                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
    451                 uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
    452                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
    453                 pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
    454         }
    455 }
    456 
    457 static void ega_move_cursor(bool silent)
     465                pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
     466                uint8_t stat = pio_read_8(instance->base + EGA_DATA_REG);
     467                pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
     468                pio_write_8(instance->base + EGA_DATA_REG, stat & (~(1 << 5)));
     469        }
     470}
     471
     472static void ega_move_cursor(ega_instance_t *instance, bool silent)
    458473{
    459474        if (!silent) {
    460                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
    461                 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
    462                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
    463                 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
    464         }
    465 }
    466 
    467 static void ega_sync_cursor(bool silent)
     475                pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
     476                pio_write_8(instance->base + EGA_DATA_REG,
     477                    (uint8_t) ((instance->cursor >> 8) & 0xff));
     478                pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
     479                pio_write_8(instance->base + EGA_DATA_REG,
     480                    (uint8_t) (instance->cursor & 0xff));
     481        }
     482}
     483
     484static void ega_sync_cursor(ega_instance_t *instance, bool silent)
    468485{
    469486        if (!silent) {
    470                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
    471                 uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
    472                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
    473                 uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
     487                pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
     488                uint8_t hi = pio_read_8(instance->base + EGA_DATA_REG);
     489                pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
     490                uint8_t lo = pio_read_8(instance->base + EGA_DATA_REG);
    474491               
    475                 ega_cursor = (hi << 8) | lo;
     492                instance->cursor = (hi << 8) | lo;
    476493        } else
    477                 ega_cursor = 0;
    478        
    479         if (ega_cursor >= EGA_SCREEN)
    480                 ega_cursor = 0;
    481        
    482         if ((ega_cursor % EGA_COLS) != 0)
    483                 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
    484        
    485         memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
     494                instance->cursor = 0;
     495       
     496        if (instance->cursor >= EGA_SCREEN)
     497                instance->cursor = 0;
     498       
     499        if ((instance->cursor % EGA_COLS) != 0)
     500                instance->cursor =
     501                    (instance->cursor + EGA_COLS) - instance->cursor % EGA_COLS;
     502       
     503        memsetw(instance->backbuf + instance->cursor * 2,
     504            EGA_SCREEN - instance->cursor, EMPTY_CHAR);
    486505       
    487506        if (!silent)
    488                 memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
    489        
    490         ega_check_cursor(silent);
    491         ega_move_cursor(silent);
    492         ega_show_cursor(silent);
    493 }
    494 
    495 static void ega_display_char(wchar_t ch, bool silent)
     507                memsetw(instance->addr + instance->cursor * 2,
     508                    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
     509       
     510        ega_check_cursor(instance, silent);
     511        ega_move_cursor(instance, silent);
     512        ega_show_cursor(instance, silent);
     513}
     514
     515static void ega_display_char(ega_instance_t *instance, wchar_t ch, bool silent)
    496516{
    497517        uint16_t index = ega_oem_glyph(ch);
     
    507527        }
    508528       
    509         backbuf[ega_cursor * 2] = glyph;
    510         backbuf[ega_cursor * 2 + 1] = style;
     529        instance->backbuf[instance->cursor * 2] = glyph;
     530        instance->backbuf[instance->cursor * 2 + 1] = style;
    511531       
    512532        if (!silent) {
    513                 videoram[ega_cursor * 2] = glyph;
    514                 videoram[ega_cursor * 2 + 1] = style;
    515         }
    516 }
    517 
    518 static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
    519 {
    520         ipl_t ipl;
    521        
    522         ipl = interrupts_disable();
    523         spinlock_lock(&egalock);
     533                instance->addr[instance->cursor * 2] = glyph;
     534                instance->addr[instance->cursor * 2 + 1] = style;
     535        }
     536}
     537
     538static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent)
     539{
     540        ega_instance_t *instance = (ega_instance_t *) dev->data;
     541       
     542        ipl_t ipl = interrupts_disable();
     543        spinlock_lock(&instance->lock);
    524544       
    525545        switch (ch) {
    526546        case '\n':
    527                 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
     547                instance->cursor = (instance->cursor + EGA_COLS)
     548                    - instance->cursor % EGA_COLS;
    528549                break;
    529550        case '\t':
    530                 ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
     551                instance->cursor = (instance->cursor + 8)
     552                    - instance->cursor % 8;
    531553                break;
    532554        case '\b':
    533                 if (ega_cursor % EGA_COLS)
    534                         ega_cursor--;
     555                if (instance->cursor % EGA_COLS)
     556                        instance->cursor--;
    535557                break;
    536558        default:
    537                 ega_display_char(ch, silent);
    538                 ega_cursor++;
     559                ega_display_char(instance, ch, silent);
     560                instance->cursor++;
    539561                break;
    540562        }
    541         ega_check_cursor(silent);
    542         ega_move_cursor(silent);
    543        
    544         spinlock_unlock(&egalock);
     563        ega_check_cursor(instance, silent);
     564        ega_move_cursor(instance, silent);
     565       
     566        spinlock_unlock(&instance->lock);
    545567        interrupts_restore(ipl);
    546568}
    547569
    548 static outdev_t ega_console;
    549 static outdev_operations_t ega_ops = {
    550         .write = ega_putchar
    551 };
    552 
    553 void ega_init(ioport8_t *base, uintptr_t videoram_phys)
    554 {
    555         /* Initialize the software structure. */
    556         ega_base = base;
    557        
    558         backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
    559         if (!backbuf)
    560                 panic("Unable to allocate backbuffer.");
    561        
    562         videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
     570static void ega_redraw(outdev_t *dev)
     571{
     572        ega_instance_t *instance = (ega_instance_t *) dev->data;
     573       
     574        ipl_t ipl = interrupts_disable();
     575        spinlock_lock(&instance->lock);
     576       
     577        memcpy(instance->addr, instance->backbuf, EGA_VRAM_SIZE);
     578        ega_move_cursor(instance, silent);
     579        ega_show_cursor(instance, silent);
     580       
     581        spinlock_unlock(&instance->lock);
     582        interrupts_restore(ipl);
     583}
     584
     585outdev_t *ega_init(ioport8_t *base, uintptr_t addr)
     586{
     587        outdev_t *egadev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     588        if (!egadev)
     589                return NULL;
     590       
     591        ega_instance_t *instance = malloc(sizeof(ega_instance_t), FRAME_ATOMIC);
     592        if (!instance) {
     593                free(egadev);
     594                return NULL;
     595        }
     596       
     597        outdev_initialize("egadev", egadev, &egadev_ops);
     598        egadev->data = instance;
     599       
     600        spinlock_initialize(&instance->lock, "*ega_lock");
     601       
     602        instance->base = base;
     603        instance->addr = (uint8_t *) hw_map(addr, EGA_VRAM_SIZE);
     604        if (!instance->addr) {
     605                LOG("Unable to EGA video memory.");
     606                free(instance);
     607                free(egadev);
     608                return NULL;
     609        }
     610       
     611        instance->backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
     612        if (!instance->backbuf) {
     613                LOG("Unable to allocate backbuffer.");
     614                free(instance);
     615                free(egadev);
     616                return NULL;
     617        }
    563618       
    564619        /* Synchronize the back buffer and cursor position. */
    565         memcpy(backbuf, videoram, EGA_VRAM_SIZE);
    566         ega_sync_cursor(silent);
    567        
    568         outdev_initialize("ega", &ega_console, &ega_ops);
    569         stdout = &ega_console;
    570        
    571         sysinfo_set_item_val("fb", NULL, true);
    572         sysinfo_set_item_val("fb.kind", NULL, 2);
    573         sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
    574         sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
    575         sysinfo_set_item_val("fb.blinking", NULL, true);
    576         sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
    577 }
    578 
    579 void ega_redraw(void)
    580 {
    581         memcpy(videoram, backbuf, EGA_VRAM_SIZE);
    582         ega_move_cursor(silent);
    583         ega_show_cursor(silent);
     620        memcpy(instance->backbuf, instance->addr, EGA_VRAM_SIZE);
     621        ega_sync_cursor(instance, silent);
     622       
     623        if (!fb_exported) {
     624                /*
     625                 * This is the necessary evil until the userspace driver is entirely
     626                 * self-sufficient.
     627                 */
     628                sysinfo_set_item_val("fb", NULL, true);
     629                sysinfo_set_item_val("fb.kind", NULL, 2);
     630                sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
     631                sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
     632                sysinfo_set_item_val("fb.blinking", NULL, true);
     633                sysinfo_set_item_val("fb.address.physical", NULL, addr);
     634               
     635                fb_exported = true;
     636        }
     637       
     638        return egadev;
    584639}
    585640
Note: See TracChangeset for help on using the changeset viewer.