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