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