xref: /OK3568_Linux_fs/kernel/arch/x86/boot/video-bios.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* -*- linux-c -*- ------------------------------------------------------- *
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *   Copyright (C) 1991, 1992 Linus Torvalds
5*4882a593Smuzhiyun  *   Copyright 2007 rPath, Inc. - All Rights Reserved
6*4882a593Smuzhiyun  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * ----------------------------------------------------------------------- */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun  * Standard video BIOS modes
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * We have two options for this; silent and scanned.
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "boot.h"
17*4882a593Smuzhiyun #include "video.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static __videocard video_bios;
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* Set a conventional BIOS mode */
22*4882a593Smuzhiyun static int set_bios_mode(u8 mode);
23*4882a593Smuzhiyun 
bios_set_mode(struct mode_info * mi)24*4882a593Smuzhiyun static int bios_set_mode(struct mode_info *mi)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
set_bios_mode(u8 mode)29*4882a593Smuzhiyun static int set_bios_mode(u8 mode)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	struct biosregs ireg, oreg;
32*4882a593Smuzhiyun 	u8 new_mode;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	initregs(&ireg);
35*4882a593Smuzhiyun 	ireg.al = mode;		/* AH=0x00 Set Video Mode */
36*4882a593Smuzhiyun 	intcall(0x10, &ireg, NULL);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	ireg.ah = 0x0f;		/* Get Current Video Mode */
39*4882a593Smuzhiyun 	intcall(0x10, &ireg, &oreg);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	do_restore = 1;		/* Assume video contents were lost */
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	/* Not all BIOSes are clean with the top bit */
44*4882a593Smuzhiyun 	new_mode = oreg.al & 0x7f;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (new_mode == mode)
47*4882a593Smuzhiyun 		return 0;	/* Mode change OK */
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #ifndef _WAKEUP
50*4882a593Smuzhiyun 	if (new_mode != boot_params.screen_info.orig_video_mode) {
51*4882a593Smuzhiyun 		/* Mode setting failed, but we didn't end up where we
52*4882a593Smuzhiyun 		   started.  That's bad.  Try to revert to the original
53*4882a593Smuzhiyun 		   video mode. */
54*4882a593Smuzhiyun 		ireg.ax = boot_params.screen_info.orig_video_mode;
55*4882a593Smuzhiyun 		intcall(0x10, &ireg, NULL);
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun #endif
58*4882a593Smuzhiyun 	return -1;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
bios_probe(void)61*4882a593Smuzhiyun static int bios_probe(void)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	u8 mode;
64*4882a593Smuzhiyun #ifdef _WAKEUP
65*4882a593Smuzhiyun 	u8 saved_mode = 0x03;
66*4882a593Smuzhiyun #else
67*4882a593Smuzhiyun 	u8 saved_mode = boot_params.screen_info.orig_video_mode;
68*4882a593Smuzhiyun #endif
69*4882a593Smuzhiyun 	u16 crtc;
70*4882a593Smuzhiyun 	struct mode_info *mi;
71*4882a593Smuzhiyun 	int nmodes = 0;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
74*4882a593Smuzhiyun 		return 0;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	set_fs(0);
77*4882a593Smuzhiyun 	crtc = vga_crtc();
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	video_bios.modes = GET_HEAP(struct mode_info, 0);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	for (mode = 0x14; mode <= 0x7f; mode++) {
82*4882a593Smuzhiyun 		if (!heap_free(sizeof(struct mode_info)))
83*4882a593Smuzhiyun 			break;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 		if (mode_defined(VIDEO_FIRST_BIOS+mode))
86*4882a593Smuzhiyun 			continue;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 		if (set_bios_mode(mode))
89*4882a593Smuzhiyun 			continue;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 		/* Try to verify that it's a text mode. */
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		/* Attribute Controller: make graphics controller disabled */
94*4882a593Smuzhiyun 		if (in_idx(0x3c0, 0x10) & 0x01)
95*4882a593Smuzhiyun 			continue;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 		/* Graphics Controller: verify Alpha addressing enabled */
98*4882a593Smuzhiyun 		if (in_idx(0x3ce, 0x06) & 0x01)
99*4882a593Smuzhiyun 			continue;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 		/* CRTC cursor location low should be zero(?) */
102*4882a593Smuzhiyun 		if (in_idx(crtc, 0x0f))
103*4882a593Smuzhiyun 			continue;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 		mi = GET_HEAP(struct mode_info, 1);
106*4882a593Smuzhiyun 		mi->mode = VIDEO_FIRST_BIOS+mode;
107*4882a593Smuzhiyun 		mi->depth = 0;	/* text */
108*4882a593Smuzhiyun 		mi->x = rdfs16(0x44a);
109*4882a593Smuzhiyun 		mi->y = rdfs8(0x484)+1;
110*4882a593Smuzhiyun 		nmodes++;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	set_bios_mode(saved_mode);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	return nmodes;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun static __videocard video_bios =
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	.card_name	= "BIOS",
121*4882a593Smuzhiyun 	.probe		= bios_probe,
122*4882a593Smuzhiyun 	.set_mode	= bios_set_mode,
123*4882a593Smuzhiyun 	.unsafe		= 1,
124*4882a593Smuzhiyun 	.xmode_first	= VIDEO_FIRST_BIOS,
125*4882a593Smuzhiyun 	.xmode_n	= 0x80,
126*4882a593Smuzhiyun };
127