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