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