Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* -*- linux-c -*- ------------------------------------------------------- *
0003  *
0004  *   Copyright (C) 1991, 1992 Linus Torvalds
0005  *   Copyright 2007 rPath, Inc. - All Rights Reserved
0006  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
0007  *
0008  * ----------------------------------------------------------------------- */
0009 
0010 /*
0011  * Common all-VGA modes
0012  */
0013 
0014 #include "boot.h"
0015 #include "video.h"
0016 
0017 static struct mode_info vga_modes[] = {
0018     { VIDEO_80x25,  80, 25, 0 },
0019     { VIDEO_8POINT, 80, 50, 0 },
0020     { VIDEO_80x43,  80, 43, 0 },
0021     { VIDEO_80x28,  80, 28, 0 },
0022     { VIDEO_80x30,  80, 30, 0 },
0023     { VIDEO_80x34,  80, 34, 0 },
0024     { VIDEO_80x60,  80, 60, 0 },
0025 };
0026 
0027 static struct mode_info ega_modes[] = {
0028     { VIDEO_80x25,  80, 25, 0 },
0029     { VIDEO_8POINT, 80, 43, 0 },
0030 };
0031 
0032 static struct mode_info cga_modes[] = {
0033     { VIDEO_80x25,  80, 25, 0 },
0034 };
0035 
0036 static __videocard video_vga;
0037 
0038 /* Set basic 80x25 mode */
0039 static u8 vga_set_basic_mode(void)
0040 {
0041     struct biosregs ireg, oreg;
0042     u8 mode;
0043 
0044     initregs(&ireg);
0045 
0046     /* Query current mode */
0047     ireg.ax = 0x0f00;
0048     intcall(0x10, &ireg, &oreg);
0049     mode = oreg.al;
0050 
0051     if (mode != 3 && mode != 7)
0052         mode = 3;
0053 
0054     /* Set the mode */
0055     ireg.ax = mode;     /* AH=0: set mode */
0056     intcall(0x10, &ireg, NULL);
0057     do_restore = 1;
0058     return mode;
0059 }
0060 
0061 static void vga_set_8font(void)
0062 {
0063     /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
0064     struct biosregs ireg;
0065 
0066     initregs(&ireg);
0067 
0068     /* Set 8x8 font */
0069     ireg.ax = 0x1112;
0070     /* ireg.bl = 0; */
0071     intcall(0x10, &ireg, NULL);
0072 
0073     /* Use alternate print screen */
0074     ireg.ax = 0x1200;
0075     ireg.bl = 0x20;
0076     intcall(0x10, &ireg, NULL);
0077 
0078     /* Turn off cursor emulation */
0079     ireg.ax = 0x1201;
0080     ireg.bl = 0x34;
0081     intcall(0x10, &ireg, NULL);
0082 
0083     /* Cursor is scan lines 6-7 */
0084     ireg.ax = 0x0100;
0085     ireg.cx = 0x0607;
0086     intcall(0x10, &ireg, NULL);
0087 }
0088 
0089 static void vga_set_14font(void)
0090 {
0091     /* Set 9x14 font - 80x28 on VGA */
0092     struct biosregs ireg;
0093 
0094     initregs(&ireg);
0095 
0096     /* Set 9x14 font */
0097     ireg.ax = 0x1111;
0098     /* ireg.bl = 0; */
0099     intcall(0x10, &ireg, NULL);
0100 
0101     /* Turn off cursor emulation */
0102     ireg.ax = 0x1201;
0103     ireg.bl = 0x34;
0104     intcall(0x10, &ireg, NULL);
0105 
0106     /* Cursor is scan lines 11-12 */
0107     ireg.ax = 0x0100;
0108     ireg.cx = 0x0b0c;
0109     intcall(0x10, &ireg, NULL);
0110 }
0111 
0112 static void vga_set_80x43(void)
0113 {
0114     /* Set 80x43 mode on VGA (not EGA) */
0115     struct biosregs ireg;
0116 
0117     initregs(&ireg);
0118 
0119     /* Set 350 scans */
0120     ireg.ax = 0x1201;
0121     ireg.bl = 0x30;
0122     intcall(0x10, &ireg, NULL);
0123 
0124     /* Reset video mode */
0125     ireg.ax = 0x0003;
0126     intcall(0x10, &ireg, NULL);
0127 
0128     vga_set_8font();
0129 }
0130 
0131 /* I/O address of the VGA CRTC */
0132 u16 vga_crtc(void)
0133 {
0134     return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
0135 }
0136 
0137 static void vga_set_480_scanlines(void)
0138 {
0139     u16 crtc;       /* CRTC base address */
0140     u8  csel;       /* CRTC miscellaneous output register */
0141 
0142     crtc = vga_crtc();
0143 
0144     out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
0145     out_idx(0x0b, crtc, 0x06); /* Vertical total */
0146     out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
0147     out_idx(0xea, crtc, 0x10); /* Vertical sync start */
0148     out_idx(0xdf, crtc, 0x12); /* Vertical display end */
0149     out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
0150     out_idx(0x04, crtc, 0x16); /* Vertical blank end */
0151     csel = inb(0x3cc);
0152     csel &= 0x0d;
0153     csel |= 0xe2;
0154     outb(csel, 0x3c2);
0155 }
0156 
0157 static void vga_set_vertical_end(int lines)
0158 {
0159     u16 crtc;       /* CRTC base address */
0160     u8  ovfw;       /* CRTC overflow register */
0161     int end = lines-1;
0162 
0163     crtc = vga_crtc();
0164 
0165     ovfw = 0x3c | ((end >> (8-1)) & 0x02) | ((end >> (9-6)) & 0x40);
0166 
0167     out_idx(ovfw, crtc, 0x07); /* Vertical overflow */
0168     out_idx(end,  crtc, 0x12); /* Vertical display end */
0169 }
0170 
0171 static void vga_set_80x30(void)
0172 {
0173     vga_set_480_scanlines();
0174     vga_set_vertical_end(30*16);
0175 }
0176 
0177 static void vga_set_80x34(void)
0178 {
0179     vga_set_480_scanlines();
0180     vga_set_14font();
0181     vga_set_vertical_end(34*14);
0182 }
0183 
0184 static void vga_set_80x60(void)
0185 {
0186     vga_set_480_scanlines();
0187     vga_set_8font();
0188     vga_set_vertical_end(60*8);
0189 }
0190 
0191 static int vga_set_mode(struct mode_info *mode)
0192 {
0193     /* Set the basic mode */
0194     vga_set_basic_mode();
0195 
0196     /* Override a possibly broken BIOS */
0197     force_x = mode->x;
0198     force_y = mode->y;
0199 
0200     switch (mode->mode) {
0201     case VIDEO_80x25:
0202         break;
0203     case VIDEO_8POINT:
0204         vga_set_8font();
0205         break;
0206     case VIDEO_80x43:
0207         vga_set_80x43();
0208         break;
0209     case VIDEO_80x28:
0210         vga_set_14font();
0211         break;
0212     case VIDEO_80x30:
0213         vga_set_80x30();
0214         break;
0215     case VIDEO_80x34:
0216         vga_set_80x34();
0217         break;
0218     case VIDEO_80x60:
0219         vga_set_80x60();
0220         break;
0221     }
0222 
0223     return 0;
0224 }
0225 
0226 /*
0227  * Note: this probe includes basic information required by all
0228  * systems.  It should be executed first, by making sure
0229  * video-vga.c is listed first in the Makefile.
0230  */
0231 static int vga_probe(void)
0232 {
0233     static const char *card_name[] = {
0234         "CGA/MDA/HGC", "EGA", "VGA"
0235     };
0236     static struct mode_info *mode_lists[] = {
0237         cga_modes,
0238         ega_modes,
0239         vga_modes,
0240     };
0241     static int mode_count[] = {
0242         ARRAY_SIZE(cga_modes),
0243         ARRAY_SIZE(ega_modes),
0244         ARRAY_SIZE(vga_modes),
0245     };
0246 
0247     struct biosregs ireg, oreg;
0248 
0249     initregs(&ireg);
0250 
0251     ireg.ax = 0x1200;
0252     ireg.bl = 0x10;     /* Check EGA/VGA */
0253     intcall(0x10, &ireg, &oreg);
0254 
0255 #ifndef _WAKEUP
0256     boot_params.screen_info.orig_video_ega_bx = oreg.bx;
0257 #endif
0258 
0259     /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
0260     if (oreg.bl != 0x10) {
0261         /* EGA/VGA */
0262         ireg.ax = 0x1a00;
0263         intcall(0x10, &ireg, &oreg);
0264 
0265         if (oreg.al == 0x1a) {
0266             adapter = ADAPTER_VGA;
0267 #ifndef _WAKEUP
0268             boot_params.screen_info.orig_video_isVGA = 1;
0269 #endif
0270         } else {
0271             adapter = ADAPTER_EGA;
0272         }
0273     } else {
0274         adapter = ADAPTER_CGA;
0275     }
0276 
0277     video_vga.modes = mode_lists[adapter];
0278     video_vga.card_name = card_name[adapter];
0279     return mode_count[adapter];
0280 }
0281 
0282 static __videocard video_vga = {
0283     .card_name  = "VGA",
0284     .probe      = vga_probe,
0285     .set_mode   = vga_set_mode,
0286 };