aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/boot/video-vga.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-07-11 15:18:52 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 13:55:55 -0400
commit5e8ddcbe8692ca9854991c6875d302fa7e424e3c (patch)
tree31264c71e36c34ce24db9f26ac2f6384dbd75790 /arch/i386/boot/video-vga.c
parent337496eb73ec970fe008095fdb2b2af60a2a7fa3 (diff)
Video mode probing support for the new x86 setup code
Video mode probing for the new x86 setup code. This code breaks down different drivers into modules. This code deliberately drops support for a lot of the vendor-specific mode probing present in the assembly version, since a lot of those probes have been found to be stale in current versions of those chips -- frequently, support for those modes have been dropped from recent video BIOSes due to space constraints, but the video BIOS signatures are still the same. However, additional drivers should be extremely straightforward to plug in, if desirable. Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/boot/video-vga.c')
-rw-r--r--arch/i386/boot/video-vga.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c
new file mode 100644
index 000000000000..700d09a9c9b3
--- /dev/null
+++ b/arch/i386/boot/video-vga.c
@@ -0,0 +1,260 @@
1/* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright 2007 rPath, Inc. - All Rights Reserved
5 *
6 * This file is part of the Linux kernel, and is made available under
7 * the terms of the GNU General Public License version 2.
8 *
9 * ----------------------------------------------------------------------- */
10
11/*
12 * arch/i386/boot/video-vga.c
13 *
14 * Common all-VGA modes
15 */
16
17#include "boot.h"
18#include "video.h"
19
20static struct mode_info vga_modes[] = {
21 { VIDEO_80x25, 80, 25 },
22 { VIDEO_8POINT, 80, 50 },
23 { VIDEO_80x43, 80, 43 },
24 { VIDEO_80x28, 80, 28 },
25 { VIDEO_80x30, 80, 30 },
26 { VIDEO_80x34, 80, 34 },
27 { VIDEO_80x60, 80, 60 },
28};
29
30static struct mode_info ega_modes[] = {
31 { VIDEO_80x25, 80, 25 },
32 { VIDEO_8POINT, 80, 43 },
33};
34
35static struct mode_info cga_modes[] = {
36 { VIDEO_80x25, 80, 25 },
37};
38
39__videocard video_vga;
40
41/* Set basic 80x25 mode */
42static u8 vga_set_basic_mode(void)
43{
44 u16 ax;
45 u8 rows;
46 u8 mode;
47
48#ifdef CONFIG_VIDEO_400_HACK
49 if (adapter >= ADAPTER_VGA) {
50 asm(INT10
51 : : "a" (0x1202), "b" (0x0030)
52 : "ecx", "edx", "esi", "edi");
53 }
54#endif
55
56 ax = 0x0f00;
57 asm(INT10
58 : "+a" (ax)
59 : : "ebx", "ecx", "edx", "esi", "edi");
60
61 mode = (u8)ax;
62
63 set_fs(0);
64 rows = rdfs8(0x484); /* rows minus one */
65
66#ifndef CONFIG_VIDEO_400_HACK
67 if ((ax == 0x5003 || ax == 0x5007) &&
68 (rows == 0 || rows == 24))
69 return mode;
70#endif
71
72 if (mode != 3 && mode != 7)
73 mode = 3;
74
75 /* Set the mode */
76 asm volatile(INT10
77 : : "a" (mode)
78 : "ebx", "ecx", "edx", "esi", "edi");
79 do_restore = 1;
80 return mode;
81}
82
83static void vga_set_8font(void)
84{
85 /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
86
87 /* Set 8x8 font */
88 asm volatile(INT10 : : "a" (0x1112), "b" (0));
89
90 /* Use alternate print screen */
91 asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
92
93 /* Turn off cursor emulation */
94 asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
95
96 /* Cursor is scan lines 6-7 */
97 asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
98}
99
100static void vga_set_14font(void)
101{
102 /* Set 9x14 font - 80x28 on VGA */
103
104 /* Set 9x14 font */
105 asm volatile(INT10 : : "a" (0x1111), "b" (0));
106
107 /* Turn off cursor emulation */
108 asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
109
110 /* Cursor is scan lines 11-12 */
111 asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
112}
113
114static void vga_set_80x43(void)
115{
116 /* Set 80x43 mode on VGA (not EGA) */
117
118 /* Set 350 scans */
119 asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
120
121 /* Reset video mode */
122 asm volatile(INT10 : : "a" (0x0003));
123
124 vga_set_8font();
125}
126
127/* I/O address of the VGA CRTC */
128u16 vga_crtc(void)
129{
130 return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
131}
132
133static void vga_set_480_scanlines(int end)
134{
135 u16 crtc;
136 u8 csel;
137
138 crtc = vga_crtc();
139
140 out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
141 out_idx(0x0b, crtc, 0x06); /* Vertical total */
142 out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
143 out_idx(0xea, crtc, 0x10); /* Vertical sync start */
144 out_idx(end, crtc, 0x12); /* Vertical display end */
145 out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
146 out_idx(0x04, crtc, 0x16); /* Vertical blank end */
147 csel = inb(0x3cc);
148 csel &= 0x0d;
149 csel |= 0xe2;
150 outb(csel, 0x3cc);
151}
152
153static void vga_set_80x30(void)
154{
155 vga_set_480_scanlines(0xdf);
156}
157
158static void vga_set_80x34(void)
159{
160 vga_set_14font();
161 vga_set_480_scanlines(0xdb);
162}
163
164static void vga_set_80x60(void)
165{
166 vga_set_8font();
167 vga_set_480_scanlines(0xdf);
168}
169
170static int vga_set_mode(struct mode_info *mode)
171{
172 /* Set the basic mode */
173 vga_set_basic_mode();
174
175 /* Override a possibly broken BIOS */
176 force_x = mode->x;
177 force_y = mode->y;
178
179 switch (mode->mode) {
180 case VIDEO_80x25:
181 break;
182 case VIDEO_8POINT:
183 vga_set_8font();
184 break;
185 case VIDEO_80x43:
186 vga_set_80x43();
187 break;
188 case VIDEO_80x28:
189 vga_set_14font();
190 break;
191 case VIDEO_80x30:
192 vga_set_80x30();
193 break;
194 case VIDEO_80x34:
195 vga_set_80x34();
196 break;
197 case VIDEO_80x60:
198 vga_set_80x60();
199 break;
200 }
201
202 return 0;
203}
204
205/*
206 * Note: this probe includes basic information required by all
207 * systems. It should be executed first, by making sure
208 * video-vga.c is listed first in the Makefile.
209 */
210static int vga_probe(void)
211{
212 static const char *card_name[] = {
213 "CGA/MDA/HGC", "EGA", "VGA"
214 };
215 static struct mode_info *mode_lists[] = {
216 cga_modes,
217 ega_modes,
218 vga_modes,
219 };
220 static int mode_count[] = {
221 sizeof(cga_modes)/sizeof(struct mode_info),
222 sizeof(ega_modes)/sizeof(struct mode_info),
223 sizeof(vga_modes)/sizeof(struct mode_info),
224 };
225 u8 vga_flag;
226
227 asm(INT10
228 : "=b" (boot_params.screen_info.orig_video_ega_bx)
229 : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
230 : "ecx", "edx", "esi", "edi");
231
232 /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
233 if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
234 /* EGA/VGA */
235 asm(INT10
236 : "=a" (vga_flag)
237 : "a" (0x1a00)
238 : "ebx", "ecx", "edx", "esi", "edi");
239
240 if (vga_flag == 0x1a) {
241 adapter = ADAPTER_VGA;
242 boot_params.screen_info.orig_video_isVGA = 1;
243 } else {
244 adapter = ADAPTER_EGA;
245 }
246 } else {
247 adapter = ADAPTER_CGA;
248 }
249
250 video_vga.modes = mode_lists[adapter];
251 video_vga.card_name = card_name[adapter];
252 return mode_count[adapter];
253}
254
255__videocard video_vga =
256{
257 .card_name = "VGA",
258 .probe = vga_probe,
259 .set_mode = vga_set_mode,
260};