xref: /plan9-contrib/sys/src/9/pc/cga.c (revision 1045bea11e2fdfc8e23a3be73ec6cf07aa628e91)
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"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier enum {
97dd7cddfSDavid du Colombier 	Black,
107dd7cddfSDavid du Colombier 	Blue,
117dd7cddfSDavid du Colombier 	Green,
127dd7cddfSDavid du Colombier 	Cyan,
137dd7cddfSDavid du Colombier 	Red,
147dd7cddfSDavid du Colombier 	Magenta,
157dd7cddfSDavid du Colombier 	Brown,
167dd7cddfSDavid du Colombier 	Grey,
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier 	Bright = 0x08,
197dd7cddfSDavid du Colombier 	Blinking = 0x80,
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	Yellow = Bright|Brown,
227dd7cddfSDavid du Colombier 	White = Bright|Grey,
237dd7cddfSDavid du Colombier };
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier enum {
267dd7cddfSDavid du Colombier 	Width		= 80*2,
277dd7cddfSDavid du Colombier 	Height		= 25,
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	Attr		= (Black<<4)|Grey,	/* high nibble background
307dd7cddfSDavid du Colombier 						 * low foreground
317dd7cddfSDavid du Colombier 						 */
32*1045bea1SDavid du Colombier 
33*1045bea1SDavid du Colombier 	Poststrlen	= 0,
34*1045bea1SDavid du Colombier 	Postcodelen	= 2,
35*1045bea1SDavid du Colombier 	Postlen		= Poststrlen+Postcodelen,
367dd7cddfSDavid du Colombier };
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier #define CGASCREENBASE	((uchar*)KADDR(0xB8000))
39*1045bea1SDavid du Colombier #define CGA		CGASCREENBASE
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier static int cgapos;
427dd7cddfSDavid du Colombier static Lock cgascreenlock;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier static uchar
cgaregr(int index)457dd7cddfSDavid du Colombier cgaregr(int index)
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	outb(0x3D4, index);
487dd7cddfSDavid du Colombier 	return inb(0x3D4+1) & 0xFF;
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier static void
cgaregw(int index,int data)527dd7cddfSDavid du Colombier cgaregw(int index, int data)
537dd7cddfSDavid du Colombier {
547dd7cddfSDavid du Colombier 	outb(0x3D4, index);
557dd7cddfSDavid du Colombier 	outb(0x3D4+1, data);
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier static void
movecursor(void)597dd7cddfSDavid du Colombier movecursor(void)
607dd7cddfSDavid du Colombier {
617dd7cddfSDavid du Colombier 	cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
627dd7cddfSDavid du Colombier 	cgaregw(0x0F, cgapos/2 & 0xFF);
637dd7cddfSDavid du Colombier 	CGASCREENBASE[cgapos+1] = Attr;
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier static void
cgascreenputc(int c)677dd7cddfSDavid du Colombier cgascreenputc(int c)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier 	int i;
707dd7cddfSDavid du Colombier 	uchar *p;
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier 	if(c == '\n'){
737dd7cddfSDavid du Colombier 		cgapos = cgapos/Width;
747dd7cddfSDavid du Colombier 		cgapos = (cgapos+1)*Width;
757dd7cddfSDavid du Colombier 	}
767dd7cddfSDavid du Colombier 	else if(c == '\t'){
777dd7cddfSDavid du Colombier 		i = 8 - ((cgapos/2)&7);
787dd7cddfSDavid du Colombier 		while(i-->0)
797dd7cddfSDavid du Colombier 			cgascreenputc(' ');
807dd7cddfSDavid du Colombier 	}
817dd7cddfSDavid du Colombier 	else if(c == '\b'){
827dd7cddfSDavid du Colombier 		if(cgapos >= 2)
837dd7cddfSDavid du Colombier 			cgapos -= 2;
847dd7cddfSDavid du Colombier 		cgascreenputc(' ');
857dd7cddfSDavid du Colombier 		cgapos -= 2;
867dd7cddfSDavid du Colombier 	}
877dd7cddfSDavid du Colombier 	else{
887dd7cddfSDavid du Colombier 		CGASCREENBASE[cgapos++] = c;
897dd7cddfSDavid du Colombier 		CGASCREENBASE[cgapos++] = Attr;
907dd7cddfSDavid du Colombier 	}
917dd7cddfSDavid du Colombier 	if(cgapos >= Width*Height){
927dd7cddfSDavid du Colombier 		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
937dd7cddfSDavid du Colombier 		p = &CGASCREENBASE[Width*(Height-1)];
947dd7cddfSDavid du Colombier 		for(i=0; i<Width/2; i++){
957dd7cddfSDavid du Colombier 			*p++ = ' ';
967dd7cddfSDavid du Colombier 			*p++ = Attr;
977dd7cddfSDavid du Colombier 		}
987dd7cddfSDavid du Colombier 		cgapos = Width*(Height-1);
997dd7cddfSDavid du Colombier 	}
1007dd7cddfSDavid du Colombier 	movecursor();
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier static void
cgascreenputs(char * s,int n)1047dd7cddfSDavid du Colombier cgascreenputs(char* s, int n)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier 	if(!islo()){
1077dd7cddfSDavid du Colombier 		/*
1087dd7cddfSDavid du Colombier 		 * Don't deadlock trying to
1097dd7cddfSDavid du Colombier 		 * print in an interrupt.
1107dd7cddfSDavid du Colombier 		 */
1117dd7cddfSDavid du Colombier 		if(!canlock(&cgascreenlock))
1127dd7cddfSDavid du Colombier 			return;
1137dd7cddfSDavid du Colombier 	}
1147dd7cddfSDavid du Colombier 	else
1157dd7cddfSDavid du Colombier 		lock(&cgascreenlock);
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier 	while(n-- > 0)
1187dd7cddfSDavid du Colombier 		cgascreenputc(*s++);
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	unlock(&cgascreenlock);
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
123*1045bea1SDavid du Colombier char hex[] = "0123456789ABCDEF";
124*1045bea1SDavid du Colombier 
125*1045bea1SDavid du Colombier void
cgapost(int code)126*1045bea1SDavid du Colombier cgapost(int code)
127*1045bea1SDavid du Colombier {
128*1045bea1SDavid du Colombier 	uchar *cga;
129*1045bea1SDavid du Colombier 
130*1045bea1SDavid du Colombier 	cga = CGA;
131*1045bea1SDavid du Colombier 	cga[Width*Height-Postcodelen*2] = hex[(code>>4) & 0x0F];
132*1045bea1SDavid du Colombier 	cga[Width*Height-Postcodelen*2+1] = Attr;
133*1045bea1SDavid du Colombier 	cga[Width*Height-Postcodelen*2+2] = hex[code & 0x0F];
134*1045bea1SDavid du Colombier 	cga[Width*Height-Postcodelen*2+3] = Attr;
135*1045bea1SDavid du Colombier }
136*1045bea1SDavid du Colombier 
1379a747e4fSDavid du Colombier void
screeninit(void)1389a747e4fSDavid du Colombier screeninit(void)
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier 
1419a747e4fSDavid du Colombier 	cgapos = cgaregr(0x0E)<<8;
1429a747e4fSDavid du Colombier 	cgapos |= cgaregr(0x0F);
1439a747e4fSDavid du Colombier 	cgapos *= 2;
1449a747e4fSDavid du Colombier 
1459a747e4fSDavid du Colombier 	screenputs = cgascreenputs;
1469a747e4fSDavid du Colombier }
147