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