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