36 #include <linux/module.h>
37 #include <linux/types.h>
39 #include <linux/kernel.h>
41 #include <linux/string.h>
43 #include <linux/slab.h>
49 #include <linux/screen_info.h>
54 static int cursor_size_lastfrom;
55 static int cursor_size_lastto;
56 static u32 vgacon_xres;
57 static u32 vgacon_yres;
62 #define CAN_LOAD_EGA_FONTS
63 #define CAN_LOAD_PALETTE
71 #define VGA_FONTWIDTH 8
76 static const char *vgacon_startup(
void);
78 static void vgacon_deinit(
struct vc_data *
c);
80 static int vgacon_switch(
struct vc_data *
c);
81 static int vgacon_blank(
struct vc_data *
c,
int blank,
int mode_switch);
82 static int vgacon_set_palette(
struct vc_data *
vc,
unsigned char *
table);
83 static int vgacon_scrolldelta(
struct vc_data *
c,
int lines);
84 static int vgacon_set_origin(
struct vc_data *
c);
85 static void vgacon_save_screen(
struct vc_data *
c);
86 static int vgacon_scroll(
struct vc_data *
c,
int t,
int b,
int dir,
89 static unsigned long vgacon_uni_pagedir[2];
98 static unsigned int vga_video_num_columns;
99 static unsigned int vga_video_num_lines;
104 static unsigned char vga_hardscroll_user_enable
__read_mostly = 1;
105 static unsigned char vga_font_is_default = 1;
106 static int vga_vesa_blanked;
107 static int vga_palette_blanked;
108 static int vga_is_gfx;
109 static int vga_512_chars;
110 static int vga_video_font_height;
112 static unsigned int vga_rolled_over;
114 static int vgacon_text_mode_force;
118 return vgacon_text_mode_force ?
true :
false;
124 vgacon_text_mode_force = 1;
129 __setup(
"nomodeset", text_mode);
138 vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
142 __setup(
"no-scroll", no_scroll);
151 static inline void write_vga(
unsigned char reg,
unsigned int val)
163 v1 = reg + (val & 0xff00);
164 v2 = reg + 1 + ((val << 8) & 0xff00);
165 outw(
v1, vga_video_port_reg);
166 outw(
v2, vga_video_port_reg);
176 static inline void vga_set_mem_top(
struct vc_data *
c)
181 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
183 static void *vgacon_scrollback;
184 static int vgacon_scrollback_tail;
185 static int vgacon_scrollback_size;
186 static int vgacon_scrollback_rows;
187 static int vgacon_scrollback_cnt;
188 static int vgacon_scrollback_cur;
189 static int vgacon_scrollback_save;
190 static int vgacon_scrollback_restore;
194 int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
196 if (vgacon_scrollback) {
197 vgacon_scrollback_cnt = 0;
198 vgacon_scrollback_tail = 0;
199 vgacon_scrollback_cur = 0;
200 vgacon_scrollback_rows = rows - 1;
201 vgacon_scrollback_size = rows * pitch;
207 vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
GFP_NOWAIT);
221 scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
223 vgacon_scrollback_cnt++;
227 if (vgacon_scrollback_tail >= vgacon_scrollback_size)
228 vgacon_scrollback_tail = 0;
230 if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
231 vgacon_scrollback_cnt = vgacon_scrollback_rows;
233 vgacon_scrollback_cur = vgacon_scrollback_cnt;
237 static void vgacon_restore_screen(
struct vc_data *c)
239 vgacon_scrollback_save = 0;
241 if (!vga_is_gfx && !vgacon_scrollback_restore) {
245 vgacon_scrollback_restore = 1;
246 vgacon_scrollback_cur = vgacon_scrollback_cnt;
250 static int vgacon_scrolldelta(
struct vc_data *c,
int lines)
260 if (!vgacon_scrollback)
263 if (!vgacon_scrollback_save) {
265 vgacon_save_screen(c);
266 vgacon_scrollback_save = 1;
269 vgacon_scrollback_restore = 0;
270 start = vgacon_scrollback_cur + lines;
271 end = start +
abs(lines);
276 if (start > vgacon_scrollback_cnt)
277 start = vgacon_scrollback_cnt;
282 if (end > vgacon_scrollback_cnt)
283 end = vgacon_scrollback_cnt;
285 vgacon_scrollback_cur =
start;
287 soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt -
end) *
292 soff += vgacon_scrollback_size;
294 count = vgacon_scrollback_cnt -
start;
308 copysize =
min(count, vgacon_scrollback_size - soff);
309 scr_memcpyw(d, vgacon_scrollback + soff, copysize);
326 #define vgacon_scrollback_startup(...) do { } while (0)
327 #define vgacon_scrollback_init(...) do { } while (0)
328 #define vgacon_scrollback_update(...) do { } while (0)
330 static void vgacon_restore_screen(
struct vc_data *c)
333 vgacon_scrolldelta(c, 0);
336 static int vgacon_scrolldelta(
struct vc_data *c,
int lines)
344 if (vga_rolled_over >
354 st = (c->
vc_origin - vga_vram_base - ul + we) % we;
368 static const char *vgacon_startup(
void)
370 const char *display_desc =
NULL;
377 #ifdef CONFIG_DUMMY_CONSOLE
405 vga_vram_base = 0xb0000;
409 static struct resource ega_console_resource =
410 { .
name =
"ega", .start = 0x3B0, .end = 0x3BF };
412 vga_vram_size = 0x8000;
413 display_desc =
"EGA+";
415 &ega_console_resource);
417 static struct resource mda1_console_resource =
418 { .
name =
"mda", .start = 0x3B0, .end = 0x3BB };
419 static struct resource mda2_console_resource =
420 { .
name =
"mda", .start = 0x3BF, .end = 0x3BF };
422 vga_vram_size = 0x2000;
423 display_desc =
"*MDA";
425 &mda1_console_resource);
427 &mda2_console_resource);
428 vga_video_font_height = 14;
432 vga_can_do_color = 1;
433 vga_vram_base = 0xb8000;
439 vga_vram_size = 0x8000;
442 static struct resource ega_console_resource
443 = { .
name =
"ega", .start = 0x3C0, .end = 0x3DF };
445 display_desc =
"EGA";
447 &ega_console_resource);
449 static struct resource vga_console_resource
450 = { .
name =
"vga+", .start = 0x3C0, .end = 0x3DF };
452 display_desc =
"VGA+";
454 &vga_console_resource);
456 #ifdef VGA_CAN_DO_64KB
463 vga_vram_base = 0xa0000;
464 vga_vram_size = 0x10000;
474 for (i = 0; i < 16; i++) {
485 for (i = 0; i < 16; i++) {
493 static struct resource cga_console_resource =
494 { .
name =
"cga", .start = 0x3D4, .end = 0x3D5 };
496 vga_vram_size = 0x2000;
497 display_desc =
"*CGA";
499 &cga_console_resource);
500 vga_video_font_height = 8;
504 vga_vram_base =
VGA_MAP_MEM(vga_vram_base, vga_vram_size);
505 vga_vram_end = vga_vram_base + vga_vram_size;
511 p = (
volatile u16 *) vga_vram_base;
534 vga_hardscroll_enabled = vga_hardscroll_user_enable;
539 vga_video_font_height * vga_video_num_lines;
543 vgacon_yres = vga_scan_lines;
545 if (!vga_init_done) {
553 static void vgacon_init(
struct vc_data *c,
int init)
566 c->
vc_cols = vga_video_num_columns;
567 c->
vc_rows = vga_video_num_lines;
569 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
572 c->
vc_font.height = vga_video_font_height;
581 vgacon_uni_pagedir[1]++;
582 if (!vgacon_uni_pagedir[0] && p)
591 static void vgacon_deinit(
struct vc_data *c)
599 if (!--vgacon_uni_pagedir[1])
606 u8 blink,
u8 underline,
u8 reverse,
u8 italic)
610 if (vga_can_do_color) {
615 else if (intensity == 0)
626 if (!vga_can_do_color) {
628 attr = (attr & 0xF8) | 0x02;
630 attr = (attr & 0xf8) | 0x01;
631 else if (intensity == 0)
632 attr = (attr & 0xf0) | 0x08;
637 static void vgacon_invert_region(
struct vc_data *c,
u16 * p,
int count)
639 int col = vga_can_do_color;
644 a = ((
a) & 0x88ff) | (((
a) & 0x7000) >> 4) |
645 (((a) & 0x0700) << 4);
647 a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
652 static void vgacon_set_cursor_size(
int xpos,
int from,
int to)
657 #ifdef TRIDENT_GLITCH
662 if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
664 cursor_size_lastfrom =
from;
665 cursor_size_lastto = to;
670 curs =
inb_p(vga_video_port_val);
672 cure =
inb_p(vga_video_port_val);
678 curs = (curs & 0xc0) | from;
679 cure = (cure & 0xe0) | to;
682 outb_p(curs, vga_video_port_val);
684 outb_p(cure, vga_video_port_val);
688 static void vgacon_cursor(
struct vc_data *c,
int mode)
693 vgacon_restore_screen(c);
697 write_vga(14, (c->
vc_pos - vga_vram_base) / 2);
699 vgacon_set_cursor_size(c->
vc_x, 31, 30);
701 vgacon_set_cursor_size(c->
vc_x, 31, 31);
706 write_vga(14, (c->
vc_pos - vga_vram_base) / 2);
709 vgacon_set_cursor_size(c->
vc_x,
718 vgacon_set_cursor_size(c->
vc_x,
725 vgacon_set_cursor_size(c->
vc_x,
732 vgacon_set_cursor_size(c->
vc_x,
740 vgacon_set_cursor_size(c->
vc_x, 31, 30);
742 vgacon_set_cursor_size(c->
vc_x, 31, 31);
745 vgacon_set_cursor_size(c->
vc_x, 1,
753 static int vgacon_doresize(
struct vc_data *c,
757 unsigned int scanlines = height * c->
vc_font.height;
758 u8 scanlines_lo = 0,
r7 = 0, vsync_end = 0,
mode, max_scan;
763 vgacon_yres = height * c->
vc_font.height;
766 max_scan =
inb_p(vga_video_port_val);
772 mode =
inb_p(vga_video_port_val);
778 scanlines_lo = scanlines & 0xff;
781 r7 =
inb_p(vga_video_port_val) & ~0x42;
783 if (scanlines & 0x100)
785 if (scanlines & 0x200)
790 vsync_end =
inb_p(vga_video_port_val);
792 outb_p(vsync_end & ~0x80, vga_video_port_val);
796 outb_p(width - 1, vga_video_port_val);
798 outb_p(width >> 1, vga_video_port_val);
802 outb_p(scanlines_lo, vga_video_port_val);
808 outb_p(vsync_end, vga_video_port_val);
815 static int vgacon_switch(
struct vc_data *c)
826 vga_video_num_columns = c->
vc_cols;
827 vga_video_num_lines = c->
vc_rows;
837 if ((vgacon_xres != x || vgacon_yres != y) &&
838 (!(vga_video_num_columns % 2) &&
840 vga_video_num_lines <= rows))
848 static void vga_set_palette(
struct vc_data *
vc,
unsigned char *
table)
853 for (i = j = 0; i < 16; i++) {
861 static int vgacon_set_palette(
struct vc_data *vc,
unsigned char *table)
863 #ifdef CAN_LOAD_PALETTE
867 vga_set_palette(vc, table);
893 if (!vga_vesa_blanked) {
896 vga_state.CrtCtrlIndex =
inb_p(vga_video_port_reg);
900 outb_p(0x00, vga_video_port_reg);
901 vga_state.HorizontalTotal =
inb_p(vga_video_port_val);
902 outb_p(0x01, vga_video_port_reg);
903 vga_state.HorizDisplayEnd =
inb_p(vga_video_port_val);
904 outb_p(0x04, vga_video_port_reg);
905 vga_state.StartHorizRetrace =
inb_p(vga_video_port_val);
906 outb_p(0x05, vga_video_port_reg);
907 vga_state.EndHorizRetrace =
inb_p(vga_video_port_val);
908 outb_p(0x07, vga_video_port_reg);
909 vga_state.Overflow =
inb_p(vga_video_port_val);
910 outb_p(0x10, vga_video_port_reg);
911 vga_state.StartVertRetrace =
inb_p(vga_video_port_val);
912 outb_p(0x11, vga_video_port_reg);
913 vga_state.EndVertRetrace =
inb_p(vga_video_port_val);
914 outb_p(0x17, vga_video_port_reg);
915 vga_state.ModeControl =
inb_p(vga_video_port_val);
925 if ((vga_state.CrtMiscIO & 0x80) == 0x80)
934 outb_p(0x10, vga_video_port_reg);
935 outb_p(0xff, vga_video_port_val);
936 outb_p(0x11, vga_video_port_reg);
937 outb_p(0x40, vga_video_port_val);
938 outb_p(0x07, vga_video_port_reg);
939 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);
948 outb_p(0x04, vga_video_port_reg);
949 outb_p(0xff, vga_video_port_val);
950 outb_p(0x05, vga_video_port_reg);
951 outb_p(0x00, vga_video_port_val);
956 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
960 static void vga_vesa_unblank(
struct vgastate *state)
966 outb_p(0x00, vga_video_port_reg);
967 outb_p(vga_state.HorizontalTotal, vga_video_port_val);
968 outb_p(0x01, vga_video_port_reg);
969 outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
970 outb_p(0x04, vga_video_port_reg);
971 outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
972 outb_p(0x05, vga_video_port_reg);
973 outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
974 outb_p(0x07, vga_video_port_reg);
975 outb_p(vga_state.Overflow, vga_video_port_val);
976 outb_p(0x10, vga_video_port_reg);
977 outb_p(vga_state.StartVertRetrace, vga_video_port_val);
978 outb_p(0x11, vga_video_port_reg);
979 outb_p(vga_state.EndVertRetrace, vga_video_port_val);
980 outb_p(0x17, vga_video_port_reg);
981 outb_p(vga_state.ModeControl, vga_video_port_val);
987 outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
991 static void vga_pal_blank(
struct vgastate *state)
996 for (i = 0; i < 16; i++) {
1004 static int vgacon_blank(
struct vc_data *c,
int blank,
int mode_switch)
1008 if (vga_vesa_blanked) {
1009 vga_vesa_unblank(&state);
1010 vga_vesa_blanked = 0;
1012 if (vga_palette_blanked) {
1014 vga_palette_blanked = 0;
1023 vga_pal_blank(&state);
1024 vga_palette_blanked = 1;
1027 vgacon_set_origin(c);
1028 scr_memsetw((
void *) vga_vram_base,
BLANK,
1035 vga_vesa_blank(&state, blank - 1);
1036 vga_vesa_blanked = blank;
1054 #ifdef CAN_LOAD_EGA_FONTS
1056 #define colourmap 0xa0000
1059 #define blackwmap 0xa0000
1062 static int vgacon_do_font_op(
struct vgastate *state,
char *
arg,
int set,
int ch512)
1064 unsigned short video_port_status = vga_video_port_reg + 6;
1065 int font_select = 0x00, beg,
i;
1071 #ifdef VGA_CAN_DO_64KB
1080 #ifdef BROKEN_GRAPHICS_PROGRAMS
1088 vga_font_is_default = 0;
1089 font_select = ch512 ? 0x04 : 0x00;
1097 vga_font_is_default = !
arg;
1100 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
1103 if (!vga_font_is_default)
1127 for (i = 0; i <
cmapsz; i++)
1130 for (i = 0; i <
cmapsz; i++)
1142 for (i = 0; i <
cmapsz; i++)
1145 for (i = 0; i <
cmapsz; i++)
1171 if ((
set) && (ch512 != vga_512_chars)) {
1178 vga_512_chars = ch512;
1181 inb_p(video_port_status);
1186 inb_p(video_port_status);
1196 static int vgacon_adjust_height(
struct vc_data *vc,
unsigned fontheight)
1198 unsigned char ovr, vde, fsr;
1199 int rows, maxscan,
i;
1202 maxscan = rows * fontheight - 1;
1215 outb_p(0x07, vga_video_port_reg);
1216 ovr =
inb_p(vga_video_port_val);
1217 outb_p(0x09, vga_video_port_reg);
1218 fsr =
inb_p(vga_video_port_val);
1221 vde = maxscan & 0xff;
1222 ovr = (ovr & 0xbd) +
1223 ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
1224 fsr = (fsr & 0xe0) + (fontheight - 1);
1227 outb_p(0x07, vga_video_port_reg);
1228 outb_p(ovr, vga_video_port_val);
1229 outb_p(0x09, vga_video_port_reg);
1230 outb_p(fsr, vga_video_port_val);
1231 outb_p(0x12, vga_video_port_reg);
1232 outb_p(vde, vga_video_port_val);
1234 vga_video_font_height = fontheight;
1242 cursor_size_lastfrom = 0;
1243 cursor_size_lastto = 0;
1246 c->
vc_font.height = fontheight;
1261 if (font->
width != VGA_FONTWIDTH ||
1262 (charcount != 256 && charcount != 512))
1265 rc = vgacon_do_font_op(&state, font->
data, 1, charcount == 512);
1270 rc = vgacon_adjust_height(c, font->
height);
1281 font->
charcount = vga_512_chars ? 512 : 256;
1284 return vgacon_do_font_op(&state, font->
data, 0, vga_512_chars);
1289 #define vgacon_font_set NULL
1290 #define vgacon_font_get NULL
1294 static int vgacon_resize(
struct vc_data *c,
unsigned int width,
1295 unsigned int height,
unsigned int user)
1302 return (user) ? 0 : -
EINVAL;
1305 vgacon_doresize(c, width, height);
1309 static int vgacon_set_origin(
struct vc_data *c)
1316 vga_rolled_over = 0;
1320 static void vgacon_save_screen(
struct vc_data *c)
1322 static int vga_bootup_console = 0;
1324 if (!vga_bootup_console) {
1329 vga_bootup_console = 1;
1342 static int vgacon_scroll(
struct vc_data *c,
int t,
int b,
int dir,
1351 if (!vga_hardscroll_enabled || lines >= c->
vc_rows / 2)
1354 vgacon_restore_screen(c);
1361 (
u16 *) (oldo + delta),
1364 vga_rolled_over = oldo - vga_vram_base;
1371 if (oldo - delta < vga_vram_base) {
1374 delta), (
u16 *) oldo,
1377 vga_rolled_over = 0;
1396 static int vgacon_dummy(
struct vc_data *c)
1401 #define DUMMY (void *) vgacon_dummy
1405 .con_startup = vgacon_startup,
1406 .con_init = vgacon_init,
1407 .con_deinit = vgacon_deinit,
1411 .con_cursor = vgacon_cursor,
1412 .con_scroll = vgacon_scroll,
1414 .con_switch = vgacon_switch,
1415 .con_blank = vgacon_blank,
1416 .con_font_set = vgacon_font_set,
1417 .con_font_get = vgacon_font_get,
1418 .con_resize = vgacon_resize,
1419 .con_set_palette = vgacon_set_palette,
1420 .con_scrolldelta = vgacon_scrolldelta,
1421 .con_set_origin = vgacon_set_origin,
1422 .con_save_screen = vgacon_save_screen,
1423 .con_build_attr = vgacon_build_attr,
1424 .con_invert_region = vgacon_invert_region,