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