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