1 /*
2  * (C) Copyright 2002
3  * Daniel Engstr�m, Omicron Ceti AB, daniel@omicron.se
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 #include <pci.h>
26 #include <stdio_dev.h>
27 #include <i8042.h>
28 #include <asm/ptrace.h>
29 #include <asm/realmode.h>
30 #include <asm/io.h>
31 #include <asm/pci.h>
32 
33 
34 /* basic textmode I/O from linux kernel */
35 static char *vidmem = (char *)0xb8000;
36 static int vidport;
37 static int lines, cols;
38 static int orig_x, orig_y;
39 
beep(int dur)40 static void beep(int dur)
41 {
42 	int i;
43 
44 	outb_p(3, 0x61);
45 	for (i=0;i<10*dur;i++) {
46 		udelay(1000);
47 	}
48 	outb_p(0, 0x61);
49 }
50 
scroll(void)51 static void scroll(void)
52 {
53 	int i;
54 
55 	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
56 	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
57 		vidmem[i] = ' ';
58 }
59 
__video_putc(const char c,int * x,int * y)60 static void __video_putc(const char c, int *x, int *y)
61 {
62 	if (c == '\n') {
63 		(*x) = 0;
64 		if ( ++(*y) >= lines ) {
65 			scroll();
66 			(*y)--;
67 		}
68 	} else if (c == '\b') {
69 		if ((*x) != 0) {
70 			--(*x);
71 			vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' ';
72 		}
73 	} else if (c == '\r') {
74 		(*x) = 0;
75 
76 	} else if (c == '\a') {
77 		beep(3);
78 
79 	} else if (c == '\t') {
80 		__video_putc(' ', x, y);
81 		__video_putc(' ', x, y);
82 		__video_putc(' ', x, y);
83 		__video_putc(' ', x, y);
84 		__video_putc(' ', x, y);
85 		__video_putc(' ', x, y);
86 		__video_putc(' ', x, y);
87 		__video_putc(' ', x, y);
88 	} else if (c == '\v') {
89 		switch ((*x) % 8) {
90 		case 0:
91 			__video_putc(' ', x, y);
92 		case 7:
93 			__video_putc(' ', x, y);
94 		case 6:
95 			__video_putc(' ', x, y);
96 		case 5:
97 			__video_putc(' ', x, y);
98 		case 4:
99 			__video_putc(' ', x, y);
100 		case 3:
101 			__video_putc(' ', x, y);
102 		case 2:
103 			__video_putc(' ', x, y);
104 		case 1:
105 			__video_putc(' ', x, y);
106 		}
107 	} else if (c == '\f') {
108 		int i;
109 		for (i=0;i<lines*cols*2;i+=2) {
110 			vidmem[i] = 0;
111 		}
112 		(*x) = 0;
113 		(*y) = 0;
114 	} else {
115 		vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c;
116 		if ( ++(*x) >= cols ) {
117 			(*x) = 0;
118 			if ( ++(*y) >= lines ) {
119 				scroll();
120 				(*y)--;
121 			}
122 		}
123 	}
124 }
125 
video_putc(const char c)126 static void video_putc(const char c)
127 {
128 	int x,y,pos;
129 
130 	x = orig_x;
131 	y = orig_y;
132 
133 	__video_putc(c, &x, &y);
134 
135 	orig_x = x;
136 	orig_y = y;
137 
138 	pos = (x + cols * y) * 2;	/* Update cursor position */
139 	outb_p(14, vidport);
140 	outb_p(0xff & (pos >> 9), vidport+1);
141 	outb_p(15, vidport);
142 	outb_p(0xff & (pos >> 1), vidport+1);
143 }
144 
video_puts(const char * s)145 static void video_puts(const char *s)
146 {
147 	int x,y,pos;
148 	char c;
149 
150 	x = orig_x;
151 	y = orig_y;
152 
153 	while ( ( c = *s++ ) != '\0' ) {
154 		__video_putc(c, &x, &y);
155 	}
156 
157 	orig_x = x;
158 	orig_y = y;
159 
160 	pos = (x + cols * y) * 2;	/* Update cursor position */
161 	outb_p(14, vidport);
162 	outb_p(0xff & (pos >> 9), vidport+1);
163 	outb_p(15, vidport);
164 	outb_p(0xff & (pos >> 1), vidport+1);
165 }
166 
video_init(void)167 int video_init(void)
168 {
169 	u16 pos;
170 
171 	static struct stdio_dev vga_dev;
172 	static struct stdio_dev kbd_dev;
173 
174 	vidmem = (char *) 0xb8000;
175 	vidport = 0x3d4;
176 
177 	lines = 25;
178 	cols = 80;
179 
180 	outb_p(14, vidport);
181 	pos = inb_p(vidport+1);
182 	pos <<= 8;
183 	outb_p(15, vidport);
184 	pos |= inb_p(vidport+1);
185 
186 	orig_x = pos%cols;
187 	orig_y = pos/cols;
188 
189 #if 0
190 	printf("pos %x %d %d\n", pos, orig_x, orig_y);
191 #endif
192 	if (orig_y > lines) {
193 		orig_x = orig_y =0;
194 	}
195 
196 
197 	memset(&vga_dev, 0, sizeof(vga_dev));
198 	strcpy(vga_dev.name, "vga");
199 	vga_dev.ext   = 0;
200 	vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
201 	vga_dev.putc  = video_putc;        /* 'putc' function */
202 	vga_dev.puts  = video_puts;        /* 'puts' function */
203 	vga_dev.tstc  = NULL;              /* 'tstc' function */
204 	vga_dev.getc  = NULL;              /* 'getc' function */
205 
206 	if (stdio_register(&vga_dev) == 0) {
207 	    return 1;
208 	}
209 
210 	if (i8042_kbd_init()) {
211 		return 1;
212 	}
213 
214 	memset(&kbd_dev, 0, sizeof(kbd_dev));
215 	strcpy(kbd_dev.name, "kbd");
216 	kbd_dev.ext   = 0;
217 	kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
218 	kbd_dev.putc  = NULL;        /* 'putc' function */
219 	kbd_dev.puts  = NULL;        /* 'puts' function */
220 	kbd_dev.tstc  = i8042_tstc;  /* 'tstc' function */
221 	kbd_dev.getc  = i8042_getc;  /* 'getc' function */
222 
223 	if (stdio_register(&kbd_dev) == 0) {
224 	    return 1;
225 	}
226 	return 0;
227 }
228 
229 
drv_video_init(void)230 int drv_video_init(void)
231 {
232 	if (video_bios_init()) {
233 		return 1;
234 	}
235 
236 	return video_init();
237 }
238