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 is always 1,
426 * but vgacon_init can be called more than once, and init will
429 c->vc_can_do_color = vga_can_do_color;
431 /* set dimensions manually if init != 0 since vc_resize() will fail */
433 c->vc_cols = vga_video_num_columns;
434 c->vc_rows = vga_video_num_lines;
436 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
438 c->vc_scan_lines = vga_scan_lines;
439 c->vc_font.height = c->vc_cell_height = vga_video_font_height;
440 c->vc_complement_mask = 0x7700;
442 c->vc_hi_font_mask = 0x0800;
443 p = *c->vc_uni_pagedir_loc;
444 if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
446 c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
449 if (!vgacon_uni_pagedir && p)
450 con_set_default_unimap(c);
452 /* Only set the default if the user didn't deliberately override it */
453 if (global_cursor_default == -1)
454 global_cursor_default =
455 !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
458 static void vgacon_deinit(struct vc_data *c)
460 /* When closing the active console, reset video origin */
461 if (CON_IS_VISIBLE(c)) {
462 c->vc_visible_origin = vga_vram_base;
466 if (!--vgacon_refcount)
468 c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
469 con_set_default_unimap(c);
472 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
473 u8 blink, u8 underline, u8 reverse, u8 italic)
477 if (vga_can_do_color) {
479 attr = (attr & 0xF0) | c->vc_itcolor;
481 attr = (attr & 0xf0) | c->vc_ulcolor;
482 else if (intensity == 0)
483 attr = (attr & 0xf0) | c->vc_halfcolor;
487 ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
493 if (!vga_can_do_color) {
495 attr = (attr & 0xF8) | 0x02;
497 attr = (attr & 0xf8) | 0x01;
498 else if (intensity == 0)
499 attr = (attr & 0xf0) | 0x08;
504 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
506 int col = vga_can_do_color;
509 u16 a = scr_readw(p);
511 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
512 (((a) & 0x0700) << 4);
514 a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
519 static void vgacon_set_cursor_size(int xpos, int from, int to)
524 #ifdef TRIDENT_GLITCH
529 if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
531 cursor_size_lastfrom = from;
532 cursor_size_lastto = to;
534 raw_spin_lock_irqsave(&vga_lock, flags);
535 if (vga_video_type >= VIDEO_TYPE_VGAC) {
536 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
537 curs = inb_p(vga_video_port_val);
538 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
539 cure = inb_p(vga_video_port_val);
545 curs = (curs & 0xc0) | from;
546 cure = (cure & 0xe0) | to;
548 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
549 outb_p(curs, vga_video_port_val);
550 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
551 outb_p(cure, vga_video_port_val);
552 raw_spin_unlock_irqrestore(&vga_lock, flags);
555 static void vgacon_cursor(struct vc_data *c, int mode)
557 if (c->vc_mode != KD_TEXT)
560 vgacon_restore_screen(c);
564 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
565 if (vga_video_type >= VIDEO_TYPE_VGAC)
566 vgacon_set_cursor_size(c->vc_x, 31, 30);
568 vgacon_set_cursor_size(c->vc_x, 31, 31);
573 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
574 switch (c->vc_cursor_type & 0x0f) {
576 vgacon_set_cursor_size(c->vc_x,
585 vgacon_set_cursor_size(c->vc_x,
586 c->vc_cell_height / 3,
591 case CUR_LOWER_THIRD:
592 vgacon_set_cursor_size(c->vc_x,
593 (c->vc_cell_height * 2) / 3,
599 vgacon_set_cursor_size(c->vc_x,
600 c->vc_cell_height / 2,
606 if (vga_video_type >= VIDEO_TYPE_VGAC)
607 vgacon_set_cursor_size(c->vc_x, 31, 30);
609 vgacon_set_cursor_size(c->vc_x, 31, 31);
612 vgacon_set_cursor_size(c->vc_x, 1,
620 static int vgacon_doresize(struct vc_data *c,
621 unsigned int width, unsigned int height)
624 unsigned int scanlines = height * c->vc_cell_height;
625 u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
627 raw_spin_lock_irqsave(&vga_lock, flags);
629 vgacon_xres = width * VGA_FONTWIDTH;
630 vgacon_yres = height * c->vc_cell_height;
631 if (vga_video_type >= VIDEO_TYPE_VGAC) {
632 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
633 max_scan = inb_p(vga_video_port_val);
638 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
639 mode = inb_p(vga_video_port_val);
645 scanlines_lo = scanlines & 0xff;
647 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
648 r7 = inb_p(vga_video_port_val) & ~0x42;
650 if (scanlines & 0x100)
652 if (scanlines & 0x200)
655 /* deprotect registers */
656 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
657 vsync_end = inb_p(vga_video_port_val);
658 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
659 outb_p(vsync_end & ~0x80, vga_video_port_val);
662 outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
663 outb_p(width - 1, vga_video_port_val);
664 outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
665 outb_p(width >> 1, vga_video_port_val);
667 if (vga_video_type >= VIDEO_TYPE_VGAC) {
668 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
669 outb_p(scanlines_lo, vga_video_port_val);
670 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
671 outb_p(r7,vga_video_port_val);
673 /* reprotect registers */
674 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
675 outb_p(vsync_end, vga_video_port_val);
678 raw_spin_unlock_irqrestore(&vga_lock, flags);
682 static int vgacon_switch(struct vc_data *c)
684 int x = c->vc_cols * VGA_FONTWIDTH;
685 int y = c->vc_rows * c->vc_cell_height;
686 int rows = screen_info.orig_video_lines * vga_default_font_height/
689 * We need to save screen size here as it's the only way
690 * we can spot the screen has been resized and we need to
691 * set size of freshly allocated screens ourselves.
693 vga_video_num_columns = c->vc_cols;
694 vga_video_num_lines = c->vc_rows;
696 /* We can only copy out the size of the video buffer here,
697 * otherwise we get into VGA BIOS */
700 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
701 c->vc_screenbuf_size > vga_vram_size ?
702 vga_vram_size : c->vc_screenbuf_size);
704 if ((vgacon_xres != x || vgacon_yres != y) &&
705 (!(vga_video_num_columns % 2) &&
706 vga_video_num_columns <= screen_info.orig_video_cols &&
707 vga_video_num_lines <= rows))
708 vgacon_doresize(c, c->vc_cols, c->vc_rows);
711 return 0; /* Redrawing not needed */
714 static void vga_set_palette(struct vc_data *vc, unsigned char *table)
718 vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
719 for (i = j = 0; i < 16; i++) {
720 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
721 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
722 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
723 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
727 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
729 #ifdef CAN_LOAD_PALETTE
730 if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
731 || !CON_IS_VISIBLE(vc))
733 vga_set_palette(vc, table);
740 /* structure holding original VGA register settings */
742 unsigned char SeqCtrlIndex; /* Sequencer Index reg. */
743 unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */
744 unsigned char CrtMiscIO; /* Miscellaneous register */
745 unsigned char HorizontalTotal; /* CRT-Controller:00h */
746 unsigned char HorizDisplayEnd; /* CRT-Controller:01h */
747 unsigned char StartHorizRetrace; /* CRT-Controller:04h */
748 unsigned char EndHorizRetrace; /* CRT-Controller:05h */
749 unsigned char Overflow; /* CRT-Controller:07h */
750 unsigned char StartVertRetrace; /* CRT-Controller:10h */
751 unsigned char EndVertRetrace; /* CRT-Controller:11h */
752 unsigned char ModeControl; /* CRT-Controller:17h */
753 unsigned char ClockingMode; /* Seq-Controller:01h */
756 static void vga_vesa_blank(struct vgastate *state, int mode)
758 /* save original values of VGA controller registers */
759 if (!vga_vesa_blanked) {
760 raw_spin_lock_irq(&vga_lock);
761 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
762 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
763 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
764 raw_spin_unlock_irq(&vga_lock);
766 outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
767 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
768 outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
769 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
770 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
771 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
772 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
773 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
774 outb_p(0x07, vga_video_port_reg); /* Overflow */
775 vga_state.Overflow = inb_p(vga_video_port_val);
776 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
777 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
778 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
779 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
780 outb_p(0x17, vga_video_port_reg); /* ModeControl */
781 vga_state.ModeControl = inb_p(vga_video_port_val);
782 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
785 /* assure that video is enabled */
786 /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
787 raw_spin_lock_irq(&vga_lock);
788 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
790 /* test for vertical retrace in process.... */
791 if ((vga_state.CrtMiscIO & 0x80) == 0x80)
792 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
795 * Set <End of vertical retrace> to minimum (0) and
796 * <Start of vertical Retrace> to maximum (incl. overflow)
797 * Result: turn off vertical sync (VSync) pulse.
799 if (mode & VESA_VSYNC_SUSPEND) {
800 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
801 outb_p(0xff, vga_video_port_val); /* maximum value */
802 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
803 outb_p(0x40, vga_video_port_val); /* minimum (bits 0..3) */
804 outb_p(0x07, vga_video_port_reg); /* Overflow */
805 outb_p(vga_state.Overflow | 0x84, vga_video_port_val); /* bits 9,10 of vert. retrace */
808 if (mode & VESA_HSYNC_SUSPEND) {
810 * Set <End of horizontal retrace> to minimum (0) and
811 * <Start of horizontal Retrace> to maximum
812 * Result: turn off horizontal sync (HSync) pulse.
814 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
815 outb_p(0xff, vga_video_port_val); /* maximum */
816 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
817 outb_p(0x00, vga_video_port_val); /* minimum (0) */
820 /* restore both index registers */
821 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
822 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
823 raw_spin_unlock_irq(&vga_lock);
826 static void vga_vesa_unblank(struct vgastate *state)
828 /* restore original values of VGA controller registers */
829 raw_spin_lock_irq(&vga_lock);
830 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
832 outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
833 outb_p(vga_state.HorizontalTotal, vga_video_port_val);
834 outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */
835 outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
836 outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */
837 outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
838 outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */
839 outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
840 outb_p(0x07, vga_video_port_reg); /* Overflow */
841 outb_p(vga_state.Overflow, vga_video_port_val);
842 outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */
843 outb_p(vga_state.StartVertRetrace, vga_video_port_val);
844 outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */
845 outb_p(vga_state.EndVertRetrace, vga_video_port_val);
846 outb_p(0x17, vga_video_port_reg); /* ModeControl */
847 outb_p(vga_state.ModeControl, vga_video_port_val);
849 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
851 /* restore index/control registers */
852 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
853 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
854 raw_spin_unlock_irq(&vga_lock);
857 static void vga_pal_blank(struct vgastate *state)
861 vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
862 for (i = 0; i < 16; i++) {
863 vga_w(state->vgabase, VGA_PEL_IW, i);
864 vga_w(state->vgabase, VGA_PEL_D, 0);
865 vga_w(state->vgabase, VGA_PEL_D, 0);
866 vga_w(state->vgabase, VGA_PEL_D, 0);
870 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
873 case 0: /* Unblank */
874 if (vga_vesa_blanked) {
875 vga_vesa_unblank(&vgastate);
876 vga_vesa_blanked = 0;
878 if (vga_palette_blanked) {
879 vga_set_palette(c, color_table);
880 vga_palette_blanked = 0;
884 /* Tell console.c that it has to restore the screen itself */
886 case 1: /* Normal blanking */
887 case -1: /* Obsolete */
888 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
889 vga_pal_blank(&vgastate);
890 vga_palette_blanked = 1;
893 vgacon_set_origin(c);
894 scr_memsetw((void *) vga_vram_base, BLANK,
895 c->vc_screenbuf_size);
899 default: /* VESA blanking */
900 if (vga_video_type == VIDEO_TYPE_VGAC) {
901 vga_vesa_blank(&vgastate, blank - 1);
902 vga_vesa_blanked = blank;
911 * The font loading code goes back to the codepage package by
912 * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
913 * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
914 * Video Systems_ by Richard Wilton. 1987. Microsoft Press".)
916 * Change for certain monochrome monitors by Yury Shevchuck
917 * (sizif@botik.yaroslavl.su).
920 #ifdef CAN_LOAD_EGA_FONTS
922 #define colourmap 0xa0000
923 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
924 should use 0xA0000 for the bwmap as well.. */
925 #define blackwmap 0xa0000
928 static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
930 unsigned short video_port_status = vga_video_port_reg + 6;
931 int font_select = 0x00, beg, i;
933 bool clear_attribs = false;
934 if (vga_video_type != VIDEO_TYPE_EGAM) {
935 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
937 #ifdef VGA_CAN_DO_64KB
938 if (vga_video_type == VIDEO_TYPE_VGAC)
942 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
946 #ifdef BROKEN_GRAPHICS_PROGRAMS
948 * All fonts are loaded in slot 0 (0:1 for 512 ch)
952 return -EINVAL; /* Return to default font not supported */
954 vga_font_is_default = 0;
955 font_select = ch512 ? 0x04 : 0x00;
958 * The default font is kept in slot 0 and is never touched.
959 * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
963 vga_font_is_default = !arg;
965 ch512 = 0; /* Default font is always 256 */
966 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
969 if (!vga_font_is_default)
970 charmap += 4 * cmapsz;
973 raw_spin_lock_irq(&vga_lock);
974 /* First, the Sequencer */
975 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
976 /* CPU writes only to map 2 */
977 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
978 /* Sequential addressing */
979 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
980 /* Clear synchronous reset */
981 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
983 /* Now, the graphics controller, select map 2 */
984 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
985 /* disable odd-even addressing */
986 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
987 /* map start at A000:0000 */
988 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
989 raw_spin_unlock_irq(&vga_lock);
993 for (i = 0; i < cmapsz; i++) {
994 vga_writeb(arg[i], charmap + i);
998 for (i = 0; i < cmapsz; i++) {
999 arg[i] = vga_readb(charmap + i);
1004 * In 512-character mode, the character map is not contiguous if
1005 * we want to remain EGA compatible -- which we do
1009 charmap += 2 * cmapsz;
1012 for (i = 0; i < cmapsz; i++) {
1013 vga_writeb(arg[i], charmap + i);
1017 for (i = 0; i < cmapsz; i++) {
1018 arg[i] = vga_readb(charmap + i);
1024 raw_spin_lock_irq(&vga_lock);
1025 /* First, the sequencer, Synchronous reset */
1026 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
1027 /* CPU writes to maps 0 and 1 */
1028 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
1029 /* odd-even addressing */
1030 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
1031 /* Character Map Select */
1033 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
1034 /* clear synchronous reset */
1035 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1037 /* Now, the graphics controller, select map 0 for CPU */
1038 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
1039 /* enable even-odd addressing */
1040 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
1041 /* map starts at b800:0 or b000:0 */
1042 vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
1044 /* if 512 char mode is already enabled don't re-enable it. */
1045 if ((set) && (ch512 != vga_512_chars)) {
1046 vga_512_chars = ch512;
1047 /* 256-char: enable intensity bit
1048 512-char: disable intensity bit */
1049 inb_p(video_port_status); /* clear address flip-flop */
1050 /* color plane enable register */
1051 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
1052 /* Wilton (1987) mentions the following; I don't know what
1053 it means, but it works, and it appears necessary */
1054 inb_p(video_port_status);
1055 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1056 clear_attribs = true;
1058 raw_spin_unlock_irq(&vga_lock);
1060 if (clear_attribs) {
1061 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1062 struct vc_data *c = vc_cons[i].d;
1063 if (c && c->vc_sw == &vga_con) {
1064 /* force hi font mask to 0, so we always clear
1065 the bit on either transition */
1066 c->vc_hi_font_mask = 0x00;
1067 clear_buffer_attributes(c);
1068 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1076 * Adjust the screen to fit a font of a certain height
1078 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
1080 unsigned char ovr, vde, fsr;
1081 int rows, maxscan, i;
1083 rows = vc->vc_scan_lines / fontheight; /* Number of video rows we end up with */
1084 maxscan = rows * fontheight - 1; /* Scan lines to actually display-1 */
1086 /* Reprogram the CRTC for the new font size
1087 Note: the attempt to read the overflow register will fail
1088 on an EGA, but using 0xff for the previous value appears to
1089 be OK for EGA text modes in the range 257-512 scan lines, so I
1090 guess we don't need to worry about it.
1092 The same applies for the spill bits in the font size and cursor
1093 registers; they are write-only on EGA, but it appears that they
1094 are all don't care bits on EGA, so I guess it doesn't matter. */
1096 raw_spin_lock_irq(&vga_lock);
1097 outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
1098 ovr = inb_p(vga_video_port_val);
1099 outb_p(0x09, vga_video_port_reg); /* Font size register */
1100 fsr = inb_p(vga_video_port_val);
1101 raw_spin_unlock_irq(&vga_lock);
1103 vde = maxscan & 0xff; /* Vertical display end reg */
1104 ovr = (ovr & 0xbd) + /* Overflow register */
1105 ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1106 fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */
1108 raw_spin_lock_irq(&vga_lock);
1109 outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
1110 outb_p(ovr, vga_video_port_val);
1111 outb_p(0x09, vga_video_port_reg); /* Font size */
1112 outb_p(fsr, vga_video_port_val);
1113 outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
1114 outb_p(vde, vga_video_port_val);
1115 raw_spin_unlock_irq(&vga_lock);
1116 vga_video_font_height = fontheight;
1118 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1119 struct vc_data *c = vc_cons[i].d;
1121 if (c && c->vc_sw == &vga_con) {
1122 if (CON_IS_VISIBLE(c)) {
1123 /* void size to cause regs to be rewritten */
1124 cursor_size_lastfrom = 0;
1125 cursor_size_lastto = 0;
1126 c->vc_sw->con_cursor(c, CM_DRAW);
1128 c->vc_font.height = c->vc_cell_height = fontheight;
1129 vc_resize(c, 0, rows); /* Adjust console size */
1135 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
1137 unsigned charcount = font->charcount;
1140 if (vga_video_type < VIDEO_TYPE_EGAM)
1143 if (font->width != VGA_FONTWIDTH ||
1144 (charcount != 256 && charcount != 512))
1147 rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1151 if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1152 rc = vgacon_adjust_height(c, font->height);
1156 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1158 if (vga_video_type < VIDEO_TYPE_EGAM)
1161 font->width = VGA_FONTWIDTH;
1162 font->height = c->vc_font.height;
1163 font->charcount = vga_512_chars ? 512 : 256;
1166 return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1171 #define vgacon_font_set NULL
1172 #define vgacon_font_get NULL
1176 static int vgacon_resize(struct vc_data *c, unsigned int width,
1177 unsigned int height, unsigned int user)
1179 if ((width << 1) * height > vga_vram_size)
1184 * Ho ho! Someone (svgatextmode, eh?) may have reprogrammed
1185 * the video mode! Set the new defaults then and go away.
1187 screen_info.orig_video_cols = width;
1188 screen_info.orig_video_lines = height;
1189 vga_default_font_height = c->vc_cell_height;
1192 if (width % 2 || width > screen_info.orig_video_cols ||
1193 height > (screen_info.orig_video_lines * vga_default_font_height)/
1197 if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1198 vgacon_doresize(c, width, height);
1202 static int vgacon_set_origin(struct vc_data *c)
1204 if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
1205 (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */
1207 c->vc_origin = c->vc_visible_origin = vga_vram_base;
1209 vga_rolled_over = 0;
1213 static void vgacon_save_screen(struct vc_data *c)
1215 static int vga_bootup_console = 0;
1217 if (!vga_bootup_console) {
1218 /* This is a gross hack, but here is the only place we can
1219 * set bootup console parameters without messing up generic
1220 * console initialization routines.
1222 vga_bootup_console = 1;
1223 c->vc_x = screen_info.orig_x;
1224 c->vc_y = screen_info.orig_y;
1227 /* We can't copy in more than the size of the video buffer,
1228 * or we'll be copying in VGA BIOS */
1231 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1232 c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1235 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1241 if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1244 if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1247 vgacon_restore_screen(c);
1248 oldo = c->vc_origin;
1249 delta = lines * c->vc_size_row;
1251 if (c->vc_scr_end + delta >= vga_vram_end) {
1252 scr_memcpyw((u16 *) vga_vram_base,
1253 (u16 *) (oldo + delta),
1254 c->vc_screenbuf_size - delta);
1255 c->vc_origin = vga_vram_base;
1256 vga_rolled_over = oldo - vga_vram_base;
1258 c->vc_origin += delta;
1259 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1260 delta), c->vc_video_erase_char,
1263 if (oldo - delta < vga_vram_base) {
1264 scr_memmovew((u16 *) (vga_vram_end -
1265 c->vc_screenbuf_size +
1266 delta), (u16 *) oldo,
1267 c->vc_screenbuf_size - delta);
1268 c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1269 vga_rolled_over = 0;
1271 c->vc_origin -= delta;
1272 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1273 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1276 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1277 c->vc_visible_origin = c->vc_origin;
1279 c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1285 * The console `switch' structure for the VGA based console
1288 static int vgacon_dummy(struct vc_data *c)
1293 #define DUMMY (void *) vgacon_dummy
1295 const struct consw vga_con = {
1296 .owner = THIS_MODULE,
1297 .con_startup = vgacon_startup,
1298 .con_init = vgacon_init,
1299 .con_deinit = vgacon_deinit,
1303 .con_cursor = vgacon_cursor,
1304 .con_scroll = vgacon_scroll,
1306 .con_switch = vgacon_switch,
1307 .con_blank = vgacon_blank,
1308 .con_font_set = vgacon_font_set,
1309 .con_font_get = vgacon_font_get,
1310 .con_resize = vgacon_resize,
1311 .con_set_palette = vgacon_set_palette,
1312 .con_scrolldelta = vgacon_scrolldelta,
1313 .con_set_origin = vgacon_set_origin,
1314 .con_save_screen = vgacon_save_screen,
1315 .con_build_attr = vgacon_build_attr,
1316 .con_invert_region = vgacon_invert_region,
1318 EXPORT_SYMBOL(vga_con);
1320 MODULE_LICENSE("GPL");