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