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 21 static __videocard video_bios; 22 23 /* Set a conventional BIOS mode */ 24 static int set_bios_mode(u8 mode); 25 26 static int bios_set_mode(struct mode_info *mi) 27 { 28 return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS); 29 } 30 31 static 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 63 static 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 120 static __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