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