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