xref: /inferno-os/os/boot/puma/cga.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "io.h"
6 #include "fns.h"
7 
8 enum {
9 	Width		= 160,
10 	Height		= 25,
11 
12 	Attr		= 7,		/* white on black */
13 };
14 
15 #define CGASCREENBASE	((uchar*)KADDR(0xB8000))
16 
17 static int pos;
18 static int screeninitdone;
19 
20 static uchar
cgaregr(int index)21 cgaregr(int index)
22 {
23 	outb(0x3D4, index);
24 	return inb(0x3D4+1) & 0xFF;
25 }
26 
27 static void
cgaregw(int index,int data)28 cgaregw(int index, int data)
29 {
30 	outb(0x3D4, index);
31 	outb(0x3D4+1, data);
32 }
33 
34 static void
movecursor(void)35 movecursor(void)
36 {
37 	cgaregw(0x0E, (pos/2>>8) & 0xFF);
38 	cgaregw(0x0F, pos/2 & 0xFF);
39 	CGASCREENBASE[pos+1] = Attr;
40 }
41 
42 static void
cgascreenputc(int c)43 cgascreenputc(int c)
44 {
45 	int i;
46 
47 	if(c == '\n'){
48 		pos = pos/Width;
49 		pos = (pos+1)*Width;
50 	}
51 	else if(c == '\t'){
52 		i = 8 - ((pos/2)&7);
53 		while(i-->0)
54 			cgascreenputc(' ');
55 	}
56 	else if(c == '\b'){
57 		if(pos >= 2)
58 			pos -= 2;
59 		cgascreenputc(' ');
60 		pos -= 2;
61 	}
62 	else{
63 		CGASCREENBASE[pos++] = c;
64 		CGASCREENBASE[pos++] = Attr;
65 	}
66 	if(pos >= Width*Height){
67 		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
68 		memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
69 		pos = Width*(Height-1);
70 	}
71 	movecursor();
72 }
73 
74 void
screeninit(void)75 screeninit(void)
76 {
77 	if(screeninitdone == 0){
78 		pos = cgaregr(0x0E)<<8;
79 		pos |= cgaregr(0x0F);
80 		pos *= 2;
81 		screeninitdone = 1;
82 	}
83 }
84 
85 void
cgascreenputs(char * s,int n)86 cgascreenputs(char* s, int n)
87 {
88 	if(screeninitdone == 0)
89 		screeninit();
90 	while(n-- > 0)
91 		cgascreenputc(*s++);
92 }
93