17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
6*4de34a7eSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier #include "../port/error.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier #define Image IMAGE
107dd7cddfSDavid du Colombier #include <draw.h>
117dd7cddfSDavid du Colombier #include <memdraw.h>
127dd7cddfSDavid du Colombier #include <cursor.h>
137dd7cddfSDavid du Colombier #include "screen.h"
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier static Memimage* back;
167dd7cddfSDavid du Colombier static Memimage *conscol;
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier static Point curpos;
197dd7cddfSDavid du Colombier static Rectangle window;
207dd7cddfSDavid du Colombier static int *xp;
217dd7cddfSDavid du Colombier static int xbuf[256];
22*4de34a7eSDavid du Colombier Lock vgascreenlock;
237dd7cddfSDavid du Colombier int drawdebug;
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier void
vgaimageinit(ulong chan)267dd7cddfSDavid du Colombier vgaimageinit(ulong chan)
277dd7cddfSDavid du Colombier {
287dd7cddfSDavid du Colombier if(back == nil){
297dd7cddfSDavid du Colombier back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
307dd7cddfSDavid du Colombier if(back == nil)
317dd7cddfSDavid du Colombier panic("back alloc"); /* RSC BUG */
327dd7cddfSDavid du Colombier back->flags |= Frepl;
337dd7cddfSDavid du Colombier back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
347dd7cddfSDavid du Colombier memfillcolor(back, DBlack);
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier if(conscol == nil){
387dd7cddfSDavid du Colombier conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
397dd7cddfSDavid du Colombier if(conscol == nil)
407dd7cddfSDavid du Colombier panic("conscol alloc"); /* RSC BUG */
417dd7cddfSDavid du Colombier conscol->flags |= Frepl;
427dd7cddfSDavid du Colombier conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
437dd7cddfSDavid du Colombier memfillcolor(conscol, DWhite);
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier static void
vgascroll(VGAscr * scr)487dd7cddfSDavid du Colombier vgascroll(VGAscr* scr)
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier int h, o;
517dd7cddfSDavid du Colombier Point p;
527dd7cddfSDavid du Colombier Rectangle r;
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier h = scr->memdefont->height;
557dd7cddfSDavid du Colombier o = 8*h;
567dd7cddfSDavid du Colombier r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
577dd7cddfSDavid du Colombier p = Pt(window.min.x, window.min.y+o);
586a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
597dd7cddfSDavid du Colombier r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
606a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier curpos.y -= o;
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier static void
vgascreenputc(VGAscr * scr,char * buf,Rectangle * flushr)667dd7cddfSDavid du Colombier vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
677dd7cddfSDavid du Colombier {
687dd7cddfSDavid du Colombier Point p;
697dd7cddfSDavid du Colombier int h, w, pos;
707dd7cddfSDavid du Colombier Rectangle r;
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier // drawdebug = 1;
737dd7cddfSDavid du Colombier if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
747dd7cddfSDavid du Colombier xp = xbuf;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier h = scr->memdefont->height;
777dd7cddfSDavid du Colombier switch(buf[0]){
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier case '\n':
807dd7cddfSDavid du Colombier if(curpos.y+h >= window.max.y){
817dd7cddfSDavid du Colombier vgascroll(scr);
827dd7cddfSDavid du Colombier *flushr = window;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier curpos.y += h;
857dd7cddfSDavid du Colombier vgascreenputc(scr, "\r", flushr);
867dd7cddfSDavid du Colombier break;
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier case '\r':
897dd7cddfSDavid du Colombier xp = xbuf;
907dd7cddfSDavid du Colombier curpos.x = window.min.x;
917dd7cddfSDavid du Colombier break;
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier case '\t':
947dd7cddfSDavid du Colombier p = memsubfontwidth(scr->memdefont, " ");
957dd7cddfSDavid du Colombier w = p.x;
9680ee5cbfSDavid du Colombier if(curpos.x >= window.max.x-4*w)
9780ee5cbfSDavid du Colombier vgascreenputc(scr, "\n", flushr);
9880ee5cbfSDavid du Colombier
997dd7cddfSDavid du Colombier pos = (curpos.x-window.min.x)/w;
1007dd7cddfSDavid du Colombier pos = 4-(pos%4);
10180ee5cbfSDavid du Colombier *xp++ = curpos.x;
1027dd7cddfSDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
1036a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
1047dd7cddfSDavid du Colombier curpos.x += pos*w;
1057dd7cddfSDavid du Colombier break;
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier case '\b':
1087dd7cddfSDavid du Colombier if(xp <= xbuf)
1097dd7cddfSDavid du Colombier break;
1107dd7cddfSDavid du Colombier xp--;
1117dd7cddfSDavid du Colombier r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
1126a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
1137dd7cddfSDavid du Colombier combinerect(flushr, r);
1147dd7cddfSDavid du Colombier curpos.x = *xp;
1157dd7cddfSDavid du Colombier break;
1167dd7cddfSDavid du Colombier
11780ee5cbfSDavid du Colombier case '\0':
11880ee5cbfSDavid du Colombier break;
11980ee5cbfSDavid du Colombier
1207dd7cddfSDavid du Colombier default:
1217dd7cddfSDavid du Colombier p = memsubfontwidth(scr->memdefont, buf);
1227dd7cddfSDavid du Colombier w = p.x;
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier if(curpos.x >= window.max.x-w)
1257dd7cddfSDavid du Colombier vgascreenputc(scr, "\n", flushr);
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier *xp++ = curpos.x;
1287dd7cddfSDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
1296a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
1307dd7cddfSDavid du Colombier memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
1317dd7cddfSDavid du Colombier combinerect(flushr, r);
1327dd7cddfSDavid du Colombier curpos.x += w;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier // drawdebug = 0;
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier static void
vgascreenputs(char * s,int n)1387dd7cddfSDavid du Colombier vgascreenputs(char* s, int n)
1397dd7cddfSDavid du Colombier {
140*4de34a7eSDavid du Colombier int i, gotdraw;
1417dd7cddfSDavid du Colombier Rune r;
1427dd7cddfSDavid du Colombier char buf[4];
1437dd7cddfSDavid du Colombier VGAscr *scr;
1447dd7cddfSDavid du Colombier Rectangle flushr;
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier scr = &vgascreen[0];
1477dd7cddfSDavid du Colombier
1487dd7cddfSDavid du Colombier if(!islo()){
1497dd7cddfSDavid du Colombier /*
1507dd7cddfSDavid du Colombier * Don't deadlock trying to
1517dd7cddfSDavid du Colombier * print in an interrupt.
1527dd7cddfSDavid du Colombier */
1537dd7cddfSDavid du Colombier if(!canlock(&vgascreenlock))
1547dd7cddfSDavid du Colombier return;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier else
1577dd7cddfSDavid du Colombier lock(&vgascreenlock);
1587dd7cddfSDavid du Colombier
159*4de34a7eSDavid du Colombier /*
160*4de34a7eSDavid du Colombier * Be nice to hold this, but not going to deadlock
161*4de34a7eSDavid du Colombier * waiting for it. Just try and see.
162*4de34a7eSDavid du Colombier */
163*4de34a7eSDavid du Colombier gotdraw = canqlock(&drawlock);
164*4de34a7eSDavid du Colombier
1657dd7cddfSDavid du Colombier flushr = Rect(10000, 10000, -10000, -10000);
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier while(n > 0){
1687dd7cddfSDavid du Colombier i = chartorune(&r, s);
1697dd7cddfSDavid du Colombier if(i == 0){
1707dd7cddfSDavid du Colombier s++;
1717dd7cddfSDavid du Colombier --n;
1727dd7cddfSDavid du Colombier continue;
1737dd7cddfSDavid du Colombier }
1747dd7cddfSDavid du Colombier memmove(buf, s, i);
1757dd7cddfSDavid du Colombier buf[i] = 0;
1767dd7cddfSDavid du Colombier n -= i;
1777dd7cddfSDavid du Colombier s += i;
1787dd7cddfSDavid du Colombier vgascreenputc(scr, buf, &flushr);
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier flushmemscreen(flushr);
1817dd7cddfSDavid du Colombier
182*4de34a7eSDavid du Colombier if(gotdraw)
183*4de34a7eSDavid du Colombier qunlock(&drawlock);
1847dd7cddfSDavid du Colombier unlock(&vgascreenlock);
1857dd7cddfSDavid du Colombier }
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier void
vgascreenwin(VGAscr * scr)1887dd7cddfSDavid du Colombier vgascreenwin(VGAscr* scr)
1897dd7cddfSDavid du Colombier {
1907dd7cddfSDavid du Colombier int h, w;
1917dd7cddfSDavid du Colombier
1927dd7cddfSDavid du Colombier h = scr->memdefont->height;
1937dd7cddfSDavid du Colombier w = scr->memdefont->info[' '].width;
1947dd7cddfSDavid du Colombier
19580ee5cbfSDavid du Colombier window = insetrect(scr->gscreen->r, 48);
19680ee5cbfSDavid du Colombier window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
1977dd7cddfSDavid du Colombier window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
1987dd7cddfSDavid du Colombier curpos = window.min;
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier screenputs = vgascreenputs;
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier /*
2047dd7cddfSDavid du Colombier * Supposedly this is the way to turn DPMS
2057dd7cddfSDavid du Colombier * monitors off using just the VGA registers.
2067dd7cddfSDavid du Colombier * Unfortunately, it seems to mess up the video mode
2077dd7cddfSDavid du Colombier * on the cards I've tried.
2087dd7cddfSDavid du Colombier */
2097dd7cddfSDavid du Colombier void
vgablank(VGAscr *,int blank)2107dd7cddfSDavid du Colombier vgablank(VGAscr*, int blank)
2117dd7cddfSDavid du Colombier {
2127dd7cddfSDavid du Colombier uchar seq1, crtc17;
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier if(blank) {
2157dd7cddfSDavid du Colombier seq1 = 0x00;
2167dd7cddfSDavid du Colombier crtc17 = 0x80;
2177dd7cddfSDavid du Colombier } else {
2187dd7cddfSDavid du Colombier seq1 = 0x20;
2197dd7cddfSDavid du Colombier crtc17 = 0x00;
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier outs(Seqx, 0x0100); /* synchronous reset */
2237dd7cddfSDavid du Colombier seq1 |= vgaxi(Seqx, 1) & ~0x20;
2247dd7cddfSDavid du Colombier vgaxo(Seqx, 1, seq1);
2257dd7cddfSDavid du Colombier crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
2267dd7cddfSDavid du Colombier delay(10);
2277dd7cddfSDavid du Colombier vgaxo(Crtx, 0x17, crtc17);
2287dd7cddfSDavid du Colombier outs(Crtx, 0x0300); /* end synchronous reset */
2297dd7cddfSDavid du Colombier }
2309a747e4fSDavid du Colombier
2319a747e4fSDavid du Colombier void
addvgaseg(char * name,ulong pa,ulong size)2329a747e4fSDavid du Colombier addvgaseg(char *name, ulong pa, ulong size)
2339a747e4fSDavid du Colombier {
2349a747e4fSDavid du Colombier Physseg seg;
2359a747e4fSDavid du Colombier
2369a747e4fSDavid du Colombier memset(&seg, 0, sizeof seg);
2379a747e4fSDavid du Colombier seg.attr = SG_PHYSICAL;
2389a747e4fSDavid du Colombier seg.name = name;
2399a747e4fSDavid du Colombier seg.pa = pa;
2409a747e4fSDavid du Colombier seg.size = size;
2419a747e4fSDavid du Colombier addphysseg(&seg);
2429a747e4fSDavid du Colombier }
2439a747e4fSDavid du Colombier
2443ff48bf5SDavid du Colombier void
cornerstring(char * s)2453ff48bf5SDavid du Colombier cornerstring(char *s)
2463ff48bf5SDavid du Colombier {
2473ff48bf5SDavid du Colombier int h, w;
2483ff48bf5SDavid du Colombier VGAscr *scr;
2493ff48bf5SDavid du Colombier Rectangle r;
2503ff48bf5SDavid du Colombier Point p;
2513ff48bf5SDavid du Colombier
2523ff48bf5SDavid du Colombier scr = &vgascreen[0];
253*4de34a7eSDavid du Colombier if(scr->vaddr == nil || screenputs != vgascreenputs)
2543ff48bf5SDavid du Colombier return;
2553ff48bf5SDavid du Colombier p = memsubfontwidth(scr->memdefont, s);
2563ff48bf5SDavid du Colombier w = p.x;
2573ff48bf5SDavid du Colombier h = scr->memdefont->height;
2583ff48bf5SDavid du Colombier
2593ff48bf5SDavid du Colombier r = Rect(0, 0, w, h);
2606a9fc400SDavid du Colombier memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
2613ff48bf5SDavid du Colombier memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
2623ff48bf5SDavid du Colombier // flushmemscreen(r);
2633ff48bf5SDavid du Colombier }
264