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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [vga.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/drivers/char/vga.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 *                      1995  Jay Estabrook
6
 */
7
 
8
/*
9
 *      vga.c
10
 *
11
 * This module exports the console low-level io support for VGA
12
 *
13
 *     'int con_get_font(char *data)'
14
 *     'int con_set_font(char *data, int ch512)'
15
 *     'int con_adjust_height(int fontheight)'
16
 *
17
 *     'int con_get_cmap(char *)'
18
 *     'int con_set_cmap(char *)'
19
 *
20
 *     'int reset_palette(int currcons)'
21
 *     'void set_palette(void)'
22
 *
23
 * User definable mapping table and font loading by Eugene G. Crosser,
24
 * <crosser@pccross.msk.su>
25
 *
26
 * Improved loadable font/UTF-8 support by H. Peter Anvin
27
 * Feb-Sep 1995 <peter.anvin@linux.org>
28
 *
29
 * Colour palette handling, by Simon Tatham
30
 * 17-Jun-95 <sgt20@cam.ac.uk>
31
 *
32
 * if 512 char mode is already enabled don't re-enable it,
33
 * because it causes screen to flicker, by Mitja Horvat
34
 * 5-May-96 <mitja.horvat@guest.arnes.si>
35
 *
36
 */
37
 
38
#include <linux/sched.h>
39
#include <linux/timer.h>
40
#include <linux/interrupt.h>
41
#include <linux/tty.h>
42
#include <linux/tty_flip.h>
43
#include <linux/config.h>
44
#include <linux/kernel.h>
45
#include <linux/string.h>
46
#include <linux/errno.h>
47
#include <linux/kd.h>
48
#include <linux/malloc.h>
49
#include <linux/major.h>
50
#include <linux/mm.h>
51
#include <linux/ioport.h>
52
 
53
#include <asm/io.h>
54
#include <asm/system.h>
55
#include <asm/segment.h>
56
#include <asm/bitops.h>
57
 
58
#include "kbd_kern.h"
59
#include "vt_kern.h"
60
#include "consolemap.h"
61
#include "selection.h"
62
#include "console_struct.h"
63
 
64
#define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
65
#define CAN_LOAD_PALETTE      /* undefine if the user must not do this */
66
 
67
#define dac_reg (0x3c8)
68
#define dac_val (0x3c9)
69
 
70
 
71
void
72
set_palette (void)
73
{
74
        int i, j ;
75
 
76
        if (video_type != VIDEO_TYPE_VGAC || console_blanked ||
77
            vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
78
                return ;
79
 
80
        for (i=j=0; i<16; i++) {
81
                outb_p (color_table[i], dac_reg) ;
82
                outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
83
                outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
84
                outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
85
        }
86
}
87
 
88
void
89
__set_origin(unsigned short offset)
90
{
91
        unsigned long flags;
92
 
93
        clear_selection();
94
 
95
        save_flags(flags); cli();
96
        __origin = offset;
97
        outb_p(12, video_port_reg);
98
        outb_p(offset >> 8, video_port_val);
99
        outb_p(13, video_port_reg);
100
        outb_p(offset, video_port_val);
101
        restore_flags(flags);
102
}
103
 
104
/*
105
 * Put the cursor just beyond the end of the display adaptor memory.
106
 */
107
void
108
hide_cursor(void)
109
{
110
  /* This is inefficient, we could just put the cursor at 0xffff,
111
     but perhaps the delays due to the inefficiency are useful for
112
     some hardware... */
113
        outb_p(14, video_port_reg);
114
        outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
115
        outb_p(15, video_port_reg);
116
        outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
117
}
118
 
119
void
120
set_cursor(int currcons)
121
{
122
        unsigned long flags;
123
 
124
        if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
125
                return;
126
        if (__real_origin != __origin)
127
                __set_origin(__real_origin);
128
        save_flags(flags); cli();
129
        if (deccm) {
130
                outb_p(14, video_port_reg);
131
                outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
132
                outb_p(15, video_port_reg);
133
                outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
134
        } else
135
                hide_cursor();
136
        restore_flags(flags);
137
}
138
 
139
unsigned long
140
con_type_init(unsigned long kmem_start, const char **display_desc)
141
{
142
        if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
143
        {
144
                video_mem_base = 0xb0000;
145
                video_port_reg = 0x3b4;
146
                video_port_val = 0x3b5;
147
                if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
148
                {
149
                        video_type = VIDEO_TYPE_EGAM;
150
                        video_mem_term = 0xb8000;
151
                        *display_desc = "EGA+";
152
                        request_region(0x3b0,16,"ega");
153
                }
154
                else
155
                {
156
                        video_type = VIDEO_TYPE_MDA;
157
                        video_mem_term = 0xb2000;
158
                        *display_desc = "*MDA";
159
                        request_region(0x3b0,12,"mda");
160
                        request_region(0x3bf, 1,"mda");
161
                }
162
        }
163
        else                            /* If not, it is color. */
164
        {
165
                can_do_color = 1;
166
                video_mem_base = 0xb8000;
167
                video_port_reg  = 0x3d4;
168
                video_port_val  = 0x3d5;
169
                if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
170
                {
171
                        int i ;
172
 
173
                        video_mem_term = 0xc0000;
174
 
175
                        if (!ORIG_VIDEO_ISVGA) {
176
                                video_type = VIDEO_TYPE_EGAC;
177
                                *display_desc = "EGA";
178
                                request_region(0x3c0,32,"ega");
179
                        } else {
180
                                video_type = VIDEO_TYPE_VGAC;
181
                                *display_desc = "VGA+";
182
                                request_region(0x3c0,32,"vga+");
183
 
184
#ifdef VGA_CAN_DO_64KB
185
                                /*
186
                                 * get 64K rather than 32K of video RAM.
187
                                 * This doesn't actually work on all "VGA"
188
                                 * controllers (it seems like setting MM=01
189
                                 * and COE=1 isn't necessarily a good idea)
190
                                 */
191
                                video_mem_base = 0xa0000 ;
192
                                video_mem_term = 0xb0000 ;
193
                                outb_p (6, 0x3ce) ;
194
                                outb_p (6, 0x3cf) ;
195
#endif
196
 
197
                                /*
198
                                 * Normalise the palette registers, to point
199
                                 * the 16 screen colours to the first 16
200
                                 * DAC entries.
201
                                 */
202
 
203
                                for (i=0; i<16; i++) {
204
                                        inb_p (0x3da) ;
205
                                        outb_p (i, 0x3c0) ;
206
                                        outb_p (i, 0x3c0) ;
207
                                }
208
                                outb_p (0x20, 0x3c0) ;
209
 
210
                                /* now set the DAC registers back to their
211
                                 * default values */
212
 
213
                                for (i=0; i<16; i++) {
214
                                        outb_p (color_table[i], 0x3c8) ;
215
                                        outb_p (default_red[i], 0x3c9) ;
216
                                        outb_p (default_grn[i], 0x3c9) ;
217
                                        outb_p (default_blu[i], 0x3c9) ;
218
                                }
219
                        }
220
                }
221
                else
222
                {
223
                        video_type = VIDEO_TYPE_CGA;
224
                        video_mem_term = 0xba000;
225
                        *display_desc = "*CGA";
226
                        request_region(0x3d4,2,"cga");
227
                }
228
        }
229
        return kmem_start;
230
}
231
 
232
void
233
get_scrmem(int currcons)
234
{
235
        memcpyw((unsigned short *)vc_scrbuf[currcons],
236
                (unsigned short *)origin, video_screen_size);
237
        origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
238
        scr_end = video_mem_end = video_mem_start + video_screen_size;
239
        pos = origin + y*video_size_row + (x<<1);
240
}
241
 
242
void
243
set_scrmem(int currcons, long offset)
244
{
245
#ifdef CONFIG_HGA
246
  /* This works with XFree86 1.2, 1.3 and 2.0
247
     This code could be extended and made more generally useful if we could
248
     determine the actual video mode. It appears that this should be
249
     possible on a genuine Hercules card, but I (WM) haven't been able to
250
     read from any of the required registers on my clone card.
251
     */
252
        /* This code should work with Hercules and MDA cards. */
253
        if (video_type == VIDEO_TYPE_MDA)
254
          {
255
            if (vcmode == KD_TEXT)
256
              {
257
                /* Ensure that the card is in text mode. */
258
                int     i;
259
                static char herc_txt_tbl[12] = {
260
                  0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
261
                outb_p(0, 0x3bf);  /* Back to power-on defaults */
262
                outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
263
                for ( i = 0 ; i < 12 ; i++ )
264
                  {
265
                    outb_p(i, 0x3b4);
266
                    outb_p(herc_txt_tbl[i], 0x3b5);
267
                  }
268
              }
269
#define HGA_BLINKER_ON 0x20
270
#define HGA_SCREEN_ON  8
271
            /* Make sure that the hardware is not blanked */
272
            outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
273
          }
274
#endif CONFIG_HGA
275
 
276
        if (video_mem_term - video_mem_base < offset + video_screen_size)
277
          offset = 0;    /* strange ... */
278
        memcpyw((unsigned short *)(video_mem_base + offset),
279
                (unsigned short *) origin, video_screen_size);
280
        video_mem_start = video_mem_base;
281
        video_mem_end = video_mem_term;
282
        origin = video_mem_base + offset;
283
        scr_end = origin + video_screen_size;
284
        pos = origin + y*video_size_row + (x<<1);
285
        has_wrapped = 0;
286
}
287
 
288
/*
289
 * PIO_FONT support.
290
 *
291
 * The font loading code goes back to the codepage package by
292
 * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
293
 * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
294
 * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
295
 *
296
 * Change for certain monochrome monitors by Yury Shevchuck
297
 * (sizif@botik.yaroslavl.su).
298
 */
299
 
300
#define colourmap ((char *)0xa0000)
301
/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
302
   should use 0xA0000 for the bwmap as well.. */
303
#define blackwmap ((char *)0xa0000)
304
#define cmapsz 8192
305
#define attrib_port (0x3c0)
306
#define seq_port_reg (0x3c4)
307
#define seq_port_val (0x3c5)
308
#define gr_port_reg (0x3ce)
309
#define gr_port_val (0x3cf)
310
 
311
int
312
set_get_font(char * arg, int set, int ch512)
313
{
314
#ifdef CAN_LOAD_EGA_FONTS
315
        static int ch512enabled = 0;
316
        int i;
317
        char *charmap;
318
        int beg;
319
        unsigned short video_port_status = video_port_reg + 6;
320
        int font_select = 0x00;
321
 
322
        /* no use to "load" CGA... */
323
 
324
        if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_VGAC) {
325
                charmap = colourmap;
326
                beg = 0x0e;
327
#ifdef VGA_CAN_DO_64KB
328
                if (video_type == VIDEO_TYPE_VGAC)
329
                        beg = 0x06;
330
#endif
331
        } else if (video_type == VIDEO_TYPE_EGAM) {
332
                charmap = blackwmap;
333
                beg = 0x0a;
334
        } else
335
                return -EINVAL;
336
 
337
        if (arg)
338
          {
339
            i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg,
340
                            ch512 ? 2*cmapsz : cmapsz);
341
            if (i)
342
              return i;
343
          }
344
        else
345
          ch512 = 0;             /* Default font is always 256 */
346
 
347
#ifdef BROKEN_GRAPHICS_PROGRAMS
348
        /*
349
         * All fonts are loaded in slot 0 (0:1 for 512 ch)
350
         */
351
 
352
        if (!arg)
353
          return -EINVAL;       /* Return to default font not supported */
354
 
355
        video_font_is_default = 0;
356
        font_select = ch512 ? 0x04 : 0x00;
357
#else   
358
        /*
359
         * The default font is kept in slot 0 and is never touched.
360
         * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
361
         */
362
 
363
        if (set)
364
          {
365
            video_font_is_default = !arg;
366
            font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
367
          }
368
 
369
        if ( !video_font_is_default )
370
          charmap += 4*cmapsz;
371
#endif
372
 
373
        cli();
374
        outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
375
        outb_p( 0x01, seq_port_val );   /* Synchronous reset */
376
        outb_p( 0x02, seq_port_reg );
377
        outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
378
        outb_p( 0x04, seq_port_reg );
379
        outb_p( 0x07, seq_port_val );   /* Sequential addressing */
380
        outb_p( 0x00, seq_port_reg );
381
        outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
382
 
383
        outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
384
        outb_p( 0x02, gr_port_val );    /* select map 2 */
385
        outb_p( 0x05, gr_port_reg );
386
        outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
387
        outb_p( 0x06, gr_port_reg );
388
        outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
389
        sti();
390
 
391
        if (arg)
392
          {
393
            if (set)
394
              for (i=0; i<cmapsz ; i++)
395
                scr_writeb(get_user(arg + i), charmap + i);
396
            else
397
              for (i=0; i<cmapsz ; i++)
398
                put_user(scr_readb(charmap + i), arg + i);
399
 
400
 
401
        /*
402
         * In 512-character mode, the character map is not contiguous if
403
         * we want to remain EGA compatible -- which we do
404
         */
405
 
406
            if (ch512)
407
              {
408
                charmap += 2*cmapsz;
409
                arg += cmapsz;
410
                if (set)
411
                  for (i=0; i<cmapsz ; i++)
412
                    *(charmap+i) = get_user(arg+i);
413
                else
414
                  for (i=0; i<cmapsz ; i++)
415
                    put_user(*(charmap+i), arg+i);
416
              }
417
          }
418
 
419
        cli();
420
        outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
421
        outb_p( 0x01, seq_port_val );   /* Synchronous reset */
422
        outb_p( 0x02, seq_port_reg );
423
        outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
424
        outb_p( 0x04, seq_port_reg );
425
        outb_p( 0x03, seq_port_val );   /* odd-even addressing */
426
        if (set)
427
          {
428
            outb_p( 0x03, seq_port_reg ); /* Character Map Select */
429
            outb_p( font_select, seq_port_val );
430
          }
431
        outb_p( 0x00, seq_port_reg );
432
        outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
433
 
434
        outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
435
        outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
436
        outb_p( 0x05, gr_port_reg );
437
        outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
438
        outb_p( 0x06, gr_port_reg );
439
        outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
440
 
441
        /* if 512 char mode is already enabled don't re-enable it. */
442
        if ((set)&&(ch512!=ch512enabled))       /* attribute controller */
443
          {
444
            ch512enabled=ch512;
445
            /* 256-char: enable intensity bit
446
               512-char: disable intensity bit */
447
            inb_p( video_port_status ); /* clear address flip-flop */
448
            outb_p ( 0x12, attrib_port ); /* color plane enable register */
449
            outb_p ( ch512 ? 0x07 : 0x0f, attrib_port );
450
            /* Wilton (1987) mentions the following; I don't know what
451
               it means, but it works, and it appears necessary */
452
            inb_p( video_port_status );
453
            outb_p ( 0x20, attrib_port );
454
          }
455
        sti();
456
 
457
        return 0;
458
#else
459
        return -EINVAL;
460
#endif
461
}
462
 
463
/*
464
 * Adjust the screen to fit a font of a certain height
465
 *
466
 * Returns < 0 for error, 0 if nothing changed, and the number
467
 * of lines on the adjusted console if changed.
468
 */
469
int
470
con_adjust_height(unsigned long fontheight)
471
{
472
        int rows, maxscan;
473
        unsigned char ovr, vde, fsr, curs, cure;
474
 
475
        if (fontheight > 32 || (video_type != VIDEO_TYPE_VGAC &&
476
            video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM))
477
                return -EINVAL;
478
 
479
        if ( fontheight == video_font_height || fontheight == 0 )
480
                return 0;
481
 
482
        video_font_height = fontheight;
483
 
484
        rows = video_scan_lines/fontheight;     /* Number of video rows we end up with */
485
        maxscan = rows*fontheight - 1;          /* Scan lines to actually display-1 */
486
 
487
        /* Reprogram the CRTC for the new font size
488
           Note: the attempt to read the overflow register will fail
489
           on an EGA, but using 0xff for the previous value appears to
490
           be OK for EGA text modes in the range 257-512 scan lines, so I
491
           guess we don't need to worry about it.
492
 
493
           The same applies for the spill bits in the font size and cursor
494
           registers; they are write-only on EGA, but it appears that they
495
           are all don't care bits on EGA, so I guess it doesn't matter. */
496
 
497
        cli();
498
        outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
499
        ovr = inb_p(video_port_val);
500
        outb_p( 0x09, video_port_reg );         /* Font size register */
501
        fsr = inb_p(video_port_val);
502
        outb_p( 0x0a, video_port_reg );         /* Cursor start */
503
        curs = inb_p(video_port_val);
504
        outb_p( 0x0b, video_port_reg );         /* Cursor end */
505
        cure = inb_p(video_port_val);
506
        sti();
507
 
508
        vde = maxscan & 0xff;                   /* Vertical display end reg */
509
        ovr = (ovr & 0xbd) +                    /* Overflow register */
510
              ((maxscan & 0x100) >> 7) +
511
              ((maxscan & 0x200) >> 3);
512
        fsr = (fsr & 0xe0) + (fontheight-1);    /*  Font size register */
513
        curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
514
        cure = (cure & 0xe0) + fontheight - (fontheight < 10 ? 1 : 2);
515
 
516
        cli();
517
        outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
518
        outb_p( ovr, video_port_val );
519
        outb_p( 0x09, video_port_reg );         /* Font size */
520
        outb_p( fsr, video_port_val );
521
        outb_p( 0x0a, video_port_reg );         /* Cursor start */
522
        outb_p( curs, video_port_val );
523
        outb_p( 0x0b, video_port_reg );         /* Cursor end */
524
        outb_p( cure, video_port_val );
525
        outb_p( 0x12, video_port_reg );         /* Vertical display limit */
526
        outb_p( vde, video_port_val );
527
        sti();
528
 
529
        if ( rows == video_num_lines ) {
530
          /* Change didn't affect number of lines -- no need to scare
531
             the rest of the world */
532
          return 0;
533
        }
534
 
535
        vc_resize(rows, 0);                      /* Adjust console size */
536
 
537
        return rows;
538
}
539
 
540
int
541
set_get_cmap(unsigned char * arg, int set) {
542
#ifdef CAN_LOAD_PALETTE
543
        int i;
544
 
545
        /* no use to set colourmaps in less than colour VGA */
546
 
547
        if (video_type != VIDEO_TYPE_VGAC)
548
                return -EINVAL;
549
 
550
        i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
551
        if (i)
552
                return i;
553
 
554
        for (i=0; i<16; i++) {
555
                if (set) {
556
                        default_red[i] = get_user(arg++) ;
557
                        default_grn[i] = get_user(arg++) ;
558
                        default_blu[i] = get_user(arg++) ;
559
                } else {
560
                        put_user (default_red[i], arg++) ;
561
                        put_user (default_grn[i], arg++) ;
562
                        put_user (default_blu[i], arg++) ;
563
                }
564
        }
565
        if (set) {
566
                for (i=0; i<MAX_NR_CONSOLES; i++)
567
                        if (vc_cons_allocated(i)) {
568
                                int j, k ;
569
                                for (j=k=0; j<16; j++) {
570
                                        vc_cons[i].d->vc_palette[k++] = default_red[j];
571
                                        vc_cons[i].d->vc_palette[k++] = default_grn[j];
572
                                        vc_cons[i].d->vc_palette[k++] = default_blu[j];
573
                                }
574
                        }
575
                set_palette() ;
576
        }
577
 
578
        return 0;
579
#else
580
        return -EINVAL;
581
#endif
582
}

powered by: WebSVN 2.1.0

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