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