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