1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <linux/module.h>
37#include <linux/types.h>
38#include <linux/fs.h>
39#include <linux/kernel.h>
40#include <linux/console.h>
41#include <linux/string.h>
42#include <linux/kd.h>
43#include <linux/slab.h>
44#include <linux/vt_kern.h>
45#include <linux/sched.h>
46#include <linux/selection.h>
47#include <linux/spinlock.h>
48#include <linux/ioport.h>
49#include <linux/init.h>
50#include <linux/screen_info.h>
51#include <video/vga.h>
52#include <asm/io.h>
53
54static DEFINE_RAW_SPINLOCK(vga_lock);
55static int cursor_size_lastfrom;
56static int cursor_size_lastto;
57static u32 vgacon_xres;
58static u32 vgacon_yres;
59static struct vgastate vgastate;
60
61#define BLANK 0x0020
62
63#define VGA_FONTWIDTH 8
64
65
66
67
68static const char *vgacon_startup(void);
69static void vgacon_init(struct vc_data *c, int init);
70static void vgacon_deinit(struct vc_data *c);
71static void vgacon_cursor(struct vc_data *c, int mode);
72static int vgacon_switch(struct vc_data *c);
73static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
74static void vgacon_scrolldelta(struct vc_data *c, int lines);
75static int vgacon_set_origin(struct vc_data *c);
76static void vgacon_save_screen(struct vc_data *c);
77static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
78static struct uni_pagedir *vgacon_uni_pagedir;
79static int vgacon_refcount;
80
81
82static bool vga_init_done;
83static unsigned long vga_vram_base __read_mostly;
84static unsigned long vga_vram_end __read_mostly;
85static unsigned int vga_vram_size __read_mostly;
86static u16 vga_video_port_reg __read_mostly;
87static u16 vga_video_port_val __read_mostly;
88static unsigned int vga_video_num_columns;
89static unsigned int vga_video_num_lines;
90static bool vga_can_do_color;
91static unsigned int vga_default_font_height __read_mostly;
92static unsigned char vga_video_type __read_mostly;
93static bool vga_font_is_default = true;
94static int vga_vesa_blanked;
95static bool vga_palette_blanked;
96static bool vga_is_gfx;
97static bool vga_512_chars;
98static int vga_video_font_height;
99static int vga_scan_lines __read_mostly;
100static unsigned int vga_rolled_over;
101
102static bool vgacon_text_mode_force;
103static bool vga_hardscroll_enabled;
104static bool vga_hardscroll_user_enable = true;
105
106bool vgacon_text_force(void)
107{
108 return vgacon_text_mode_force;
109}
110EXPORT_SYMBOL(vgacon_text_force);
111
112static int __init text_mode(char *str)
113{
114 vgacon_text_mode_force = true;
115
116 pr_warning("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
117 pr_warning("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");
118 pr_warning("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
119
120 return 1;
121}
122
123
124__setup("nomodeset", text_mode);
125
126static int __init no_scroll(char *str)
127{
128
129
130
131
132
133 vga_hardscroll_user_enable = vga_hardscroll_enabled = false;
134 return 1;
135}
136
137__setup("no-scroll", no_scroll);
138
139
140
141
142
143
144
145
146static inline void write_vga(unsigned char reg, unsigned int val)
147{
148 unsigned int v1, v2;
149 unsigned long flags;
150
151
152
153
154
155 raw_spin_lock_irqsave(&vga_lock, flags);
156 v1 = reg + (val & 0xff00);
157 v2 = reg + 1 + ((val << 8) & 0xff00);
158 outw(v1, vga_video_port_reg);
159 outw(v2, vga_video_port_reg);
160 raw_spin_unlock_irqrestore(&vga_lock, flags);
161}
162
163static inline void vga_set_mem_top(struct vc_data *c)
164{
165 write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
166}
167
168#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
169
170struct vgacon_scrollback_info {
171 void *data;
172 int tail;
173 int size;
174 int rows;
175 int cnt;
176 int cur;
177 int save;
178 int restore;
179};
180
181static struct vgacon_scrollback_info *vgacon_scrollback_cur;
182static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
183static bool scrollback_persistent = \
184 IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
185module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
186MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
187
188static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
189{
190 struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
191
192 if (scrollback->data && reset_size > 0)
193 memset(scrollback->data, 0, reset_size);
194
195 scrollback->cnt = 0;
196 scrollback->tail = 0;
197 scrollback->cur = 0;
198}
199
200static void vgacon_scrollback_init(int vc_num)
201{
202 int pitch = vga_video_num_columns * 2;
203 size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
204 int rows = size / pitch;
205 void *data;
206
207 data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
208 GFP_NOWAIT);
209
210 vgacon_scrollbacks[vc_num].data = data;
211 vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
212
213 vgacon_scrollback_cur->rows = rows - 1;
214 vgacon_scrollback_cur->size = rows * pitch;
215
216 vgacon_scrollback_reset(vc_num, size);
217}
218
219static void vgacon_scrollback_switch(int vc_num)
220{
221 if (!scrollback_persistent)
222 vc_num = 0;
223
224 if (!vgacon_scrollbacks[vc_num].data) {
225 vgacon_scrollback_init(vc_num);
226 } else {
227 if (scrollback_persistent) {
228 vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
229 } else {
230 size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
231
232 vgacon_scrollback_reset(vc_num, size);
233 }
234 }
235}
236
237static void vgacon_scrollback_startup(void)
238{
239 vgacon_scrollback_cur = &vgacon_scrollbacks[0];
240 vgacon_scrollback_init(0);
241}
242
243static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
244{
245 void *p;
246
247 if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
248 c->vc_num != fg_console)
249 return;
250
251 p = (void *) (c->vc_origin + t * c->vc_size_row);
252
253 while (count--) {
254 scr_memcpyw(vgacon_scrollback_cur->data +
255 vgacon_scrollback_cur->tail,
256 p, c->vc_size_row);
257
258 vgacon_scrollback_cur->cnt++;
259 p += c->vc_size_row;
260 vgacon_scrollback_cur->tail += c->vc_size_row;
261
262 if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
263 vgacon_scrollback_cur->tail = 0;
264
265 if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
266 vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
267
268 vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
269 }
270}
271
272static void vgacon_restore_screen(struct vc_data *c)
273{
274 vgacon_scrollback_cur->save = 0;
275
276 if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
277 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
278 c->vc_screenbuf_size > vga_vram_size ?
279 vga_vram_size : c->vc_screenbuf_size);
280 vgacon_scrollback_cur->restore = 1;
281 vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
282 }
283}
284
285static void vgacon_scrolldelta(struct vc_data *c, int lines)
286{
287 int start, end, count, soff;
288
289 if (!lines) {
290 c->vc_visible_origin = c->vc_origin;
291 vga_set_mem_top(c);
292 return;
293 }
294
295 if (!vgacon_scrollback_cur->data)
296 return;
297
298 if (!vgacon_scrollback_cur->save) {
299 vgacon_cursor(c, CM_ERASE);
300 vgacon_save_screen(c);
301 vgacon_scrollback_cur->save = 1;
302 }
303
304 vgacon_scrollback_cur->restore = 0;
305 start = vgacon_scrollback_cur->cur + lines;
306 end = start + abs(lines);
307
308 if (start < 0)
309 start = 0;
310
311 if (start > vgacon_scrollback_cur->cnt)
312 start = vgacon_scrollback_cur->cnt;
313
314 if (end < 0)
315 end = 0;
316
317 if (end > vgacon_scrollback_cur->cnt)
318 end = vgacon_scrollback_cur->cnt;
319
320 vgacon_scrollback_cur->cur = start;
321 count = end - start;
322 soff = vgacon_scrollback_cur->tail -
323 ((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
324 soff -= count * c->vc_size_row;
325
326 if (soff < 0)
327 soff += vgacon_scrollback_cur->size;
328
329 count = vgacon_scrollback_cur->cnt - start;
330
331 if (count > c->vc_rows)
332 count = c->vc_rows;
333
334 if (count) {
335 int copysize;
336
337 int diff = c->vc_rows - count;
338 void *d = (void *) c->vc_origin;
339 void *s = (void *) c->vc_screenbuf;
340
341 count *= c->vc_size_row;
342
343 copysize = min(count, vgacon_scrollback_cur->size - soff);
344 scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
345 d += copysize;
346 count -= copysize;
347
348 if (count) {
349 scr_memcpyw(d, vgacon_scrollback_cur->data, count);
350 d += count;
351 }
352
353 if (diff)
354 scr_memcpyw(d, s, diff * c->vc_size_row);
355 } else
356 vgacon_cursor(c, CM_MOVE);
357}
358
359static void vgacon_flush_scrollback(struct vc_data *c)
360{
361 size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
362
363 vgacon_scrollback_reset(c->vc_num, size);
364}
365#else
366#define vgacon_scrollback_startup(...) do { } while (0)
367#define vgacon_scrollback_init(...) do { } while (0)
368#define vgacon_scrollback_update(...) do { } while (0)
369#define vgacon_scrollback_switch(...) do { } while (0)
370
371static void vgacon_restore_screen(struct vc_data *c)
372{
373 if (c->vc_origin != c->vc_visible_origin)
374 vgacon_scrolldelta(c, 0);
375}
376
377static void vgacon_scrolldelta(struct vc_data *c, int lines)
378{
379 vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
380 vga_vram_size);
381 vga_set_mem_top(c);
382}
383
384static void vgacon_flush_scrollback(struct vc_data *c)
385{
386}
387#endif
388
389static const char *vgacon_startup(void)
390{
391 const char *display_desc = NULL;
392 u16 saved1, saved2;
393 volatile u16 *p;
394
395 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
396 screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
397 no_vga:
398#ifdef CONFIG_DUMMY_CONSOLE
399 conswitchp = &dummy_con;
400 return conswitchp->con_startup();
401#else
402 return NULL;
403#endif
404 }
405
406
407 if ((screen_info.orig_video_lines == 0) ||
408 (screen_info.orig_video_cols == 0))
409 goto no_vga;
410
411
412 if ((screen_info.orig_video_mode == 0x0D) ||
413 (screen_info.orig_video_mode == 0x0E) ||
414 (screen_info.orig_video_mode == 0x10) ||
415 (screen_info.orig_video_mode == 0x12) ||
416 (screen_info.orig_video_mode == 0x6A))
417 goto no_vga;
418
419 vga_video_num_lines = screen_info.orig_video_lines;
420 vga_video_num_columns = screen_info.orig_video_cols;
421 vgastate.vgabase = NULL;
422
423 if (screen_info.orig_video_mode == 7) {
424
425 vga_vram_base = 0xb0000;
426 vga_video_port_reg = VGA_CRT_IM;
427 vga_video_port_val = VGA_CRT_DM;
428 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
429 static struct resource ega_console_resource =
430 { .name = "ega",
431 .flags = IORESOURCE_IO,
432 .start = 0x3B0,
433 .end = 0x3BF };
434 vga_video_type = VIDEO_TYPE_EGAM;
435 vga_vram_size = 0x8000;
436 display_desc = "EGA+";
437 request_resource(&ioport_resource,
438 &ega_console_resource);
439 } else {
440 static struct resource mda1_console_resource =
441 { .name = "mda",
442 .flags = IORESOURCE_IO,
443 .start = 0x3B0,
444 .end = 0x3BB };
445 static struct resource mda2_console_resource =
446 { .name = "mda",
447 .flags = IORESOURCE_IO,
448 .start = 0x3BF,
449 .end = 0x3BF };
450 vga_video_type = VIDEO_TYPE_MDA;
451 vga_vram_size = 0x2000;
452 display_desc = "*MDA";
453 request_resource(&ioport_resource,
454 &mda1_console_resource);
455 request_resource(&ioport_resource,
456 &mda2_console_resource);
457 vga_video_font_height = 14;
458 }
459 } else {
460
461 vga_can_do_color = true;
462 vga_vram_base = 0xb8000;
463 vga_video_port_reg = VGA_CRT_IC;
464 vga_video_port_val = VGA_CRT_DC;
465 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
466 int i;
467
468 vga_vram_size = 0x8000;
469
470 if (!screen_info.orig_video_isVGA) {
471 static struct resource ega_console_resource =
472 { .name = "ega",
473 .flags = IORESOURCE_IO,
474 .start = 0x3C0,
475 .end = 0x3DF };
476 vga_video_type = VIDEO_TYPE_EGAC;
477 display_desc = "EGA";
478 request_resource(&ioport_resource,
479 &ega_console_resource);
480 } else {
481 static struct resource vga_console_resource =
482 { .name = "vga+",
483 .flags = IORESOURCE_IO,
484 .start = 0x3C0,
485 .end = 0x3DF };
486 vga_video_type = VIDEO_TYPE_VGAC;
487 display_desc = "VGA+";
488 request_resource(&ioport_resource,
489 &vga_console_resource);
490
491
492
493
494
495
496
497 for (i = 0; i < 16; i++) {
498 inb_p(VGA_IS1_RC);
499 outb_p(i, VGA_ATT_W);
500 outb_p(i, VGA_ATT_W);
501 }
502 outb_p(0x20, VGA_ATT_W);
503
504
505
506
507
508 for (i = 0; i < 16; i++) {
509 outb_p(color_table[i], VGA_PEL_IW);
510 outb_p(default_red[i], VGA_PEL_D);
511 outb_p(default_grn[i], VGA_PEL_D);
512 outb_p(default_blu[i], VGA_PEL_D);
513 }
514 }
515 } else {
516 static struct resource cga_console_resource =
517 { .name = "cga",
518 .flags = IORESOURCE_IO,
519 .start = 0x3D4,
520 .end = 0x3D5 };
521 vga_video_type = VIDEO_TYPE_CGA;
522 vga_vram_size = 0x2000;
523 display_desc = "*CGA";
524 request_resource(&ioport_resource,
525 &cga_console_resource);
526 vga_video_font_height = 8;
527 }
528 }
529
530 vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
531 vga_vram_end = vga_vram_base + vga_vram_size;
532
533
534
535
536
537 p = (volatile u16 *) vga_vram_base;
538 saved1 = scr_readw(p);
539 saved2 = scr_readw(p + 1);
540 scr_writew(0xAA55, p);
541 scr_writew(0x55AA, p + 1);
542 if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
543 scr_writew(saved1, p);
544 scr_writew(saved2, p + 1);
545 goto no_vga;
546 }
547 scr_writew(0x55AA, p);
548 scr_writew(0xAA55, p + 1);
549 if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
550 scr_writew(saved1, p);
551 scr_writew(saved2, p + 1);
552 goto no_vga;
553 }
554 scr_writew(saved1, p);
555 scr_writew(saved2, p + 1);
556
557 if (vga_video_type == VIDEO_TYPE_EGAC
558 || vga_video_type == VIDEO_TYPE_VGAC
559 || vga_video_type == VIDEO_TYPE_EGAM) {
560 vga_hardscroll_enabled = vga_hardscroll_user_enable;
561 vga_default_font_height = screen_info.orig_video_points;
562 vga_video_font_height = screen_info.orig_video_points;
563
564 vga_scan_lines =
565 vga_video_font_height * vga_video_num_lines;
566 }
567
568 vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
569 vgacon_yres = vga_scan_lines;
570
571 if (!vga_init_done) {
572 vgacon_scrollback_startup();
573 vga_init_done = true;
574 }
575
576 return display_desc;
577}
578
579static void vgacon_init(struct vc_data *c, int init)
580{
581 struct uni_pagedir *p;
582
583
584
585
586
587
588 c->vc_can_do_color = vga_can_do_color;
589
590
591 if (init) {
592 c->vc_cols = vga_video_num_columns;
593 c->vc_rows = vga_video_num_lines;
594 } else
595 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
596
597 c->vc_scan_lines = vga_scan_lines;
598 c->vc_font.height = vga_video_font_height;
599 c->vc_complement_mask = 0x7700;
600 if (vga_512_chars)
601 c->vc_hi_font_mask = 0x0800;
602 p = *c->vc_uni_pagedir_loc;
603 if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
604 con_free_unimap(c);
605 c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
606 vgacon_refcount++;
607 }
608 if (!vgacon_uni_pagedir && p)
609 con_set_default_unimap(c);
610
611
612 if (global_cursor_default == -1)
613 global_cursor_default =
614 !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
615}
616
617static void vgacon_deinit(struct vc_data *c)
618{
619
620 if (con_is_visible(c)) {
621 c->vc_visible_origin = vga_vram_base;
622 vga_set_mem_top(c);
623 }
624
625 if (!--vgacon_refcount)
626 con_free_unimap(c);
627 c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
628 con_set_default_unimap(c);
629}
630
631static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
632 u8 blink, u8 underline, u8 reverse, u8 italic)
633{
634 u8 attr = color;
635
636 if (vga_can_do_color) {
637 if (italic)
638 attr = (attr & 0xF0) | c->vc_itcolor;
639 else if (underline)
640 attr = (attr & 0xf0) | c->vc_ulcolor;
641 else if (intensity == 0)
642 attr = (attr & 0xf0) | c->vc_halfcolor;
643 }
644 if (reverse)
645 attr =
646 ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
647 0x77);
648 if (blink)
649 attr ^= 0x80;
650 if (intensity == 2)
651 attr ^= 0x08;
652 if (!vga_can_do_color) {
653 if (italic)
654 attr = (attr & 0xF8) | 0x02;
655 else if (underline)
656 attr = (attr & 0xf8) | 0x01;
657 else if (intensity == 0)
658 attr = (attr & 0xf0) | 0x08;
659 }
660 return attr;
661}
662
663static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
664{
665 const bool col = vga_can_do_color;
666
667 while (count--) {
668 u16 a = scr_readw(p);
669 if (col)
670 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
671 (((a) & 0x0700) << 4);
672 else
673 a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
674 scr_writew(a, p++);
675 }
676}
677
678static void vgacon_set_cursor_size(int xpos, int from, int to)
679{
680 unsigned long flags;
681 int curs, cure;
682
683 if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
684 return;
685 cursor_size_lastfrom = from;
686 cursor_size_lastto = to;
687
688 raw_spin_lock_irqsave(&vga_lock, flags);
689 if (vga_video_type >= VIDEO_TYPE_VGAC) {
690 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
691 curs = inb_p(vga_video_port_val);
692 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
693 cure = inb_p(vga_video_port_val);
694 } else {
695 curs = 0;
696 cure = 0;
697 }
698
699 curs = (curs & 0xc0) | from;
700 cure = (cure & 0xe0) | to;
701
702 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
703 outb_p(curs, vga_video_port_val);
704 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
705 outb_p(cure, vga_video_port_val);
706 raw_spin_unlock_irqrestore(&vga_lock, flags);
707}
708
709static void vgacon_cursor(struct vc_data *c, int mode)
710{
711 if (c->vc_mode != KD_TEXT)
712 return;
713
714 vgacon_restore_screen(c);
715
716 switch (mode) {
717 case CM_ERASE:
718 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
719 if (vga_video_type >= VIDEO_TYPE_VGAC)
720 vgacon_set_cursor_size(c->vc_x, 31, 30);
721 else
722 vgacon_set_cursor_size(c->vc_x, 31, 31);
723 break;
724
725 case CM_MOVE:
726 case CM_DRAW:
727 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
728 switch (c->vc_cursor_type & 0x0f) {
729 case CUR_UNDERLINE:
730 vgacon_set_cursor_size(c->vc_x,
731 c->vc_font.height -
732 (c->vc_font.height <
733 10 ? 2 : 3),
734 c->vc_font.height -
735 (c->vc_font.height <
736 10 ? 1 : 2));
737 break;
738 case CUR_TWO_THIRDS:
739 vgacon_set_cursor_size(c->vc_x,
740 c->vc_font.height / 3,
741 c->vc_font.height -
742 (c->vc_font.height <
743 10 ? 1 : 2));
744 break;
745 case CUR_LOWER_THIRD:
746 vgacon_set_cursor_size(c->vc_x,
747 (c->vc_font.height * 2) / 3,
748 c->vc_font.height -
749 (c->vc_font.height <
750 10 ? 1 : 2));
751 break;
752 case CUR_LOWER_HALF:
753 vgacon_set_cursor_size(c->vc_x,
754 c->vc_font.height / 2,
755 c->vc_font.height -
756 (c->vc_font.height <
757 10 ? 1 : 2));
758 break;
759 case CUR_NONE:
760 if (vga_video_type >= VIDEO_TYPE_VGAC)
761 vgacon_set_cursor_size(c->vc_x, 31, 30);
762 else
763 vgacon_set_cursor_size(c->vc_x, 31, 31);
764 break;
765 default:
766 vgacon_set_cursor_size(c->vc_x, 1,
767 c->vc_font.height);
768 break;
769 }
770 break;
771 }
772}
773
774static int vgacon_doresize(struct vc_data *c,
775 unsigned int width, unsigned int height)
776{
777 unsigned long flags;
778 unsigned int scanlines = height * c->vc_font.height;
779 u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
780
781 raw_spin_lock_irqsave(&vga_lock, flags);
782
783 vgacon_xres = width * VGA_FONTWIDTH;
784 vgacon_yres = height * c->vc_font.height;
785 if (vga_video_type >= VIDEO_TYPE_VGAC) {
786 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
787 max_scan = inb_p(vga_video_port_val);
788
789 if (max_scan & 0x80)
790 scanlines <<= 1;
791
792 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
793 mode = inb_p(vga_video_port_val);
794
795 if (mode & 0x04)
796 scanlines >>= 1;
797
798 scanlines -= 1;
799 scanlines_lo = scanlines & 0xff;
800
801 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
802 r7 = inb_p(vga_video_port_val) & ~0x42;
803
804 if (scanlines & 0x100)
805 r7 |= 0x02;
806 if (scanlines & 0x200)
807 r7 |= 0x40;
808
809
810 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
811 vsync_end = inb_p(vga_video_port_val);
812 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
813 outb_p(vsync_end & ~0x80, vga_video_port_val);
814 }
815
816 outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
817 outb_p(width - 1, vga_video_port_val);
818 outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
819 outb_p(width >> 1, vga_video_port_val);
820
821 if (vga_video_type >= VIDEO_TYPE_VGAC) {
822 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
823 outb_p(scanlines_lo, vga_video_port_val);
824 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
825 outb_p(r7,vga_video_port_val);
826
827
828 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
829 outb_p(vsync_end, vga_video_port_val);
830 }
831
832 raw_spin_unlock_irqrestore(&vga_lock, flags);
833 return 0;
834}
835
836static int vgacon_switch(struct vc_data *c)
837{
838 int x = c->vc_cols * VGA_FONTWIDTH;
839 int y = c->vc_rows * c->vc_font.height;
840 int rows = screen_info.orig_video_lines * vga_default_font_height/
841 c->vc_font.height;
842
843
844
845
846
847 vga_video_num_columns = c->vc_cols;
848 vga_video_num_lines = c->vc_rows;
849
850
851
852
853 if (!vga_is_gfx) {
854 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
855 c->vc_screenbuf_size > vga_vram_size ?
856 vga_vram_size : c->vc_screenbuf_size);
857
858 if ((vgacon_xres != x || vgacon_yres != y) &&
859 (!(vga_video_num_columns % 2) &&
860 vga_video_num_columns <= screen_info.orig_video_cols &&
861 vga_video_num_lines <= rows))
862 vgacon_doresize(c, c->vc_cols, c->vc_rows);
863 }
864
865 vgacon_scrollback_switch(c->vc_num);
866 return 0;
867}
868
869static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
870{
871 int i, j;
872
873 vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
874 for (i = j = 0; i < 16; i++) {
875 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
876 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
877 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
878 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
879 }
880}
881
882static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
883{
884 if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
885 || !con_is_visible(vc))
886 return;
887 vga_set_palette(vc, table);
888}
889
890
891static struct {
892 unsigned char SeqCtrlIndex;
893 unsigned char CrtCtrlIndex;
894 unsigned char CrtMiscIO;
895 unsigned char HorizontalTotal;
896 unsigned char HorizDisplayEnd;
897 unsigned char StartHorizRetrace;
898 unsigned char EndHorizRetrace;
899 unsigned char Overflow;
900 unsigned char StartVertRetrace;
901 unsigned char EndVertRetrace;
902 unsigned char ModeControl;
903 unsigned char ClockingMode;
904} vga_state;
905
906static void vga_vesa_blank(struct vgastate *state, int mode)
907{
908
909 if (!vga_vesa_blanked) {
910 raw_spin_lock_irq(&vga_lock);
911 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
912 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
913 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
914 raw_spin_unlock_irq(&vga_lock);
915
916 outb_p(0x00, vga_video_port_reg);
917 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
918 outb_p(0x01, vga_video_port_reg);
919 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
920 outb_p(0x04, vga_video_port_reg);
921 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
922 outb_p(0x05, vga_video_port_reg);
923 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
924 outb_p(0x07, vga_video_port_reg);
925 vga_state.Overflow = inb_p(vga_video_port_val);
926 outb_p(0x10, vga_video_port_reg);
927 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
928 outb_p(0x11, vga_video_port_reg);
929 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
930 outb_p(0x17, vga_video_port_reg);
931 vga_state.ModeControl = inb_p(vga_video_port_val);
932 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
933 }
934
935
936
937 raw_spin_lock_irq(&vga_lock);
938 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
939
940
941 if ((vga_state.CrtMiscIO & 0x80) == 0x80)
942 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
943
944
945
946
947
948
949 if (mode & VESA_VSYNC_SUSPEND) {
950 outb_p(0x10, vga_video_port_reg);
951 outb_p(0xff, vga_video_port_val);
952 outb_p(0x11, vga_video_port_reg);
953 outb_p(0x40, vga_video_port_val);
954 outb_p(0x07, vga_video_port_reg);
955 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);
956 }
957
958 if (mode & VESA_HSYNC_SUSPEND) {
959
960
961
962
963
964 outb_p(0x04, vga_video_port_reg);
965 outb_p(0xff, vga_video_port_val);
966 outb_p(0x05, vga_video_port_reg);
967 outb_p(0x00, vga_video_port_val);
968 }
969
970
971 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
972 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
973 raw_spin_unlock_irq(&vga_lock);
974}
975
976static void vga_vesa_unblank(struct vgastate *state)
977{
978
979 raw_spin_lock_irq(&vga_lock);
980 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
981
982 outb_p(0x00, vga_video_port_reg);
983 outb_p(vga_state.HorizontalTotal, vga_video_port_val);
984 outb_p(0x01, vga_video_port_reg);
985 outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
986 outb_p(0x04, vga_video_port_reg);
987 outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
988 outb_p(0x05, vga_video_port_reg);
989 outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
990 outb_p(0x07, vga_video_port_reg);
991 outb_p(vga_state.Overflow, vga_video_port_val);
992 outb_p(0x10, vga_video_port_reg);
993 outb_p(vga_state.StartVertRetrace, vga_video_port_val);
994 outb_p(0x11, vga_video_port_reg);
995 outb_p(vga_state.EndVertRetrace, vga_video_port_val);
996 outb_p(0x17, vga_video_port_reg);
997 outb_p(vga_state.ModeControl, vga_video_port_val);
998
999 vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
1000
1001
1002 vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
1003 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
1004 raw_spin_unlock_irq(&vga_lock);
1005}
1006
1007static void vga_pal_blank(struct vgastate *state)
1008{
1009 int i;
1010
1011 vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
1012 for (i = 0; i < 16; i++) {
1013 vga_w(state->vgabase, VGA_PEL_IW, i);
1014 vga_w(state->vgabase, VGA_PEL_D, 0);
1015 vga_w(state->vgabase, VGA_PEL_D, 0);
1016 vga_w(state->vgabase, VGA_PEL_D, 0);
1017 }
1018}
1019
1020static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
1021{
1022 switch (blank) {
1023 case 0:
1024 if (vga_vesa_blanked) {
1025 vga_vesa_unblank(&vgastate);
1026 vga_vesa_blanked = 0;
1027 }
1028 if (vga_palette_blanked) {
1029 vga_set_palette(c, color_table);
1030 vga_palette_blanked = false;
1031 return 0;
1032 }
1033 vga_is_gfx = false;
1034
1035 return 1;
1036 case 1:
1037 case -1:
1038 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
1039 vga_pal_blank(&vgastate);
1040 vga_palette_blanked = true;
1041 return 0;
1042 }
1043 vgacon_set_origin(c);
1044 scr_memsetw((void *) vga_vram_base, BLANK,
1045 c->vc_screenbuf_size);
1046 if (mode_switch)
1047 vga_is_gfx = true;
1048 return 1;
1049 default:
1050 if (vga_video_type == VIDEO_TYPE_VGAC) {
1051 vga_vesa_blank(&vgastate, blank - 1);
1052 vga_vesa_blanked = blank;
1053 }
1054 return 0;
1055 }
1056}
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070#define colourmap 0xa0000
1071
1072
1073#define blackwmap 0xa0000
1074#define cmapsz 8192
1075
1076static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
1077 bool ch512)
1078{
1079 unsigned short video_port_status = vga_video_port_reg + 6;
1080 int font_select = 0x00, beg, i;
1081 char *charmap;
1082 bool clear_attribs = false;
1083 if (vga_video_type != VIDEO_TYPE_EGAM) {
1084 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
1085 beg = 0x0e;
1086 } else {
1087 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
1088 beg = 0x0a;
1089 }
1090
1091#ifdef BROKEN_GRAPHICS_PROGRAMS
1092
1093
1094
1095
1096 if (!arg)
1097 return -EINVAL;
1098
1099 vga_font_is_default = false;
1100 font_select = ch512 ? 0x04 : 0x00;
1101#else
1102
1103
1104
1105
1106
1107 if (set) {
1108 vga_font_is_default = !arg;
1109 if (!arg)
1110 ch512 = false;
1111 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
1112 }
1113
1114 if (!vga_font_is_default)
1115 charmap += 4 * cmapsz;
1116#endif
1117
1118 raw_spin_lock_irq(&vga_lock);
1119
1120 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
1121
1122 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
1123
1124 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
1125
1126 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1127
1128
1129 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
1130
1131 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
1132
1133 vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
1134 raw_spin_unlock_irq(&vga_lock);
1135
1136 if (arg) {
1137 if (set)
1138 for (i = 0; i < cmapsz; i++) {
1139 vga_writeb(arg[i], charmap + i);
1140 cond_resched();
1141 }
1142 else
1143 for (i = 0; i < cmapsz; i++) {
1144 arg[i] = vga_readb(charmap + i);
1145 cond_resched();
1146 }
1147
1148
1149
1150
1151
1152
1153 if (ch512) {
1154 charmap += 2 * cmapsz;
1155 arg += cmapsz;
1156 if (set)
1157 for (i = 0; i < cmapsz; i++) {
1158 vga_writeb(arg[i], charmap + i);
1159 cond_resched();
1160 }
1161 else
1162 for (i = 0; i < cmapsz; i++) {
1163 arg[i] = vga_readb(charmap + i);
1164 cond_resched();
1165 }
1166 }
1167 }
1168
1169 raw_spin_lock_irq(&vga_lock);
1170
1171 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
1172
1173 vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
1174
1175 vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
1176
1177 if (set)
1178 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
1179
1180 vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
1181
1182
1183 vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
1184
1185 vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
1186
1187 vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
1188
1189
1190 if ((set) && (ch512 != vga_512_chars)) {
1191 vga_512_chars = ch512;
1192
1193
1194 inb_p(video_port_status);
1195
1196 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
1197
1198
1199 inb_p(video_port_status);
1200 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
1201 clear_attribs = true;
1202 }
1203 raw_spin_unlock_irq(&vga_lock);
1204
1205 if (clear_attribs) {
1206 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1207 struct vc_data *c = vc_cons[i].d;
1208 if (c && c->vc_sw == &vga_con) {
1209
1210
1211 c->vc_hi_font_mask = 0x00;
1212 clear_buffer_attributes(c);
1213 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1214 }
1215 }
1216 }
1217 return 0;
1218}
1219
1220
1221
1222
1223static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
1224{
1225 unsigned char ovr, vde, fsr;
1226 int rows, maxscan, i;
1227
1228 rows = vc->vc_scan_lines / fontheight;
1229 maxscan = rows * fontheight - 1;
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 raw_spin_lock_irq(&vga_lock);
1242 outb_p(0x07, vga_video_port_reg);
1243 ovr = inb_p(vga_video_port_val);
1244 outb_p(0x09, vga_video_port_reg);
1245 fsr = inb_p(vga_video_port_val);
1246 raw_spin_unlock_irq(&vga_lock);
1247
1248 vde = maxscan & 0xff;
1249 ovr = (ovr & 0xbd) +
1250 ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1251 fsr = (fsr & 0xe0) + (fontheight - 1);
1252
1253 raw_spin_lock_irq(&vga_lock);
1254 outb_p(0x07, vga_video_port_reg);
1255 outb_p(ovr, vga_video_port_val);
1256 outb_p(0x09, vga_video_port_reg);
1257 outb_p(fsr, vga_video_port_val);
1258 outb_p(0x12, vga_video_port_reg);
1259 outb_p(vde, vga_video_port_val);
1260 raw_spin_unlock_irq(&vga_lock);
1261 vga_video_font_height = fontheight;
1262
1263 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1264 struct vc_data *c = vc_cons[i].d;
1265
1266 if (c && c->vc_sw == &vga_con) {
1267 if (con_is_visible(c)) {
1268
1269 cursor_size_lastfrom = 0;
1270 cursor_size_lastto = 0;
1271 c->vc_sw->con_cursor(c, CM_DRAW);
1272 }
1273 c->vc_font.height = fontheight;
1274 vc_resize(c, 0, rows);
1275 }
1276 }
1277 return 0;
1278}
1279
1280static int vgacon_font_set(struct vc_data *c, struct console_font *font,
1281 unsigned int flags)
1282{
1283 unsigned charcount = font->charcount;
1284 int rc;
1285
1286 if (vga_video_type < VIDEO_TYPE_EGAM)
1287 return -EINVAL;
1288
1289 if (font->width != VGA_FONTWIDTH ||
1290 (charcount != 256 && charcount != 512))
1291 return -EINVAL;
1292
1293 rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
1294 if (rc)
1295 return rc;
1296
1297 if (!(flags & KD_FONT_FLAG_DONT_RECALC))
1298 rc = vgacon_adjust_height(c, font->height);
1299 return rc;
1300}
1301
1302static int vgacon_font_get(struct vc_data *c, struct console_font *font)
1303{
1304 if (vga_video_type < VIDEO_TYPE_EGAM)
1305 return -EINVAL;
1306
1307 font->width = VGA_FONTWIDTH;
1308 font->height = c->vc_font.height;
1309 font->charcount = vga_512_chars ? 512 : 256;
1310 if (!font->data)
1311 return 0;
1312 return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
1313}
1314
1315static int vgacon_resize(struct vc_data *c, unsigned int width,
1316 unsigned int height, unsigned int user)
1317{
1318 if (width % 2 || width > screen_info.orig_video_cols ||
1319 height > (screen_info.orig_video_lines * vga_default_font_height)/
1320 c->vc_font.height)
1321
1322
1323 return (user) ? 0 : -EINVAL;
1324
1325 if (con_is_visible(c) && !vga_is_gfx)
1326 vgacon_doresize(c, width, height);
1327 return 0;
1328}
1329
1330static int vgacon_set_origin(struct vc_data *c)
1331{
1332 if (vga_is_gfx ||
1333 (console_blanked && !vga_palette_blanked))
1334 return 0;
1335 c->vc_origin = c->vc_visible_origin = vga_vram_base;
1336 vga_set_mem_top(c);
1337 vga_rolled_over = 0;
1338 return 1;
1339}
1340
1341static void vgacon_save_screen(struct vc_data *c)
1342{
1343 static int vga_bootup_console = 0;
1344
1345 if (!vga_bootup_console) {
1346
1347
1348
1349
1350 vga_bootup_console = 1;
1351 c->vc_x = screen_info.orig_x;
1352 c->vc_y = screen_info.orig_y;
1353 }
1354
1355
1356
1357
1358 if (!vga_is_gfx)
1359 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
1360 c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
1361}
1362
1363static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
1364 enum con_scroll dir, unsigned int lines)
1365{
1366 unsigned long oldo;
1367 unsigned int delta;
1368
1369 if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
1370 return false;
1371
1372 if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
1373 return false;
1374
1375 vgacon_restore_screen(c);
1376 oldo = c->vc_origin;
1377 delta = lines * c->vc_size_row;
1378 if (dir == SM_UP) {
1379 vgacon_scrollback_update(c, t, lines);
1380 if (c->vc_scr_end + delta >= vga_vram_end) {
1381 scr_memcpyw((u16 *) vga_vram_base,
1382 (u16 *) (oldo + delta),
1383 c->vc_screenbuf_size - delta);
1384 c->vc_origin = vga_vram_base;
1385 vga_rolled_over = oldo - vga_vram_base;
1386 } else
1387 c->vc_origin += delta;
1388 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1389 delta), c->vc_video_erase_char,
1390 delta);
1391 } else {
1392 if (oldo - delta < vga_vram_base) {
1393 scr_memmovew((u16 *) (vga_vram_end -
1394 c->vc_screenbuf_size +
1395 delta), (u16 *) oldo,
1396 c->vc_screenbuf_size - delta);
1397 c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1398 vga_rolled_over = 0;
1399 } else
1400 c->vc_origin -= delta;
1401 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1402 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1403 delta);
1404 }
1405 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1406 c->vc_visible_origin = c->vc_origin;
1407 vga_set_mem_top(c);
1408 c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1409 return true;
1410}
1411
1412
1413
1414
1415
1416static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
1417 int width) { }
1418static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
1419static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
1420 int count, int ypos, int xpos) { }
1421
1422const struct consw vga_con = {
1423 .owner = THIS_MODULE,
1424 .con_startup = vgacon_startup,
1425 .con_init = vgacon_init,
1426 .con_deinit = vgacon_deinit,
1427 .con_clear = vgacon_clear,
1428 .con_putc = vgacon_putc,
1429 .con_putcs = vgacon_putcs,
1430 .con_cursor = vgacon_cursor,
1431 .con_scroll = vgacon_scroll,
1432 .con_switch = vgacon_switch,
1433 .con_blank = vgacon_blank,
1434 .con_font_set = vgacon_font_set,
1435 .con_font_get = vgacon_font_get,
1436 .con_resize = vgacon_resize,
1437 .con_set_palette = vgacon_set_palette,
1438 .con_scrolldelta = vgacon_scrolldelta,
1439 .con_set_origin = vgacon_set_origin,
1440 .con_save_screen = vgacon_save_screen,
1441 .con_build_attr = vgacon_build_attr,
1442 .con_invert_region = vgacon_invert_region,
1443 .con_flush_scrollback = vgacon_flush_scrollback,
1444};
1445EXPORT_SYMBOL(vga_con);
1446
1447MODULE_LICENSE("GPL");
1448