mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 06:18:54 +00:00 
			
		
		
		
	 febe04de3b
			
		
	
	
		febe04de3b
		
	
	
	
	
		
			
			Some intcall() misuses the input biosregs as output in
cf06de7b9c
This fixes the problem vga=ask boot option doesn't show enough modes.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
LKML-Reference: <20090701021307.GA3127@localhost.localdomain>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
		
	
			
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* -*- linux-c -*- ------------------------------------------------------- *
 | |
|  *
 | |
|  *   Copyright (C) 1991, 1992 Linus Torvalds
 | |
|  *   Copyright 2007 rPath, Inc. - All Rights Reserved
 | |
|  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
 | |
|  *
 | |
|  *   This file is part of the Linux kernel, and is made available under
 | |
|  *   the terms of the GNU General Public License version 2.
 | |
|  *
 | |
|  * ----------------------------------------------------------------------- */
 | |
| 
 | |
| /*
 | |
|  * Standard video BIOS modes
 | |
|  *
 | |
|  * We have two options for this; silent and scanned.
 | |
|  */
 | |
| 
 | |
| #include "boot.h"
 | |
| #include "video.h"
 | |
| 
 | |
| static __videocard video_bios;
 | |
| 
 | |
| /* Set a conventional BIOS mode */
 | |
| static int set_bios_mode(u8 mode);
 | |
| 
 | |
| static int bios_set_mode(struct mode_info *mi)
 | |
| {
 | |
| 	return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
 | |
| }
 | |
| 
 | |
| static int set_bios_mode(u8 mode)
 | |
| {
 | |
| 	struct biosregs ireg, oreg;
 | |
| 	u8 new_mode;
 | |
| 
 | |
| 	initregs(&ireg);
 | |
| 	ireg.al = mode;		/* AH=0x00 Set Video Mode */
 | |
| 	intcall(0x10, &ireg, NULL);
 | |
| 
 | |
| 	ireg.ah = 0x0f;		/* Get Current Video Mode */
 | |
| 	intcall(0x10, &ireg, &oreg);
 | |
| 
 | |
| 	do_restore = 1;		/* Assume video contents were lost */
 | |
| 
 | |
| 	/* Not all BIOSes are clean with the top bit */
 | |
| 	new_mode = oreg.al & 0x7f;
 | |
| 
 | |
| 	if (new_mode == mode)
 | |
| 		return 0;	/* Mode change OK */
 | |
| 
 | |
| #ifndef _WAKEUP
 | |
| 	if (new_mode != boot_params.screen_info.orig_video_mode) {
 | |
| 		/* Mode setting failed, but we didn't end up where we
 | |
| 		   started.  That's bad.  Try to revert to the original
 | |
| 		   video mode. */
 | |
| 		ireg.ax = boot_params.screen_info.orig_video_mode;
 | |
| 		intcall(0x10, &ireg, NULL);
 | |
| 	}
 | |
| #endif
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| static int bios_probe(void)
 | |
| {
 | |
| 	u8 mode;
 | |
| #ifdef _WAKEUP
 | |
| 	u8 saved_mode = 0x03;
 | |
| #else
 | |
| 	u8 saved_mode = boot_params.screen_info.orig_video_mode;
 | |
| #endif
 | |
| 	u16 crtc;
 | |
| 	struct mode_info *mi;
 | |
| 	int nmodes = 0;
 | |
| 
 | |
| 	if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
 | |
| 		return 0;
 | |
| 
 | |
| 	set_fs(0);
 | |
| 	crtc = vga_crtc();
 | |
| 
 | |
| 	video_bios.modes = GET_HEAP(struct mode_info, 0);
 | |
| 
 | |
| 	for (mode = 0x14; mode <= 0x7f; mode++) {
 | |
| 		if (!heap_free(sizeof(struct mode_info)))
 | |
| 			break;
 | |
| 
 | |
| 		if (mode_defined(VIDEO_FIRST_BIOS+mode))
 | |
| 			continue;
 | |
| 
 | |
| 		if (set_bios_mode(mode))
 | |
| 			continue;
 | |
| 
 | |
| 		/* Try to verify that it's a text mode. */
 | |
| 
 | |
| 		/* Attribute Controller: make graphics controller disabled */
 | |
| 		if (in_idx(0x3c0, 0x10) & 0x01)
 | |
| 			continue;
 | |
| 
 | |
| 		/* Graphics Controller: verify Alpha addressing enabled */
 | |
| 		if (in_idx(0x3ce, 0x06) & 0x01)
 | |
| 			continue;
 | |
| 
 | |
| 		/* CRTC cursor location low should be zero(?) */
 | |
| 		if (in_idx(crtc, 0x0f))
 | |
| 			continue;
 | |
| 
 | |
| 		mi = GET_HEAP(struct mode_info, 1);
 | |
| 		mi->mode = VIDEO_FIRST_BIOS+mode;
 | |
| 		mi->depth = 0;	/* text */
 | |
| 		mi->x = rdfs16(0x44a);
 | |
| 		mi->y = rdfs8(0x484)+1;
 | |
| 		nmodes++;
 | |
| 	}
 | |
| 
 | |
| 	set_bios_mode(saved_mode);
 | |
| 
 | |
| 	return nmodes;
 | |
| }
 | |
| 
 | |
| static __videocard video_bios =
 | |
| {
 | |
| 	.card_name	= "BIOS",
 | |
| 	.probe		= bios_probe,
 | |
| 	.set_mode	= bios_set_mode,
 | |
| 	.unsafe		= 1,
 | |
| 	.xmode_first	= VIDEO_FIRST_BIOS,
 | |
| 	.xmode_n	= 0x80,
 | |
| };
 |