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