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