Changeset a71c158 in mainline for kernel/genarch/src/drivers/ega/ega.c


Ignore:
Timestamp:
2009-08-21T14:12:45Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0e6dce8, b50b5af2, e5792d1
Parents:
90c8b8d
Message:

kernel output devices now suport multiple instances (except ski and sgcn, which respect the same interface, but behave as singletons)
if more than one output device gets initialized, the output is cloned to all of them
get rid of arch_grab_console() and arch_release_console() (output devices can implement a generic "redraw" method, input devices respect the "silent" global variable)
related cleanups and modifications

File:
1 edited

Legend:

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

    r90c8b8d ra71c158  
    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_wire(&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.