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