Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | /* -*- linux-c -*- ------------------------------------------------------- * * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright 2007 rPath, Inc. - All Rights Reserved * Copyright 2009 Intel Corporation; author H. Peter Anvin * * This file is part of the Linux kernel, and is made available under * the terms of the GNU General Public License version 2. * * ----------------------------------------------------------------------- */ /* * Common all-VGA modes */ #include "boot.h" #include "video.h" static struct mode_info vga_modes[] = { { VIDEO_80x25, 80, 25, 0 }, { VIDEO_8POINT, 80, 50, 0 }, { VIDEO_80x43, 80, 43, 0 }, { VIDEO_80x28, 80, 28, 0 }, { VIDEO_80x30, 80, 30, 0 }, { VIDEO_80x34, 80, 34, 0 }, { VIDEO_80x60, 80, 60, 0 }, }; static struct mode_info ega_modes[] = { { VIDEO_80x25, 80, 25, 0 }, { VIDEO_8POINT, 80, 43, 0 }, }; static struct mode_info cga_modes[] = { { VIDEO_80x25, 80, 25, 0 }, }; static __videocard video_vga; /* Set basic 80x25 mode */ static u8 vga_set_basic_mode(void) { struct biosregs ireg, oreg; u8 mode; initregs(&ireg); /* Query current mode */ ireg.ax = 0x0f00; intcall(0x10, &ireg, &oreg); mode = oreg.al; if (mode != 3 && mode != 7) mode = 3; /* Set the mode */ ireg.ax = mode; /* AH=0: set mode */ intcall(0x10, &ireg, NULL); do_restore = 1; return mode; } static void vga_set_8font(void) { /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ struct biosregs ireg; initregs(&ireg); /* Set 8x8 font */ ireg.ax = 0x1112; /* ireg.bl = 0; */ intcall(0x10, &ireg, NULL); /* Use alternate print screen */ ireg.ax = 0x1200; ireg.bl = 0x20; intcall(0x10, &ireg, NULL); /* Turn off cursor emulation */ ireg.ax = 0x1201; ireg.bl = 0x34; intcall(0x10, &ireg, NULL); /* Cursor is scan lines 6-7 */ ireg.ax = 0x0100; ireg.cx = 0x0607; intcall(0x10, &ireg, NULL); } static void vga_set_14font(void) { /* Set 9x14 font - 80x28 on VGA */ struct biosregs ireg; initregs(&ireg); /* Set 9x14 font */ ireg.ax = 0x1111; /* ireg.bl = 0; */ intcall(0x10, &ireg, NULL); /* Turn off cursor emulation */ ireg.ax = 0x1201; ireg.bl = 0x34; intcall(0x10, &ireg, NULL); /* Cursor is scan lines 11-12 */ ireg.ax = 0x0100; ireg.cx = 0x0b0c; intcall(0x10, &ireg, NULL); } static void vga_set_80x43(void) { /* Set 80x43 mode on VGA (not EGA) */ struct biosregs ireg; initregs(&ireg); /* Set 350 scans */ ireg.ax = 0x1201; ireg.bl = 0x30; intcall(0x10, &ireg, NULL); /* Reset video mode */ ireg.ax = 0x0003; intcall(0x10, &ireg, NULL); vga_set_8font(); } /* I/O address of the VGA CRTC */ u16 vga_crtc(void) { return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4; } static void vga_set_480_scanlines(void) { u16 crtc; /* CRTC base address */ u8 csel; /* CRTC miscellaneous output register */ crtc = vga_crtc(); out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */ out_idx(0x0b, crtc, 0x06); /* Vertical total */ out_idx(0x3e, crtc, 0x07); /* Vertical overflow */ out_idx(0xea, crtc, 0x10); /* Vertical sync start */ out_idx(0xdf, crtc, 0x12); /* Vertical display end */ out_idx(0xe7, crtc, 0x15); /* Vertical blank start */ out_idx(0x04, crtc, 0x16); /* Vertical blank end */ csel = inb(0x3cc); csel &= 0x0d; csel |= 0xe2; outb(csel, 0x3c2); } static void vga_set_vertical_end(int lines) { u16 crtc; /* CRTC base address */ u8 ovfw; /* CRTC overflow register */ int end = lines-1; crtc = vga_crtc(); ovfw = 0x3c | ((end >> (8-1)) & 0x02) | ((end >> (9-6)) & 0x40); out_idx(ovfw, crtc, 0x07); /* Vertical overflow */ out_idx(end, crtc, 0x12); /* Vertical display end */ } static void vga_set_80x30(void) { vga_set_480_scanlines(); vga_set_vertical_end(30*16); } static void vga_set_80x34(void) { vga_set_480_scanlines(); vga_set_14font(); vga_set_vertical_end(34*14); } static void vga_set_80x60(void) { vga_set_480_scanlines(); vga_set_8font(); vga_set_vertical_end(60*8); } static int vga_set_mode(struct mode_info *mode) { /* Set the basic mode */ vga_set_basic_mode(); /* Override a possibly broken BIOS */ force_x = mode->x; force_y = mode->y; switch (mode->mode) { case VIDEO_80x25: break; case VIDEO_8POINT: vga_set_8font(); break; case VIDEO_80x43: vga_set_80x43(); break; case VIDEO_80x28: vga_set_14font(); break; case VIDEO_80x30: vga_set_80x30(); break; case VIDEO_80x34: vga_set_80x34(); break; case VIDEO_80x60: vga_set_80x60(); break; } return 0; } /* * Note: this probe includes basic information required by all * systems. It should be executed first, by making sure * video-vga.c is listed first in the Makefile. */ static int vga_probe(void) { static const char *card_name[] = { "CGA/MDA/HGC", "EGA", "VGA" }; static struct mode_info *mode_lists[] = { cga_modes, ega_modes, vga_modes, }; static int mode_count[] = { ARRAY_SIZE(cga_modes), ARRAY_SIZE(ega_modes), ARRAY_SIZE(vga_modes), }; struct biosregs ireg, oreg; initregs(&ireg); ireg.ax = 0x1200; ireg.bl = 0x10; /* Check EGA/VGA */ intcall(0x10, &ireg, &oreg); #ifndef _WAKEUP boot_params.screen_info.orig_video_ega_bx = oreg.bx; #endif /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ if (oreg.bl != 0x10) { /* EGA/VGA */ ireg.ax = 0x1a00; intcall(0x10, &ireg, &oreg); if (oreg.al == 0x1a) { adapter = ADAPTER_VGA; #ifndef _WAKEUP boot_params.screen_info.orig_video_isVGA = 1; #endif } else { adapter = ADAPTER_EGA; } } else { adapter = ADAPTER_CGA; } video_vga.modes = mode_lists[adapter]; video_vga.card_name = card_name[adapter]; return mode_count[adapter]; } static __videocard video_vga = { .card_name = "VGA", .probe = vga_probe, .set_mode = vga_set_mode, }; |