|  | // SPDX-License-Identifier: GPL-2.0-only | 
|  | /* -*- linux-c -*- ------------------------------------------------------- * | 
|  | * | 
|  | *   Copyright (C) 1991, 1992 Linus Torvalds | 
|  | *   Copyright 2007 rPath, Inc. - All Rights Reserved | 
|  | *   Copyright 2009 Intel Corporation; author H. Peter Anvin | 
|  | * | 
|  | * ----------------------------------------------------------------------- */ | 
|  |  | 
|  | /* | 
|  | * 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, | 
|  | }; |