[PATCH] fix video console init
[coreboot.git] / payloads / libpayload / drivers / video / video.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <config.h>
31 #include <libpayload.h>
32 #include <video_console.h>
33
34 #ifdef CONFIG_GEODELX_VIDEO_CONSOLE
35 extern struct video_console geodelx_video_console;
36 #endif
37
38 #ifdef CONFIG_VGA_VIDEO_CONSOLE
39 extern struct video_console vga_video_console;
40 #endif
41
42 static struct video_console *console_list[] =
43 {
44 #ifdef CONFIG_GEODELX_VIDEO_CONSOLE
45         &geodelx_video_console,
46 #endif
47 #ifdef CONFIG_VGA_VIDEO_CONSOLE
48         &vga_video_console,
49 #endif
50 };
51
52 static struct video_console *console;
53
54 static int cursorx;
55 static int cursory;
56 static unsigned int cursor_enabled = 1;
57
58 static void video_console_fixup_cursor(void)
59 {
60         if (!cursor_enabled)
61                 return;
62
63         if (cursorx < 0)
64                 cursorx = 0;
65
66         if (cursory < 0)
67                 cursory = 0;
68
69         if (cursorx > VIDEO_COLS) {
70                 cursorx = 0;
71                 cursory++;
72         }
73
74         while(cursory >= VIDEO_ROWS) {
75                 console->scroll_up();
76                 cursory--;
77         }
78
79         if (console && console->set_cursor)
80                 console->set_cursor(cursorx, cursory);
81 }
82
83 void video_console_cursor_enable(int state)
84 {
85         if (console && console->enable_cursor)
86                 console->enable_cursor(state);
87
88         cursor_enabled = state;
89
90         if (cursor_enabled)
91                 video_console_fixup_cursor();
92 }
93
94 void video_console_clear(void)
95 {
96         if (console)
97                 console->clear();
98
99         cursorx = 0;
100         cursory = 0;
101
102         if (console && console->set_cursor)
103                 console->set_cursor(cursorx, cursory);
104 }
105
106 void video_console_putc(u8 row, u8 col, unsigned int ch)
107 {
108         if (console)
109                 console->putc(row, col, ch);
110 }
111
112 void video_console_putchar(unsigned int ch)
113 {
114         /* replace black-on-black with light-gray-on-black.
115            do it here, instead of in libc/console.c */
116         if ((ch & 0xFF00) == 0) {
117                 ch |= 0x0700;
118         }
119         switch(ch & 0xFF) {
120         case '\r':
121                 cursorx = 0;
122                 break;
123
124         case '\n':
125                 cursory++;
126                 break;
127
128         case '\b':
129                 cursorx--;
130                 if (cursorx < 0) {
131                         cursory--;
132                         cursorx = VIDEO_COLS;
133                 }
134                 break;
135
136         case '\t':
137                 while(cursorx % 8 && cursorx < VIDEO_COLS) {
138                         if (console)
139                                 console->putc(cursory, cursorx, (ch & 0xFF00) | ' ');
140
141                         cursorx++;
142                 }
143                 break;
144         default:
145                 if (console)
146                         console->putc(cursory, cursorx++, ch);
147                 break;
148         }
149
150         video_console_fixup_cursor();
151 }
152
153 void video_console_get_cursor(unsigned int *x, unsigned int *y, unsigned int *en)
154 {
155         *x=0;
156         *y=0;
157         *en=0;
158
159         if (console->get_cursor)
160                 console->get_cursor(x, y, en);
161
162         *x = cursorx;
163         *y = cursory;
164 }
165
166 void video_console_set_cursor(unsigned int x, unsigned int y)
167 {
168         cursorx = x;
169         cursory = y;
170         video_console_fixup_cursor();
171 }
172
173 static struct console_output_driver cons = {
174         .putchar = video_console_putchar
175 };
176
177 int video_console_init(void)
178 {
179                 int i;
180
181                 for(i = 0; i < ARRAY_SIZE(console_list); i++) {
182                         if (console_list[i]->init())
183                                 continue;
184
185                         console = console_list[i];
186
187                         if (console->get_cursor)
188                                 console->get_cursor((unsigned int*)&cursorx, (unsigned int*)&cursory, &cursor_enabled);
189
190                         if (cursorx) {
191                                 cursorx = 0;
192                                 cursory++;
193                         }
194
195                         video_console_fixup_cursor();
196                         console_add_output_driver(&cons);
197                         return 0;
198                 }
199
200                 return 0;
201 }
202