root/arch/x86/boot/video-mode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. probe_cards
  2. mode_defined
  3. raw_set_mode
  4. vga_recalc_vertical
  5. set_mode

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* -*- linux-c -*- ------------------------------------------------------- *
   3  *
   4  *   Copyright (C) 1991, 1992 Linus Torvalds
   5  *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
   6  *
   7  * ----------------------------------------------------------------------- */
   8 
   9 /*
  10  * arch/i386/boot/video-mode.c
  11  *
  12  * Set the video mode.  This is separated out into a different
  13  * file in order to be shared with the ACPI wakeup code.
  14  */
  15 
  16 #include "boot.h"
  17 #include "video.h"
  18 #include "vesa.h"
  19 
  20 #include <uapi/asm/boot.h>
  21 
  22 /*
  23  * Common variables
  24  */
  25 int adapter;            /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
  26 int force_x, force_y;   /* Don't query the BIOS for cols/rows */
  27 int do_restore;         /* Screen contents changed during mode flip */
  28 int graphic_mode;       /* Graphic mode with linear frame buffer */
  29 
  30 /* Probe the video drivers and have them generate their mode lists. */
  31 void probe_cards(int unsafe)
  32 {
  33         struct card_info *card;
  34         static u8 probed[2];
  35 
  36         if (probed[unsafe])
  37                 return;
  38 
  39         probed[unsafe] = 1;
  40 
  41         for (card = video_cards; card < video_cards_end; card++) {
  42                 if (card->unsafe == unsafe) {
  43                         if (card->probe)
  44                                 card->nmodes = card->probe();
  45                         else
  46                                 card->nmodes = 0;
  47                 }
  48         }
  49 }
  50 
  51 /* Test if a mode is defined */
  52 int mode_defined(u16 mode)
  53 {
  54         struct card_info *card;
  55         struct mode_info *mi;
  56         int i;
  57 
  58         for (card = video_cards; card < video_cards_end; card++) {
  59                 mi = card->modes;
  60                 for (i = 0; i < card->nmodes; i++, mi++) {
  61                         if (mi->mode == mode)
  62                                 return 1;
  63                 }
  64         }
  65 
  66         return 0;
  67 }
  68 
  69 /* Set mode (without recalc) */
  70 static int raw_set_mode(u16 mode, u16 *real_mode)
  71 {
  72         int nmode, i;
  73         struct card_info *card;
  74         struct mode_info *mi;
  75 
  76         /* Drop the recalc bit if set */
  77         mode &= ~VIDEO_RECALC;
  78 
  79         /* Scan for mode based on fixed ID, position, or resolution */
  80         nmode = 0;
  81         for (card = video_cards; card < video_cards_end; card++) {
  82                 mi = card->modes;
  83                 for (i = 0; i < card->nmodes; i++, mi++) {
  84                         int visible = mi->x || mi->y;
  85 
  86                         if ((mode == nmode && visible) ||
  87                             mode == mi->mode ||
  88                             mode == (mi->y << 8)+mi->x) {
  89                                 *real_mode = mi->mode;
  90                                 return card->set_mode(mi);
  91                         }
  92 
  93                         if (visible)
  94                                 nmode++;
  95                 }
  96         }
  97 
  98         /* Nothing found?  Is it an "exceptional" (unprobed) mode? */
  99         for (card = video_cards; card < video_cards_end; card++) {
 100                 if (mode >= card->xmode_first &&
 101                     mode < card->xmode_first+card->xmode_n) {
 102                         struct mode_info mix;
 103                         *real_mode = mix.mode = mode;
 104                         mix.x = mix.y = 0;
 105                         return card->set_mode(&mix);
 106                 }
 107         }
 108 
 109         /* Otherwise, failure... */
 110         return -1;
 111 }
 112 
 113 /*
 114  * Recalculate the vertical video cutoff (hack!)
 115  */
 116 static void vga_recalc_vertical(void)
 117 {
 118         unsigned int font_size, rows;
 119         u16 crtc;
 120         u8 pt, ov;
 121 
 122         set_fs(0);
 123         font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
 124         rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
 125 
 126         rows *= font_size;      /* Visible scan lines */
 127         rows--;                 /* ... minus one */
 128 
 129         crtc = vga_crtc();
 130 
 131         pt = in_idx(crtc, 0x11);
 132         pt &= ~0x80;            /* Unlock CR0-7 */
 133         out_idx(pt, crtc, 0x11);
 134 
 135         out_idx((u8)rows, crtc, 0x12); /* Lower height register */
 136 
 137         ov = in_idx(crtc, 0x07); /* Overflow register */
 138         ov &= 0xbd;
 139         ov |= (rows >> (8-1)) & 0x02;
 140         ov |= (rows >> (9-6)) & 0x40;
 141         out_idx(ov, crtc, 0x07);
 142 }
 143 
 144 /* Set mode (with recalc if specified) */
 145 int set_mode(u16 mode)
 146 {
 147         int rv;
 148         u16 real_mode;
 149 
 150         /* Very special mode numbers... */
 151         if (mode == VIDEO_CURRENT_MODE)
 152                 return 0;       /* Nothing to do... */
 153         else if (mode == NORMAL_VGA)
 154                 mode = VIDEO_80x25;
 155         else if (mode == EXTENDED_VGA)
 156                 mode = VIDEO_8POINT;
 157 
 158         rv = raw_set_mode(mode, &real_mode);
 159         if (rv)
 160                 return rv;
 161 
 162         if (mode & VIDEO_RECALC)
 163                 vga_recalc_vertical();
 164 
 165         /* Save the canonical mode number for the kernel, not
 166            an alias, size specification or menu position */
 167 #ifndef _WAKEUP
 168         boot_params.hdr.vid_mode = real_mode;
 169 #endif
 170         return 0;
 171 }

/* [<][>][^][v][top][bottom][index][help] */