~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/vgacon.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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/config.h>
 37 #include <linux/types.h>
 38 #include <linux/sched.h>
 39 #include <linux/fs.h>
 40 #include <linux/kernel.h>
 41 #include <linux/tty.h>
 42 #include <linux/console.h>
 43 #include <linux/console_struct.h>
 44 #include <linux/string.h>
 45 #include <linux/kd.h>
 46 #include <linux/malloc.h>
 47 #include <linux/vt_kern.h>
 48 #include <linux/selection.h>
 49 #include <linux/spinlock.h>
 50 #include <linux/ioport.h>
 51 #include <linux/init.h>
 52 
 53 #include <asm/io.h>
 54 
 55 static spinlock_t vga_lock = SPIN_LOCK_UNLOCKED;
 56 
 57 #define BLANK 0x0020
 58 
 59 #define CAN_LOAD_EGA_FONTS      /* undefine if the user must not do this */
 60 #define CAN_LOAD_PALETTE        /* undefine if the user must not do this */
 61 
 62 /* You really do _NOT_ want to define this, unless you have buggy
 63  * Trident VGA which will resize cursor when moving it between column
 64  * 15 & 16. If you define this and your VGA is OK, inverse bug will
 65  * appear.
 66  */
 67 #undef TRIDENT_GLITCH
 68 
 69 #define dac_reg         0x3c8
 70 #define dac_val         0x3c9
 71 #define attrib_port     0x3c0
 72 #define seq_port_reg    0x3c4
 73 #define seq_port_val    0x3c5
 74 #define gr_port_reg     0x3ce
 75 #define gr_port_val     0x3cf
 76 #define video_misc_rd   0x3cc
 77 #define video_misc_wr   0x3c2
 78 
 79 /*
 80  *  Interface used by the world
 81  */
 82 
 83 static const char *vgacon_startup(void);
 84 static void vgacon_init(struct vc_data *c, int init);
 85 static void vgacon_deinit(struct vc_data *c);
 86 static void vgacon_cursor(struct vc_data *c, int mode);
 87 static int vgacon_switch(struct vc_data *c);
 88 static int vgacon_blank(struct vc_data *c, int blank);
 89 static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);
 90 static int vgacon_set_palette(struct vc_data *c, unsigned char *table);
 91 static int vgacon_scrolldelta(struct vc_data *c, int lines);
 92 static int vgacon_set_origin(struct vc_data *c);
 93 static void vgacon_save_screen(struct vc_data *c);
 94 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines);
 95 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);
 96 static void vgacon_invert_region(struct vc_data *c, u16 *p, int count);
 97 static unsigned long vgacon_uni_pagedir[2];
 98 
 99 
