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