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