diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/vga.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/pc/vga.c')
| -rw-r--r-- | os/pc/vga.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/os/pc/vga.c b/os/pc/vga.c new file mode 100644 index 00000000..0d6c7743 --- /dev/null +++ b/os/pc/vga.c @@ -0,0 +1,241 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#define Image IMAGE +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +static Memimage* back; +static Memimage *conscol; + +static Point curpos; +static Rectangle window; +static int *xp; +static int xbuf[256]; +static Lock vgascreenlock; +int drawdebug; + +void +vgaimageinit(ulong chan) +{ + if(back == nil){ + back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ + if(back == nil) + panic("back alloc"); /* RSC BUG */ + back->flags |= Frepl; + back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); + memfillcolor(back, DBlack); + } + + if(conscol == nil){ + conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ + if(conscol == nil) + panic("conscol alloc"); /* RSC BUG */ + conscol->flags |= Frepl; + conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); + memfillcolor(conscol, DWhite); + } +} + +static void +vgascroll(VGAscr* scr) +{ + int h, o; + Point p; + Rectangle r; + + h = scr->memdefont->height; + o = 8*h; + r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); + p = Pt(window.min.x, window.min.y+o); + memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S); + r = Rpt(Pt(window.min.x, window.max.y-o), window.max); + memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S); + + curpos.y -= o; +} + +static void +vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) +{ + Point p; + int h, w, pos; + Rectangle r; + +// drawdebug = 1; + if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) + xp = xbuf; + + h = scr->memdefont->height; + switch(buf[0]){ + + case '\n': + if(curpos.y+h >= window.max.y){ + vgascroll(scr); + *flushr = window; + } + curpos.y += h; + vgascreenputc(scr, "\r", flushr); + break; + + case '\r': + xp = xbuf; + curpos.x = window.min.x; + break; + + case '\t': + p = memsubfontwidth(scr->memdefont, " "); + w = p.x; + if(curpos.x >= window.max.x-4*w) + vgascreenputc(scr, "\n", flushr); + + pos = (curpos.x-window.min.x)/w; + pos = 4-(pos%4); + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); + memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); + curpos.x += pos*w; + break; + + case '\b': + if(xp <= xbuf) + break; + xp--; + r = Rect(*xp, curpos.y, curpos.x, curpos.y+h); + memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S); + combinerect(flushr, r); + curpos.x = *xp; + break; + + case '\0': + break; + + default: + p = memsubfontwidth(scr->memdefont, buf); + w = p.x; + + if(curpos.x >= window.max.x-w) + vgascreenputc(scr, "\n", flushr); + + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h); + memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf); + combinerect(flushr, r); + curpos.x += w; + } +// drawdebug = 0; +} + +static void +vgascreenputs(char* s, int n) +{ + int i; + Rune r; + char buf[4]; + VGAscr *scr; + Rectangle flushr; + + scr = &vgascreen[0]; + + if(!islo()){ + /* + * Don't deadlock trying to + * print in an interrupt. + */ + if(!canlock(&vgascreenlock)) + return; + } + else + lock(&vgascreenlock); + + flushr = Rect(10000, 10000, -10000, -10000); + + while(n > 0){ + i = chartorune(&r, s); + if(i == 0){ + s++; + --n; + continue; + } + memmove(buf, s, i); + buf[i] = 0; + n -= i; + s += i; + vgascreenputc(scr, buf, &flushr); + } + flushmemscreen(flushr); + + unlock(&vgascreenlock); +} + +void +vgascreenwin(VGAscr* scr) +{ + int h, w; + + h = scr->memdefont->height; + w = scr->memdefont->info[' '].width; + + window = insetrect(scr->gscreen->r, 48); + window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w; + window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; + curpos = window.min; + + screenputs = vgascreenputs; +} + +/* + * Supposedly this is the way to turn DPMS + * monitors off using just the VGA registers. + * Unfortunately, it seems to mess up the video mode + * on the cards I've tried. + */ +void +vgablank(VGAscr*, int blank) +{ + uchar seq1, crtc17; + + if(blank) { + seq1 = 0x00; + crtc17 = 0x80; + } else { + seq1 = 0x20; + crtc17 = 0x00; + } + + outs(Seqx, 0x0100); /* synchronous reset */ + seq1 |= vgaxi(Seqx, 1) & ~0x20; + vgaxo(Seqx, 1, seq1); + crtc17 |= vgaxi(Crtx, 0x17) & ~0x80; + delay(10); + vgaxo(Crtx, 0x17, crtc17); + outs(Crtx, 0x0300); /* end synchronous reset */ +} + +void +cornerstring(char *s) +{ + int h, w; + VGAscr *scr; + Rectangle r; + Point p; + + scr = &vgascreen[0]; + if(scr->aperture == 0 || screenputs != vgascreenputs) + return; + p = memsubfontwidth(scr->memdefont, s); + w = p.x; + h = scr->memdefont->height; + + r = Rect(0, 0, w, h); + memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s); +// flushmemscreen(r); +} |
