2 * linux/drivers/video/vgacon.c -- Low level VGA based console driver
4 * Created 28 Sep 1997 by Geert Uytterhoeven
6 * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
8 * This file is based on the old console.c, vga.c and vesa_blank.c drivers.
10 * Copyright (C) 1991, 1992 Linus Torvalds
13 * User definable mapping table and font loading by Eugene G. Crosser,
14 * <crosser@average.org>
16 * Improved loadable font/UTF-8 support by H. Peter Anvin
17 * Feb-Sep 1995 <peter.anvin@linux.org>
19 * Colour palette handling, by Simon Tatham
20 * 17-Jun-95 <sgt20@cam.ac.uk>
22 * if 512 char mode is already enabled don't re-enable it,
23 * because it causes screen to flicker, by Mitja Horvat
24 * 5-May-96 <mitja.horvat@guest.arnes.si>
26 * Use 2 outw instead of 4 outb_p to reduce erroneous text
27 * flashing on RHS of screen during heavy console scrolling .
28 * Oct 1996, Paul Gortmaker.
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive for
36 #include <linux/module.h>
37 #include <linux/types.h>
39 #include <linux/kernel.h>
40 #include <linux/console.h>
41 #include <linux/string.h>
43 #include <linux/slab.h>
44 #include <linux/vt_kern.h>
45 #include <linux/sched.h>
46 #include <linux/selection.h>
47 #include <linux/spinlock.h>
48 #include <linux/ioport.h>
49 #include <linux/init.h>
50 #include <linux/screen_info.h>
51 #include <video/vga.h>
54 static DEFINE_RAW_SPINLOCK(vga_lock);
55 static int cursor_size_lastfrom;
56 static int cursor_size_lastto;
57 static u32 vgacon_xres;
58 static u32 vgacon_yres;
59 static struct vgastate vgastate;
63 #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */
64 #define CAN_LOAD_PALETTE /* undefine if the user must not do this */
66 /* You really do _NOT_ want to define this, unless you have buggy
67 * Trident VGA which will resize cursor when moving it between column
68 * 15 & 16. If you define this and your VGA is OK, inverse bug will
72 #define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */
74 * Interface used by the world
77 static const char *vgacon_startup(void);
78 static void vgacon_init(struct vc_data *c, int init);
79 static void vgacon_deinit(struct vc_data *c);
80 static void vgacon_cursor(struct vc_data *c, int mode);
81 static int vgacon_switch(struct vc_data *c);
82 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
83 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);
84 static int vgacon_scrolldelta(struct vc_data *c, int lines);
85 static int vgacon_set_origin(struct vc_data *c);
86 static void vgacon_save_screen(struct vc_data *c);
87 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
89 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
90 static struct uni_pagedir *vgacon_uni_pagedir;
91 static int vgacon_refcount;
93 /* Description of the hardware situation */
94 static int vga_init_done __read_mostly;
95 static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
96 static unsigned long vga_vram_end __read_mostly; /* End of video memory */
97 static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
98 static u16 vga_video_port_reg __read_mostly; /* Video register select port */
99 static u16 vga_video_port_val __read_mostly; /* Video register value port */
100 static unsigned int vga_video_num_columns; /* Number of text columns */
101 static unsigned int vga_video_num_lines; /* Number of text lines */
102 static int vga_can_do_color __read_mostly; /* Do we support colors? */
103 static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */
104 static unsigned char vga_video_type __read_mostly; /* Card type */
105 static unsigned char vga_hardscroll_enabled __read_mostly;
106 static unsigned char vga_hardscroll_user_enable __read_mostly = 1;
107 static unsigned char vga_font_is_default = 1;
108 static int vga_vesa_blanked;
109 static int vga_palette_blanked;
110 static int vga_is_gfx;
111 static int vga_512_chars;
112 static int vga_video_font_height;
113 static int vga_scan_lines __read_mostly;
114 static unsigned int vga_rolled_over;
116 static int vgacon_text_mode_force;
118 bool vgacon_text_force(void)
120 return vgacon_text_mode_force ? true : false;
122 EXPORT_SYMBOL(vgacon_text_force);
124 static int __init text_mode(char *str)
126 vgacon_text_mode_force = 1;
130 /* force text mode - used by kernel modesetting */
131 __setup("nomodeset", text_mode);
133 static int __init no_scroll(char *str)
136 * Disabling scrollback is required for the Braillex ib80-piezo
137 * Braille reader made by F.H. Papenmeier (Germany).
138 * Use the "no-scroll" bootflag.
140 vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
144 __setup("no-scroll", no_scroll);
147 * By replacing the four outb_p with two back to back outw, we can reduce
148 * the window of opportunity to see text mislocated to the RHS of the
149 * console during heavy scrolling activity. However there is the remote
150 * possibility that some pre-dinosaur hardware won't like the back to back
151 * I/O. Since the Xservers get away with it, we should be able to as well.
153 static inline void write_vga(unsigned char reg, unsigned int val)
159 * ddprintk might set the console position from interrupt
160 * handlers, thus the write has to be IRQ-atomic.
162 raw_spin_lock_irqsave(&vga_lock, flags);
165 v1 = reg + (val & 0xff00);
166 v2 = reg + 1 + ((val << 8) & 0xff00);
167 outw(v1, vga_video_port_reg);
168 outw(v2, vga_video_port_reg);
170 outb_p(reg, vga_video_port_reg);
171 outb_p(val >> 8, vga_video_port_val);
172 outb_p(reg + 1, vga_video_port_reg);
173 outb_p(val & 0xff, vga_video_port_val);
175 raw_spin_unlock_irqrestore(&vga_lock, flags);
178 static inline void vga_set_mem_top(struct vc_data *c)
180 write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
183 static void vgacon_restore_screen(struct vc_data *c)
185 if (c->vc_origin != c->vc_visible_origin)
186 vgacon_scrolldelta(c, 0);
189 static int vgacon_scrolldelta(struct vc_data *c, int lines)
191 if (!lines) /* Turn scrollback off */
192 c->vc_visible_origin = c->vc_origin;
194 int margin = c->vc_size_row * 4;
197 if (vga_rolled_over >
198 (c->vc_scr_end - vga_vram_base) + margin) {
199 ul = c->vc_scr_end - vga_vram_base;
200 we = vga_rolled_over + c->vc_size_row;
205 p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
206 lines * c->vc_size_row;
207 st = (c->vc_origin - vga_vram_base - ul + we) % we;
214 c->vc_visible_origin = vga_vram_base + (p + ul) % we;
220 static const char *vgacon_startup(void)
222 const char *display_desc = NULL;
226 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
227 screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
229 #ifdef CONFIG_DUMMY_CONSOLE
230 conswitchp = &dummy_con;
231 return conswitchp->con_startup();
237 /* boot_params.screen_info initialized? */
238 if ((screen_info.orig_video_mode == 0) &&
239 (screen_info.orig_video_lines == 0) &&
240 (screen_info.orig_video_cols == 0))
243 /* VGA16 modes are not handled by VGACON */
244 if ((screen_info.orig_video_mode == 0x0D) || /* 320x200/4 */
245 (screen_info.orig_video_mode == 0x0E) || /* 640x200/4 */
246 (screen_info.orig_video_mode == 0x10) || /* 640x350/4 */
247 (screen_info.orig_video_mode == 0x12) || /* 640x480/4 */
248 (screen_info.orig_video_mode == 0x6A)) /* 800x600/4 (VESA) */
251 vga_video_num_lines = screen_info.orig_video_lines;
252 vga_video_num_columns = screen_info.orig_video_cols;
253 vgastate.vgabase = NULL;
255 if (screen_info.orig_video_mode == 7) {
256 /* Monochrome display */
257 vga_vram_base = 0xb0000;
258 vga_video_port_reg = VGA_CRT_IM;
259 vga_video_port_val = VGA_CRT_DM;
260 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
261 static struct resource ega_console_resource =
263 .flags = IORESOURCE_IO,
266 vga_video_type = VIDEO_TYPE_EGAM;
267 vga_vram_size = 0x8000;
268 display_desc = "EGA+";
269 request_resource(&ioport_resource,
270 &ega_console_resource);
272 static struct resource mda1_console_resource =
274 .flags = IORESOURCE_IO,
277 static struct resource mda2_console_resource =
279 .flags = IORESOURCE_IO,
282 vga_video_type = VIDEO_TYPE_MDA;
283 vga_vram_size = 0x2000;
284 display_desc = "*MDA";
285 request_resource(&ioport_resource,
286 &mda1_console_resource);
287 request_resource(&ioport_resource,
288 &mda2_console_resource);
289 vga_video_font_height = 14;
292 /* If not, it is color. */
293 vga_can_do_color = 1;
294 vga_vram_base = 0xb8000;
295 vga_video_port_reg = VGA_CRT_IC;
296 vga_video_port_val = VGA_CRT_DC;
297 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
300 vga_vram_size = 0x8000;
302 if (!screen_info.orig_video_isVGA) {
303 static struct resource ega_console_resource =
305 .flags = IORESOURCE_IO,
308 vga_video_type = VIDEO_TYPE_EGAC;
309 display_desc = "EGA";
310 request_resource(&ioport_resource,
311 &ega_console_resource);
313 static struct resource vga_console_resource =
315 .flags = IORESOURCE_IO,
318 vga_video_type = VIDEO_TYPE_VGAC;
319 display_desc = "VGA+";
320 request_resource(&ioport_resource,
321 &vga_console_resource);
323 #ifdef VGA_CAN_DO_64KB
325 * get 64K rather than 32K of video RAM.
326 * This doesn't actually work on all "VGA"
327 * controllers (it seems like setting MM=01
328 * and COE=1 isn't necessarily a good idea)
330 vga_vram_base = 0xa0000;
331 vga_vram_size = 0x10000;
332 outb_p(6, VGA_GFX_I);
333 outb_p(6, VGA_GFX_D);
336 * Normalise the palette registers, to point
337 * the 16 screen colours to the first 16
341 for (i = 0; i < 16; i++) {
343 outb_p(i, VGA_ATT_W);
344 outb_p(i, VGA_ATT_W);
346 outb_p(0x20, VGA_ATT_W);
349 * Now set the DAC registers back to their
352 for (i = 0; i < 16; i++) {
353 outb_p(color_table[i], VGA_PEL_IW);
354 outb_p(default_red[i], VGA_PEL_D);
355 outb_p(default_grn[i], VGA_PEL_D);
356 outb_p(default_blu[i], VGA_PEL_D);
360 static struct resource cga_console_resource =
362 .flags = IORESOURCE_IO,
365 vga_video_type = VIDEO_TYPE_CGA;
366 vga_vram_size = 0x2000;
367 display_desc = "*CGA";
368 request_resource(&ioport_resource,
369 &cga_console_resource);
370 vga_video_font_height = 8;
374 vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
375 vga_vram_end = vga_vram_base + vga_vram_size;
378 * Find out if there is a graphics card present.
379 * Are there smarter methods around?
381 p = (volatile u16 *) vga_vram_base;
382 saved1 = scr_readw(p);
383 saved2 = scr_readw(p + 1);
384 scr_writew(0xAA55, p);
385 scr_writew(0x55AA, p + 1);
386 if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
387 scr_writew(saved1, p);
388 scr_writew(saved2, p + 1);
391 scr_writew(0x55AA, p);
392 scr_writew(0xAA55, p + 1);
393 if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
394 scr_writew(saved1, p);
395 scr_writew(saved2, p + 1);
398 scr_writew(saved1, p);
399 scr_writew(saved2, p + 1);
401 if (vga_video_type == VIDEO_TYPE_EGAC
402 || vga_video_type == VIDEO_TYPE_VGAC
403 || vga_video_type == VIDEO_TYPE_EGAM) {
404 vga_hardscroll_enabled = vga_hardscroll_user_enable;
405 vga_default_font_height = screen_info.orig_video_points;
406 vga_video_font_height = screen_info.orig_video_points;
407 /* This may be suboptimal but is a safe bet - go with it */
409 vga_video_font_height * vga_video_num_lines;
412 vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
413 vgacon_yres = vga_scan_lines;
420 static void vgacon_init(struct vc_data *c, int init)
422 struct uni_pagedir *p;
425 * We cannot be loaded as a module, therefore init will be 1
426 * if we are the default console, however if we are a fallback
427 * console, for example if fbcon has failed registration, then
428 * init will be 0, so we need to make sure our boot parameters
429 * have been copied to the console structure for vgacon_resize
430 * ultimately called by vc_resize. Any subsequent calls to
431 * vgacon_init init will have init set to 0 too.
433 c->vc_can_do_color = vga_can_do_color;
434 c->vc_scan_lines = vga_scan_lines;
435 c->vc_font.height = c->vc_cell_height = vga_video_font_height;
437 /* set dimensions manually if init != 0 since vc_resize() will fail */
439 c->vc_cols = vga_video_num_columns;
440 c->vc_rows = vga_video_num_lines;
442 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
444 c->vc_complement_mask = 0x7700;
446 c->vc_hi_font_mask = 0x0800;
447 p = *c->vc_uni_pagedir_loc;
448 if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
450 c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
453 if (!vgacon_uni_pagedir && p)
454 con_set_default_unimap(c);
456 /* Only set the default if the user didn't deliberately override it */
457 if (global_cursor_default == -1)
458 global_cursor_default =
459 !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
462 static void vgacon_deinit(struct vc_data *c)
464 /* When closing the active console, reset video origin */
465 if (CON_IS_VISIBLE(c)) {
466 c->vc_visible_origin = vga_vram_base;
470 if (!--vgacon_refcount)
472 c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
473 con_set_default_unimap(c);
476 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
477 u8 blink, u8 underline, u8 reverse, u8 italic)
481 if (vga_can_do_color) {
483 attr = (attr & 0xF0) | c->vc_itcolor;
485 attr = (attr & 0xf0) | c->vc_ulcolor;
486 else if (intensity == 0)
487 attr = (attr & 0xf0) | c->vc_halfcolor;
491 ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
497 if (!vga_can_do_color) {
499 attr = (attr & 0xF8) | 0x02;
501 attr = (attr & 0xf8) | 0x01;
502 else if (intensity == 0)
503 attr = (attr & 0xf0) | 0x08;
508 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
510 int col = vga_can_do_color;
513 u16 a = scr_readw(p);
515 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
516 (((a) & 0x0700) << 4);
518 a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
523 static void vgacon_set_cursor_size(int xpos, int from, int to)
528 #ifdef TRIDENT_GLITCH
533 if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
535 cursor_size_lastfrom = from;
536 cursor_size_lastto = to;
538 raw_spin_lock_irqsave(&vga_lock, flags);
539 if (vga_video_type >= VIDEO_TYPE_VGAC) {
540 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
541 curs = inb_p(vga_video_port_val);
542 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
543 cure = inb_p(vga_video_port_val);
549 curs = (curs & 0xc0) | from;
550 cure = (cure & 0xe0) | to;
552 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
553 outb_p(curs, vga_video_port_val);
554 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
555 outb_p(cure, vga_video_port_val);
556 raw_spin_unlock_irqrestore(&vga_lock, flags);
559 static void vgacon_cursor(struct vc_data *c, int mode)
561 if (c->vc_mode != KD_TEXT)
564 vgacon_restore_screen(c);
568 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
569 if (vga_video_type >= VIDEO_TYPE_VGAC)
570 vgacon_set_cursor_size(c->vc_x, 31, 30);
572 vgacon_set_cursor_size(c->vc_x, 31, 31);
577 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
578 switch (c->vc_cursor_type & 0x0f) {
580 vgacon_set_cursor_size(c->vc_x,
589 vgacon_set_cursor_size(c->vc_x,
590 c->vc_cell_height / 3,
595 case CUR_LOWER_THIRD:
596 vgacon_set_cursor_size(c->vc_x,
597 (c->vc_cell_height * 2) / 3,
603 vgacon_set_cursor_size(c->vc_x,
604 c->vc_cell_height / 2,
610 if (vga_video_type >= VIDEO_TYPE_VGAC)
611 vgacon_set_cursor_size(c->vc_x, 31, 30);
613 vgacon_set_cursor_size(c->vc_x, 31, 31);
616 vgacon_set_cursor_size(c->vc_x, 1,
624 static int vgacon_doresize(struct vc_data *c,
625 unsigned int width, unsigned int height)
628 unsigned int scanlines = height * c->vc_cell_height;
629 u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
631 raw_spin_lock_irqsave(&vga_lock, flags);
633 vgacon_xres = width * VGA_FONTWIDTH;
634 vgacon_yres = height * c->vc_cell_height;
635 if (vga_video_type >= VIDEO_TYPE_VGAC) {
636 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
637 max_scan = inb_p(vga_video_port_val);
642 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
643 mode = inb_p(vga_video_port_val);
649 scanlines_lo = scanlines & 0xff;
651 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
652 r7 = inb_p(vga_video_port_val) & ~0x42;
654 if (scanlines & 0x100)
656 if (scanlines & 0x200)
659 /* deprotect registers */
660 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
661 vsync_end = inb_p(vga_video_port_val);
662 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
663 outb_p(vsync_end & ~0x80, vga_video_port_val);
666 outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
667 outb_p(width - 1, vga_video_port_val);
668 outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
669 outb_p(width >> 1, vga_video_port_val);
671 if (vga_video_type >= VIDEO_TYPE_VGAC) {
672 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
673 outb_p(scanlines_lo, vga_video_port_val);
674 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
675 outb_p(r7,vga_video_port_val);
677 /* reprotect registers */
678 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
679 outb_p(vsync_end, vga_video_port_val);
682 raw_spin_unlock_irqrestore(&vga_lock, flags);
686 static int vgacon_switch(struct vc_data *c)
688 int x = c->vc_cols * VGA_FONTWIDTH;
689 int y = c->vc_rows * c->vc_cell_height;
690 int rows = screen_info.orig_video_lines * vga_default_font_height/
693 * We need to save screen size here as it's the only way
694 * we can spot the screen has been resized and we need to
695 * set size of freshly allocated screens ourselves.
697 vga_video_num_columns = c->vc_cols;
698 vga_video_num_lines = c->vc_rows;
700 /* We can only copy out the size of the video buffer here,
701 * otherwise we get into VGA BIOS */
704 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
705 c->vc_screenbuf_size > vga_vram_size ?
706 vga_vram_size : c->vc_screenbuf_size);
708 if ((vgacon_xres != x || vgacon_yres != y) &&
709 (!(vga_video_num_columns % 2) &&
710 vga_video_num_columns <= screen_info.orig_video_cols &&
711 vga_video_num_lines <= rows))
712 vgacon_doresize(c, c->vc_cols, c->vc_rows);
715 return 0; /* Redrawing not needed */
718 static void vga_set_palette(struct vc_data *vc, unsigned char *table)
722 vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
723 for (i = j = 0; i < 16; i++) {
724 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
725 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
726 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
727 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
731 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
733 #ifdef CAN_LOAD_PALETTE
734 if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
735 || !CON_IS_VISIBLE(vc))
737 vga_set_palette(vc, table);
744 /* structure holding original VGA register settings */
746 unsigned char SeqCtrlIndex; /* Sequencer Index reg. */
747 unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */
748 unsigned char CrtMiscIO; /* Miscellaneous register */
749 unsigned char HorizontalTotal; /* CRT-Controller:00h */
750 unsigned char HorizDisplayEnd; /* CRT-Controller:01h */
751 unsigned char StartHorizRetrace; /* CRT-Controller:04h */
752 unsigned char EndHorizRetrace; /* CRT-Controller:05h */
753 unsigned char Overflow; /* CRT-Controller:07h */
754 unsigned char StartVertRetrace; /* CRT-Controller:10h */
755 unsigned char EndVertRetrace; /* CRT-Controller:11h */
756 unsigned char ModeControl; /* CRT-Controller:17h */
757 unsigned char ClockingMode; /* Seq-Controller:01h */
760 static void vga_vesa_blank(struct vgastate *state, int mode)
762 /* save original values of VGA controller registers */
763 if (!vga_vesa_blanked) {
764 raw_spin_lock_irq(&vga_lock);
765 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
766 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
767 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
768 raw_spin_unlock_irq(&vga_lock);
770 outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
771 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
772 outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
773 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
774 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
775 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
776 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
777 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
778 outb_p(0x07, vga_video_port_reg); /* Overflow */
779 vga_state.Overflow = inb_p(vga_video_port_val);
780 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
781 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
782 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
783 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
784 outb_p(0x17, vga_video_port_reg); /* ModeControl */
785 vga_state.ModeControl = inb_p(vga_video_port_val);
786 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
789 /* assure that video is enabled */
790 /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
791 raw_spin_lock_irq(&vga_lock);
792 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
794 /* test for vertical retrace in process.... */
795 if ((vga_state.CrtMiscIO & 0x80) == 0x80)
796 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
799 * Set <End of vertical retrace> to minimum (0) and
800 * <Start of vertical Retrace> to maximum (incl. overflow)
801 * Result: turn off vertical sync (VSync) pulse.
803 if (mode & VESA_VSYNC_SUSPEND) {
804 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
805 outb_p(0xff, vga_video_port_val); /* maximum value */
806 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
807 outb_p(0x40, vga_video_port_val); /* minimum (bits 0..3) */
808 outb_p(0x07, vga_video_port_reg); /* Overflow */
809 outb_p(vga_state.Overflow | 0x84, vga_video_port_val); /* bits 9,10 of vert. retrace */
812 if (mode & VESA_HSYNC_SUSPEND) {
814 * Set <End of horizontal retrace> to minimum (0) and
815 * <Start of horizontal Retrace> to maximum
816 * Result: turn off horizontal sync (HSync) pulse.
818 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
819 outb_p(0xff, vga_video_port_val); /* maximum */
820 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
821 outb_p(0x00, vga_video_port_val); /* minimum (0) */
824 /* restore both index registers */
825 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
826 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
827 raw_spin_unlock_irq(&vga_lock);
830 static void vga_vesa_unblank(struct vgastate *state)
832 /* restore original values of VGA controller registers */
833 raw_spin_lock_irq(&vga_lock);
834 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
836 outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
837 outb_p(vga_state.HorizontalTotal, vga_video_port_val);
838 outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
839 outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
840 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
841 outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
842 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
843 outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
844 outb_p(0x07, vga_video_port_reg); /* Overflow */
845 outb_p(vga_state.Overflow, vga_video_port_val);
846 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
847 outb_p(vga_state.StartVertRetrace, vga_video_port_val);
848 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
849 outb_p(vga_state.EndVertRetrace, vga_video_port_val);
850 outb_p(0x17, vga_video_port_reg); /* ModeControl */
851 outb_p(vga_state.ModeControl, vga_video_port_val);
853 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
855 /* restore index/control registers */
856 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
857 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
858 raw_spin_unlock_irq(&vga_lock);
861 static void vga_pal_blank(struct vgastate *state)
865 vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
866 for (i = 0; i < 16; i++) {
867 vga_w(state->vgabase, VGA_PEL_IW, i);
868 vga_w(state->vgabase, VGA_PEL_D, 0);
869 vga_w(state->vgabase, VGA_PEL_D, 0);
870 vga_w(state->vgabase, VGA_PEL_D, 0);
874 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
877 case 0: /* Unblank */
878 if (vga_vesa_blanked) {
879 vga_vesa_unblank(&vgastate);
880 vga_vesa_blanked = 0;
882 if (vga_palette_blanked) {
883 vga_set_palette(c, color_table);
884 vga_palette_blanked = 0;
888 /* Tell console.c that it has to restore the screen itself */
890 case 1: /* Normal blanking */
891 case -1: /* Obsolete */
892 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
893 vga_pal_blank(&vgastate);
894 vga_palette_blanked = 1;
897 vgacon_set_origin(c);
898 scr_memsetw((void *) vga_vram_base, BLANK,
899 c->vc_screenbuf_size);
903 default: /* VESA blanking */
904 if (vga_video_type == VIDEO_TYPE_VGAC) {
905 vga_vesa_blank(&vgastate, blank - 1);
906 vga_vesa_blanked = blank;
915 * The font loading code goes back to the codepage package by
916 * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
917 * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
918 * Video Systems_ by Richard Wilton. 1987. Microsoft Press".)
920 * Change for certain monochrome monitors by Yury Shevchuck
921 * (sizif@botik.yaroslavl.su).
924 #ifdef CAN_LOAD_EGA_FONTS
926 #define colourmap 0xa0000
927 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
928 should use 0xA0000 for the bwmap as well.. */
929 #define blackwmap 0xa0000
932 static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
934 unsigned short video_port_status = vga_video_port_reg + 6;
935 int font_select = 0x00, beg, i;
937 bool clear_attribs = false;
938 if (vga_video_type != VIDEO_TYPE_EGAM) {
939 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
941 #ifdef VGA_CAN_DO_64KB
942 if (vga_video_type == VIDEO_TYPE_VGAC)
946 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
950 #ifdef BROKEN_GRAPHICS_PROGRAMS
952 * All fonts are loaded in slot 0 (0:1 for 512 ch)
956 return -EINVAL; /* Return to default font not supported */
958 vga_font_is_default = 0;
959 font_select = ch512 ? 0x04 : 0x00;
962 * The default font is kept in slot 0 and is never touched.
963 * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
967 vga_font_is_default = !arg;
969 ch512 = 0; /* Default font is always 256 */
970 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
973 if (!vga_font_is_default)
974 charmap += 4 * cmapsz;
977 raw_spin_lock_irq(&vga_lock);
978 /* First, the Sequencer */
979 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
980 /* CPU writes only to map 2 */
981 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
982 /* Sequential addressing */
983 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
984 /* Clear synchronous reset */
985 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
987 /* Now, the graphics controller, select map 2 */
988 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
989 /* disable odd-even addressing */
990 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
991 /* map start at A000:0000 */
992 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
993 raw_spin_unlock_irq(&vga_lock);
997 for (i = 0; i < cmapsz; i++) {
998 vga_writeb(arg[i], charmap + i);
1002 for (i = 0; i < cmapsz; i++) {
1003 arg[i] = vga_readb(charmap + i);
1008 * In 512-character mode, the character map is not contiguous if
1009 * we want to remain EGA compatible -- which we do
1013 charmap += 2 * cmapsz;
1016 for (i = 0; i < cmapsz; i++) {
1017 vga_writeb(arg[i], charmap + i);
1021 for (i = 0; i < cmapsz; i++) {
1022 arg[i] = vga_readb(charmap + i);
1028 raw_spin_lock_irq(&vga_lock);
1029 /* First, the sequencer, Synchronous reset */
1030 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
1031 /* CPU writes to maps 0 and 1 */
1032 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
1033 /* odd-even addressing */
1034 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
1035 /* Character Map Select */
1037 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
1038 /* clear synchronous reset */
1039 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1041 /* Now, the graphics controller, select map 0 for CPU */
1042 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
1043 /* enable even-odd addressing */
1044 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
1045 /* map starts at b800:0 or b000:0 */
1046 vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
1048 /* if 512 char mode is already enabled don't re-enable it. */
1049 if ((set) && (ch512 != vga_512_chars)) {
1050 vga_512_chars = ch512;
1051 /* 256-char: enable intensity bit
1052 512-char: disable intensity bit */
1053 inb_p(video_port_status); /* clear address flip-flop */
1054 /* color plane enable register */
1055 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
1056 /* Wilton (1987) mentions the following; I don't know what
1057 it means, but it works, and it appears necessary */
1058 inb_p(video_port_status);
1059 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1060 clear_attribs = true;
1062 raw_spin_unlock_irq(&vga_lock);
1064 if (clear_attribs) {
1065 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1066 struct vc_data *c = vc_cons[i].d;
1067 if (c && c->vc_sw == &vga_con) {
1068 /* force hi font mask to 0, so we always clear
1069 the bit on either transition */
1070 c->vc_hi_font_mask = 0x00;
1071 clear_buffer_attributes(c);
1072 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1080 * Adjust the screen to fit a font of a certain height
1082 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
1084 unsigned char ovr, vde, fsr;
1085 int rows, maxscan, i;
1087 rows = vc->vc_scan_lines / fontheight; /* Number of video rows we end up with */
1088 maxscan = rows * fontheight - 1; /* Scan lines to actually display-1 */
1090 /* Reprogram the CRTC for the new font size
1091 Note: the attempt to read the overflow register will fail
1092 on an EGA, but using 0xff for the previous value appears to
1093 be OK for EGA text modes in the range 257-512 scan lines, so I
1094 guess we don't need to worry about it.
1096 The same applies for the spill bits in the font size and cursor
1097 registers; they are write-only on EGA, but it appears that they
1098 are all don't care bits on EGA, so I guess it doesn't matter. */
1100 raw_spin_lock_irq(&vga_lock);
1101 outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
1102 ovr = inb_p(vga_video_port_val);
1103 outb_p(0x09, vga_video_port_reg); /* Font size register */
1104 fsr = inb_p(vga_video_port_val);
1105 raw_spin_unlock_irq(&vga_lock);
1107 vde = maxscan & 0xff; /* Vertical display end reg */
1108 ovr = (ovr & 0xbd) + /* Overflow register */
1109 ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1110 fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */
1112 raw_spin_lock_irq(&vga_lock);
1113 outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
1114 outb_p(ovr, vga_video_port_val);
1115 outb_p(0x09, vga_video_port_reg); /* Font size */
1116 outb_p(fsr, vga_video_port_val);
1117 outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
1118 outb_p(vde, vga_video_port_val);
1119 raw_spin_unlock_irq(&vga_lock);
1120 vga_video_font_height = fontheight;
1122 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1123 struct vc_data *c = vc_cons[i].d;
1125 if (c && c->vc_sw == &vga_con) {
1126 if (CON_IS_VISIBLE(c)) {
1127 /* void size to cause regs to be rewritten */
1128 cursor_size_lastfrom = 0;
1129 cursor_size_lastto = 0;
1130 c->vc_sw->con_cursor(c, CM_DRAW);
1132 c->vc_font.height = c->vc_cell_height = fontheight;
1133 vc_resize(c, 0, rows); /* Adjust console size */
1139 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
1141 unsigned charcount = font->charcount;
1144 if (vga_video_type < VIDEO_TYPE_EGAM)
1147 if (font->width != VGA_FONTWIDTH ||
1148 (charcount != 256 && charcount != 512))
1151 rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1155 if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1156 rc = vgacon_adjust_height(c, font->height);
1160 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1162 if (vga_video_type < VIDEO_TYPE_EGAM)
1165 font->width = VGA_FONTWIDTH;
1166 font->height = c->vc_font.height;
1167 font->charcount = vga_512_chars ? 512 : 256;
1170 return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1175 #define vgacon_font_set NULL
1176 #define vgacon_font_get NULL
1180 static int vgacon_resize(struct vc_data *c, unsigned int width,
1181 unsigned int height, unsigned int user)
1183 if ((width << 1) * height > vga_vram_size)
1188 * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed
1189 * the video mode! Set the new defaults then and go away.
1191 screen_info.orig_video_cols = width;
1192 screen_info.orig_video_lines = height;
1193 vga_default_font_height = c->vc_cell_height;
1196 if (width % 2 || width > screen_info.orig_video_cols ||
1197 height > (screen_info.orig_video_lines * vga_default_font_height)/
1201 if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1202 vgacon_doresize(c, width, height);
1206 static int vgacon_set_origin(struct vc_data *c)
1208 if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
1209 (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
1211 c->vc_origin = c->vc_visible_origin = vga_vram_base;
1213 vga_rolled_over = 0;
1217 static void vgacon_save_screen(struct vc_data *c)
1219 static int vga_bootup_console = 0;
1221 if (!vga_bootup_console) {
1222 /* This is a gross hack, but here is the only place we can
1223 * set bootup console parameters without messing up generic
1224 * console initialization routines.
1226 vga_bootup_console = 1;
1227 c->vc_x = screen_info.orig_x;
1228 c->vc_y = screen_info.orig_y;
1231 /* We can't copy in more than the size of the video buffer,
1232 * or we'll be copying in VGA BIOS */
1235 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1236 c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1239 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1245 if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1248 if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1251 vgacon_restore_screen(c);
1252 oldo = c->vc_origin;
1253 delta = lines * c->vc_size_row;
1255 if (c->vc_scr_end + delta >= vga_vram_end) {
1256 scr_memcpyw((u16 *) vga_vram_base,
1257 (u16 *) (oldo + delta),
1258 c->vc_screenbuf_size - delta);
1259 c->vc_origin = vga_vram_base;
1260 vga_rolled_over = oldo - vga_vram_base;
1262 c->vc_origin += delta;
1263 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1264 delta), c->vc_video_erase_char,
1267 if (oldo - delta < vga_vram_base) {
1268 scr_memmovew((u16 *) (vga_vram_end -
1269 c->vc_screenbuf_size +
1270 delta), (u16 *) oldo,
1271 c->vc_screenbuf_size - delta);
1272 c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1273 vga_rolled_over = 0;
1275 c->vc_origin -= delta;
1276 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1277 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1280 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1281 c->vc_visible_origin = c->vc_origin;
1283 c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1289 * The console `switch' structure for the VGA based console
1292 static int vgacon_dummy(struct vc_data *c)
1297 #define DUMMY (void *) vgacon_dummy
1299 const struct consw vga_con = {
1300 .owner = THIS_MODULE,
1301 .con_startup = vgacon_startup,
1302 .con_init = vgacon_init,
1303 .con_deinit = vgacon_deinit,
1307 .con_cursor = vgacon_cursor,
1308 .con_scroll = vgacon_scroll,
1310 .con_switch = vgacon_switch,
1311 .con_blank = vgacon_blank,
1312 .con_font_set = vgacon_font_set,
1313 .con_font_get = vgacon_font_get,
1314 .con_resize = vgacon_resize,
1315 .con_set_palette = vgacon_set_palette,
1316 .con_scrolldelta = vgacon_scrolldelta,
1317 .con_set_origin = vgacon_set_origin,
1318 .con_save_screen = vgacon_save_screen,
1319 .con_build_attr = vgacon_build_attr,
1320 .con_invert_region = vgacon_invert_region,
1322 EXPORT_SYMBOL(vga_con);
1324 MODULE_LICENSE("GPL");