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