xref: /linux/drivers/video/console/vgacon.c (revision 858259cf7d1c443c836a2022b78cb281f0a9b95e)
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, (c->vc_pos - vga_vram_base) / 2);
452 		vgacon_set_cursor_size(c->vc_x, 31, 30);
453 		break;
454 
455 	case CM_MOVE:
456 	case CM_DRAW:
457 		write_vga(14, (c->vc_pos - vga_vram_base) / 2);
458 		switch (c->vc_cursor_type & 0x0f) {
459 		case CUR_UNDERLINE:
460 			vgacon_set_cursor_size(c->vc_x,
461 					       c->vc_font.height -
462 					       (c->vc_font.height <
463 						10 ? 2 : 3),
464 					       c->vc_font.height -
465 					       (c->vc_font.height <
466 						10 ? 1 : 2));
467 			break;
468 		case CUR_TWO_THIRDS:
469 			vgacon_set_cursor_size(c->vc_x,
470 					       c->vc_font.height / 3,
471 					       c->vc_font.height -
472 					       (c->vc_font.height <
473 						10 ? 1 : 2));
474 			break;
475 		case CUR_LOWER_THIRD:
476 			vgacon_set_cursor_size(c->vc_x,
477 					       (c->vc_font.height * 2) / 3,
478 					       c->vc_font.height -
479 					       (c->vc_font.height <
480 						10 ? 1 : 2));
481 			break;
482 		case CUR_LOWER_HALF:
483 			vgacon_set_cursor_size(c->vc_x,
484 					       c->vc_font.height / 2,
485 					       c->vc_font.height -
486 					       (c->vc_font.height <
487 						10 ? 1 : 2));
488 			break;
489 		case CUR_NONE:
490 			vgacon_set_cursor_size(c->vc_x, 31, 30);
491 			break;
492 		default:
493 			vgacon_set_cursor_size(c->vc_x, 1,
494 					       c->vc_font.height);
495 			break;
496 		}
497 		break;
498 	}
499 }
500 
501 static int vgacon_doresize(struct vc_data *c,
502 		unsigned int width, unsigned int height)
503 {
504 	unsigned long flags;
505 	unsigned int scanlines = height * c->vc_font.height;
506 	u8 scanlines_lo, r7, vsync_end, mode;
507 
508 	spin_lock_irqsave(&vga_lock, flags);
509 
510 	outb_p(VGA_CRTC_MODE, vga_video_port_reg);
511 	mode = inb_p(vga_video_port_val);
512 
513 	if (mode & 0x04)
514 		scanlines >>= 1;
515 
516 	scanlines -= 1;
517 	scanlines_lo = scanlines & 0xff;
518 
519 	outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
520 	r7 = inb_p(vga_video_port_val) & ~0x42;
521 
522 	if (scanlines & 0x100)
523 		r7 |= 0x02;
524 	if (scanlines & 0x200)
525 		r7 |= 0x40;
526 
527 	/* deprotect registers */
528 	outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
529 	vsync_end = inb_p(vga_video_port_val);
530 	outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
531 	outb_p(vsync_end & ~0x80, vga_video_port_val);
532 
533 	outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
534 	outb_p(width - 1, vga_video_port_val);
535 	outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
536 	outb_p(width >> 1, vga_video_port_val);
537 
538 	outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
539 	outb_p(scanlines_lo, vga_video_port_val);
540 	outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
541 	outb_p(r7,vga_video_port_val);
542 
543 	/* reprotect registers */
544 	outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
545 	outb_p(vsync_end, vga_video_port_val);
546 
547 	spin_unlock_irqrestore(&vga_lock, flags);
548 
549 	return 0;
550 }
551 
552 static int vgacon_switch(struct vc_data *c)
553 {
554 	/*
555 	 * We need to save screen size here as it's the only way
556 	 * we can spot the screen has been resized and we need to
557 	 * set size of freshly allocated screens ourselves.
558 	 */
559 	vga_video_num_columns = c->vc_cols;
560 	vga_video_num_lines = c->vc_rows;
561 
562 	/* We can only copy out the size of the video buffer here,
563 	 * otherwise we get into VGA BIOS */
564 
565 	if (!vga_is_gfx) {
566 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
567 			    c->vc_screenbuf_size > vga_vram_size ?
568 				vga_vram_size : c->vc_screenbuf_size);
569 		if (!(vga_video_num_columns % 2) &&
570 		    vga_video_num_columns <= ORIG_VIDEO_COLS &&
571 		    vga_video_num_lines <= (ORIG_VIDEO_LINES *
572 			vga_default_font_height) / c->vc_font.height)
573 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
574 	}
575 
576 	return 0;		/* Redrawing not needed */
577 }
578 
579 static void vga_set_palette(struct vc_data *vc, unsigned char *table)
580 {
581 	int i, j;
582 
583 	vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
584 	for (i = j = 0; i < 16; i++) {
585 		vga_w(state.vgabase, VGA_PEL_IW, table[i]);
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 		vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
589 	}
590 }
591 
592 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
593 {
594 #ifdef CAN_LOAD_PALETTE
595 	if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
596 	    || !CON_IS_VISIBLE(vc))
597 		return -EINVAL;
598 	vga_set_palette(vc, table);
599 	return 0;
600 #else
601 	return -EINVAL;
602 #endif
603 }
604 
605 /* structure holding original VGA register settings */
606 static struct {
607 	unsigned char SeqCtrlIndex;	/* Sequencer Index reg.   */
608 	unsigned char CrtCtrlIndex;	/* CRT-Contr. Index reg.  */
609 	unsigned char CrtMiscIO;	/* Miscellaneous register */
610 	unsigned char HorizontalTotal;	/* CRT-Controller:00h */
611 	unsigned char HorizDisplayEnd;	/* CRT-Controller:01h */
612 	unsigned char StartHorizRetrace;	/* CRT-Controller:04h */
613 	unsigned char EndHorizRetrace;	/* CRT-Controller:05h */
614 	unsigned char Overflow;	/* CRT-Controller:07h */
615 	unsigned char StartVertRetrace;	/* CRT-Controller:10h */
616 	unsigned char EndVertRetrace;	/* CRT-Controller:11h */
617 	unsigned char ModeControl;	/* CRT-Controller:17h */
618 	unsigned char ClockingMode;	/* Seq-Controller:01h */
619 } vga_state;
620 
621 static void vga_vesa_blank(struct vgastate *state, int mode)
622 {
623 	/* save original values of VGA controller registers */
624 	if (!vga_vesa_blanked) {
625 		spin_lock_irq(&vga_lock);
626 		vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
627 		vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
628 		vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
629 		spin_unlock_irq(&vga_lock);
630 
631 		outb_p(0x00, vga_video_port_reg);	/* HorizontalTotal */
632 		vga_state.HorizontalTotal = inb_p(vga_video_port_val);
633 		outb_p(0x01, vga_video_port_reg);	/* HorizDisplayEnd */
634 		vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
635 		outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
636 		vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
637 		outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
638 		vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
639 		outb_p(0x07, vga_video_port_reg);	/* Overflow */
640 		vga_state.Overflow = inb_p(vga_video_port_val);
641 		outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
642 		vga_state.StartVertRetrace = inb_p(vga_video_port_val);
643 		outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
644 		vga_state.EndVertRetrace = inb_p(vga_video_port_val);
645 		outb_p(0x17, vga_video_port_reg);	/* ModeControl */
646 		vga_state.ModeControl = inb_p(vga_video_port_val);
647 		vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
648 	}
649 
650 	/* assure that video is enabled */
651 	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
652 	spin_lock_irq(&vga_lock);
653 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
654 
655 	/* test for vertical retrace in process.... */
656 	if ((vga_state.CrtMiscIO & 0x80) == 0x80)
657 		vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
658 
659 	/*
660 	 * Set <End of vertical retrace> to minimum (0) and
661 	 * <Start of vertical Retrace> to maximum (incl. overflow)
662 	 * Result: turn off vertical sync (VSync) pulse.
663 	 */
664 	if (mode & VESA_VSYNC_SUSPEND) {
665 		outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
666 		outb_p(0xff, vga_video_port_val);	/* maximum value */
667 		outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
668 		outb_p(0x40, vga_video_port_val);	/* minimum (bits 0..3)  */
669 		outb_p(0x07, vga_video_port_reg);	/* Overflow */
670 		outb_p(vga_state.Overflow | 0x84, vga_video_port_val);	/* bits 9,10 of vert. retrace */
671 	}
672 
673 	if (mode & VESA_HSYNC_SUSPEND) {
674 		/*
675 		 * Set <End of horizontal retrace> to minimum (0) and
676 		 *  <Start of horizontal Retrace> to maximum
677 		 * Result: turn off horizontal sync (HSync) pulse.
678 		 */
679 		outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
680 		outb_p(0xff, vga_video_port_val);	/* maximum */
681 		outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
682 		outb_p(0x00, vga_video_port_val);	/* minimum (0) */
683 	}
684 
685 	/* restore both index registers */
686 	vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
687 	outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
688 	spin_unlock_irq(&vga_lock);
689 }
690 
691 static void vga_vesa_unblank(struct vgastate *state)
692 {
693 	/* restore original values of VGA controller registers */
694 	spin_lock_irq(&vga_lock);
695 	vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
696 
697 	outb_p(0x00, vga_video_port_reg);	/* HorizontalTotal */
698 	outb_p(vga_state.HorizontalTotal, vga_video_port_val);
699 	outb_p(0x01, vga_video_port_reg);	/* HorizDisplayEnd */
700 	outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
701 	outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
702 	outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
703 	outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
704 	outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
705 	outb_p(0x07, vga_video_port_reg);	/* Overflow */
706 	outb_p(vga_state.Overflow, vga_video_port_val);
707 	outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
708 	outb_p(vga_state.StartVertRetrace, vga_video_port_val);
709 	outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
710 	outb_p(vga_state.EndVertRetrace, vga_video_port_val);
711 	outb_p(0x17, vga_video_port_reg);	/* ModeControl */
712 	outb_p(vga_state.ModeControl, vga_video_port_val);
713 	/* ClockingMode */
714 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
715 
716 	/* restore index/control registers */
717 	vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
718 	outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
719 	spin_unlock_irq(&vga_lock);
720 }
721 
722 static void vga_pal_blank(struct vgastate *state)
723 {
724 	int i;
725 
726 	vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
727 	for (i = 0; i < 16; i++) {
728 		vga_w(state->vgabase, VGA_PEL_IW, i);
729 		vga_w(state->vgabase, VGA_PEL_D, 0);
730 		vga_w(state->vgabase, VGA_PEL_D, 0);
731 		vga_w(state->vgabase, VGA_PEL_D, 0);
732 	}
733 }
734 
735 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
736 {
737 	switch (blank) {
738 	case 0:		/* Unblank */
739 		if (vga_vesa_blanked) {
740 			vga_vesa_unblank(&state);
741 			vga_vesa_blanked = 0;
742 		}
743 		if (vga_palette_blanked) {
744 			vga_set_palette(c, color_table);
745 			vga_palette_blanked = 0;
746 			return 0;
747 		}
748 		vga_is_gfx = 0;
749 		/* Tell console.c that it has to restore the screen itself */
750 		return 1;
751 	case 1:		/* Normal blanking */
752 	case -1:	/* Obsolete */
753 		if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
754 			vga_pal_blank(&state);
755 			vga_palette_blanked = 1;
756 			return 0;
757 		}
758 		vgacon_set_origin(c);
759 		scr_memsetw((void *) vga_vram_base, BLANK,
760 			    c->vc_screenbuf_size);
761 		if (mode_switch)
762 			vga_is_gfx = 1;
763 		return 1;
764 	default:		/* VESA blanking */
765 		if (vga_video_type == VIDEO_TYPE_VGAC) {
766 			vga_vesa_blank(&state, blank - 1);
767 			vga_vesa_blanked = blank;
768 		}
769 		return 0;
770 	}
771 }
772 
773 /*
774  * PIO_FONT support.
775  *
776  * The font loading code goes back to the codepage package by
777  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
778  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
779  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
780  *
781  * Change for certain monochrome monitors by Yury Shevchuck
782  * (sizif@botik.yaroslavl.su).
783  */
784 
785 #ifdef CAN_LOAD_EGA_FONTS
786 
787 #define colourmap 0xa0000
788 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
789    should use 0xA0000 for the bwmap as well.. */
790 #define blackwmap 0xa0000
791 #define cmapsz 8192
792 
793 static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
794 {
795 	unsigned short video_port_status = vga_video_port_reg + 6;
796 	int font_select = 0x00, beg, i;
797 	char *charmap;
798 
799 	if (vga_video_type != VIDEO_TYPE_EGAM) {
800 		charmap = (char *) VGA_MAP_MEM(colourmap);
801 		beg = 0x0e;
802 #ifdef VGA_CAN_DO_64KB
803 		if (vga_video_type == VIDEO_TYPE_VGAC)
804 			beg = 0x06;
805 #endif
806 	} else {
807 		charmap = (char *) VGA_MAP_MEM(blackwmap);
808 		beg = 0x0a;
809 	}
810 
811 #ifdef BROKEN_GRAPHICS_PROGRAMS
812 	/*
813 	 * All fonts are loaded in slot 0 (0:1 for 512 ch)
814 	 */
815 
816 	if (!arg)
817 		return -EINVAL;	/* Return to default font not supported */
818 
819 	vga_font_is_default = 0;
820 	font_select = ch512 ? 0x04 : 0x00;
821 #else
822 	/*
823 	 * The default font is kept in slot 0 and is never touched.
824 	 * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
825 	 */
826 
827 	if (set) {
828 		vga_font_is_default = !arg;
829 		if (!arg)
830 			ch512 = 0;	/* Default font is always 256 */
831 		font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
832 	}
833 
834 	if (!vga_font_is_default)
835 		charmap += 4 * cmapsz;
836 #endif
837 
838 	unlock_kernel();
839 	spin_lock_irq(&vga_lock);
840 	/* First, the Sequencer */
841 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
842 	/* CPU writes only to map 2 */
843 	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
844 	/* Sequential addressing */
845 	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
846 	/* Clear synchronous reset */
847 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
848 
849 	/* Now, the graphics controller, select map 2 */
850 	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
851 	/* disable odd-even addressing */
852 	vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
853 	/* map start at A000:0000 */
854 	vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
855 	spin_unlock_irq(&vga_lock);
856 
857 	if (arg) {
858 		if (set)
859 			for (i = 0; i < cmapsz; i++)
860 				vga_writeb(arg[i], charmap + i);
861 		else
862 			for (i = 0; i < cmapsz; i++)
863 				arg[i] = vga_readb(charmap + i);
864 
865 		/*
866 		 * In 512-character mode, the character map is not contiguous if
867 		 * we want to remain EGA compatible -- which we do
868 		 */
869 
870 		if (ch512) {
871 			charmap += 2 * cmapsz;
872 			arg += cmapsz;
873 			if (set)
874 				for (i = 0; i < cmapsz; i++)
875 					vga_writeb(arg[i], charmap + i);
876 			else
877 				for (i = 0; i < cmapsz; i++)
878 					arg[i] = vga_readb(charmap + i);
879 		}
880 	}
881 
882 	spin_lock_irq(&vga_lock);
883 	/* First, the sequencer, Synchronous reset */
884 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
885 	/* CPU writes to maps 0 and 1 */
886 	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
887 	/* odd-even addressing */
888 	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
889 	/* Character Map Select */
890 	if (set)
891 		vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
892 	/* clear synchronous reset */
893 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
894 
895 	/* Now, the graphics controller, select map 0 for CPU */
896 	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
897 	/* enable even-odd addressing */
898 	vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
899 	/* map starts at b800:0 or b000:0 */
900 	vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
901 
902 	/* if 512 char mode is already enabled don't re-enable it. */
903 	if ((set) && (ch512 != vga_512_chars)) {
904 		int i;
905 
906 		/* attribute controller */
907 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
908 			struct vc_data *c = vc_cons[i].d;
909 			if (c && c->vc_sw == &vga_con)
910 				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
911 		}
912 		vga_512_chars = ch512;
913 		/* 256-char: enable intensity bit
914 		   512-char: disable intensity bit */
915 		inb_p(video_port_status);	/* clear address flip-flop */
916 		/* color plane enable register */
917 		vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
918 		/* Wilton (1987) mentions the following; I don't know what
919 		   it means, but it works, and it appears necessary */
920 		inb_p(video_port_status);
921 		vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
922 	}
923 	spin_unlock_irq(&vga_lock);
924 	lock_kernel();
925 	return 0;
926 }
927 
928 /*
929  * Adjust the screen to fit a font of a certain height
930  */
931 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
932 {
933 	unsigned char ovr, vde, fsr;
934 	int rows, maxscan, i;
935 
936 	rows = vc->vc_scan_lines / fontheight;	/* Number of video rows we end up with */
937 	maxscan = rows * fontheight - 1;	/* Scan lines to actually display-1 */
938 
939 	/* Reprogram the CRTC for the new font size
940 	   Note: the attempt to read the overflow register will fail
941 	   on an EGA, but using 0xff for the previous value appears to
942 	   be OK for EGA text modes in the range 257-512 scan lines, so I
943 	   guess we don't need to worry about it.
944 
945 	   The same applies for the spill bits in the font size and cursor
946 	   registers; they are write-only on EGA, but it appears that they
947 	   are all don't care bits on EGA, so I guess it doesn't matter. */
948 
949 	spin_lock_irq(&vga_lock);
950 	outb_p(0x07, vga_video_port_reg);	/* CRTC overflow register */
951 	ovr = inb_p(vga_video_port_val);
952 	outb_p(0x09, vga_video_port_reg);	/* Font size register */
953 	fsr = inb_p(vga_video_port_val);
954 	spin_unlock_irq(&vga_lock);
955 
956 	vde = maxscan & 0xff;	/* Vertical display end reg */
957 	ovr = (ovr & 0xbd) +	/* Overflow register */
958 	    ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
959 	fsr = (fsr & 0xe0) + (fontheight - 1);	/*  Font size register */
960 
961 	spin_lock_irq(&vga_lock);
962 	outb_p(0x07, vga_video_port_reg);	/* CRTC overflow register */
963 	outb_p(ovr, vga_video_port_val);
964 	outb_p(0x09, vga_video_port_reg);	/* Font size */
965 	outb_p(fsr, vga_video_port_val);
966 	outb_p(0x12, vga_video_port_reg);	/* Vertical display limit */
967 	outb_p(vde, vga_video_port_val);
968 	spin_unlock_irq(&vga_lock);
969 
970 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
971 		struct vc_data *c = vc_cons[i].d;
972 
973 		if (c && c->vc_sw == &vga_con) {
974 			if (CON_IS_VISIBLE(c)) {
975 			        /* void size to cause regs to be rewritten */
976 				cursor_size_lastfrom = 0;
977 				cursor_size_lastto = 0;
978 				c->vc_sw->con_cursor(c, CM_DRAW);
979 			}
980 			c->vc_font.height = fontheight;
981 			vc_resize(c, 0, rows);	/* Adjust console size */
982 		}
983 	}
984 	return 0;
985 }
986 
987 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
988 {
989 	unsigned charcount = font->charcount;
990 	int rc;
991 
992 	if (vga_video_type < VIDEO_TYPE_EGAM)
993 		return -EINVAL;
994 
995 	if (font->width != 8 || (charcount != 256 && charcount != 512))
996 		return -EINVAL;
997 
998 	rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
999 	if (rc)
1000 		return rc;
1001 
1002 	if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1003 		rc = vgacon_adjust_height(c, font->height);
1004 	return rc;
1005 }
1006 
1007 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1008 {
1009 	if (vga_video_type < VIDEO_TYPE_EGAM)
1010 		return -EINVAL;
1011 
1012 	font->width = 8;
1013 	font->height = c->vc_font.height;
1014 	font->charcount = vga_512_chars ? 512 : 256;
1015 	if (!font->data)
1016 		return 0;
1017 	return vgacon_do_font_op(&state, font->data, 0, 0);
1018 }
1019 
1020 #else
1021 
1022 #define vgacon_font_set NULL
1023 #define vgacon_font_get NULL
1024 
1025 #endif
1026 
1027 static int vgacon_resize(struct vc_data *c, unsigned int width,
1028 				unsigned int height)
1029 {
1030 	if (width % 2 || width > ORIG_VIDEO_COLS ||
1031 	    height > (ORIG_VIDEO_LINES * vga_default_font_height)/
1032 	    c->vc_font.height)
1033 		/* let svgatextmode tinker with video timings */
1034 		return 0;
1035 
1036 	if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1037 		vgacon_doresize(c, width, height);
1038 	return 0;
1039 }
1040 
1041 static int vgacon_scrolldelta(struct vc_data *c, int lines)
1042 {
1043 	if (!lines)		/* Turn scrollback off */
1044 		c->vc_visible_origin = c->vc_origin;
1045 	else {
1046 		int margin = c->vc_size_row * 4;
1047 		int ul, we, p, st;
1048 
1049 		if (vga_rolled_over >
1050 		    (c->vc_scr_end - vga_vram_base) + margin) {
1051 			ul = c->vc_scr_end - vga_vram_base;
1052 			we = vga_rolled_over + c->vc_size_row;
1053 		} else {
1054 			ul = 0;
1055 			we = vga_vram_size;
1056 		}
1057 		p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
1058 		    lines * c->vc_size_row;
1059 		st = (c->vc_origin - vga_vram_base - ul + we) % we;
1060 		if (st < 2 * margin)
1061 			margin = 0;
1062 		if (p < margin)
1063 			p = 0;
1064 		if (p > st - margin)
1065 			p = st;
1066 		c->vc_visible_origin = vga_vram_base + (p + ul) % we;
1067 	}
1068 	vga_set_mem_top(c);
1069 	return 1;
1070 }
1071 
1072 static int vgacon_set_origin(struct vc_data *c)
1073 {
1074 	if (vga_is_gfx ||	/* We don't play origin tricks in graphic modes */
1075 	    (console_blanked && !vga_palette_blanked))	/* Nor we write to blanked screens */
1076 		return 0;
1077 	c->vc_origin = c->vc_visible_origin = vga_vram_base;
1078 	vga_set_mem_top(c);
1079 	vga_rolled_over = 0;
1080 	return 1;
1081 }
1082 
1083 static void vgacon_save_screen(struct vc_data *c)
1084 {
1085 	static int vga_bootup_console = 0;
1086 
1087 	if (!vga_bootup_console) {
1088 		/* This is a gross hack, but here is the only place we can
1089 		 * set bootup console parameters without messing up generic
1090 		 * console initialization routines.
1091 		 */
1092 		vga_bootup_console = 1;
1093 		c->vc_x = ORIG_X;
1094 		c->vc_y = ORIG_Y;
1095 	}
1096 
1097 	/* We can't copy in more then the size of the video buffer,
1098 	 * or we'll be copying in VGA BIOS */
1099 
1100 	if (!vga_is_gfx)
1101 		scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1102 			    c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1103 }
1104 
1105 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1106 			 int lines)
1107 {
1108 	unsigned long oldo;
1109 	unsigned int delta;
1110 
1111 	if (t || b != c->vc_rows || vga_is_gfx)
1112 		return 0;
1113 
1114 	if (c->vc_origin != c->vc_visible_origin)
1115 		vgacon_scrolldelta(c, 0);
1116 
1117 	if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1118 		return 0;
1119 
1120 	oldo = c->vc_origin;
1121 	delta = lines * c->vc_size_row;
1122 	if (dir == SM_UP) {
1123 		if (c->vc_scr_end + delta >= vga_vram_end) {
1124 			scr_memcpyw((u16 *) vga_vram_base,
1125 				    (u16 *) (oldo + delta),
1126 				    c->vc_screenbuf_size - delta);
1127 			c->vc_origin = vga_vram_base;
1128 			vga_rolled_over = oldo - vga_vram_base;
1129 		} else
1130 			c->vc_origin += delta;
1131 		scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1132 				     delta), c->vc_video_erase_char,
1133 			    delta);
1134 	} else {
1135 		if (oldo - delta < vga_vram_base) {
1136 			scr_memmovew((u16 *) (vga_vram_end -
1137 					      c->vc_screenbuf_size +
1138 					      delta), (u16 *) oldo,
1139 				     c->vc_screenbuf_size - delta);
1140 			c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1141 			vga_rolled_over = 0;
1142 		} else
1143 			c->vc_origin -= delta;
1144 		c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1145 		scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1146 			    delta);
1147 	}
1148 	c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1149 	c->vc_visible_origin = c->vc_origin;
1150 	vga_set_mem_top(c);
1151 	c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1152 	return 1;
1153 }
1154 
1155 
1156 /*
1157  *  The console `switch' structure for the VGA based console
1158  */
1159 
1160 static int vgacon_dummy(struct vc_data *c)
1161 {
1162 	return 0;
1163 }
1164 
1165 #define DUMMY (void *) vgacon_dummy
1166 
1167 const struct consw vga_con = {
1168 	.owner = THIS_MODULE,
1169 	.con_startup = vgacon_startup,
1170 	.con_init = vgacon_init,
1171 	.con_deinit = vgacon_deinit,
1172 	.con_clear = DUMMY,
1173 	.con_putc = DUMMY,
1174 	.con_putcs = DUMMY,
1175 	.con_cursor = vgacon_cursor,
1176 	.con_scroll = vgacon_scroll,
1177 	.con_bmove = DUMMY,
1178 	.con_switch = vgacon_switch,
1179 	.con_blank = vgacon_blank,
1180 	.con_font_set = vgacon_font_set,
1181 	.con_font_get = vgacon_font_get,
1182 	.con_resize = vgacon_resize,
1183 	.con_set_palette = vgacon_set_palette,
1184 	.con_scrolldelta = vgacon_scrolldelta,
1185 	.con_set_origin = vgacon_set_origin,
1186 	.con_save_screen = vgacon_save_screen,
1187 	.con_build_attr = vgacon_build_attr,
1188 	.con_invert_region = vgacon_invert_region,
1189 };
1190 
1191 MODULE_LICENSE("GPL");
1192