linux/arch/x86/boot/video-bios.c
<<
>>
Prefs
   1/* -*- linux-c -*- ------------------------------------------------------- *
   2 *
   3 *   Copyright (C) 1991, 1992 Linus Torvalds
   4 *   Copyright 2007 rPath, Inc. - All Rights Reserved
   5 *   Copyright 2009 Intel Corporation; author H. Peter Anvin
   6 *
   7 *   This file is part of the Linux kernel, and is made available under
   8 *   the terms of the GNU General Public License version 2.
   9 *
  10 * ----------------------------------------------------------------------- */
  11
  12/*
  13 * Standard video BIOS modes
  14 *
  15 * We have two options for this; silent and scanned.
  16 */
  17
  18#include "boot.h"
  19#include "video.h"
  20
  21static __videocard video_bios;
  22
  23/* Set a conventional BIOS mode */
  24static int set_bios_mode(u8 mode);
  25
  26static int bios_set_mode(struct mode_info *mi)
  27{
  28        return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
  29}
  30
  31static int set_bios_mode(u8 mode)
  32{
  33        struct biosregs ireg, oreg;
  34        u8 new_mode;
  35
  36        initregs(&ireg);
  37        ireg.al = mode;         /* AH=0x00 Set Video Mode */
  38        intcall(0x10, &ireg, NULL);
  39
  40        ireg.ah = 0x0f;         /* Get Current Video Mode */
  41        intcall(0x10, &ireg, &oreg);
  42
  43        do_restore = 1;         /* Assume video contents were lost */
  44
  45        /* Not all BIOSes are clean with the top bit */
  46        new_mode = oreg.al & 0x7f;
  47
  48        if (new_mode == mode)
  49                return 0;       /* Mode change OK */
  50
  51#ifndef _WAKEUP
  52        if (new_mode != boot_params.screen_info.orig_video_mode) {
  53                /* Mode setting failed, but we didn't end up where we
  54                   started.  That's bad.  Try to revert to the original
  55                   video mode. */
  56                ireg.ax = boot_params.screen_info.orig_video_mode;
  57                intcall(0x10, &ireg, NULL);
  58        }
  59#endif
  60        return -1;
  61}
  62
  63static int bios_probe(void)
  64{
  65        u8 mode;
  66#ifdef _WAKEUP
  67        u8 saved_mode = 0x03;
  68#else
  69        u8 saved_mode = boot_params.screen_info.orig_video_mode;
  70#endif
  71        u16 crtc;
  72        struct mode_info *mi;
  73        int nmodes = 0;
  74
  75        if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
  76                return 0;
  77
  78        set_fs(0);
  79        crtc = vga_crtc();
  80
  81        video_bios.modes = GET_HEAP(struct mode_info, 0);
  82
  83        for (mode = 0x14; mode <= 0x7f; mode++) {
  84                if (!heap_free(sizeof(struct mode_info)))
  85                        break;
  86
  87                if (mode_defined(VIDEO_FIRST_BIOS+mode))
  88                        continue;
  89
  90                if (set_bios_mode(mode))
  91                        continue;
  92
  93                /* Try to verify that it's a text mode. */
  94
  95                /* Attribute Controller: make graphics controller disabled */
  96                if (in_idx(0x3c0, 0x10) & 0x01)
  97                        continue;
  98
  99                /* Graphics Controller: verify Alpha addressing enabled */
 100                if (in_idx(0x3ce, 0x06) & 0x01)
 101                        continue;
 102
 103                /* CRTC cursor location low should be zero(?) */
 104                if (in_idx(crtc, 0x0f))
 105                        continue;
 106
 107                mi = GET_HEAP(struct mode_info, 1);
 108                mi->mode = VIDEO_FIRST_BIOS+mode;
 109                mi->depth = 0;  /* text */
 110                mi->x = rdfs16(0x44a);
 111                mi->y = rdfs8(0x484)+1;
 112                nmodes++;
 113        }
 114
 115        set_bios_mode(saved_mode);
 116
 117        return nmodes;
 118}
 119
 120static __videocard video_bios =
 121{
 122        .card_name      = "BIOS",
 123        .probe          = bios_probe,
 124        .set_mode       = bios_set_mode,
 125        .unsafe         = 1,
 126        .xmode_first    = VIDEO_FIRST_BIOS,
 127        .xmode_n        = 0x80,
 128};
 129