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