Merge from vendor branch READLINE:
[dragonfly.git] / sys / dev / video / pcvt / i386 / pcvt_drv.c
1 /*
2  * Copyright (c) 1999 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) 1993 Charles Hannum.
9  *
10  * All rights reserved.
11  *
12  * Parts of this code regarding the NetBSD interface were written
13  * by Charles Hannum.
14  *
15  * This code is derived from software contributed to Berkeley by
16  * William Jolitz and Don Ahn.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  *    notice, this list of conditions and the following disclaimer in the
25  *    documentation and/or other materials provided with the distribution.
26  * 3. All advertising materials mentioning features or use of this software
27  *    must display the following acknowledgement:
28  *      This product includes software developed by
29  *      Hellmuth Michaelis, Brian Dunford-Shore, Joerg Wunsch, Scott Turner
30  *      and Charles Hannum.
31  * 4. The name authors may not be used to endorse or promote products
32  *    derived from this software without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
35  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
38  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  */
45
46 /*---------------------------------------------------------------------------*
47  *
48  *      pcvt_drv.c      VT220 Driver Main Module / OS - Interface
49  *      ---------------------------------------------------------
50  *
51  *      Last Edit-Date: [Mon Dec 27 14:03:36 1999]
52  *
53  * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_drv.c,v 1.63.2.1 2001/02/26 04:23:13 jlemon Exp $
54  * $DragonFly: src/sys/dev/video/pcvt/i386/Attic/pcvt_drv.c,v 1.12 2004/09/19 02:43:26 dillon Exp $
55  *
56  *---------------------------------------------------------------------------*/
57
58 #include "use_vt.h"
59 #if NVT > 0
60
61 #define EXTERN                  /* allocate mem */
62
63 #include "pcvt_hdr.h"   /* global include */
64
65 #if PCVT_FREEBSD >= 200
66 #include <sys/bus.h>
67 #include <machine/stdarg.h>
68 #else
69 #include "machine/stdarg.h"
70 #endif
71
72 extern int getchar (void);
73
74 #if PCVT_NETBSD
75         extern u_short *Crtat;
76 #endif /* PCVT_NETBSD */
77
78 static void vgapelinit(void);   /* read initial VGA DAC palette */
79
80 #if defined XSERVER && !PCVT_USL_VT_COMPAT
81 static int pcvt_xmode_set(int on, struct thread *td); /* initialize for X mode */
82 #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
83
84 #ifdef _DEV_KBD_KBDREG_H_
85 static void pcvt_reset_detect_timeout(int unit, int hz);
86 static void detect_kbd(void *arg);
87 static kbd_callback_func_t pcevent;
88 #endif
89
90 static cn_probe_t       pccnprobe;
91 static cn_init_t        pccninit;
92 static cn_term_t        pccnterm;
93 static cn_getc_t        pccngetc;
94 static cn_checkc_t      pccncheckc;
95 static cn_putc_t        pccnputc;
96
97 CONS_DRIVER(pc, pccnprobe, pccninit, pccnterm, pccngetc, pccncheckc, pccnputc,
98             NULL);
99
100 static  d_open_t        pcopen;
101 static  d_close_t       pcclose;
102 static  d_ioctl_t       pcioctl;
103 static  d_mmap_t        pcmmap;
104
105 #define CDEV_MAJOR      12
106 struct cdevsw pc_cdevsw = {
107         /* name */      "vt",
108         /* maj */       CDEV_MAJOR,
109         /* flags */     D_TTY | D_KQFILTER,
110         /* port */      NULL,
111         /* clone */     NULL,
112
113         /* open */      pcopen,
114         /* close */     pcclose,
115         /* read */      ttyread,
116         /* write */     ttywrite,
117         /* ioctl */     pcioctl,
118         /* poll */      ttypoll,
119         /* mmap */      pcmmap,
120         /* strategy */  nostrategy,
121         /* dump */      nodump,
122         /* psize */     nopsize,
123         /* kqfilter */  ttykqfilter
124 };
125
126 static struct callout   pcvt_timeout_ch;
127
128 #if PCVT_NETBSD > 100   /* NetBSD-current Feb 20 1995 */
129 int
130 pcprobe(struct device *parent, void *match, void *aux)
131 #else
132 #if PCVT_NETBSD > 9
133 int
134 pcprobe(struct device *parent, struct device *self, void *aux)
135 #else
136 int
137 pcprobe(struct isa_device *dev)
138 #endif /* PCVT_NETBSD > 9 */
139 #endif /* PCVT_NETBSD > 100 */
140 {
141 #ifdef _DEV_KBD_KBDREG_H_
142         int i;
143
144         if (kbd == NULL) {
145                 reset_keyboard = 0;
146                 kbd_configure(KB_CONF_PROBE_ONLY);
147                 i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)dev->id_unit);
148                 if ((i < 0) || ((kbd = kbd_get_keyboard(i)) == NULL))
149                         return (-1);
150         }
151         reset_keyboard = 1;             /* it's now safe to do kbd reset */
152 #endif /* _DEV_KBD_KBDREG_H_ */
153
154         kbd_code_init();
155
156 #if PCVT_NETBSD > 9
157         ((struct isa_attach_args *)aux)->ia_iosize = 16;
158         return 1;
159 #else
160 #ifdef _DEV_KBD_KBDREG_H_
161         return (-1);
162 #elif PCVT_NETBSD || PCVT_FREEBSD
163         return (16);
164 #else
165         return 1;
166 #endif /* PCVT_NETBSD || PCVT_FREEBSD */
167 #endif /* PCVT_NETBSD > 9 */
168
169 }
170
171 #if PCVT_NETBSD > 9
172 void
173 pcattach(struct device *parent, struct device *self, void *aux)
174 {
175         struct isa_attach_args *ia = aux;
176         static struct intrhand vthand;
177 #else
178 int
179 pcattach(struct isa_device *dev)
180 {
181 #endif /* PCVT_NETBSD > 9 */
182
183         int i;
184
185         if ((pcvt_timeout_ch.c_flags & CALLOUT_DID_INIT) == 0)
186                 callout_init(&pcvt_timeout_ch);
187         pcvt_support_init();
188         vt_coldmalloc();                /* allocate memory for screens */
189
190 #ifdef _DEV_KBD_KBDREG_H_
191         if (kbd == NULL)
192                 pcvt_reset_detect_timeout(dev->id_unit, hz * 2);
193 #endif /* _DEV_KBD_KBDREG_H_ */
194
195 #if PCVT_NETBSD || PCVT_FREEBSD
196
197 #if PCVT_NETBSD > 9
198         printf(": ");
199 #else
200         printf("vt%d: ", dev->id_unit);
201 #endif /* PCVT_NETBSD > 9 */
202
203         switch(adaptor_type)
204         {
205                 case MDA_ADAPTOR:
206                         printf("mda");
207                         break;
208
209                 case CGA_ADAPTOR:
210                         printf("cga");
211                         break;
212
213                 case EGA_ADAPTOR:
214                         printf("ega");
215                         break;
216
217                 case VGA_ADAPTOR:
218                         printf("%s, ", (char *)vga_string(vga_type));
219                         if(can_do_132col)
220                                 printf("80/132 col");
221                         else
222                                 printf("80 col");
223                         vgapelinit();
224                         break;
225
226                 default:
227                         printf("unknown");
228                         break;
229         }
230
231         if(color == 0)
232                 printf(", mono");
233         else
234                 printf(", color");
235
236         printf(", %d scr, ", totalscreens);
237
238         switch(keyboard_type)
239         {
240                 case KB_AT:
241                         printf("at-");
242                         break;
243
244                 case KB_MFII:
245                         printf("mf2-");
246                         break;
247
248                 default:
249                         printf("unknown ");
250                         break;
251         }
252
253         printf("kbd, [R%s]\n", PCVT_REL);
254
255 #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
256
257         for(i = 0; i < totalscreens; i++)
258         {
259
260 #if PCVT_NETBSD
261                 pc_tty[i] = ttymalloc();
262                 vs[i].vs_tty = pc_tty[i];
263 #else /* !PCVT_NETBSD */
264                 pccons[i] = ttymalloc(pccons[i]);
265                 vs[i].vs_tty = pccons[i];
266 #endif /* PCVT_NETBSD */
267
268         }
269
270 #if PCVT_EMU_MOUSE
271 #if PCVT_NETBSD
272         pc_tty[totalscreens] = ttymalloc(); /* the mouse emulator tty */
273 #else /* !PCVT_NETBSD */
274         /* the mouse emulator tty */
275         pc_tty[totalscreens] = ttymalloc(pccons[totalscreens]);
276 #endif /* PCVT_NETBSD */
277 #endif /* PCVT_EMU_MOUSE */
278
279 #if PCVT_NETBSD
280         pcconsp = pc_tty[0];
281 #else  /* !PCVT_NETBSD */
282         pcconsp = pccons[0];
283 #endif  /* PCVT_NETBSD */
284
285 #endif /* #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
286
287 #else /* !PCVT_NETBSD && !PCVT_FREEBSD*/
288
289         switch(adaptor_type)
290         {
291                 case MDA_ADAPTOR:
292                         printf(" <mda");
293                         break;
294
295                 case CGA_ADAPTOR:
296                         printf(" <cga");
297                         break;
298
299                 case EGA_ADAPTOR:
300                         printf(" <ega");
301                         break;
302
303                 case VGA_ADAPTOR:
304                         printf(" <%s,", (char *)vga_string(vga_type));
305                         if(can_do_132col)
306                                 printf("80/132 col");
307                         else
308                                 printf("80 col");
309                         vgapelinit();
310                         break;
311
312                 default:
313                         printf(" <unknown");
314                         break;
315         }
316
317         if(color == 0)
318                 printf(",mono");
319         else
320                 printf(",color");
321
322         printf(",%d scr,", totalscreens);
323
324         switch(keyboard_type)
325         {
326                 case KB_AT:
327                         printf("at-");
328                         break;
329
330                 case KB_MFII:
331                         printf("mf2-");
332                         break;
333
334                 default:
335                         printf("unknown ");
336                         break;
337         }
338
339         printf("kbd,[R%s]>", PCVT_REL);
340
341 #endif  /* PCVT_NETBSD || PCVT_FREEBSD */
342
343 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
344         cdevsw_add(&pc_cdevsw, 0, 0);
345         for(i = 0; i < totalscreens; i++)
346         {
347                 ttyregister(&pccons[i]);
348                 vs[i].vs_tty = &pccons[i];
349                 make_dev(&pc_cdevsw, i, UID_ROOT, GID_WHEEL, 0600, "ttyv%r", i);
350         }
351 #endif /* !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
352
353         async_update(UPDATE_START);     /* start asynchronous updates */
354
355 #if PCVT_NETBSD > 9
356
357         vthand.ih_fun = pcrint;
358         vthand.ih_arg = 0;
359         vthand.ih_level = IPL_TTY;
360
361 #if (PCVT_NETBSD > 100) && defined(IST_EDGE)
362         intr_establish(ia->ia_irq, IST_EDGE, &vthand);
363 #else /* PCVT_NETBSD > 100 */
364         intr_establish(ia->ia_irq, &vthand);
365 #endif /* PCVT_NETBSD > 100 */
366
367 #else /* PCVT_NETBSD > 9 */
368
369         dev->id_ointr = pcrint;
370
371         return 1;
372
373 #endif /* PCVT_NETBSD > 9 */
374
375 }
376
377 /* had a look at the friedl driver */
378
379 #if !PCVT_NETBSD
380
381 struct tty *
382 get_pccons(Dev_t dev)
383 {
384         int i = minor(dev);
385
386 #if PCVT_EMU_MOUSE
387         if(i == totalscreens)
388 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
389                 return(&pccons[i]);
390 #else
391                 return(pccons[i]);
392 #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
393 #endif /* PCVT_EMU_MOUSE */
394
395         if(i >= PCVT_NSCREENS)
396                 return(NULL);
397 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
398         return(&pccons[i]);
399 #else
400         return(pccons[i]);
401 #endif
402 }
403
404 #else
405
406 struct tty *
407 get_pccons(Dev_t dev)
408 {
409         int i = minor(dev);
410
411 #if PCVT_EMU_MOUSE
412         if(i == totalscreens)
413                 return(pc_tty[i]);
414 #endif /* PCVT_EMU_MOUSE */
415
416         if(i >= PCVT_NSCREENS)
417                 return(NULL);
418         return(pc_tty[i]);
419 }
420
421 #endif /* !PCVT_NETBSD */
422
423 /*---------------------------------------------------------------------------*
424  *              /dev/ttyc0, /dev/ttyc1, etc.
425  *---------------------------------------------------------------------------*/
426 int
427 pcopen(Dev_t dev, int flag, int mode, struct thread *td)
428 {
429         struct tty *tp;
430         struct video_state *vsx;
431         int s, retval;
432         int winsz = 0;
433         int i = minor(dev);
434
435 #if PCVT_EMU_MOUSE
436         if(i == totalscreens)
437                 vsx = 0;
438         else
439 #endif /* PCVT_EMU_MOUSE */
440
441         vsx = &vs[i];
442
443         if((tp = get_pccons(dev)) == NULL)
444                 return ENXIO;
445
446         dev->si_tty = tp;
447
448 #if PCVT_EMU_MOUSE
449         if(i == totalscreens)
450         {
451                 if(mouse.opened == 0)
452                         mouse.buttons = mouse.extendedseen =
453                                 mouse.breakseen = mouse.lastmove.tv_sec = 0;
454                 mouse.minor = i;
455                 mouse.opened++;
456         }
457         else
458 #endif /* PCVT_EMU_MOUSE */
459
460         vsx->openf++;
461
462         tp->t_oproc = pcstart;
463         tp->t_param = pcparam;
464         tp->t_stop = nottystop;
465         tp->t_dev = dev;
466
467         if ((tp->t_state & TS_ISOPEN) == 0)
468         {
469
470 #ifdef TS_WOPEN /* not (FreeBSD-1.1.5 or FreeBSD some time after 2.0.5) */
471                 tp->t_state |= TS_WOPEN;
472 #endif
473
474                 ttychars(tp);
475                 tp->t_iflag = TTYDEF_IFLAG;
476                 tp->t_oflag = TTYDEF_OFLAG;
477                 tp->t_cflag = TTYDEF_CFLAG;
478                 tp->t_lflag = TTYDEF_LFLAG;
479                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
480                 pcparam(tp, &tp->t_termios);
481                 (*linesw[tp->t_line].l_modem)(tp, 1);   /* fake connection */
482                 winsz = 1;                      /* set winsize later */
483         }
484         else if (tp->t_state & TS_XCLUDE && suser(td))
485                 return (EBUSY);
486
487 #if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
488         retval = ((*linesw[tp->t_line].l_open)(dev, tp));
489 #else
490         retval = ((*linesw[tp->t_line].l_open)(dev, tp, flag));
491 #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
492
493         if(winsz == 1)
494         {
495
496                 /*
497                  * The line discipline has clobbered t_winsize if TS_ISOPEN
498                  * was clear. (NetBSD PR #400 from Bill Sommerfeld)
499                  * We have to do this after calling the open routine, because
500                  * it does some other things in other/older *BSD releases -hm
501                  */
502
503                 s = spltty();
504
505                 tp->t_winsize.ws_col = vsx->maxcol;
506                 tp->t_winsize.ws_row = vsx->screen_rows;
507                 tp->t_winsize.ws_xpixel = (vsx->maxcol == 80)? 720: 1056;
508                 tp->t_winsize.ws_ypixel = 400;
509
510                 splx(s);
511         }
512
513         return(retval);
514 }
515
516 int
517 pcclose(Dev_t dev, int flag, int mode, struct thread *td)
518 {
519         struct tty *tp;
520         struct video_state *vsx;
521         int i = minor(dev);
522
523 #if PCVT_EMU_MOUSE
524         if(i == totalscreens)
525                 vsx = 0;
526         else
527 #endif /* PCVT_EMU_MOUSE */
528
529         vsx = &vs[i];
530
531         if((tp = get_pccons(dev)) == NULL)
532                 return ENXIO;
533
534         (*linesw[tp->t_line].l_close)(tp, flag);
535         ttyclose(tp);
536
537 #if PCVT_EMU_MOUSE
538         if(i == totalscreens)
539                 mouse.opened = 0;
540         else
541 #endif /* PCVT_EMU_MOUSE */
542
543         vsx->openf = 0;
544
545 #if PCVT_USL_VT_COMPAT
546 #if PCVT_EMU_MOUSE
547
548         if(i == totalscreens)
549                 return (0);
550
551 #endif /* PCVT_EMU_MOUSE */
552
553         reset_usl_modes(vsx);
554
555 #endif /* PCVT_USL_VT_COMPAT */
556
557         return(0);
558 }
559
560 int
561 pcioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
562 {
563         int error;
564         struct tty *tp;
565
566         if((tp = get_pccons(dev)) == NULL)
567                 return(ENXIO);
568
569         /* note that some ioctl's are global, e.g.  KBSTPMAT: There is
570          * only one keyboard and different repeat rates for instance between
571          * sessions are a suspicious wish. If you really need this make the
572          * appropriate variables arrays
573          */
574
575 #if PCVT_EMU_MOUSE
576         if(minor(dev) == totalscreens)
577         {
578                 if((error = mouse_ioctl(dev, cmd, data)) >= 0)
579                         return error;
580                 goto do_standard;
581         }
582 #endif /* PCVT_EMU_MOUSE */
583
584 #ifdef XSERVER
585 #if PCVT_USL_VT_COMPAT
586
587         if((error = usl_vt_ioctl(dev, cmd, data, flag, td->td_proc)) >= 0)
588                 return error;
589
590         /*
591          * just for compatibility:
592          * XFree86 < 2.0 and SuperProbe still might use it
593          *
594          * NB: THIS IS A HACK! Do not use it unless you explicitly need.
595          * Especially, since the vty is not put into process-controlled
596          * mode (this would require the application to co-operate), any
597          * attempts to switch vtys while this kind of X mode is active
598          * may cause serious trouble.
599          */
600         switch(cmd)
601         {
602           case CONSOLE_X_MODE_ON:
603           {
604             int i;
605
606             if((error = usl_vt_ioctl(dev, KDENABIO, 0, flag, td->td_proc)) > 0)
607               return error;
608
609             i = KD_GRAPHICS;
610             if((error = usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc))
611                > 0)
612               return error;
613
614             i = K_RAW;
615             error = usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
616             return error;
617           }
618
619           case CONSOLE_X_MODE_OFF:
620           {
621             int i;
622
623             (void)usl_vt_ioctl(dev, KDDISABIO, 0, flag, td->td_proc);
624
625             i = KD_TEXT;
626             (void)usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc);
627
628             i = K_XLATE;
629             (void)usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
630             return 0;
631           }
632
633
634           case CONSOLE_X_BELL:
635
636                 /*
637                  * If `data' is non-null, the first int value denotes
638                  * the pitch, the second a duration. Otherwise, behaves
639                  * like BEL.
640                  */
641
642                 if (data)
643                 {
644
645 #if PCVT_NETBSD
646                         sysbeep(((int *)data)[0],
647                                 ((int *)data)[1] * hz / 1000);
648 #else /* PCVT_NETBSD */
649                         sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
650                                 ((int *)data)[1] * hz / 3000);
651 #endif /* PCVT_NETBSD */
652
653                 }
654                 else
655                 {
656                         sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
657                 }
658                 return (0);
659
660           default: /* fall through */ ;
661         }
662
663 #else /* PCVT_USL_VT_COMPAT */
664
665         switch(cmd)
666         {
667           case CONSOLE_X_MODE_ON:
668                 return pcvt_xmode_set(1, td->td_proc);
669
670           case CONSOLE_X_MODE_OFF:
671                 return pcvt_xmode_set(0, td->td_proc);
672
673           case CONSOLE_X_BELL:
674
675                 /*
676                  * If `data' is non-null, the first int value denotes
677                  * the pitch, the second a duration. Otherwise, behaves
678                  * like BEL.
679                  */
680
681                 if (data)
682                 {
683
684 #if PCVT_NETBSD
685                         sysbeep(((int *)data)[0],
686                                 ((int *)data)[1] * hz / 1000);
687 #else /* PCVT_NETBSD */
688                         sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
689                                 ((int *)data)[1] * hz / 3000);
690 #endif /* PCVT_NETBSD */
691
692                 }
693                 else
694                 {
695                         sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
696                 }
697                 return (0);
698
699           default: /* fall through */ ;
700         }
701
702 #endif /* PCVT_USL_VT_COMPAT */
703 #endif /* XSERVER */
704
705         if((error = kbdioctl(dev,cmd,data,flag)) >= 0)
706                 return error;
707
708         if((error = vgaioctl(dev,cmd,data,flag)) >= 0)
709                 return error;
710
711 #if PCVT_EMU_MOUSE
712 do_standard:
713 #endif
714
715 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
716         if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td))
717             != ENOIOCTL)
718                 return (error);
719 #else
720         if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag)) >= 0)
721                 return(error);
722 #endif /* PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200 */
723
724 #if PCVT_NETBSD > 9
725         if((error = ttioctl(tp, cmd, data, flag, td)) >= 0)
726                 return (error);
727 #else
728         if((error = ttioctl(tp, cmd, data, flag)) != ENOIOCTL)
729                 return (error);
730 #endif /* PCVT_NETBSD > 9 */
731
732         return (ENOTTY);
733 }
734
735 int
736 pcmmap(Dev_t dev, vm_offset_t offset, int nprot)
737 {
738         if (offset > 0x20000 - PAGE_SIZE)
739                 return -1;
740         return i386_btop((0xa0000 + offset));
741 }
742
743 /*---------------------------------------------------------------------------*
744  *
745  *      handle a keyboard receive interrupt
746  *
747  *      NOTE: the keyboard is multiplexed by means of "pcconsp"
748  *      between virtual screens. pcconsp - switching is done in
749  *      the vgapage() routine
750  *
751  *---------------------------------------------------------------------------*/
752
753 #if PCVT_KBD_FIFO
754
755 u_char pcvt_kbd_fifo[PCVT_KBD_FIFO_SZ];
756 static int pcvt_kbd_wptr = 0;
757 int pcvt_kbd_rptr = 0;
758 short pcvt_kbd_count= 0;
759 static u_char pcvt_timeout_scheduled = 0;
760
761 static void
762 pcvt_timeout(void *arg)
763 {
764         u_char *cp;
765
766 #if PCVT_SLOW_INTERRUPT
767         int     s;
768 #endif
769
770         pcvt_timeout_scheduled = 0;
771
772 #if PCVT_SCREENSAVER
773         pcvt_scrnsv_reset();
774 #endif /* PCVT_SCREENSAVER */
775
776         while (pcvt_kbd_count)
777         {
778                 if (((cp = sgetc(1)) != 0) &&
779                     (vs[current_video_screen].openf))
780                 {
781
782 #if PCVT_NULLCHARS
783                         if(*cp == '\0')
784                         {
785                                 /* pass a NULL character */
786                                 (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
787                         }
788 /* XXX */               else
789 #endif /* PCVT_NULLCHARS */
790
791                         while (*cp)
792                                 (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
793                 }
794
795                 PCVT_DISABLE_INTR ();
796
797                 if (!pcvt_kbd_count)
798                         pcvt_timeout_scheduled = 0;
799
800                 PCVT_ENABLE_INTR ();
801         }
802
803         return;
804 }
805 #endif
806
807 #ifdef _DEV_KBD_KBDREG_H_
808
809 static 
810 void
811 pcvt_reset_detect_timeout(int unit, int hz)
812 {
813         static struct callout **prd_callout_ary;
814         static int nprd;
815         struct callout *prd_ch;
816
817         KKASSERT(unit >= 0 && unit < 4096);
818
819         /*
820          * Expand our callout pointer array if necessary
821          */
822         if (unit >= nprd) {
823                 struct callout **nary;
824                 int nunits;
825                 int i;
826
827                 nunits = (unit + 1 + 7) & ~7;
828                 nary = malloc(nunits * sizeof(struct callout *), 
829                                 M_DEVBUF, M_INTWAIT|M_ZERO);
830
831                 /* detect race if we blocked */
832                 if (nunits > nprd) {
833                         for (i = 0; i < nprd; ++i)
834                                 nary[i] = prd_callout_ary[i];
835                         prd_callout_ary = nary;
836                         nprd = nunits;
837                 } else {
838                         free(nary, M_DEVBUF);
839                 }
840         }
841
842         /*
843          * Malloc a callout if necessary
844          */
845         if ((prd_ch = prd_callout_ary[unit]) == NULL) {
846                 prd_ch = malloc(sizeof(struct callout), M_DEVBUF, M_INTWAIT);
847                 callout_init(prd_ch);
848
849                 /* detect race if we blocked */
850                 if (prd_callout_ary[unit] == NULL) {
851                         prd_callout_ary[unit] = prd_ch;
852                 } else {
853                         free(prd_ch, M_DEVBUF);
854                         prd_ch = prd_callout_ary[unit];
855                 }
856         }
857         callout_reset(prd_ch, hz, detect_kbd, (void *)unit);
858 }
859
860 static void
861 detect_kbd(void *arg)
862 {
863         int unit = (int)arg;
864         int i;
865
866         if (kbd != NULL)
867                 return;
868         i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
869         if (i >= 0)
870                 kbd = kbd_get_keyboard(i);
871         if (kbd != NULL)
872         {
873                 reset_keyboard = 1;     /* ok to reset the keyboard */
874                 kbd_code_init();
875                 return;
876         }
877         reset_keyboard = 0;
878         pcvt_reset_detect_timeout(unit, hz * 2);
879 }
880
881 int
882 pcevent(keyboard_t *thiskbd, int event, void *arg)
883 {
884         int unit = (int)arg;
885
886         if (thiskbd != kbd)
887                 return EINVAL;          /* shouldn't happen */
888
889         switch (event) {
890         case KBDIO_KEYINPUT:
891                 pcrint(unit);
892                 return 0;
893         case KBDIO_UNLOADING:
894                 reset_keyboard = 0;
895                 kbd = NULL;
896                 kbd_release(thiskbd, (void *)&kbd);
897                 pcvt_reset_detect_timeout(unit, hz * 4);
898                 return 0;
899         default:
900                 return EINVAL;
901         }
902 }
903 #endif /* _DEV_KBD_KBDREG_H_ */
904
905 void
906 pcrint(int unit)
907 {
908
909 #if PCVT_KBD_FIFO
910         u_char  dt;
911         u_char  ret = -1;
912
913 # if PCVT_SLOW_INTERRUPT
914         int     s;
915 # endif
916
917 # ifdef _DEV_KBD_KBDREG_H_
918         int     c;
919 # endif
920
921 #else /* !PCVT_KBD_FIFO */
922         u_char  *cp;
923 #endif /* PCVT_KBD_FIFO */
924
925 #if PCVT_SCREENSAVER
926         pcvt_scrnsv_reset();
927 #endif /* PCVT_SCREENSAVER */
928
929 #if PCVT_KBD_FIFO
930         if (kbd_polling)
931         {
932                 sgetc(1);
933                 return;
934         }
935
936 # ifndef _DEV_KBD_KBDREG_H_
937         while (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)    /* check 8042 buffer */
938         {
939                 ret = 1;                                /* got something */
940
941                 PCVT_KBD_DELAY();                       /* 7 us delay */
942
943                 dt = inb(CONTROLLER_DATA);              /* get it 8042 data */
944 # else 
945         while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) != -1)
946         {
947                 ret = 1;                                /* got something */
948                 dt = c;
949 # endif /* _DEV_KBD_KBDREG_H_ */
950
951                 if (pcvt_kbd_count >= PCVT_KBD_FIFO_SZ) /* fifo overflow ? */
952                 {
953                         log (LOG_WARNING, "pcvt: keyboard buffer overflow\n");
954                 }
955                 else
956                 {
957                         pcvt_kbd_fifo[pcvt_kbd_wptr++] = dt; /* data -> fifo */
958
959                         PCVT_DISABLE_INTR ();   /* XXX necessary ? */
960                         pcvt_kbd_count++;               /* update fifo count */
961                         PCVT_ENABLE_INTR ();
962
963                         if (pcvt_kbd_wptr >= PCVT_KBD_FIFO_SZ)
964                                 pcvt_kbd_wptr = 0;      /* wraparound pointer */
965                 }
966         }
967
968         if (ret == 1)   /* got data from keyboard ? */
969         {
970                 if (!pcvt_timeout_scheduled)    /* if not already active .. */
971                 {
972                         PCVT_DISABLE_INTR ();
973                         pcvt_timeout_scheduled = 1;     /* flag active */
974                                                         /* fire off */
975                         callout_reset(&pcvt_timeout_ch, hz / 100,
976                                         pcvt_timeout, NULL);
977                         PCVT_ENABLE_INTR ();
978                 }
979         }
980
981 #else /* !PCVT_KBD_FIFO */
982
983         if((cp = sgetc(1)) == 0)
984                 return;
985
986         if (kbd_polling)
987                 return;
988
989         if(!(vs[current_video_screen].openf))   /* XXX was vs[minor(dev)] */
990                 return;
991
992 #if PCVT_NULLCHARS
993         if(*cp == '\0')
994         {
995                 /* pass a NULL character */
996                 (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
997                 return;
998         }
999 #endif /* PCVT_NULLCHARS */
1000
1001         while (*cp)
1002                 (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
1003
1004 #endif /* PCVT_KBD_FIFO */
1005 }
1006
1007
1008 #if PCVT_NETBSD || PCVT_FREEBSD >= 200
1009
1010 void
1011 pcstart(struct tty *tp)
1012 {
1013         struct clist *rbp;
1014         int s, len;
1015         u_char buf[PCVT_PCBURST];
1016
1017         s = spltty();
1018
1019         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1020                 goto out;
1021
1022         tp->t_state |= TS_BUSY;
1023
1024         splx(s);
1025
1026         async_update(UPDATE_KERN);
1027
1028         rbp = &tp->t_outq;
1029
1030         /*
1031          * Call q_to_b() at spltty() to ensure that the queue is empty when
1032          * the loop terminates.
1033          */
1034
1035         s = spltty();
1036
1037         while((len = q_to_b(rbp, buf, PCVT_PCBURST)) > 0)
1038         {
1039                 if(vs[minor(tp->t_dev)].scrolling)
1040                         sgetc(31337);
1041                 
1042                 /*
1043                  * We need to do this outside spl since it could be fairly
1044                  * expensive and we don't want our serial ports to overflow.
1045                  */
1046                 splx(s);
1047                 sput(&buf[0], 0, len, minor(tp->t_dev));
1048                 s = spltty();
1049         }
1050
1051         tp->t_state &= ~TS_BUSY;
1052
1053 #ifndef TS_ASLEEP /* FreeBSD some time after 2.0.5 */
1054         ttwwakeup(tp);
1055 #else
1056         if (rbp->c_cc <= tp->t_lowat)
1057         {
1058                 if (tp->t_state&TS_ASLEEP)
1059                 {
1060                         tp->t_state &= ~TS_ASLEEP;
1061                         wakeup((caddr_t)rbp);
1062                 }
1063                 selwakeup(&tp->t_wsel);
1064         }
1065 #endif
1066 out:
1067         splx(s);
1068 }
1069
1070 void
1071 pcstop(struct tty *tp, int flag)
1072 {
1073 }
1074
1075 #else /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1076
1077 void
1078 pcstart(struct tty *tp)
1079 {
1080         int s;
1081         unsigned char c;
1082
1083         s = spltty();
1084
1085         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1086         {
1087                 goto out;
1088         }
1089
1090         for(;;)
1091         {
1092
1093 #if !(PCVT_FREEBSD > 114)
1094
1095 #if !(PCVT_FREEBSD > 111)
1096                 if (RB_LEN(&tp->t_out) <= tp->t_lowat)
1097 #else
1098                 if (RB_LEN(tp->t_out) <= tp->t_lowat)
1099 #endif
1100                 {
1101                         if (tp->t_state&TS_ASLEEP)
1102                         {
1103                                 tp->t_state &= ~TS_ASLEEP;
1104 #if !(PCVT_FREEBSD > 111)
1105                                 wakeup((caddr_t)&tp->t_out);
1106 #else
1107                                 wakeup((caddr_t)tp->t_out);
1108 #endif
1109                         }
1110
1111                         if (tp->t_wsel)
1112                         {
1113                                 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
1114                                 tp->t_wsel = 0;
1115                                 tp->t_state &= ~TS_WCOLL;
1116                         }
1117                 }
1118
1119 #else /* PCVT_FREEBSD > 114 */
1120                 if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT)
1121                     || tp->t_wsel) {
1122                         ttwwakeup(tp);
1123                 }
1124 #endif /* !PCVT_FREEBSD > 114 */
1125
1126 #if !(PCVT_FREEBSD > 111)
1127                 if (RB_LEN(&tp->t_out) == 0)
1128 #else
1129                 if (RB_LEN(tp->t_out) == 0)
1130 #endif
1131                 {
1132                         goto out;
1133                 }
1134
1135 #if !(PCVT_FREEBSD > 111)
1136                 c = getc(&tp->t_out);
1137 #else
1138                 c = getc(tp->t_out);
1139 #endif
1140
1141                 tp->t_state |= TS_BUSY; /* patch from Frank Maclachlan */
1142                 splx(s);
1143                 sput(&c, 0, 1, minor(tp->t_dev));
1144                 spltty();
1145                 tp->t_state &= ~TS_BUSY; /* patch from Frank Maclachlan */
1146         }
1147 out:
1148         splx(s);
1149 }
1150
1151 #endif /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1152
1153 /*---------------------------------------------------------------------------*
1154  *              /dev/console
1155  *---------------------------------------------------------------------------*/
1156
1157 #if !PCVT_NETBSD        /* has moved to cons.c in netbsd-current */
1158 void
1159 consinit()              /* init for kernel messages during boot */
1160 {
1161 }
1162 #endif /* PCVT_NETBSD */
1163
1164 #if PCVT_FREEBSD > 205
1165 static void
1166 #else
1167 int
1168 #endif
1169 pccnprobe(struct consdev *cp)
1170 {
1171         int unit = 0;
1172         int i;
1173
1174         /* See if this driver is disabled in probe hint. */ 
1175         if (resource_int_value("vt", unit, "disabled", &i) == 0 && i) {
1176                 cp->cn_pri = CN_DEAD;
1177                 return;
1178         }
1179
1180 #ifdef _DEV_KBD_KBDREG_H_
1181         kbd_configure(KB_CONF_PROBE_ONLY);
1182         if (kbd_find_keyboard("*", unit) < 0)
1183         {
1184                 cp->cn_pri = CN_DEAD;
1185                 return;
1186         }
1187 #endif /* _DEV_KBD_KBDREG_H_ */
1188
1189         /* initialize required fields */
1190
1191         cp->cn_dev = make_adhoc_dev(&pc_cdevsw, 0);
1192         cp->cn_pri = CN_INTERNAL;
1193
1194 #if !PCVT_NETBSD
1195
1196 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
1197         cp->cn_tp = &pccons[0];
1198 #else
1199         cp->cn_tp = pccons[0];
1200 #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
1201
1202 #endif /* !PCVT_NETBSD */
1203
1204 #if PCVT_FREEBSD <= 205
1205         return 1;
1206 #endif
1207 }
1208
1209 #if PCVT_FREEBSD > 205
1210 static void
1211 #else
1212 int
1213 #endif
1214 pccninit(struct consdev *cp)
1215 {
1216         int unit = 0;
1217         int i;
1218
1219         pcvt_is_console = 1;
1220
1221 #ifdef _DEV_KBD_KBDREG_H_
1222         /*
1223          * Don't reset the keyboard via `kbdio' just yet.
1224          * The system clock has not been calibrated...
1225          */
1226         reset_keyboard = 0;
1227
1228         if (kbd)
1229         {
1230                 kbd_release(kbd, (void *)&kbd);
1231                 kbd = NULL;
1232         }
1233         i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
1234         if (i >= 0)
1235                 kbd = kbd_get_keyboard(i);
1236
1237 #if PCVT_SCANSET == 2
1238         /*
1239          * Turn off scancode translation early so that UserConfig 
1240          * and DDB can read the keyboard.
1241          */
1242         if (kbd)
1243         {
1244                 empty_both_buffers(*(KBDC *)kbd->kb_data, 10);
1245                 set_controller_command_byte(*(KBDC *)kbd->kb_data,
1246                                             KBD_TRANSLATION, 0);
1247         }
1248 #endif /* PCVT_SCANSET == 2 */
1249
1250 #endif /* _DEV_KBD_KBDREG_H_ */
1251
1252 #if PCVT_FREEBSD <= 205
1253         return 0;
1254 #endif
1255 }
1256
1257 static void
1258 pccnterm(struct consdev *cp)
1259 {
1260 #ifdef _DEV_KBD_KBDREG_H_
1261         if (kbd)
1262         {
1263                 kbd_release(kbd, (void *)&kbd);
1264                 kbd = NULL;
1265         }
1266 #endif /* _DEV_KBD_KBDREG_H_ */
1267 }
1268
1269 #if PCVT_FREEBSD > 205
1270 static void
1271 #else
1272 int
1273 #endif
1274 pccnputc(Dev_t dev, U_char c)
1275 {
1276
1277 #if PCVT_SW0CNOUTP
1278
1279         if(current_video_screen != 0)
1280         {
1281
1282 #if !PCVT_USL_VT_COMPAT
1283                 vgapage(0);
1284 #else
1285                 switch_screen(0, 0);
1286 #endif /* !PCVT_USL_VT_COMPAT */
1287
1288         }
1289
1290 #endif /* PCVT_SW0CNOUTP */
1291
1292         if (c == '\n')
1293                 sput("\r", 1, 1, 0);
1294
1295         sput((char *) &c, 1, 1, 0);
1296
1297         async_update(UPDATE_KERN);
1298
1299 #if PCVT_FREEBSD <= 205
1300         return 0;
1301 #endif
1302 }
1303
1304 static int
1305 pccngetc(Dev_t dev)
1306 {
1307         int s;
1308         static u_char *cp, cbuf[4]; /* Temp buf for multi-char key sequence. */
1309         u_char c;
1310
1311 #ifdef XSERVER
1312
1313 #if !PCVT_USL_VT_COMPAT
1314         if (pcvt_xmode)
1315                 return 0;
1316 #else /* !PCVT_USL_VT_COMPAT */
1317         if (pcvt_kbd_raw)
1318                 return 0;
1319 #endif /* !PCVT_USL_VT_COMPAT */
1320
1321 #endif /* XSERVER */
1322
1323         if (cp && *cp)
1324                 /*
1325                  * We still have a pending key sequence, e.g.
1326                  * from an arrow key.  Deliver this one first.
1327                  */
1328                 return (*cp++);
1329
1330 #ifdef _DEV_KBD_KBDREG_H_
1331         if (kbd == NULL)
1332                 return 0;
1333 #endif  
1334
1335         s = spltty();           /* block pcrint while we poll */
1336         kbd_polling = 1;
1337 #ifdef _DEV_KBD_KBDREG_H_
1338         (*kbdsw[kbd->kb_index]->enable)(kbd);
1339 #endif  
1340         cp = sgetc(0);
1341 #ifdef _DEV_KBD_KBDREG_H_
1342         (*kbdsw[kbd->kb_index]->disable)(kbd);
1343 #endif  
1344         kbd_polling = 0;
1345         splx(s);
1346         c = *cp++;
1347         if (c && *cp) {
1348                 /* Preserve the multi-char sequence for the next call. */
1349                 bcopy(cp, cbuf, 3); /* take care for a trailing '\0' */
1350                 cp = cbuf;
1351         } else
1352                 cp = 0;
1353
1354 #if ! (PCVT_FREEBSD >= 201)
1355         /* this belongs to cons.c */
1356         if (c == '\r')
1357                 c = '\n';
1358 #endif /* ! (PCVT_FREEBSD >= 201) */
1359
1360         return c;
1361 }
1362
1363 #if PCVT_FREEBSD >= 200
1364 static int
1365 pccncheckc(Dev_t dev)
1366 {
1367         char *cp;
1368         int x;
1369
1370 #ifdef _DEV_KBD_KBDREG_H_
1371         if (kbd == NULL)
1372                 return 0;
1373 #endif  
1374
1375         x = spltty();
1376         kbd_polling = 1;
1377 #ifdef _DEV_KBD_KBDREG_H_
1378         (*kbdsw[kbd->kb_index]->enable)(kbd);
1379 #endif  
1380         cp = sgetc(1);
1381 #ifdef _DEV_KBD_KBDREG_H_
1382         (*kbdsw[kbd->kb_index]->disable)(kbd);
1383 #endif  
1384         kbd_polling = 0;
1385         splx(x);
1386         return (cp == NULL ? -1 : *cp);
1387 }
1388 #endif /* PCVT_FREEBSD >= 200 */
1389
1390 #if PCVT_NETBSD >= 100
1391 void
1392 pccnpollc(Dev_t dev, int on)
1393 {
1394         kbd_polling = on;
1395         if (!on) {
1396                 int s;
1397
1398                 /*
1399                  * If disabling polling, make sure there are no bytes left in
1400                  * the FIFO, holding up the interrupt line.  Otherwise we
1401                  * won't get any further interrupts.
1402                  */
1403                 s = spltty();
1404                 pcrint();
1405                 splx(s);
1406         }
1407 }
1408 #endif /* PCVT_NETBSD >= 100 */
1409
1410 /*---------------------------------------------------------------------------*
1411  *      Set line parameters
1412  *---------------------------------------------------------------------------*/
1413 int
1414 pcparam(struct tty *tp, struct termios *t)
1415 {
1416         int cflag = t->c_cflag;
1417
1418         /* and copy to tty */
1419
1420         tp->t_ispeed = t->c_ispeed;
1421         tp->t_ospeed = t->c_ospeed;
1422         tp->t_cflag = cflag;
1423
1424         return(0);
1425 }
1426
1427 /*----------------------------------------------------------------------*
1428  *      read initial VGA palette (as stored by VGA ROM BIOS) into
1429  *      palette save area
1430  *----------------------------------------------------------------------*/
1431 void
1432 vgapelinit(void)
1433 {
1434         unsigned idx;
1435         struct rgb *val;
1436
1437         /* first, read all and store to first screen's save buffer */
1438         for(idx = 0, val = vs[0].palette; idx < NVGAPEL; idx++, val++)
1439                 vgapaletteio(idx, val, 0 /* read it */);
1440
1441         /* now, duplicate for remaining screens */
1442         for(idx = 1; idx < PCVT_NSCREENS; idx++)
1443                 bcopy(vs[0].palette, vs[idx].palette,
1444                       NVGAPEL * sizeof(struct rgb));
1445 }
1446
1447 #if defined XSERVER && !PCVT_USL_VT_COMPAT
1448 /*----------------------------------------------------------------------*
1449  *      initialize for X mode
1450  *      i.e.: grant current process (the X server) all IO privileges,
1451  *      and mark in static variable so other hooks can test for it,
1452  *      save all loaded fonts and screen pages to pageable buffers;
1453  *      if parameter `on' is false, the same procedure is done reverse.
1454  *----------------------------------------------------------------------*/
1455 static int
1456 pcvt_xmode_set(int on, struct thread *td)
1457 {
1458         static unsigned char *saved_fonts[NVGAFONTS];
1459
1460 #if PCVT_SCREENSAVER
1461         static unsigned saved_scrnsv_tmo = 0;
1462 #endif /* PCVT_SCREENSAVER */
1463
1464 #if (PCVT_NETBSD > 9) || (PCVT_FREEBSD > 102)
1465         struct trapframe *fp;
1466 #else
1467         struct syscframe *fp;
1468 #endif /* PCVT_NETBSD > 9 */
1469
1470         int error, i;
1471
1472         /* X will only run on VGA and Hercules adaptors */
1473
1474         if(adaptor_type != VGA_ADAPTOR && adaptor_type != MDA_ADAPTOR)
1475                 return (EINVAL);
1476
1477 #if PCVT_NETBSD > 9
1478         fp = (struct trapframe *)p->p_regs;
1479 #else
1480         fp = (struct syscframe *)p->p_regs;
1481 #endif /* PCVT_NETBSD > 9 */
1482
1483         if(on)
1484         {
1485                 /*
1486                  * Test whether the calling process has super-user privileges
1487                  * and we're in insecure mode.
1488                  * This prevents us from granting the potential security hole
1489                  * `IO priv' to insufficiently privileged processes.
1490                  */
1491                 error = suser(td);
1492                 if (error != 0)
1493                         return (error);
1494                 if (securelevel > 0)
1495                         return (EPERM);
1496
1497                 if(pcvt_xmode)
1498                         return 0;
1499
1500                 pcvt_xmode = pcvt_kbd_raw = 1;
1501
1502                 for(i = 0; i < totalfonts; i++)
1503                 {
1504                         if(vgacs[i].loaded)
1505                         {
1506                                 saved_fonts[i] = (unsigned char *)
1507                                         malloc(32 * 256, M_DEVBUF, M_WAITOK);
1508                                 if(saved_fonts[i] == 0)
1509                                 {
1510                                         printf(
1511                                   "pcvt_xmode_set: no font buffer available\n");
1512                                         return (EAGAIN);
1513                                 }
1514                                 else
1515                                 {
1516                                         vga_move_charset(i, saved_fonts[i], 1);
1517                                 }
1518                         }
1519                         else
1520                         {
1521                                 saved_fonts[i] = 0;
1522                         }
1523                 }
1524
1525 #if PCVT_SCREENSAVER
1526                 if(saved_scrnsv_tmo = scrnsv_timeout)
1527                         pcvt_set_scrnsv_tmo(0); /* turn it off */
1528 #endif /* PCVT_SCREENSAVER */
1529
1530                 async_update(UPDATE_STOP);      /* turn off */
1531
1532                 /* disable text output and save screen contents */
1533                 /* video board memory -> kernel memory */
1534
1535                 bcopy(vsp->Crtat, vsp->Memory,
1536                        vsp->screen_rowsize * vsp->maxcol * CHR);
1537
1538                 vsp->Crtat = vsp->Memory;       /* operate in memory now */
1539
1540 #ifndef _DEV_KBD_KBDREG_H_
1541
1542 #if PCVT_SCANSET == 2
1543                 /* put keyboard to return ancient PC scan codes */
1544                 kbc_8042cmd(CONTR_WRITE);
1545 #if PCVT_USEKBDSEC              /* security enabled */
1546                 outb(CONTROLLER_DATA,
1547                  (COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
1548 #else                           /* security disabled */
1549                 outb(CONTROLLER_DATA,
1550                  (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
1551 #endif /* PCVT_USEKBDSEC */
1552 #endif /* PCVT_SCANSET == 2 */
1553
1554 #else /* _DEV_KBD_KBDREG_H_ */
1555
1556 #if PCVT_SCANSET == 2
1557                 /* put keyboard to return ancient PC scan codes */
1558                 set_controller_command_byte(*(KBDC *)kbd->kb_data, 
1559                         KBD_TRANSLATION, KBD_TRANSLATION); 
1560 #endif /* PCVT_SCANSET == 2 */
1561
1562 #endif /* !_DEV_KBD_KBDREG_H_ */
1563
1564 #if PCVT_NETBSD > 9
1565                 fp->tf_eflags |= PSL_IOPL;
1566 #else
1567                 fp->sf_eflags |= PSL_IOPL;
1568 #endif /* PCVT_NETBSD > 9 */
1569
1570         }
1571         else
1572         {
1573                 if(!pcvt_xmode)         /* verify if in X */
1574                         return 0;
1575
1576                 pcvt_xmode = pcvt_kbd_raw = 0;
1577
1578                 for(i = 0; i < totalfonts; i++)
1579                 {
1580                         if(saved_fonts[i])
1581                         {
1582                                 vga_move_charset(i, saved_fonts[i], 0);
1583                                 free(saved_fonts[i], M_DEVBUF);
1584                                 saved_fonts[i] = 0;
1585                         }
1586                 }
1587
1588 #if PCVT_NETBSD > 9
1589                 fp->tf_eflags &= ~PSL_IOPL;
1590 #else
1591                 fp->sf_eflags &= ~PSL_IOPL;
1592 #endif /* PCVT_NETBSD > 9 */
1593
1594 #if PCVT_SCREENSAVER
1595                 if(saved_scrnsv_tmo)
1596                         pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
1597 #endif /* PCVT_SCREENSAVER */
1598
1599 #ifndef _DEV_KBD_KBDREG_H_
1600
1601 #if PCVT_SCANSET == 2
1602                 kbc_8042cmd(CONTR_WRITE);
1603 #if PCVT_USEKBDSEC              /* security enabled */
1604                 outb(CONTROLLER_DATA,
1605                  (COMMAND_SYSFLG|COMMAND_IRQEN));
1606 #else                           /* security disabled */
1607                 outb(CONTROLLER_DATA,
1608                  (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN));
1609 #endif /* PCVT_USEKBDSEC */
1610 #endif /* PCVT_SCANSET == 2 */
1611
1612 #else /* _DEV_KBD_KBDREG_H_ */
1613
1614 #if PCVT_SCANSET == 2
1615                 set_controller_command_byte(*(KBDC *)kbd->kb_data,
1616                         KBD_TRANSLATION, 0);
1617 #endif /* PCVT_SCANSET == 2 */
1618
1619 #endif /* !_DEV_KBD_KBDREG_H_ */
1620
1621                 if(adaptor_type == MDA_ADAPTOR)
1622                 {
1623                     /*
1624                      * Due to the fact that HGC registers are write-only,
1625                      * the Xserver can only make guesses about the state
1626                      * the HGC adaptor has been before turning on X mode.
1627                      * Thus, the display must be re-enabled now, and the
1628                      * cursor shape and location restored.
1629                      */
1630                     outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
1631                     outb(addr_6845, CRTC_CURSORH); /* select high register */
1632                     outb(addr_6845+1,
1633                          ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
1634                     outb(addr_6845, CRTC_CURSORL); /* select low register */
1635                     outb(addr_6845+1,
1636                          ((vsp->Crtat + vsp->cur_offset) - Crtat));
1637
1638                     outb(addr_6845, CRTC_CURSTART); /* select high register */
1639                     outb(addr_6845+1, vsp->cursor_start);
1640                     outb(addr_6845, CRTC_CUREND); /* select low register */
1641                     outb(addr_6845+1, vsp->cursor_end);
1642                   }
1643
1644                 /* restore screen and re-enable text output */
1645                 /* kernel memory -> video board memory */
1646
1647                 bcopy(vsp->Memory, Crtat,
1648                        vsp->screen_rowsize * vsp->maxcol * CHR);
1649
1650                 vsp->Crtat = Crtat;     /* operate on-screen now */
1651
1652                 /* set crtc screen memory start address */
1653
1654                 outb(addr_6845, CRTC_STARTADRH);
1655                 outb(addr_6845+1, (vsp->Crtat - Crtat) >> 8);
1656                 outb(addr_6845, CRTC_STARTADRL);
1657                 outb(addr_6845+1, (vsp->Crtat - Crtat));
1658
1659                 async_update(UPDATE_START);
1660         }
1661         return 0;
1662 }
1663 #endif  /* XSERVER && !PCVT_USL_VT_COMPAT */
1664
1665 #endif  /* NVT > 0 */
1666
1667 /*-------------------------- E O F -------------------------------------*/