xref: /openbmc/linux/drivers/video/console/vgacon.c (revision a06c488d)
1 /*
2  *  linux/drivers/video/vgacon.c -- Low level VGA based console driver
3  *
4  *	Created 28 Sep 1997 by Geert Uytterhoeven
5  *
6  *	Rewritten by Martin Mares <mj@ucw.cz>, July 1998
7  *
8  *  This file is based on the old console.c, vga.c and vesa_blank.c drivers.
9  *
10  *	Copyright (C) 1991, 1992  Linus Torvalds
11  *			    1995  Jay Estabrook
12  *
13  *	User definable mapping table and font loading by Eugene G. Crosser,
14  *	<crosser@average.org>
15  *
16  *	Improved loadable font/UTF-8 support by H. Peter Anvin
17  *	Feb-Sep 1995 <peter.anvin@linux.org>
18  *
19  *	Colour palette handling, by Simon Tatham
20  *	17-Jun-95 <sgt20@cam.ac.uk>
21  *
22  *	if 512 char mode is already enabled don't re-enable it,
23  *	because it causes screen to flicker, by Mitja Horvat
24  *	5-May-96 <mitja.horvat@guest.arnes.si>
25  *
26  *	Use 2 outw instead of 4 outb_p to reduce erroneous text
27  *	flashing on RHS of screen during heavy console scrolling .
28  *	Oct 1996, Paul Gortmaker.
29  *
30  *
31  *  This file is subject to the terms and conditions of the GNU General Public
32  *  License.  See the file COPYING in the main directory of this archive for
33  *  more details.
34  */
35 
36 #include <linux/module.h>
37 #include <linux/types.h>
38 #include <linux/fs.h>
39 #include <linux/kernel.h>
40 #include <linux/console.h>
41 #include <linux/string.h>
42 #include <linux/kd.h>
43 #include <linux/slab.h>
44 #include <linux/vt_kern.h>
45 #include <linux/sched.h>
46 #include <linux/selection.h>
47 #include <linux/spinlock.h>
48 #include <linux/ioport.h>
49 #include <linux/init.h>
50 #include <linux/screen_info.h>
51 #include <video/vga.h>
52 #include <asm/io.h>
53 
54 static DEFINE_RAW_SPINLOCK(vga_lock);
55 static int cursor_size_lastfrom;
56 static int cursor_size_lastto;
57 static u32 vgacon_xres;
58 static u32 vgacon_yres;
59 static struct vgastate vgastate;
60 
61 #define BLANK 0x0020
62 
63 #define 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 #define VGA_FONTWIDTH       8   /* VGA does not support fontwidths != 8 */
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 void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
90 static struct uni_pagedir *vgacon_uni_pagedir;
91 static int vgacon_refcount;
92 
93 /* Description of the hardware situation */
94 static int		vga_init_done		__read_mostly;
95 static unsigned long	vga_vram_base		__read_mostly;	/* Base of video memory */
96 static unsigned long	vga_vram_end		__read_mostly;	/* End of video memory */
97 static unsigned int	vga_vram_size		__read_mostly;	/* Size of video memory */
98 static u16		vga_video_port_reg	__read_mostly;	/* Video register select port */
99 static u16		vga_video_port_val	__read_mostly;	/* Video register value port */
100 static unsigned int	vga_video_num_columns;			/* Number of text columns */
101 static unsigned int	vga_video_num_lines;			/* Number of text lines */
102 static int		vga_can_do_color	__read_mostly;	/* Do we support colors? */
103 static unsigned int	vga_default_font_height __read_mostly;	/* Height of default screen font */
104 static unsigned char	vga_video_type		__read_mostly;	/* Card type */
105 static unsigned char	vga_hardscroll_enabled	__read_mostly;
106 static unsigned char	vga_hardscroll_user_enable __read_mostly = 1;
107 static unsigned char	vga_font_is_default = 1;
108 static int		vga_vesa_blanked;
109 static int 		vga_palette_blanked;
110 static int 		vga_is_gfx;
111 static int 		vga_512_chars;
112 static int 		vga_video_font_height;
113 static int 		vga_scan_lines		__read_mostly;
114 static unsigned int 	vga_rolled_over;
115 
116 static int vgacon_text_mode_force;
117 
118 bool vgacon_text_force(void)
119 {
120 	return vgacon_text_mode_force ? true : false;
121 }
122 EXPORT_SYMBOL(vgacon_text_force);
123 
124 static int __init text_mode(char *str)
125 {
126 	vgacon_text_mode_force = 1;
127 	return 1;
128 }
129 
130 /* force text mode - used by kernel modesetting */
131 __setup("nomodeset", text_mode);
132 
133 static int __init no_scroll(char *str)
134 {
135 	/*
136 	 * Disabling scrollback is required for the Braillex ib80-piezo
137 	 * Braille reader made by F.H. Papenmeier (Germany).
138 	 * Use the "no-scroll" bootflag.
139 	 */
140 	vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
141 	return 1;
142 }
143 
144 __setup("no-scroll", no_scroll);
145 
146 /*
147  * By replacing the four outb_p with two back to back outw, we can reduce
148  * the window of opportunity to see text mislocated to the RHS of the
149  * console during heavy scrolling activity. However there is the remote
150  * possibility that some pre-dinosaur hardware won't like the back to back
151  * I/O. Since the Xservers get away with it, we should be able to as well.
152  */
153 static inline void write_vga(unsigned char reg, unsigned int val)
154 {
155 	unsigned int v1, v2;
156 	unsigned long flags;
157 
158 	/*
159 	 * ddprintk might set the console position from interrupt
160 	 * handlers, thus the write has to be IRQ-atomic.
161 	 */
162 	raw_spin_lock_irqsave(&vga_lock, flags);
163 
164 #ifndef SLOW_VGA
165 	v1 = reg + (val & 0xff00);
166 	v2 = reg + 1 + ((val << 8) & 0xff00);
167 	outw(v1, vga_video_port_reg);
168 	outw(v2, vga_video_port_reg);
169 #else
170 	outb_p(reg, vga_video_port_reg);
171 	outb_p(val >> 8, vga_video_port_val);
172 	outb_p(reg + 1, vga_video_port_reg);
173 	outb_p(val & 0xff, vga_video_port_val);
174 #endif
175 	raw_spin_unlock_irqrestore(&vga_lock, flags);
176 }
177 
178 static inline void vga_set_mem_top(struct vc_data *c)
179 {
180 	write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
181 }
182 
183 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
184 /* software scrollback */
185 static void *vgacon_scrollback;
186 static int vgacon_scrollback_tail;
187 static int vgacon_scrollback_size;
188 static int vgacon_scrollback_rows;
189 static int vgacon_scrollback_cnt;
190 static int vgacon_scrollback_cur;
191 static int vgacon_scrollback_save;
192 static int vgacon_scrollback_restore;
193 
194 static void vgacon_scrollback_init(int pitch)
195 {
196 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
197 
198 	if (vgacon_scrollback) {
199 		vgacon_scrollback_cnt  = 0;
200 		vgacon_scrollback_tail = 0;
201 		vgacon_scrollback_cur  = 0;
202 		vgacon_scrollback_rows = rows - 1;
203 		vgacon_scrollback_size = rows * pitch;
204 	}
205 }
206 
207 static void vgacon_scrollback_startup(void)
208 {
209 	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
210 	vgacon_scrollback_init(vga_video_num_columns * 2);
211 }
212 
213 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
214 {
215 	void *p;
216 
217 	if (!vgacon_scrollback_size || c->vc_num != fg_console)
218 		return;
219 
220 	p = (void *) (c->vc_origin + t * c->vc_size_row);
221 
222 	while (count--) {
223 		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
224 			    p, c->vc_size_row);
225 		vgacon_scrollback_cnt++;
226 		p += c->vc_size_row;
227 		vgacon_scrollback_tail += c->vc_size_row;
228 
229 		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
230 			vgacon_scrollback_tail = 0;
231 
232 		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
233 			vgacon_scrollback_cnt = vgacon_scrollback_rows;
234 
235 		vgacon_scrollback_cur = vgacon_scrollback_cnt;
236 	}
237 }
238 
239 static void vgacon_restore_screen(struct vc_data *c)
240 {
241 	vgacon_scrollback_save = 0;
242 
243 	if (!vga_is_gfx && !vgacon_scrollback_restore) {
244 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
245 			    c->vc_screenbuf_size > vga_vram_size ?
246 			    vga_vram_size : c->vc_screenbuf_size);
247 		vgacon_scrollback_restore = 1;
248 		vgacon_scrollback_cur = vgacon_scrollback_cnt;
249 	}
250 }
251 
252 static int vgacon_scrolldelta(struct vc_data *c, int lines)
253 {
254 	int start, end, count, soff;
255 
256 	if (!lines) {
257 		c->vc_visible_origin = c->vc_origin;
258 		vga_set_mem_top(c);
259 		return 1;
260 	}
261 
262 	if (!vgacon_scrollback)
263 		return 1;
264 
265 	if (!vgacon_scrollback_save) {
266 		vgacon_cursor(c, CM_ERASE);
267 		vgacon_save_screen(c);
268 		vgacon_scrollback_save = 1;
269 	}
270 
271 	vgacon_scrollback_restore = 0;
272 	start = vgacon_scrollback_cur + lines;
273 	end = start + abs(lines);
274 
275 	if (start < 0)
276 		start = 0;
277 
278 	if (start > vgacon_scrollback_cnt)
279 		start = vgacon_scrollback_cnt;
280 
281 	if (end < 0)
282 		end = 0;
283 
284 	if (end > vgacon_scrollback_cnt)
285 		end = vgacon_scrollback_cnt;
286 
287 	vgacon_scrollback_cur = start;
288 	count = end - start;
289 	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
290 					 c->vc_size_row);
291 	soff -= count * c->vc_size_row;
292 
293 	if (soff < 0)
294 		soff += vgacon_scrollback_size;
295 
296 	count = vgacon_scrollback_cnt - start;
297 
298 	if (count > c->vc_rows)
299 		count = c->vc_rows;
300 
301 	if (count) {
302 		int copysize;
303 
304 		int diff = c->vc_rows - count;
305 		void *d = (void *) c->vc_origin;
306 		void *s = (void *) c->vc_screenbuf;
307 
308 		count *= c->vc_size_row;
309 		/* how much memory to end of buffer left? */
310 		copysize = min(count, vgacon_scrollback_size - soff);
311 		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
312 		d += copysize;
313 		count -= copysize;
314 
315 		if (count) {
316 			scr_memcpyw(d, vgacon_scrollback, count);
317 			d += count;
318 		}
319 
320 		if (diff)
321 			scr_memcpyw(d, s, diff * c->vc_size_row);
322 	} else
323 		vgacon_cursor(c, CM_MOVE);
324 
325 	return 1;
326 }
327 #else
328 #define vgacon_scrollback_startup(...) do { } while (0)
329 #define vgacon_scrollback_init(...)    do { } while (0)
330 #define vgacon_scrollback_update(...)  do { } while (0)
331 
332 static void vgacon_restore_screen(struct vc_data *c)
333 {
334 	if (c->vc_origin != c->vc_visible_origin)
335 		vgacon_scrolldelta(c, 0);
336 }
337 
338 static int vgacon_scrolldelta(struct vc_data *c, int lines)
339 {
340 	if (!lines)		/* Turn scrollback off */
341 		c->vc_visible_origin = c->vc_origin;
342 	else {
343 		int margin = c->vc_size_row * 4;
344 		int ul, we, p, st;
345 
346 		if (vga_rolled_over >
347 		    (c->vc_scr_end - vga_vram_base) + margin) {
348 			ul = c->vc_scr_end - vga_vram_base;
349 			we = vga_rolled_over + c->vc_size_row;
350 		} else {
351 			ul = 0;
352 			we = vga_vram_size;
353 		}
354 		p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
355 		    lines * c->vc_size_row;
356 		st = (c->vc_origin - vga_vram_base - ul + we) % we;
357 		if (st < 2 * margin)
358 			margin = 0;
359 		if (p < margin)
360 			p = 0;
361 		if (p > st - margin)
362 			p = st;
363 		c->vc_visible_origin = vga_vram_base + (p + ul) % we;
364 	}
365 	vga_set_mem_top(c);
366 	return 1;
367 }
368 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
369 
370 static const char *vgacon_startup(void)
371 {
372 	const char *display_desc = NULL;
373 	u16 saved1, saved2;
374 	volatile u16 *p;
375 
376 	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
377 	    screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
378 	      no_vga:
379 #ifdef CONFIG_DUMMY_CONSOLE
380 		conswitchp = &dummy_con;
381 		return conswitchp->con_startup();
382 #else
383 		return NULL;
384 #endif
385 	}
386 
387 	/* boot_params.screen_info initialized? */
388 	if ((screen_info.orig_video_mode  == 0) &&
389 	    (screen_info.orig_video_lines == 0) &&
390 	    (screen_info.orig_video_cols  == 0))
391 		goto no_vga;
392 
393 	/* VGA16 modes are not handled by VGACON */
394 	if ((screen_info.orig_video_mode == 0x0D) ||	/* 320x200/4 */
395 	    (screen_info.orig_video_mode == 0x0E) ||	/* 640x200/4 */
396 	    (screen_info.orig_video_mode == 0x10) ||	/* 640x350/4 */
397 	    (screen_info.orig_video_mode == 0x12) ||	/* 640x480/4 */
398 	    (screen_info.orig_video_mode == 0x6A))	/* 800x600/4 (VESA) */
399 		goto no_vga;
400 
401 	vga_video_num_lines = screen_info.orig_video_lines;
402 	vga_video_num_columns = screen_info.orig_video_cols;
403 	vgastate.vgabase = NULL;
404 
405 	if (screen_info.orig_video_mode == 7) {
406 		/* Monochrome display */
407 		vga_vram_base = 0xb0000;
408 		vga_video_port_reg = VGA_CRT_IM;
409 		vga_video_port_val = VGA_CRT_DM;
410 		if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
411 			static struct resource ega_console_resource =
412 			    { .name = "ega", .start = 0x3B0, .end = 0x3BF };
413 			vga_video_type = VIDEO_TYPE_EGAM;
414 			vga_vram_size = 0x8000;
415 			display_desc = "EGA+";
416 			request_resource(&ioport_resource,
417 					 &ega_console_resource);
418 		} else {
419 			static struct resource mda1_console_resource =
420 			    { .name = "mda", .start = 0x3B0, .end = 0x3BB };
421 			static struct resource mda2_console_resource =
422 			    { .name = "mda", .start = 0x3BF, .end = 0x3BF };
423 			vga_video_type = VIDEO_TYPE_MDA;
424 			vga_vram_size = 0x2000;
425 			display_desc = "*MDA";
426 			request_resource(&ioport_resource,
427 					 &mda1_console_resource);
428 			request_resource(&ioport_resource,
429 					 &mda2_console_resource);
430 			vga_video_font_height = 14;
431 		}
432 	} else {
433 		/* If not, it is color. */
434 		vga_can_do_color = 1;
435 		vga_vram_base = 0xb8000;
436 		vga_video_port_reg = VGA_CRT_IC;
437 		vga_video_port_val = VGA_CRT_DC;
438 		if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
439 			int i;
440 
441 			vga_vram_size = 0x8000;
442 
443 			if (!screen_info.orig_video_isVGA) {
444 				static struct resource ega_console_resource
445 				    = { .name = "ega", .start = 0x3C0, .end = 0x3DF };
446 				vga_video_type = VIDEO_TYPE_EGAC;
447 				display_desc = "EGA";
448 				request_resource(&ioport_resource,
449 						 &ega_console_resource);
450 			} else {
451 				static struct resource vga_console_resource
452 				    = { .name = "vga+", .start = 0x3C0, .end = 0x3DF };
453 				vga_video_type = VIDEO_TYPE_VGAC;
454 				display_desc = "VGA+";
455 				request_resource(&ioport_resource,
456 						 &vga_console_resource);
457 
458 #ifdef VGA_CAN_DO_64KB
459 				/*
460 				 * get 64K rather than 32K of video RAM.
461 				 * This doesn't actually work on all "VGA"
462 				 * controllers (it seems like setting MM=01
463 				 * and COE=1 isn't necessarily a good idea)
464 				 */
465 				vga_vram_base = 0xa0000;
466 				vga_vram_size = 0x10000;
467 				outb_p(6, VGA_GFX_I);
468 				outb_p(6, VGA_GFX_D);
469 #endif
470 				/*
471 				 * Normalise the palette registers, to point
472 				 * the 16 screen colours to the first 16
473 				 * DAC entries.
474 				 */
475 
476 				for (i = 0; i < 16; i++) {
477 					inb_p(VGA_IS1_RC);
478 					outb_p(i, VGA_ATT_W);
479 					outb_p(i, VGA_ATT_W);
480 				}
481 				outb_p(0x20, VGA_ATT_W);
482 
483 				/*
484 				 * Now set the DAC registers back to their
485 				 * default values
486 				 */
487 				for (i = 0; i < 16; i++) {
488 					outb_p(color_table[i], VGA_PEL_IW);
489 					outb_p(default_red[i], VGA_PEL_D);
490 					outb_p(default_grn[i], VGA_PEL_D);
491 					outb_p(default_blu[i], VGA_PEL_D);
492 				}
493 			}
494 		} else {
495 			static struct resource cga_console_resource =
496 			    { .name = "cga", .start = 0x3D4, .end = 0x3D5 };
497 			vga_video_type = VIDEO_TYPE_CGA;
498 			vga_vram_size = 0x2000;
499 			display_desc = "*CGA";
500 			request_resource(&ioport_resource,
501 					 &cga_console_resource);
502 			vga_video_font_height = 8;
503 		}
504 	}
505 
506 	vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
507 	vga_vram_end = vga_vram_base + vga_vram_size;
508 
509 	/*
510 	 *      Find out if there is a graphics card present.
511 	 *      Are there smarter methods around?
512 	 */
513 	p = (volatile u16 *) vga_vram_base;
514 	saved1 = scr_readw(p);
515 	saved2 = scr_readw(p + 1);
516 	scr_writew(0xAA55, p);
517 	scr_writew(0x55AA, p + 1);
518 	if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
519 		scr_writew(saved1, p);
520 		scr_writew(saved2, p + 1);
521 		goto no_vga;
522 	}
523 	scr_writew(0x55AA, p);
524 	scr_writew(0xAA55, p + 1);
525 	if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
526 		scr_writew(saved1, p);
527 		scr_writew(saved2, p + 1);
528 		goto no_vga;
529 	}
530 	scr_writew(saved1, p);
531 	scr_writew(saved2, p + 1);
532 
533 	if (vga_video_type == VIDEO_TYPE_EGAC
534 	    || vga_video_type == VIDEO_TYPE_VGAC
535 	    || vga_video_type == VIDEO_TYPE_EGAM) {
536 		vga_hardscroll_enabled = vga_hardscroll_user_enable;
537 		vga_default_font_height = screen_info.orig_video_points;
538 		vga_video_font_height = screen_info.orig_video_points;
539 		/* This may be suboptimal but is a safe bet - go with it */
540 		vga_scan_lines =
541 		    vga_video_font_height * vga_video_num_lines;
542 	}
543 
544 	vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
545 	vgacon_yres = vga_scan_lines;
546 
547 	if (!vga_init_done) {
548 		vgacon_scrollback_startup();
549 		vga_init_done = 1;
550 	}
551 
552 	return display_desc;
553 }
554 
555 static void vgacon_init(struct vc_data *c, int init)
556 {
557 	struct uni_pagedir *p;
558 
559 	/*
560 	 * We cannot be loaded as a module, therefore init is always 1,
561 	 * but vgacon_init can be called more than once, and init will
562 	 * not be 1.
563 	 */
564 	c->vc_can_do_color = vga_can_do_color;
565 
566 	/* set dimensions manually if init != 0 since vc_resize() will fail */
567 	if (init) {
568 		c->vc_cols = vga_video_num_columns;
569 		c->vc_rows = vga_video_num_lines;
570 	} else
571 		vc_resize(c, vga_video_num_columns, vga_video_num_lines);
572 
573 	c->vc_scan_lines = vga_scan_lines;
574 	c->vc_font.height = vga_video_font_height;
575 	c->vc_complement_mask = 0x7700;
576 	if (vga_512_chars)
577 		c->vc_hi_font_mask = 0x0800;
578 	p = *c->vc_uni_pagedir_loc;
579 	if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
580 		con_free_unimap(c);
581 		c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
582 		vgacon_refcount++;
583 	}
584 	if (!vgacon_uni_pagedir && p)
585 		con_set_default_unimap(c);
586 
587 	/* Only set the default if the user didn't deliberately override it */
588 	if (global_cursor_default == -1)
589 		global_cursor_default =
590 			!(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
591 }
592 
593 static void vgacon_deinit(struct vc_data *c)
594 {
595 	/* When closing the active console, reset video origin */
596 	if (CON_IS_VISIBLE(c)) {
597 		c->vc_visible_origin = vga_vram_base;
598 		vga_set_mem_top(c);
599 	}
600 
601 	if (!--vgacon_refcount)
602 		con_free_unimap(c);
603 	c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
604 	con_set_default_unimap(c);
605 }
606 
607 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
608 			    u8 blink, u8 underline, u8 reverse, u8 italic)
609 {
610 	u8 attr = color;
611 
612 	if (vga_can_do_color) {
613 		if (italic)
614 			attr = (attr & 0xF0) | c->vc_itcolor;
615 		else if (underline)
616 			attr = (attr & 0xf0) | c->vc_ulcolor;
617 		else if (intensity == 0)
618 			attr = (attr & 0xf0) | c->vc_halfcolor;
619 	}
620 	if (reverse)
621 		attr =
622 		    ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
623 				       0x77);
624 	if (blink)
625 		attr ^= 0x80;
626 	if (intensity == 2)
627 		attr ^= 0x08;
628 	if (!vga_can_do_color) {
629 		if (italic)
630 			attr = (attr & 0xF8) | 0x02;
631 		else if (underline)
632 			attr = (attr & 0xf8) | 0x01;
633 		else if (intensity == 0)
634 			attr = (attr & 0xf0) | 0x08;
635 	}
636 	return attr;
637 }
638 
639 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
640 {
641 	int col = vga_can_do_color;
642 
643 	while (count--) {
644 		u16 a = scr_readw(p);
645 		if (col)
646 			a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
647 			    (((a) & 0x0700) << 4);
648 		else
649 			a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
650 		scr_writew(a, p++);
651 	}
652 }
653 
654 static void vgacon_set_cursor_size(int xpos, int from, int to)
655 {
656 	unsigned long flags;
657 	int curs, cure;
658 
659 #ifdef TRIDENT_GLITCH
660 	if (xpos < 16)
661 		from--, to--;
662 #endif
663 
664 	if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
665 		return;
666 	cursor_size_lastfrom = from;
667 	cursor_size_lastto = to;
668 
669 	raw_spin_lock_irqsave(&vga_lock, flags);
670 	if (vga_video_type >= VIDEO_TYPE_VGAC) {
671 		outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
672 		curs = inb_p(vga_video_port_val);
673 		outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
674 		cure = inb_p(vga_video_port_val);
675 	} else {
676 		curs = 0;
677 		cure = 0;
678 	}
679 
680 	curs = (curs & 0xc0) | from;
681 	cure = (cure & 0xe0) | to;
682 
683 	outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
684 	outb_p(curs, vga_video_port_val);
685 	outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
686 	outb_p(cure, vga_video_port_val);
687 	raw_spin_unlock_irqrestore(&vga_lock, flags);
688 }
689 
690 static void vgacon_cursor(struct vc_data *c, int mode)
691 {
692 	if (c->vc_mode != KD_TEXT)
693 		return;
694 
695 	vgacon_restore_screen(c);
696 
697 	switch (mode) {
698 	case CM_ERASE:
699 		write_vga(14, (c->vc_pos - vga_vram_base) / 2);
700 	        if (vga_video_type >= VIDEO_TYPE_VGAC)
701 			vgacon_set_cursor_size(c->vc_x, 31, 30);
702 		else
703 			vgacon_set_cursor_size(c->vc_x, 31, 31);
704 		break;
705 
706 	case CM_MOVE:
707 	case CM_DRAW:
708 		write_vga(14, (c->vc_pos - vga_vram_base) / 2);
709 		switch (c->vc_cursor_type & 0x0f) {
710 		case CUR_UNDERLINE:
711 			vgacon_set_cursor_size(c->vc_x,
712 					       c->vc_font.height -
713 					       (c->vc_font.height <
714 						10 ? 2 : 3),
715 					       c->vc_font.height -
716 					       (c->vc_font.height <
717 						10 ? 1 : 2));
718 			break;
719 		case CUR_TWO_THIRDS:
720 			vgacon_set_cursor_size(c->vc_x,
721 					       c->vc_font.height / 3,
722 					       c->vc_font.height -
723 					       (c->vc_font.height <
724 						10 ? 1 : 2));
725 			break;
726 		case CUR_LOWER_THIRD:
727 			vgacon_set_cursor_size(c->vc_x,
728 					       (c->vc_font.height * 2) / 3,
729 					       c->vc_font.height -
730 					       (c->vc_font.height <
731 						10 ? 1 : 2));
732 			break;
733 		case CUR_LOWER_HALF:
734 			vgacon_set_cursor_size(c->vc_x,
735 					       c->vc_font.height / 2,
736 					       c->vc_font.height -
737 					       (c->vc_font.height <
738 						10 ? 1 : 2));
739 			break;
740 		case CUR_NONE:
741 			if (vga_video_type >= VIDEO_TYPE_VGAC)
742 				vgacon_set_cursor_size(c->vc_x, 31, 30);
743 			else
744 				vgacon_set_cursor_size(c->vc_x, 31, 31);
745 			break;
746 		default:
747 			vgacon_set_cursor_size(c->vc_x, 1,
748 					       c->vc_font.height);
749 			break;
750 		}
751 		break;
752 	}
753 }
754 
755 static int vgacon_doresize(struct vc_data *c,
756 		unsigned int width, unsigned int height)
757 {
758 	unsigned long flags;
759 	unsigned int scanlines = height * c->vc_font.height;
760 	u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
761 
762 	raw_spin_lock_irqsave(&vga_lock, flags);
763 
764 	vgacon_xres = width * VGA_FONTWIDTH;
765 	vgacon_yres = height * c->vc_font.height;
766 	if (vga_video_type >= VIDEO_TYPE_VGAC) {
767 		outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
768 		max_scan = inb_p(vga_video_port_val);
769 
770 		if (max_scan & 0x80)
771 			scanlines <<= 1;
772 
773 		outb_p(VGA_CRTC_MODE, vga_video_port_reg);
774 		mode = inb_p(vga_video_port_val);
775 
776 		if (mode & 0x04)
777 			scanlines >>= 1;
778 
779 		scanlines -= 1;
780 		scanlines_lo = scanlines & 0xff;
781 
782 		outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
783 		r7 = inb_p(vga_video_port_val) & ~0x42;
784 
785 		if (scanlines & 0x100)
786 			r7 |= 0x02;
787 		if (scanlines & 0x200)
788 			r7 |= 0x40;
789 
790 		/* deprotect registers */
791 		outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
792 		vsync_end = inb_p(vga_video_port_val);
793 		outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
794 		outb_p(vsync_end & ~0x80, vga_video_port_val);
795 	}
796 
797 	outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
798 	outb_p(width - 1, vga_video_port_val);
799 	outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
800 	outb_p(width >> 1, vga_video_port_val);
801 
802 	if (vga_video_type >= VIDEO_TYPE_VGAC) {
803 		outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
804 		outb_p(scanlines_lo, vga_video_port_val);
805 		outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
806 		outb_p(r7,vga_video_port_val);
807 
808 		/* reprotect registers */
809 		outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
810 		outb_p(vsync_end, vga_video_port_val);
811 	}
812 
813 	raw_spin_unlock_irqrestore(&vga_lock, flags);
814 	return 0;
815 }
816 
817 static int vgacon_switch(struct vc_data *c)
818 {
819 	int x = c->vc_cols * VGA_FONTWIDTH;
820 	int y = c->vc_rows * c->vc_font.height;
821 	int rows = screen_info.orig_video_lines * vga_default_font_height/
822 		c->vc_font.height;
823 	/*
824 	 * We need to save screen size here as it's the only way
825 	 * we can spot the screen has been resized and we need to
826 	 * set size of freshly allocated screens ourselves.
827 	 */
828 	vga_video_num_columns = c->vc_cols;
829 	vga_video_num_lines = c->vc_rows;
830 
831 	/* We can only copy out the size of the video buffer here,
832 	 * otherwise we get into VGA BIOS */
833 
834 	if (!vga_is_gfx) {
835 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
836 			    c->vc_screenbuf_size > vga_vram_size ?
837 				vga_vram_size : c->vc_screenbuf_size);
838 
839 		if ((vgacon_xres != x || vgacon_yres != y) &&
840 		    (!(vga_video_num_columns % 2) &&
841 		     vga_video_num_columns <= screen_info.orig_video_cols &&
842 		     vga_video_num_lines <= rows))
843 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
844 	}
845 
846 	vgacon_scrollback_init(c->vc_size_row);
847 	return 0;		/* Redrawing not needed */
848 }
849 
850 static void vga_set_palette(struct vc_data *vc, unsigned char *table)
851 {
852 	int i, j;
853 
854 	vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
855 	for (i = j = 0; i < 16; i++) {
856 		vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
857 		vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
858 		vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
859 		vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
860 	}
861 }
862 
863 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
864 {
865 #ifdef CAN_LOAD_PALETTE
866 	if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
867 	    || !CON_IS_VISIBLE(vc))
868 		return -EINVAL;
869 	vga_set_palette(vc, table);
870 	return 0;
871 #else
872 	return -EINVAL;
873 #endif
874 }
875 
876 /* structure holding original VGA register settings */
877 static struct {
878 	unsigned char SeqCtrlIndex;	/* Sequencer Index reg.   */
879 	unsigned char CrtCtrlIndex;	/* CRT-Contr. Index reg.  */
880 	unsigned char CrtMiscIO;	/* Miscellaneous register */
881 	unsigned char HorizontalTotal;	/* CRT-Controller:00h */
882 	unsigned char HorizDisplayEnd;	/* CRT-Controller:01h */
883 	unsigned char StartHorizRetrace;	/* CRT-Controller:04h */
884 	unsigned char EndHorizRetrace;	/* CRT-Controller:05h */
885 	unsigned char Overflow;	/* CRT-Controller:07h */
886 	unsigned char StartVertRetrace;	/* CRT-Controller:10h */
887 	unsigned char EndVertRetrace;	/* CRT-Controller:11h */
888 	unsigned char ModeControl;	/* CRT-Controller:17h */
889 	unsigned char ClockingMode;	/* Seq-Controller:01h */
890 } vga_state;
891 
892 static void vga_vesa_blank(struct vgastate *state, int mode)
893 {
894 	/* save original values of VGA controller registers */
895 	if (!vga_vesa_blanked) {
896 		raw_spin_lock_irq(&vga_lock);
897 		vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
898 		vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
899 		vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
900 		raw_spin_unlock_irq(&vga_lock);
901 
902 		outb_p(0x00, vga_video_port_reg);	/* HorizontalTotal */
903 		vga_state.HorizontalTotal = inb_p(vga_video_port_val);
904 		outb_p(0x01, vga_video_port_reg);	/* HorizDisplayEnd */
905 		vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
906 		outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
907 		vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
908 		outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
909 		vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
910 		outb_p(0x07, vga_video_port_reg);	/* Overflow */
911 		vga_state.Overflow = inb_p(vga_video_port_val);
912 		outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
913 		vga_state.StartVertRetrace = inb_p(vga_video_port_val);
914 		outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
915 		vga_state.EndVertRetrace = inb_p(vga_video_port_val);
916 		outb_p(0x17, vga_video_port_reg);	/* ModeControl */
917 		vga_state.ModeControl = inb_p(vga_video_port_val);
918 		vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
919 	}
920 
921 	/* assure that video is enabled */
922 	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
923 	raw_spin_lock_irq(&vga_lock);
924 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
925 
926 	/* test for vertical retrace in process.... */
927 	if ((vga_state.CrtMiscIO & 0x80) == 0x80)
928 		vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
929 
930 	/*
931 	 * Set <End of vertical retrace> to minimum (0) and
932 	 * <Start of vertical Retrace> to maximum (incl. overflow)
933 	 * Result: turn off vertical sync (VSync) pulse.
934 	 */
935 	if (mode & VESA_VSYNC_SUSPEND) {
936 		outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
937 		outb_p(0xff, vga_video_port_val);	/* maximum value */
938 		outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
939 		outb_p(0x40, vga_video_port_val);	/* minimum (bits 0..3)  */
940 		outb_p(0x07, vga_video_port_reg);	/* Overflow */
941 		outb_p(vga_state.Overflow | 0x84, vga_video_port_val);	/* bits 9,10 of vert. retrace */
942 	}
943 
944 	if (mode & VESA_HSYNC_SUSPEND) {
945 		/*
946 		 * Set <End of horizontal retrace> to minimum (0) and
947 		 *  <Start of horizontal Retrace> to maximum
948 		 * Result: turn off horizontal sync (HSync) pulse.
949 		 */
950 		outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
951 		outb_p(0xff, vga_video_port_val);	/* maximum */
952 		outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
953 		outb_p(0x00, vga_video_port_val);	/* minimum (0) */
954 	}
955 
956 	/* restore both index registers */
957 	vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
958 	outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
959 	raw_spin_unlock_irq(&vga_lock);
960 }
961 
962 static void vga_vesa_unblank(struct vgastate *state)
963 {
964 	/* restore original values of VGA controller registers */
965 	raw_spin_lock_irq(&vga_lock);
966 	vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
967 
968 	outb_p(0x00, vga_video_port_reg);	/* HorizontalTotal */
969 	outb_p(vga_state.HorizontalTotal, vga_video_port_val);
970 	outb_p(0x01, vga_video_port_reg);	/* HorizDisplayEnd */
971 	outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
972 	outb_p(0x04, vga_video_port_reg);	/* StartHorizRetrace */
973 	outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
974 	outb_p(0x05, vga_video_port_reg);	/* EndHorizRetrace */
975 	outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
976 	outb_p(0x07, vga_video_port_reg);	/* Overflow */
977 	outb_p(vga_state.Overflow, vga_video_port_val);
978 	outb_p(0x10, vga_video_port_reg);	/* StartVertRetrace */
979 	outb_p(vga_state.StartVertRetrace, vga_video_port_val);
980 	outb_p(0x11, vga_video_port_reg);	/* EndVertRetrace */
981 	outb_p(vga_state.EndVertRetrace, vga_video_port_val);
982 	outb_p(0x17, vga_video_port_reg);	/* ModeControl */
983 	outb_p(vga_state.ModeControl, vga_video_port_val);
984 	/* ClockingMode */
985 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
986 
987 	/* restore index/control registers */
988 	vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
989 	outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
990 	raw_spin_unlock_irq(&vga_lock);
991 }
992 
993 static void vga_pal_blank(struct vgastate *state)
994 {
995 	int i;
996 
997 	vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
998 	for (i = 0; i < 16; i++) {
999 		vga_w(state->vgabase, VGA_PEL_IW, i);
1000 		vga_w(state->vgabase, VGA_PEL_D, 0);
1001 		vga_w(state->vgabase, VGA_PEL_D, 0);
1002 		vga_w(state->vgabase, VGA_PEL_D, 0);
1003 	}
1004 }
1005 
1006 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
1007 {
1008 	switch (blank) {
1009 	case 0:		/* Unblank */
1010 		if (vga_vesa_blanked) {
1011 			vga_vesa_unblank(&vgastate);
1012 			vga_vesa_blanked = 0;
1013 		}
1014 		if (vga_palette_blanked) {
1015 			vga_set_palette(c, color_table);
1016 			vga_palette_blanked = 0;
1017 			return 0;
1018 		}
1019 		vga_is_gfx = 0;
1020 		/* Tell console.c that it has to restore the screen itself */
1021 		return 1;
1022 	case 1:		/* Normal blanking */
1023 	case -1:	/* Obsolete */
1024 		if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
1025 			vga_pal_blank(&vgastate);
1026 			vga_palette_blanked = 1;
1027 			return 0;
1028 		}
1029 		vgacon_set_origin(c);
1030 		scr_memsetw((void *) vga_vram_base, BLANK,
1031 			    c->vc_screenbuf_size);
1032 		if (mode_switch)
1033 			vga_is_gfx = 1;
1034 		return 1;
1035 	default:		/* VESA blanking */
1036 		if (vga_video_type == VIDEO_TYPE_VGAC) {
1037 			vga_vesa_blank(&vgastate, blank - 1);
1038 			vga_vesa_blanked = blank;
1039 		}
1040 		return 0;
1041 	}
1042 }
1043 
1044 /*
1045  * PIO_FONT support.
1046  *
1047  * The font loading code goes back to the codepage package by
1048  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
1049  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
1050  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
1051  *
1052  * Change for certain monochrome monitors by Yury Shevchuck
1053  * (sizif@botik.yaroslavl.su).
1054  */
1055 
1056 #ifdef CAN_LOAD_EGA_FONTS
1057 
1058 #define colourmap 0xa0000
1059 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
1060    should use 0xA0000 for the bwmap as well.. */
1061 #define blackwmap 0xa0000
1062 #define cmapsz 8192
1063 
1064 static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1065 {
1066 	unsigned short video_port_status = vga_video_port_reg + 6;
1067 	int font_select = 0x00, beg, i;
1068 	char *charmap;
1069 	bool clear_attribs = false;
1070 	if (vga_video_type != VIDEO_TYPE_EGAM) {
1071 		charmap = (char *) VGA_MAP_MEM(colourmap, 0);
1072 		beg = 0x0e;
1073 #ifdef VGA_CAN_DO_64KB
1074 		if (vga_video_type == VIDEO_TYPE_VGAC)
1075 			beg = 0x06;
1076 #endif
1077 	} else {
1078 		charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
1079 		beg = 0x0a;
1080 	}
1081 
1082 #ifdef BROKEN_GRAPHICS_PROGRAMS
1083 	/*
1084 	 * All fonts are loaded in slot 0 (0:1 for 512 ch)
1085 	 */
1086 
1087 	if (!arg)
1088 		return -EINVAL;	/* Return to default font not supported */
1089 
1090 	vga_font_is_default = 0;
1091 	font_select = ch512 ? 0x04 : 0x00;
1092 #else
1093 	/*
1094 	 * The default font is kept in slot 0 and is never touched.
1095 	 * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
1096 	 */
1097 
1098 	if (set) {
1099 		vga_font_is_default = !arg;
1100 		if (!arg)
1101 			ch512 = 0;	/* Default font is always 256 */
1102 		font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
1103 	}
1104 
1105 	if (!vga_font_is_default)
1106 		charmap += 4 * cmapsz;
1107 #endif
1108 
1109 	raw_spin_lock_irq(&vga_lock);
1110 	/* First, the Sequencer */
1111 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
1112 	/* CPU writes only to map 2 */
1113 	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
1114 	/* Sequential addressing */
1115 	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
1116 	/* Clear synchronous reset */
1117 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1118 
1119 	/* Now, the graphics controller, select map 2 */
1120 	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
1121 	/* disable odd-even addressing */
1122 	vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
1123 	/* map start at A000:0000 */
1124 	vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
1125 	raw_spin_unlock_irq(&vga_lock);
1126 
1127 	if (arg) {
1128 		if (set)
1129 			for (i = 0; i < cmapsz; i++) {
1130 				vga_writeb(arg[i], charmap + i);
1131 				cond_resched();
1132 			}
1133 		else
1134 			for (i = 0; i < cmapsz; i++) {
1135 				arg[i] = vga_readb(charmap + i);
1136 				cond_resched();
1137 			}
1138 
1139 		/*
1140 		 * In 512-character mode, the character map is not contiguous if
1141 		 * we want to remain EGA compatible -- which we do
1142 		 */
1143 
1144 		if (ch512) {
1145 			charmap += 2 * cmapsz;
1146 			arg += cmapsz;
1147 			if (set)
1148 				for (i = 0; i < cmapsz; i++) {
1149 					vga_writeb(arg[i], charmap + i);
1150 					cond_resched();
1151 				}
1152 			else
1153 				for (i = 0; i < cmapsz; i++) {
1154 					arg[i] = vga_readb(charmap + i);
1155 					cond_resched();
1156 				}
1157 		}
1158 	}
1159 
1160 	raw_spin_lock_irq(&vga_lock);
1161 	/* First, the sequencer, Synchronous reset */
1162 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
1163 	/* CPU writes to maps 0 and 1 */
1164 	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
1165 	/* odd-even addressing */
1166 	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
1167 	/* Character Map Select */
1168 	if (set)
1169 		vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
1170 	/* clear synchronous reset */
1171 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1172 
1173 	/* Now, the graphics controller, select map 0 for CPU */
1174 	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
1175 	/* enable even-odd addressing */
1176 	vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
1177 	/* map starts at b800:0 or b000:0 */
1178 	vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
1179 
1180 	/* if 512 char mode is already enabled don't re-enable it. */
1181 	if ((set) && (ch512 != vga_512_chars)) {
1182 		vga_512_chars = ch512;
1183 		/* 256-char: enable intensity bit
1184 		   512-char: disable intensity bit */
1185 		inb_p(video_port_status);	/* clear address flip-flop */
1186 		/* color plane enable register */
1187 		vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
1188 		/* Wilton (1987) mentions the following; I don't know what
1189 		   it means, but it works, and it appears necessary */
1190 		inb_p(video_port_status);
1191 		vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1192 		clear_attribs = true;
1193 	}
1194 	raw_spin_unlock_irq(&vga_lock);
1195 
1196 	if (clear_attribs) {
1197 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
1198 			struct vc_data *c = vc_cons[i].d;
1199 			if (c && c->vc_sw == &vga_con) {
1200 				/* force hi font mask to 0, so we always clear
1201 				   the bit on either transition */
1202 				c->vc_hi_font_mask = 0x00;
1203 				clear_buffer_attributes(c);
1204 				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1205 			}
1206 		}
1207 	}
1208 	return 0;
1209 }
1210 
1211 /*
1212  * Adjust the screen to fit a font of a certain height
1213  */
1214 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
1215 {
1216 	unsigned char ovr, vde, fsr;
1217 	int rows, maxscan, i;
1218 
1219 	rows = vc->vc_scan_lines / fontheight;	/* Number of video rows we end up with */
1220 	maxscan = rows * fontheight - 1;	/* Scan lines to actually display-1 */
1221 
1222 	/* Reprogram the CRTC for the new font size
1223 	   Note: the attempt to read the overflow register will fail
1224 	   on an EGA, but using 0xff for the previous value appears to
1225 	   be OK for EGA text modes in the range 257-512 scan lines, so I
1226 	   guess we don't need to worry about it.
1227 
1228 	   The same applies for the spill bits in the font size and cursor
1229 	   registers; they are write-only on EGA, but it appears that they
1230 	   are all don't care bits on EGA, so I guess it doesn't matter. */
1231 
1232 	raw_spin_lock_irq(&vga_lock);
1233 	outb_p(0x07, vga_video_port_reg);	/* CRTC overflow register */
1234 	ovr = inb_p(vga_video_port_val);
1235 	outb_p(0x09, vga_video_port_reg);	/* Font size register */
1236 	fsr = inb_p(vga_video_port_val);
1237 	raw_spin_unlock_irq(&vga_lock);
1238 
1239 	vde = maxscan & 0xff;	/* Vertical display end reg */
1240 	ovr = (ovr & 0xbd) +	/* Overflow register */
1241 	    ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1242 	fsr = (fsr & 0xe0) + (fontheight - 1);	/*  Font size register */
1243 
1244 	raw_spin_lock_irq(&vga_lock);
1245 	outb_p(0x07, vga_video_port_reg);	/* CRTC overflow register */
1246 	outb_p(ovr, vga_video_port_val);
1247 	outb_p(0x09, vga_video_port_reg);	/* Font size */
1248 	outb_p(fsr, vga_video_port_val);
1249 	outb_p(0x12, vga_video_port_reg);	/* Vertical display limit */
1250 	outb_p(vde, vga_video_port_val);
1251 	raw_spin_unlock_irq(&vga_lock);
1252 	vga_video_font_height = fontheight;
1253 
1254 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
1255 		struct vc_data *c = vc_cons[i].d;
1256 
1257 		if (c && c->vc_sw == &vga_con) {
1258 			if (CON_IS_VISIBLE(c)) {
1259 			        /* void size to cause regs to be rewritten */
1260 				cursor_size_lastfrom = 0;
1261 				cursor_size_lastto = 0;
1262 				c->vc_sw->con_cursor(c, CM_DRAW);
1263 			}
1264 			c->vc_font.height = fontheight;
1265 			vc_resize(c, 0, rows);	/* Adjust console size */
1266 		}
1267 	}
1268 	return 0;
1269 }
1270 
1271 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
1272 {
1273 	unsigned charcount = font->charcount;
1274 	int rc;
1275 
1276 	if (vga_video_type < VIDEO_TYPE_EGAM)
1277 		return -EINVAL;
1278 
1279 	if (font->width != VGA_FONTWIDTH ||
1280 	    (charcount != 256 && charcount != 512))
1281 		return -EINVAL;
1282 
1283 	rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1284 	if (rc)
1285 		return rc;
1286 
1287 	if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1288 		rc = vgacon_adjust_height(c, font->height);
1289 	return rc;
1290 }
1291 
1292 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1293 {
1294 	if (vga_video_type < VIDEO_TYPE_EGAM)
1295 		return -EINVAL;
1296 
1297 	font->width = VGA_FONTWIDTH;
1298 	font->height = c->vc_font.height;
1299 	font->charcount = vga_512_chars ? 512 : 256;
1300 	if (!font->data)
1301 		return 0;
1302 	return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1303 }
1304 
1305 #else
1306 
1307 #define vgacon_font_set NULL
1308 #define vgacon_font_get NULL
1309 
1310 #endif
1311 
1312 static int vgacon_resize(struct vc_data *c, unsigned int width,
1313 			 unsigned int height, unsigned int user)
1314 {
1315 	if (width % 2 || width > screen_info.orig_video_cols ||
1316 	    height > (screen_info.orig_video_lines * vga_default_font_height)/
1317 	    c->vc_font.height)
1318 		/* let svgatextmode tinker with video timings and
1319 		   return success */
1320 		return (user) ? 0 : -EINVAL;
1321 
1322 	if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1323 		vgacon_doresize(c, width, height);
1324 	return 0;
1325 }
1326 
1327 static int vgacon_set_origin(struct vc_data *c)
1328 {
1329 	if (vga_is_gfx ||	/* We don't play origin tricks in graphic modes */
1330 	    (console_blanked && !vga_palette_blanked))	/* Nor we write to blanked screens */
1331 		return 0;
1332 	c->vc_origin = c->vc_visible_origin = vga_vram_base;
1333 	vga_set_mem_top(c);
1334 	vga_rolled_over = 0;
1335 	return 1;
1336 }
1337 
1338 static void vgacon_save_screen(struct vc_data *c)
1339 {
1340 	static int vga_bootup_console = 0;
1341 
1342 	if (!vga_bootup_console) {
1343 		/* This is a gross hack, but here is the only place we can
1344 		 * set bootup console parameters without messing up generic
1345 		 * console initialization routines.
1346 		 */
1347 		vga_bootup_console = 1;
1348 		c->vc_x = screen_info.orig_x;
1349 		c->vc_y = screen_info.orig_y;
1350 	}
1351 
1352 	/* We can't copy in more than the size of the video buffer,
1353 	 * or we'll be copying in VGA BIOS */
1354 
1355 	if (!vga_is_gfx)
1356 		scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1357 			    c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1358 }
1359 
1360 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1361 			 int lines)
1362 {
1363 	unsigned long oldo;
1364 	unsigned int delta;
1365 
1366 	if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1367 		return 0;
1368 
1369 	if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1370 		return 0;
1371 
1372 	vgacon_restore_screen(c);
1373 	oldo = c->vc_origin;
1374 	delta = lines * c->vc_size_row;
1375 	if (dir == SM_UP) {
1376 		vgacon_scrollback_update(c, t, lines);
1377 		if (c->vc_scr_end + delta >= vga_vram_end) {
1378 			scr_memcpyw((u16 *) vga_vram_base,
1379 				    (u16 *) (oldo + delta),
1380 				    c->vc_screenbuf_size - delta);
1381 			c->vc_origin = vga_vram_base;
1382 			vga_rolled_over = oldo - vga_vram_base;
1383 		} else
1384 			c->vc_origin += delta;
1385 		scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1386 				     delta), c->vc_video_erase_char,
1387 			    delta);
1388 	} else {
1389 		if (oldo - delta < vga_vram_base) {
1390 			scr_memmovew((u16 *) (vga_vram_end -
1391 					      c->vc_screenbuf_size +
1392 					      delta), (u16 *) oldo,
1393 				     c->vc_screenbuf_size - delta);
1394 			c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1395 			vga_rolled_over = 0;
1396 		} else
1397 			c->vc_origin -= delta;
1398 		c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1399 		scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1400 			    delta);
1401 	}
1402 	c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1403 	c->vc_visible_origin = c->vc_origin;
1404 	vga_set_mem_top(c);
1405 	c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1406 	return 1;
1407 }
1408 
1409 
1410 /*
1411  *  The console `switch' structure for the VGA based console
1412  */
1413 
1414 static int vgacon_dummy(struct vc_data *c)
1415 {
1416 	return 0;
1417 }
1418 
1419 #define DUMMY (void *) vgacon_dummy
1420 
1421 const struct consw vga_con = {
1422 	.owner = THIS_MODULE,
1423 	.con_startup = vgacon_startup,
1424 	.con_init = vgacon_init,
1425 	.con_deinit = vgacon_deinit,
1426 	.con_clear = DUMMY,
1427 	.con_putc = DUMMY,
1428 	.con_putcs = DUMMY,
1429 	.con_cursor = vgacon_cursor,
1430 	.con_scroll = vgacon_scroll,
1431 	.con_bmove = DUMMY,
1432 	.con_switch = vgacon_switch,
1433 	.con_blank = vgacon_blank,
1434 	.con_font_set = vgacon_font_set,
1435 	.con_font_get = vgacon_font_get,
1436 	.con_resize = vgacon_resize,
1437 	.con_set_palette = vgacon_set_palette,
1438 	.con_scrolldelta = vgacon_scrolldelta,
1439 	.con_set_origin = vgacon_set_origin,
1440 	.con_save_screen = vgacon_save_screen,
1441 	.con_build_attr = vgacon_build_attr,
1442 	.con_invert_region = vgacon_invert_region,
1443 };
1444 EXPORT_SYMBOL(vga_con);
1445 
1446 MODULE_LICENSE("GPL");
1447