]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/x86/lib/video.c
b29075c490a48ce14e3c3c485fdb21bbcc198172
[people/ms/u-boot.git] / arch / x86 / lib / video.c
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 /* basic textmode I/O from linux kernel */
34 static char *vidmem = (char *)0xb8000;
35 static int vidport;
36 static int lines, cols;
37 static int orig_x, orig_y;
38
39 static void beep(int dur)
40 {
41 int i;
42
43 outb_p(3, 0x61);
44 for (i = 0; i < 10*dur; i++)
45 udelay(1000);
46
47 outb_p(0, 0x61);
48 }
49
50 static void scroll(void)
51 {
52 int i;
53
54 memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
55 for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
56 vidmem[i] = ' ';
57 }
58
59 static void __video_putc(const char c, int *x, int *y)
60 {
61 if (c == '\n') {
62 (*x) = 0;
63 if (++(*y) >= lines) {
64 scroll();
65 (*y)--;
66 }
67 } else if (c == '\b') {
68 if ((*x) != 0) {
69 --(*x);
70 vidmem[((*x) + cols * (*y)) * 2] = ' ';
71 }
72 } else if (c == '\r') {
73 (*x) = 0;
74
75 } else if (c == '\a') {
76 beep(3);
77
78 } else if (c == '\t') {
79 __video_putc(' ', x, y);
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 } else if (c == '\v') {
88 switch ((*x) % 8) {
89 case 0:
90 __video_putc(' ', x, y);
91 case 7:
92 __video_putc(' ', x, y);
93 case 6:
94 __video_putc(' ', x, y);
95 case 5:
96 __video_putc(' ', x, y);
97 case 4:
98 __video_putc(' ', x, y);
99 case 3:
100 __video_putc(' ', x, y);
101 case 2:
102 __video_putc(' ', x, y);
103 case 1:
104 __video_putc(' ', x, y);
105 }
106 } else if (c == '\f') {
107 int i;
108 for (i = 0; i < lines * cols * 2; i += 2)
109 vidmem[i] = 0;
110 (*x) = 0;
111 (*y) = 0;
112 } else {
113 vidmem[((*x) + cols * (*y)) * 2] = c;
114 if (++(*x) >= cols) {
115 (*x) = 0;
116 if (++(*y) >= lines) {
117 scroll();
118 (*y)--;
119 }
120 }
121 }
122 }
123
124 static void video_putc(const char c)
125 {
126 int x,y,pos;
127
128 x = orig_x;
129 y = orig_y;
130
131 __video_putc(c, &x, &y);
132
133 orig_x = x;
134 orig_y = y;
135
136 pos = (x + cols * y) * 2; /* Update cursor position */
137 outb_p(14, vidport);
138 outb_p(0xff & (pos >> 9), vidport+1);
139 outb_p(15, vidport);
140 outb_p(0xff & (pos >> 1), vidport+1);
141 }
142
143 static void video_puts(const char *s)
144 {
145 int x,y,pos;
146 char c;
147
148 x = orig_x;
149 y = orig_y;
150
151 while ((c = *s++) != '\0')
152 __video_putc(c, &x, &y);
153
154 orig_x = x;
155 orig_y = y;
156
157 pos = (x + cols * y) * 2; /* Update cursor position */
158 outb_p(14, vidport);
159 outb_p(0xff & (pos >> 9), vidport+1);
160 outb_p(15, vidport);
161 outb_p(0xff & (pos >> 1), vidport+1);
162 }
163
164 int video_init(void)
165 {
166 u16 pos;
167
168 static struct stdio_dev vga_dev;
169 static struct stdio_dev kbd_dev;
170
171 vidmem = (char *) 0xb8000;
172 vidport = 0x3d4;
173
174 lines = 25;
175 cols = 80;
176
177 outb_p(14, vidport);
178 pos = inb_p(vidport+1);
179 pos <<= 8;
180 outb_p(15, vidport);
181 pos |= inb_p(vidport+1);
182
183 orig_x = pos%cols;
184 orig_y = pos/cols;
185
186 #if 0
187 printf("pos %x %d %d\n", pos, orig_x, orig_y);
188 #endif
189 if (orig_y > lines)
190 orig_x = orig_y =0;
191
192 memset(&vga_dev, 0, sizeof(vga_dev));
193 strcpy(vga_dev.name, "vga");
194 vga_dev.ext = 0;
195 vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
196 vga_dev.putc = video_putc; /* 'putc' function */
197 vga_dev.puts = video_puts; /* 'puts' function */
198 vga_dev.tstc = NULL; /* 'tstc' function */
199 vga_dev.getc = NULL; /* 'getc' function */
200
201 if (stdio_register(&vga_dev) == 0)
202 return 1;
203
204 if (i8042_kbd_init())
205 return 1;
206
207 memset(&kbd_dev, 0, sizeof(kbd_dev));
208 strcpy(kbd_dev.name, "kbd");
209 kbd_dev.ext = 0;
210 kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
211 kbd_dev.putc = NULL; /* 'putc' function */
212 kbd_dev.puts = NULL; /* 'puts' function */
213 kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
214 kbd_dev.getc = i8042_getc; /* 'getc' function */
215
216 if (stdio_register(&kbd_dev) == 0)
217 return 1;
218
219 return 0;
220 }
221
222
223 int drv_video_init(void)
224 {
225 if (video_bios_init())
226 return 1;
227
228 return video_init();
229 }