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