2 * Copyright (c) 1999 Hellmuth Michaelis
4 * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
6 * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
8 * Copyright (c) 1993 Charles Hannum.
10 * All rights reserved.
12 * Parts of this code regarding the NetBSD interface were written
15 * This code is derived from software contributed to Berkeley by
16 * William Jolitz and Don Ahn.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
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
31 * 4. The name authors may not be used to endorse or promote products
32 * derived from this software without specific prior written permission.
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.
46 /*---------------------------------------------------------------------------*
48 * pcvt_drv.c VT220 Driver Main Module / OS - Interface
49 * ---------------------------------------------------------
51 * Last Edit-Date: [Mon Dec 27 14:03:36 1999]
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 $
56 *---------------------------------------------------------------------------*/
61 #define EXTERN /* allocate mem */
63 #include "pcvt_hdr.h" /* global include */
65 #if PCVT_FREEBSD >= 200
67 #include <machine/stdarg.h>
69 #include "machine/stdarg.h"
72 extern int getchar (void);
75 extern u_short *Crtat;
76 #endif /* PCVT_NETBSD */
78 static void vgapelinit(void); /* read initial VGA DAC palette */
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 */
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;
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;
97 CONS_DRIVER(pc, pccnprobe, pccninit, pccnterm, pccngetc, pccncheckc, pccnputc,
100 static d_open_t pcopen;
101 static d_close_t pcclose;
102 static d_ioctl_t pcioctl;
103 static d_mmap_t pcmmap;
105 #define CDEV_MAJOR 12
106 struct cdevsw pc_cdevsw = {
108 /* maj */ CDEV_MAJOR,
109 /* flags */ D_TTY | D_KQFILTER,
116 /* write */ ttywrite,
120 /* strategy */ nostrategy,
123 /* kqfilter */ ttykqfilter
126 static struct callout pcvt_timeout_ch;
128 #if PCVT_NETBSD > 100 /* NetBSD-current Feb 20 1995 */
130 pcprobe(struct device *parent, void *match, void *aux)
134 pcprobe(struct device *parent, struct device *self, void *aux)
137 pcprobe(struct isa_device *dev)
138 #endif /* PCVT_NETBSD > 9 */
139 #endif /* PCVT_NETBSD > 100 */
141 #ifdef _DEV_KBD_KBDREG_H_
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))
151 reset_keyboard = 1; /* it's now safe to do kbd reset */
152 #endif /* _DEV_KBD_KBDREG_H_ */
157 ((struct isa_attach_args *)aux)->ia_iosize = 16;
160 #ifdef _DEV_KBD_KBDREG_H_
162 #elif PCVT_NETBSD || PCVT_FREEBSD
166 #endif /* PCVT_NETBSD || PCVT_FREEBSD */
167 #endif /* PCVT_NETBSD > 9 */
173 pcattach(struct device *parent, struct device *self, void *aux)
175 struct isa_attach_args *ia = aux;
176 static struct intrhand vthand;
179 pcattach(struct isa_device *dev)
181 #endif /* PCVT_NETBSD > 9 */
185 if ((pcvt_timeout_ch.c_flags & CALLOUT_DID_INIT) == 0)
186 callout_init(&pcvt_timeout_ch);
188 vt_coldmalloc(); /* allocate memory for screens */
190 #ifdef _DEV_KBD_KBDREG_H_
192 pcvt_reset_detect_timeout(dev->id_unit, hz * 2);
193 #endif /* _DEV_KBD_KBDREG_H_ */
195 #if PCVT_NETBSD || PCVT_FREEBSD
200 printf("vt%d: ", dev->id_unit);
201 #endif /* PCVT_NETBSD > 9 */
218 printf("%s, ", (char *)vga_string(vga_type));
220 printf("80/132 col");
236 printf(", %d scr, ", totalscreens);
238 switch(keyboard_type)
253 printf("kbd, [R%s]\n", PCVT_REL);
255 #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
257 for(i = 0; i < totalscreens; i++)
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 */
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 */
281 #else /* !PCVT_NETBSD */
283 #endif /* PCVT_NETBSD */
285 #endif /* #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
287 #else /* !PCVT_NETBSD && !PCVT_FREEBSD*/
304 printf(" <%s,", (char *)vga_string(vga_type));
306 printf("80/132 col");
322 printf(",%d scr,", totalscreens);
324 switch(keyboard_type)
339 printf("kbd,[R%s]>", PCVT_REL);
341 #endif /* PCVT_NETBSD || PCVT_FREEBSD */
343 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
344 cdevsw_add(&pc_cdevsw, 0, 0);
345 for(i = 0; i < totalscreens; i++)
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);
351 #endif /* !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
353 async_update(UPDATE_START); /* start asynchronous updates */
357 vthand.ih_fun = pcrint;
359 vthand.ih_level = IPL_TTY;
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 */
367 #else /* PCVT_NETBSD > 9 */
369 dev->id_ointr = pcrint;
373 #endif /* PCVT_NETBSD > 9 */
377 /* had a look at the friedl driver */
382 get_pccons(Dev_t dev)
387 if(i == totalscreens)
388 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
392 #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
393 #endif /* PCVT_EMU_MOUSE */
395 if(i >= PCVT_NSCREENS)
397 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
407 get_pccons(Dev_t dev)
412 if(i == totalscreens)
414 #endif /* PCVT_EMU_MOUSE */
416 if(i >= PCVT_NSCREENS)
421 #endif /* !PCVT_NETBSD */
423 /*---------------------------------------------------------------------------*
424 * /dev/ttyc0, /dev/ttyc1, etc.
425 *---------------------------------------------------------------------------*/
427 pcopen(Dev_t dev, int flag, int mode, struct thread *td)
430 struct video_state *vsx;
436 if(i == totalscreens)
439 #endif /* PCVT_EMU_MOUSE */
443 if((tp = get_pccons(dev)) == NULL)
449 if(i == totalscreens)
451 if(mouse.opened == 0)
452 mouse.buttons = mouse.extendedseen =
453 mouse.breakseen = mouse.lastmove.tv_sec = 0;
458 #endif /* PCVT_EMU_MOUSE */
462 tp->t_oproc = pcstart;
463 tp->t_param = pcparam;
464 tp->t_stop = nottystop;
467 if ((tp->t_state & TS_ISOPEN) == 0)
470 #ifdef TS_WOPEN /* not (FreeBSD-1.1.5 or FreeBSD some time after 2.0.5) */
471 tp->t_state |= TS_WOPEN;
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 */
484 else if (tp->t_state & TS_XCLUDE && suser(td))
487 #if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
488 retval = ((*linesw[tp->t_line].l_open)(dev, tp));
490 retval = ((*linesw[tp->t_line].l_open)(dev, tp, flag));
491 #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
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
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;
517 pcclose(Dev_t dev, int flag, int mode, struct thread *td)
520 struct video_state *vsx;
524 if(i == totalscreens)
527 #endif /* PCVT_EMU_MOUSE */
531 if((tp = get_pccons(dev)) == NULL)
534 (*linesw[tp->t_line].l_close)(tp, flag);
538 if(i == totalscreens)
541 #endif /* PCVT_EMU_MOUSE */
545 #if PCVT_USL_VT_COMPAT
548 if(i == totalscreens)
551 #endif /* PCVT_EMU_MOUSE */
553 reset_usl_modes(vsx);
555 #endif /* PCVT_USL_VT_COMPAT */
561 pcioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
566 if((tp = get_pccons(dev)) == NULL)
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
576 if(minor(dev) == totalscreens)
578 if((error = mouse_ioctl(dev, cmd, data)) >= 0)
582 #endif /* PCVT_EMU_MOUSE */
585 #if PCVT_USL_VT_COMPAT
587 if((error = usl_vt_ioctl(dev, cmd, data, flag, td->td_proc)) >= 0)
591 * just for compatibility:
592 * XFree86 < 2.0 and SuperProbe still might use it
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.
602 case CONSOLE_X_MODE_ON:
606 if((error = usl_vt_ioctl(dev, KDENABIO, 0, flag, td->td_proc)) > 0)
610 if((error = usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc))
615 error = usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
619 case CONSOLE_X_MODE_OFF:
623 (void)usl_vt_ioctl(dev, KDDISABIO, 0, flag, td->td_proc);
626 (void)usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc);
629 (void)usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
637 * If `data' is non-null, the first int value denotes
638 * the pitch, the second a duration. Otherwise, behaves
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 */
656 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
660 default: /* fall through */ ;
663 #else /* PCVT_USL_VT_COMPAT */
667 case CONSOLE_X_MODE_ON:
668 return pcvt_xmode_set(1, td->td_proc);
670 case CONSOLE_X_MODE_OFF:
671 return pcvt_xmode_set(0, td->td_proc);
676 * If `data' is non-null, the first int value denotes
677 * the pitch, the second a duration. Otherwise, behaves
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 */
695 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
699 default: /* fall through */ ;
702 #endif /* PCVT_USL_VT_COMPAT */
705 if((error = kbdioctl(dev,cmd,data,flag)) >= 0)
708 if((error = vgaioctl(dev,cmd,data,flag)) >= 0)
715 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
716 if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td))
720 if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag)) >= 0)
722 #endif /* PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200 */
725 if((error = ttioctl(tp, cmd, data, flag, td)) >= 0)
728 if((error = ttioctl(tp, cmd, data, flag)) != ENOIOCTL)
730 #endif /* PCVT_NETBSD > 9 */
736 pcmmap(Dev_t dev, vm_offset_t offset, int nprot)
738 if (offset > 0x20000 - PAGE_SIZE)
740 return i386_btop((0xa0000 + offset));
743 /*---------------------------------------------------------------------------*
745 * handle a keyboard receive interrupt
747 * NOTE: the keyboard is multiplexed by means of "pcconsp"
748 * between virtual screens. pcconsp - switching is done in
749 * the vgapage() routine
751 *---------------------------------------------------------------------------*/
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;
762 pcvt_timeout(void *arg)
766 #if PCVT_SLOW_INTERRUPT
770 pcvt_timeout_scheduled = 0;
774 #endif /* PCVT_SCREENSAVER */
776 while (pcvt_kbd_count)
778 if (((cp = sgetc(1)) != 0) &&
779 (vs[current_video_screen].openf))
785 /* pass a NULL character */
786 (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
789 #endif /* PCVT_NULLCHARS */
792 (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
795 PCVT_DISABLE_INTR ();
798 pcvt_timeout_scheduled = 0;
807 #ifdef _DEV_KBD_KBDREG_H_
811 pcvt_reset_detect_timeout(int unit, int hz)
813 static struct callout **prd_callout_ary;
815 struct callout *prd_ch;
817 KKASSERT(unit >= 0 && unit < 4096);
820 * Expand our callout pointer array if necessary
823 struct callout **nary;
827 nunits = (unit + 1 + 7) & ~7;
828 nary = malloc(nunits * sizeof(struct callout *),
829 M_DEVBUF, M_INTWAIT|M_ZERO);
831 /* detect race if we blocked */
833 for (i = 0; i < nprd; ++i)
834 nary[i] = prd_callout_ary[i];
835 prd_callout_ary = nary;
838 free(nary, M_DEVBUF);
843 * Malloc a callout if necessary
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);
849 /* detect race if we blocked */
850 if (prd_callout_ary[unit] == NULL) {
851 prd_callout_ary[unit] = prd_ch;
853 free(prd_ch, M_DEVBUF);
854 prd_ch = prd_callout_ary[unit];
857 callout_reset(prd_ch, hz, detect_kbd, (void *)unit);
861 detect_kbd(void *arg)
868 i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
870 kbd = kbd_get_keyboard(i);
873 reset_keyboard = 1; /* ok to reset the keyboard */
878 pcvt_reset_detect_timeout(unit, hz * 2);
882 pcevent(keyboard_t *thiskbd, int event, void *arg)
887 return EINVAL; /* shouldn't happen */
893 case KBDIO_UNLOADING:
896 kbd_release(thiskbd, (void *)&kbd);
897 pcvt_reset_detect_timeout(unit, hz * 4);
903 #endif /* _DEV_KBD_KBDREG_H_ */
913 # if PCVT_SLOW_INTERRUPT
917 # ifdef _DEV_KBD_KBDREG_H_
921 #else /* !PCVT_KBD_FIFO */
923 #endif /* PCVT_KBD_FIFO */
927 #endif /* PCVT_SCREENSAVER */
936 # ifndef _DEV_KBD_KBDREG_H_
937 while (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) /* check 8042 buffer */
939 ret = 1; /* got something */
941 PCVT_KBD_DELAY(); /* 7 us delay */
943 dt = inb(CONTROLLER_DATA); /* get it 8042 data */
945 while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) != -1)
947 ret = 1; /* got something */
949 # endif /* _DEV_KBD_KBDREG_H_ */
951 if (pcvt_kbd_count >= PCVT_KBD_FIFO_SZ) /* fifo overflow ? */
953 log (LOG_WARNING, "pcvt: keyboard buffer overflow\n");
957 pcvt_kbd_fifo[pcvt_kbd_wptr++] = dt; /* data -> fifo */
959 PCVT_DISABLE_INTR (); /* XXX necessary ? */
960 pcvt_kbd_count++; /* update fifo count */
963 if (pcvt_kbd_wptr >= PCVT_KBD_FIFO_SZ)
964 pcvt_kbd_wptr = 0; /* wraparound pointer */
968 if (ret == 1) /* got data from keyboard ? */
970 if (!pcvt_timeout_scheduled) /* if not already active .. */
972 PCVT_DISABLE_INTR ();
973 pcvt_timeout_scheduled = 1; /* flag active */
975 callout_reset(&pcvt_timeout_ch, hz / 100,
981 #else /* !PCVT_KBD_FIFO */
983 if((cp = sgetc(1)) == 0)
989 if(!(vs[current_video_screen].openf)) /* XXX was vs[minor(dev)] */
995 /* pass a NULL character */
996 (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
999 #endif /* PCVT_NULLCHARS */
1002 (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
1004 #endif /* PCVT_KBD_FIFO */
1008 #if PCVT_NETBSD || PCVT_FREEBSD >= 200
1011 pcstart(struct tty *tp)
1015 u_char buf[PCVT_PCBURST];
1019 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1022 tp->t_state |= TS_BUSY;
1026 async_update(UPDATE_KERN);
1031 * Call q_to_b() at spltty() to ensure that the queue is empty when
1032 * the loop terminates.
1037 while((len = q_to_b(rbp, buf, PCVT_PCBURST)) > 0)
1039 if(vs[minor(tp->t_dev)].scrolling)
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.
1047 sput(&buf[0], 0, len, minor(tp->t_dev));
1051 tp->t_state &= ~TS_BUSY;
1053 #ifndef TS_ASLEEP /* FreeBSD some time after 2.0.5 */
1056 if (rbp->c_cc <= tp->t_lowat)
1058 if (tp->t_state&TS_ASLEEP)
1060 tp->t_state &= ~TS_ASLEEP;
1061 wakeup((caddr_t)rbp);
1063 selwakeup(&tp->t_wsel);
1071 pcstop(struct tty *tp, int flag)
1075 #else /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1078 pcstart(struct tty *tp)
1085 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1093 #if !(PCVT_FREEBSD > 114)
1095 #if !(PCVT_FREEBSD > 111)
1096 if (RB_LEN(&tp->t_out) <= tp->t_lowat)
1098 if (RB_LEN(tp->t_out) <= tp->t_lowat)
1101 if (tp->t_state&TS_ASLEEP)
1103 tp->t_state &= ~TS_ASLEEP;
1104 #if !(PCVT_FREEBSD > 111)
1105 wakeup((caddr_t)&tp->t_out);
1107 wakeup((caddr_t)tp->t_out);
1113 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
1115 tp->t_state &= ~TS_WCOLL;
1119 #else /* PCVT_FREEBSD > 114 */
1120 if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT)
1124 #endif /* !PCVT_FREEBSD > 114 */
1126 #if !(PCVT_FREEBSD > 111)
1127 if (RB_LEN(&tp->t_out) == 0)
1129 if (RB_LEN(tp->t_out) == 0)
1135 #if !(PCVT_FREEBSD > 111)
1136 c = getc(&tp->t_out);
1138 c = getc(tp->t_out);
1141 tp->t_state |= TS_BUSY; /* patch from Frank Maclachlan */
1143 sput(&c, 0, 1, minor(tp->t_dev));
1145 tp->t_state &= ~TS_BUSY; /* patch from Frank Maclachlan */
1151 #endif /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1153 /*---------------------------------------------------------------------------*
1155 *---------------------------------------------------------------------------*/
1157 #if !PCVT_NETBSD /* has moved to cons.c in netbsd-current */
1159 consinit() /* init for kernel messages during boot */
1162 #endif /* PCVT_NETBSD */
1164 #if PCVT_FREEBSD > 205
1169 pccnprobe(struct consdev *cp)
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;
1180 #ifdef _DEV_KBD_KBDREG_H_
1181 kbd_configure(KB_CONF_PROBE_ONLY);
1182 if (kbd_find_keyboard("*", unit) < 0)
1184 cp->cn_pri = CN_DEAD;
1187 #endif /* _DEV_KBD_KBDREG_H_ */
1189 /* initialize required fields */
1191 cp->cn_dev = make_adhoc_dev(&pc_cdevsw, 0);
1192 cp->cn_pri = CN_INTERNAL;
1196 #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
1197 cp->cn_tp = &pccons[0];
1199 cp->cn_tp = pccons[0];
1200 #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
1202 #endif /* !PCVT_NETBSD */
1204 #if PCVT_FREEBSD <= 205
1209 #if PCVT_FREEBSD > 205
1214 pccninit(struct consdev *cp)
1219 pcvt_is_console = 1;
1221 #ifdef _DEV_KBD_KBDREG_H_
1223 * Don't reset the keyboard via `kbdio' just yet.
1224 * The system clock has not been calibrated...
1230 kbd_release(kbd, (void *)&kbd);
1233 i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
1235 kbd = kbd_get_keyboard(i);
1237 #if PCVT_SCANSET == 2
1239 * Turn off scancode translation early so that UserConfig
1240 * and DDB can read the keyboard.
1244 empty_both_buffers(*(KBDC *)kbd->kb_data, 10);
1245 set_controller_command_byte(*(KBDC *)kbd->kb_data,
1246 KBD_TRANSLATION, 0);
1248 #endif /* PCVT_SCANSET == 2 */
1250 #endif /* _DEV_KBD_KBDREG_H_ */
1252 #if PCVT_FREEBSD <= 205
1258 pccnterm(struct consdev *cp)
1260 #ifdef _DEV_KBD_KBDREG_H_
1263 kbd_release(kbd, (void *)&kbd);
1266 #endif /* _DEV_KBD_KBDREG_H_ */
1269 #if PCVT_FREEBSD > 205
1274 pccnputc(Dev_t dev, U_char c)
1279 if(current_video_screen != 0)
1282 #if !PCVT_USL_VT_COMPAT
1285 switch_screen(0, 0);
1286 #endif /* !PCVT_USL_VT_COMPAT */
1290 #endif /* PCVT_SW0CNOUTP */
1293 sput("\r", 1, 1, 0);
1295 sput((char *) &c, 1, 1, 0);
1297 async_update(UPDATE_KERN);
1299 #if PCVT_FREEBSD <= 205
1308 static u_char *cp, cbuf[4]; /* Temp buf for multi-char key sequence. */
1313 #if !PCVT_USL_VT_COMPAT
1316 #else /* !PCVT_USL_VT_COMPAT */
1319 #endif /* !PCVT_USL_VT_COMPAT */
1321 #endif /* XSERVER */
1325 * We still have a pending key sequence, e.g.
1326 * from an arrow key. Deliver this one first.
1330 #ifdef _DEV_KBD_KBDREG_H_
1335 s = spltty(); /* block pcrint while we poll */
1337 #ifdef _DEV_KBD_KBDREG_H_
1338 (*kbdsw[kbd->kb_index]->enable)(kbd);
1341 #ifdef _DEV_KBD_KBDREG_H_
1342 (*kbdsw[kbd->kb_index]->disable)(kbd);
1348 /* Preserve the multi-char sequence for the next call. */
1349 bcopy(cp, cbuf, 3); /* take care for a trailing '\0' */
1354 #if ! (PCVT_FREEBSD >= 201)
1355 /* this belongs to cons.c */
1358 #endif /* ! (PCVT_FREEBSD >= 201) */
1363 #if PCVT_FREEBSD >= 200
1365 pccncheckc(Dev_t dev)
1370 #ifdef _DEV_KBD_KBDREG_H_
1377 #ifdef _DEV_KBD_KBDREG_H_
1378 (*kbdsw[kbd->kb_index]->enable)(kbd);
1381 #ifdef _DEV_KBD_KBDREG_H_
1382 (*kbdsw[kbd->kb_index]->disable)(kbd);
1386 return (cp == NULL ? -1 : *cp);
1388 #endif /* PCVT_FREEBSD >= 200 */
1390 #if PCVT_NETBSD >= 100
1392 pccnpollc(Dev_t dev, int on)
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.
1408 #endif /* PCVT_NETBSD >= 100 */
1410 /*---------------------------------------------------------------------------*
1411 * Set line parameters
1412 *---------------------------------------------------------------------------*/
1414 pcparam(struct tty *tp, struct termios *t)
1416 int cflag = t->c_cflag;
1418 /* and copy to tty */
1420 tp->t_ispeed = t->c_ispeed;
1421 tp->t_ospeed = t->c_ospeed;
1422 tp->t_cflag = cflag;
1427 /*----------------------------------------------------------------------*
1428 * read initial VGA palette (as stored by VGA ROM BIOS) into
1430 *----------------------------------------------------------------------*/
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 */);
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));
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 *----------------------------------------------------------------------*/
1456 pcvt_xmode_set(int on, struct thread *td)
1458 static unsigned char *saved_fonts[NVGAFONTS];
1460 #if PCVT_SCREENSAVER
1461 static unsigned saved_scrnsv_tmo = 0;
1462 #endif /* PCVT_SCREENSAVER */
1464 #if (PCVT_NETBSD > 9) || (PCVT_FREEBSD > 102)
1465 struct trapframe *fp;
1467 struct syscframe *fp;
1468 #endif /* PCVT_NETBSD > 9 */
1472 /* X will only run on VGA and Hercules adaptors */
1474 if(adaptor_type != VGA_ADAPTOR && adaptor_type != MDA_ADAPTOR)
1478 fp = (struct trapframe *)p->p_regs;
1480 fp = (struct syscframe *)p->p_regs;
1481 #endif /* PCVT_NETBSD > 9 */
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.
1494 if (securelevel > 0)
1500 pcvt_xmode = pcvt_kbd_raw = 1;
1502 for(i = 0; i < totalfonts; i++)
1506 saved_fonts[i] = (unsigned char *)
1507 malloc(32 * 256, M_DEVBUF, M_WAITOK);
1508 if(saved_fonts[i] == 0)
1511 "pcvt_xmode_set: no font buffer available\n");
1516 vga_move_charset(i, saved_fonts[i], 1);
1525 #if PCVT_SCREENSAVER
1526 if(saved_scrnsv_tmo = scrnsv_timeout)
1527 pcvt_set_scrnsv_tmo(0); /* turn it off */
1528 #endif /* PCVT_SCREENSAVER */
1530 async_update(UPDATE_STOP); /* turn off */
1532 /* disable text output and save screen contents */
1533 /* video board memory -> kernel memory */
1535 bcopy(vsp->Crtat, vsp->Memory,
1536 vsp->screen_rowsize * vsp->maxcol * CHR);
1538 vsp->Crtat = vsp->Memory; /* operate in memory now */
1540 #ifndef _DEV_KBD_KBDREG_H_
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 */
1554 #else /* _DEV_KBD_KBDREG_H_ */
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 */
1562 #endif /* !_DEV_KBD_KBDREG_H_ */
1565 fp->tf_eflags |= PSL_IOPL;
1567 fp->sf_eflags |= PSL_IOPL;
1568 #endif /* PCVT_NETBSD > 9 */
1573 if(!pcvt_xmode) /* verify if in X */
1576 pcvt_xmode = pcvt_kbd_raw = 0;
1578 for(i = 0; i < totalfonts; i++)
1582 vga_move_charset(i, saved_fonts[i], 0);
1583 free(saved_fonts[i], M_DEVBUF);
1589 fp->tf_eflags &= ~PSL_IOPL;
1591 fp->sf_eflags &= ~PSL_IOPL;
1592 #endif /* PCVT_NETBSD > 9 */
1594 #if PCVT_SCREENSAVER
1595 if(saved_scrnsv_tmo)
1596 pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
1597 #endif /* PCVT_SCREENSAVER */
1599 #ifndef _DEV_KBD_KBDREG_H_
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 */
1612 #else /* _DEV_KBD_KBDREG_H_ */
1614 #if PCVT_SCANSET == 2
1615 set_controller_command_byte(*(KBDC *)kbd->kb_data,
1616 KBD_TRANSLATION, 0);
1617 #endif /* PCVT_SCANSET == 2 */
1619 #endif /* !_DEV_KBD_KBDREG_H_ */
1621 if(adaptor_type == MDA_ADAPTOR)
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.
1630 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
1631 outb(addr_6845, CRTC_CURSORH); /* select high register */
1633 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
1634 outb(addr_6845, CRTC_CURSORL); /* select low register */
1636 ((vsp->Crtat + vsp->cur_offset) - Crtat));
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);
1644 /* restore screen and re-enable text output */
1645 /* kernel memory -> video board memory */
1647 bcopy(vsp->Memory, Crtat,
1648 vsp->screen_rowsize * vsp->maxcol * CHR);
1650 vsp->Crtat = Crtat; /* operate on-screen now */
1652 /* set crtc screen memory start address */
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));
1659 async_update(UPDATE_START);
1663 #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
1665 #endif /* NVT > 0 */
1667 /*-------------------------- E O F -------------------------------------*/