]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/x86/lib/video.c
Merge 'u-boot-atmel/master' into 'u-boot-arm/master'
[karo-tx-uboot.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 #ifndef CONFIG_X86_NO_REAL_MODE
226         if (video_bios_init())
227                 return 1;
228 #endif
229
230         return video_init();
231 }