| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | /* -*- linux-c -*- ------------------------------------------------------- *
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   Copyright (C) 1991, 1992 Linus Torvalds | 
					
						
							|  |  |  |  *   Copyright 2007 rPath, Inc. - All Rights Reserved | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  |  *   Copyright 2009 Intel Corporation; author H. Peter Anvin | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  *   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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-21 19:49:09 -04:00
										 |  |  | static __videocard video_bios; | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  | 	struct biosregs ireg, oreg; | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	u8 new_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  | 	initregs(&ireg); | 
					
						
							|  |  |  | 	ireg.al = mode;		/* AH=0x00 Set Video Mode */ | 
					
						
							|  |  |  | 	intcall(0x10, &ireg, NULL); | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  | 	ireg.ah = 0x0f;		/* Get Current Video Mode */ | 
					
						
							|  |  |  | 	intcall(0x10, &ireg, &oreg); | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-26 10:10:35 -07:00
										 |  |  | 	do_restore = 1;		/* Assume video contents were lost */ | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Not all BIOSes are clean with the top bit */ | 
					
						
							| 
									
										
										
										
											2009-07-01 11:13:07 +09:00
										 |  |  | 	new_mode = oreg.al & 0x7f; | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (new_mode == mode) | 
					
						
							|  |  |  | 		return 0;	/* Mode change OK */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-10 23:28:10 +02:00
										 |  |  | #ifndef _WAKEUP
 | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	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. */ | 
					
						
							| 
									
										
										
										
											2009-04-01 18:20:11 -07:00
										 |  |  | 		ireg.ax = boot_params.screen_info.orig_video_mode; | 
					
						
							|  |  |  | 		intcall(0x10, &ireg, NULL); | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-04-10 23:28:10 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int bios_probe(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 mode; | 
					
						
							| 
									
										
										
										
											2008-04-10 23:28:10 +02:00
										 |  |  | #ifdef _WAKEUP
 | 
					
						
							|  |  |  | 	u8 saved_mode = 0x03; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	u8 saved_mode = boot_params.screen_info.orig_video_mode; | 
					
						
							| 
									
										
										
										
											2008-04-10 23:28:10 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	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++) { | 
					
						
							| 
									
										
										
										
											2007-10-25 16:09:38 -07:00
										 |  |  | 		if (!heap_free(sizeof(struct mode_info))) | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2008-01-30 13:33:02 +01:00
										 |  |  | 		mi->depth = 0;	/* text */ | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 		mi->x = rdfs16(0x44a); | 
					
						
							|  |  |  | 		mi->y = rdfs8(0x484)+1; | 
					
						
							|  |  |  | 		nmodes++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	set_bios_mode(saved_mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nmodes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-21 19:49:09 -04:00
										 |  |  | static __videocard video_bios = | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-01-30 13:33:02 +01:00
										 |  |  | 	.card_name	= "BIOS", | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:52 -07:00
										 |  |  | 	.probe		= bios_probe, | 
					
						
							|  |  |  | 	.set_mode	= bios_set_mode, | 
					
						
							|  |  |  | 	.unsafe		= 1, | 
					
						
							|  |  |  | 	.xmode_first	= VIDEO_FIRST_BIOS, | 
					
						
							|  |  |  | 	.xmode_n	= 0x80, | 
					
						
							|  |  |  | }; |