Refactoring parts of the common USB OHCI code
[kernel/u-boot.git] / lib_i386 / 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 <devices.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
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
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
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
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
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
167 int video_init(void)
168 {
169         u16 pos;
170
171         static device_t vga_dev;
172         static device_t 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 (device_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 (device_register(&kbd_dev) == 0) {
224             return 1;
225         }
226         return 0;
227 }
228
229
230 int drv_video_init(void)
231 {
232         if (video_bios_init()) {
233                 return 1;
234         }
235
236         return video_init();
237 }