1 /*-
2 * Copyright (c) 1999, 2000 Hellmuth Michaelis
3 *
4 * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
5 *
6 * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
7 *
8 * Copyright (C) 1992, 1993 Soeren Schmidt.
9 *
10 * All rights reserved.
11 *
12 * For the sake of compatibility, portions of this code regarding the
13 * X server interface are taken from Soeren Schmidt's syscons driver.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by Hellmuth Michaelis,
26 * Brian Dunford-Shore, Joerg Wunsch, Scott Turner and Soeren Schmidt.
27 * 4. The name authors may not be used to endorse or promote products
28 * derived from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 /*---------------------------------------------------------------------------*
43 *
44 * pcvt_sup.c VT220 Driver Support Routines
45 * ---------------------------------------------
46 *
47 * Last Edit-Date: [Wed Apr 5 17:24:20 2000]
48 *
49 * $FreeBSD: releng/6.0/sys/i386/isa/pcvt/pcvt_sup.c 139790 2005-01-06 22:18:23Z imp $
50 *
51 *---------------------------------------------------------------------------*/
52
53 #include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
54
55 #include <sys/resource.h>
56
57 static void vid_cursor ( struct cursorshape *data );
58 static void vgasetfontattr ( struct vgafontattr *data );
59 static void vgagetfontattr ( struct vgafontattr *data );
60 static void vgaloadchar ( struct vgaloadchar *data );
61 static void vid_getscreen ( struct screeninfo *data, struct cdev *dev );
62 static void vid_setscreen ( struct screeninfo *data, struct cdev *dev );
63 static void setchargen ( void );
64 static void setchargen3 ( void );
65 static void resetchargen ( void );
66 static void vgareadpel ( struct vgapel *data, struct cdev *dev );
67 static void vgawritepel ( struct vgapel *data, struct cdev *dev );
68 static void vgapcvtid ( struct pcvtid *data );
69 static void vgapcvtinfo ( struct pcvtinfo *data );
70
71 #ifdef XSERVER
72 static unsigned char * compute_charset_base ( unsigned fontset );
73 #endif /* XSERVER */
74
75 static struct callout_handle async_update_ch =
76 CALLOUT_HANDLE_INITIALIZER(&async_update_ch);
77
78 #if PCVT_SCREENSAVER
79 static void scrnsv_timedout ( void *arg );
80 static struct callout_handle scrnsv_timeout_ch =
81 CALLOUT_HANDLE_INITIALIZER(&scrnsv_timeout_ch);
82 static u_short *savedscreen = (u_short *)0; /* ptr to screen contents */
83 static size_t scrnsv_size = (size_t)-1; /* size of saved image */
84
85 #ifndef XSERVER
86 static unsigned scrnsv_timeout = 0; /* initially off */
87 static void pcvt_set_scrnsv_tmo ( int timeout );/* else declared global */
88 #endif /* XSERVER */
89
90 #if PCVT_PRETTYSCRNS
91 static u_short *scrnsv_current = (u_short *)0; /* attention char ptr */
92 static struct callout_handle scrnsv_blink_ch =
93 CALLOUT_HANDLE_INITIALIZER(&scrnsv_blink_ch);
94 static void scrnsv_blink ( void * );
95 static u_short getrand ( void );
96 #endif /* PCVT_PRETTYSCRNS */
97
98 #endif /* PCVT_SCREENSAVER */
99
100
101 /*---------------------------------------------------------------------------*
102 * execute vga ioctls
103 *---------------------------------------------------------------------------*/
104 int
105 vgaioctl(struct cdev *dev, int cmd, caddr_t data, int flag)
106 {
107 if(minor(dev) >= PCVT_NSCREENS)
108 return -1;
109
110 /*
111 * Some of the commands are not applicable if the vt in question, or the
112 * current vt is in graphics mode (i.e., the X server acts on it); they
113 * will cause an EAGAIN (resource temporarily unavailable) to be returned.
114 */
115
116 #ifdef XSERVER
117 #define is_dev_grafx vs[minor(dev)].vt_status & VT_GRAFX
118 #define is_current_grafx vsp->vt_status & VT_GRAFX
119 #else /* !XSERVER */
120 #define is_dev_grafx 0
121 #define is_current_grafx 0
122 #endif /* XSERVER */
123
124 switch(cmd)
125 {
126 case VGACURSOR:
127 if(is_current_grafx)
128 return EAGAIN;
129 vid_cursor((struct cursorshape *)data);
130 break;
131
132 case VGALOADCHAR:
133 if((adaptor_type != VGA_ADAPTOR) &&
134 (adaptor_type != EGA_ADAPTOR))
135 return -1;
136 if(is_current_grafx)
137 return EAGAIN;
138 vgaloadchar((struct vgaloadchar *)data);
139 break;
140
141 case VGASETFONTATTR:
142 if((adaptor_type != VGA_ADAPTOR) &&
143 (adaptor_type != EGA_ADAPTOR))
144 return -1;
145
146 #if PCVT_SCREENSAVER
147 pcvt_scrnsv_reset();
148 #endif /* PCVT_SCREENSAVER */
149
150 vgasetfontattr((struct vgafontattr *)data);
151 break;
152
153 case VGAGETFONTATTR:
154 if((adaptor_type != VGA_ADAPTOR) &&
155 (adaptor_type != EGA_ADAPTOR))
156 return -1;
157 vgagetfontattr((struct vgafontattr *)data);
158 break;
159
160 case VGASETSCREEN:
161 #if PCVT_SCREENSAVER
162 pcvt_scrnsv_reset();
163 #endif /* PCVT_SCREENSAVER */
164
165 vid_setscreen((struct screeninfo *)data, dev);
166 break;
167
168 case VGAGETSCREEN:
169 vid_getscreen((struct screeninfo *)data, dev);
170 break;
171
172 case VGAREADPEL:
173 if(adaptor_type != VGA_ADAPTOR)
174 return -1;
175 if(is_dev_grafx)
176 return EAGAIN;
177 vgareadpel((struct vgapel *)data, dev);
178 break;
179
180 case VGAWRITEPEL:
181 if(adaptor_type != VGA_ADAPTOR)
182 return -1;
183 if(is_dev_grafx)
184 return EAGAIN;
185 vgawritepel((struct vgapel *)data, dev);
186 break;
187
188 #if PCVT_SCREENSAVER
189 case VGASCREENSAVER:
190 if(is_current_grafx)
191 return EAGAIN;
192 pcvt_set_scrnsv_tmo(*(int *)data);
193 pcvt_scrnsv_reset();
194 break;
195 #endif /* PCVT_SCREENSAVER */
196
197 case VGAPCVTID:
198 vgapcvtid((struct pcvtid *)data);
199 break;
200
201 case VGAPCVTINFO:
202 vgapcvtinfo((struct pcvtinfo *)data);
203 break;
204
205 case VGASETCOLMS:
206 if(is_dev_grafx)
207 return EAGAIN;
208 if(*(int *)data == 80)
209 (void)vt_col(&vs[minor(dev)], SCR_COL80);
210 else if(*(int *)data == 132)
211 {
212 if(vt_col(&vs[minor(dev)], SCR_COL132) == 0)
213 return EINVAL; /* not a VGA */
214 }
215 else
216 return EINVAL;
217 break;
218
219 #if 0
220 case SETSCROLLSIZE:
221 reallocate_scrollbuffer(vsp, *(u_short *)data);
222 break;
223 #endif
224
225 case TIOCSWINSZ:
226 /* do nothing here */
227 break;
228
229 default:
230 return -1;
231 }
232 return 0;
233
234 #undef is_dev_grafx
235 #undef is_current_grafx
236 }
237
238 /*---------------------------------------------------------------------------*
239 * video ioctl - return driver id
240 *---------------------------------------------------------------------------*/
241 static void
242 vgapcvtid(struct pcvtid *data)
243 {
244 snprintf(data->name, sizeof(data->name), "%s", PCVTIDNAME);
245 data->rmajor = PCVTIDMAJOR;
246 data->rminor = PCVTIDMINOR;
247 }
248
249 /*---------------------------------------------------------------------------*
250 * video ioctl - return driver compile time options data
251 *---------------------------------------------------------------------------*/
252 static void
253 vgapcvtinfo(struct pcvtinfo *data)
254 {
255 data->nscreens = PCVT_NSCREENS;
256 data->scanset = PCVT_SCANSET;
257 data->updatefast= PCVT_UPDATEFAST;
258 data->updateslow= PCVT_UPDATESLOW;
259 data->sysbeepf = PCVT_SYSBEEPF;
260 data->pcburst = PCVT_PCBURST;
261 data->kbd_fifo_sz = PCVT_KBD_FIFO_SZ;
262
263 data->compile_opts = (0
264
265 #if PCVT_VT220KEYB
266 | CONF_VT220KEYB
267 #endif
268 #if PCVT_SCREENSAVER
269 | CONF_SCREENSAVER
270 #endif
271 #if PCVT_PRETTYSCRNS
272 | CONF_PRETTYSCRNS
273 #endif
274 #if PCVT_CTRL_ALT_DEL
275 | CONF_CTRL_ALT_DEL
276 #endif
277 #if PCVT_USEKBDSEC
278 | CONF_USEKBDSEC
279 #endif
280 #if PCVT_24LINESDEF
281 | CONF_24LINESDEF
282 #endif
283 #if PCVT_SHOWKEYS
284 | CONF_SHOWKEYS
285 #endif
286 #if PCVT_NULLCHARS
287 | CONF_NULLCHARS
288 #endif
289 #if PCVT_SETCOLOR
290 | CONF_SETCOLOR
291 #endif
292 #if PCVT_132GENERIC
293 | CONF_132GENERIC
294 #endif
295 #ifdef XSERVER
296 | CONF_XSERVER
297 #endif
298 #if PCVT_INHIBIT_NUMLOCK
299 | CONF_INHIBIT_NUMLOCK
300 #endif
301 #if PCVT_META_ESC
302 | CONF_META_ESC
303 #endif
304 #if PCVT_SLOW_INTERRUPT
305 | CONF_SLOW_INTERRUPT
306 #endif
307 #if PCVT_NO_LED_UPDATE
308 | CONF_NO_LED_UPDATE
309 #endif
310 #if PCVT_GREENSAVER
311 | CONF_GREENSAVER
312 #endif
313
314 );
315 }
316
317 /*---------------------------------------------------------------------------*
318 * video ioctl - set cursor appearence
319 *---------------------------------------------------------------------------*/
320 static void
321 vid_cursor(struct cursorshape *data)
322 {
323 int screen;
324 int start;
325 int end;
326 int line_height;
327 int character_set;
328
329 /* for which virtual screen, -1 for current */
330 screen = data->screen_no;
331
332 if(screen == -1) /* current ? */
333 screen = current_video_screen;
334 else if(screen > totalscreens - 1)
335 screen = totalscreens - 1;
336 else if(screen < 0)
337 screen = 0;
338
339 if(adaptor_type == VGA_ADAPTOR || adaptor_type == EGA_ADAPTOR)
340 {
341 character_set = vs[screen].vga_charset;
342 character_set = (character_set < 0) ? 0 :
343 ((character_set < totalfonts) ?
344 character_set :
345 totalfonts-1);
346
347 line_height = vgacs[character_set].char_scanlines & 0x1F;
348 }
349 else if(adaptor_type == MDA_ADAPTOR)
350 {
351 line_height = 14;
352 }
353 else
354 {
355 line_height = 8; /* CGA */
356 }
357
358 start = (data->start < 0) ? 0 :
359 ((data->start > line_height) ? line_height : data->start);
360
361 if((vga_family == VGA_F_TRI) && (start == 0))
362 start = 1;
363
364 end = (data->end < 0) ? 0 :
365 ((data->end > line_height) ? line_height : data->end);
366
367 vs[screen].cursor_start = start;
368 vs[screen].cursor_end = end;
369
370 if(screen == current_video_screen)
371 {
372 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
373 outb(addr_6845+1, start);
374 outb(addr_6845,CRTC_CUREND); /* cursor end reg */
375 outb(addr_6845+1, end);
376 }
377 }
378
379 /*---------------------------------------------------------------------------*
380 * ega/vga ioctl - set font attributes
381 *---------------------------------------------------------------------------*/
382 static void
383 vgasetfontattr(struct vgafontattr *data)
384 {
385 register int i;
386 int vga_character_set;
387 int lines_per_character;
388 int totscanlines;
389 int size;
390
391 vga_character_set = data->character_set;
392 vga_character_set = (vga_character_set < 0) ? 0 :
393 ((vga_character_set < totalfonts) ?
394 vga_character_set : totalfonts-1);
395
396 vgacs[vga_character_set].loaded = data->font_loaded;
397
398 /* Limit Characters to 32 scanlines doubled */
399 vgacs[vga_character_set].char_scanlines =
400 (data->character_scanlines & 0x1F)
401 | 0x40; /* always set bit 9 of line cmp reg */
402
403 if(adaptor_type == EGA_ADAPTOR)
404 /* ...and screen height to scan 350 lines */
405 vgacs[vga_character_set].scr_scanlines =
406 (data->screen_scanlines > 0x5d) ?
407 0x5d : data->screen_scanlines;
408 else
409 /* ...and screen height to scan 480 lines */
410 vgacs[vga_character_set].scr_scanlines =
411 (data->screen_scanlines > 0xdF) ?
412 0xdF : data->screen_scanlines;
413
414 lines_per_character =
415 (int)(0x1F & vgacs[vga_character_set].char_scanlines)+1;
416
417 totscanlines = 0x101 + (int)vgacs[vga_character_set].scr_scanlines;
418
419 size = data->screen_size;
420
421 if(adaptor_type == EGA_ADAPTOR)
422 {
423 switch(size)
424 {
425 case SIZ_25ROWS: /* This case is always OK */
426 break;
427
428 case SIZ_35ROWS:
429 if(totscanlines/lines_per_character >= 35)
430 size = SIZ_35ROWS;
431 else
432 size = SIZ_25ROWS;
433 break;
434
435 case SIZ_43ROWS:
436 default:
437 if(totscanlines/lines_per_character >= 43)
438 size = SIZ_43ROWS;
439 else if(totscanlines/lines_per_character >= 35)
440 size = SIZ_35ROWS;
441 else
442 size = SIZ_25ROWS;
443 break;
444 }
445 }
446 else
447 {
448 switch(size)
449 {
450 case SIZ_25ROWS: /* This case is always OK */
451 break;
452
453 case SIZ_28ROWS:
454 if(totscanlines/lines_per_character >= 28)
455 size = SIZ_28ROWS;
456 else
457 size = SIZ_25ROWS;
458 break;
459
460 case SIZ_40ROWS:
461 if(totscanlines/lines_per_character >= 40)
462 size = SIZ_40ROWS;
463 else if(totscanlines/lines_per_character >= 28)
464 size = SIZ_28ROWS;
465 else
466 size = SIZ_25ROWS;
467 break;
468
469 case SIZ_50ROWS:
470 default:
471 if(totscanlines/lines_per_character >= 50)
472 size = SIZ_50ROWS;
473 else if(totscanlines/lines_per_character >= 40)
474 size = SIZ_40ROWS;
475 else if(totscanlines/lines_per_character >= 28)
476 size = SIZ_28ROWS;
477 else
478 size = SIZ_25ROWS;
479 break;
480 }
481 }
482
483 vgacs[vga_character_set].screen_size = size;
484
485 for (i = 0;i < PCVT_NSCREENS;i++)
486 {
487 if(vga_character_set == vs[i].vga_charset)
488 set_charset(&(vs[i]),vga_character_set);
489 }
490
491 #ifdef XSERVER
492 switch_screen(current_video_screen, 0, 0);
493 #else
494 vgapage(current_video_screen);
495 #endif /* XSERVER */
496
497 }
498
499 /*---------------------------------------------------------------------------*
500 * ega/vga ioctl - get font attributes
501 *---------------------------------------------------------------------------*/
502 static void
503 vgagetfontattr(struct vgafontattr *data)
504 {
505 int vga_character_set;
506
507 vga_character_set = data->character_set;
508 vga_character_set = (vga_character_set < 0) ? 0 :
509 ((vga_character_set < (int)totalfonts) ?
510 vga_character_set :
511 (int)(totalfonts-1));
512
513 data->character_set = (int)vga_character_set;
514
515 data->font_loaded = (int)vgacs[vga_character_set].loaded;
516
517 data->character_scanlines =
518 (int)vgacs[vga_character_set].char_scanlines
519 & 0x1f; /* do not display the overflow bits */
520
521 data->screen_scanlines = (int)vgacs[vga_character_set].scr_scanlines;
522
523 data->screen_size = (int)vgacs[vga_character_set].screen_size;
524 }
525
526 /*---------------------------------------------------------------------------*
527 * ega/vga ioctl - load a character shape into character set
528 *---------------------------------------------------------------------------*/
529 static void
530 vgaloadchar(struct vgaloadchar *data)
531 {
532 int vga_character_set;
533 int character;
534 int lines_per_character;
535
536 vga_character_set = data->character_set;
537 vga_character_set = (vga_character_set < 0) ? 0 :
538 ((vga_character_set < (int)totalfonts) ?
539 vga_character_set : (int)(totalfonts-1));
540
541 character = (data->character < 0) ? 0 :
542 ((data->character > 255) ? 255 : data->character);
543
544 lines_per_character = (int)data->character_scanlines;
545 lines_per_character = (lines_per_character < 0) ? 0 :
546 ((lines_per_character > 32) ? 32 : lines_per_character);
547
548 loadchar(vga_character_set,character,lines_per_character,
549 data->char_table);
550 }
551
552 /*---------------------------------------------------------------------------*
553 * video ioctl - get screen information
554 *---------------------------------------------------------------------------*/
555 static void
556 vid_getscreen(struct screeninfo *data, struct cdev *dev)
557 {
558 int device = minor(dev);
559 data->adaptor_type = adaptor_type; /* video adapter installed */
560 data->monitor_type = color; /* monitor type installed */
561 data->totalfonts = totalfonts; /* no of downloadble fonts */
562 data->totalscreens = totalscreens; /* no of virtual screens */
563 data->screen_no = device; /* this screen number */
564 data->current_screen = current_video_screen; /* displayed screen no */
565 /* screen size */
566 data->screen_size = vgacs[(vs[device].vga_charset)].screen_size;
567 /* pure VT mode or HP/VT mode */
568 data->pure_vt_mode = vs[device].vt_pure_mode;
569 data->vga_family = vga_family; /* manufacturer, family */
570 data->vga_type = vga_type; /* detected chipset type */
571 data->vga_132 = can_do_132col; /* 132 column support */
572 data->force_24lines = vs[device].force24; /* force 24 lines */
573 }
574
575 /*---------------------------------------------------------------------------*
576 * video ioctl - set screen information
577 *---------------------------------------------------------------------------*/
578 static void
579 vid_setscreen(struct screeninfo *data, struct cdev *dev)
580 {
581 int screen;
582
583 if(data->current_screen == -1)
584 {
585 screen = minor(dev);
586 }
587 else
588 {
589 if(data->current_screen >= PCVT_NSCREENS)
590 return; /* XXXXXX */
591 screen = data->current_screen;
592 }
593
594 vgapage(screen);
595
596 #ifdef XSERVER
597 {
598 int x = spltty(), waitfor = screen + 1;
599 /* if the vt is yet to be released by a process, wait here */
600 if(vs[screen].vt_status & VT_WAIT_REL)
601 (void)usl_vt_ioctl(dev, VT_WAITACTIVE,
602 (caddr_t)&waitfor, 0, 0);
603 splx(x);
604 }
605 /* make sure the switch really happened */
606 if(screen != current_video_screen)
607 return; /* XXX should say "EAGAIN" here */
608 #endif /* XSERVER */
609
610 if((data->screen_size != -1) || (data->force_24lines != -1))
611 {
612 if(data->screen_size == -1)
613 data->screen_size =
614 vgacs[(vs[screen].vga_charset)].screen_size;
615
616 if(data->force_24lines != -1)
617 {
618 vs[screen].force24 = data->force_24lines;
619
620 if(vs[screen].force24)
621 {
622 swritefkl(2,(u_char *)"FORCE24 ENABLE *",
623 &vs[screen]);
624 }
625 else
626 {
627 swritefkl(2,(u_char *)"FORCE24 ENABLE ",
628 &vs[screen]);
629 }
630 }
631
632 if((data->screen_size == SIZ_25ROWS) ||
633 (data->screen_size == SIZ_28ROWS) ||
634 (data->screen_size == SIZ_35ROWS) ||
635 (data->screen_size == SIZ_40ROWS) ||
636 (data->screen_size == SIZ_43ROWS) ||
637 (data->screen_size == SIZ_50ROWS))
638 {
639 if(data->screen_no == -1)
640 set_screen_size(vsp, data->screen_size);
641 else
642 set_screen_size(&vs[minor(dev)],
643 data->screen_size);
644 }
645 }
646
647 if(data->pure_vt_mode != -1)
648 {
649 if((data->pure_vt_mode == M_HPVT) ||
650 (data->pure_vt_mode == M_PUREVT))
651 {
652 if(data->screen_no == -1)
653 set_emulation_mode(vsp, data->pure_vt_mode);
654 else
655 set_emulation_mode(&vs[minor(dev)],
656 data->pure_vt_mode);
657 }
658 }
659 }
660
661 /*---------------------------------------------------------------------------*
662 * set screen size/resolution for a virtual screen
663 *---------------------------------------------------------------------------*/
664 void
665 set_screen_size(struct video_state *svsp, int size)
666 {
667 int i;
668
669 for(i = 0; i < totalfonts; i++)
670 {
671 if(vgacs[i].screen_size == size)
672 {
673 set_charset(svsp, i);
674 clr_parms(svsp); /* escape parameter init */
675 svsp->state = STATE_INIT; /* initial state */
676 svsp->scrr_beg = 0; /* start of scrolling region */
677 svsp->sc_flag = 0; /* invalidate saved cursor
678 * position */
679 svsp->transparent = 0; /* disable control code
680 * processing */
681
682 /* Update tty to reflect screen size */
683
684 if (svsp->vs_tty)
685 {
686 svsp->vs_tty->t_winsize.ws_col = svsp->maxcol;
687 svsp->vs_tty->t_winsize.ws_xpixel =
688 (svsp->maxcol == 80)? 720: 1056;
689 svsp->vs_tty->t_winsize.ws_ypixel = 400;
690 svsp->vs_tty->t_winsize.ws_row =
691 svsp->screen_rows;
692 }
693 /* screen_rows already calculated in set_charset() */
694 if(svsp->vt_pure_mode == M_HPVT && svsp->labels_on)
695 {
696 if(svsp->which_fkl == SYS_FKL)
697 sw_sfkl(svsp);
698 else if(svsp->which_fkl == USR_FKL)
699 sw_ufkl(svsp);
700 }
701
702
703 svsp->scrr_len = svsp->screen_rows;
704 svsp->scrr_end = svsp->scrr_len - 1;
705
706 if (svsp->vs_tty && svsp->vs_tty->t_pgrp) {
707 PGRP_LOCK(svsp->vs_tty->t_pgrp);
708 pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
709 PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
710 }
711
712 reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
713 break;
714 }
715 }
716 }
717
718 /*---------------------------------------------------------------------------*
719 * resize the scrollback buffer to the specified number of "pages"
720 *---------------------------------------------------------------------------*/
721 void
722 reallocate_scrollbuffer(struct video_state *svsp, int pages)
723 {
724 int s;
725 u_short *stmp;
726
727 if(pages < 2)
728 pages = 2;
729 if(pages > 50)
730 pages = 50;
731
732 s = splhigh();
733
734 if((stmp = (u_short *)malloc(svsp->maxcol * svsp->screen_rows *
735 pages * CHR, M_DEVBUF, M_NOWAIT)) == NULL)
736 {
737 splx(s);
738 printf("pcvt: reallocate_scrollbuffer, malloc failed\n");
739 return;
740 }
741
742 svsp->max_off = svsp->screen_rows * pages - 1;
743
744 if(svsp->Scrollback)
745 {
746 bcopy(svsp->Scrollback, stmp,
747 (min(pages, svsp->scrollback_pages)) *
748 svsp->screen_rows * svsp->maxcol * CHR);
749 free(svsp->Scrollback, M_DEVBUF);
750 svsp->Scrollback = stmp;
751 }
752 else
753 {
754 svsp->scr_offset = 0;
755 svsp->scrolling = 0;
756 svsp->Scrollback = stmp;
757
758 bcopy(svsp->Crtat, svsp->Scrollback,
759 svsp->screen_rows * svsp->maxcol * CHR);
760
761 svsp->scr_offset = svsp->row;
762 }
763
764 svsp->scrollback_pages = pages;
765
766 splx(s);
767 }
768
769 /*---------------------------------------------------------------------------*
770 * VGA ioctl - read DAC palette entry
771 *---------------------------------------------------------------------------*/
772 static void
773 vgareadpel(struct vgapel *data, struct cdev *dev)
774 {
775 register unsigned vpage = minor(dev);
776 register unsigned idx = data->idx;
777
778 if(idx >= NVGAPEL)
779 return; /* no such entry */
780
781 /* do not read VGA palette directly, use saved values */
782 data->r = vs[vpage].palette[idx].r;
783 data->g = vs[vpage].palette[idx].g;
784 data->b = vs[vpage].palette[idx].b;
785 }
786
787 /*---------------------------------------------------------------------------*
788 * VGA ioctl - write DAC palette entry
789 *---------------------------------------------------------------------------*/
790 static void
791 vgawritepel(struct vgapel *data, struct cdev *dev)
792 {
793 register unsigned vpage = minor(dev);
794 register unsigned idx = data->idx;
795
796 if(idx >= NVGAPEL)
797 return; /* no such entry */
798
799 /* first, update saved values for this video screen */
800 vs[vpage].palette[idx].r = data->r;
801 vs[vpage].palette[idx].g = data->g;
802 vs[vpage].palette[idx].b = data->b;
803
804 /* if this happens on active screen, update VGA DAC, too */
805 if(vpage == current_video_screen)
806 vgapaletteio(idx, &vs[vpage].palette[idx], 1);
807 }
808
809 /*---------------------------------------------------------------------------*
810 * VGA physical IO - read/write one palette entry
811 *---------------------------------------------------------------------------*/
812 void
813 vgapaletteio(unsigned idx, struct rgb *val, int writeit)
814 {
815 if(writeit)
816 {
817 outb(VGA_DAC + 2, idx);
818 outb(VGA_DAC + 3, val->r & VGA_PMSK);
819 outb(VGA_DAC + 3, val->g & VGA_PMSK);
820 outb(VGA_DAC + 3, val->b & VGA_PMSK);
821 }
822 else /* read it */
823 {
824 outb(VGA_DAC + 1, idx);
825 val->r = inb(VGA_DAC + 3) & VGA_PMSK;
826 val->g = inb(VGA_DAC + 3) & VGA_PMSK;
827 val->b = inb(VGA_DAC + 3) & VGA_PMSK;
828 }
829 }
830
831 /*---------------------------------------------------------------------------*
832 *
833 * update asynchronous: cursor, cursor pos displ, sys load, keyb scan
834 *
835 * arg is:
836 * UPDATE_START = do update; requeue
837 * UPDATE_STOP = suspend updates
838 * UPDATE_KERN = do update for kernel printfs
839 *
840 *---------------------------------------------------------------------------*/
841 void
842 async_update(void *arg)
843 {
844 static int lastpos = 0;
845 static int counter = PCVT_UPDATESLOW;
846
847 #ifdef XSERVER
848 /* need a method to suspend the updates */
849
850 if(arg == UPDATE_STOP)
851 {
852 untimeout(async_update, UPDATE_START, async_update_ch);
853 return;
854 }
855 #endif /* XSERVER */
856
857 /* first check if update is possible */
858
859 if(chargen_access) /* does no-one load characters? */
860 {
861 goto async_update_exit; /* do not update anything */
862 }
863
864 #if PCVT_SCREENSAVER
865 if(reset_screen_saver && (counter == PCVT_UPDATESLOW))
866 {
867 pcvt_scrnsv_reset(); /* yes, do it */
868 reset_screen_saver = 0; /* re-init */
869 }
870 else if(scrnsv_active) /* is the screen not blanked? */
871 {
872 goto async_update_exit; /* do not update anything */
873 }
874 #endif /* PCVT_SCREENSAVER */
875
876 /*-------------------------------------------------------------------*/
877 /* this takes place on EVERY virtual screen (if not in X mode etc...)*/
878 /*-------------------------------------------------------------------*/
879
880 if ( cursor_pos_valid &&
881 (lastpos != (vsp->Crtat + vsp->cur_offset - Crtat)))
882 {
883 lastpos = vsp->Crtat + vsp->cur_offset - Crtat;
884 outb(addr_6845, CRTC_CURSORH); /* high register */
885 outb(addr_6845+1, ((lastpos) >> 8));
886 outb(addr_6845, CRTC_CURSORL); /* low register */
887 outb(addr_6845+1, (lastpos));
888 }
889
890 if (arg == UPDATE_KERN) /* Magic arg: for kernel printfs */
891 return;
892
893 if(--counter) /* below is possible update */
894 goto async_update_exit; /* just now and then ..... */
895 counter = PCVT_UPDATESLOW; /* caution, see screensaver above !! */
896
897 /*-------------------------------------------------------------------*/
898 /* this takes place ONLY on screen 0 if in HP mode, labels on, !X */
899 /*-------------------------------------------------------------------*/
900
901 /* additional processing for HP necessary ? */
902
903 if((vs[0].vt_pure_mode == M_HPVT) && (vs[0].labels_on))
904 {
905 static volatile u_char buffer[] =
906 "System Load: 1min: 0.00 5min: 0.00 15min: 0.00";
907 register int tmp, i;
908 #if PCVT_SHOWKEYS
909 extern u_char rawkeybuf[80];
910
911 if(keyboard_show)
912 {
913 for(i = 0; i < 80; i++)
914 {
915 *((vs[0].Crtat+((vs[0].screen_rows+2)
916 * vs[0].maxcol))+i) =
917 user_attr | rawkeybuf[i];
918 }
919 }
920 else
921 {
922 #endif /* PCVT_SHOWKEYS */
923
924 /* display load averages in last line (taken from tty.c) */
925 i = 18;
926 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2)
927 >> FSHIFT;
928 buffer[i++] =
929 ((((tmp/100)/10) == 0) ?
930 ' ' :
931 ((tmp/100)/10) + '');
932 buffer[i++] = ((tmp/100)%10) + '';
933 buffer[i++] = '.';
934 buffer[i++] = ((tmp%100)/10) + '';
935 buffer[i++] = ((tmp%100)%10) + '';
936 i += 6;
937 tmp = (averunnable.ldavg[1] * 100 + FSCALE / 2)
938 >> FSHIFT;
939 buffer[i++] = ((((tmp/100)/10) == 0) ?
940 ' ' :
941 ((tmp/100)/10) + '');
942 buffer[i++] = ((tmp/100)%10) + '';
943 buffer[i++] = '.';
944 buffer[i++] = ((tmp%100)/10) + '';
945 buffer[i++] = ((tmp%100)%10) + '';
946 i += 7;
947 tmp = (averunnable.ldavg[2] * 100 + FSCALE / 2)
948 >> FSHIFT;
949 buffer[i++] = ((((tmp/100)/10) == 0) ?
950 ' ' :
951 ((tmp/100)/10) + '');
952 buffer[i++] = ((tmp/100)%10) + '';
953 buffer[i++] = '.';
954 buffer[i++] = ((tmp%100)/10) + '';
955 buffer[i++] = ((tmp%100)%10) + '';
956 buffer[i] = '\0';
957
958 for(i = 0; buffer[i]; i++)
959 {
960 *((vs[0].Crtat +
961 ((vs[0].screen_rows + 2) * vs[0].maxcol)
962 ) + i
963 ) = user_attr | buffer[i];
964 }
965
966 #if PCVT_SHOWKEYS
967 for(; i < 77; i++)
968 {
969 *((vs[0].Crtat +
970 ((vs[0].screen_rows + 2) * vs[0].maxcol)
971 ) + i
972 ) = user_attr | ' ';
973 }
974
975 }
976 #endif /* PCVT_SHOWKEYS */
977 }
978
979 /*-------------------------------------------------------------------*/
980 /* this takes place on EVERY screen which is in HP mode, labels on,!X*/
981 /*-------------------------------------------------------------------*/
982
983 if((vsp->vt_pure_mode == M_HPVT) && (vsp->labels_on))
984 {
985 register int col = vsp->col+1;
986 register u_short *p = vsp->Crtat +
987 (vsp->screen_rows * vsp->maxcol);
988
989 /* update column display between labels */
990
991 if(vsp->maxcol == SCR_COL132)
992 {
993 p += (SCR_COL132 - SCR_COL80)/2;
994
995 if(col >= 100)
996 {
997 *(p + LABEL_COLU) = user_attr | '1';
998 col -= 100;
999 }
1000 else
1001 {
1002 *(p + LABEL_COLU) = user_attr | '';
1003 }
1004 }
1005 *(p + LABEL_COLH) = user_attr | ((col/10) + '');
1006 *(p + LABEL_COLL) = user_attr | ((col%10) + '');
1007
1008 /* update row display between labels */
1009
1010 *(p + LABEL_ROWH) = (user_attr | (((vsp->row+1)/10) + ''));
1011 *(p + LABEL_ROWL) = (user_attr | (((vsp->row+1)%10) + ''));
1012 }
1013
1014 async_update_exit:
1015
1016 if(arg == UPDATE_START)
1017 {
1018 async_update_ch = timeout(async_update, UPDATE_START,
1019 PCVT_UPDATEFAST);
1020 }
1021 }
1022
1023 /*---------------------------------------------------------------------------*
1024 * set character set for virtual screen
1025 *---------------------------------------------------------------------------*/
1026 void
1027 set_charset(struct video_state *svsp, int curvgacs)
1028 {
1029 static int sizetab[] = { 25, 28, 35, 40, 43, 50 };
1030 int oldsize, oldrows, newsize, newrows;
1031
1032 if((curvgacs < 0) || (curvgacs > (NVGAFONTS-1)))
1033 return;
1034
1035 svsp->vga_charset = curvgacs;
1036
1037 select_vga_charset(curvgacs);
1038
1039 oldsize = svsp->screen_rowsize;
1040 oldrows = svsp->screen_rows;
1041 newsize = sizetab[(vgacs[curvgacs].screen_size)];
1042 newrows = newsize;
1043 if (svsp->vt_pure_mode == M_HPVT)
1044 newrows -= 3;
1045 if (newrows == 25 && svsp->force24)
1046 newrows = 24;
1047 if (newrows < oldrows) {
1048 int nscroll = svsp->row + 1 - newrows;
1049
1050 if (svsp->row >= oldrows) /* Sanity check */
1051 nscroll = oldrows - newrows;
1052 if (nscroll > 0) {
1053 /* Scroll up */
1054 bcopy (svsp->Crtat + nscroll * svsp->maxcol,
1055 svsp->Crtat,
1056 newrows * svsp->maxcol * CHR);
1057 svsp->row -= nscroll;
1058 svsp->cur_offset -= nscroll * svsp->maxcol;
1059 }
1060 if (newrows < newsize)
1061 fillw(user_attr | ' ',
1062 svsp->Crtat + newrows * svsp->maxcol,
1063 (newsize - newrows) * svsp->maxcol);
1064 } else if (oldrows < newsize)
1065 fillw(user_attr | ' ',
1066 svsp->Crtat + oldrows * svsp->maxcol,
1067 (newsize - oldrows) * svsp->maxcol);
1068
1069 svsp->screen_rowsize = newsize;
1070 svsp->screen_rows = newrows;
1071
1072 /* Clip scrolling region */
1073 if(svsp->scrr_end > svsp->screen_rows - 1)
1074 svsp->scrr_end = svsp->screen_rows - 1;
1075 svsp->scrr_len = svsp->scrr_end - svsp->scrr_beg + 1;
1076
1077 /* Clip cursor pos */
1078
1079 if(svsp->cur_offset > (svsp->scrr_len * svsp->maxcol))
1080 svsp->cur_offset = (svsp->scrr_len * svsp->maxcol) + svsp->col;
1081 }
1082
1083 /*---------------------------------------------------------------------------*
1084 * select a vga character set
1085 *---------------------------------------------------------------------------*/
1086 void
1087 select_vga_charset(int vga_charset)
1088 {
1089 int first, second;
1090 int fflag = 0;
1091 int sflag = 0;
1092 u_char cmap = 0;
1093
1094 static u_char cmaptaba[] =
1095 {0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13};
1096
1097 static u_char cmaptabb[] =
1098 {0x00, 0x04, 0x08, 0x0c, 0x20, 0x24, 0x28, 0x2c};
1099
1100 if((adaptor_type != EGA_ADAPTOR) && (adaptor_type != VGA_ADAPTOR))
1101 return;
1102
1103 if((vga_charset < 0) || (vga_charset >= totalfonts))
1104 return;
1105
1106 if(!vgacs[vga_charset].loaded)
1107 return;
1108
1109 /*--------------------------------------------------------------
1110 find the the first and second charset of a given resolution.
1111 the first is used for lower 256 and the second (if any) is
1112 used for the upper 256 entries of a complete 512 entry ega/
1113 vga charset.
1114 --------------------------------------------------------------*/
1115
1116 for(first = 0; first < totalfonts; first++)
1117 {
1118 if(!vgacs[first].loaded)
1119 continue;
1120 if(vgacs[first].screen_size != vgacs[vga_charset].screen_size)
1121 continue;
1122 if(vgacs[first].char_scanlines !=
1123 vgacs[vga_charset].char_scanlines)
1124 continue;
1125 if(vgacs[first].scr_scanlines !=
1126 vgacs[vga_charset].scr_scanlines)
1127 continue;
1128 fflag = 1;
1129 break;
1130 }
1131
1132 if(fflag != 1)
1133 return;
1134
1135 for(second = first+1; second < totalfonts; second++)
1136 {
1137 if(!vgacs[second].loaded)
1138 continue;
1139 if(vgacs[second].screen_size != vgacs[vga_charset].screen_size)
1140 continue;
1141 if(vgacs[second].char_scanlines !=
1142 vgacs[vga_charset].char_scanlines)
1143 continue;
1144 if(vgacs[second].scr_scanlines !=
1145 vgacs[vga_charset].scr_scanlines)
1146 continue;
1147 sflag = 1;
1148 break;
1149 }
1150
1151 cmap = cmaptaba[first];
1152 if(sflag)
1153 {
1154 cmap |= cmaptabb[second];
1155 vgacs[first].secondloaded = second;
1156 }
1157 else
1158 {
1159 vgacs[first].secondloaded = 0; /*cs 0 can never become a 2nd!*/
1160 }
1161
1162 if(vsp->wd132col)
1163 {
1164 cmap = (vga_charset & 0x07);
1165 cmap |= 0x10;
1166 }
1167
1168 outb(TS_INDEX, TS_FONTSEL); /* character map select register */
1169 outb(TS_DATA, cmap); /* new char map */
1170
1171 outb(addr_6845, CRTC_MAXROW); /* max scan line reg */
1172 outb(addr_6845+1,
1173 vgacs[first].char_scanlines); /* scanlines/char */
1174
1175 outb(addr_6845, CRTC_VDE); /* vert display enable end */
1176 outb(addr_6845+1,
1177 vgacs[first].scr_scanlines); /* low byte of scr scanlines */
1178
1179 if((color == 0) && (adaptor_type == VGA_ADAPTOR))
1180 {
1181 outb(addr_6845, CRTC_ULOC); /* underline location reg */
1182 outb(addr_6845+1, (vgacs[first].char_scanlines & 0x1F));
1183 }
1184 }
1185
1186 /*---------------------------------------------------------------------------*
1187 * switch vga-card to load a character set
1188 *---------------------------------------------------------------------------*/
1189 static void
1190 setchargen(void)
1191 {
1192 chargen_access = 1; /* flag we are accessing the chargen ram */
1193
1194 /* program sequencer to access character generator */
1195
1196 outb(TS_INDEX, TS_SYNCRESET);
1197 outb(TS_DATA, 0x01); /* synchronous reset */
1198
1199 outb(TS_INDEX, TS_WRPLMASK);
1200 outb(TS_DATA, 0x04); /* write to map 2 */
1201
1202 outb(TS_INDEX, TS_MEMMODE);
1203 outb(TS_DATA, 0x07); /* sequential addressing */
1204
1205 outb(TS_INDEX, TS_SYNCRESET);
1206 outb(TS_DATA, 0x03); /* clear synchronous reset */
1207
1208 /* program graphics controller to access character generator */
1209
1210 outb(GDC_INDEX, GDC_RDPLANESEL);
1211 outb(GDC_DATA, 0x02); /* select map 2 for cpu reads */
1212
1213 outb(GDC_INDEX, GDC_MODE);
1214 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1215
1216 outb(GDC_INDEX, GDC_MISC);
1217 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1218 }
1219
1220 /*---------------------------------------------------------------------------*
1221 * switch vga-card to load a character set to plane 3
1222 *---------------------------------------------------------------------------*/
1223 static void
1224 setchargen3(void)
1225 {
1226 chargen_access = 1; /* flag we are accessing the chargen ram */
1227
1228 /* program sequencer to access character generator */
1229
1230 outb(TS_INDEX, TS_SYNCRESET);
1231 outb(TS_DATA, 0x01); /* synchronous reset */
1232
1233 outb(TS_INDEX, TS_WRPLMASK);
1234 outb(TS_DATA, 0x08); /* write to map 3 */
1235
1236 outb(TS_INDEX, TS_MEMMODE);
1237 outb(TS_DATA, 0x07); /* sequential addressing */
1238
1239 outb(TS_INDEX, TS_SYNCRESET);
1240 outb(TS_DATA, 0x03); /* clear synchronous reset */
1241
1242 /* program graphics controller to access character generator */
1243
1244 outb(GDC_INDEX, GDC_RDPLANESEL);
1245 outb(GDC_DATA, 0x03); /* select map 3 for cpu reads */
1246
1247 outb(GDC_INDEX, GDC_MODE);
1248 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1249
1250 outb(GDC_INDEX, GDC_MISC);
1251 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1252 }
1253
1254 /*---------------------------------------------------------------------------*
1255 * switch back vga-card to normal operation
1256 *---------------------------------------------------------------------------*/
1257 static void
1258 resetchargen(void)
1259 {
1260 /* program sequencer to access video ram */
1261
1262 outb(TS_INDEX, TS_SYNCRESET);
1263 outb(TS_DATA, 0x01); /* synchronous reset */
1264
1265 outb(TS_INDEX, TS_WRPLMASK);
1266 outb(TS_DATA, 0x03); /* write to map 0 & 1 */
1267
1268 outb(TS_INDEX, TS_MEMMODE);
1269 outb(TS_DATA, 0x03); /* odd-even addressing */
1270
1271 outb(TS_INDEX, TS_SYNCRESET);
1272 outb(TS_DATA, 0x03); /* clear synchronous reset */
1273
1274 /* program graphics controller to access character generator */
1275
1276 outb(GDC_INDEX, GDC_RDPLANESEL);
1277 outb(GDC_DATA, 0x00); /* select map 0 for cpu reads */
1278
1279 outb(GDC_INDEX, GDC_MODE);
1280 outb(GDC_DATA, 0x10); /* enable odd-even addressing */
1281
1282 outb(GDC_INDEX, GDC_MISC);
1283 if(color)
1284 outb(GDC_DATA, 0x0e); /* map starts at 0xb800 */
1285 else
1286 outb(GDC_DATA, 0x0a); /* map starts at 0xb000 */
1287
1288 chargen_access = 0; /* flag we are NOT accessing the chargen ram */
1289 }
1290
1291
1292 /*---------------------------------------------------------------------------*
1293 * switch screen off (VGA only)
1294 *---------------------------------------------------------------------------*/
1295 void
1296 vga_screen_off(void)
1297 {
1298 unsigned char old;
1299
1300 outb(TS_INDEX, TS_SYNCRESET);
1301 outb(TS_DATA, 0x01); /* synchronous reset */
1302
1303 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1304 old = inb(TS_DATA); /* get current value */
1305
1306 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1307 outb(TS_DATA, (old | 0x20)); /* screen off bit on */
1308
1309 outb(TS_INDEX, TS_SYNCRESET);
1310 outb(TS_DATA, 0x03); /* clear synchronous reset */
1311 }
1312
1313 /*---------------------------------------------------------------------------*
1314 * switch screen back on (VGA only)
1315 *---------------------------------------------------------------------------*/
1316 void
1317 vga_screen_on(void)
1318 {
1319 unsigned char old;
1320
1321 outb(TS_INDEX, TS_SYNCRESET);
1322 outb(TS_DATA, 0x01); /* synchronous reset */
1323
1324 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1325 old = inb(TS_DATA); /* get current value */
1326
1327 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1328 outb(TS_DATA, (old & ~0x20)); /* screen off bit off */
1329
1330 outb(TS_INDEX, TS_SYNCRESET);
1331 outb(TS_DATA, 0x03); /* clear synchronous reset */
1332 }
1333
1334 /*---------------------------------------------------------------------------*
1335 * compute character set base address (in kernel map)
1336 *---------------------------------------------------------------------------*/
1337 static unsigned char *
1338 compute_charset_base(unsigned fontset)
1339 {
1340 unsigned char *d = (unsigned char *)Crtat;
1341
1342 static int charset_offset[8] = { 0x0000, 0x4000, 0x8000, 0xC000,
1343 0x2000, 0x6000, 0xA000, 0xE000 };
1344
1345 static int charsetw_offset[8] = { 0x0000, 0x2000, 0x4000, 0x6000,
1346 0x8000, 0xA000, 0xC000, 0xE000 };
1347
1348 switch(adaptor_type)
1349 {
1350 case EGA_ADAPTOR:
1351 fontset = (fontset > 3) ? 3 : fontset;
1352 break;
1353
1354 case VGA_ADAPTOR:
1355 fontset = (fontset > 7) ? 7 : fontset;
1356 break;
1357
1358 default:
1359 return 0;
1360 }
1361
1362 if(color)
1363 d -= (0xB8000 - 0xA0000); /* Point to 0xA0000 */
1364 else
1365 d -= (0xB0000 - 0xA0000); /* Point to 0xA0000 */
1366
1367 if(vsp->wd132col)
1368 d += charsetw_offset[fontset]; /* Load into Character set n */
1369 else
1370 d += charset_offset[fontset]; /* Load into Character set n */
1371
1372 return d;
1373 }
1374
1375 /*---------------------------------------------------------------------------*
1376 * load a char into ega/vga character generator ram
1377 *---------------------------------------------------------------------------*/
1378 void
1379 loadchar(int fontset, int character, int char_scanlines, u_char *char_table)
1380 {
1381 unsigned char *d;
1382 unsigned char *bak;
1383 int j, k;
1384
1385 if((d = compute_charset_base(fontset)) == 0)
1386 return;
1387
1388 d += (character * 32); /* 32 bytes per character */
1389
1390 if(vsp->wd132col &&
1391 (fontset == 1||fontset == 3||fontset == 5||fontset == 7))
1392 setchargen3(); /* access chargen ram */
1393 else
1394 setchargen(); /* access chargen ram */
1395
1396 for(j = k = 0; j < char_scanlines; j++) /* x bit high characters */
1397 {
1398 *d = char_table[k];
1399 d++;
1400 k++;
1401 }
1402 for(; j < 32; j++) /* Up to 32 bytes per character image*/
1403 {
1404 *d = 0x00;
1405 d++;
1406 }
1407
1408 resetchargen(); /* access video ram */
1409
1410 if(saved_charsets[fontset] == 0)
1411 saved_charsets[fontset] =
1412 (u_char *)malloc(32 * 256, M_DEVBUF, M_WAITOK);
1413
1414 if((bak = saved_charsets[fontset]))
1415 {
1416 /* make a backup copy of this char */
1417 bak += (character * 32);
1418 bzero(bak, 32);
1419 bcopy(char_table, bak, char_scanlines);
1420 }
1421 #ifdef DIAGNOSTIC
1422 else
1423 panic("pcvt loadchar: no backup buffer");
1424 #endif /* DIAGNOSTIC */
1425 }
1426
1427 /*---------------------------------------------------------------------------*
1428 * save/restore character set n to addr b
1429 * since there are always backed up copies, we do not save anything here
1430 * parameter "b" is totally ignored
1431 *---------------------------------------------------------------------------*/
1432 void
1433 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1434 {
1435 unsigned char *d = compute_charset_base(n);
1436
1437 if(save_it)
1438 return;
1439
1440 if(saved_charsets[n] == 0)
1441 #ifdef DIAGNOSTIC
1442 panic("pcvt: restoring unbuffered charset");
1443 #else
1444 return;
1445 #endif
1446
1447 #ifdef DIAGNOSTIC
1448 if(d == 0)
1449 panic("vga_move_charset: wrong adaptor");
1450 #endif
1451
1452 if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
1453 {
1454 setchargen3();
1455 d -= 0x2000;
1456 }
1457 else
1458 {
1459 setchargen();
1460 }
1461
1462 /* PLEASE, leave the following alone using bcopyb, as several */
1463 /* chipsets have problems if their memory is accessed with 32 */
1464 /* or 16 bits wide, don't change this to using bcopy for speed! */
1465
1466 bcopyb(saved_charsets[n], d,
1467 256 /* chars */ * 32 /* bytes per char */);
1468
1469 resetchargen();
1470 }
1471
1472 #ifndef XSERVER
1473 /*---------------------------------------------------------------------------*
1474 * switch to virtual screen n (0 ... PCVT_NSCREENS-1)
1475 *---------------------------------------------------------------------------*/
1476 void
1477 vgapage(int n)
1478 {
1479 int cols = vsp->maxcol; /* get current col val */
1480
1481 if(n < 0 || n >= totalscreens)
1482 return;
1483
1484 /* video board memory -> kernel memory */
1485
1486 bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR);
1487
1488 vsp->Crtat = vsp->Memory; /* operate in memory now */
1489
1490 /* update global screen pointers/variables */
1491
1492 current_video_screen = n; /* current screen no */
1493
1494 vsp = &vs[n]; /* current video state ptr */
1495
1496 /* kernel memory -> video board memory */
1497
1498 bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR);
1499
1500 vsp->Crtat = Crtat; /* operate on screen now */
1501
1502 outb(addr_6845, CRTC_STARTADRH);
1503 outb(addr_6845+1, 0);
1504 outb(addr_6845, CRTC_STARTADRL);
1505 outb(addr_6845+1, 0);
1506
1507 select_vga_charset(vsp->vga_charset);
1508
1509 if(vsp->maxcol != cols)
1510 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
1511
1512 outb(addr_6845, CRTC_CURSORH); /* select high register */
1513 outb(addr_6845+1, vsp->cur_offset >> 8);
1514 outb(addr_6845, CRTC_CURSORL); /* select low register */
1515 outb(addr_6845+1, vsp->cur_offset);
1516
1517 if(vsp->cursor_on)
1518 {
1519 outb(addr_6845, CRTC_CURSTART); /* select high register */
1520 outb(addr_6845+1, vsp->cursor_start);
1521 outb(addr_6845, CRTC_CUREND); /* select low register */
1522 outb(addr_6845+1, vsp->cursor_end);
1523 }
1524 else
1525 {
1526 sw_cursor(0);
1527 }
1528
1529 if(adaptor_type == VGA_ADAPTOR)
1530 {
1531 unsigned i;
1532
1533 /* switch VGA DAC palette entries */
1534
1535 for(i = 0; i < NVGAPEL; i++)
1536 vgapaletteio(i, &vsp->palette[i], 1);
1537 }
1538
1539 update_led(); /* update led's */
1540
1541 update_hp(vsp); /* update fkey labels, if present */
1542 }
1543 #endif /* XSERVER */
1544
1545 /*---------------------------------------------------------------------------*
1546 * test if it is a vga
1547 *---------------------------------------------------------------------------*/
1548 int
1549 vga_test(void)
1550 {
1551 u_char old, new, check;
1552
1553 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1554 old = inb(addr_6845+1); /* get current value */
1555
1556 new = old | CURSOR_ON_BIT; /* set cursor on by setting bit 5 on */
1557
1558 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1559 outb(addr_6845+1,new); /* cursor should be on now */
1560
1561 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1562 check = inb(addr_6845+1); /* get current value */
1563
1564 if(check != new)
1565 {
1566 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1567 outb(addr_6845+1,old); /* failsafe */
1568 return(0); /* must be ega */
1569 }
1570
1571 new = old & ~CURSOR_ON_BIT; /* turn cursor off by clearing bit 5 */
1572
1573 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1574 outb(addr_6845+1,new); /* cursor should be off now */
1575
1576 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1577 check = inb(addr_6845+1); /* get current value */
1578
1579 if(check != new)
1580 {
1581 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1582 outb(addr_6845+1,old); /* failsafe */
1583 return(0); /* must be ega */
1584 }
1585
1586 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1587 outb(addr_6845+1,old); /* failsafe */
1588
1589 return(1); /* vga */
1590 }
1591
1592 /*---------------------------------------------------------------------------*
1593 * convert upper/lower sixel font array to vga font array
1594 *---------------------------------------------------------------------------*/
1595 void
1596 sixel_vga(struct sixels *sixelp, u_char *vgachar)
1597 {
1598 register int i, j;
1599 register int shift;
1600 register u_char mask;
1601
1602 for(j = 0; j < 16; j++)
1603 vgachar[j] = 0;
1604
1605 mask = 0x01;
1606 for(j = 0; j < 6; j++)
1607 {
1608 for(i = 0, shift = 7; i < 8; i++, shift--)
1609 vgachar[j] |= ((((sixelp->upper[i]) & mask) >> j)
1610 << shift);
1611 mask <<= 1;
1612 }
1613
1614 mask = 0x01;
1615 for(j = 0; j < 4; j++)
1616 {
1617 for(i = 0, shift = 7; i < 8; i++, shift--)
1618 vgachar[j+6] |= ((((sixelp->lower[i]) & mask) >>j)
1619 << shift);
1620 mask <<= 1;
1621 }
1622 }
1623
1624 /*---------------------------------------------------------------------------*
1625 * Expand 8x10 EGA/VGA characters to 8x16 EGA/VGA characters
1626 *---------------------------------------------------------------------------*/
1627 void
1628 vga10_vga16(u_char *invga, u_char *outvga)
1629 {
1630 register int i,j;
1631
1632 /*
1633 * Keep the top and bottom scanlines the same and double every scan
1634 * line in between.
1635 */
1636
1637 outvga[0] = invga[0];
1638 outvga[1] = invga[1];
1639 outvga[14] = invga[8];
1640 outvga[15] = invga[9];
1641
1642 for(i = j = 2;i < 8 && j < 14;i++,j += 2)
1643 {
1644 outvga[j] = invga[i];
1645 outvga[j+1] = invga[i];
1646 }
1647 }
1648
1649 /*---------------------------------------------------------------------------*
1650 * Expand 8x10 EGA/VGA characters to 8x14 EGA/VGA characters
1651 *---------------------------------------------------------------------------*/
1652 void
1653 vga10_vga14(u_char *invga, u_char *outvga)
1654 {
1655 register int i;
1656
1657 /*
1658 * Double the top two and bottom two scanlines and copy everything
1659 * in between.
1660 */
1661
1662 outvga[0] = invga[0];
1663 outvga[1] = invga[0];
1664 outvga[2] = invga[1];
1665 outvga[3] = invga[1];
1666 outvga[10] = invga[8];
1667 outvga[11] = invga[8];
1668 outvga[12] = invga[9];
1669 outvga[13] = invga[9];
1670
1671 for(i = 2;i < 8;i++)
1672 outvga[i+2] = invga[i];
1673 }
1674
1675 /*---------------------------------------------------------------------------*
1676 * Expand 8x10 EGA/VGA characters to 8x10 EGA/VGA characters
1677 *---------------------------------------------------------------------------*/
1678 void
1679 vga10_vga10(u_char *invga, u_char *outvga)
1680 {
1681 register int i;
1682
1683 for(i = 0;i < 10;i++)
1684 outvga[i] = invga[i];
1685 }
1686
1687 /*---------------------------------------------------------------------------*
1688 * Contract 8x10 EGA/VGA characters to 8x8 EGA/VGA characters
1689 *---------------------------------------------------------------------------*/
1690 void
1691 vga10_vga8(u_char *invga, u_char *outvga)
1692 {
1693 /* Skip scanlines 3 and 7 */
1694
1695 outvga[0] = invga[0];
1696 outvga[1] = invga[1];
1697 outvga[2] = invga[2];
1698 outvga[3] = invga[4];
1699 outvga[4] = invga[5];
1700 outvga[5] = invga[6];
1701 outvga[6] = invga[8];
1702 outvga[7] = invga[9];
1703 }
1704
1705 /*---------------------------------------------------------------------------*
1706 * disconnect attribute bit 3 from generating intensity
1707 * (and use it for a second character set !)
1708 *---------------------------------------------------------------------------*/
1709 void
1710 set_2ndcharset(void)
1711 {
1712 if(color) /* prepare to access index register! */
1713 inb(GN_INPSTAT1C);
1714 else
1715 inb(GN_INPSTAT1M);
1716
1717 /* select color plane enable reg, caution: set ATC access bit ! */
1718
1719 outb(ATC_INDEX, (ATC_COLPLEN | ATC_ACCESS));
1720 outb(ATC_DATAW, 0x07); /* disable plane 3 */
1721 }
1722
1723 #if PCVT_SCREENSAVER
1724 #if PCVT_PRETTYSCRNS
1725
1726 /*---------------------------------------------------------------------------*
1727 * produce some kinda random number, had a look into the system library...
1728 *---------------------------------------------------------------------------*/
1729 static u_short
1730 getrand(void)
1731 {
1732 static unsigned long seed = 1;
1733 register u_short res = (u_short)seed;
1734 seed = seed * 1103515245L + time_second;
1735 return res;
1736 }
1737
1738 /*---------------------------------------------------------------------------*
1739 * produce "nice" screensaving ....
1740 *---------------------------------------------------------------------------*/
1741 static void
1742 scrnsv_blink(void * arg)
1743 {
1744 static struct rgb blink_rgb[8] =
1745 {
1746 {63, 63, 63}, /* white */
1747 {0, 63, 42}, /* pale green */
1748 {63, 63, 0}, /* yellow */
1749 {63, 21, 63}, /* violet */
1750 {42, 63, 0}, /* yellow-green */
1751 {63, 42, 0}, /* amber */
1752 {63, 42, 42}, /* rose */
1753 {21, 42, 42} /* cyan */
1754 };
1755 register u_short r = getrand();
1756 unsigned pos = (r % (scrnsv_size / 2));
1757
1758 *scrnsv_current = /* (0 << 8) + */ ' ';
1759 scrnsv_current = vsp->Crtat + pos;
1760 *scrnsv_current = (7 /* LIGHTGRAY */ << 8) + '*';
1761 if(adaptor_type == VGA_ADAPTOR)
1762 vgapaletteio(7 /* LIGHTGRAY */, &blink_rgb[(r >> 4) & 7], 1);
1763 scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
1764 }
1765
1766 #endif /* PCVT_PRETTYSCRNS */
1767
1768 /*---------------------------------------------------------------------------*
1769 * set timeout time
1770 *---------------------------------------------------------------------------*/
1771 #ifndef XSERVER
1772 static void
1773 pcvt_set_scrnsv_tmo(int timeout)
1774 #else
1775 void
1776 pcvt_set_scrnsv_tmo(int timeout)
1777 #endif /* XSERVER */
1778 {
1779 int x = splhigh();
1780
1781 if(scrnsv_timeout)
1782 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
1783
1784 scrnsv_timeout = timeout;
1785 pcvt_scrnsv_reset(); /* sanity */
1786 splx(x);
1787 if(timeout == 0 && savedscreen)
1788 {
1789 /* release buffer when screen saver turned off */
1790 free(savedscreen, M_TEMP);
1791 savedscreen = (u_short *)0;
1792 }
1793 }
1794
1795 #if PCVT_GREENSAVER
1796 /*---------------------------------------------------------------------------*
1797 * switch monitor on/off
1798 *---------------------------------------------------------------------------*/
1799 static void
1800 green_saver(int blank)
1801 {
1802 u_char val;
1803
1804 if (blank)
1805 {
1806 outb(TS_INDEX, 0x01);
1807 val = inb(TS_DATA);
1808 outb(TS_INDEX, 0x01);
1809 outb(TS_DATA, val | 0x20);
1810 outb(addr_6845, 0x17);
1811 val = inb(addr_6845 + 1);
1812 outb(addr_6845 + 1, val & ~0x80);
1813 }
1814 else
1815 {
1816 outb(TS_INDEX, 0x01);
1817 val = inb(TS_DATA);
1818 outb(TS_INDEX, 0x01);
1819 outb(TS_DATA, val & 0xDF);
1820 outb(addr_6845, 0x17);
1821 val = inb(addr_6845 + 1);
1822 outb(addr_6845 + 1, val | 0x80);
1823 }
1824 }
1825 #endif
1826
1827 /*---------------------------------------------------------------------------*
1828 * we were timed out
1829 *---------------------------------------------------------------------------*/
1830 static void
1831 scrnsv_timedout(void *arg)
1832 {
1833 /* this function is called by timeout() */
1834 /* raise priority to avoid conflicts with kbd intr */
1835 int x = spltty();
1836
1837 /*
1838 * due to some undefined problems with video adaptor RAM
1839 * access timing, the following has been splitted into
1840 * two pieces called subsequently with a time difference
1841 * of 100 millisec
1842 */
1843
1844 if(++scrnsv_active == 1)
1845 {
1846 register size_t s;
1847 /*
1848 * first, allocate a buffer
1849 * do only if none allocated yet or another size required
1850 * this reduces malloc() overhead by avoiding successive
1851 * calls to malloc() and free() if they would have requested
1852 * the same buffer
1853 *
1854 * XXX This is inherited from old days where no buffering
1855 * happened at all. Meanwhile we should use the standard
1856 * screen buffer instead. Any volunteers? :-) [At least,
1857 * this code proved to work...]
1858 */
1859
1860 s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
1861
1862 if(savedscreen == (u_short *)0 || s != scrnsv_size)
1863 {
1864 /* really need to allocate */
1865 if(savedscreen)
1866 free(savedscreen, M_TEMP);
1867 scrnsv_size = s;
1868 if((savedscreen =
1869 (u_short *)malloc(s, M_TEMP, M_NOWAIT))
1870 == (u_short *)0)
1871 {
1872 /*
1873 * didn't get the buffer memory,
1874 * turn off screen saver
1875 */
1876 scrnsv_timeout = scrnsv_active = 0;
1877 splx(x);
1878 return;
1879 }
1880 }
1881 /* save current screen */
1882 bcopy(vsp->Crtat, savedscreen, scrnsv_size);
1883
1884 /* on VGA's, make sure palette is set to blank screen */
1885 if(adaptor_type == VGA_ADAPTOR)
1886 {
1887 struct rgb black = {0, 0, 0};
1888 vgapaletteio(0 /* BLACK */, &black, 1);
1889 }
1890 /* prepare for next time... */
1891 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL, hz / 10);
1892 }
1893 else
1894 {
1895 /* second call, now blank the screen */
1896 /* fill screen with blanks */
1897 fillw(/* (BLACK<<8) + */ ' ', vsp->Crtat, scrnsv_size / 2);
1898
1899 #if PCVT_PRETTYSCRNS
1900 scrnsv_current = vsp->Crtat;
1901 scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
1902 #endif /* PCVT_PRETTYSCRNS */
1903
1904 sw_cursor(0); /* cursor off on mda/cga */
1905
1906 #if PCVT_GREENSAVER
1907 green_saver(1);
1908 #endif
1909 }
1910 splx(x);
1911 }
1912
1913 /*---------------------------------------------------------------------------*
1914 * interface to screensaver "subsystem"
1915 *---------------------------------------------------------------------------*/
1916 void
1917 pcvt_scrnsv_reset(void)
1918 {
1919 /*
1920 * to save lotta time with superfluous timeout()/untimeout() calls
1921 * when having massive output operations, we remember the last
1922 * second of kernel timer we've rescheduled scrnsv_timedout()
1923 */
1924 static long last_schedule = 0L;
1925 register int x = splhigh();
1926 int reschedule = 0;
1927
1928 if((scrnsv_active == 1 || scrnsv_timeout) &&
1929 last_schedule != time_second)
1930 {
1931 last_schedule = time_second;
1932 reschedule = 1;
1933 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
1934 }
1935 if(scrnsv_active)
1936 {
1937
1938 #if PCVT_PRETTYSCRNS
1939 if(scrnsv_active > 1)
1940 untimeout(scrnsv_blink, NULL, scrnsv_blink_ch);
1941 #endif /* PCVT_PRETTYSCRNS */
1942
1943 bcopy(savedscreen, vsp->Crtat, scrnsv_size);
1944 if(adaptor_type == VGA_ADAPTOR)
1945 {
1946 /* back up VGA palette info */
1947 vgapaletteio(0 /* BLACK */, &vsp->palette[0], 1);
1948
1949 #if PCVT_PRETTYSCRNS
1950 vgapaletteio(7 /* LIGHTGRAY */, &vsp->palette[7], 1);
1951 #endif /* PCVT_PRETTYSCRNS */
1952
1953 #if PCVT_GREENSAVER
1954 green_saver(0);
1955 #endif
1956 }
1957 scrnsv_active = 0;
1958
1959 if(vsp->cursor_on)
1960 sw_cursor(1); /* cursor on */
1961 }
1962
1963 if(reschedule)
1964 {
1965 /* mark next timeout */
1966 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL,
1967 scrnsv_timeout * hz);
1968 }
1969 splx(x);
1970 }
1971
1972 #endif /* PCVT_SCREENSAVER */
1973
1974 /*---------------------------------------------------------------------------*
1975 * switch cursor on/off
1976 *---------------------------------------------------------------------------*/
1977 void
1978 sw_cursor(int onoff)
1979 {
1980 if(adaptor_type == EGA_ADAPTOR)
1981 {
1982 int start, end;
1983 if(onoff)
1984 {
1985 start = vsp->cursor_start;
1986 end = vsp->cursor_end;
1987 }
1988 else
1989 {
1990 int cs = vs[current_video_screen].vga_charset;
1991
1992 cs = (cs < 0) ? 0 : ((cs < totalfonts) ?
1993 cs : totalfonts-1);
1994
1995 start = (vgacs[cs].char_scanlines & 0x1F) + 1;
1996 end = 0;
1997 }
1998 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1999 outb(addr_6845+1, start);
2000 outb(addr_6845,CRTC_CUREND); /* cursor end reg */
2001 outb(addr_6845+1, end);
2002 }
2003 else /* mda, cga, vga */
2004 {
2005 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
2006 if(onoff)
2007 outb(addr_6845+1, vsp->cursor_start);
2008 else
2009 outb(addr_6845+1, CURSOR_ON_BIT);
2010 }
2011 }
2012
2013 /*---------------------------------------------------------------------------*
2014 * cold init support, if a mono monitor is attached to a
2015 * vga or ega, it comes up with a mda emulation. switch
2016 * board to generic ega/vga mode in this case.
2017 *---------------------------------------------------------------------------*/
2018 void
2019 mda2egaorvga(void)
2020 {
2021 /*
2022 * program sequencer to access
2023 * video ram
2024 */
2025
2026 /* synchronous reset */
2027 outb(TS_INDEX, TS_SYNCRESET);
2028 outb(TS_DATA, 0x01);
2029
2030 /* write to map 0 & 1 */
2031 outb(TS_INDEX, TS_WRPLMASK);
2032 outb(TS_DATA, 0x03);
2033
2034 /* odd-even addressing */
2035 outb(TS_INDEX, TS_MEMMODE);
2036 outb(TS_DATA, 0x03);
2037
2038 /* clear synchronous reset */
2039 outb(TS_INDEX, TS_SYNCRESET);
2040 outb(TS_DATA, 0x03);
2041
2042 /*
2043 * program graphics controller
2044 * to access character
2045 * generator
2046 */
2047
2048 /* select map 0 for cpu reads */
2049 outb(GDC_INDEX, GDC_RDPLANESEL);
2050 outb(GDC_DATA, 0x00);
2051
2052 /* enable odd-even addressing */
2053 outb(GDC_INDEX, GDC_MODE);
2054 outb(GDC_DATA, 0x10);
2055
2056 /* map starts at 0xb000 */
2057 outb(GDC_INDEX, GDC_MISC);
2058 outb(GDC_DATA, 0x0a);
2059 }
2060
2061 /* ------------------------- E O F ------------------------------------------*/
Cache object: 043f711287f12e1e9a082e3c57828861
|