diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/console/mdacon.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/video/console/mdacon.c')
-rw-r--r-- | drivers/video/console/mdacon.c | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c new file mode 100644 index 000000000000..989e4d49e5bb --- /dev/null +++ b/drivers/video/console/mdacon.c | |||
@@ -0,0 +1,603 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mdacon.c -- Low level MDA based console driver | ||
3 | * | ||
4 | * (c) 1998 Andrew Apted <ajapted@netspace.net.au> | ||
5 | * | ||
6 | * including portions (c) 1995-1998 Patrick Caulfield. | ||
7 | * | ||
8 | * slight improvements (c) 2000 Edward Betts <edward@debian.org> | ||
9 | * | ||
10 | * This file is based on the VGA console driver (vgacon.c): | ||
11 | * | ||
12 | * Created 28 Sep 1997 by Geert Uytterhoeven | ||
13 | * | ||
14 | * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 | ||
15 | * | ||
16 | * and on the old console.c, vga.c and vesa_blank.c drivers: | ||
17 | * | ||
18 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
19 | * 1995 Jay Estabrook | ||
20 | * | ||
21 | * This file is subject to the terms and conditions of the GNU General Public | ||
22 | * License. See the file COPYING in the main directory of this archive for | ||
23 | * more details. | ||
24 | * | ||
25 | * Changelog: | ||
26 | * Paul G. (03/2001) Fix mdacon= boot prompt to use __setup(). | ||
27 | */ | ||
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/console.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/kd.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/vt_kern.h> | ||
40 | #include <linux/vt_buffer.h> | ||
41 | #include <linux/selection.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <linux/ioport.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/init.h> | ||
46 | |||
47 | #include <asm/io.h> | ||
48 | #include <asm/vga.h> | ||
49 | |||
50 | static DEFINE_SPINLOCK(mda_lock); | ||
51 | |||
52 | /* description of the hardware layout */ | ||
53 | |||
54 | static unsigned long mda_vram_base; /* Base of video memory */ | ||
55 | static unsigned long mda_vram_len; /* Size of video memory */ | ||
56 | static unsigned int mda_num_columns; /* Number of text columns */ | ||
57 | static unsigned int mda_num_lines; /* Number of text lines */ | ||
58 | |||
59 | static unsigned int mda_index_port; /* Register select port */ | ||
60 | static unsigned int mda_value_port; /* Register value port */ | ||
61 | static unsigned int mda_mode_port; /* Mode control port */ | ||
62 | static unsigned int mda_status_port; /* Status and Config port */ | ||
63 | static unsigned int mda_gfx_port; /* Graphics control port */ | ||
64 | |||
65 | /* current hardware state */ | ||
66 | |||
67 | static int mda_cursor_loc=-1; | ||
68 | static int mda_cursor_size_from=-1; | ||
69 | static int mda_cursor_size_to=-1; | ||
70 | |||
71 | static enum { TYPE_MDA, TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } mda_type; | ||
72 | static char *mda_type_name; | ||
73 | |||
74 | /* console information */ | ||
75 | |||
76 | static int mda_first_vc = 1; | ||
77 | static int mda_last_vc = 16; | ||
78 | |||
79 | static struct vc_data *mda_display_fg = NULL; | ||
80 | |||
81 | module_param(mda_first_vc, int, 0); | ||
82 | module_param(mda_last_vc, int, 0); | ||
83 | |||
84 | /* MDA register values | ||
85 | */ | ||
86 | |||
87 | #define MDA_CURSOR_BLINKING 0x00 | ||
88 | #define MDA_CURSOR_OFF 0x20 | ||
89 | #define MDA_CURSOR_SLOWBLINK 0x60 | ||
90 | |||
91 | #define MDA_MODE_GRAPHICS 0x02 | ||
92 | #define MDA_MODE_VIDEO_EN 0x08 | ||
93 | #define MDA_MODE_BLINK_EN 0x20 | ||
94 | #define MDA_MODE_GFX_PAGE1 0x80 | ||
95 | |||
96 | #define MDA_STATUS_HSYNC 0x01 | ||
97 | #define MDA_STATUS_VSYNC 0x80 | ||
98 | #define MDA_STATUS_VIDEO 0x08 | ||
99 | |||
100 | #define MDA_CONFIG_COL132 0x08 | ||
101 | #define MDA_GFX_MODE_EN 0x01 | ||
102 | #define MDA_GFX_PAGE_EN 0x02 | ||
103 | |||
104 | |||
105 | /* | ||
106 | * MDA could easily be classified as "pre-dinosaur hardware". | ||
107 | */ | ||
108 | |||
109 | static void write_mda_b(unsigned int val, unsigned char reg) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | |||
113 | spin_lock_irqsave(&mda_lock, flags); | ||
114 | |||
115 | outb_p(reg, mda_index_port); | ||
116 | outb_p(val, mda_value_port); | ||
117 | |||
118 | spin_unlock_irqrestore(&mda_lock, flags); | ||
119 | } | ||
120 | |||
121 | static void write_mda_w(unsigned int val, unsigned char reg) | ||
122 | { | ||
123 | unsigned long flags; | ||
124 | |||
125 | spin_lock_irqsave(&mda_lock, flags); | ||
126 | |||
127 | outb_p(reg, mda_index_port); outb_p(val >> 8, mda_value_port); | ||
128 | outb_p(reg+1, mda_index_port); outb_p(val & 0xff, mda_value_port); | ||
129 | |||
130 | spin_unlock_irqrestore(&mda_lock, flags); | ||
131 | } | ||
132 | |||
133 | #ifdef TEST_MDA_B | ||
134 | static int test_mda_b(unsigned char val, unsigned char reg) | ||
135 | { | ||
136 | unsigned long flags; | ||
137 | |||
138 | spin_lock_irqsave(&mda_lock, flags); | ||
139 | |||
140 | outb_p(reg, mda_index_port); | ||
141 | outb (val, mda_value_port); | ||
142 | |||
143 | udelay(20); val = (inb_p(mda_value_port) == val); | ||
144 | |||
145 | spin_unlock_irqrestore(&mda_lock, flags); | ||
146 | return val; | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | static inline void mda_set_cursor(unsigned int location) | ||
151 | { | ||
152 | if (mda_cursor_loc == location) | ||
153 | return; | ||
154 | |||
155 | write_mda_w(location >> 1, 0x0e); | ||
156 | |||
157 | mda_cursor_loc = location; | ||
158 | } | ||
159 | |||
160 | static inline void mda_set_cursor_size(int from, int to) | ||
161 | { | ||
162 | if (mda_cursor_size_from==from && mda_cursor_size_to==to) | ||
163 | return; | ||
164 | |||
165 | if (from > to) { | ||
166 | write_mda_b(MDA_CURSOR_OFF, 0x0a); /* disable cursor */ | ||
167 | } else { | ||
168 | write_mda_b(from, 0x0a); /* cursor start */ | ||
169 | write_mda_b(to, 0x0b); /* cursor end */ | ||
170 | } | ||
171 | |||
172 | mda_cursor_size_from = from; | ||
173 | mda_cursor_size_to = to; | ||
174 | } | ||
175 | |||
176 | |||
177 | #ifndef MODULE | ||
178 | static int __init mdacon_setup(char *str) | ||
179 | { | ||
180 | /* command line format: mdacon=<first>,<last> */ | ||
181 | |||
182 | int ints[3]; | ||
183 | |||
184 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
185 | |||
186 | if (ints[0] < 2) | ||
187 | return 0; | ||
188 | |||
189 | if (ints[1] < 1 || ints[1] > MAX_NR_CONSOLES || | ||
190 | ints[2] < 1 || ints[2] > MAX_NR_CONSOLES) | ||
191 | return 0; | ||
192 | |||
193 | mda_first_vc = ints[1]; | ||
194 | mda_last_vc = ints[2]; | ||
195 | return 1; | ||
196 | } | ||
197 | |||
198 | __setup("mdacon=", mdacon_setup); | ||
199 | #endif | ||
200 | |||
201 | static int __init mda_detect(void) | ||
202 | { | ||
203 | int count=0; | ||
204 | u16 *p, p_save; | ||
205 | u16 *q, q_save; | ||
206 | |||
207 | /* do a memory check */ | ||
208 | |||
209 | p = (u16 *) mda_vram_base; | ||
210 | q = (u16 *) (mda_vram_base + 0x01000); | ||
211 | |||
212 | p_save = scr_readw(p); q_save = scr_readw(q); | ||
213 | |||
214 | scr_writew(0xAA55, p); if (scr_readw(p) == 0xAA55) count++; | ||
215 | scr_writew(0x55AA, p); if (scr_readw(p) == 0x55AA) count++; | ||
216 | scr_writew(p_save, p); | ||
217 | |||
218 | if (count != 2) { | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* check if we have 4K or 8K */ | ||
223 | |||
224 | scr_writew(0xA55A, q); scr_writew(0x0000, p); | ||
225 | if (scr_readw(q) == 0xA55A) count++; | ||
226 | |||
227 | scr_writew(0x5AA5, q); scr_writew(0x0000, p); | ||
228 | if (scr_readw(q) == 0x5AA5) count++; | ||
229 | |||
230 | scr_writew(p_save, p); scr_writew(q_save, q); | ||
231 | |||
232 | if (count == 4) { | ||
233 | mda_vram_len = 0x02000; | ||
234 | } | ||
235 | |||
236 | /* Ok, there is definitely a card registering at the correct | ||
237 | * memory location, so now we do an I/O port test. | ||
238 | */ | ||
239 | |||
240 | #ifdef TEST_MDA_B | ||
241 | /* Edward: These two mess `tests' mess up my cursor on bootup */ | ||
242 | |||
243 | /* cursor low register */ | ||
244 | if (! test_mda_b(0x66, 0x0f)) { | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* cursor low register */ | ||
249 | if (! test_mda_b(0x99, 0x0f)) { | ||
250 | return 0; | ||
251 | } | ||
252 | #endif | ||
253 | |||
254 | /* See if the card is a Hercules, by checking whether the vsync | ||
255 | * bit of the status register is changing. This test lasts for | ||
256 | * approximately 1/10th of a second. | ||
257 | */ | ||
258 | |||
259 | p_save = q_save = inb_p(mda_status_port) & MDA_STATUS_VSYNC; | ||
260 | |||
261 | for (count=0; count < 50000 && p_save == q_save; count++) { | ||
262 | q_save = inb(mda_status_port) & MDA_STATUS_VSYNC; | ||
263 | udelay(2); | ||
264 | } | ||
265 | |||
266 | if (p_save != q_save) { | ||
267 | switch (inb_p(mda_status_port) & 0x70) { | ||
268 | case 0x10: | ||
269 | mda_type = TYPE_HERCPLUS; | ||
270 | mda_type_name = "HerculesPlus"; | ||
271 | break; | ||
272 | case 0x50: | ||
273 | mda_type = TYPE_HERCCOLOR; | ||
274 | mda_type_name = "HerculesColor"; | ||
275 | break; | ||
276 | default: | ||
277 | mda_type = TYPE_HERC; | ||
278 | mda_type_name = "Hercules"; | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | return 1; | ||
284 | } | ||
285 | |||
286 | static void __init mda_initialize(void) | ||
287 | { | ||
288 | write_mda_b(97, 0x00); /* horizontal total */ | ||
289 | write_mda_b(80, 0x01); /* horizontal displayed */ | ||
290 | write_mda_b(82, 0x02); /* horizontal sync pos */ | ||
291 | write_mda_b(15, 0x03); /* horizontal sync width */ | ||
292 | |||
293 | write_mda_b(25, 0x04); /* vertical total */ | ||
294 | write_mda_b(6, 0x05); /* vertical total adjust */ | ||
295 | write_mda_b(25, 0x06); /* vertical displayed */ | ||
296 | write_mda_b(25, 0x07); /* vertical sync pos */ | ||
297 | |||
298 | write_mda_b(2, 0x08); /* interlace mode */ | ||
299 | write_mda_b(13, 0x09); /* maximum scanline */ | ||
300 | write_mda_b(12, 0x0a); /* cursor start */ | ||
301 | write_mda_b(13, 0x0b); /* cursor end */ | ||
302 | |||
303 | write_mda_w(0x0000, 0x0c); /* start address */ | ||
304 | write_mda_w(0x0000, 0x0e); /* cursor location */ | ||
305 | |||
306 | outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, mda_mode_port); | ||
307 | outb_p(0x00, mda_status_port); | ||
308 | outb_p(0x00, mda_gfx_port); | ||
309 | } | ||
310 | |||
311 | static const char __init *mdacon_startup(void) | ||
312 | { | ||
313 | mda_num_columns = 80; | ||
314 | mda_num_lines = 25; | ||
315 | |||
316 | mda_vram_base = VGA_MAP_MEM(0xb0000); | ||
317 | mda_vram_len = 0x01000; | ||
318 | |||
319 | mda_index_port = 0x3b4; | ||
320 | mda_value_port = 0x3b5; | ||
321 | mda_mode_port = 0x3b8; | ||
322 | mda_status_port = 0x3ba; | ||
323 | mda_gfx_port = 0x3bf; | ||
324 | |||
325 | mda_type = TYPE_MDA; | ||
326 | mda_type_name = "MDA"; | ||
327 | |||
328 | if (! mda_detect()) { | ||
329 | printk("mdacon: MDA card not detected.\n"); | ||
330 | return NULL; | ||
331 | } | ||
332 | |||
333 | if (mda_type != TYPE_MDA) { | ||
334 | mda_initialize(); | ||
335 | } | ||
336 | |||
337 | /* cursor looks ugly during boot-up, so turn it off */ | ||
338 | mda_set_cursor(mda_vram_len - 1); | ||
339 | |||
340 | printk("mdacon: %s with %ldK of memory detected.\n", | ||
341 | mda_type_name, mda_vram_len/1024); | ||
342 | |||
343 | return "MDA-2"; | ||
344 | } | ||
345 | |||
346 | static void mdacon_init(struct vc_data *c, int init) | ||
347 | { | ||
348 | c->vc_complement_mask = 0x0800; /* reverse video */ | ||
349 | c->vc_display_fg = &mda_display_fg; | ||
350 | |||
351 | if (init) { | ||
352 | c->vc_cols = mda_num_columns; | ||
353 | c->vc_rows = mda_num_lines; | ||
354 | } else | ||
355 | vc_resize(c, mda_num_columns, mda_num_lines); | ||
356 | |||
357 | /* make the first MDA console visible */ | ||
358 | |||
359 | if (mda_display_fg == NULL) | ||
360 | mda_display_fg = c; | ||
361 | } | ||
362 | |||
363 | static void mdacon_deinit(struct vc_data *c) | ||
364 | { | ||
365 | /* con_set_default_unimap(c->vc_num); */ | ||
366 | |||
367 | if (mda_display_fg == c) | ||
368 | mda_display_fg = NULL; | ||
369 | } | ||
370 | |||
371 | static inline u16 mda_convert_attr(u16 ch) | ||
372 | { | ||
373 | u16 attr = 0x0700; | ||
374 | |||
375 | /* Underline and reverse-video are mutually exclusive on MDA. | ||
376 | * Since reverse-video is used for cursors and selected areas, | ||
377 | * it takes precedence. | ||
378 | */ | ||
379 | |||
380 | if (ch & 0x0800) attr = 0x7000; /* reverse */ | ||
381 | else if (ch & 0x0400) attr = 0x0100; /* underline */ | ||
382 | |||
383 | return ((ch & 0x0200) << 2) | /* intensity */ | ||
384 | (ch & 0x8000) | /* blink */ | ||
385 | (ch & 0x00ff) | attr; | ||
386 | } | ||
387 | |||
388 | static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, | ||
389 | u8 blink, u8 underline, u8 reverse) | ||
390 | { | ||
391 | /* The attribute is just a bit vector: | ||
392 | * | ||
393 | * Bit 0..1 : intensity (0..2) | ||
394 | * Bit 2 : underline | ||
395 | * Bit 3 : reverse | ||
396 | * Bit 7 : blink | ||
397 | */ | ||
398 | |||
399 | return (intensity & 3) | | ||
400 | ((underline & 1) << 2) | | ||
401 | ((reverse & 1) << 3) | | ||
402 | ((blink & 1) << 7); | ||
403 | } | ||
404 | |||
405 | static void mdacon_invert_region(struct vc_data *c, u16 *p, int count) | ||
406 | { | ||
407 | for (; count > 0; count--) { | ||
408 | scr_writew(scr_readw(p) ^ 0x0800, p); | ||
409 | p++; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | #define MDA_ADDR(x,y) ((u16 *) mda_vram_base + (y)*mda_num_columns + (x)) | ||
414 | |||
415 | static void mdacon_putc(struct vc_data *c, int ch, int y, int x) | ||
416 | { | ||
417 | scr_writew(mda_convert_attr(ch), MDA_ADDR(x, y)); | ||
418 | } | ||
419 | |||
420 | static void mdacon_putcs(struct vc_data *c, const unsigned short *s, | ||
421 | int count, int y, int x) | ||
422 | { | ||
423 | u16 *dest = MDA_ADDR(x, y); | ||
424 | |||
425 | for (; count > 0; count--) { | ||
426 | scr_writew(mda_convert_attr(scr_readw(s++)), dest++); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | static void mdacon_clear(struct vc_data *c, int y, int x, | ||
431 | int height, int width) | ||
432 | { | ||
433 | u16 *dest = MDA_ADDR(x, y); | ||
434 | u16 eattr = mda_convert_attr(c->vc_video_erase_char); | ||
435 | |||
436 | if (width <= 0 || height <= 0) | ||
437 | return; | ||
438 | |||
439 | if (x==0 && width==mda_num_columns) { | ||
440 | scr_memsetw(dest, eattr, height*width*2); | ||
441 | } else { | ||
442 | for (; height > 0; height--, dest+=mda_num_columns) | ||
443 | scr_memsetw(dest, eattr, width*2); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | static void mdacon_bmove(struct vc_data *c, int sy, int sx, | ||
448 | int dy, int dx, int height, int width) | ||
449 | { | ||
450 | u16 *src, *dest; | ||
451 | |||
452 | if (width <= 0 || height <= 0) | ||
453 | return; | ||
454 | |||
455 | if (sx==0 && dx==0 && width==mda_num_columns) { | ||
456 | scr_memmovew(MDA_ADDR(0,dy), MDA_ADDR(0,sy), height*width*2); | ||
457 | |||
458 | } else if (dy < sy || (dy == sy && dx < sx)) { | ||
459 | src = MDA_ADDR(sx, sy); | ||
460 | dest = MDA_ADDR(dx, dy); | ||
461 | |||
462 | for (; height > 0; height--) { | ||
463 | scr_memmovew(dest, src, width*2); | ||
464 | src += mda_num_columns; | ||
465 | dest += mda_num_columns; | ||
466 | } | ||
467 | } else { | ||
468 | src = MDA_ADDR(sx, sy+height-1); | ||
469 | dest = MDA_ADDR(dx, dy+height-1); | ||
470 | |||
471 | for (; height > 0; height--) { | ||
472 | scr_memmovew(dest, src, width*2); | ||
473 | src -= mda_num_columns; | ||
474 | dest -= mda_num_columns; | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | |||
479 | static int mdacon_switch(struct vc_data *c) | ||
480 | { | ||
481 | return 1; /* redrawing needed */ | ||
482 | } | ||
483 | |||
484 | static int mdacon_set_palette(struct vc_data *c, unsigned char *table) | ||
485 | { | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) | ||
490 | { | ||
491 | if (mda_type == TYPE_MDA) { | ||
492 | if (blank) | ||
493 | scr_memsetw((void *)mda_vram_base, | ||
494 | mda_convert_attr(c->vc_video_erase_char), | ||
495 | c->vc_screenbuf_size); | ||
496 | /* Tell console.c that it has to restore the screen itself */ | ||
497 | return 1; | ||
498 | } else { | ||
499 | if (blank) | ||
500 | outb_p(0x00, mda_mode_port); /* disable video */ | ||
501 | else | ||
502 | outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, | ||
503 | mda_mode_port); | ||
504 | return 0; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | static int mdacon_scrolldelta(struct vc_data *c, int lines) | ||
509 | { | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static void mdacon_cursor(struct vc_data *c, int mode) | ||
514 | { | ||
515 | if (mode == CM_ERASE) { | ||
516 | mda_set_cursor(mda_vram_len - 1); | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2); | ||
521 | |||
522 | switch (c->vc_cursor_type & 0x0f) { | ||
523 | |||
524 | case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break; | ||
525 | case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break; | ||
526 | case CUR_TWO_THIRDS: mda_set_cursor_size(4, 13); break; | ||
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; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) | ||
534 | { | ||
535 | u16 eattr = mda_convert_attr(c->vc_video_erase_char); | ||
536 | |||
537 | if (!lines) | ||
538 | return 0; | ||
539 | |||
540 | if (lines > c->vc_rows) /* maximum realistic size */ | ||
541 | lines = c->vc_rows; | ||
542 | |||
543 | switch (dir) { | ||
544 | |||
545 | case SM_UP: | ||
546 | scr_memmovew(MDA_ADDR(0,t), MDA_ADDR(0,t+lines), | ||
547 | (b-t-lines)*mda_num_columns*2); | ||
548 | scr_memsetw(MDA_ADDR(0,b-lines), eattr, | ||
549 | lines*mda_num_columns*2); | ||
550 | break; | ||
551 | |||
552 | case SM_DOWN: | ||
553 | scr_memmovew(MDA_ADDR(0,t+lines), MDA_ADDR(0,t), | ||
554 | (b-t-lines)*mda_num_columns*2); | ||
555 | scr_memsetw(MDA_ADDR(0,t), eattr, lines*mda_num_columns*2); | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | |||
563 | /* | ||
564 | * The console `switch' structure for the MDA based console | ||
565 | */ | ||
566 | |||
567 | static const struct consw mda_con = { | ||
568 | .owner = THIS_MODULE, | ||
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, | ||
584 | }; | ||
585 | |||
586 | int __init mda_console_init(void) | ||
587 | { | ||
588 | if (mda_first_vc > mda_last_vc) | ||
589 | return 1; | ||
590 | |||
591 | return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); | ||
592 | } | ||
593 | |||
594 | static void __exit mda_console_exit(void) | ||
595 | { | ||
596 | give_up_console(&mda_con); | ||
597 | } | ||
598 | |||
599 | module_init(mda_console_init); | ||
600 | module_exit(mda_console_exit); | ||
601 | |||
602 | MODULE_LICENSE("GPL"); | ||
603 | |||