Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"

enum {
        Black,
        Blue,
        Green,
        Cyan,
        Red,
        Magenta,
        Brown,
        Grey,

        Bright = 0x08,
        Blinking = 0x80,

        Yellow = Bright|Brown,
        White = Bright|Grey,
};
        
enum {
        Width           = 80*2,
        Height          = 25,

        Attr            = (Black<<4)|Grey,      /* high nibble background
                                                 * low foreground
                                                 */
};

#define CGASCREENBASE   ((uchar*)KADDR(0xB8000))

#define inb(x)          0        /* TODO */
#define outb(x, y)                      /* TODO */

static int cgapos;
static Lock cgascreenlock;

static uchar
cgaregr(int index)
{
        USED(index);
        outb(0x3D4, index);
        return inb(0x3D4+1) & 0xFF;
}

static void
cgaregw(int index, int data)
{
        USED(index, data);
        outb(0x3D4, index);
        outb(0x3D4+1, data);
}

static void
movecursor(void)
{
        cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
        cgaregw(0x0F, cgapos/2 & 0xFF);
        CGASCREENBASE[cgapos+1] = Attr;
}

static void
cgascreenputc(int c)
{
        int i;
        uchar *p;

        if(c == '\n'){
                cgapos = cgapos/Width;
                cgapos = (cgapos+1)*Width;
        }
        else if(c == '\t'){
                i = 8 - ((cgapos/2)&7);
                while(i-->0)
                        cgascreenputc(' ');
        }
        else if(c == '\b'){
                if(cgapos >= 2)
                        cgapos -= 2;
                cgascreenputc(' ');
                cgapos -= 2;
        }
        else{
                CGASCREENBASE[cgapos++] = c;
                CGASCREENBASE[cgapos++] = Attr;
        }
        if(cgapos >= Width*Height){
                memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
                p = &CGASCREENBASE[Width*(Height-1)];
                for(i=0; i<Width/2; i++){
                        *p++ = ' ';
                        *p++ = Attr;
                }
                cgapos = Width*(Height-1);
        }
        movecursor();
}

static void
cgascreenputs(char* s, int n)
{
        if(!islo()){
                /*
                 * Don't deadlock trying to
                 * print in an interrupt.
                 */
                if(!canlock(&cgascreenlock))
                        return;
        }
        else
                lock(&cgascreenlock);

        while(n-- > 0)
                cgascreenputc(*s++);

        unlock(&cgascreenlock);
}

void
screeninit(void)
{

        cgapos = cgaregr(0x0E)<<8;
        cgapos |= cgaregr(0x0F);
        cgapos *= 2;

        screenputs = cgascreenputs;
}