GNU Linux-libre 4.19.207-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 is always 1,
374          * but vgacon_init can be called more than once, and init will
375          * not be 1.
376          */
377         c->vc_can_do_color = vga_can_do_color;
378
379         /* set dimensions manually if init != 0 since vc_resize() will fail */
380         if (init) {
381                 c->vc_cols = vga_video_num_columns;
382                 c->vc_rows = vga_video_num_lines;
383         } else
384                 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
385
386         c->vc_scan_lines = vga_scan_lines;
387         c->vc_font.height = c->vc_cell_height = vga_video_font_height;
388         c->vc_complement_mask = 0x7700;
389         if (vga_512_chars)
390                 c->vc_hi_font_mask = 0x0800;
391         p = *c->vc_uni_pagedir_loc;
392         if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
393                 con_free_unimap(c);
394                 c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
395                 vgacon_refcount++;
396         }
397         if (!vgacon_uni_pagedir && p)
398                 con_set_default_unimap(c);
399
400         /* Only set the default if the user didn't deliberately override it */
401         if (global_cursor_default == -1)
402                 global_cursor_default =
403                         !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
404 }
405
406 static void vgacon_deinit(struct vc_data *c)
407 {
408         /* When closing the active console, reset video origin */
409         if (con_is_visible(c)) {
410                 c->vc_visible_origin = vga_vram_base;
411                 vga_set_mem_top(c);
412         }
413
414         if (!--vgacon_refcount)
415                 con_free_unimap(c);
416         c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
417         con_set_default_unimap(c);
418 }
419
420 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
421                             u8 blink, u8 underline, u8 reverse, u8 italic)
422 {
423         u8 attr = color;
424
425         if (vga_can_do_color) {
426                 if (italic)
427                         attr = (attr & 0xF0) | c->vc_itcolor;
428                 else if (underline)
429                         attr = (attr & 0xf0) | c->vc_ulcolor;
430                 else if (intensity == 0)
431                         attr = (attr & 0xf0) | c->vc_halfcolor;
432         }
433         if (reverse)
434                 attr =
435                     ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
436                                        0x77);
437         if (blink)
438                 attr ^= 0x80;
439         if (intensity == 2)
440                 attr ^= 0x08;
441         if (!vga_can_do_color) {
442                 if (italic)
443                         attr = (attr & 0xF8) | 0x02;
444                 else if (underline)
445                         attr = (attr & 0xf8) | 0x01;
446                 else if (intensity == 0)
447                         attr = (attr & 0xf0) | 0x08;
448         }
449         return attr;
450 }
451
452 static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
453 {
454         const bool col = vga_can_do_color;
455
456         while (count--) {
457                 u16 a = scr_readw(p);
458                 if (col)
459                         a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
460                             (((a) & 0x0700) << 4);
461                 else
462                         a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
463                 scr_writew(a, p++);
464         }
465 }
466
467 static void vgacon_set_cursor_size(int xpos, int from, int to)
468 {
469         unsigned long flags;
470         int curs, cure;
471
472         if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
473                 return;
474         cursor_size_lastfrom = from;
475         cursor_size_lastto = to;
476
477         raw_spin_lock_irqsave(&vga_lock, flags);
478         if (vga_video_type >= VIDEO_TYPE_VGAC) {
479                 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
480                 curs = inb_p(vga_video_port_val);
481                 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
482                 cure = inb_p(vga_video_port_val);
483         } else {
484                 curs = 0;
485                 cure = 0;
486         }
487
488         curs = (curs & 0xc0) | from;
489         cure = (cure & 0xe0) | to;
490
491         outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
492         outb_p(curs, vga_video_port_val);
493         outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
494         outb_p(cure, vga_video_port_val);
495         raw_spin_unlock_irqrestore(&vga_lock, flags);
496 }
497
498 static void vgacon_cursor(struct vc_data *c, int mode)
499 {
500         if (c->vc_mode != KD_TEXT)
501                 return;
502
503         vgacon_restore_screen(c);
504
505         switch (mode) {
506         case CM_ERASE:
507                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
508                 if (vga_video_type >= VIDEO_TYPE_VGAC)
509                         vgacon_set_cursor_size(c->vc_x, 31, 30);
510                 else
511                         vgacon_set_cursor_size(c->vc_x, 31, 31);
512                 break;
513
514         case CM_MOVE:
515         case CM_DRAW:
516                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
517                 switch (c->vc_cursor_type & 0x0f) {
518                 case CUR_UNDERLINE:
519                         vgacon_set_cursor_size(c->vc_x,
520                                                c->vc_cell_height -
521                                                (c->vc_cell_height <
522                                                 10 ? 2 : 3),
523                                                c->vc_cell_height -
524                                                (c->vc_cell_height <
525                                                 10 ? 1 : 2));
526                         break;
527                 case CUR_TWO_THIRDS:
528                         vgacon_set_cursor_size(c->vc_x,
529                                                c->vc_cell_height / 3,
530                                                c->vc_cell_height -
531                                                (c->vc_cell_height <
532                                                 10 ? 1 : 2));
533                         break;
534                 case CUR_LOWER_THIRD:
535                         vgacon_set_cursor_size(c->vc_x,
536                                                (c->vc_cell_height * 2) / 3,
537                                                c->vc_cell_height -
538                                                (c->vc_cell_height <
539                                                 10 ? 1 : 2));
540                         break;
541                 case CUR_LOWER_HALF:
542                         vgacon_set_cursor_size(c->vc_x,
543                                                c->vc_cell_height / 2,
544                                                c->vc_cell_height -
545                                                (c->vc_cell_height <
546                                                 10 ? 1 : 2));
547                         break;
548                 case CUR_NONE:
549                         if (vga_video_type >= VIDEO_TYPE_VGAC)
550                                 vgacon_set_cursor_size(c->vc_x, 31, 30);
551                         else
552                                 vgacon_set_cursor_size(c->vc_x, 31, 31);
553                         break;
554                 default:
555                         vgacon_set_cursor_size(c->vc_x, 1,
556                                                c->vc_cell_height);
557                         break;
558                 }
559                 break;
560         }
561 }
562
563 static int vgacon_doresize(struct vc_data *c,
564                 unsigned int width, unsigned int height)
565 {
566         unsigned long flags;
567         unsigned int scanlines = height * c->vc_cell_height;
568         u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
569
570         raw_spin_lock_irqsave(&vga_lock, flags);
571
572         vgacon_xres = width * VGA_FONTWIDTH;
573         vgacon_yres = height * c->vc_cell_height;
574         if (vga_video_type >= VIDEO_TYPE_VGAC) {
575                 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
576                 max_scan = inb_p(vga_video_port_val);
577
578                 if (max_scan & 0x80)
579                         scanlines <<= 1;
580
581                 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
582                 mode = inb_p(vga_video_port_val);
583
584                 if (mode & 0x04)
585                         scanlines >>= 1;
586
587                 scanlines -= 1;
588                 scanlines_lo = scanlines & 0xff;
589
590                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
591                 r7 = inb_p(vga_video_port_val) & ~0x42;
592
593                 if (scanlines & 0x100)
594                         r7 |= 0x02;
595                 if (scanlines & 0x200)
596                         r7 |= 0x40;
597
598                 /* deprotect registers */
599                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
600                 vsync_end = inb_p(vga_video_port_val);
601                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
602                 outb_p(vsync_end & ~0x80, vga_video_port_val);
603         }
604
605         outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
606         outb_p(width - 1, vga_video_port_val);
607         outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
608         outb_p(width >> 1, vga_video_port_val);
609
610         if (vga_video_type >= VIDEO_TYPE_VGAC) {
611                 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
612                 outb_p(scanlines_lo, vga_video_port_val);
613                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
614                 outb_p(r7,vga_video_port_val);
615
616                 /* reprotect registers */
617                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
618                 outb_p(vsync_end, vga_video_port_val);
619         }
620
621         raw_spin_unlock_irqrestore(&vga_lock, flags);
622         return 0;
623 }
624
625 static int vgacon_switch(struct vc_data *c)
626 {
627         int x = c->vc_cols * VGA_FONTWIDTH;
628         int y = c->vc_rows * c->vc_cell_height;
629         int rows = screen_info.orig_video_lines * vga_default_font_height/
630                 c->vc_cell_height;
631         /*
632          * We need to save screen size here as it's the only way
633          * we can spot the screen has been resized and we need to
634          * set size of freshly allocated screens ourselves.
635          */
636         vga_video_num_columns = c->vc_cols;
637         vga_video_num_lines = c->vc_rows;
638
639         /* We can only copy out the size of the video buffer here,
640          * otherwise we get into VGA BIOS */
641
642         if (!vga_is_gfx) {
643                 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
644                             c->vc_screenbuf_size > vga_vram_size ?
645                                 vga_vram_size : c->vc_screenbuf_size);
646
647                 if ((vgacon_xres != x || vgacon_yres != y) &&
648                     (!(vga_video_num_columns % 2) &&
649                      vga_video_num_columns <= screen_info.orig_video_cols &&
650                      vga_video_num_lines <= rows))
651                         vgacon_doresize(c, c->vc_cols, c->vc_rows);
652         }
653
654         return 0;               /* Redrawing not needed */
655 }
656
657 static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
658 {
659         int i, j;
660
661         vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
662         for (i = j = 0; i < 16; i++) {
663                 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
664                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
665                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
666                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
667         }
668 }
669
670 static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
671 {
672         if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
673             || !con_is_visible(vc))
674                 return;
675         vga_set_palette(vc, table);
676 }
677
678 /* structure holding original VGA register settings */
679 static struct {
680         unsigned char SeqCtrlIndex;     /* Sequencer Index reg.   */
681         unsigned char CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
682         unsigned char CrtMiscIO;        /* Miscellaneous register */
683         unsigned char HorizontalTotal;  /* CRT-Controller:00h */
684         unsigned char HorizDisplayEnd;  /* CRT-Controller:01h */
685         unsigned char StartHorizRetrace;        /* CRT-Controller:04h */
686         unsigned char EndHorizRetrace;  /* CRT-Controller:05h */
687         unsigned char Overflow; /* CRT-Controller:07h */
688         unsigned char StartVertRetrace; /* CRT-Controller:10h */
689         unsigned char EndVertRetrace;   /* CRT-Controller:11h */
690         unsigned char ModeControl;      /* CRT-Controller:17h */
691         unsigned char ClockingMode;     /* Seq-Controller:01h */
692 } vga_state;
693
694 static void vga_vesa_blank(struct vgastate *state, int mode)
695 {
696         /* save original values of VGA controller registers */
697         if (!vga_vesa_blanked) {
698                 raw_spin_lock_irq(&vga_lock);
699                 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
700                 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
701                 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
702                 raw_spin_unlock_irq(&vga_lock);
703
704                 outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
705                 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
706                 outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
707                 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
708                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
709                 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
710                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
711                 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
712                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
713                 vga_state.Overflow = inb_p(vga_video_port_val);
714                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
715                 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
716                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
717                 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
718                 outb_p(0x17, vga_video_port_reg);       /* ModeControl */
719                 vga_state.ModeControl = inb_p(vga_video_port_val);
720                 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
721         }
722
723         /* assure that video is enabled */
724         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
725         raw_spin_lock_irq(&vga_lock);
726         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
727
728         /* test for vertical retrace in process.... */
729         if ((vga_state.CrtMiscIO & 0x80) == 0x80)
730                 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
731
732         /*
733          * Set <End of vertical retrace> to minimum (0) and
734          * <Start of vertical Retrace> to maximum (incl. overflow)
735          * Result: turn off vertical sync (VSync) pulse.
736          */
737         if (mode & VESA_VSYNC_SUSPEND) {
738                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
739                 outb_p(0xff, vga_video_port_val);       /* maximum value */
740                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
741                 outb_p(0x40, vga_video_port_val);       /* minimum (bits 0..3)  */
742                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
743                 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);  /* bits 9,10 of vert. retrace */
744         }
745
746         if (mode & VESA_HSYNC_SUSPEND) {
747                 /*
748                  * Set <End of horizontal retrace> to minimum (0) and
749                  *  <Start of horizontal Retrace> to maximum
750                  * Result: turn off horizontal sync (HSync) pulse.
751                  */
752                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
753                 outb_p(0xff, vga_video_port_val);       /* maximum */
754                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
755                 outb_p(0x00, vga_video_port_val);       /* minimum (0) */
756         }
757
758         /* restore both index registers */
759         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
760         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
761         raw_spin_unlock_irq(&vga_lock);
762 }
763
764 static void vga_vesa_unblank(struct vgastate *state)
765 {
766         /* restore original values of VGA controller registers */
767         raw_spin_lock_irq(&vga_lock);
768         vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
769
770         outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
771         outb_p(vga_state.HorizontalTotal, vga_video_port_val);
772         outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
773         outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
774         outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
775         outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
776         outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
777         outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
778         outb_p(0x07, vga_video_port_reg);       /* Overflow */
779         outb_p(vga_state.Overflow, vga_video_port_val);
780         outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
781         outb_p(vga_state.StartVertRetrace, vga_video_port_val);
782         outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
783         outb_p(vga_state.EndVertRetrace, vga_video_port_val);
784         outb_p(0x17, vga_video_port_reg);       /* ModeControl */
785         outb_p(vga_state.ModeControl, vga_video_port_val);
786         /* ClockingMode */
787         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
788
789         /* restore index/control registers */
790         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
791         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
792         raw_spin_unlock_irq(&vga_lock);
793 }
794
795 static void vga_pal_blank(struct vgastate *state)
796 {
797         int i;
798
799         vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
800         for (i = 0; i < 16; i++) {
801                 vga_w(state->vgabase, VGA_PEL_IW, i);
802                 vga_w(state->vgabase, VGA_PEL_D, 0);
803                 vga_w(state->vgabase, VGA_PEL_D, 0);
804                 vga_w(state->vgabase, VGA_PEL_D, 0);
805         }
806 }
807
808 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
809 {
810         switch (blank) {
811         case 0:         /* Unblank */
812                 if (vga_vesa_blanked) {
813                         vga_vesa_unblank(&vgastate);
814                         vga_vesa_blanked = 0;
815                 }
816                 if (vga_palette_blanked) {
817                         vga_set_palette(c, color_table);
818                         vga_palette_blanked = false;
819                         return 0;
820                 }
821                 vga_is_gfx = false;
822                 /* Tell console.c that it has to restore the screen itself */
823                 return 1;
824         case 1:         /* Normal blanking */
825         case -1:        /* Obsolete */
826                 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
827                         vga_pal_blank(&vgastate);
828                         vga_palette_blanked = true;
829                         return 0;
830                 }
831                 vgacon_set_origin(c);
832                 scr_memsetw((void *) vga_vram_base, BLANK,
833                             c->vc_screenbuf_size);
834                 if (mode_switch)
835                         vga_is_gfx = true;
836                 return 1;
837         default:                /* VESA blanking */
838                 if (vga_video_type == VIDEO_TYPE_VGAC) {
839                         vga_vesa_blank(&vgastate, blank - 1);
840                         vga_vesa_blanked = blank;
841                 }
842                 return 0;
843         }
844 }
845
846 /*
847  * PIO_FONT support.
848  *
849  * The font loading code goes back to the codepage package by
850  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
851  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
852  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
853  *
854  * Change for certain monochrome monitors by Yury Shevchuck
855  * (sizif@botik.yaroslavl.su).
856  */
857
858 #define colourmap 0xa0000
859 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
860    should use 0xA0000 for the bwmap as well.. */
861 #define blackwmap 0xa0000
862 #define cmapsz 8192
863
864 static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
865                 bool ch512)
866 {
867         unsigned short video_port_status = vga_video_port_reg + 6;
868         int font_select = 0x00, beg, i;
869         char *charmap;
870         bool clear_attribs = false;
871         if (vga_video_type != VIDEO_TYPE_EGAM) {
872                 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
873                 beg = 0x0e;
874         } else {
875                 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
876                 beg = 0x0a;
877         }
878
879 #ifdef BROKEN_GRAPHICS_PROGRAMS
880         /*
881          * All fonts are loaded in slot 0 (0:1 for 512 ch)
882          */
883
884         if (!arg)
885                 return -EINVAL; /* Return to default font not supported */
886
887         vga_font_is_default = false;
888         font_select = ch512 ? 0x04 : 0x00;
889 #else
890         /*
891          * The default font is kept in slot 0 and is never touched.
892          * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
893          */
894
895         if (set) {
896                 vga_font_is_default = !arg;
897                 if (!arg)
898                         ch512 = false;  /* Default font is always 256 */
899                 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
900         }
901
902         if (!vga_font_is_default)
903                 charmap += 4 * cmapsz;
904 #endif
905
906         raw_spin_lock_irq(&vga_lock);
907         /* First, the Sequencer */
908         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
909         /* CPU writes only to map 2 */
910         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);    
911         /* Sequential addressing */
912         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);    
913         /* Clear synchronous reset */
914         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
915
916         /* Now, the graphics controller, select map 2 */
917         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);             
918         /* disable odd-even addressing */
919         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
920         /* map start at A000:0000 */
921         vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
922         raw_spin_unlock_irq(&vga_lock);
923
924         if (arg) {
925                 if (set)
926                         for (i = 0; i < cmapsz; i++) {
927                                 vga_writeb(arg[i], charmap + i);
928                                 cond_resched();
929                         }
930                 else
931                         for (i = 0; i < cmapsz; i++) {
932                                 arg[i] = vga_readb(charmap + i);
933                                 cond_resched();
934                         }
935
936                 /*
937                  * In 512-character mode, the character map is not contiguous if
938                  * we want to remain EGA compatible -- which we do
939                  */
940
941                 if (ch512) {
942                         charmap += 2 * cmapsz;
943                         arg += cmapsz;
944                         if (set)
945                                 for (i = 0; i < cmapsz; i++) {
946                                         vga_writeb(arg[i], charmap + i);
947                                         cond_resched();
948                                 }
949                         else
950                                 for (i = 0; i < cmapsz; i++) {
951                                         arg[i] = vga_readb(charmap + i);
952                                         cond_resched();
953                                 }
954                 }
955         }
956
957         raw_spin_lock_irq(&vga_lock);
958         /* First, the sequencer, Synchronous reset */
959         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);  
960         /* CPU writes to maps 0 and 1 */
961         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
962         /* odd-even addressing */
963         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
964         /* Character Map Select */
965         if (set)
966                 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
967         /* clear synchronous reset */
968         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
969
970         /* Now, the graphics controller, select map 0 for CPU */
971         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
972         /* enable even-odd addressing */
973         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
974         /* map starts at b800:0 or b000:0 */
975         vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
976
977         /* if 512 char mode is already enabled don't re-enable it. */
978         if ((set) && (ch512 != vga_512_chars)) {
979                 vga_512_chars = ch512;
980                 /* 256-char: enable intensity bit
981                    512-char: disable intensity bit */
982                 inb_p(video_port_status);       /* clear address flip-flop */
983                 /* color plane enable register */
984                 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
985                 /* Wilton (1987) mentions the following; I don't know what
986                    it means, but it works, and it appears necessary */
987                 inb_p(video_port_status);
988                 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);    
989                 clear_attribs = true;
990         }
991         raw_spin_unlock_irq(&vga_lock);
992
993         if (clear_attribs) {
994                 for (i = 0; i < MAX_NR_CONSOLES; i++) {
995                         struct vc_data *c = vc_cons[i].d;
996                         if (c && c->vc_sw == &vga_con) {
997                                 /* force hi font mask to 0, so we always clear
998                                    the bit on either transition */
999                                 c->vc_hi_font_mask = 0x00;
1000                                 clear_buffer_attributes(c);
1001                                 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1002                         }
1003                 }
1004         }
1005         return 0;
1006 }
1007
1008 /*
1009  * Adjust the screen to fit a font of a certain height
1010  */
1011 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
1012 {
1013         unsigned char ovr, vde, fsr;
1014         int rows, maxscan, i;
1015
1016         rows = vc->vc_scan_lines / fontheight;  /* Number of video rows we end up with */
1017         maxscan = rows * fontheight - 1;        /* Scan lines to actually display-1 */
1018
1019         /* Reprogram the CRTC for the new font size
1020            Note: the attempt to read the overflow register will fail
1021            on an EGA, but using 0xff for the previous value appears to
1022            be OK for EGA text modes in the range 257-512 scan lines, so I
1023            guess we don't need to worry about it.
1024
1025            The same applies for the spill bits in the font size and cursor
1026            registers; they are write-only on EGA, but it appears that they
1027            are all don't care bits on EGA, so I guess it doesn't matter. */
1028
1029         raw_spin_lock_irq(&vga_lock);
1030         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
1031         ovr = inb_p(vga_video_port_val);
1032         outb_p(0x09, vga_video_port_reg);       /* Font size register */
1033         fsr = inb_p(vga_video_port_val);
1034         raw_spin_unlock_irq(&vga_lock);
1035
1036         vde = maxscan & 0xff;   /* Vertical display end reg */
1037         ovr = (ovr & 0xbd) +    /* Overflow register */
1038             ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1039         fsr = (fsr & 0xe0) + (fontheight - 1);  /*  Font size register */
1040
1041         raw_spin_lock_irq(&vga_lock);
1042         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
1043         outb_p(ovr, vga_video_port_val);
1044         outb_p(0x09, vga_video_port_reg);       /* Font size */
1045         outb_p(fsr, vga_video_port_val);
1046         outb_p(0x12, vga_video_port_reg);       /* Vertical display limit */
1047         outb_p(vde, vga_video_port_val);
1048         raw_spin_unlock_irq(&vga_lock);
1049         vga_video_font_height = fontheight;
1050
1051         for (i = 0; i < MAX_NR_CONSOLES; i++) {
1052                 struct vc_data *c = vc_cons[i].d;
1053
1054                 if (c && c->vc_sw == &vga_con) {
1055                         if (con_is_visible(c)) {
1056                                 /* void size to cause regs to be rewritten */
1057                                 cursor_size_lastfrom = 0;
1058                                 cursor_size_lastto = 0;
1059                                 c->vc_sw->con_cursor(c, CM_DRAW);
1060                         }
1061                         c->vc_font.height = c->vc_cell_height = fontheight;
1062                         vc_resize(c, 0, rows);  /* Adjust console size */
1063                 }
1064         }
1065         return 0;
1066 }
1067
1068 static int vgacon_font_set(struct vc_data *c, struct console_font *font,
1069                            unsigned int flags)
1070 {
1071         unsigned charcount = font->charcount;
1072         int rc;
1073
1074         if (vga_video_type < VIDEO_TYPE_EGAM)
1075                 return -EINVAL;
1076
1077         if (font->width != VGA_FONTWIDTH ||
1078             (charcount != 256 && charcount != 512))
1079                 return -EINVAL;
1080
1081         rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1082         if (rc)
1083                 return rc;
1084
1085         if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1086                 rc = vgacon_adjust_height(c, font->height);
1087         return rc;
1088 }
1089
1090 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1091 {
1092         if (vga_video_type < VIDEO_TYPE_EGAM)
1093                 return -EINVAL;
1094
1095         font->width = VGA_FONTWIDTH;
1096         font->height = c->vc_font.height;
1097         font->charcount = vga_512_chars ? 512 : 256;
1098         if (!font->data)
1099                 return 0;
1100         return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1101 }
1102
1103 static int vgacon_resize(struct vc_data *c, unsigned int width,
1104                          unsigned int height, unsigned int user)
1105 {
1106         if ((width << 1) * height > vga_vram_size)
1107                 return -EINVAL;
1108
1109         if (user) {
1110                 /*
1111                  * Ho ho!  Someone (svgatextmode, eh?) may have reprogrammed
1112                  * the video mode!  Set the new defaults then and go away.
1113                  */
1114                 screen_info.orig_video_cols = width;
1115                 screen_info.orig_video_lines = height;
1116                 vga_default_font_height = c->vc_cell_height;
1117                 return 0;
1118         }
1119         if (width % 2 || width > screen_info.orig_video_cols ||
1120             height > (screen_info.orig_video_lines * vga_default_font_height)/
1121             c->vc_cell_height)
1122                 return -EINVAL;
1123
1124         if (con_is_visible(c) && !vga_is_gfx) /* who knows */
1125                 vgacon_doresize(c, width, height);
1126         return 0;
1127 }
1128
1129 static int vgacon_set_origin(struct vc_data *c)
1130 {
1131         if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
1132             (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
1133                 return 0;
1134         c->vc_origin = c->vc_visible_origin = vga_vram_base;
1135         vga_set_mem_top(c);
1136         vga_rolled_over = 0;
1137         return 1;
1138 }
1139
1140 static void vgacon_save_screen(struct vc_data *c)
1141 {
1142         static int vga_bootup_console = 0;
1143
1144         if (!vga_bootup_console) {
1145                 /* This is a gross hack, but here is the only place we can
1146                  * set bootup console parameters without messing up generic
1147                  * console initialization routines.
1148                  */
1149                 vga_bootup_console = 1;
1150                 c->vc_x = screen_info.orig_x;
1151                 c->vc_y = screen_info.orig_y;
1152         }
1153
1154         /* We can't copy in more than the size of the video buffer,
1155          * or we'll be copying in VGA BIOS */
1156
1157         if (!vga_is_gfx)
1158                 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1159                             c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1160 }
1161
1162 static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
1163                 enum con_scroll dir, unsigned int lines)
1164 {
1165         unsigned long oldo;
1166         unsigned int delta;
1167
1168         if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1169                 return false;
1170
1171         if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1172                 return false;
1173
1174         vgacon_restore_screen(c);
1175         oldo = c->vc_origin;
1176         delta = lines * c->vc_size_row;
1177         if (dir == SM_UP) {
1178                 if (c->vc_scr_end + delta >= vga_vram_end) {
1179                         scr_memcpyw((u16 *) vga_vram_base,
1180                                     (u16 *) (oldo + delta),
1181                                     c->vc_screenbuf_size - delta);
1182                         c->vc_origin = vga_vram_base;
1183                         vga_rolled_over = oldo - vga_vram_base;
1184                 } else
1185                         c->vc_origin += delta;
1186                 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1187                                      delta), c->vc_video_erase_char,
1188                             delta);
1189         } else {
1190                 if (oldo - delta < vga_vram_base) {
1191                         scr_memmovew((u16 *) (vga_vram_end -
1192                                               c->vc_screenbuf_size +
1193                                               delta), (u16 *) oldo,
1194                                      c->vc_screenbuf_size - delta);
1195                         c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1196                         vga_rolled_over = 0;
1197                 } else
1198                         c->vc_origin -= delta;
1199                 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1200                 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1201                             delta);
1202         }
1203         c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1204         c->vc_visible_origin = c->vc_origin;
1205         vga_set_mem_top(c);
1206         c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1207         return true;
1208 }
1209
1210 /*
1211  *  The console `switch' structure for the VGA based console
1212  */
1213
1214 static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
1215                          int width) { }
1216 static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
1217 static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
1218                          int count, int ypos, int xpos) { }
1219
1220 const struct consw vga_con = {
1221         .owner = THIS_MODULE,
1222         .con_startup = vgacon_startup,
1223         .con_init = vgacon_init,
1224         .con_deinit = vgacon_deinit,
1225         .con_clear = vgacon_clear,
1226         .con_putc = vgacon_putc,
1227         .con_putcs = vgacon_putcs,
1228         .con_cursor = vgacon_cursor,
1229         .con_scroll = vgacon_scroll,
1230         .con_switch = vgacon_switch,
1231         .con_blank = vgacon_blank,
1232         .con_font_set = vgacon_font_set,
1233         .con_font_get = vgacon_font_get,
1234         .con_resize = vgacon_resize,
1235         .con_set_palette = vgacon_set_palette,
1236         .con_scrolldelta = vgacon_scrolldelta,
1237         .con_set_origin = vgacon_set_origin,
1238         .con_save_screen = vgacon_save_screen,
1239         .con_build_attr = vgacon_build_attr,
1240         .con_invert_region = vgacon_invert_region,
1241 };
1242 EXPORT_SYMBOL(vga_con);
1243
1244 MODULE_LICENSE("GPL");