18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/drivers/video/vgacon.c -- Low level VGA based console driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Created 28 Sep 1997 by Geert Uytterhoeven 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This file is based on the old console.c, vga.c and vesa_blank.c drivers. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 118c2ecf20Sopenharmony_ci * 1995 Jay Estabrook 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * User definable mapping table and font loading by Eugene G. Crosser, 148c2ecf20Sopenharmony_ci * <crosser@average.org> 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Improved loadable font/UTF-8 support by H. Peter Anvin 178c2ecf20Sopenharmony_ci * Feb-Sep 1995 <peter.anvin@linux.org> 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Colour palette handling, by Simon Tatham 208c2ecf20Sopenharmony_ci * 17-Jun-95 <sgt20@cam.ac.uk> 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * if 512 char mode is already enabled don't re-enable it, 238c2ecf20Sopenharmony_ci * because it causes screen to flicker, by Mitja Horvat 248c2ecf20Sopenharmony_ci * 5-May-96 <mitja.horvat@guest.arnes.si> 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Use 2 outw instead of 4 outb_p to reduce erroneous text 278c2ecf20Sopenharmony_ci * flashing on RHS of screen during heavy console scrolling . 288c2ecf20Sopenharmony_ci * Oct 1996, Paul Gortmaker. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 328c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 338c2ecf20Sopenharmony_ci * more details. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/module.h> 378c2ecf20Sopenharmony_ci#include <linux/types.h> 388c2ecf20Sopenharmony_ci#include <linux/fs.h> 398c2ecf20Sopenharmony_ci#include <linux/kernel.h> 408c2ecf20Sopenharmony_ci#include <linux/console.h> 418c2ecf20Sopenharmony_ci#include <linux/string.h> 428c2ecf20Sopenharmony_ci#include <linux/kd.h> 438c2ecf20Sopenharmony_ci#include <linux/slab.h> 448c2ecf20Sopenharmony_ci#include <linux/vt_kern.h> 458c2ecf20Sopenharmony_ci#include <linux/sched.h> 468c2ecf20Sopenharmony_ci#include <linux/selection.h> 478c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 488c2ecf20Sopenharmony_ci#include <linux/ioport.h> 498c2ecf20Sopenharmony_ci#include <linux/init.h> 508c2ecf20Sopenharmony_ci#include <linux/screen_info.h> 518c2ecf20Sopenharmony_ci#include <video/vga.h> 528c2ecf20Sopenharmony_ci#include <asm/io.h> 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(vga_lock); 558c2ecf20Sopenharmony_cistatic int cursor_size_lastfrom; 568c2ecf20Sopenharmony_cistatic int cursor_size_lastto; 578c2ecf20Sopenharmony_cistatic u32 vgacon_xres; 588c2ecf20Sopenharmony_cistatic u32 vgacon_yres; 598c2ecf20Sopenharmony_cistatic struct vgastate vgastate; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define BLANK 0x0020 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * Interface used by the world 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic const char *vgacon_startup(void); 698c2ecf20Sopenharmony_cistatic void vgacon_init(struct vc_data *c, int init); 708c2ecf20Sopenharmony_cistatic void vgacon_deinit(struct vc_data *c); 718c2ecf20Sopenharmony_cistatic void vgacon_cursor(struct vc_data *c, int mode); 728c2ecf20Sopenharmony_cistatic int vgacon_switch(struct vc_data *c); 738c2ecf20Sopenharmony_cistatic int vgacon_blank(struct vc_data *c, int blank, int mode_switch); 748c2ecf20Sopenharmony_cistatic void vgacon_scrolldelta(struct vc_data *c, int lines); 758c2ecf20Sopenharmony_cistatic int vgacon_set_origin(struct vc_data *c); 768c2ecf20Sopenharmony_cistatic void vgacon_save_screen(struct vc_data *c); 778c2ecf20Sopenharmony_cistatic void vgacon_invert_region(struct vc_data *c, u16 * p, int count); 788c2ecf20Sopenharmony_cistatic struct uni_pagedir *vgacon_uni_pagedir; 798c2ecf20Sopenharmony_cistatic int vgacon_refcount; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* Description of the hardware situation */ 828c2ecf20Sopenharmony_cistatic bool vga_init_done; 838c2ecf20Sopenharmony_cistatic unsigned long vga_vram_base __read_mostly; /* Base of video memory */ 848c2ecf20Sopenharmony_cistatic unsigned long vga_vram_end __read_mostly; /* End of video memory */ 858c2ecf20Sopenharmony_cistatic unsigned int vga_vram_size __read_mostly; /* Size of video memory */ 868c2ecf20Sopenharmony_cistatic u16 vga_video_port_reg __read_mostly; /* Video register select port */ 878c2ecf20Sopenharmony_cistatic u16 vga_video_port_val __read_mostly; /* Video register value port */ 888c2ecf20Sopenharmony_cistatic unsigned int vga_video_num_columns; /* Number of text columns */ 898c2ecf20Sopenharmony_cistatic unsigned int vga_video_num_lines; /* Number of text lines */ 908c2ecf20Sopenharmony_cistatic bool vga_can_do_color; /* Do we support colors? */ 918c2ecf20Sopenharmony_cistatic unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ 928c2ecf20Sopenharmony_cistatic unsigned char vga_video_type __read_mostly; /* Card type */ 938c2ecf20Sopenharmony_cistatic bool vga_font_is_default = true; 948c2ecf20Sopenharmony_cistatic int vga_vesa_blanked; 958c2ecf20Sopenharmony_cistatic bool vga_palette_blanked; 968c2ecf20Sopenharmony_cistatic bool vga_is_gfx; 978c2ecf20Sopenharmony_cistatic bool vga_512_chars; 988c2ecf20Sopenharmony_cistatic int vga_video_font_height; 998c2ecf20Sopenharmony_cistatic int vga_scan_lines __read_mostly; 1008c2ecf20Sopenharmony_cistatic unsigned int vga_rolled_over; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic bool vgacon_text_mode_force; 1038c2ecf20Sopenharmony_cistatic bool vga_hardscroll_enabled; 1048c2ecf20Sopenharmony_cistatic bool vga_hardscroll_user_enable = true; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cibool vgacon_text_force(void) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci return vgacon_text_mode_force; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vgacon_text_force); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic int __init text_mode(char *str) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci vgacon_text_mode_force = true; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci pr_warn("You have booted with nomodeset. This means your GPU drivers are DISABLED\n"); 1178c2ecf20Sopenharmony_ci pr_warn("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n"); 1188c2ecf20Sopenharmony_ci pr_warn("Unless you actually understand what nomodeset does, you should reboot without enabling it\n"); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci return 1; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* force text mode - used by kernel modesetting */ 1248c2ecf20Sopenharmony_ci__setup("nomodeset", text_mode); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic int __init no_scroll(char *str) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci /* 1298c2ecf20Sopenharmony_ci * Disabling scrollback is required for the Braillex ib80-piezo 1308c2ecf20Sopenharmony_ci * Braille reader made by F.H. Papenmeier (Germany). 1318c2ecf20Sopenharmony_ci * Use the "no-scroll" bootflag. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci vga_hardscroll_user_enable = vga_hardscroll_enabled = false; 1348c2ecf20Sopenharmony_ci return 1; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci__setup("no-scroll", no_scroll); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* 1408c2ecf20Sopenharmony_ci * By replacing the four outb_p with two back to back outw, we can reduce 1418c2ecf20Sopenharmony_ci * the window of opportunity to see text mislocated to the RHS of the 1428c2ecf20Sopenharmony_ci * console during heavy scrolling activity. However there is the remote 1438c2ecf20Sopenharmony_ci * possibility that some pre-dinosaur hardware won't like the back to back 1448c2ecf20Sopenharmony_ci * I/O. Since the Xservers get away with it, we should be able to as well. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_cistatic inline void write_vga(unsigned char reg, unsigned int val) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci unsigned int v1, v2; 1498c2ecf20Sopenharmony_ci unsigned long flags; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* 1528c2ecf20Sopenharmony_ci * ddprintk might set the console position from interrupt 1538c2ecf20Sopenharmony_ci * handlers, thus the write has to be IRQ-atomic. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci raw_spin_lock_irqsave(&vga_lock, flags); 1568c2ecf20Sopenharmony_ci v1 = reg + (val & 0xff00); 1578c2ecf20Sopenharmony_ci v2 = reg + 1 + ((val << 8) & 0xff00); 1588c2ecf20Sopenharmony_ci outw(v1, vga_video_port_reg); 1598c2ecf20Sopenharmony_ci outw(v2, vga_video_port_reg); 1608c2ecf20Sopenharmony_ci raw_spin_unlock_irqrestore(&vga_lock, flags); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline void vga_set_mem_top(struct vc_data *c) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic void vgacon_restore_screen(struct vc_data *c) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci if (c->vc_origin != c->vc_visible_origin) 1718c2ecf20Sopenharmony_ci vgacon_scrolldelta(c, 0); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic void vgacon_scrolldelta(struct vc_data *c, int lines) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base, 1778c2ecf20Sopenharmony_ci vga_vram_size); 1788c2ecf20Sopenharmony_ci vga_set_mem_top(c); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic const char *vgacon_startup(void) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci const char *display_desc = NULL; 1848c2ecf20Sopenharmony_ci u16 saved1, saved2; 1858c2ecf20Sopenharmony_ci volatile u16 *p; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB || 1888c2ecf20Sopenharmony_ci screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) { 1898c2ecf20Sopenharmony_ci no_vga: 1908c2ecf20Sopenharmony_ci#ifdef CONFIG_DUMMY_CONSOLE 1918c2ecf20Sopenharmony_ci conswitchp = &dummy_con; 1928c2ecf20Sopenharmony_ci return conswitchp->con_startup(); 1938c2ecf20Sopenharmony_ci#else 1948c2ecf20Sopenharmony_ci return NULL; 1958c2ecf20Sopenharmony_ci#endif 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* boot_params.screen_info reasonably initialized? */ 1998c2ecf20Sopenharmony_ci if ((screen_info.orig_video_lines == 0) || 2008c2ecf20Sopenharmony_ci (screen_info.orig_video_cols == 0)) 2018c2ecf20Sopenharmony_ci goto no_vga; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* VGA16 modes are not handled by VGACON */ 2048c2ecf20Sopenharmony_ci if ((screen_info.orig_video_mode == 0x0D) || /* 320x200/4 */ 2058c2ecf20Sopenharmony_ci (screen_info.orig_video_mode == 0x0E) || /* 640x200/4 */ 2068c2ecf20Sopenharmony_ci (screen_info.orig_video_mode == 0x10) || /* 640x350/4 */ 2078c2ecf20Sopenharmony_ci (screen_info.orig_video_mode == 0x12) || /* 640x480/4 */ 2088c2ecf20Sopenharmony_ci (screen_info.orig_video_mode == 0x6A)) /* 800x600/4 (VESA) */ 2098c2ecf20Sopenharmony_ci goto no_vga; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci vga_video_num_lines = screen_info.orig_video_lines; 2128c2ecf20Sopenharmony_ci vga_video_num_columns = screen_info.orig_video_cols; 2138c2ecf20Sopenharmony_ci vgastate.vgabase = NULL; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (screen_info.orig_video_mode == 7) { 2168c2ecf20Sopenharmony_ci /* Monochrome display */ 2178c2ecf20Sopenharmony_ci vga_vram_base = 0xb0000; 2188c2ecf20Sopenharmony_ci vga_video_port_reg = VGA_CRT_IM; 2198c2ecf20Sopenharmony_ci vga_video_port_val = VGA_CRT_DM; 2208c2ecf20Sopenharmony_ci if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) { 2218c2ecf20Sopenharmony_ci static struct resource ega_console_resource = 2228c2ecf20Sopenharmony_ci { .name = "ega", 2238c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 2248c2ecf20Sopenharmony_ci .start = 0x3B0, 2258c2ecf20Sopenharmony_ci .end = 0x3BF }; 2268c2ecf20Sopenharmony_ci vga_video_type = VIDEO_TYPE_EGAM; 2278c2ecf20Sopenharmony_ci vga_vram_size = 0x8000; 2288c2ecf20Sopenharmony_ci display_desc = "EGA+"; 2298c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 2308c2ecf20Sopenharmony_ci &ega_console_resource); 2318c2ecf20Sopenharmony_ci } else { 2328c2ecf20Sopenharmony_ci static struct resource mda1_console_resource = 2338c2ecf20Sopenharmony_ci { .name = "mda", 2348c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 2358c2ecf20Sopenharmony_ci .start = 0x3B0, 2368c2ecf20Sopenharmony_ci .end = 0x3BB }; 2378c2ecf20Sopenharmony_ci static struct resource mda2_console_resource = 2388c2ecf20Sopenharmony_ci { .name = "mda", 2398c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 2408c2ecf20Sopenharmony_ci .start = 0x3BF, 2418c2ecf20Sopenharmony_ci .end = 0x3BF }; 2428c2ecf20Sopenharmony_ci vga_video_type = VIDEO_TYPE_MDA; 2438c2ecf20Sopenharmony_ci vga_vram_size = 0x2000; 2448c2ecf20Sopenharmony_ci display_desc = "*MDA"; 2458c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 2468c2ecf20Sopenharmony_ci &mda1_console_resource); 2478c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 2488c2ecf20Sopenharmony_ci &mda2_console_resource); 2498c2ecf20Sopenharmony_ci vga_video_font_height = 14; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci } else { 2528c2ecf20Sopenharmony_ci /* If not, it is color. */ 2538c2ecf20Sopenharmony_ci vga_can_do_color = true; 2548c2ecf20Sopenharmony_ci vga_vram_base = 0xb8000; 2558c2ecf20Sopenharmony_ci vga_video_port_reg = VGA_CRT_IC; 2568c2ecf20Sopenharmony_ci vga_video_port_val = VGA_CRT_DC; 2578c2ecf20Sopenharmony_ci if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) { 2588c2ecf20Sopenharmony_ci int i; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci vga_vram_size = 0x8000; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (!screen_info.orig_video_isVGA) { 2638c2ecf20Sopenharmony_ci static struct resource ega_console_resource = 2648c2ecf20Sopenharmony_ci { .name = "ega", 2658c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 2668c2ecf20Sopenharmony_ci .start = 0x3C0, 2678c2ecf20Sopenharmony_ci .end = 0x3DF }; 2688c2ecf20Sopenharmony_ci vga_video_type = VIDEO_TYPE_EGAC; 2698c2ecf20Sopenharmony_ci display_desc = "EGA"; 2708c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 2718c2ecf20Sopenharmony_ci &ega_console_resource); 2728c2ecf20Sopenharmony_ci } else { 2738c2ecf20Sopenharmony_ci static struct resource vga_console_resource = 2748c2ecf20Sopenharmony_ci { .name = "vga+", 2758c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 2768c2ecf20Sopenharmony_ci .start = 0x3C0, 2778c2ecf20Sopenharmony_ci .end = 0x3DF }; 2788c2ecf20Sopenharmony_ci vga_video_type = VIDEO_TYPE_VGAC; 2798c2ecf20Sopenharmony_ci display_desc = "VGA+"; 2808c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 2818c2ecf20Sopenharmony_ci &vga_console_resource); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* 2848c2ecf20Sopenharmony_ci * Normalise the palette registers, to point 2858c2ecf20Sopenharmony_ci * the 16 screen colours to the first 16 2868c2ecf20Sopenharmony_ci * DAC entries. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 2908c2ecf20Sopenharmony_ci inb_p(VGA_IS1_RC); 2918c2ecf20Sopenharmony_ci outb_p(i, VGA_ATT_W); 2928c2ecf20Sopenharmony_ci outb_p(i, VGA_ATT_W); 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci outb_p(0x20, VGA_ATT_W); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* 2978c2ecf20Sopenharmony_ci * Now set the DAC registers back to their 2988c2ecf20Sopenharmony_ci * default values 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 3018c2ecf20Sopenharmony_ci outb_p(color_table[i], VGA_PEL_IW); 3028c2ecf20Sopenharmony_ci outb_p(default_red[i], VGA_PEL_D); 3038c2ecf20Sopenharmony_ci outb_p(default_grn[i], VGA_PEL_D); 3048c2ecf20Sopenharmony_ci outb_p(default_blu[i], VGA_PEL_D); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci } else { 3088c2ecf20Sopenharmony_ci static struct resource cga_console_resource = 3098c2ecf20Sopenharmony_ci { .name = "cga", 3108c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO, 3118c2ecf20Sopenharmony_ci .start = 0x3D4, 3128c2ecf20Sopenharmony_ci .end = 0x3D5 }; 3138c2ecf20Sopenharmony_ci vga_video_type = VIDEO_TYPE_CGA; 3148c2ecf20Sopenharmony_ci vga_vram_size = 0x2000; 3158c2ecf20Sopenharmony_ci display_desc = "*CGA"; 3168c2ecf20Sopenharmony_ci request_resource(&ioport_resource, 3178c2ecf20Sopenharmony_ci &cga_console_resource); 3188c2ecf20Sopenharmony_ci vga_video_font_height = 8; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size); 3238c2ecf20Sopenharmony_ci vga_vram_end = vga_vram_base + vga_vram_size; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* 3268c2ecf20Sopenharmony_ci * Find out if there is a graphics card present. 3278c2ecf20Sopenharmony_ci * Are there smarter methods around? 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_ci p = (volatile u16 *) vga_vram_base; 3308c2ecf20Sopenharmony_ci saved1 = scr_readw(p); 3318c2ecf20Sopenharmony_ci saved2 = scr_readw(p + 1); 3328c2ecf20Sopenharmony_ci scr_writew(0xAA55, p); 3338c2ecf20Sopenharmony_ci scr_writew(0x55AA, p + 1); 3348c2ecf20Sopenharmony_ci if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) { 3358c2ecf20Sopenharmony_ci scr_writew(saved1, p); 3368c2ecf20Sopenharmony_ci scr_writew(saved2, p + 1); 3378c2ecf20Sopenharmony_ci goto no_vga; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci scr_writew(0x55AA, p); 3408c2ecf20Sopenharmony_ci scr_writew(0xAA55, p + 1); 3418c2ecf20Sopenharmony_ci if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) { 3428c2ecf20Sopenharmony_ci scr_writew(saved1, p); 3438c2ecf20Sopenharmony_ci scr_writew(saved2, p + 1); 3448c2ecf20Sopenharmony_ci goto no_vga; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci scr_writew(saved1, p); 3478c2ecf20Sopenharmony_ci scr_writew(saved2, p + 1); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (vga_video_type == VIDEO_TYPE_EGAC 3508c2ecf20Sopenharmony_ci || vga_video_type == VIDEO_TYPE_VGAC 3518c2ecf20Sopenharmony_ci || vga_video_type == VIDEO_TYPE_EGAM) { 3528c2ecf20Sopenharmony_ci vga_hardscroll_enabled = vga_hardscroll_user_enable; 3538c2ecf20Sopenharmony_ci vga_default_font_height = screen_info.orig_video_points; 3548c2ecf20Sopenharmony_ci vga_video_font_height = screen_info.orig_video_points; 3558c2ecf20Sopenharmony_ci /* This may be suboptimal but is a safe bet - go with it */ 3568c2ecf20Sopenharmony_ci vga_scan_lines = 3578c2ecf20Sopenharmony_ci vga_video_font_height * vga_video_num_lines; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH; 3618c2ecf20Sopenharmony_ci vgacon_yres = vga_scan_lines; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci vga_init_done = true; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return display_desc; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic void vgacon_init(struct vc_data *c, int init) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct uni_pagedir *p; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* 3738c2ecf20Sopenharmony_ci * We cannot be loaded as a module, therefore init will be 1 3748c2ecf20Sopenharmony_ci * if we are the default console, however if we are a fallback 3758c2ecf20Sopenharmony_ci * console, for example if fbcon has failed registration, then 3768c2ecf20Sopenharmony_ci * init will be 0, so we need to make sure our boot parameters 3778c2ecf20Sopenharmony_ci * have been copied to the console structure for vgacon_resize 3788c2ecf20Sopenharmony_ci * ultimately called by vc_resize. Any subsequent calls to 3798c2ecf20Sopenharmony_ci * vgacon_init init will have init set to 0 too. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ci c->vc_can_do_color = vga_can_do_color; 3828c2ecf20Sopenharmony_ci c->vc_scan_lines = vga_scan_lines; 3838c2ecf20Sopenharmony_ci c->vc_font.height = c->vc_cell_height = vga_video_font_height; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* set dimensions manually if init != 0 since vc_resize() will fail */ 3868c2ecf20Sopenharmony_ci if (init) { 3878c2ecf20Sopenharmony_ci c->vc_cols = vga_video_num_columns; 3888c2ecf20Sopenharmony_ci c->vc_rows = vga_video_num_lines; 3898c2ecf20Sopenharmony_ci } else 3908c2ecf20Sopenharmony_ci vc_resize(c, vga_video_num_columns, vga_video_num_lines); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci c->vc_complement_mask = 0x7700; 3938c2ecf20Sopenharmony_ci if (vga_512_chars) 3948c2ecf20Sopenharmony_ci c->vc_hi_font_mask = 0x0800; 3958c2ecf20Sopenharmony_ci p = *c->vc_uni_pagedir_loc; 3968c2ecf20Sopenharmony_ci if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) { 3978c2ecf20Sopenharmony_ci con_free_unimap(c); 3988c2ecf20Sopenharmony_ci c->vc_uni_pagedir_loc = &vgacon_uni_pagedir; 3998c2ecf20Sopenharmony_ci vgacon_refcount++; 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci if (!vgacon_uni_pagedir && p) 4028c2ecf20Sopenharmony_ci con_set_default_unimap(c); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* Only set the default if the user didn't deliberately override it */ 4058c2ecf20Sopenharmony_ci if (global_cursor_default == -1) 4068c2ecf20Sopenharmony_ci global_cursor_default = 4078c2ecf20Sopenharmony_ci !(screen_info.flags & VIDEO_FLAGS_NOCURSOR); 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic void vgacon_deinit(struct vc_data *c) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci /* When closing the active console, reset video origin */ 4138c2ecf20Sopenharmony_ci if (con_is_visible(c)) { 4148c2ecf20Sopenharmony_ci c->vc_visible_origin = vga_vram_base; 4158c2ecf20Sopenharmony_ci vga_set_mem_top(c); 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (!--vgacon_refcount) 4198c2ecf20Sopenharmony_ci con_free_unimap(c); 4208c2ecf20Sopenharmony_ci c->vc_uni_pagedir_loc = &c->vc_uni_pagedir; 4218c2ecf20Sopenharmony_ci con_set_default_unimap(c); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic u8 vgacon_build_attr(struct vc_data *c, u8 color, 4258c2ecf20Sopenharmony_ci enum vc_intensity intensity, 4268c2ecf20Sopenharmony_ci bool blink, bool underline, bool reverse, 4278c2ecf20Sopenharmony_ci bool italic) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci u8 attr = color; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci if (vga_can_do_color) { 4328c2ecf20Sopenharmony_ci if (italic) 4338c2ecf20Sopenharmony_ci attr = (attr & 0xF0) | c->vc_itcolor; 4348c2ecf20Sopenharmony_ci else if (underline) 4358c2ecf20Sopenharmony_ci attr = (attr & 0xf0) | c->vc_ulcolor; 4368c2ecf20Sopenharmony_ci else if (intensity == VCI_HALF_BRIGHT) 4378c2ecf20Sopenharmony_ci attr = (attr & 0xf0) | c->vc_halfcolor; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci if (reverse) 4408c2ecf20Sopenharmony_ci attr = 4418c2ecf20Sopenharmony_ci ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 4428c2ecf20Sopenharmony_ci 0x77); 4438c2ecf20Sopenharmony_ci if (blink) 4448c2ecf20Sopenharmony_ci attr ^= 0x80; 4458c2ecf20Sopenharmony_ci if (intensity == VCI_BOLD) 4468c2ecf20Sopenharmony_ci attr ^= 0x08; 4478c2ecf20Sopenharmony_ci if (!vga_can_do_color) { 4488c2ecf20Sopenharmony_ci if (italic) 4498c2ecf20Sopenharmony_ci attr = (attr & 0xF8) | 0x02; 4508c2ecf20Sopenharmony_ci else if (underline) 4518c2ecf20Sopenharmony_ci attr = (attr & 0xf8) | 0x01; 4528c2ecf20Sopenharmony_ci else if (intensity == VCI_HALF_BRIGHT) 4538c2ecf20Sopenharmony_ci attr = (attr & 0xf0) | 0x08; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci return attr; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void vgacon_invert_region(struct vc_data *c, u16 * p, int count) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci const bool col = vga_can_do_color; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci while (count--) { 4638c2ecf20Sopenharmony_ci u16 a = scr_readw(p); 4648c2ecf20Sopenharmony_ci if (col) 4658c2ecf20Sopenharmony_ci a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | 4668c2ecf20Sopenharmony_ci (((a) & 0x0700) << 4); 4678c2ecf20Sopenharmony_ci else 4688c2ecf20Sopenharmony_ci a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; 4698c2ecf20Sopenharmony_ci scr_writew(a, p++); 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic void vgacon_set_cursor_size(int xpos, int from, int to) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci unsigned long flags; 4768c2ecf20Sopenharmony_ci int curs, cure; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto)) 4798c2ecf20Sopenharmony_ci return; 4808c2ecf20Sopenharmony_ci cursor_size_lastfrom = from; 4818c2ecf20Sopenharmony_ci cursor_size_lastto = to; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci raw_spin_lock_irqsave(&vga_lock, flags); 4848c2ecf20Sopenharmony_ci if (vga_video_type >= VIDEO_TYPE_VGAC) { 4858c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); 4868c2ecf20Sopenharmony_ci curs = inb_p(vga_video_port_val); 4878c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); 4888c2ecf20Sopenharmony_ci cure = inb_p(vga_video_port_val); 4898c2ecf20Sopenharmony_ci } else { 4908c2ecf20Sopenharmony_ci curs = 0; 4918c2ecf20Sopenharmony_ci cure = 0; 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci curs = (curs & 0xc0) | from; 4958c2ecf20Sopenharmony_ci cure = (cure & 0xe0) | to; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); 4988c2ecf20Sopenharmony_ci outb_p(curs, vga_video_port_val); 4998c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); 5008c2ecf20Sopenharmony_ci outb_p(cure, vga_video_port_val); 5018c2ecf20Sopenharmony_ci raw_spin_unlock_irqrestore(&vga_lock, flags); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic void vgacon_cursor(struct vc_data *c, int mode) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci if (c->vc_mode != KD_TEXT) 5078c2ecf20Sopenharmony_ci return; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci vgacon_restore_screen(c); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci switch (mode) { 5128c2ecf20Sopenharmony_ci case CM_ERASE: 5138c2ecf20Sopenharmony_ci write_vga(14, (c->vc_pos - vga_vram_base) / 2); 5148c2ecf20Sopenharmony_ci if (vga_video_type >= VIDEO_TYPE_VGAC) 5158c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 31, 30); 5168c2ecf20Sopenharmony_ci else 5178c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 31, 31); 5188c2ecf20Sopenharmony_ci break; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci case CM_MOVE: 5218c2ecf20Sopenharmony_ci case CM_DRAW: 5228c2ecf20Sopenharmony_ci write_vga(14, (c->vc_pos - vga_vram_base) / 2); 5238c2ecf20Sopenharmony_ci switch (CUR_SIZE(c->vc_cursor_type)) { 5248c2ecf20Sopenharmony_ci case CUR_UNDERLINE: 5258c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 5268c2ecf20Sopenharmony_ci c->vc_cell_height - 5278c2ecf20Sopenharmony_ci (c->vc_cell_height < 5288c2ecf20Sopenharmony_ci 10 ? 2 : 3), 5298c2ecf20Sopenharmony_ci c->vc_cell_height - 5308c2ecf20Sopenharmony_ci (c->vc_cell_height < 5318c2ecf20Sopenharmony_ci 10 ? 1 : 2)); 5328c2ecf20Sopenharmony_ci break; 5338c2ecf20Sopenharmony_ci case CUR_TWO_THIRDS: 5348c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 5358c2ecf20Sopenharmony_ci c->vc_cell_height / 3, 5368c2ecf20Sopenharmony_ci c->vc_cell_height - 5378c2ecf20Sopenharmony_ci (c->vc_cell_height < 5388c2ecf20Sopenharmony_ci 10 ? 1 : 2)); 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci case CUR_LOWER_THIRD: 5418c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 5428c2ecf20Sopenharmony_ci (c->vc_cell_height * 2) / 3, 5438c2ecf20Sopenharmony_ci c->vc_cell_height - 5448c2ecf20Sopenharmony_ci (c->vc_cell_height < 5458c2ecf20Sopenharmony_ci 10 ? 1 : 2)); 5468c2ecf20Sopenharmony_ci break; 5478c2ecf20Sopenharmony_ci case CUR_LOWER_HALF: 5488c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 5498c2ecf20Sopenharmony_ci c->vc_cell_height / 2, 5508c2ecf20Sopenharmony_ci c->vc_cell_height - 5518c2ecf20Sopenharmony_ci (c->vc_cell_height < 5528c2ecf20Sopenharmony_ci 10 ? 1 : 2)); 5538c2ecf20Sopenharmony_ci break; 5548c2ecf20Sopenharmony_ci case CUR_NONE: 5558c2ecf20Sopenharmony_ci if (vga_video_type >= VIDEO_TYPE_VGAC) 5568c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 31, 30); 5578c2ecf20Sopenharmony_ci else 5588c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 31, 31); 5598c2ecf20Sopenharmony_ci break; 5608c2ecf20Sopenharmony_ci default: 5618c2ecf20Sopenharmony_ci vgacon_set_cursor_size(c->state.x, 1, 5628c2ecf20Sopenharmony_ci c->vc_cell_height); 5638c2ecf20Sopenharmony_ci break; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci break; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cistatic int vgacon_doresize(struct vc_data *c, 5708c2ecf20Sopenharmony_ci unsigned int width, unsigned int height) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci unsigned long flags; 5738c2ecf20Sopenharmony_ci unsigned int scanlines = height * c->vc_cell_height; 5748c2ecf20Sopenharmony_ci u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci raw_spin_lock_irqsave(&vga_lock, flags); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci vgacon_xres = width * VGA_FONTWIDTH; 5798c2ecf20Sopenharmony_ci vgacon_yres = height * c->vc_cell_height; 5808c2ecf20Sopenharmony_ci if (vga_video_type >= VIDEO_TYPE_VGAC) { 5818c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg); 5828c2ecf20Sopenharmony_ci max_scan = inb_p(vga_video_port_val); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (max_scan & 0x80) 5858c2ecf20Sopenharmony_ci scanlines <<= 1; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_MODE, vga_video_port_reg); 5888c2ecf20Sopenharmony_ci mode = inb_p(vga_video_port_val); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (mode & 0x04) 5918c2ecf20Sopenharmony_ci scanlines >>= 1; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci scanlines -= 1; 5948c2ecf20Sopenharmony_ci scanlines_lo = scanlines & 0xff; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg); 5978c2ecf20Sopenharmony_ci r7 = inb_p(vga_video_port_val) & ~0x42; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci if (scanlines & 0x100) 6008c2ecf20Sopenharmony_ci r7 |= 0x02; 6018c2ecf20Sopenharmony_ci if (scanlines & 0x200) 6028c2ecf20Sopenharmony_ci r7 |= 0x40; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* deprotect registers */ 6058c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); 6068c2ecf20Sopenharmony_ci vsync_end = inb_p(vga_video_port_val); 6078c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); 6088c2ecf20Sopenharmony_ci outb_p(vsync_end & ~0x80, vga_video_port_val); 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_H_DISP, vga_video_port_reg); 6128c2ecf20Sopenharmony_ci outb_p(width - 1, vga_video_port_val); 6138c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_OFFSET, vga_video_port_reg); 6148c2ecf20Sopenharmony_ci outb_p(width >> 1, vga_video_port_val); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (vga_video_type >= VIDEO_TYPE_VGAC) { 6178c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg); 6188c2ecf20Sopenharmony_ci outb_p(scanlines_lo, vga_video_port_val); 6198c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg); 6208c2ecf20Sopenharmony_ci outb_p(r7,vga_video_port_val); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* reprotect registers */ 6238c2ecf20Sopenharmony_ci outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); 6248c2ecf20Sopenharmony_ci outb_p(vsync_end, vga_video_port_val); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci raw_spin_unlock_irqrestore(&vga_lock, flags); 6288c2ecf20Sopenharmony_ci return 0; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int vgacon_switch(struct vc_data *c) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int x = c->vc_cols * VGA_FONTWIDTH; 6348c2ecf20Sopenharmony_ci int y = c->vc_rows * c->vc_cell_height; 6358c2ecf20Sopenharmony_ci int rows = screen_info.orig_video_lines * vga_default_font_height/ 6368c2ecf20Sopenharmony_ci c->vc_cell_height; 6378c2ecf20Sopenharmony_ci /* 6388c2ecf20Sopenharmony_ci * We need to save screen size here as it's the only way 6398c2ecf20Sopenharmony_ci * we can spot the screen has been resized and we need to 6408c2ecf20Sopenharmony_ci * set size of freshly allocated screens ourselves. 6418c2ecf20Sopenharmony_ci */ 6428c2ecf20Sopenharmony_ci vga_video_num_columns = c->vc_cols; 6438c2ecf20Sopenharmony_ci vga_video_num_lines = c->vc_rows; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* We can only copy out the size of the video buffer here, 6468c2ecf20Sopenharmony_ci * otherwise we get into VGA BIOS */ 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci if (!vga_is_gfx) { 6498c2ecf20Sopenharmony_ci scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, 6508c2ecf20Sopenharmony_ci c->vc_screenbuf_size > vga_vram_size ? 6518c2ecf20Sopenharmony_ci vga_vram_size : c->vc_screenbuf_size); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if ((vgacon_xres != x || vgacon_yres != y) && 6548c2ecf20Sopenharmony_ci (!(vga_video_num_columns % 2) && 6558c2ecf20Sopenharmony_ci vga_video_num_columns <= screen_info.orig_video_cols && 6568c2ecf20Sopenharmony_ci vga_video_num_lines <= rows)) 6578c2ecf20Sopenharmony_ci vgacon_doresize(c, c->vc_cols, c->vc_rows); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci return 0; /* Redrawing not needed */ 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic void vga_set_palette(struct vc_data *vc, const unsigned char *table) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci int i, j; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff); 6688c2ecf20Sopenharmony_ci for (i = j = 0; i < 16; i++) { 6698c2ecf20Sopenharmony_ci vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]); 6708c2ecf20Sopenharmony_ci vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); 6718c2ecf20Sopenharmony_ci vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); 6728c2ecf20Sopenharmony_ci vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci} 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_cistatic void vgacon_set_palette(struct vc_data *vc, const unsigned char *table) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked 6798c2ecf20Sopenharmony_ci || !con_is_visible(vc)) 6808c2ecf20Sopenharmony_ci return; 6818c2ecf20Sopenharmony_ci vga_set_palette(vc, table); 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci/* structure holding original VGA register settings */ 6858c2ecf20Sopenharmony_cistatic struct { 6868c2ecf20Sopenharmony_ci unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ 6878c2ecf20Sopenharmony_ci unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ 6888c2ecf20Sopenharmony_ci unsigned char CrtMiscIO; /* Miscellaneous register */ 6898c2ecf20Sopenharmony_ci unsigned char HorizontalTotal; /* CRT-Controller:00h */ 6908c2ecf20Sopenharmony_ci unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ 6918c2ecf20Sopenharmony_ci unsigned char StartHorizRetrace; /* CRT-Controller:04h */ 6928c2ecf20Sopenharmony_ci unsigned char EndHorizRetrace; /* CRT-Controller:05h */ 6938c2ecf20Sopenharmony_ci unsigned char Overflow; /* CRT-Controller:07h */ 6948c2ecf20Sopenharmony_ci unsigned char StartVertRetrace; /* CRT-Controller:10h */ 6958c2ecf20Sopenharmony_ci unsigned char EndVertRetrace; /* CRT-Controller:11h */ 6968c2ecf20Sopenharmony_ci unsigned char ModeControl; /* CRT-Controller:17h */ 6978c2ecf20Sopenharmony_ci unsigned char ClockingMode; /* Seq-Controller:01h */ 6988c2ecf20Sopenharmony_ci} vga_state; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic void vga_vesa_blank(struct vgastate *state, int mode) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci /* save original values of VGA controller registers */ 7038c2ecf20Sopenharmony_ci if (!vga_vesa_blanked) { 7048c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 7058c2ecf20Sopenharmony_ci vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I); 7068c2ecf20Sopenharmony_ci vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); 7078c2ecf20Sopenharmony_ci vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R); 7088c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ 7118c2ecf20Sopenharmony_ci vga_state.HorizontalTotal = inb_p(vga_video_port_val); 7128c2ecf20Sopenharmony_ci outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */ 7138c2ecf20Sopenharmony_ci vga_state.HorizDisplayEnd = inb_p(vga_video_port_val); 7148c2ecf20Sopenharmony_ci outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ 7158c2ecf20Sopenharmony_ci vga_state.StartHorizRetrace = inb_p(vga_video_port_val); 7168c2ecf20Sopenharmony_ci outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ 7178c2ecf20Sopenharmony_ci vga_state.EndHorizRetrace = inb_p(vga_video_port_val); 7188c2ecf20Sopenharmony_ci outb_p(0x07, vga_video_port_reg); /* Overflow */ 7198c2ecf20Sopenharmony_ci vga_state.Overflow = inb_p(vga_video_port_val); 7208c2ecf20Sopenharmony_ci outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ 7218c2ecf20Sopenharmony_ci vga_state.StartVertRetrace = inb_p(vga_video_port_val); 7228c2ecf20Sopenharmony_ci outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ 7238c2ecf20Sopenharmony_ci vga_state.EndVertRetrace = inb_p(vga_video_port_val); 7248c2ecf20Sopenharmony_ci outb_p(0x17, vga_video_port_reg); /* ModeControl */ 7258c2ecf20Sopenharmony_ci vga_state.ModeControl = inb_p(vga_video_port_val); 7268c2ecf20Sopenharmony_ci vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci /* assure that video is enabled */ 7308c2ecf20Sopenharmony_ci /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ 7318c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 7328c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* test for vertical retrace in process.... */ 7358c2ecf20Sopenharmony_ci if ((vga_state.CrtMiscIO & 0x80) == 0x80) 7368c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF); 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci /* 7398c2ecf20Sopenharmony_ci * Set <End of vertical retrace> to minimum (0) and 7408c2ecf20Sopenharmony_ci * <Start of vertical Retrace> to maximum (incl. overflow) 7418c2ecf20Sopenharmony_ci * Result: turn off vertical sync (VSync) pulse. 7428c2ecf20Sopenharmony_ci */ 7438c2ecf20Sopenharmony_ci if (mode & VESA_VSYNC_SUSPEND) { 7448c2ecf20Sopenharmony_ci outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ 7458c2ecf20Sopenharmony_ci outb_p(0xff, vga_video_port_val); /* maximum value */ 7468c2ecf20Sopenharmony_ci outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ 7478c2ecf20Sopenharmony_ci outb_p(0x40, vga_video_port_val); /* minimum (bits 0..3) */ 7488c2ecf20Sopenharmony_ci outb_p(0x07, vga_video_port_reg); /* Overflow */ 7498c2ecf20Sopenharmony_ci outb_p(vga_state.Overflow | 0x84, vga_video_port_val); /* bits 9,10 of vert. retrace */ 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci if (mode & VESA_HSYNC_SUSPEND) { 7538c2ecf20Sopenharmony_ci /* 7548c2ecf20Sopenharmony_ci * Set <End of horizontal retrace> to minimum (0) and 7558c2ecf20Sopenharmony_ci * <Start of horizontal Retrace> to maximum 7568c2ecf20Sopenharmony_ci * Result: turn off horizontal sync (HSync) pulse. 7578c2ecf20Sopenharmony_ci */ 7588c2ecf20Sopenharmony_ci outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ 7598c2ecf20Sopenharmony_ci outb_p(0xff, vga_video_port_val); /* maximum */ 7608c2ecf20Sopenharmony_ci outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ 7618c2ecf20Sopenharmony_ci outb_p(0x00, vga_video_port_val); /* minimum (0) */ 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* restore both index registers */ 7658c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); 7668c2ecf20Sopenharmony_ci outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); 7678c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 7688c2ecf20Sopenharmony_ci} 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cistatic void vga_vesa_unblank(struct vgastate *state) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci /* restore original values of VGA controller registers */ 7738c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 7748c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ 7778c2ecf20Sopenharmony_ci outb_p(vga_state.HorizontalTotal, vga_video_port_val); 7788c2ecf20Sopenharmony_ci outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */ 7798c2ecf20Sopenharmony_ci outb_p(vga_state.HorizDisplayEnd, vga_video_port_val); 7808c2ecf20Sopenharmony_ci outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ 7818c2ecf20Sopenharmony_ci outb_p(vga_state.StartHorizRetrace, vga_video_port_val); 7828c2ecf20Sopenharmony_ci outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ 7838c2ecf20Sopenharmony_ci outb_p(vga_state.EndHorizRetrace, vga_video_port_val); 7848c2ecf20Sopenharmony_ci outb_p(0x07, vga_video_port_reg); /* Overflow */ 7858c2ecf20Sopenharmony_ci outb_p(vga_state.Overflow, vga_video_port_val); 7868c2ecf20Sopenharmony_ci outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ 7878c2ecf20Sopenharmony_ci outb_p(vga_state.StartVertRetrace, vga_video_port_val); 7888c2ecf20Sopenharmony_ci outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ 7898c2ecf20Sopenharmony_ci outb_p(vga_state.EndVertRetrace, vga_video_port_val); 7908c2ecf20Sopenharmony_ci outb_p(0x17, vga_video_port_reg); /* ModeControl */ 7918c2ecf20Sopenharmony_ci outb_p(vga_state.ModeControl, vga_video_port_val); 7928c2ecf20Sopenharmony_ci /* ClockingMode */ 7938c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* restore index/control registers */ 7968c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); 7978c2ecf20Sopenharmony_ci outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); 7988c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic void vga_pal_blank(struct vgastate *state) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci int i; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_PEL_MSK, 0xff); 8068c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 8078c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_PEL_IW, i); 8088c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_PEL_D, 0); 8098c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_PEL_D, 0); 8108c2ecf20Sopenharmony_ci vga_w(state->vgabase, VGA_PEL_D, 0); 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic int vgacon_blank(struct vc_data *c, int blank, int mode_switch) 8158c2ecf20Sopenharmony_ci{ 8168c2ecf20Sopenharmony_ci switch (blank) { 8178c2ecf20Sopenharmony_ci case 0: /* Unblank */ 8188c2ecf20Sopenharmony_ci if (vga_vesa_blanked) { 8198c2ecf20Sopenharmony_ci vga_vesa_unblank(&vgastate); 8208c2ecf20Sopenharmony_ci vga_vesa_blanked = 0; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci if (vga_palette_blanked) { 8238c2ecf20Sopenharmony_ci vga_set_palette(c, color_table); 8248c2ecf20Sopenharmony_ci vga_palette_blanked = false; 8258c2ecf20Sopenharmony_ci return 0; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci vga_is_gfx = false; 8288c2ecf20Sopenharmony_ci /* Tell console.c that it has to restore the screen itself */ 8298c2ecf20Sopenharmony_ci return 1; 8308c2ecf20Sopenharmony_ci case 1: /* Normal blanking */ 8318c2ecf20Sopenharmony_ci case -1: /* Obsolete */ 8328c2ecf20Sopenharmony_ci if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { 8338c2ecf20Sopenharmony_ci vga_pal_blank(&vgastate); 8348c2ecf20Sopenharmony_ci vga_palette_blanked = true; 8358c2ecf20Sopenharmony_ci return 0; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci vgacon_set_origin(c); 8388c2ecf20Sopenharmony_ci scr_memsetw((void *) vga_vram_base, BLANK, 8398c2ecf20Sopenharmony_ci c->vc_screenbuf_size); 8408c2ecf20Sopenharmony_ci if (mode_switch) 8418c2ecf20Sopenharmony_ci vga_is_gfx = true; 8428c2ecf20Sopenharmony_ci return 1; 8438c2ecf20Sopenharmony_ci default: /* VESA blanking */ 8448c2ecf20Sopenharmony_ci if (vga_video_type == VIDEO_TYPE_VGAC) { 8458c2ecf20Sopenharmony_ci vga_vesa_blank(&vgastate, blank - 1); 8468c2ecf20Sopenharmony_ci vga_vesa_blanked = blank; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci return 0; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci} 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci/* 8538c2ecf20Sopenharmony_ci * PIO_FONT support. 8548c2ecf20Sopenharmony_ci * 8558c2ecf20Sopenharmony_ci * The font loading code goes back to the codepage package by 8568c2ecf20Sopenharmony_ci * Joel Hoffman (joel@wam.umd.edu). (He reports that the original 8578c2ecf20Sopenharmony_ci * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2 8588c2ecf20Sopenharmony_ci * Video Systems_ by Richard Wilton. 1987. Microsoft Press".) 8598c2ecf20Sopenharmony_ci * 8608c2ecf20Sopenharmony_ci * Change for certain monochrome monitors by Yury Shevchuck 8618c2ecf20Sopenharmony_ci * (sizif@botik.yaroslavl.su). 8628c2ecf20Sopenharmony_ci */ 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci#define colourmap 0xa0000 8658c2ecf20Sopenharmony_ci/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we 8668c2ecf20Sopenharmony_ci should use 0xA0000 for the bwmap as well.. */ 8678c2ecf20Sopenharmony_ci#define blackwmap 0xa0000 8688c2ecf20Sopenharmony_ci#define cmapsz 8192 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_cistatic int vgacon_do_font_op(struct vgastate *state, char *arg, int set, 8718c2ecf20Sopenharmony_ci bool ch512) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci unsigned short video_port_status = vga_video_port_reg + 6; 8748c2ecf20Sopenharmony_ci int font_select = 0x00, beg, i; 8758c2ecf20Sopenharmony_ci char *charmap; 8768c2ecf20Sopenharmony_ci bool clear_attribs = false; 8778c2ecf20Sopenharmony_ci if (vga_video_type != VIDEO_TYPE_EGAM) { 8788c2ecf20Sopenharmony_ci charmap = (char *) VGA_MAP_MEM(colourmap, 0); 8798c2ecf20Sopenharmony_ci beg = 0x0e; 8808c2ecf20Sopenharmony_ci } else { 8818c2ecf20Sopenharmony_ci charmap = (char *) VGA_MAP_MEM(blackwmap, 0); 8828c2ecf20Sopenharmony_ci beg = 0x0a; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci#ifdef BROKEN_GRAPHICS_PROGRAMS 8868c2ecf20Sopenharmony_ci /* 8878c2ecf20Sopenharmony_ci * All fonts are loaded in slot 0 (0:1 for 512 ch) 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (!arg) 8918c2ecf20Sopenharmony_ci return -EINVAL; /* Return to default font not supported */ 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci vga_font_is_default = false; 8948c2ecf20Sopenharmony_ci font_select = ch512 ? 0x04 : 0x00; 8958c2ecf20Sopenharmony_ci#else 8968c2ecf20Sopenharmony_ci /* 8978c2ecf20Sopenharmony_ci * The default font is kept in slot 0 and is never touched. 8988c2ecf20Sopenharmony_ci * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch) 8998c2ecf20Sopenharmony_ci */ 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (set) { 9028c2ecf20Sopenharmony_ci vga_font_is_default = !arg; 9038c2ecf20Sopenharmony_ci if (!arg) 9048c2ecf20Sopenharmony_ci ch512 = false; /* Default font is always 256 */ 9058c2ecf20Sopenharmony_ci font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci if (!vga_font_is_default) 9098c2ecf20Sopenharmony_ci charmap += 4 * cmapsz; 9108c2ecf20Sopenharmony_ci#endif 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 9138c2ecf20Sopenharmony_ci /* First, the Sequencer */ 9148c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); 9158c2ecf20Sopenharmony_ci /* CPU writes only to map 2 */ 9168c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04); 9178c2ecf20Sopenharmony_ci /* Sequential addressing */ 9188c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07); 9198c2ecf20Sopenharmony_ci /* Clear synchronous reset */ 9208c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci /* Now, the graphics controller, select map 2 */ 9238c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02); 9248c2ecf20Sopenharmony_ci /* disable odd-even addressing */ 9258c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00); 9268c2ecf20Sopenharmony_ci /* map start at A000:0000 */ 9278c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00); 9288c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci if (arg) { 9318c2ecf20Sopenharmony_ci if (set) 9328c2ecf20Sopenharmony_ci for (i = 0; i < cmapsz; i++) { 9338c2ecf20Sopenharmony_ci vga_writeb(arg[i], charmap + i); 9348c2ecf20Sopenharmony_ci cond_resched(); 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci else 9378c2ecf20Sopenharmony_ci for (i = 0; i < cmapsz; i++) { 9388c2ecf20Sopenharmony_ci arg[i] = vga_readb(charmap + i); 9398c2ecf20Sopenharmony_ci cond_resched(); 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci /* 9438c2ecf20Sopenharmony_ci * In 512-character mode, the character map is not contiguous if 9448c2ecf20Sopenharmony_ci * we want to remain EGA compatible -- which we do 9458c2ecf20Sopenharmony_ci */ 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (ch512) { 9488c2ecf20Sopenharmony_ci charmap += 2 * cmapsz; 9498c2ecf20Sopenharmony_ci arg += cmapsz; 9508c2ecf20Sopenharmony_ci if (set) 9518c2ecf20Sopenharmony_ci for (i = 0; i < cmapsz; i++) { 9528c2ecf20Sopenharmony_ci vga_writeb(arg[i], charmap + i); 9538c2ecf20Sopenharmony_ci cond_resched(); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci else 9568c2ecf20Sopenharmony_ci for (i = 0; i < cmapsz; i++) { 9578c2ecf20Sopenharmony_ci arg[i] = vga_readb(charmap + i); 9588c2ecf20Sopenharmony_ci cond_resched(); 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 9648c2ecf20Sopenharmony_ci /* First, the sequencer, Synchronous reset */ 9658c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); 9668c2ecf20Sopenharmony_ci /* CPU writes to maps 0 and 1 */ 9678c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03); 9688c2ecf20Sopenharmony_ci /* odd-even addressing */ 9698c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03); 9708c2ecf20Sopenharmony_ci /* Character Map Select */ 9718c2ecf20Sopenharmony_ci if (set) 9728c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select); 9738c2ecf20Sopenharmony_ci /* clear synchronous reset */ 9748c2ecf20Sopenharmony_ci vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03); 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci /* Now, the graphics controller, select map 0 for CPU */ 9778c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00); 9788c2ecf20Sopenharmony_ci /* enable even-odd addressing */ 9798c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10); 9808c2ecf20Sopenharmony_ci /* map starts at b800:0 or b000:0 */ 9818c2ecf20Sopenharmony_ci vga_wgfx(state->vgabase, VGA_GFX_MISC, beg); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* if 512 char mode is already enabled don't re-enable it. */ 9848c2ecf20Sopenharmony_ci if ((set) && (ch512 != vga_512_chars)) { 9858c2ecf20Sopenharmony_ci vga_512_chars = ch512; 9868c2ecf20Sopenharmony_ci /* 256-char: enable intensity bit 9878c2ecf20Sopenharmony_ci 512-char: disable intensity bit */ 9888c2ecf20Sopenharmony_ci inb_p(video_port_status); /* clear address flip-flop */ 9898c2ecf20Sopenharmony_ci /* color plane enable register */ 9908c2ecf20Sopenharmony_ci vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f); 9918c2ecf20Sopenharmony_ci /* Wilton (1987) mentions the following; I don't know what 9928c2ecf20Sopenharmony_ci it means, but it works, and it appears necessary */ 9938c2ecf20Sopenharmony_ci inb_p(video_port_status); 9948c2ecf20Sopenharmony_ci vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); 9958c2ecf20Sopenharmony_ci clear_attribs = true; 9968c2ecf20Sopenharmony_ci } 9978c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci if (clear_attribs) { 10008c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) { 10018c2ecf20Sopenharmony_ci struct vc_data *c = vc_cons[i].d; 10028c2ecf20Sopenharmony_ci if (c && c->vc_sw == &vga_con) { 10038c2ecf20Sopenharmony_ci /* force hi font mask to 0, so we always clear 10048c2ecf20Sopenharmony_ci the bit on either transition */ 10058c2ecf20Sopenharmony_ci c->vc_hi_font_mask = 0x00; 10068c2ecf20Sopenharmony_ci clear_buffer_attributes(c); 10078c2ecf20Sopenharmony_ci c->vc_hi_font_mask = ch512 ? 0x0800 : 0; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci return 0; 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci/* 10158c2ecf20Sopenharmony_ci * Adjust the screen to fit a font of a certain height 10168c2ecf20Sopenharmony_ci */ 10178c2ecf20Sopenharmony_cistatic int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) 10188c2ecf20Sopenharmony_ci{ 10198c2ecf20Sopenharmony_ci unsigned char ovr, vde, fsr; 10208c2ecf20Sopenharmony_ci int rows, maxscan, i; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci rows = vc->vc_scan_lines / fontheight; /* Number of video rows we end up with */ 10238c2ecf20Sopenharmony_ci maxscan = rows * fontheight - 1; /* Scan lines to actually display-1 */ 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* Reprogram the CRTC for the new font size 10268c2ecf20Sopenharmony_ci Note: the attempt to read the overflow register will fail 10278c2ecf20Sopenharmony_ci on an EGA, but using 0xff for the previous value appears to 10288c2ecf20Sopenharmony_ci be OK for EGA text modes in the range 257-512 scan lines, so I 10298c2ecf20Sopenharmony_ci guess we don't need to worry about it. 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci The same applies for the spill bits in the font size and cursor 10328c2ecf20Sopenharmony_ci registers; they are write-only on EGA, but it appears that they 10338c2ecf20Sopenharmony_ci are all don't care bits on EGA, so I guess it doesn't matter. */ 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 10368c2ecf20Sopenharmony_ci outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ 10378c2ecf20Sopenharmony_ci ovr = inb_p(vga_video_port_val); 10388c2ecf20Sopenharmony_ci outb_p(0x09, vga_video_port_reg); /* Font size register */ 10398c2ecf20Sopenharmony_ci fsr = inb_p(vga_video_port_val); 10408c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci vde = maxscan & 0xff; /* Vertical display end reg */ 10438c2ecf20Sopenharmony_ci ovr = (ovr & 0xbd) + /* Overflow register */ 10448c2ecf20Sopenharmony_ci ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3); 10458c2ecf20Sopenharmony_ci fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */ 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci raw_spin_lock_irq(&vga_lock); 10488c2ecf20Sopenharmony_ci outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ 10498c2ecf20Sopenharmony_ci outb_p(ovr, vga_video_port_val); 10508c2ecf20Sopenharmony_ci outb_p(0x09, vga_video_port_reg); /* Font size */ 10518c2ecf20Sopenharmony_ci outb_p(fsr, vga_video_port_val); 10528c2ecf20Sopenharmony_ci outb_p(0x12, vga_video_port_reg); /* Vertical display limit */ 10538c2ecf20Sopenharmony_ci outb_p(vde, vga_video_port_val); 10548c2ecf20Sopenharmony_ci raw_spin_unlock_irq(&vga_lock); 10558c2ecf20Sopenharmony_ci vga_video_font_height = fontheight; 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) { 10588c2ecf20Sopenharmony_ci struct vc_data *c = vc_cons[i].d; 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci if (c && c->vc_sw == &vga_con) { 10618c2ecf20Sopenharmony_ci if (con_is_visible(c)) { 10628c2ecf20Sopenharmony_ci /* void size to cause regs to be rewritten */ 10638c2ecf20Sopenharmony_ci cursor_size_lastfrom = 0; 10648c2ecf20Sopenharmony_ci cursor_size_lastto = 0; 10658c2ecf20Sopenharmony_ci c->vc_sw->con_cursor(c, CM_DRAW); 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci c->vc_font.height = c->vc_cell_height = fontheight; 10688c2ecf20Sopenharmony_ci vc_resize(c, 0, rows); /* Adjust console size */ 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci return 0; 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cistatic int vgacon_font_set(struct vc_data *c, struct console_font *font, 10758c2ecf20Sopenharmony_ci unsigned int flags) 10768c2ecf20Sopenharmony_ci{ 10778c2ecf20Sopenharmony_ci unsigned charcount = font->charcount; 10788c2ecf20Sopenharmony_ci int rc; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (vga_video_type < VIDEO_TYPE_EGAM) 10818c2ecf20Sopenharmony_ci return -EINVAL; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (font->width != VGA_FONTWIDTH || 10848c2ecf20Sopenharmony_ci (charcount != 256 && charcount != 512)) 10858c2ecf20Sopenharmony_ci return -EINVAL; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512); 10888c2ecf20Sopenharmony_ci if (rc) 10898c2ecf20Sopenharmony_ci return rc; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci if (!(flags & KD_FONT_FLAG_DONT_RECALC)) 10928c2ecf20Sopenharmony_ci rc = vgacon_adjust_height(c, font->height); 10938c2ecf20Sopenharmony_ci return rc; 10948c2ecf20Sopenharmony_ci} 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_cistatic int vgacon_font_get(struct vc_data *c, struct console_font *font) 10978c2ecf20Sopenharmony_ci{ 10988c2ecf20Sopenharmony_ci if (vga_video_type < VIDEO_TYPE_EGAM) 10998c2ecf20Sopenharmony_ci return -EINVAL; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci font->width = VGA_FONTWIDTH; 11028c2ecf20Sopenharmony_ci font->height = c->vc_font.height; 11038c2ecf20Sopenharmony_ci font->charcount = vga_512_chars ? 512 : 256; 11048c2ecf20Sopenharmony_ci if (!font->data) 11058c2ecf20Sopenharmony_ci return 0; 11068c2ecf20Sopenharmony_ci return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars); 11078c2ecf20Sopenharmony_ci} 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_cistatic int vgacon_resize(struct vc_data *c, unsigned int width, 11108c2ecf20Sopenharmony_ci unsigned int height, unsigned int user) 11118c2ecf20Sopenharmony_ci{ 11128c2ecf20Sopenharmony_ci if ((width << 1) * height > vga_vram_size) 11138c2ecf20Sopenharmony_ci return -EINVAL; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (user) { 11168c2ecf20Sopenharmony_ci /* 11178c2ecf20Sopenharmony_ci * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed 11188c2ecf20Sopenharmony_ci * the video mode! Set the new defaults then and go away. 11198c2ecf20Sopenharmony_ci */ 11208c2ecf20Sopenharmony_ci screen_info.orig_video_cols = width; 11218c2ecf20Sopenharmony_ci screen_info.orig_video_lines = height; 11228c2ecf20Sopenharmony_ci vga_default_font_height = c->vc_cell_height; 11238c2ecf20Sopenharmony_ci return 0; 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci if (width % 2 || width > screen_info.orig_video_cols || 11268c2ecf20Sopenharmony_ci height > (screen_info.orig_video_lines * vga_default_font_height)/ 11278c2ecf20Sopenharmony_ci c->vc_cell_height) 11288c2ecf20Sopenharmony_ci return -EINVAL; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci if (con_is_visible(c) && !vga_is_gfx) /* who knows */ 11318c2ecf20Sopenharmony_ci vgacon_doresize(c, width, height); 11328c2ecf20Sopenharmony_ci return 0; 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic int vgacon_set_origin(struct vc_data *c) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ 11388c2ecf20Sopenharmony_ci (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ 11398c2ecf20Sopenharmony_ci return 0; 11408c2ecf20Sopenharmony_ci c->vc_origin = c->vc_visible_origin = vga_vram_base; 11418c2ecf20Sopenharmony_ci vga_set_mem_top(c); 11428c2ecf20Sopenharmony_ci vga_rolled_over = 0; 11438c2ecf20Sopenharmony_ci return 1; 11448c2ecf20Sopenharmony_ci} 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_cistatic void vgacon_save_screen(struct vc_data *c) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci static int vga_bootup_console = 0; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (!vga_bootup_console) { 11518c2ecf20Sopenharmony_ci /* This is a gross hack, but here is the only place we can 11528c2ecf20Sopenharmony_ci * set bootup console parameters without messing up generic 11538c2ecf20Sopenharmony_ci * console initialization routines. 11548c2ecf20Sopenharmony_ci */ 11558c2ecf20Sopenharmony_ci vga_bootup_console = 1; 11568c2ecf20Sopenharmony_ci c->state.x = screen_info.orig_x; 11578c2ecf20Sopenharmony_ci c->state.y = screen_info.orig_y; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci /* We can't copy in more than the size of the video buffer, 11618c2ecf20Sopenharmony_ci * or we'll be copying in VGA BIOS */ 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (!vga_is_gfx) 11648c2ecf20Sopenharmony_ci scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, 11658c2ecf20Sopenharmony_ci c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, 11698c2ecf20Sopenharmony_ci enum con_scroll dir, unsigned int lines) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci unsigned long oldo; 11728c2ecf20Sopenharmony_ci unsigned int delta; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT) 11758c2ecf20Sopenharmony_ci return false; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) 11788c2ecf20Sopenharmony_ci return false; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci vgacon_restore_screen(c); 11818c2ecf20Sopenharmony_ci oldo = c->vc_origin; 11828c2ecf20Sopenharmony_ci delta = lines * c->vc_size_row; 11838c2ecf20Sopenharmony_ci if (dir == SM_UP) { 11848c2ecf20Sopenharmony_ci if (c->vc_scr_end + delta >= vga_vram_end) { 11858c2ecf20Sopenharmony_ci scr_memcpyw((u16 *) vga_vram_base, 11868c2ecf20Sopenharmony_ci (u16 *) (oldo + delta), 11878c2ecf20Sopenharmony_ci c->vc_screenbuf_size - delta); 11888c2ecf20Sopenharmony_ci c->vc_origin = vga_vram_base; 11898c2ecf20Sopenharmony_ci vga_rolled_over = oldo - vga_vram_base; 11908c2ecf20Sopenharmony_ci } else 11918c2ecf20Sopenharmony_ci c->vc_origin += delta; 11928c2ecf20Sopenharmony_ci scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size - 11938c2ecf20Sopenharmony_ci delta), c->vc_video_erase_char, 11948c2ecf20Sopenharmony_ci delta); 11958c2ecf20Sopenharmony_ci } else { 11968c2ecf20Sopenharmony_ci if (oldo - delta < vga_vram_base) { 11978c2ecf20Sopenharmony_ci scr_memmovew((u16 *) (vga_vram_end - 11988c2ecf20Sopenharmony_ci c->vc_screenbuf_size + 11998c2ecf20Sopenharmony_ci delta), (u16 *) oldo, 12008c2ecf20Sopenharmony_ci c->vc_screenbuf_size - delta); 12018c2ecf20Sopenharmony_ci c->vc_origin = vga_vram_end - c->vc_screenbuf_size; 12028c2ecf20Sopenharmony_ci vga_rolled_over = 0; 12038c2ecf20Sopenharmony_ci } else 12048c2ecf20Sopenharmony_ci c->vc_origin -= delta; 12058c2ecf20Sopenharmony_ci c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 12068c2ecf20Sopenharmony_ci scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char, 12078c2ecf20Sopenharmony_ci delta); 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 12108c2ecf20Sopenharmony_ci c->vc_visible_origin = c->vc_origin; 12118c2ecf20Sopenharmony_ci vga_set_mem_top(c); 12128c2ecf20Sopenharmony_ci c->vc_pos = (c->vc_pos - oldo) + c->vc_origin; 12138c2ecf20Sopenharmony_ci return true; 12148c2ecf20Sopenharmony_ci} 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci/* 12178c2ecf20Sopenharmony_ci * The console `switch' structure for the VGA based console 12188c2ecf20Sopenharmony_ci */ 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic void vgacon_clear(struct vc_data *vc, int sy, int sx, int height, 12218c2ecf20Sopenharmony_ci int width) { } 12228c2ecf20Sopenharmony_cistatic void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } 12238c2ecf20Sopenharmony_cistatic void vgacon_putcs(struct vc_data *vc, const unsigned short *s, 12248c2ecf20Sopenharmony_ci int count, int ypos, int xpos) { } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ciconst struct consw vga_con = { 12278c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 12288c2ecf20Sopenharmony_ci .con_startup = vgacon_startup, 12298c2ecf20Sopenharmony_ci .con_init = vgacon_init, 12308c2ecf20Sopenharmony_ci .con_deinit = vgacon_deinit, 12318c2ecf20Sopenharmony_ci .con_clear = vgacon_clear, 12328c2ecf20Sopenharmony_ci .con_putc = vgacon_putc, 12338c2ecf20Sopenharmony_ci .con_putcs = vgacon_putcs, 12348c2ecf20Sopenharmony_ci .con_cursor = vgacon_cursor, 12358c2ecf20Sopenharmony_ci .con_scroll = vgacon_scroll, 12368c2ecf20Sopenharmony_ci .con_switch = vgacon_switch, 12378c2ecf20Sopenharmony_ci .con_blank = vgacon_blank, 12388c2ecf20Sopenharmony_ci .con_font_set = vgacon_font_set, 12398c2ecf20Sopenharmony_ci .con_font_get = vgacon_font_get, 12408c2ecf20Sopenharmony_ci .con_resize = vgacon_resize, 12418c2ecf20Sopenharmony_ci .con_set_palette = vgacon_set_palette, 12428c2ecf20Sopenharmony_ci .con_scrolldelta = vgacon_scrolldelta, 12438c2ecf20Sopenharmony_ci .con_set_origin = vgacon_set_origin, 12448c2ecf20Sopenharmony_ci .con_save_screen = vgacon_save_screen, 12458c2ecf20Sopenharmony_ci .con_build_attr = vgacon_build_attr, 12468c2ecf20Sopenharmony_ci .con_invert_region = vgacon_invert_region, 12478c2ecf20Sopenharmony_ci}; 12488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vga_con); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1251