Merge 6.8-rc6 into tty-next
[linux-2.6-microblaze.git] / drivers / video / console / vgacon.c
1 /*
2  *  linux/drivers/video/vgacon.c -- Low level VGA based console driver
3  *
4  *      Created 28 Sep 1997 by Geert Uytterhoeven
5  *
6  *      Rewritten by Martin Mares <mj@ucw.cz>, July 1998
7  *
8  *  This file is based on the old console.c, vga.c and vesa_blank.c drivers.
9  *
10  *      Copyright (C) 1991, 1992  Linus Torvalds
11  *                          1995  Jay Estabrook
12  *
13  *      User definable mapping table and font loading by Eugene G. Crosser,
14  *      <crosser@average.org>
15  *
16  *      Improved loadable font/UTF-8 support by H. Peter Anvin
17  *      Feb-Sep 1995 <peter.anvin@linux.org>
18  *
19  *      Colour palette handling, by Simon Tatham
20  *      17-Jun-95 <sgt20@cam.ac.uk>
21  *
22  *      if 512 char mode is already enabled don't re-enable it,
23  *      because it causes screen to flicker, by Mitja Horvat
24  *      5-May-96 <mitja.horvat@guest.arnes.si>
25  *
26  *      Use 2 outw instead of 4 outb_p to reduce erroneous text
27  *      flashing on RHS of screen during heavy console scrolling .
28  *      Oct 1996, Paul Gortmaker.
29  *
30  *
31  *  This file is subject to the terms and conditions of the GNU General Public
32  *  License.  See the file COPYING in the main directory of this archive for
33  *  more details.
34  */
35
36 #include <linux/module.h>
37 #include <linux/types.h>
38 #include <linux/fs.h>
39 #include <linux/kernel.h>
40 #include <linux/console.h>
41 #include <linux/string.h>
42 #include <linux/kd.h>
43 #include <linux/slab.h>
44 #include <linux/vt_kern.h>
45 #include <linux/sched.h>
46 #include <linux/selection.h>
47 #include <linux/spinlock.h>
48 #include <linux/ioport.h>
49 #include <linux/init.h>
50 #include <linux/screen_info.h>
51 #include <video/vga.h>
52 #include <asm/io.h>
53
54 static DEFINE_RAW_SPINLOCK(vga_lock);
55 static int cursor_size_lastfrom;
56 static int cursor_size_lastto;
57 static u32 vgacon_xres;
58 static u32 vgacon_yres;
59 static struct vgastate vgastate;
60
61 #define BLANK 0x0020
62
63 #define VGA_FONTWIDTH       8   /* VGA does not support fontwidths != 8 */
64 /*
65  *  Interface used by the world
66  */
67
68 static bool 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 enum vesa_blank_mode 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, bool enable)
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         write_vga(14, (c->vc_pos - vga_vram_base) / 2);
518
519         if (!enable) {
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                 return;
525         }
526
527         switch (CUR_SIZE(c->vc_cursor_type)) {
528         case CUR_UNDERLINE:
529                 vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3),
530                                        c_height - (c_height < 10 ? 1 : 2));
531                 break;
532         case CUR_TWO_THIRDS:
533                 vgacon_set_cursor_size(c_height / 3,
534                                        c_height - (c_height < 10 ? 1 : 2));
535                 break;
536         case CUR_LOWER_THIRD:
537                 vgacon_set_cursor_size(c_height * 2 / 3,
538                                        c_height - (c_height < 10 ? 1 : 2));
539                 break;
540         case CUR_LOWER_HALF:
541                 vgacon_set_cursor_size(c_height / 2,
542                                        c_height - (c_height < 10 ? 1 : 2));
543                 break;
544         case CUR_NONE:
545                 if (vga_video_type >= VIDEO_TYPE_VGAC)
546                         vgacon_set_cursor_size(31, 30);
547                 else
548                         vgacon_set_cursor_size(31, 31);
549                 break;
550         default:
551                 vgacon_set_cursor_size(1, c_height);
552                 break;
553         }
554 }
555
556 static void vgacon_doresize(struct vc_data *c,
557                 unsigned int width, unsigned int height)
558 {
559         unsigned long flags;
560         unsigned int scanlines = height * c->vc_cell_height;
561         u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
562
563         raw_spin_lock_irqsave(&vga_lock, flags);
564
565         vgacon_xres = width * VGA_FONTWIDTH;
566         vgacon_yres = height * c->vc_cell_height;
567         if (vga_video_type >= VIDEO_TYPE_VGAC) {
568                 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
569                 max_scan = inb_p(vga_video_port_val);
570
571                 if (max_scan & 0x80)
572                         scanlines <<= 1;
573
574                 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
575                 mode = inb_p(vga_video_port_val);
576
577                 if (mode & 0x04)
578                         scanlines >>= 1;
579
580                 scanlines -= 1;
581                 scanlines_lo = scanlines & 0xff;
582
583                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
584                 r7 = inb_p(vga_video_port_val) & ~0x42;
585
586                 if (scanlines & 0x100)
587                         r7 |= 0x02;
588                 if (scanlines & 0x200)
589                         r7 |= 0x40;
590
591                 /* deprotect registers */
592                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
593                 vsync_end = inb_p(vga_video_port_val);
594                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
595                 outb_p(vsync_end & ~0x80, vga_video_port_val);
596         }
597
598         outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
599         outb_p(width - 1, vga_video_port_val);
600         outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
601         outb_p(width >> 1, vga_video_port_val);
602
603         if (vga_video_type >= VIDEO_TYPE_VGAC) {
604                 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
605                 outb_p(scanlines_lo, vga_video_port_val);
606                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
607                 outb_p(r7,vga_video_port_val);
608
609                 /* reprotect registers */
610                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
611                 outb_p(vsync_end, vga_video_port_val);
612         }
613
614         raw_spin_unlock_irqrestore(&vga_lock, flags);
615 }
616
617 static bool vgacon_switch(struct vc_data *c)
618 {
619         int x = c->vc_cols * VGA_FONTWIDTH;
620         int y = c->vc_rows * c->vc_cell_height;
621         int rows = vga_si->orig_video_lines * vga_default_font_height/
622                 c->vc_cell_height;
623         /*
624          * We need to save screen size here as it's the only way
625          * we can spot the screen has been resized and we need to
626          * set size of freshly allocated screens ourselves.
627          */
628         vga_video_num_columns = c->vc_cols;
629         vga_video_num_lines = c->vc_rows;
630
631         /* We can only copy out the size of the video buffer here,
632          * otherwise we get into VGA BIOS */
633
634         if (!vga_is_gfx) {
635                 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
636                             c->vc_screenbuf_size > vga_vram_size ?
637                                 vga_vram_size : c->vc_screenbuf_size);
638
639                 if ((vgacon_xres != x || vgacon_yres != y) &&
640                     (!(vga_video_num_columns % 2) &&
641                      vga_video_num_columns <= vga_si->orig_video_cols &&
642                      vga_video_num_lines <= rows))
643                         vgacon_doresize(c, c->vc_cols, c->vc_rows);
644         }
645
646         return false;           /* Redrawing not needed */
647 }
648
649 static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
650 {
651         int i, j;
652
653         vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
654         for (i = j = 0; i < 16; i++) {
655                 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
656                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
657                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
658                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
659         }
660 }
661
662 static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
663 {
664         if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
665             || !con_is_visible(vc))
666                 return;
667         vga_set_palette(vc, table);
668 }
669
670 /* structure holding original VGA register settings */
671 static struct {
672         unsigned char SeqCtrlIndex;     /* Sequencer Index reg.   */
673         unsigned char CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
674         unsigned char CrtMiscIO;        /* Miscellaneous register */
675         unsigned char HorizontalTotal;  /* CRT-Controller:00h */
676         unsigned char HorizDisplayEnd;  /* CRT-Controller:01h */
677         unsigned char StartHorizRetrace;        /* CRT-Controller:04h */
678         unsigned char EndHorizRetrace;  /* CRT-Controller:05h */
679         unsigned char Overflow; /* CRT-Controller:07h */
680         unsigned char StartVertRetrace; /* CRT-Controller:10h */
681         unsigned char EndVertRetrace;   /* CRT-Controller:11h */
682         unsigned char ModeControl;      /* CRT-Controller:17h */
683         unsigned char ClockingMode;     /* Seq-Controller:01h */
684 } vga_state;
685
686 static void vga_vesa_blank(struct vgastate *state, enum vesa_blank_mode mode)
687 {
688         /* save original values of VGA controller registers */
689         if (!vga_vesa_blanked) {
690                 raw_spin_lock_irq(&vga_lock);
691                 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
692                 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
693                 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
694                 raw_spin_unlock_irq(&vga_lock);
695
696                 outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
697                 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
698                 outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
699                 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
700                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
701                 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
702                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
703                 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
704                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
705                 vga_state.Overflow = inb_p(vga_video_port_val);
706                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
707                 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
708                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
709                 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
710                 outb_p(0x17, vga_video_port_reg);       /* ModeControl */
711                 vga_state.ModeControl = inb_p(vga_video_port_val);
712                 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
713         }
714
715         /* assure that video is enabled */
716         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
717         raw_spin_lock_irq(&vga_lock);
718         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
719
720         /* test for vertical retrace in process.... */
721         if ((vga_state.CrtMiscIO & 0x80) == 0x80)
722                 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
723
724         /*
725          * Set <End of vertical retrace> to minimum (0) and
726          * <Start of vertical Retrace> to maximum (incl. overflow)
727          * Result: turn off vertical sync (VSync) pulse.
728          */
729         if (mode & VESA_VSYNC_SUSPEND) {
730                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
731                 outb_p(0xff, vga_video_port_val);       /* maximum value */
732                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
733                 outb_p(0x40, vga_video_port_val);       /* minimum (bits 0..3)  */
734                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
735                 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);  /* bits 9,10 of vert. retrace */
736         }
737
738         if (mode & VESA_HSYNC_SUSPEND) {
739                 /*
740                  * Set <End of horizontal retrace> to minimum (0) and
741                  *  <Start of horizontal Retrace> to maximum
742                  * Result: turn off horizontal sync (HSync) pulse.
743                  */
744                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
745                 outb_p(0xff, vga_video_port_val);       /* maximum */
746                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
747                 outb_p(0x00, vga_video_port_val);       /* minimum (0) */
748         }
749
750         /* restore both index registers */
751         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
752         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
753         raw_spin_unlock_irq(&vga_lock);
754 }
755
756 static void vga_vesa_unblank(struct vgastate *state)
757 {
758         /* restore original values of VGA controller registers */
759         raw_spin_lock_irq(&vga_lock);
760         vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
761
762         outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
763         outb_p(vga_state.HorizontalTotal, vga_video_port_val);
764         outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
765         outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
766         outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
767         outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
768         outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
769         outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
770         outb_p(0x07, vga_video_port_reg);       /* Overflow */
771         outb_p(vga_state.Overflow, vga_video_port_val);
772         outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
773         outb_p(vga_state.StartVertRetrace, vga_video_port_val);
774         outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
775         outb_p(vga_state.EndVertRetrace, vga_video_port_val);
776         outb_p(0x17, vga_video_port_reg);       /* ModeControl */
777         outb_p(vga_state.ModeControl, vga_video_port_val);
778         /* ClockingMode */
779         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
780
781         /* restore index/control registers */
782         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
783         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
784         raw_spin_unlock_irq(&vga_lock);
785 }
786
787 static void vga_pal_blank(struct vgastate *state)
788 {
789         int i;
790
791         vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
792         for (i = 0; i < 16; i++) {
793                 vga_w(state->vgabase, VGA_PEL_IW, i);
794                 vga_w(state->vgabase, VGA_PEL_D, 0);
795                 vga_w(state->vgabase, VGA_PEL_D, 0);
796                 vga_w(state->vgabase, VGA_PEL_D, 0);
797         }
798 }
799
800 static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
801                          bool mode_switch)
802 {
803         switch (blank) {
804         case VESA_NO_BLANKING:          /* Unblank */
805                 if (vga_vesa_blanked) {
806                         vga_vesa_unblank(&vgastate);
807                         vga_vesa_blanked = VESA_NO_BLANKING;
808                 }
809                 if (vga_palette_blanked) {
810                         vga_set_palette(c, color_table);
811                         vga_palette_blanked = false;
812                         return 0;
813                 }
814                 vga_is_gfx = false;
815                 /* Tell console.c that it has to restore the screen itself */
816                 return 1;
817         case VESA_VSYNC_SUSPEND:        /* Normal blanking */
818                 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
819                         vga_pal_blank(&vgastate);
820                         vga_palette_blanked = true;
821                         return 0;
822                 }
823                 vgacon_set_origin(c);
824                 scr_memsetw((void *) vga_vram_base, BLANK,
825                             c->vc_screenbuf_size);
826                 if (mode_switch)
827                         vga_is_gfx = true;
828                 return 1;
829         default:                /* VESA blanking */
830                 if (vga_video_type == VIDEO_TYPE_VGAC) {
831                         vga_vesa_blank(&vgastate, blank - 1);
832                         vga_vesa_blanked = blank;
833                 }
834                 return 0;
835         }
836 }
837
838 /*
839  * PIO_FONT support.
840  *
841  * The font loading code goes back to the codepage package by
842  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
843  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
844  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
845  *
846  * Change for certain monochrome monitors by Yury Shevchuck
847  * (sizif@botik.yaroslavl.su).
848  */
849
850 #define colourmap 0xa0000
851 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
852    should use 0xA0000 for the bwmap as well.. */
853 #define blackwmap 0xa0000
854 #define cmapsz 8192
855
856 static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
857                 bool ch512)
858 {
859         unsigned short video_port_status = vga_video_port_reg + 6;
860         int font_select = 0x00, beg, i;
861         char *charmap;
862         bool clear_attribs = false;
863         if (vga_video_type != VIDEO_TYPE_EGAM) {
864                 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
865                 beg = 0x0e;
866         } else {
867                 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
868                 beg = 0x0a;
869         }
870
871         /*
872          * All fonts are loaded in slot 0 (0:1 for 512 ch)
873          */
874
875         if (!arg)
876                 return -EINVAL; /* Return to default font not supported */
877
878         font_select = ch512 ? 0x04 : 0x00;
879
880         raw_spin_lock_irq(&vga_lock);
881         /* First, the Sequencer */
882         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
883         /* CPU writes only to map 2 */
884         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);    
885         /* Sequential addressing */
886         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);    
887         /* Clear synchronous reset */
888         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
889
890         /* Now, the graphics controller, select map 2 */
891         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);             
892         /* disable odd-even addressing */
893         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
894         /* map start at A000:0000 */
895         vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
896         raw_spin_unlock_irq(&vga_lock);
897
898         if (arg) {
899                 if (set)
900                         for (i = 0; i < cmapsz; i++) {
901                                 vga_writeb(arg[i], charmap + i);
902                                 cond_resched();
903                         }
904                 else
905                         for (i = 0; i < cmapsz; i++) {
906                                 arg[i] = vga_readb(charmap + i);
907                                 cond_resched();
908                         }
909
910                 /*
911                  * In 512-character mode, the character map is not contiguous if
912                  * we want to remain EGA compatible -- which we do
913                  */
914
915                 if (ch512) {
916                         charmap += 2 * cmapsz;
917                         arg += cmapsz;
918                         if (set)
919                                 for (i = 0; i < cmapsz; i++) {
920                                         vga_writeb(arg[i], charmap + i);
921                                         cond_resched();
922                                 }
923                         else
924                                 for (i = 0; i < cmapsz; i++) {
925                                         arg[i] = vga_readb(charmap + i);
926                                         cond_resched();
927                                 }
928                 }
929         }
930
931         raw_spin_lock_irq(&vga_lock);
932         /* First, the sequencer, Synchronous reset */
933         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);  
934         /* CPU writes to maps 0 and 1 */
935         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
936         /* odd-even addressing */
937         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
938         /* Character Map Select */
939         if (set)
940                 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
941         /* clear synchronous reset */
942         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
943
944         /* Now, the graphics controller, select map 0 for CPU */
945         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
946         /* enable even-odd addressing */
947         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
948         /* map starts at b800:0 or b000:0 */
949         vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
950
951         /* if 512 char mode is already enabled don't re-enable it. */
952         if ((set) && (ch512 != vga_512_chars)) {
953                 vga_512_chars = ch512;
954                 /* 256-char: enable intensity bit
955                    512-char: disable intensity bit */
956                 inb_p(video_port_status);       /* clear address flip-flop */
957                 /* color plane enable register */
958                 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
959                 /* Wilton (1987) mentions the following; I don't know what
960                    it means, but it works, and it appears necessary */
961                 inb_p(video_port_status);
962                 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);    
963                 clear_attribs = true;
964         }
965         raw_spin_unlock_irq(&vga_lock);
966
967         if (clear_attribs) {
968                 for (i = 0; i < MAX_NR_CONSOLES; i++) {
969                         struct vc_data *c = vc_cons[i].d;
970                         if (c && c->vc_sw == &vga_con) {
971                                 /* force hi font mask to 0, so we always clear
972                                    the bit on either transition */
973                                 c->vc_hi_font_mask = 0x00;
974                                 clear_buffer_attributes(c);
975                                 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
976                         }
977                 }
978         }
979         return 0;
980 }
981
982 /*
983  * Adjust the screen to fit a font of a certain height
984  */
985 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
986 {
987         unsigned char ovr, vde, fsr;
988         int rows, maxscan, i;
989
990         rows = vc->vc_scan_lines / fontheight;  /* Number of video rows we end up with */
991         maxscan = rows * fontheight - 1;        /* Scan lines to actually display-1 */
992
993         /* Reprogram the CRTC for the new font size
994            Note: the attempt to read the overflow register will fail
995            on an EGA, but using 0xff for the previous value appears to
996            be OK for EGA text modes in the range 257-512 scan lines, so I
997            guess we don't need to worry about it.
998
999            The same applies for the spill bits in the font size and cursor
1000            registers; they are write-only on EGA, but it appears that they
1001            are all don't care bits on EGA, so I guess it doesn't matter. */
1002
1003         raw_spin_lock_irq(&vga_lock);
1004         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
1005         ovr = inb_p(vga_video_port_val);
1006         outb_p(0x09, vga_video_port_reg);       /* Font size register */
1007         fsr = inb_p(vga_video_port_val);
1008         raw_spin_unlock_irq(&vga_lock);
1009
1010         vde = maxscan & 0xff;   /* Vertical display end reg */
1011         ovr = (ovr & 0xbd) +    /* Overflow register */
1012             ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1013         fsr = (fsr & 0xe0) + (fontheight - 1);  /*  Font size register */
1014
1015         raw_spin_lock_irq(&vga_lock);
1016         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
1017         outb_p(ovr, vga_video_port_val);
1018         outb_p(0x09, vga_video_port_reg);       /* Font size */
1019         outb_p(fsr, vga_video_port_val);
1020         outb_p(0x12, vga_video_port_reg);       /* Vertical display limit */
1021         outb_p(vde, vga_video_port_val);
1022         raw_spin_unlock_irq(&vga_lock);
1023         vga_video_font_height = fontheight;
1024
1025         for (i = 0; i < MAX_NR_CONSOLES; i++) {
1026                 struct vc_data *c = vc_cons[i].d;
1027
1028                 if (c && c->vc_sw == &vga_con) {
1029                         if (con_is_visible(c)) {
1030                                 /* void size to cause regs to be rewritten */
1031                                 cursor_size_lastfrom = 0;
1032                                 cursor_size_lastto = 0;
1033                                 c->vc_sw->con_cursor(c, true);
1034                         }
1035                         c->vc_font.height = c->vc_cell_height = fontheight;
1036                         vc_resize(c, 0, rows);  /* Adjust console size */
1037                 }
1038         }
1039         return 0;
1040 }
1041
1042 static int vgacon_font_set(struct vc_data *c, const struct console_font *font,
1043                            unsigned int vpitch, unsigned int flags)
1044 {
1045         unsigned charcount = font->charcount;
1046         int rc;
1047
1048         if (vga_video_type < VIDEO_TYPE_EGAM)
1049                 return -EINVAL;
1050
1051         if (font->width != VGA_FONTWIDTH || font->height > 32 || vpitch != 32 ||
1052             (charcount != 256 && charcount != 512))
1053                 return -EINVAL;
1054
1055         rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1056         if (rc)
1057                 return rc;
1058
1059         if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1060                 rc = vgacon_adjust_height(c, font->height);
1061         return rc;
1062 }
1063
1064 static int vgacon_font_get(struct vc_data *c, struct console_font *font, unsigned int vpitch)
1065 {
1066         if (vga_video_type < VIDEO_TYPE_EGAM || vpitch != 32)
1067                 return -EINVAL;
1068
1069         font->width = VGA_FONTWIDTH;
1070         font->height = c->vc_font.height;
1071         font->charcount = vga_512_chars ? 512 : 256;
1072         if (!font->data)
1073                 return 0;
1074         return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1075 }
1076
1077 static int vgacon_resize(struct vc_data *c, unsigned int width,
1078                          unsigned int height, bool from_user)
1079 {
1080         if ((width << 1) * height > vga_vram_size)
1081                 return -EINVAL;
1082
1083         if (from_user) {
1084                 /*
1085                  * Ho ho!  Someone (svgatextmode, eh?) may have reprogrammed
1086                  * the video mode!  Set the new defaults then and go away.
1087                  */
1088                 vga_si->orig_video_cols = width;
1089                 vga_si->orig_video_lines = height;
1090                 vga_default_font_height = c->vc_cell_height;
1091                 return 0;
1092         }
1093         if (width % 2 || width > vga_si->orig_video_cols ||
1094             height > (vga_si->orig_video_lines * vga_default_font_height)/
1095             c->vc_cell_height)
1096                 return -EINVAL;
1097
1098         if (con_is_visible(c) && !vga_is_gfx) /* who knows */
1099                 vgacon_doresize(c, width, height);
1100         return 0;
1101 }
1102
1103 static bool vgacon_set_origin(struct vc_data *c)
1104 {
1105         if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
1106             (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
1107                 return false;
1108         c->vc_origin = c->vc_visible_origin = vga_vram_base;
1109         vga_set_mem_top(c);
1110         vga_rolled_over = 0;
1111         return true;
1112 }
1113
1114 static void vgacon_save_screen(struct vc_data *c)
1115 {
1116         static int vga_bootup_console = 0;
1117
1118         if (!vga_bootup_console) {
1119                 /* This is a gross hack, but here is the only place we can
1120                  * set bootup console parameters without messing up generic
1121                  * console initialization routines.
1122                  */
1123                 vga_bootup_console = 1;
1124                 c->state.x = vga_si->orig_x;
1125                 c->state.y = vga_si->orig_y;
1126         }
1127
1128         /* We can't copy in more than the size of the video buffer,
1129          * or we'll be copying in VGA BIOS */
1130
1131         if (!vga_is_gfx)
1132                 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1133                             c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1134 }
1135
1136 static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
1137                 enum con_scroll dir, unsigned int lines)
1138 {
1139         unsigned long oldo;
1140         unsigned int delta;
1141
1142         if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1143                 return false;
1144
1145         if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1146                 return false;
1147
1148         vgacon_restore_screen(c);
1149         oldo = c->vc_origin;
1150         delta = lines * c->vc_size_row;
1151         if (dir == SM_UP) {
1152                 if (c->vc_scr_end + delta >= vga_vram_end) {
1153                         scr_memcpyw((u16 *) vga_vram_base,
1154                                     (u16 *) (oldo + delta),
1155                                     c->vc_screenbuf_size - delta);
1156                         c->vc_origin = vga_vram_base;
1157                         vga_rolled_over = oldo - vga_vram_base;
1158                 } else
1159                         c->vc_origin += delta;
1160                 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1161                                      delta), c->vc_video_erase_char,
1162                             delta);
1163         } else {
1164                 if (oldo - delta < vga_vram_base) {
1165                         scr_memmovew((u16 *) (vga_vram_end -
1166                                               c->vc_screenbuf_size +
1167                                               delta), (u16 *) oldo,
1168                                      c->vc_screenbuf_size - delta);
1169                         c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1170                         vga_rolled_over = 0;
1171                 } else
1172                         c->vc_origin -= delta;
1173                 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1174                 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1175                             delta);
1176         }
1177         c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1178         c->vc_visible_origin = c->vc_origin;
1179         vga_set_mem_top(c);
1180         c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1181         return true;
1182 }
1183
1184 /*
1185  *  The console `switch' structure for the VGA based console
1186  */
1187
1188 static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
1189                          unsigned int width) { }
1190 static void vgacon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
1191                          unsigned int ypos, unsigned int xpos) { }
1192
1193 const struct consw vga_con = {
1194         .owner = THIS_MODULE,
1195         .con_startup = vgacon_startup,
1196         .con_init = vgacon_init,
1197         .con_deinit = vgacon_deinit,
1198         .con_clear = vgacon_clear,
1199         .con_putcs = vgacon_putcs,
1200         .con_cursor = vgacon_cursor,
1201         .con_scroll = vgacon_scroll,
1202         .con_switch = vgacon_switch,
1203         .con_blank = vgacon_blank,
1204         .con_font_set = vgacon_font_set,
1205         .con_font_get = vgacon_font_get,
1206         .con_resize = vgacon_resize,
1207         .con_set_palette = vgacon_set_palette,
1208         .con_scrolldelta = vgacon_scrolldelta,
1209         .con_set_origin = vgacon_set_origin,
1210         .con_save_screen = vgacon_save_screen,
1211         .con_build_attr = vgacon_build_attr,
1212         .con_invert_region = vgacon_invert_region,
1213 };
1214 EXPORT_SYMBOL(vga_con);
1215
1216 void vgacon_register_screen(struct screen_info *si)
1217 {
1218         if (!si || vga_si)
1219                 return;
1220
1221         conswitchp = &vga_con;
1222         vga_si = si;
1223 }
1224
1225 MODULE_LICENSE("GPL");