^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/vgacon.c -- Low level VGA based console driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Created 28 Sep 1997 by Geert Uytterhoeven
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is based on the old console.c, vga.c and vesa_blank.c drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 1991, 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 1995 Jay Estabrook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * User definable mapping table and font loading by Eugene G. Crosser,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * <crosser@average.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Improved loadable font/UTF-8 support by H. Peter Anvin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Feb-Sep 1995 <peter.anvin@linux.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Colour palette handling, by Simon Tatham
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 17-Jun-95 <sgt20@cam.ac.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * if 512 char mode is already enabled don't re-enable it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * because it causes screen to flicker, by Mitja Horvat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 5-May-96 <mitja.horvat@guest.arnes.si>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Use 2 outw instead of 4 outb_p to reduce erroneous text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * flashing on RHS of screen during heavy console scrolling .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Oct 1996, Paul Gortmaker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/kd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/vt_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/selection.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/screen_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static DEFINE_RAW_SPINLOCK(vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int cursor_size_lastfrom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int cursor_size_lastto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static u32 vgacon_xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static u32 vgacon_yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct vgastate vgastate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define BLANK 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Interface used by the world
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const char *vgacon_startup(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void vgacon_init(struct vc_data *c, int init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void vgacon_deinit(struct vc_data *c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void vgacon_cursor(struct vc_data *c, int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int vgacon_switch(struct vc_data *c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void vgacon_scrolldelta(struct vc_data *c, int lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int vgacon_set_origin(struct vc_data *c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void vgacon_save_screen(struct vc_data *c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static struct uni_pagedir *vgacon_uni_pagedir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int vgacon_refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Description of the hardware situation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static bool vga_init_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static unsigned long vga_vram_end __read_mostly; /* End of video memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static u16 vga_video_port_reg __read_mostly; /* Video register select port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static u16 vga_video_port_val __read_mostly; /* Video register value port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static unsigned int vga_video_num_columns; /* Number of text columns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static unsigned int vga_video_num_lines; /* Number of text lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static bool vga_can_do_color; /* Do we support colors? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static unsigned char vga_video_type __read_mostly; /* Card type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static bool vga_font_is_default = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int vga_vesa_blanked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static bool vga_palette_blanked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static bool vga_is_gfx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static bool vga_512_chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int vga_video_font_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int vga_scan_lines __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static unsigned int vga_rolled_over;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static bool vgacon_text_mode_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static bool vga_hardscroll_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static bool vga_hardscroll_user_enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) bool vgacon_text_force(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return vgacon_text_mode_force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) EXPORT_SYMBOL(vgacon_text_force);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int __init text_mode(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) vgacon_text_mode_force = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pr_warn("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pr_warn("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pr_warn("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* force text mode - used by kernel modesetting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) __setup("nomodeset", text_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int __init no_scroll(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Disabling scrollback is required for the Braillex ib80-piezo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Braille reader made by F.H. Papenmeier (Germany).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Use the "no-scroll" bootflag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) vga_hardscroll_user_enable = vga_hardscroll_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) __setup("no-scroll", no_scroll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * By replacing the four outb_p with two back to back outw, we can reduce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * the window of opportunity to see text mislocated to the RHS of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * console during heavy scrolling activity. However there is the remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * possibility that some pre-dinosaur hardware won't like the back to back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * I/O. Since the Xservers get away with it, we should be able to as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static inline void write_vga(unsigned char reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned int v1, v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * ddprintk might set the console position from interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * handlers, thus the write has to be IRQ-atomic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) raw_spin_lock_irqsave(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) v1 = reg + (val & 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) v2 = reg + 1 + ((val << 8) & 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) outw(v1, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) outw(v2, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) raw_spin_unlock_irqrestore(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static inline void vga_set_mem_top(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void vgacon_restore_screen(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (c->vc_origin != c->vc_visible_origin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) vgacon_scrolldelta(c, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void vgacon_scrolldelta(struct vc_data *c, int lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) vga_vram_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) vga_set_mem_top(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const char *vgacon_startup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const char *display_desc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u16 saved1, saved2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) volatile u16 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) no_vga:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #ifdef CONFIG_DUMMY_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) conswitchp = &dummy_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return conswitchp->con_startup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* boot_params.screen_info reasonably initialized? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if ((screen_info.orig_video_lines == 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) (screen_info.orig_video_cols == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto no_vga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* VGA16 modes are not handled by VGACON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if ((screen_info.orig_video_mode == 0x0D) || /* 320x200/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) (screen_info.orig_video_mode == 0x0E) || /* 640x200/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) (screen_info.orig_video_mode == 0x10) || /* 640x350/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) (screen_info.orig_video_mode == 0x12) || /* 640x480/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (screen_info.orig_video_mode == 0x6A)) /* 800x600/4 (VESA) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto no_vga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) vga_video_num_lines = screen_info.orig_video_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) vga_video_num_columns = screen_info.orig_video_cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) vgastate.vgabase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (screen_info.orig_video_mode == 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* Monochrome display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) vga_vram_base = 0xb0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) vga_video_port_reg = VGA_CRT_IM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) vga_video_port_val = VGA_CRT_DM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static struct resource ega_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { .name = "ega",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .start = 0x3B0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .end = 0x3BF };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) vga_video_type = VIDEO_TYPE_EGAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) vga_vram_size = 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) display_desc = "EGA+";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) &ega_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct resource mda1_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { .name = "mda",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .start = 0x3B0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .end = 0x3BB };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static struct resource mda2_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) { .name = "mda",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .start = 0x3BF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .end = 0x3BF };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) vga_video_type = VIDEO_TYPE_MDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) vga_vram_size = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) display_desc = "*MDA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) &mda1_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) &mda2_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) vga_video_font_height = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* If not, it is color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) vga_can_do_color = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) vga_vram_base = 0xb8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) vga_video_port_reg = VGA_CRT_IC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) vga_video_port_val = VGA_CRT_DC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) vga_vram_size = 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!screen_info.orig_video_isVGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct resource ega_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { .name = "ega",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .start = 0x3C0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .end = 0x3DF };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) vga_video_type = VIDEO_TYPE_EGAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) display_desc = "EGA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) &ega_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static struct resource vga_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { .name = "vga+",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .start = 0x3C0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .end = 0x3DF };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) vga_video_type = VIDEO_TYPE_VGAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) display_desc = "VGA+";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) &vga_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Normalise the palette registers, to point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * the 16 screen colours to the first 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * DAC entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) inb_p(VGA_IS1_RC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) outb_p(i, VGA_ATT_W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) outb_p(i, VGA_ATT_W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) outb_p(0x20, VGA_ATT_W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Now set the DAC registers back to their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * default values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) outb_p(color_table[i], VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) outb_p(default_red[i], VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) outb_p(default_grn[i], VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) outb_p(default_blu[i], VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static struct resource cga_console_resource =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { .name = "cga",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .start = 0x3D4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .end = 0x3D5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) vga_video_type = VIDEO_TYPE_CGA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) vga_vram_size = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) display_desc = "*CGA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) request_resource(&ioport_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) &cga_console_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) vga_video_font_height = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) vga_vram_end = vga_vram_base + vga_vram_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * Find out if there is a graphics card present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Are there smarter methods around?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) p = (volatile u16 *) vga_vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) saved1 = scr_readw(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) saved2 = scr_readw(p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) scr_writew(0xAA55, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) scr_writew(0x55AA, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) scr_writew(saved1, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) scr_writew(saved2, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) goto no_vga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) scr_writew(0x55AA, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) scr_writew(0xAA55, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) scr_writew(saved1, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) scr_writew(saved2, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) goto no_vga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) scr_writew(saved1, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) scr_writew(saved2, p + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (vga_video_type == VIDEO_TYPE_EGAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) || vga_video_type == VIDEO_TYPE_VGAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) || vga_video_type == VIDEO_TYPE_EGAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) vga_hardscroll_enabled = vga_hardscroll_user_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) vga_default_font_height = screen_info.orig_video_points;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) vga_video_font_height = screen_info.orig_video_points;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* This may be suboptimal but is a safe bet - go with it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) vga_scan_lines =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) vga_video_font_height * vga_video_num_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) vgacon_yres = vga_scan_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) vga_init_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return display_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static void vgacon_init(struct vc_data *c, int init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct uni_pagedir *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * We cannot be loaded as a module, therefore init will be 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * if we are the default console, however if we are a fallback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * console, for example if fbcon has failed registration, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * init will be 0, so we need to make sure our boot parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * have been copied to the console structure for vgacon_resize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * ultimately called by vc_resize. Any subsequent calls to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * vgacon_init init will have init set to 0 too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) c->vc_can_do_color = vga_can_do_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) c->vc_scan_lines = vga_scan_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) c->vc_font.height = c->vc_cell_height = vga_video_font_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* set dimensions manually if init != 0 since vc_resize() will fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) c->vc_cols = vga_video_num_columns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) c->vc_rows = vga_video_num_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) vc_resize(c, vga_video_num_columns, vga_video_num_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) c->vc_complement_mask = 0x7700;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (vga_512_chars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) c->vc_hi_font_mask = 0x0800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) p = *c->vc_uni_pagedir_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) con_free_unimap(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) vgacon_refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!vgacon_uni_pagedir && p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) con_set_default_unimap(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Only set the default if the user didn't deliberately override it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (global_cursor_default == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) global_cursor_default =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void vgacon_deinit(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* When closing the active console, reset video origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (con_is_visible(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) c->vc_visible_origin = vga_vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) vga_set_mem_top(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!--vgacon_refcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) con_free_unimap(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) con_set_default_unimap(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static u8 vgacon_build_attr(struct vc_data *c, u8 color,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) enum vc_intensity intensity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) bool blink, bool underline, bool reverse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) bool italic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u8 attr = color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (vga_can_do_color) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (italic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) attr = (attr & 0xF0) | c->vc_itcolor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else if (underline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) attr = (attr & 0xf0) | c->vc_ulcolor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) else if (intensity == VCI_HALF_BRIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) attr = (attr & 0xf0) | c->vc_halfcolor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (reverse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 0x77);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (blink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) attr ^= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (intensity == VCI_BOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) attr ^= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (!vga_can_do_color) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (italic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) attr = (attr & 0xF8) | 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) else if (underline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) attr = (attr & 0xf8) | 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) else if (intensity == VCI_HALF_BRIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) attr = (attr & 0xf0) | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) const bool col = vga_can_do_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) while (count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) u16 a = scr_readw(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (col)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) (((a) & 0x0700) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) scr_writew(a, p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void vgacon_set_cursor_size(int xpos, int from, int to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int curs, cure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) cursor_size_lastfrom = from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) cursor_size_lastto = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) raw_spin_lock_irqsave(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (vga_video_type >= VIDEO_TYPE_VGAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) curs = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) cure = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) curs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) cure = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) curs = (curs & 0xc0) | from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) cure = (cure & 0xe0) | to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) outb_p(curs, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) outb_p(cure, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) raw_spin_unlock_irqrestore(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void vgacon_cursor(struct vc_data *c, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (c->vc_mode != KD_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) vgacon_restore_screen(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case CM_ERASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) write_vga(14, (c->vc_pos - vga_vram_base) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (vga_video_type >= VIDEO_TYPE_VGAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) vgacon_set_cursor_size(c->state.x, 31, 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) vgacon_set_cursor_size(c->state.x, 31, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case CM_MOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) case CM_DRAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) write_vga(14, (c->vc_pos - vga_vram_base) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) switch (CUR_SIZE(c->vc_cursor_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case CUR_UNDERLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) vgacon_set_cursor_size(c->state.x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) c->vc_cell_height -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) (c->vc_cell_height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 10 ? 2 : 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) c->vc_cell_height -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) (c->vc_cell_height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 10 ? 1 : 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) case CUR_TWO_THIRDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) vgacon_set_cursor_size(c->state.x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) c->vc_cell_height / 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) c->vc_cell_height -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (c->vc_cell_height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 10 ? 1 : 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case CUR_LOWER_THIRD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) vgacon_set_cursor_size(c->state.x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) (c->vc_cell_height * 2) / 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) c->vc_cell_height -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) (c->vc_cell_height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 10 ? 1 : 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case CUR_LOWER_HALF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) vgacon_set_cursor_size(c->state.x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) c->vc_cell_height / 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) c->vc_cell_height -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) (c->vc_cell_height <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 10 ? 1 : 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case CUR_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (vga_video_type >= VIDEO_TYPE_VGAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) vgacon_set_cursor_size(c->state.x, 31, 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) vgacon_set_cursor_size(c->state.x, 31, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) vgacon_set_cursor_size(c->state.x, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) c->vc_cell_height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static int vgacon_doresize(struct vc_data *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) unsigned int width, unsigned int height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) unsigned int scanlines = height * c->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) raw_spin_lock_irqsave(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) vgacon_xres = width * VGA_FONTWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) vgacon_yres = height * c->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (vga_video_type >= VIDEO_TYPE_VGAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) max_scan = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (max_scan & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) scanlines <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) outb_p(VGA_CRTC_MODE, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mode = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (mode & 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) scanlines >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) scanlines -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) scanlines_lo = scanlines & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) r7 = inb_p(vga_video_port_val) & ~0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (scanlines & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) r7 |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (scanlines & 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) r7 |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* deprotect registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) vsync_end = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) outb_p(vsync_end & ~0x80, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) outb_p(width - 1, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) outb_p(width >> 1, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (vga_video_type >= VIDEO_TYPE_VGAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) outb_p(scanlines_lo, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) outb_p(r7,vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* reprotect registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) outb_p(vsync_end, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) raw_spin_unlock_irqrestore(&vga_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static int vgacon_switch(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int x = c->vc_cols * VGA_FONTWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int y = c->vc_rows * c->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) int rows = screen_info.orig_video_lines * vga_default_font_height/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) c->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * We need to save screen size here as it's the only way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * we can spot the screen has been resized and we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * set size of freshly allocated screens ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) vga_video_num_columns = c->vc_cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) vga_video_num_lines = c->vc_rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* We can only copy out the size of the video buffer here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * otherwise we get into VGA BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (!vga_is_gfx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) c->vc_screenbuf_size > vga_vram_size ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) vga_vram_size : c->vc_screenbuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if ((vgacon_xres != x || vgacon_yres != y) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) (!(vga_video_num_columns % 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) vga_video_num_columns <= screen_info.orig_video_cols &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) vga_video_num_lines <= rows))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) vgacon_doresize(c, c->vc_cols, c->vc_rows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0; /* Redrawing not needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) for (i = j = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) || !con_is_visible(vc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) vga_set_palette(vc, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* structure holding original VGA register settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) unsigned char SeqCtrlIndex; /* Sequencer Index reg. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) unsigned char CrtMiscIO; /* Miscellaneous register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) unsigned char HorizontalTotal; /* CRT-Controller:00h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) unsigned char HorizDisplayEnd; /* CRT-Controller:01h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) unsigned char StartHorizRetrace; /* CRT-Controller:04h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned char EndHorizRetrace; /* CRT-Controller:05h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) unsigned char Overflow; /* CRT-Controller:07h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) unsigned char StartVertRetrace; /* CRT-Controller:10h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unsigned char EndVertRetrace; /* CRT-Controller:11h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) unsigned char ModeControl; /* CRT-Controller:17h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) unsigned char ClockingMode; /* Seq-Controller:01h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) } vga_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static void vga_vesa_blank(struct vgastate *state, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* save original values of VGA controller registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!vga_vesa_blanked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) vga_state.HorizontalTotal = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) outb_p(0x07, vga_video_port_reg); /* Overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) vga_state.Overflow = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) vga_state.StartVertRetrace = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) vga_state.EndVertRetrace = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) outb_p(0x17, vga_video_port_reg); /* ModeControl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) vga_state.ModeControl = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* assure that video is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* test for vertical retrace in process.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if ((vga_state.CrtMiscIO & 0x80) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * Set <End of vertical retrace> to minimum (0) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * <Start of vertical Retrace> to maximum (incl. overflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * Result: turn off vertical sync (VSync) pulse.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (mode & VESA_VSYNC_SUSPEND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) outb_p(0xff, vga_video_port_val); /* maximum value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) outb_p(0x40, vga_video_port_val); /* minimum (bits 0..3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) outb_p(0x07, vga_video_port_reg); /* Overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) outb_p(vga_state.Overflow | 0x84, vga_video_port_val); /* bits 9,10 of vert. retrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (mode & VESA_HSYNC_SUSPEND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * Set <End of horizontal retrace> to minimum (0) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * <Start of horizontal Retrace> to maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * Result: turn off horizontal sync (HSync) pulse.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) outb_p(0xff, vga_video_port_val); /* maximum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) outb_p(0x00, vga_video_port_val); /* minimum (0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* restore both index registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static void vga_vesa_unblank(struct vgastate *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* restore original values of VGA controller registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) outb_p(vga_state.HorizontalTotal, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) outb_p(0x07, vga_video_port_reg); /* Overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) outb_p(vga_state.Overflow, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) outb_p(vga_state.StartVertRetrace, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) outb_p(vga_state.EndVertRetrace, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) outb_p(0x17, vga_video_port_reg); /* ModeControl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) outb_p(vga_state.ModeControl, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* ClockingMode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* restore index/control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static void vga_pal_blank(struct vgastate *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) vga_w(state->vgabase, VGA_PEL_IW, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) vga_w(state->vgabase, VGA_PEL_D, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) vga_w(state->vgabase, VGA_PEL_D, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) vga_w(state->vgabase, VGA_PEL_D, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case 0: /* Unblank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (vga_vesa_blanked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) vga_vesa_unblank(&vgastate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) vga_vesa_blanked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (vga_palette_blanked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) vga_set_palette(c, color_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) vga_palette_blanked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) vga_is_gfx = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* Tell console.c that it has to restore the screen itself */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) case 1: /* Normal blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case -1: /* Obsolete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) vga_pal_blank(&vgastate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) vga_palette_blanked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) vgacon_set_origin(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) scr_memsetw((void *) vga_vram_base, BLANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) c->vc_screenbuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (mode_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) vga_is_gfx = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) default: /* VESA blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (vga_video_type == VIDEO_TYPE_VGAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) vga_vesa_blank(&vgastate, blank - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) vga_vesa_blanked = blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * PIO_FONT support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * The font loading code goes back to the codepage package by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * Video Systems_ by Richard Wilton. 1987. Microsoft Press".)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * Change for certain monochrome monitors by Yury Shevchuck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * (sizif@botik.yaroslavl.su).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) #define colourmap 0xa0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) should use 0xA0000 for the bwmap as well.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) #define blackwmap 0xa0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) #define cmapsz 8192
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) bool ch512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) unsigned short video_port_status = vga_video_port_reg + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) int font_select = 0x00, beg, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) char *charmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) bool clear_attribs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (vga_video_type != VIDEO_TYPE_EGAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) charmap = (char *) VGA_MAP_MEM(colourmap, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) beg = 0x0e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) beg = 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) #ifdef BROKEN_GRAPHICS_PROGRAMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * All fonts are loaded in slot 0 (0:1 for 512 ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (!arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return -EINVAL; /* Return to default font not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) vga_font_is_default = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) font_select = ch512 ? 0x04 : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * The default font is kept in slot 0 and is never touched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) vga_font_is_default = !arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (!arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ch512 = false; /* Default font is always 256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (!vga_font_is_default)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) charmap += 4 * cmapsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /* First, the Sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /* CPU writes only to map 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Sequential addressing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* Clear synchronous reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Now, the graphics controller, select map 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* disable odd-even addressing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /* map start at A000:0000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) for (i = 0; i < cmapsz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) vga_writeb(arg[i], charmap + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) for (i = 0; i < cmapsz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) arg[i] = vga_readb(charmap + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * In 512-character mode, the character map is not contiguous if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * we want to remain EGA compatible -- which we do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (ch512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) charmap += 2 * cmapsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) arg += cmapsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) for (i = 0; i < cmapsz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) vga_writeb(arg[i], charmap + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) for (i = 0; i < cmapsz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) arg[i] = vga_readb(charmap + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* First, the sequencer, Synchronous reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* CPU writes to maps 0 and 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* odd-even addressing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) /* Character Map Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* clear synchronous reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) /* Now, the graphics controller, select map 0 for CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* enable even-odd addressing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /* map starts at b800:0 or b000:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* if 512 char mode is already enabled don't re-enable it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if ((set) && (ch512 != vga_512_chars)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) vga_512_chars = ch512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* 256-char: enable intensity bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) 512-char: disable intensity bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) inb_p(video_port_status); /* clear address flip-flop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* color plane enable register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /* Wilton (1987) mentions the following; I don't know what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) it means, but it works, and it appears necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) inb_p(video_port_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) clear_attribs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (clear_attribs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) for (i = 0; i < MAX_NR_CONSOLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct vc_data *c = vc_cons[i].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (c && c->vc_sw == &vga_con) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* force hi font mask to 0, so we always clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) the bit on either transition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) c->vc_hi_font_mask = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) clear_buffer_attributes(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * Adjust the screen to fit a font of a certain height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) unsigned char ovr, vde, fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int rows, maxscan, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) rows = vc->vc_scan_lines / fontheight; /* Number of video rows we end up with */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) maxscan = rows * fontheight - 1; /* Scan lines to actually display-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /* Reprogram the CRTC for the new font size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) Note: the attempt to read the overflow register will fail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) on an EGA, but using 0xff for the previous value appears to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) be OK for EGA text modes in the range 257-512 scan lines, so I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) guess we don't need to worry about it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) The same applies for the spill bits in the font size and cursor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) registers; they are write-only on EGA, but it appears that they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) are all don't care bits on EGA, so I guess it doesn't matter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ovr = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) outb_p(0x09, vga_video_port_reg); /* Font size register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) fsr = inb_p(vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) vde = maxscan & 0xff; /* Vertical display end reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) ovr = (ovr & 0xbd) + /* Overflow register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) raw_spin_lock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) outb_p(ovr, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) outb_p(0x09, vga_video_port_reg); /* Font size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) outb_p(fsr, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) outb_p(vde, vga_video_port_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) raw_spin_unlock_irq(&vga_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) vga_video_font_height = fontheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) for (i = 0; i < MAX_NR_CONSOLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct vc_data *c = vc_cons[i].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (c && c->vc_sw == &vga_con) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (con_is_visible(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* void size to cause regs to be rewritten */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) cursor_size_lastfrom = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) cursor_size_lastto = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) c->vc_sw->con_cursor(c, CM_DRAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) c->vc_font.height = c->vc_cell_height = fontheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) vc_resize(c, 0, rows); /* Adjust console size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static int vgacon_font_set(struct vc_data *c, struct console_font *font,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) unsigned charcount = font->charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (vga_video_type < VIDEO_TYPE_EGAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (font->width != VGA_FONTWIDTH ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) (charcount != 256 && charcount != 512))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!(flags & KD_FONT_FLAG_DONT_RECALC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) rc = vgacon_adjust_height(c, font->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static int vgacon_font_get(struct vc_data *c, struct console_font *font)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (vga_video_type < VIDEO_TYPE_EGAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) font->width = VGA_FONTWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) font->height = c->vc_font.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) font->charcount = vga_512_chars ? 512 : 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (!font->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int vgacon_resize(struct vc_data *c, unsigned int width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) unsigned int height, unsigned int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if ((width << 1) * height > vga_vram_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (user) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * the video mode! Set the new defaults then and go away.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) screen_info.orig_video_cols = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) screen_info.orig_video_lines = height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) vga_default_font_height = c->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (width % 2 || width > screen_info.orig_video_cols ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) height > (screen_info.orig_video_lines * vga_default_font_height)/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) c->vc_cell_height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (con_is_visible(c) && !vga_is_gfx) /* who knows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) vgacon_doresize(c, width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) static int vgacon_set_origin(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) c->vc_origin = c->vc_visible_origin = vga_vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) vga_set_mem_top(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) vga_rolled_over = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static void vgacon_save_screen(struct vc_data *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static int vga_bootup_console = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (!vga_bootup_console) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* This is a gross hack, but here is the only place we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * set bootup console parameters without messing up generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * console initialization routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) vga_bootup_console = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) c->state.x = screen_info.orig_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) c->state.y = screen_info.orig_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* We can't copy in more than the size of the video buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * or we'll be copying in VGA BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (!vga_is_gfx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) enum con_scroll dir, unsigned int lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) unsigned long oldo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) unsigned int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) vgacon_restore_screen(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) oldo = c->vc_origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) delta = lines * c->vc_size_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (dir == SM_UP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (c->vc_scr_end + delta >= vga_vram_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) scr_memcpyw((u16 *) vga_vram_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) (u16 *) (oldo + delta),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) c->vc_screenbuf_size - delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) c->vc_origin = vga_vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) vga_rolled_over = oldo - vga_vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) c->vc_origin += delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) delta), c->vc_video_erase_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (oldo - delta < vga_vram_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) scr_memmovew((u16 *) (vga_vram_end -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) c->vc_screenbuf_size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) delta), (u16 *) oldo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) c->vc_screenbuf_size - delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) vga_rolled_over = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) c->vc_origin -= delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) c->vc_visible_origin = c->vc_origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) vga_set_mem_top(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * The console `switch' structure for the VGA based console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int width) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int count, int ypos, int xpos) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) const struct consw vga_con = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) .con_startup = vgacon_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) .con_init = vgacon_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) .con_deinit = vgacon_deinit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) .con_clear = vgacon_clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) .con_putc = vgacon_putc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) .con_putcs = vgacon_putcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) .con_cursor = vgacon_cursor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) .con_scroll = vgacon_scroll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) .con_switch = vgacon_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) .con_blank = vgacon_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) .con_font_set = vgacon_font_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) .con_font_get = vgacon_font_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) .con_resize = vgacon_resize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) .con_set_palette = vgacon_set_palette,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) .con_scrolldelta = vgacon_scrolldelta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) .con_set_origin = vgacon_set_origin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .con_save_screen = vgacon_save_screen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) .con_build_attr = vgacon_build_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .con_invert_region = vgacon_invert_region,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) EXPORT_SYMBOL(vga_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) MODULE_LICENSE("GPL");