100 /* Description of the hardware situation */
101 static unsigned long   vga_vram_base;           /* Base of video memory */
102 static unsigned long   vga_vram_end;            /* End of video memory */
103 static u16             vga_video_port_reg;      /* Video register select port */
104 static u16             vga_video_port_val;      /* Video register value port */
105 static unsigned int    vga_video_num_columns;   /* Number of text columns */
106 static unsigned int    vga_video_num_lines;     /* Number of text lines */
107 static int             vga_can_do_color = 0;    /* Do we support colors? */
108 static unsigned int    vga_default_font_height; /* Height of default screen font */
109 static unsigned char   vga_video_type;          /* Card type */
110 static unsigned char   vga_hardscroll_enabled;
111 #ifdef CONFIG_IA64_SOFTSDV_HACKS
112 /*
113  * SoftSDV doesn't have hardware assist VGA scrolling 
114  */
115 static unsigned char   vga_hardscroll_user_enable = 0;
116 #else
117 static unsigned char   vga_hardscroll_user_enable = 1;
118 #endif
119 static unsigned char   vga_font_is_default = 1;
120 static int             vga_vesa_blanked;
121 static int             vga_palette_blanked;
122 static int             vga_is_gfx;
123 static int             vga_512_chars;
124 static int             vga_video_font_height;
125 static unsigned int    vga_rolled_over = 0;
126 
127 
128 static int __init no_scroll(char *str)
129 {
130         /*
131          * Disabling scrollback is required for the Braillex ib80-piezo
132          * Braille reader made by F.H. Papenmeier (Germany).
133          * Use the "no-scroll" bootflag.
134          */
135         vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
136         return 1;
137 }
138 
139 __setup("no-scroll", no_scroll);
140 
141 /*
142  * By replacing the four outb_p with two back to back outw, we can reduce
143  * the window of opportunity to see text mislocated to the RHS of the
144  * console during heavy scrolling activity. However there is the remote
145  * possibility that some pre-dinosaur hardware won't like the back to back
146  * I/O. Since the Xservers get away with it, we should be able to as well.
147  */
148 static inline void write_vga(unsigned char reg, unsigned int val)
149 {
150         unsigned int v1, v2;
151         unsigned long flags;
152 
153         /*
154          * ddprintk might set the console position from interrupt
155          * handlers, thus the write has to be IRQ-atomic.
156          */
157         spin_lock_irqsave(&vga_lock, flags);    
158 
159 #ifndef SLOW_VGA
160         v1 = reg + (val & 0xff00);
161         v2 = reg + 1 + ((val << 8) & 0xff00);
162         outw(v1, vga_video_port_reg);
163         outw(v2, vga_video_port_reg);
164 #else
165         outb_p(reg, vga_video_port_reg);
166         outb_p(val >> 8, vga_video_port_val);
167         outb_p(reg+1, vga_video_port_reg);
168         outb_p(val & 0xff, vga_video_port_val);
169 #endif
170         spin_unlock_irqrestore(&vga_lock, flags);
171 }
172 
173 static const char __init *vgacon_startup(void)
174 {
175         const char *display_desc = NULL;
176         u16 saved1, saved2;
177         volatile u16 *p;
178 
179         if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
180         no_vga:
181 #ifdef CONFIG_DUMMY_CONSOLE
182                 conswitchp = &dummy_con;
183                 return conswitchp->con_startup();
184 #else
185                 return NULL;
186 #endif
187         }
188 
189 
190         vga_video_num_lines = ORIG_VIDEO_LINES;
191         vga_video_num_columns = ORIG_VIDEO_COLS;
192 
193         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
194         {
195                 vga_vram_base = 0xb0000;
196                 vga_video_port_reg = 0x3b4;
197                 vga_video_port_val = 0x3b5;
198                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
199                 {
200                         static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF };
201                         vga_video_type = VIDEO_TYPE_EGAM;
202                         vga_vram_end = 0xb8000;
203                         display_desc = "EGA+";
204                         request_resource(&ioport_resource, &ega_console_resource);
205                 }
206                 else
207                 {
208                         static struct resource mda1_console_resource = { "mda", 0x3B0, 0x3BB };
209                         static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF };
210                         vga_video_type = VIDEO_TYPE_MDA;
211                         vga_vram_end = 0xb2000;
212                         display_desc = "*MDA";
213                         request_resource(&ioport_resource, &mda1_console_resource);
214                         request_resource(&ioport_resource, &mda2_console_resource);
215                         vga_video_font_height = 14;
216                 }
217         }
218         else                            /* If not, it is color. */
219         {
220                 vga_can_do_color = 1;
221                 vga_vram_base = 0xb8000;
222                 vga_video_port_reg = 0x3d4;
223                 vga_video_port_val = 0x3d5;
224                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
225                 {
226                         int i;
227 
228                         vga_vram_end = 0xc0000;
229 
230                         if (!ORIG_VIDEO_ISVGA) {
231                                 static struct resource ega_console_resource = { "ega", 0x3C0, 0x3DF };
232                                 vga_video_type = VIDEO_TYPE_EGAC;
233                                 display_desc = "EGA";
234                                 request_resource(&ioport_resource, &ega_console_resource);
235                         } else {
236                                 static struct resource vga_console_resource = { "vga+", 0x3C0, 0x3DF };
237                                 vga_video_type = VIDEO_TYPE_VGAC;
238                                 display_desc = "VGA+";
239                                 request_resource(&ioport_resource, &vga_console_resource);
240 
241 #ifdef VGA_CAN_DO_64KB
242                                 /*
243                                  * get 64K rather than 32K of video RAM.
244                                  * This doesn't actually work on all "VGA"
245                                  * controllers (it seems like setting MM=01
246                                  * and COE=1 isn't necessarily a good idea)
247                                  */
248                                 vga_vram_base = 0xa0000;
249                                 vga_vram_end = 0xb0000;
250                                 outb_p (6, 0x3ce) ;
251                                 outb_p (6, 0x3cf) ;
252 #endif
253 
254                                 /*
255                                  * Normalise the palette registers, to point
256                                  * the 16 screen colours to the first 16
257                                  * DAC entries.
258                                  */
259 
260                                 for (i=0; i<16; i++) {
261                                         inb_p (0x3da) ;
262                                         outb_p (i, 0x3c0) ;
263                                         outb_p (i, 0x3c0) ;
264                                 }
265                                 outb_p (0x20, 0x3c0) ;
266 
267                                 /* now set the DAC registers back to their
268                                  * default values */
269 
270                                 for (i=0; i<16; i++) {
271                                         outb_p (color_table[i], 0x3c8) ;
272                                         outb_p (default_red[i], 0x3c9) ;
273                                         outb_p (default_grn[i], 0x3c9) ;
274                                         outb_p (default_blu[i], 0x3c9) ;
275                                 }
276                         }
277                 }
278                 else
279                 {
280                         static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 };
281                         vga_video_type = VIDEO_TYPE_CGA;
282                         vga_vram_end = 0xba000;
283                         display_desc = "*CGA";
284                         request_resource(&ioport_resource, &cga_console_resource);
285                         vga_video_font_height = 8;
286                 }
287         }
288 
289         vga_vram_base = VGA_MAP_MEM(vga_vram_base);
290         vga_vram_end = VGA_MAP_MEM(vga_vram_end);
291 
292         /*
293          *      Find out if there is a graphics card present.
294          *      Are there smarter methods around?
295          */
296         p = (volatile u16 *)vga_vram_base;
297         saved1 = scr_readw(p);
298         saved2 = scr_readw(p + 1);
299         scr_writew(0xAA55, p);
300         scr_writew(0x55AA, p + 1);
301         if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
302                 scr_writew(saved1, p);
303                 scr_writew(saved2, p + 1);
304                 goto no_vga;
305         }
306         scr_writew(0x55AA, p);
307         scr_writew(0xAA55, p + 1);
308         if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
309                 scr_writew(saved1, p);
310                 scr_writew(saved2, p + 1);
311                 goto no_vga;
312         }
313         scr_writew(saved1, p);
314         scr_writew(saved2, p + 1);
315 
316         if (vga_video_type == VIDEO_TYPE_EGAC
317             || vga_video_type == VIDEO_TYPE_VGAC
318             || vga_video_type == VIDEO_TYPE_EGAM) {
319                 vga_hardscroll_enabled = vga_hardscroll_user_enable;
320                 vga_default_font_height = ORIG_VIDEO_POINTS;
321                 vga_video_font_height = ORIG_VIDEO_POINTS;
322                 /* This may be suboptimal but is a safe bet - go with it */
323                 video_scan_lines =
324                         vga_video_font_height * vga_video_num_lines;
325         }
326         video_font_height = vga_video_font_height;
327 
328         return display_desc;
329 }
330 
331 static void vgacon_init(struct vc_data *c, int init)
332 {
333         unsigned long p;
334         
335         /* We cannot be loaded as a module, therefore init is always 1 */
336         c->vc_can_do_color = vga_can_do_color;
337         c->vc_cols = vga_video_num_columns;
338         c->vc_rows = vga_video_num_lines;
339         c->vc_complement_mask = 0x7700;
340         p = *c->vc_uni_pagedir_loc;
341         if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||
342             !--c->vc_uni_pagedir_loc[1])
343                 con_free_unimap(c->vc_num);
344         c->vc_uni_pagedir_loc = vgacon_uni_pagedir;
345         vgacon_uni_pagedir[1]++;
346         if (!vgacon_uni_pagedir[0] && p)
347                 con_set_default_unimap(c->vc_num);
348 }
349 
350 static inline void vga_set_mem_top(struct vc_data *c)
351 {
352         write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
353 }
354 
355 static void vgacon_deinit(struct vc_data *c)
356 {
357         /* When closing the last console, reset video origin */
358         if (!--vgacon_uni_pagedir[1]) {
359                 c->vc_visible_origin = vga_vram_base;
360                 vga_set_mem_top(c);
361                 con_free_unimap(c->vc_num);
362         }
363         c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
364         con_set_default_unimap(c->vc_num);
365 }
366 
367 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse)
368 {
369         u8 attr = color;
370 
371         if (vga_can_do_color) {
372                 if (underline)
373                         attr = (attr & 0xf0) | c->vc_ulcolor;
374                 else if (intensity == 0)
375                         attr = (attr & 0xf0) | c->vc_halfcolor;
376         }
377         if (reverse)
378                 attr = ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 0x77);
379         if (blink)
380                 attr ^= 0x80;
381         if (intensity == 2)
382                 attr ^= 0x08;
383         if (!vga_can_do_color) {
384                 if (underline)
385                         attr = (attr & 0xf8) | 0x01;
386                 else if (intensity == 0)
387                         attr = (attr & 0xf0) | 0x08;
388         }
389         return attr;
390 }
391 
392 static void vgacon_invert_region(struct vc_data *c, u16 *p, int count)
393 {
394         int col = vga_can_do_color;
395 
396         while (count--) {
397                 u16 a = scr_readw(p);
398                 if (col)
399                         a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
400                 else
401                         a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
402                 scr_writew(a, p++);
403         }
404 }
405 
406 static void vgacon_set_cursor_size(int xpos, int from, int to)
407 {
408         unsigned long flags;
409         int curs, cure;
410         static int lastfrom, lastto;
411 
412 #ifdef TRIDENT_GLITCH
413         if (xpos<16) from--, to--;
414 #endif
415 
416         if ((from == lastfrom) && (to == lastto)) return;
417         lastfrom = from; lastto = to;
418 
419         spin_lock_irqsave(&vga_lock, flags);
420         outb_p(0x0a, vga_video_port_reg);               /* Cursor start */
421         curs = inb_p(vga_video_port_val);
422         outb_p(0x0b, vga_video_port_reg);               /* Cursor end */
423         cure = inb_p(vga_video_port_val);
424 
425         curs = (curs & 0xc0) | from;
426         cure = (cure & 0xe0) | to;
427 
428         outb_p(0x0a, vga_video_port_reg);               /* Cursor start */
429         outb_p(curs, vga_video_port_val);
430         outb_p(0x0b, vga_video_port_reg);               /* Cursor end */
431         outb_p(cure, vga_video_port_val);
432         spin_unlock_irqrestore(&vga_lock, flags);
433 }
434 
435 static void vgacon_cursor(struct vc_data *c, int mode)
436 {
437     if (c->vc_origin != c->vc_visible_origin)
438         vgacon_scrolldelta(c, 0);
439     switch (mode) {
440         case CM_ERASE:
441             write_vga(14, (vga_vram_end - vga_vram_base - 1)/2);
442             break;
443 
444         case CM_MOVE:
445         case CM_DRAW:
446             write_vga(14, (c->vc_pos-vga_vram_base)/2);
447             switch (c->vc_cursor_type & 0x0f) {
448                 case CUR_UNDERLINE:
449                         vgacon_set_cursor_size(c->vc_x, 
450                                         video_font_height - (video_font_height < 10 ? 2 : 3),
451                                         video_font_height - (video_font_height < 10 ? 1 : 2));
452                         break;
453                 case CUR_TWO_THIRDS:
454                         vgacon_set_cursor_size(c->vc_x, 
455                                          video_font_height / 3,
456                                          video_font_height - (video_font_height < 10 ? 1 : 2));
457                         break;
458                 case CUR_LOWER_THIRD:
459                         vgacon_set_cursor_size(c->vc_x, 
460                                          (video_font_height*2) / 3,
461                                          video_font_height - (video_font_height < 10 ? 1 : 2));
462                         break;
463                 case CUR_LOWER_HALF:
464                         vgacon_set_cursor_size(c->vc_x, 
465                                          video_font_height / 2,
466                                          video_font_height - (video_font_height < 10 ? 1 : 2));
467                         break;
468                 case CUR_NONE:
469                         vgacon_set_cursor_size(c->vc_x, 31, 30);
470                         break;
471                 default:
472                         vgacon_set_cursor_size(c->vc_x, 1, video_font_height);
473                         break;
474                 }
475             break;
476     }
477 }
478 
479 static int vgacon_switch(struct vc_data *c)
480 {
481         /*
482          * We need to save screen size here as it's the only way
483          * we can spot the screen has been resized and we need to
484          * set size of freshly allocated screens ourselves.
485          */
486         vga_video_num_columns = c->vc_cols;
487         vga_video_num_lines = c->vc_rows;
488         if (!vga_is_gfx)
489                 scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size);
490         return 0;       /* Redrawing not needed */
491 }
492 
493 static void vga_set_palette(struct vc_data *c, unsigned char *table)
494 {
495         int i, j ;
496 
497         for (i=j=0; i<16; i++) {
498                 outb_p (table[i], dac_reg) ;
499                 outb_p (c->vc_palette[j++]>>2, dac_val) ;
500                 outb_p (c->vc_palette[j++]>>2, dac_val) ;
501                 outb_p (c->vc_palette[j++]>>2, dac_val) ;
502         }
503 }
504 
505 static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
506 {
507 #ifdef CAN_LOAD_PALETTE
508         if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !CON_IS_VISIBLE(c))
509                 return -EINVAL;
510         vga_set_palette(c, table);
511         return 0;
512 #else
513         return -EINVAL;
514 #endif
515 }
516 
517 /* structure holding original VGA register settings */
518 static struct {
519         unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
520         unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
521         unsigned char   CrtMiscIO;              /* Miscellaneous register */
522         unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
523         unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
524         unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
525         unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
526         unsigned char   Overflow;               /* CRT-Controller:07h */
527         unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
528         unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
529         unsigned char   ModeControl;            /* CRT-Controller:17h */
530         unsigned char   ClockingMode;           /* Seq-Controller:01h */
531 } vga_state;
532 
533 static void vga_vesa_blank(int mode)
534 {
535         /* save original values of VGA controller registers */
536         if(!vga_vesa_blanked) {
537                 spin_lock_irq(&vga_lock);
538                 vga_state.SeqCtrlIndex = inb_p(seq_port_reg);
539                 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
540                 vga_state.CrtMiscIO = inb_p(video_misc_rd);
541                 spin_unlock_irq(&vga_lock);
542 
543                 outb_p(0x00,vga_video_port_reg);        /* HorizontalTotal */
544                 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
545                 outb_p(0x01,vga_video_port_reg);        /* HorizDisplayEnd */
546                 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
547                 outb_p(0x04,vga_video_port_reg);        /* StartHorizRetrace */
548                 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
549                 outb_p(0x05,vga_video_port_reg);        /* EndHorizRetrace */
550                 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
551                 outb_p(0x07,vga_video_port_reg);        /* Overflow */
552                 vga_state.Overflow = inb_p(vga_video_port_val);
553                 outb_p(0x10,vga_video_port_reg);        /* StartVertRetrace */
554                 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
555                 outb_p(0x11,vga_video_port_reg);        /* EndVertRetrace */
556                 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
557                 outb_p(0x17,vga_video_port_reg);        /* ModeControl */
558                 vga_state.ModeControl = inb_p(vga_video_port_val);
559                 outb_p(0x01,seq_port_reg);              /* ClockingMode */
560                 vga_state.ClockingMode = inb_p(seq_port_val);
561         }
562 
563         /* assure that video is enabled */
564         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
565         spin_lock_irq(&vga_lock);
566         outb_p(0x01,seq_port_reg);
567         outb_p(vga_state.ClockingMode | 0x20,seq_port_val);
568 
569         /* test for vertical retrace in process.... */
570         if ((vga_state.CrtMiscIO & 0x80) == 0x80)
571                 outb_p(vga_state.CrtMiscIO & 0xef,video_misc_wr);
572 
573         /*
574          * Set <End of vertical retrace> to minimum (0) and
575          * <Start of vertical Retrace> to maximum (incl. overflow)
576          * Result: turn off vertical sync (VSync) pulse.
577          */
578         if (mode & VESA_VSYNC_SUSPEND) {
579                 outb_p(0x10,vga_video_port_reg);        /* StartVertRetrace */
580                 outb_p(0xff,vga_video_port_val);        /* maximum value */
581                 outb_p(0x11,vga_video_port_reg);        /* EndVertRetrace */
582                 outb_p(0x40,vga_video_port_val);        /* minimum (bits 0..3)  */
583                 outb_p(0x07,vga_video_port_reg);        /* Overflow */
584                 outb_p(vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
585         }
586 
587         if (mode & VESA_HSYNC_SUSPEND) {
588                 /*
589                  * Set <End of horizontal retrace> to minimum (0) and
590                  *  <Start of horizontal Retrace> to maximum
591                  * Result: turn off horizontal sync (HSync) pulse.
592                  */
593                 outb_p(0x04,vga_video_port_reg);        /* StartHorizRetrace */
594                 outb_p(0xff,vga_video_port_val);        /* maximum */
595                 outb_p(0x05,vga_video_port_reg);        /* EndHorizRetrace */
596                 outb_p(0x00,vga_video_port_val);        /* minimum (0) */
597         }
598 
599         /* restore both index registers */
600         outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
601         outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
602         spin_unlock_irq(&vga_lock);
603 }
604 
605 static void vga_vesa_unblank(void)
606 {
607         /* restore original values of VGA controller registers */
608         spin_lock_irq(&vga_lock);
609         outb_p(vga_state.CrtMiscIO,video_misc_wr);
610 
611         outb_p(0x00,vga_video_port_reg);                /* HorizontalTotal */
612         outb_p(vga_state.HorizontalTotal,vga_video_port_val);
613         outb_p(0x01,vga_video_port_reg);                /* HorizDisplayEnd */
614         outb_p(vga_state.HorizDisplayEnd,vga_video_port_val);
615         outb_p(0x04,vga_video_port_reg);                /* StartHorizRetrace */
616         outb_p(vga_state.StartHorizRetrace,vga_video_port_val);
617         outb_p(0x05,vga_video_port_reg);                /* EndHorizRetrace */
618         outb_p(vga_state.EndHorizRetrace,vga_video_port_val);
619         outb_p(0x07,vga_video_port_reg);                /* Overflow */
620         outb_p(vga_state.Overflow,vga_video_port_val);
621         outb_p(0x10,vga_video_port_reg);                /* StartVertRetrace */
622         outb_p(vga_state.StartVertRetrace,vga_video_port_val);
623         outb_p(0x11,vga_video_port_reg);                /* EndVertRetrace */
624         outb_p(vga_state.EndVertRetrace,vga_video_port_val);
625         outb_p(0x17,vga_video_port_reg);                /* ModeControl */
626         outb_p(vga_state.ModeControl,vga_video_port_val);
627         outb_p(0x01,seq_port_reg);              /* ClockingMode */
628         outb_p(vga_state.ClockingMode,seq_port_val);
629 
630         /* restore index/control registers */
631         outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
632         outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
633         spin_unlock_irq(&vga_lock);
634 }
635 
636 static void vga_pal_blank(void)
637 {
638         int i;
639 
640         for (i=0; i<16; i++) {
641                 outb_p (i, dac_reg) ;
642                 outb_p (0, dac_val) ;
643                 outb_p (0, dac_val) ;
644                 outb_p (0, dac_val) ;
645         }
646 }
647 
648 static int vgacon_blank(struct vc_data *c, int blank)
649 {
650         switch (blank) {
651         case 0:                         /* Unblank */
652                 if (vga_vesa_blanked) {
653                         vga_vesa_unblank();
654                         vga_vesa_blanked = 0;
655                 }
656                 if (vga_palette_blanked) {
657                         vga_set_palette(c, color_table);
658                         vga_palette_blanked = 0;
659                         return 0;
660                 }
661                 vga_is_gfx = 0;
662                 /* Tell console.c that it has to restore the screen itself */
663                 return 1;
664         case 1:                         /* Normal blanking */
665                 if (vga_video_type == VIDEO_TYPE_VGAC) {
666                         vga_pal_blank();
667                         vga_palette_blanked = 1;
668                         return 0;
669                 }
670                 vgacon_set_origin(c);
671                 scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
672                 return 1;
673         case -1:                        /* Entering graphic mode */
674                 scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
675                 vga_is_gfx = 1;
676                 return 1;
677         default:                        /* VESA blanking */
678                 if (vga_video_type == VIDEO_TYPE_VGAC) {
679                         vga_vesa_blank(blank-1);
680                         vga_vesa_blanked = blank;
681                 }
682                 return 0;
683         }
684 }
685 
686 /*
687  * PIO_FONT support.
688  *
689  * The font loading code goes back to the codepage package by
690  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
691  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
692  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
693  *
694  * Change for certain monochrome monitors by Yury Shevchuck
695  * (sizif@botik.yaroslavl.su).
696  */
697 
698 #ifdef CAN_LOAD_EGA_FONTS
699 
700 #define colourmap 0xa0000
701 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
702    should use 0xA0000 for the bwmap as well.. */
703 #define blackwmap 0xa0000
704 #define cmapsz 8192
705 
706 static int
707 vgacon_do_font_op(char *arg, int set, int ch512)
708 {
709         int i;
710         char *charmap;
711         int beg;
712         unsigned short video_port_status = vga_video_port_reg + 6;
713         int font_select = 0x00;
714 
715         if (vga_video_type != VIDEO_TYPE_EGAM) {
716                 charmap = (char *)VGA_MAP_MEM(colourmap);
717                 beg = 0x0e;
718 #ifdef VGA_CAN_DO_64KB
719                 if (vga_video_type == VIDEO_TYPE_VGAC)
720                         beg = 0x06;
721 #endif
722         } else {
723                 charmap = (char *)VGA_MAP_MEM(blackwmap);
724                 beg = 0x0a;
725         }
726         
727 #ifdef BROKEN_GRAPHICS_PROGRAMS
728         /*
729          * All fonts are loaded in slot 0 (0:1 for 512 ch)
730          */
731 
732         if (!arg)
733                 return -EINVAL;         /* Return to default font not supported */
734 
735         vga_font_is_default = 0;
736         font_select = ch512 ? 0x04 : 0x00;
737 #else   
738         /*
739          * The default font is kept in slot 0 and is never touched.
740          * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
741          */
742 
743         if (set) {
744                 vga_font_is_default = !arg;
745                 if (!arg)
746                         ch512 = 0;              /* Default font is always 256 */
747                 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
748         }
749 
750         if ( !vga_font_is_default )
751                 charmap += 4*cmapsz;
752 #endif
753 
754         spin_lock_irq(&vga_lock);
755         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
756         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
757         outb_p( 0x02, seq_port_reg );
758         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
759         outb_p( 0x04, seq_port_reg );
760         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
761         outb_p( 0x00, seq_port_reg );
762         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
763 
764         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
765         outb_p( 0x02, gr_port_val );    /* select map 2 */
766         outb_p( 0x05, gr_port_reg );
767         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
768         outb_p( 0x06, gr_port_reg );
769         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
770         spin_unlock_irq(&vga_lock);
771         
772         if (arg) {
773                 if (set)
774                         for (i=0; i<cmapsz ; i++)
775                                 vga_writeb(arg[i], charmap + i);
776                 else
777                         for (i=0; i<cmapsz ; i++)
778                                 arg[i] = vga_readb(charmap + i);
779 
780                 /*
781                  * In 512-character mode, the character map is not contiguous if
782                  * we want to remain EGA compatible -- which we do
783                  */
784 
785                 if (ch512) {
786                         charmap += 2*cmapsz;
787                         arg += cmapsz;
788                         if (set)
789                                 for (i=0; i<cmapsz ; i++)
790                                         vga_writeb(arg[i], charmap+i);
791                         else
792                                 for (i=0; i<cmapsz ; i++)
793                                         arg[i] = vga_readb(charmap+i);
794                 }
795         }
796         
797         spin_lock_irq(&vga_lock);
798         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
799         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
800         outb_p( 0x02, seq_port_reg );
801         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
802         outb_p( 0x04, seq_port_reg );
803         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
804         if (set) {
805                 outb_p( 0x03, seq_port_reg ); /* Character Map Select */
806                 outb_p( font_select, seq_port_val );
807         }
808         outb_p( 0x00, seq_port_reg );
809         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
810 
811         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
812         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
813         outb_p( 0x05, gr_port_reg );
814         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
815         outb_p( 0x06, gr_port_reg );
816         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
817 
818         /* if 512 char mode is already enabled don't re-enable it. */
819         if ((set)&&(ch512!=vga_512_chars)) {    /* attribute controller */
820                 int i;
821                 for(i=0; i<MAX_NR_CONSOLES; i++) {
822                         struct vc_data *c = vc_cons[i].d;
823                         if (c && c->vc_sw == &vga_con)
824                                 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
825                 }
826                 vga_512_chars=ch512;
827                 /* 256-char: enable intensity bit
828                    512-char: disable intensity bit */
829                 inb_p( video_port_status );     /* clear address flip-flop */
830                 outb_p ( 0x12, attrib_port ); /* color plane enable register */
831                 outb_p ( ch512 ? 0x07 : 0x0f, attrib_port );
832                 /* Wilton (1987) mentions the following; I don't know what
833                    it means, but it works, and it appears necessary */
834                 inb_p( video_port_status );
835                 outb_p ( 0x20, attrib_port );
836         }
837         spin_unlock_irq(&vga_lock);
838         return 0;
839 }
840 
841 /*
842  * Adjust the screen to fit a font of a certain height
843  */
844 static int
845 vgacon_adjust_height(unsigned fontheight)
846 {
847         int rows, maxscan;
848         unsigned char ovr, vde, fsr;
849 
850         if (fontheight == vga_video_font_height)
851                 return 0;
852 
853         vga_video_font_height = video_font_height = fontheight;
854 
855         rows = video_scan_lines/fontheight;     /* Number of video rows we end up with */
856         maxscan = rows*fontheight - 1;          /* Scan lines to actually display-1 */
857 
858         /* Reprogram the CRTC for the new font size
859            Note: the attempt to read the overflow register will fail
860            on an EGA, but using 0xff for the previous value appears to
861            be OK for EGA text modes in the range 257-512 scan lines, so I
862            guess we don't need to worry about it.
863 
864            The same applies for the spill bits in the font size and cursor
865            registers; they are write-only on EGA, but it appears that they
866            are all don't care bits on EGA, so I guess it doesn't matter. */
867 
868         spin_lock_irq(&vga_lock);
869         outb_p( 0x07, vga_video_port_reg );             /* CRTC overflow register */
870         ovr = inb_p(vga_video_port_val);
871         outb_p( 0x09, vga_video_port_reg );             /* Font size register */
872         fsr = inb_p(vga_video_port_val);
873         spin_unlock_irq(&vga_lock);
874 
875         vde = maxscan & 0xff;                   /* Vertical display end reg */
876         ovr = (ovr & 0xbd) +                    /* Overflow register */
877               ((maxscan & 0x100) >> 7) +
878               ((maxscan & 0x200) >> 3);
879         fsr = (fsr & 0xe0) + (fontheight-1);    /*  Font size register */
880 
881         spin_lock_irq(&vga_lock);
882         outb_p( 0x07, vga_video_port_reg );             /* CRTC overflow register */
883         outb_p( ovr, vga_video_port_val );
884         outb_p( 0x09, vga_video_port_reg );             /* Font size */
885         outb_p( fsr, vga_video_port_val );
886         outb_p( 0x12, vga_video_port_reg );             /* Vertical display limit */
887         outb_p( vde, vga_video_port_val );
888         spin_unlock_irq(&vga_lock);     
889 
890         vc_resize_all(rows, 0);                 /* Adjust console size */
891         return 0;
892 }
893 
894 static int vgacon_font_op(struct vc_data *c, struct console_font_op *op)
895 {
896         int rc;
897 
898         if (vga_video_type < VIDEO_TYPE_EGAM)
899                 return -EINVAL;
900 
901         if (op->op == KD_FONT_OP_SET) {
902                 if (op->width != 8 || (op->charcount != 256 && op->charcount != 512))
903                         return -EINVAL;
904                 rc = vgacon_do_font_op(op->data, 1, op->charcount == 512);
905                 if (!rc && !(op->flags & KD_FONT_FLAG_DONT_RECALC))
906                         rc = vgacon_adjust_height(op->height);
907         } else if (op->op == KD_FONT_OP_GET) {
908                 op->width = 8;
909                 op->height = vga_video_font_height;
910                 op->charcount = vga_512_chars ? 512 : 256;
911                 if (!op->data) return 0;
912                 rc = vgacon_do_font_op(op->data, 0, 0);
913         } else
914                 rc = -ENOSYS;
915         return rc;
916 }
917 
918 #else
919 
920 static int vgacon_font_op(struct vc_data *c, struct console_font_op *op)
921 {
922         return -ENOSYS;
923 }
924 
925 #endif
926 
927 static int vgacon_scrolldelta(struct vc_data *c, int lines)
928 {
929         if (!lines)                     /* Turn scrollback off */
930                 c->vc_visible_origin = c->vc_origin;
931         else {
932                 int vram_size = vga_vram_end - vga_vram_base;
933                 int margin = c->vc_size_row * 4;
934                 int ul, we, p, st;
935 
936                 if (vga_rolled_over > (c->vc_scr_end - vga_vram_base) + margin) {
937                         ul = c->vc_scr_end - vga_vram_base;
938                         we = vga_rolled_over + c->vc_size_row;
939                 } else {
940                         ul = 0;
941                         we = vram_size;
942                 }
943                 p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + lines * c->vc_size_row;
944                 st = (c->vc_origin - vga_vram_base - ul + we) % we;
945                 if (p < margin)
946                         p = 0;
947                 if (p > st - margin)
948                         p = st;
949                 c->vc_visible_origin = vga_vram_base + (p + ul) % we;
950         }
951         vga_set_mem_top(c);
952         return 1;
953 }
954 
955 static int vgacon_set_origin(struct vc_data *c)
956 {
957         if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
958             (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
959                 return 0;
960         c->vc_origin = c->vc_visible_origin = vga_vram_base;
961         vga_set_mem_top(c);
962         vga_rolled_over = 0;
963         return 1;
964 }
965 
966 static void vgacon_save_screen(struct vc_data *c)
967 {
968         static int vga_bootup_console = 0;
969 
970         if (!vga_bootup_console) {
971                 /* This is a gross hack, but here is the only place we can
972                  * set bootup console parameters without messing up generic
973                  * console initialization routines.
974                  */
975                 vga_bootup_console = 1;
976                 c->vc_x = ORIG_X;
977                 c->vc_y = ORIG_Y;
978         }
979         if (!vga_is_gfx)
980                 scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size);
981 }
982 
983 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
984 {
985         unsigned long oldo;
986         unsigned int delta;
987         
988         if (t || b != c->vc_rows || vga_is_gfx)
989                 return 0;
990 
991         if (c->vc_origin != c->vc_visible_origin)
992                 vgacon_scrolldelta(c, 0);
993 
994         if (!vga_hardscroll_enabled || lines >= c->vc_rows/2)
995                 return 0;
996 
997         oldo = c->vc_origin;
998         delta = lines * c->vc_size_row;
999         if (dir == SM_UP) {
1000                 if (c->vc_scr_end + delta >= vga_vram_end) {
1001                         scr_memcpyw((u16 *)vga_vram_base,
1002                                     (u16 *)(oldo + delta),
1003                                     c->vc_screenbuf_size - delta);
1004                         c->vc_origin = vga_vram_base;
1005                         vga_rolled_over = oldo - vga_vram_base;
1006                 } else
1007                         c->vc_origin += delta;
1008                 scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char, delta);
1009         } else {
1010                 if (oldo - delta < vga_vram_base) {
1011                         scr_memmovew((u16 *)(vga_vram_end - c->vc_screenbuf_size + delta),
1012                                      (u16 *)oldo,
1013                                      c->vc_screenbuf_size - delta);
1014                         c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
1015                         vga_rolled_over = 0;
1016                 } else
1017                         c->vc_origin -= delta;
1018                 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1019                 scr_memsetw((u16 *)(c->vc_origin), c->vc_video_erase_char, delta);
1020         }
1021         c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1022         c->vc_visible_origin = c->vc_origin;
1023         vga_set_mem_top(c);
1024         c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
1025         return 1;
1026 }
1027 
1028 
1029 /*
1030  *  The console `switch' structure for the VGA based console
1031  */
1032 
1033 static int vgacon_dummy(struct vc_data *c)
1034 {
1035         return 0;
1036 }
1037 
1038 #define DUMMY (void *) vgacon_dummy
1039 
1040 const struct consw vga_con = {
1041         con_startup:            vgacon_startup,
1042         con_init:               vgacon_init,
1043         con_deinit:             vgacon_deinit,
1044         con_clear:              DUMMY,
1045         con_putc:               DUMMY,
1046         con_putcs:              DUMMY,
1047         con_cursor:             vgacon_cursor,
1048         con_scroll:             vgacon_scroll,
1049         con_bmove:              DUMMY,
1050         con_switch:             vgacon_switch,
1051         con_blank:              vgacon_blank,
1052         con_font_op:            vgacon_font_op,
1053         con_set_palette:        vgacon_set_palette,
1054         con_scrolldelta:        vgacon_scrolldelta,
1055         con_set_origin:         vgacon_set_origin,
1056         con_save_screen:        vgacon_save_screen,
1057         con_build_attr:         vgacon_build_attr,
1058         con_invert_region:      vgacon_invert_region,
1059 };
1060 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.