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