xref: /plan9-contrib/sys/src/9/kw/cga.c (revision 10dec6bf4309263a8e0334297c2eff22553debb6)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 
8 enum {
9 	Black,
10 	Blue,
11 	Green,
12 	Cyan,
13 	Red,
14 	Magenta,
15 	Brown,
16 	Grey,
17 
18 	Bright = 0x08,
19 	Blinking = 0x80,
20 
21 	Yellow = Bright|Brown,
22 	White = Bright|Grey,
23 };
24 
25 enum {
26 	Width		= 80*2,
27 	Height		= 25,
28 
29 	Attr		= (Black<<4)|Grey,	/* high nibble background
30 						 * low foreground
31 						 */
32 };
33 
34 #define CGASCREENBASE	((uchar*)KADDR(0xB8000))
35 
36 #define inb(x)		0	/* TODO */
37 #define outb(x, y)			/* TODO */
38 
39 static int cgapos;
40 static Lock cgascreenlock;
41 
42 static uchar
cgaregr(int index)43 cgaregr(int index)
44 {
45 	USED(index);
46 	outb(0x3D4, index);
47 	return inb(0x3D4+1) & 0xFF;
48 }
49 
50 static void
cgaregw(int index,int data)51 cgaregw(int index, int data)
52 {
53 	USED(index, data);
54 	outb(0x3D4, index);
55 	outb(0x3D4+1, data);
56 }
57 
58 static void
movecursor(void)59 movecursor(void)
60 {
61 	cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
62 	cgaregw(0x0F, cgapos/2 & 0xFF);
63 	CGASCREENBASE[cgapos+1] = Attr;
64 }
65 
66 static void
cgascreenputc(int c)67 cgascreenputc(int c)
68 {
69 	int i;
70 	uchar *p;
71 
72 	if(c == '\n'){
73 		cgapos = cgapos/Width;
74 		cgapos = (cgapos+1)*Width;
75 	}
76 	else if(c == '\t'){
77 		i = 8 - ((cgapos/2)&7);
78 		while(i-->0)
79 			cgascreenputc(' ');
80 	}
81 	else if(c == '\b'){
82 		if(cgapos >= 2)
83 			cgapos -= 2;
84 		cgascreenputc(' ');
85 		cgapos -= 2;
86 	}
87 	else{
88 		CGASCREENBASE[cgapos++] = c;
89 		CGASCREENBASE[cgapos++] = Attr;
90 	}
91 	if(cgapos >= Width*Height){
92 		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
93 		p = &CGASCREENBASE[Width*(Height-1)];
94 		for(i=0; i<Width/2; i++){
95 			*p++ = ' ';
96 			*p++ = Attr;
97 		}
98 		cgapos = Width*(Height-1);
99 	}
100 	movecursor();
101 }
102 
103 static void
cgascreenputs(char * s,int n)104 cgascreenputs(char* s, int n)
105 {
106 	if(!islo()){
107 		/*
108 		 * Don't deadlock trying to
109 		 * print in an interrupt.
110 		 */
111 		if(!canlock(&cgascreenlock))
112 			return;
113 	}
114 	else
115 		lock(&cgascreenlock);
116 
117 	while(n-- > 0)
118 		cgascreenputc(*s++);
119 
120 	unlock(&cgascreenlock);
121 }
122 
123 void
screeninit(void)124 screeninit(void)
125 {
126 
127 	cgapos = cgaregr(0x0E)<<8;
128 	cgapos |= cgaregr(0x0F);
129 	cgapos *= 2;
130 
131 	screenputs = cgascreenputs;
132 }
133