Cosmetics, coding style fixes (trivial).
[coreboot.git] / payloads / libpayload / drivers / vga.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 <arch/types.h>
31 #include <libpayload.h>
32
33 #define WIDTH 80
34 #define HEIGHT 25
35
36 #define VGA_COLOR_WHITE 7
37
38 #define CRTC_INDEX      0x3d4
39 #define CRTC_DATA       0x3d5
40
41 #define VIDEO(_r, _c) \
42         ((uint16_t *) (0xB8000 + ((_r) * (WIDTH * 2)) + ((_c) * 2)))
43
44 static int cursor_enabled;
45 static int cursorx;
46 static int cursory;
47
48 static void vga_scroll_up(void);
49
50 static inline uint8_t crtc_read(uint8_t index)
51 {
52         outb(index, CRTC_INDEX);
53         return inb(CRTC_DATA);
54 }
55
56 static inline void crtc_write(uint8_t data, uint8_t index)
57 {
58         outb(index, CRTC_INDEX);
59         outb(data, CRTC_DATA);
60 }
61
62 static void vga_get_cursor_pos(void)
63 {
64         unsigned int addr;
65
66         addr = ((unsigned int)crtc_read(0x0E)) << 8;
67         addr += crtc_read(0x0E);
68
69         cursorx = addr % WIDTH;
70         cursory = addr / WIDTH;
71 }
72
73 static void vga_fixup_cursor(void)
74 {
75         unsigned int addr;
76
77         if (!cursor_enabled)
78                 return;
79
80         if (cursorx < 0)
81                 cursorx = 0;
82
83         if (cursory < 0)
84                 cursory = 0;
85
86         if (cursorx >= WIDTH) {
87                 cursorx = 0;
88                 cursory++;
89         }
90
91         while (cursory >= HEIGHT)
92                 vga_scroll_up();
93
94         addr = cursorx + (WIDTH * cursory);
95         crtc_write(addr >> 8, 0x0E);
96         crtc_write(addr, 0x0E);
97 }
98
99 void vga_cursor_enable(int state)
100 {
101         unsigned char tmp = crtc_read(0x0a);
102
103         if (state == 0) {
104                 tmp |= (1 << 5);
105                 cursor_enabled = 0;
106         } else {
107                 tmp &= ~(1 << 5);
108                 cursor_enabled = 1;
109                 vga_fixup_cursor();
110         }
111
112         crtc_write(tmp, 0x0a);
113 }
114
115 void vga_clear_line(uint8_t row, uint8_t ch, uint8_t attr)
116 {
117         int col;
118         uint16_t *ptr = VIDEO(0, row);
119
120         for (col = 0; col < WIDTH; col++)
121                 ptr[col] = ((attr & 0xFF) << 8) | (ch & 0xFF);
122 }
123
124 static void vga_scroll_up(void)
125 {
126         uint16_t *src = VIDEO(0, 1);
127         uint16_t *dst = VIDEO(0, 0);
128         int i;
129
130         for (i = 0; i < (HEIGHT - 1) * WIDTH; i++)
131                 *dst++ = *src++;
132
133         vga_clear_line(HEIGHT - 1, ' ', VGA_COLOR_WHITE);
134         cursory--;
135 }
136
137 void vga_fill(uint8_t ch, uint8_t attr)
138 {
139         uint8_t row;
140         for (row = 0; row < HEIGHT; row++)
141                 vga_clear_line(row, ch, attr);
142 }
143
144 void vga_clear(void)
145 {
146         vga_fill(' ', VGA_COLOR_WHITE);
147         vga_move_cursor(0, 0);
148 }
149
150 void vga_putc(uint8_t row, uint8_t col, unsigned int c)
151 {
152         uint16_t *ptr = VIDEO(row, col);
153         *ptr = (uint16_t) (c & 0xFFFF);
154 }
155
156 void vga_putchar(unsigned int ch)
157 {
158
159         uint16_t *ptr;
160
161         switch (ch & 0xFF) {
162         case '\r':
163                 cursorx = 0;
164                 break;
165         case '\n':
166                 cursory++;
167                 break;
168         case '\b':
169                 cursorx--;
170                 ptr = VIDEO(cursory, cursorx);
171                 *ptr = (*ptr & 0xFF00) | ' ';
172                 break;
173         case '\t':
174                 cursorx = (cursorx + 8) & ~7;
175                 break;
176
177         default:
178                 ptr = VIDEO(cursory, cursorx);
179                 *ptr = (uint16_t) (ch & 0xFFFF);
180                 cursorx++;
181                 break;
182         }
183
184         vga_fixup_cursor();
185 }
186
187 int vga_move_cursor(int x, int y)
188 {
189         cursorx = x;
190         cursory = y;
191
192         vga_fixup_cursor();
193 }
194
195 void vga_init(void)
196 {
197         /* Get the position of the cursor. */
198         vga_get_cursor_pos();
199
200         /* See if it currently enabled or not. */
201         cursor_enabled = !(crtc_read(0x0A) & (1 << 5));
202
203         /* If the cursor is enabled, get us to a sane point. */
204         if (cursor_enabled) {
205                 /* Go to the next line. */
206                 if (cursorx) {
207                         cursorx = 0;
208                         cursory++;
209                 }
210                 vga_fixup_cursor();
211         }
212 }