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