📄 vgacon.c
字号:
/* * linux/drivers/video/vgacon.c -- Low level VGA based console driver * * Created 28 Sep 1997 by Geert Uytterhoeven * * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 * * This file is based on the old console.c, vga.c and vesa_blank.c drivers. * * Copyright (C) 1991, 1992 Linus Torvalds * 1995 Jay Estabrook * * User definable mapping table and font loading by Eugene G. Crosser, * <crosser@average.org> * * Improved loadable font/UTF-8 support by H. Peter Anvin * Feb-Sep 1995 <peter.anvin@linux.org> * * Colour palette handling, by Simon Tatham * 17-Jun-95 <sgt20@cam.ac.uk> * * if 512 char mode is already enabled don't re-enable it, * because it causes screen to flicker, by Mitja Horvat * 5-May-96 <mitja.horvat@guest.arnes.si> * * Use 2 outw instead of 4 outb_p to reduce erroneous text * flashing on RHS of screen during heavy console scrolling . * Oct 1996, Paul Gortmaker. * * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/tty.h>#include <linux/console.h>#include <linux/console_struct.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/slab.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/spinlock.h>#include <linux/ioport.h>#include <linux/init.h>#include <asm/io.h>static spinlock_t vga_lock = SPIN_LOCK_UNLOCKED;#define BLANK 0x0020#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */#define CAN_LOAD_PALETTE /* undefine if the user must not do this *//* You really do _NOT_ want to define this, unless you have buggy * Trident VGA which will resize cursor when moving it between column * 15 & 16. If you define this and your VGA is OK, inverse bug will * appear. */#undef TRIDENT_GLITCH#define dac_reg 0x3c8#define dac_val 0x3c9#define attrib_port 0x3c0#define seq_port_reg 0x3c4#define seq_port_val 0x3c5#define gr_port_reg 0x3ce#define gr_port_val 0x3cf#define video_misc_rd 0x3cc#define video_misc_wr 0x3c2/* * Interface used by the world */static const char *vgacon_startup(void);static void vgacon_init(struct vc_data *c, int init);static void vgacon_deinit(struct vc_data *c);static void vgacon_cursor(struct vc_data *c, int mode);static int vgacon_switch(struct vc_data *c);static int vgacon_blank(struct vc_data *c, int blank);static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);static int vgacon_set_palette(struct vc_data *c, unsigned char *table);static int vgacon_scrolldelta(struct vc_data *c, int lines);static int vgacon_set_origin(struct vc_data *c);static void vgacon_save_screen(struct vc_data *c);static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines);static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);static void vgacon_invert_region(struct vc_data *c, u16 *p, int count);static unsigned long vgacon_uni_pagedir[2];/* Description of the hardware situation */static unsigned long vga_vram_base; /* Base of video memory */static unsigned long vga_vram_end; /* End of video memory */static u16 vga_video_port_reg; /* Video register select port */static u16 vga_video_port_val; /* Video register value port */static unsigned int vga_video_num_columns; /* Number of text columns */static unsigned int vga_video_num_lines; /* Number of text lines */static int vga_can_do_color = 0; /* Do we support colors? */static unsigned int vga_default_font_height; /* Height of default screen font */static unsigned char vga_video_type; /* Card type */static unsigned char vga_hardscroll_enabled;static unsigned char vga_hardscroll_user_enable = 1;static unsigned char vga_font_is_default = 1;static int vga_vesa_blanked;static int vga_palette_blanked;static int vga_is_gfx;static int vga_512_chars;static int vga_video_font_height;static unsigned int vga_rolled_over = 0;static int __init no_scroll(char *str){ /* * Disabling scrollback is required for the Braillex ib80-piezo * Braille reader made by F.H. Papenmeier (Germany). * Use the "no-scroll" bootflag. */ vga_hardscroll_user_enable = vga_hardscroll_enabled = 0; return 1;}__setup("no-scroll", no_scroll);/* * By replacing the four outb_p with two back to back outw, we can reduce * the window of opportunity to see text mislocated to the RHS of the * console during heavy scrolling activity. However there is the remote * possibility that some pre-dinosaur hardware won't like the back to back * I/O. Since the Xservers get away with it, we should be able to as well. */static inline void write_vga(unsigned char reg, unsigned int val){ unsigned int v1, v2; unsigned long flags; /* * ddprintk might set the console position from interrupt * handlers, thus the write has to be IRQ-atomic. */ spin_lock_irqsave(&vga_lock, flags); #ifndef SLOW_VGA v1 = reg + (val & 0xff00); v2 = reg + 1 + ((val << 8) & 0xff00); outw(v1, vga_video_port_reg); outw(v2, vga_video_port_reg);#else outb_p(reg, vga_video_port_reg); outb_p(val >> 8, vga_video_port_val); outb_p(reg+1, vga_video_port_reg); outb_p(val & 0xff, vga_video_port_val);#endif spin_unlock_irqrestore(&vga_lock, flags);}static const char __init *vgacon_startup(void){ const char *display_desc = NULL; u16 saved1, saved2; volatile u16 *p; if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) { no_vga:#ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; return conswitchp->con_startup();#else return NULL;#endif } vga_video_num_lines = ORIG_VIDEO_LINES; vga_video_num_columns = ORIG_VIDEO_COLS; if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */ { vga_vram_base = 0xb0000; vga_video_port_reg = 0x3b4; vga_video_port_val = 0x3b5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF }; vga_video_type = VIDEO_TYPE_EGAM; vga_vram_end = 0xb8000; display_desc = "EGA+"; request_resource(&ioport_resource, &ega_console_resource); } else { static struct resource mda1_console_resource = { "mda", 0x3B0, 0x3BB }; static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF }; vga_video_type = VIDEO_TYPE_MDA; vga_vram_end = 0xb2000; display_desc = "*MDA"; request_resource(&ioport_resource, &mda1_console_resource); request_resource(&ioport_resource, &mda2_console_resource); vga_video_font_height = 14; } } else /* If not, it is color. */ { vga_can_do_color = 1; vga_vram_base = 0xb8000; vga_video_port_reg = 0x3d4; vga_video_port_val = 0x3d5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { int i; vga_vram_end = 0xc0000; if (!ORIG_VIDEO_ISVGA) { static struct resource ega_console_resource = { "ega", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_EGAC; display_desc = "EGA"; request_resource(&ioport_resource, &ega_console_resource); } else { static struct resource vga_console_resource = { "vga+", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_VGAC; display_desc = "VGA+"; request_resource(&ioport_resource, &vga_console_resource);#ifdef VGA_CAN_DO_64KB /* * get 64K rather than 32K of video RAM. * This doesn't actually work on all "VGA" * controllers (it seems like setting MM=01 * and COE=1 isn't necessarily a good idea) */ vga_vram_base = 0xa0000; vga_vram_end = 0xb0000; outb_p (6, 0x3ce) ; outb_p (6, 0x3cf) ;#endif /* * Normalise the palette registers, to point * the 16 screen colours to the first 16 * DAC entries. */ for (i=0; i<16; i++) { inb_p (0x3da) ; outb_p (i, 0x3c0) ; outb_p (i, 0x3c0) ; } outb_p (0x20, 0x3c0) ; /* now set the DAC registers back to their * default values */ for (i=0; i<16; i++) { outb_p (color_table[i], 0x3c8) ; outb_p (default_red[i], 0x3c9) ; outb_p (default_grn[i], 0x3c9) ; outb_p (default_blu[i], 0x3c9) ; } } } else { static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 }; vga_video_type = VIDEO_TYPE_CGA; vga_vram_end = 0xba000; display_desc = "*CGA"; request_resource(&ioport_resource, &cga_console_resource); vga_video_font_height = 8; } } vga_vram_base = VGA_MAP_MEM(vga_vram_base); vga_vram_end = VGA_MAP_MEM(vga_vram_end); /* * Find out if there is a graphics card present. * Are there smarter methods around? */ p = (volatile u16 *)vga_vram_base; saved1 = scr_readw(p); saved2 = scr_readw(p + 1); scr_writew(0xAA55, p); scr_writew(0x55AA, p + 1); if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) { scr_writew(saved1, p); scr_writew(saved2, p + 1); goto no_vga; } scr_writew(0x55AA, p); scr_writew(0xAA55, p + 1); if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) { scr_writew(saved1, p); scr_writew(saved2, p + 1); goto no_vga; } scr_writew(saved1, p); scr_writew(saved2, p + 1); if (vga_video_type == VIDEO_TYPE_EGAC || vga_video_type == VIDEO_TYPE_VGAC || vga_video_type == VIDEO_TYPE_EGAM) { vga_hardscroll_enabled = vga_hardscroll_user_enable; vga_default_font_height = ORIG_VIDEO_POINTS; vga_video_font_height = ORIG_VIDEO_POINTS; /* This may be suboptimal but is a safe bet - go with it */ video_scan_lines = vga_video_font_height * vga_video_num_lines; } video_font_height = vga_video_font_height; return display_desc;}static void vgacon_init(struct vc_data *c, int init){ unsigned long p; /* We cannot be loaded as a module, therefore init is always 1 */ c->vc_can_do_color = vga_can_do_color; c->vc_cols = vga_video_num_columns; c->vc_rows = vga_video_num_lines; c->vc_complement_mask = 0x7700; p = *c->vc_uni_pagedir_loc; if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir || !--c->vc_uni_pagedir_loc[1]) con_free_unimap(c->vc_num); c->vc_uni_pagedir_loc = vgacon_uni_pagedir; vgacon_uni_pagedir[1]++; if (!vgacon_uni_pagedir[0] && p) con_set_default_unimap(c->vc_num);}static inline void vga_set_mem_top(struct vc_data *c){ write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);}static void vgacon_deinit(struct vc_data *c){ /* When closing the last console, reset video origin */ if (!--vgacon_uni_pagedir[1]) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -