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