29 #include <linux/types.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
34 #include <linux/string.h>
51 static unsigned long mda_vram_base;
52 static unsigned long mda_vram_len;
53 static unsigned int mda_num_columns;
54 static unsigned int mda_num_lines;
56 static unsigned int mda_index_port;
57 static unsigned int mda_value_port;
58 static unsigned int mda_mode_port;
59 static unsigned int mda_status_port;
60 static unsigned int mda_gfx_port;
64 static int mda_cursor_loc=-1;
65 static int mda_cursor_size_from=-1;
66 static int mda_cursor_size_to=-1;
69 static char *mda_type_name;
73 static int mda_first_vc = 13;
74 static int mda_last_vc = 16;
86 #define MDA_CURSOR_BLINKING 0x00
87 #define MDA_CURSOR_OFF 0x20
88 #define MDA_CURSOR_SLOWBLINK 0x60
90 #define MDA_MODE_GRAPHICS 0x02
91 #define MDA_MODE_VIDEO_EN 0x08
92 #define MDA_MODE_BLINK_EN 0x20
93 #define MDA_MODE_GFX_PAGE1 0x80
95 #define MDA_STATUS_HSYNC 0x01
96 #define MDA_STATUS_VSYNC 0x80
97 #define MDA_STATUS_VIDEO 0x08
99 #define MDA_CONFIG_COL132 0x08
100 #define MDA_GFX_MODE_EN 0x01
101 #define MDA_GFX_PAGE_EN 0x02
108 static void write_mda_b(
unsigned int val,
unsigned char reg)
114 outb_p(reg, mda_index_port);
115 outb_p(val, mda_value_port);
117 spin_unlock_irqrestore(&mda_lock, flags);
120 static void write_mda_w(
unsigned int val,
unsigned char reg)
126 outb_p(reg, mda_index_port);
outb_p(val >> 8, mda_value_port);
127 outb_p(reg+1, mda_index_port);
outb_p(val & 0xff, mda_value_port);
129 spin_unlock_irqrestore(&mda_lock, flags);
133 static int test_mda_b(
unsigned char val,
unsigned char reg)
139 outb_p(reg, mda_index_port);
140 outb (val, mda_value_port);
144 spin_unlock_irqrestore(&mda_lock, flags);
149 static inline void mda_set_cursor(
unsigned int location)
151 if (mda_cursor_loc == location)
154 write_mda_w(location >> 1, 0x0e);
159 static inline void mda_set_cursor_size(
int from,
int to)
161 if (mda_cursor_size_from==from && mda_cursor_size_to==to)
167 write_mda_b(from, 0x0a);
168 write_mda_b(to, 0x0b);
171 mda_cursor_size_from =
from;
172 mda_cursor_size_to = to;
177 static int __init mdacon_setup(
char *
str)
192 mda_first_vc = ints[1];
193 mda_last_vc = ints[2];
197 __setup(
"mdacon=", mdacon_setup);
200 static int mda_detect(
void)
208 p = (
u16 *) mda_vram_base;
209 q = (
u16 *) (mda_vram_base + 0x01000);
232 mda_vram_len = 0x02000;
243 if (! test_mda_b(0x66, 0x0f)) {
248 if (! test_mda_b(0x99, 0x0f)) {
260 for (count=0; count < 50000 && p_save == q_save; count++) {
265 if (p_save != q_save) {
266 switch (
inb_p(mda_status_port) & 0x70) {
269 mda_type_name =
"HerculesPlus";
273 mda_type_name =
"HerculesColor";
277 mda_type_name =
"Hercules";
285 static void mda_initialize(
void)
287 write_mda_b(97, 0x00);
288 write_mda_b(80, 0x01);
289 write_mda_b(82, 0x02);
290 write_mda_b(15, 0x03);
292 write_mda_b(25, 0x04);
293 write_mda_b(6, 0x05);
294 write_mda_b(25, 0x06);
295 write_mda_b(25, 0x07);
297 write_mda_b(2, 0x08);
298 write_mda_b(13, 0x09);
299 write_mda_b(12, 0x0a);
300 write_mda_b(13, 0x0b);
302 write_mda_w(0x0000, 0x0c);
303 write_mda_w(0x0000, 0x0e);
306 outb_p(0x00, mda_status_port);
307 outb_p(0x00, mda_gfx_port);
310 static const char *mdacon_startup(
void)
312 mda_num_columns = 80;
315 mda_vram_len = 0x01000;
316 mda_vram_base =
VGA_MAP_MEM(0xb0000, mda_vram_len);
318 mda_index_port = 0x3b4;
319 mda_value_port = 0x3b5;
320 mda_mode_port = 0x3b8;
321 mda_status_port = 0x3ba;
322 mda_gfx_port = 0x3bf;
325 mda_type_name =
"MDA";
327 if (! mda_detect()) {
328 printk(
"mdacon: MDA card not detected.\n");
337 mda_set_cursor(mda_vram_len - 1);
339 printk(
"mdacon: %s with %ldK of memory detected.\n",
340 mda_type_name, mda_vram_len/1024);
354 vc_resize(c, mda_num_columns, mda_num_lines);
358 if (mda_display_fg ==
NULL)
362 static void mdacon_deinit(
struct vc_data *c)
366 if (mda_display_fg == c)
367 mda_display_fg =
NULL;
370 static inline u16 mda_convert_attr(
u16 ch)
379 if (ch & 0x0800) attr = 0x7000;
380 else if (ch & 0x0400) attr = 0x0100;
382 return ((ch & 0x0200) << 2) |
384 (ch & 0x00ff) |
attr;
388 u8 blink,
u8 underline,
u8 reverse,
u8 italic)
398 return (intensity & 3) |
399 ((underline & 1) << 2) |
400 ((reverse & 1) << 3) |
405 static void mdacon_invert_region(
struct vc_data *c,
u16 *p,
int count)
407 for (; count > 0; count--) {
413 #define MDA_ADDR(x,y) ((u16 *) mda_vram_base + (y)*mda_num_columns + (x))
415 static void mdacon_putc(
struct vc_data *c,
int ch,
int y,
int x)
420 static void mdacon_putcs(
struct vc_data *c,
const unsigned short *
s,
421 int count,
int y,
int x)
425 for (; count > 0; count--) {
430 static void mdacon_clear(
struct vc_data *c,
int y,
int x,
436 if (width <= 0 || height <= 0)
439 if (x==0 && width==mda_num_columns) {
440 scr_memsetw(dest, eattr, height*width*2);
442 for (; height > 0; height--, dest+=mda_num_columns)
443 scr_memsetw(dest, eattr, width*2);
447 static void mdacon_bmove(
struct vc_data *c,
int sy,
int sx,
448 int dy,
int dx,
int height,
int width)
452 if (width <= 0 || height <= 0)
455 if (sx==0 && dx==0 && width==mda_num_columns) {
458 }
else if (dy < sy || (dy == sy && dx < sx)) {
462 for (; height > 0; height--) {
464 src += mda_num_columns;
465 dest += mda_num_columns;
471 for (; height > 0; height--) {
473 src -= mda_num_columns;
474 dest -= mda_num_columns;
479 static int mdacon_switch(
struct vc_data *c)
484 static int mdacon_set_palette(
struct vc_data *c,
unsigned char *
table)
489 static int mdacon_blank(
struct vc_data *c,
int blank,
int mode_switch)
493 scr_memsetw((
void *)mda_vram_base,
500 outb_p(0x00, mda_mode_port);
508 static int mdacon_scrolldelta(
struct vc_data *c,
int lines)
513 static void mdacon_cursor(
struct vc_data *c,
int mode)
516 mda_set_cursor(mda_vram_len - 1);
520 mda_set_cursor(c->
vc_y*mda_num_columns*2 + c->
vc_x*2);
527 case CUR_BLOCK: mda_set_cursor_size(1, 13);
break;
528 case CUR_NONE: mda_set_cursor_size(14, 13);
break;
529 default: mda_set_cursor_size(12, 13);
break;
533 static int mdacon_scroll(
struct vc_data *c,
int t,
int b,
int dir,
int lines)
547 (b-t-lines)*mda_num_columns*2);
548 scr_memsetw(
MDA_ADDR(0,b-lines), eattr,
549 lines*mda_num_columns*2);
554 (b-t-lines)*mda_num_columns*2);
555 scr_memsetw(
MDA_ADDR(0,t), eattr, lines*mda_num_columns*2);
567 static const struct consw mda_con = {
569 .con_startup = mdacon_startup,
570 .con_init = mdacon_init,
571 .con_deinit = mdacon_deinit,
572 .con_clear = mdacon_clear,
573 .con_putc = mdacon_putc,
574 .con_putcs = mdacon_putcs,
575 .con_cursor = mdacon_cursor,
576 .con_scroll = mdacon_scroll,
577 .con_bmove = mdacon_bmove,
578 .con_switch = mdacon_switch,
579 .con_blank = mdacon_blank,
580 .con_set_palette = mdacon_set_palette,
581 .con_scrolldelta = mdacon_scrolldelta,
582 .con_build_attr = mdacon_build_attr,
583 .con_invert_region = mdacon_invert_region,
588 if (mda_first_vc > mda_last_vc)
594 static void __exit mda_console_exit(
void)