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 *
   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 * Standard video BIOS modes
  13 *
  14 * We have two options for this; silent and scanned.
  15 */
  16
  17#include "boot.h"
  18#include "video.h"
  19
  20static __videocard video_bios;
  21
  22/* Set a conventional BIOS mode */
  23static int set_bios_mode(u8 mode);
  24
  25static int bios_set_mode(struct mode_info *mi)
  26{
  27        return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
  28}
  29
  30static int set_bios_mode(u8 mode)
  31{
  32        u16 ax;
  33        u8 new_mode;
  34
  35        ax = mode;              /* AH=0x00 Set Video Mode */
  36        asm volatile(INT10
  37                     : "+a" (ax)
  38                     : : "ebx", "ecx", "edx", "esi", "edi");
  39
  40        ax = 0x0f00;            /* Get Current Video Mode */
  41        asm volatile(INT10
  42                     : "+a" (ax)
  43                     : : "ebx", "ecx", "edx", "esi", "edi");
  44
  45        do_restore = 1;         /* Assume video contents were lost */
  46        new_mode = ax & 0x7f;   /* Not all BIOSes are clean with the top bit */
  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                ax = boot_params.screen_info.orig_video_mode;
  57                asm volatile(INT10
  58                             : "+a" (ax)
  59                             : : "ebx", "ecx", "edx", "esi", "edi");
  60        }
  61#endif
  62        return -1;
  63}
  64
  65static int bios_probe(void)
  66{
  67        u8 mode;
  68#ifdef _WAKEUP
  69        u8 saved_mode = 0x03;
  70#else
  71        u8 saved_mode = boot_params.screen_info.orig_video_mode;
  72#endif
  73        u16 crtc;
  74        struct mode_info *mi;
  75        int nmodes = 0;
  76
  77        if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
  78                return 0;
  79
  80        set_fs(0);
  81        crtc = vga_crtc();
  82
  83        video_bios.modes = GET_HEAP(struct mode_info, 0);
  84
  85        for (mode = 0x14; mode <= 0x7f; mode++) {
  86                if (!heap_free(sizeof(struct mode_info)))
  87                        break;
  88
  89                if (mode_defined(VIDEO_FIRST_BIOS+mode))
  90                        continue;
  91
  92                if (set_bios_mode(mode))
  93                        continue;
  94
  95                /* Try to verify that it's a text mode. */
  96
  97                /* Attribute Controller: make graphics controller disabled */
  98                if (in_idx(0x3c0, 0x10) & 0x01)
  99                        continue;
 100
 101                /* Graphics Controller: verify Alpha addressing enabled */
 102                if (in_idx(0x3ce, 0x06) & 0x01)
 103                        continue;
 104
 105                /* CRTC cursor location low should be zero(?) */
 106                if (in_idx(crtc, 0x0f))
 107                        continue;
 108
 109                mi = GET_HEAP(struct mode_info, 1);
 110                mi->mode = VIDEO_FIRST_BIOS+mode;
 111                mi->depth = 0;  /* text */
 112                mi->x = rdfs16(0x44a);
 113                mi->y = rdfs8(0x484)+1;
 114                nmodes++;
 115        }
 116
 117        set_bios_mode(saved_mode);
 118
 119        return nmodes;
 120}
 121
 122static __videocard video_bios =
 123{
 124        .card_name      = "BIOS",
 125        .probe          = bios_probe,
 126        .set_mode       = bios_set_mode,
 127        .unsafe         = 1,
 128        .xmode_first    = VIDEO_FIRST_BIOS,
 129        .xmode_n        = 0x80,
 130};
 131