xref: /plan9/sys/src/9/pc/vga.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
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