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