[PATCH] vgacon: fix EGA cursor resize function
[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         if (vga_video_type >= VIDEO_TYPE_VGAC) {
437                 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
438                 curs = inb_p(vga_video_port_val);
439                 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
440                 cure = inb_p(vga_video_port_val);
441         } else {
442                 curs = 0;
443                 cure = 0;
444         }
445
446         curs = (curs & 0xc0) | from;
447         cure = (cure & 0xe0) | to;
448
449         outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
450         outb_p(curs, vga_video_port_val);
451         outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
452         outb_p(cure, vga_video_port_val);
453         spin_unlock_irqrestore(&vga_lock, flags);
454 }
455
456 static void vgacon_cursor(struct vc_data *c, int mode)
457 {
458         if (c->vc_origin != c->vc_visible_origin)
459                 vgacon_scrolldelta(c, 0);
460         switch (mode) {
461         case CM_ERASE:
462                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
463                 if (vga_video_type >= VIDEO_TYPE_VGAC)
464                         vgacon_set_cursor_size(c->vc_x, 31, 30);
465                 else
466                         vgacon_set_cursor_size(c->vc_x, 31, 31);
467                 break;
468
469         case CM_MOVE:
470         case CM_DRAW:
471                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
472                 switch (c->vc_cursor_type & 0x0f) {
473                 case CUR_UNDERLINE:
474                         vgacon_set_cursor_size(c->vc_x,
475                                                c->vc_font.height -
476                                                (c->vc_font.height <
477                                                 10 ? 2 : 3),
478                                                c->vc_font.height -
479                                                (c->vc_font.height <
480                                                 10 ? 1 : 2));
481                         break;
482                 case CUR_TWO_THIRDS:
483                         vgacon_set_cursor_size(c->vc_x,
484                                                c->vc_font.height / 3,
485                                                c->vc_font.height -
486                                                (c->vc_font.height <
487                                                 10 ? 1 : 2));
488                         break;
489                 case CUR_LOWER_THIRD:
490                         vgacon_set_cursor_size(c->vc_x,
491                                                (c->vc_font.height * 2) / 3,
492                                                c->vc_font.height -
493                                                (c->vc_font.height <
494                                                 10 ? 1 : 2));
495                         break;
496                 case CUR_LOWER_HALF:
497                         vgacon_set_cursor_size(c->vc_x,
498                                                c->vc_font.height / 2,
499                                                c->vc_font.height -
500                                                (c->vc_font.height <
501                                                 10 ? 1 : 2));
502                         break;
503                 case CUR_NONE:
504                         if (vga_video_type >= VIDEO_TYPE_VGAC)
505                                 vgacon_set_cursor_size(c->vc_x, 31, 30);
506                         else
507                                 vgacon_set_cursor_size(c->vc_x, 31, 31);
508                         break;
509                 default:
510                         vgacon_set_cursor_size(c->vc_x, 1,
511                                                c->vc_font.height);
512                         break;
513                 }
514                 break;
515         }
516 }
517
518 static int vgacon_doresize(struct vc_data *c,
519                 unsigned int width, unsigned int height)
520 {
521         unsigned long flags;
522         unsigned int scanlines = height * c->vc_font.height;
523         u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
524
525         spin_lock_irqsave(&vga_lock, flags);
526
527         vgacon_xres = width * VGA_FONTWIDTH;
528         vgacon_yres = height * c->vc_font.height;
529         if (vga_video_type >= VIDEO_TYPE_VGAC) {
530                 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
531                 max_scan = inb_p(vga_video_port_val);
532
533                 if (max_scan & 0x80)
534                         scanlines <<= 1;
535
536                 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
537                 mode = inb_p(vga_video_port_val);
538
539                 if (mode & 0x04)
540                         scanlines >>= 1;
541
542                 scanlines -= 1;
543                 scanlines_lo = scanlines & 0xff;
544
545                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
546                 r7 = inb_p(vga_video_port_val) & ~0x42;
547
548                 if (scanlines & 0x100)
549                         r7 |= 0x02;
550                 if (scanlines & 0x200)
551                         r7 |= 0x40;
552
553                 /* deprotect registers */
554                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
555                 vsync_end = inb_p(vga_video_port_val);
556                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
557                 outb_p(vsync_end & ~0x80, vga_video_port_val);
558         }
559
560         outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
561         outb_p(width - 1, vga_video_port_val);
562         outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
563         outb_p(width >> 1, vga_video_port_val);
564
565         if (vga_video_type >= VIDEO_TYPE_VGAC) {
566                 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
567                 outb_p(scanlines_lo, vga_video_port_val);
568                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
569                 outb_p(r7,vga_video_port_val);
570
571                 /* reprotect registers */
572                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
573                 outb_p(vsync_end, vga_video_port_val);
574         }
575
576         spin_unlock_irqrestore(&vga_lock, flags);
577         return 0;
578 }
579
580 static int vgacon_switch(struct vc_data *c)
581 {
582         int x = c->vc_cols * VGA_FONTWIDTH;
583         int y = c->vc_rows * c->vc_font.height;
584         int rows = ORIG_VIDEO_LINES * vga_default_font_height/
585                 c->vc_font.height;
586         /*
587          * We need to save screen size here as it's the only way
588          * we can spot the screen has been resized and we need to
589          * set size of freshly allocated screens ourselves.
590          */
591         vga_video_num_columns = c->vc_cols;
592         vga_video_num_lines = c->vc_rows;
593
594         /* We can only copy out the size of the video buffer here,
595          * otherwise we get into VGA BIOS */
596
597         if (!vga_is_gfx) {
598                 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
599                             c->vc_screenbuf_size > vga_vram_size ?
600                                 vga_vram_size : c->vc_screenbuf_size);
601
602                 if ((vgacon_xres != x || vgacon_yres != y) &&
603                     (!(vga_video_num_columns % 2) &&
604                      vga_video_num_columns <= ORIG_VIDEO_COLS &&
605                      vga_video_num_lines <= rows))
606                         vgacon_doresize(c, c->vc_cols, c->vc_rows);
607         }
608
609         return 0;               /* Redrawing not needed */
610 }
611
612 static void vga_set_palette(struct vc_data *vc, unsigned char *table)
613 {
614         int i, j;
615
616         vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
617         for (i = j = 0; i < 16; i++) {
618                 vga_w(state.vgabase, VGA_PEL_IW, table[i]);
619                 vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
620                 vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
621                 vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
622         }
623 }
624
625 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table)
626 {
627 #ifdef CAN_LOAD_PALETTE
628         if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
629             || !CON_IS_VISIBLE(vc))
630                 return -EINVAL;
631         vga_set_palette(vc, table);
632         return 0;
633 #else
634         return -EINVAL;
635 #endif
636 }
637
638 /* structure holding original VGA register settings */
639 static struct {
640         unsigned char SeqCtrlIndex;     /* Sequencer Index reg.   */
641         unsigned char CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
642         unsigned char CrtMiscIO;        /* Miscellaneous register */
643         unsigned char HorizontalTotal;  /* CRT-Controller:00h */
644         unsigned char HorizDisplayEnd;  /* CRT-Controller:01h */
645         unsigned char StartHorizRetrace;        /* CRT-Controller:04h */
646         unsigned char EndHorizRetrace;  /* CRT-Controller:05h */
647         unsigned char Overflow; /* CRT-Controller:07h */
648         unsigned char StartVertRetrace; /* CRT-Controller:10h */
649         unsigned char EndVertRetrace;   /* CRT-Controller:11h */
650         unsigned char ModeControl;      /* CRT-Controller:17h */
651         unsigned char ClockingMode;     /* Seq-Controller:01h */
652 } vga_state;
653
654 static void vga_vesa_blank(struct vgastate *state, int mode)
655 {
656         /* save original values of VGA controller registers */
657         if (!vga_vesa_blanked) {
658                 spin_lock_irq(&vga_lock);
659                 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
660                 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
661                 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
662                 spin_unlock_irq(&vga_lock);
663
664                 outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
665                 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
666                 outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
667                 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
668                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
669                 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
670                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
671                 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
672                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
673                 vga_state.Overflow = inb_p(vga_video_port_val);
674                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
675                 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
676                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
677                 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
678                 outb_p(0x17, vga_video_port_reg);       /* ModeControl */
679                 vga_state.ModeControl = inb_p(vga_video_port_val);
680                 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
681         }
682
683         /* assure that video is enabled */
684         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
685         spin_lock_irq(&vga_lock);
686         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
687
688         /* test for vertical retrace in process.... */
689         if ((vga_state.CrtMiscIO & 0x80) == 0x80)
690                 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
691
692         /*
693          * Set <End of vertical retrace> to minimum (0) and
694          * <Start of vertical Retrace> to maximum (incl. overflow)
695          * Result: turn off vertical sync (VSync) pulse.
696          */
697         if (mode & VESA_VSYNC_SUSPEND) {
698                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
699                 outb_p(0xff, vga_video_port_val);       /* maximum value */
700                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
701                 outb_p(0x40, vga_video_port_val);       /* minimum (bits 0..3)  */
702                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
703                 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);  /* bits 9,10 of vert. retrace */
704         }
705
706         if (mode & VESA_HSYNC_SUSPEND) {
707                 /*
708                  * Set <End of horizontal retrace> to minimum (0) and
709                  *  <Start of horizontal Retrace> to maximum
710                  * Result: turn off horizontal sync (HSync) pulse.
711                  */
712                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
713                 outb_p(0xff, vga_video_port_val);       /* maximum */
714                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
715                 outb_p(0x00, vga_video_port_val);       /* minimum (0) */
716         }
717
718         /* restore both index registers */
719         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
720         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
721         spin_unlock_irq(&vga_lock);
722 }
723
724 static void vga_vesa_unblank(struct vgastate *state)
725 {
726         /* restore original values of VGA controller registers */
727         spin_lock_irq(&vga_lock);
728         vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
729
730         outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
731         outb_p(vga_state.HorizontalTotal, vga_video_port_val);
732         outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
733         outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
734         outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
735         outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
736         outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
737         outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
738         outb_p(0x07, vga_video_port_reg);       /* Overflow */
739         outb_p(vga_state.Overflow, vga_video_port_val);
740         outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
741         outb_p(vga_state.StartVertRetrace, vga_video_port_val);
742         outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
743         outb_p(vga_state.EndVertRetrace, vga_video_port_val);
744         outb_p(0x17, vga_video_port_reg);       /* ModeControl */
745         outb_p(vga_state.ModeControl, vga_video_port_val);
746         /* ClockingMode */
747         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
748
749         /* restore index/control registers */
750         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
751         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
752         spin_unlock_irq(&vga_lock);
753 }
754
755 static void vga_pal_blank(struct vgastate *state)
756 {
757         int i;
758
759         vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
760         for (i = 0; i < 16; i++) {
761                 vga_w(state->vgabase, VGA_PEL_IW, i);
762                 vga_w(state->vgabase, VGA_PEL_D, 0);
763                 vga_w(state->vgabase, VGA_PEL_D, 0);
764                 vga_w(state->vgabase, VGA_PEL_D, 0);
765         }
766 }
767
768 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
769 {
770         switch (blank) {
771         case 0:         /* Unblank */
772                 if (vga_vesa_blanked) {
773                         vga_vesa_unblank(&state);
774                         vga_vesa_blanked = 0;
775                 }
776                 if (vga_palette_blanked) {
777                         vga_set_palette(c, color_table);
778                         vga_palette_blanked = 0;
779                         return 0;
780                 }
781                 vga_is_gfx = 0;
782                 /* Tell console.c that it has to restore the screen itself */
783                 return 1;
784         case 1:         /* Normal blanking */
785         case -1:        /* Obsolete */
786                 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
787                         vga_pal_blank(&state);
788                         vga_palette_blanked = 1;
789                         return 0;
790                 }
791                 vgacon_set_origin(c);
792                 scr_memsetw((void *) vga_vram_base, BLANK,
793                             c->vc_screenbuf_size);
794                 if (mode_switch)
795                         vga_is_gfx = 1;
796                 return 1;
797         default:                /* VESA blanking */
798                 if (vga_video_type == VIDEO_TYPE_VGAC) {
799                         vga_vesa_blank(&state, blank - 1);
800                         vga_vesa_blanked = blank;
801                 }
802                 return 0;
803         }
804 }
805
806 /*
807  * PIO_FONT support.
808  *
809  * The font loading code goes back to the codepage package by
810  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
811  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
812  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
813  *
814  * Change for certain monochrome monitors by Yury Shevchuck
815  * (sizif@botik.yaroslavl.su).
816  */
817
818 #ifdef CAN_LOAD_EGA_FONTS
819
820 #define colourmap 0xa0000
821 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
822    should use 0xA0000 for the bwmap as well.. */
823 #define blackwmap 0xa0000
824 #define cmapsz 8192
825
826 static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
827 {
828         unsigned short video_port_status = vga_video_port_reg + 6;
829         int font_select = 0x00, beg, i;
830         char *charmap;
831         
832         if (vga_video_type != VIDEO_TYPE_EGAM) {
833                 charmap = (char *) VGA_MAP_MEM(colourmap);
834                 beg = 0x0e;
835 #ifdef VGA_CAN_DO_64KB
836                 if (vga_video_type == VIDEO_TYPE_VGAC)
837                         beg = 0x06;
838 #endif
839         } else {
840                 charmap = (char *) VGA_MAP_MEM(blackwmap);
841                 beg = 0x0a;
842         }
843
844 #ifdef BROKEN_GRAPHICS_PROGRAMS
845         /*
846          * All fonts are loaded in slot 0 (0:1 for 512 ch)
847          */
848
849         if (!arg)
850                 return -EINVAL; /* Return to default font not supported */
851
852         vga_font_is_default = 0;
853         font_select = ch512 ? 0x04 : 0x00;
854 #else
855         /*
856          * The default font is kept in slot 0 and is never touched.
857          * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
858          */
859
860         if (set) {
861                 vga_font_is_default = !arg;
862                 if (!arg)
863                         ch512 = 0;      /* Default font is always 256 */
864                 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
865         }
866
867         if (!vga_font_is_default)
868                 charmap += 4 * cmapsz;
869 #endif
870
871         unlock_kernel();
872         spin_lock_irq(&vga_lock);
873         /* First, the Sequencer */
874         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
875         /* CPU writes only to map 2 */
876         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);    
877         /* Sequential addressing */
878         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);    
879         /* Clear synchronous reset */
880         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
881
882         /* Now, the graphics controller, select map 2 */
883         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);             
884         /* disable odd-even addressing */
885         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
886         /* map start at A000:0000 */
887         vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
888         spin_unlock_irq(&vga_lock);
889
890         if (arg) {
891                 if (set)
892                         for (i = 0; i < cmapsz; i++)
893                                 vga_writeb(arg[i], charmap + i);
894                 else
895                         for (i = 0; i < cmapsz; i++)
896                                 arg[i] = vga_readb(charmap + i);
897
898                 /*
899                  * In 512-character mode, the character map is not contiguous if
900                  * we want to remain EGA compatible -- which we do
901                  */
902
903                 if (ch512) {
904                         charmap += 2 * cmapsz;
905                         arg += cmapsz;
906                         if (set)
907                                 for (i = 0; i < cmapsz; i++)
908                                         vga_writeb(arg[i], charmap + i);
909                         else
910                                 for (i = 0; i < cmapsz; i++)
911                                         arg[i] = vga_readb(charmap + i);
912                 }
913         }
914
915         spin_lock_irq(&vga_lock);
916         /* First, the sequencer, Synchronous reset */
917         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);  
918         /* CPU writes to maps 0 and 1 */
919         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
920         /* odd-even addressing */
921         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
922         /* Character Map Select */
923         if (set)
924                 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
925         /* clear synchronous reset */
926         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
927
928         /* Now, the graphics controller, select map 0 for CPU */
929         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
930         /* enable even-odd addressing */
931         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
932         /* map starts at b800:0 or b000:0 */
933         vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
934
935         /* if 512 char mode is already enabled don't re-enable it. */
936         if ((set) && (ch512 != vga_512_chars)) {
937                 int i;  
938                 
939                 /* attribute controller */
940                 for (i = 0; i < MAX_NR_CONSOLES; i++) {
941                         struct vc_data *c = vc_cons[i].d;
942                         if (c && c->vc_sw == &vga_con)
943                                 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
944                 }
945                 vga_512_chars = ch512;
946                 /* 256-char: enable intensity bit
947                    512-char: disable intensity bit */
948                 inb_p(video_port_status);       /* clear address flip-flop */
949                 /* color plane enable register */
950                 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
951                 /* Wilton (1987) mentions the following; I don't know what
952                    it means, but it works, and it appears necessary */
953                 inb_p(video_port_status);
954                 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);    
955         }
956         spin_unlock_irq(&vga_lock);
957         lock_kernel();
958         return 0;
959 }
960
961 /*
962  * Adjust the screen to fit a font of a certain height
963  */
964 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
965 {
966         unsigned char ovr, vde, fsr;
967         int rows, maxscan, i;
968
969         rows = vc->vc_scan_lines / fontheight;  /* Number of video rows we end up with */
970         maxscan = rows * fontheight - 1;        /* Scan lines to actually display-1 */
971
972         /* Reprogram the CRTC for the new font size
973            Note: the attempt to read the overflow register will fail
974            on an EGA, but using 0xff for the previous value appears to
975            be OK for EGA text modes in the range 257-512 scan lines, so I
976            guess we don't need to worry about it.
977
978            The same applies for the spill bits in the font size and cursor
979            registers; they are write-only on EGA, but it appears that they
980            are all don't care bits on EGA, so I guess it doesn't matter. */
981
982         spin_lock_irq(&vga_lock);
983         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
984         ovr = inb_p(vga_video_port_val);
985         outb_p(0x09, vga_video_port_reg);       /* Font size register */
986         fsr = inb_p(vga_video_port_val);
987         spin_unlock_irq(&vga_lock);
988
989         vde = maxscan & 0xff;   /* Vertical display end reg */
990         ovr = (ovr & 0xbd) +    /* Overflow register */
991             ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
992         fsr = (fsr & 0xe0) + (fontheight - 1);  /*  Font size register */
993
994         spin_lock_irq(&vga_lock);
995         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
996         outb_p(ovr, vga_video_port_val);
997         outb_p(0x09, vga_video_port_reg);       /* Font size */
998         outb_p(fsr, vga_video_port_val);
999         outb_p(0x12, vga_video_port_reg);       /* Vertical display limit */
1000         outb_p(vde, vga_video_port_val);
1001         spin_unlock_irq(&vga_lock);
1002         vga_video_font_height = fontheight;
1003
1004         for (i = 0; i < MAX_NR_CONSOLES; i++) {
1005                 struct vc_data *c = vc_cons[i].d;
1006
1007                 if (c && c->vc_sw == &vga_con) {
1008                         if (CON_IS_VISIBLE(c)) {
1009                                 /* void size to cause regs to be rewritten */
1010                                 cursor_size_lastfrom = 0;
1011                                 cursor_size_lastto = 0;
1012                                 c->vc_sw->con_cursor(c, CM_DRAW);
1013                         }
1014                         c->vc_font.height = fontheight;
1015                         vc_resize(c, 0, rows);  /* Adjust console size */
1016                 }
1017         }
1018         return 0;
1019 }
1020
1021 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
1022 {
1023         unsigned charcount = font->charcount;
1024         int rc;
1025
1026         if (vga_video_type < VIDEO_TYPE_EGAM)
1027                 return -EINVAL;
1028
1029         if (font->width != VGA_FONTWIDTH ||
1030             (charcount != 256 && charcount != 512))
1031                 return -EINVAL;
1032
1033         rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
1034         if (rc)
1035                 return rc;
1036
1037         if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1038                 rc = vgacon_adjust_height(c, font->height);
1039         return rc;
1040 }
1041
1042 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1043 {
1044         if (vga_video_type < VIDEO_TYPE_EGAM)
1045                 return -EINVAL;
1046
1047         font->width = VGA_FONTWIDTH;
1048         font->height = c->vc_font.height;
1049         font->charcount = vga_512_chars ? 512 : 256;
1050         if (!font->data)
1051                 return 0;
1052         return vgacon_do_font_op(&state, font->data, 0, 0);
1053 }
1054
1055 #else
1056
1057 #define vgacon_font_set NULL
1058 #define vgacon_font_get NULL
1059
1060 #endif
1061
1062 static int vgacon_resize(struct vc_data *c, unsigned int width,
1063                                 unsigned int height)
1064 {
1065         if (width % 2 || width > ORIG_VIDEO_COLS ||
1066             height > (ORIG_VIDEO_LINES * vga_default_font_height)/
1067             c->vc_font.height)
1068                 /* let svgatextmode tinker with video timings */
1069                 return 0;
1070
1071         if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1072                 vgacon_doresize(c, width, height);
1073         return 0;
1074 }
1075
1076 static int vgacon_scrolldelta(struct vc_data *c, int lines)
1077 {
1078         if (!lines)             /* Turn scrollback off */
1079                 c->vc_visible_origin = c->vc_origin;
1080         else {
1081                 int margin = c->vc_size_row * 4;
1082                 int ul, we, p, st;
1083
1084                 if (vga_rolled_over >
1085                     (c->vc_scr_end - vga_vram_base) + margin) {
1086                         ul = c->vc_scr_end - vga_vram_base;
1087                         we = vga_rolled_over + c->vc_size_row;
1088                 } else {
1089                         ul = 0;
1090                         we = vga_vram_size;
1091                 }
1092                 p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
1093                     lines * c->vc_size_row;
1094                 st = (c->vc_origin - vga_vram_base - ul + we) % we;
1095                 if (st < 2 * margin)
1096                         margin = 0;
1097                 if (p < margin)
1098                         p = 0;
1099                 if (p > st - margin)
1100                         p = st;
1101                 c->vc_visible_origin = vga_vram_base + (p + ul) % we;
1102         }
1103         vga_set_mem_top(c);
1104         return 1;
1105 }
1106
1107 static int vgacon_set_origin(struct vc_data *c)
1108 {
1109         if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
1110             (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
1111                 return 0;
1112         c->vc_origin = c->vc_visible_origin = vga_vram_base;
1113         vga_set_mem_top(c);
1114         vga_rolled_over = 0;
1115         return 1;
1116 }
1117
1118 static void vgacon_save_screen(struct vc_data *c)
1119 {
1120         static int vga_bootup_console = 0;
1121
1122         if (!vga_bootup_console) {
1123                 /* This is a gross hack, but here is the only place we can
1124                  * set bootup console parameters without messing up generic
1125                  * console initialization routines.
1126                  */
1127                 vga_bootup_console = 1;
1128                 c->vc_x = ORIG_X;
1129                 c->vc_y = ORIG_Y;
1130         }
1131
1132         /* We can't copy in more then the size of the video buffer,
1133          * or we'll be copying in VGA BIOS */
1134
1135         if (!vga_is_gfx)
1136                 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1137                             c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1138 }
1139
1140 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1141                          int lines)
1142 {
1143         unsigned long oldo;
1144         unsigned int delta;
1145
1146         if (t || b != c->vc_rows || vga_is_gfx)
1147                 return 0;
1148
1149         if (c->vc_origin != c->vc_visible_origin)
1150                 vgacon_scrolldelta(c, 0);
1151
1152         if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1153                 return 0;
1154
1155         oldo = c->vc_origin;
1156         delta = lines * c->vc_size_row;
1157         if (dir == SM_UP) {
1158                 if (c->vc_scr_end + delta >= vga_vram_end) {
1159                         scr_memcpyw((u16 *) vga_vram_base,
1160                                     (u16 *) (oldo + delta),
1161                                     c->vc_screenbuf_size - delta);
1162                         c->vc_origin = vga_vram_base;
1163                         vga_rolled_over = oldo - vga_vram_base;
1164                 } else
1165                         c->vc_origin += delta;
1166                 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1167                                      delta), c->vc_video_erase_char,
1168                             delta);
1169         } else {
1170                 if (oldo - delta < vga_vram_base) {
1171                         scr_memmovew((u16 *) (vga_vram_end -
1172                                               c->vc_screenbuf_size +
1173                                               delta), (u16 *) oldo,
1174                                      c->vc_screenbuf_size - delta);
1175                         c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1176                         vga_rolled_over = 0;
1177                 } else
1178                         c->vc_origin -= delta;
1179                 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1180                 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1181                             delta);
1182         }
1183         c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1184         c->vc_visible_origin = c->vc_origin;
1185         vga_set_mem_top(c);
1186         c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1187         return 1;
1188 }
1189
1190
1191 /*
1192  *  The console `switch' structure for the VGA based console
1193  */
1194
1195 static int vgacon_dummy(struct vc_data *c)
1196 {
1197         return 0;
1198 }
1199
1200 #define DUMMY (void *) vgacon_dummy
1201
1202 const struct consw vga_con = {
1203         .owner = THIS_MODULE,
1204         .con_startup = vgacon_startup,
1205         .con_init = vgacon_init,
1206         .con_deinit = vgacon_deinit,
1207         .con_clear = DUMMY,
1208         .con_putc = DUMMY,
1209         .con_putcs = DUMMY,
1210         .con_cursor = vgacon_cursor,
1211         .con_scroll = vgacon_scroll,
1212         .con_bmove = DUMMY,
1213         .con_switch = vgacon_switch,
1214         .con_blank = vgacon_blank,
1215         .con_font_set = vgacon_font_set,
1216         .con_font_get = vgacon_font_get,
1217         .con_resize = vgacon_resize,
1218         .con_set_palette = vgacon_set_palette,
1219         .con_scrolldelta = vgacon_scrolldelta,
1220         .con_set_origin = vgacon_set_origin,
1221         .con_save_screen = vgacon_save_screen,
1222         .con_build_attr = vgacon_build_attr,
1223         .con_invert_region = vgacon_invert_region,
1224 };
1225
1226 MODULE_LICENSE("GPL");