OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [console/] [vgacon.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.