summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/pcvt/pcvt_drv.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-02-05 11:01:24 +0000
committerjkh <jkh@FreeBSD.org>1995-02-05 11:01:24 +0000
commit3b9ff6800f46bec5eb5ced0f6c268c86c46b41c6 (patch)
treefca42f1297b742673ed429786a562a2eff7944ba /sys/i386/isa/pcvt/pcvt_drv.c
parentf2a7d967ea7d8531d3b2701ef8bbbd69532532d1 (diff)
downloadFreeBSD-src-3b9ff6800f46bec5eb5ced0f6c268c86c46b41c6.zip
FreeBSD-src-3b9ff6800f46bec5eb5ced0f6c268c86c46b41c6.tar.gz
Bring pcvt console driver into the tree - now users can chose whichever
console driver they like best (2 is ok, it was 4 that was a little insane for awhile there! :-). Submitted by: hm
Diffstat (limited to 'sys/i386/isa/pcvt/pcvt_drv.c')
-rw-r--r--sys/i386/isa/pcvt/pcvt_drv.c1427
1 files changed, 1427 insertions, 0 deletions
diff --git a/sys/i386/isa/pcvt/pcvt_drv.c b/sys/i386/isa/pcvt/pcvt_drv.c
new file mode 100644
index 0000000..4b49dab
--- /dev/null
+++ b/sys/i386/isa/pcvt/pcvt_drv.c
@@ -0,0 +1,1427 @@
+/*
+ * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
+ *
+ * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
+ *
+ * Copyright (c) 1993 Charles Hannum.
+ *
+ * All rights reserved.
+ *
+ * Parts of this code regarding the NetBSD interface were written
+ * by Charles Hannum.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * Hellmuth Michaelis, Brian Dunford-Shore, Joerg Wunsch, Scott Turner
+ * and Charles Hannum.
+ * 4. The name authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * @(#)pcvt_drv.c, 3.20, Last Edit-Date: [Thu Jan 5 15:54:02 1995]
+ *
+ */
+
+/*---------------------------------------------------------------------------*
+ *
+ * pcvt_drv.c VT220 Driver Main Module / OS - Interface
+ * ---------------------------------------------------------
+ * -hm ------------ Release 3.00 --------------
+ * -hm integrating NetBSD-current patches
+ * -hm adding ttrstrt() proto for NetBSD 0.9
+ * -hm kernel/console output cursor positioning fixed
+ * -hm kernel/console output switches optional to screen 0
+ * -hm FreeBSD 1.1 porting
+ * -hm the NetBSD 0.9 compiler detected a nondeclared var which was
+ * NOT detected by neither the NetBSD-current nor FreeBSD 1.x!
+ * -hm including Michael's keyboard fifo code
+ * -hm Joergs patch for FreeBSD tty-malloc code
+ * -hm adjustments for NetBSD-current
+ * -hm FreeBSD bugfix from Joerg re timeout/untimeout casts
+ * -jw including Thomas Gellekum's FreeBSD 1.1.5 patch
+ * -hm adjusting #if's for NetBSD-current
+ * -hm applying Joerg's patch for FreeBSD 2.0
+ * -hm patch from Onno & Martin for NetBSD-current (post 1.0)
+ * -hm some adjustments for NetBSD 1.0
+ * -hm NetBSD PR #400: screen size report for new session
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "vt.h"
+#if NVT > 0
+
+#define EXTERN /* allocate mem */
+
+#include "pcvt_hdr.h" /* global include */
+
+#if PCVT_NETBSD
+ extern u_short *Crtat;
+#endif /* PCVT_NETBSD */
+
+unsigned __debug = 0; /*0xffe */;
+static __color;
+static nrow;
+
+static void vgapelinit(void); /* read initial VGA DAC palette */
+
+#if defined XSERVER && !PCVT_USL_VT_COMPAT
+static int pcvt_xmode_set(int on, struct proc *p); /* initialize for X mode */
+#endif /* XSERVER && !PCVT_USL_VT_COMPAT */
+
+int
+#if PCVT_NETBSD > 9
+pcprobe(struct device *parent, struct device *self, void *aux)
+#else
+pcprobe(struct isa_device *dev)
+#endif /* PCVT_NETBSD > 9 */
+{
+ kbd_code_init();
+
+#if PCVT_NETBSD > 9
+ ((struct isa_attach_args *)aux)->ia_iosize = 16;
+ return 1;
+#else
+#if PCVT_NETBSD || PCVT_FREEBSD
+ return (16);
+#else
+ return 1;
+#endif /* PCVT_NETBSD || PCVT_FREEBSD */
+#endif /* PCVT_NETBSD > 9 */
+
+}
+
+#if PCVT_NETBSD > 9
+void
+pcattach(struct device *parent, struct device *self, void *aux)
+{
+ struct isa_attach_args *ia = aux;
+ static struct intrhand vthand;
+#else
+int
+pcattach(struct isa_device *dev)
+{
+#endif /* PCVT_NETBSD > 9 */
+
+ int i;
+
+ vt_coldmalloc(); /* allocate memory for screens */
+
+#if PCVT_NETBSD || PCVT_FREEBSD
+
+#if PCVT_NETBSD > 9
+ printf(": ");
+#else
+ printf("vt%d: ", dev->id_unit);
+#endif /* PCVT_NETBSD > 9 */
+
+ switch(adaptor_type)
+ {
+ case MDA_ADAPTOR:
+ printf("mda");
+ break;
+
+ case CGA_ADAPTOR:
+ printf("cga");
+ break;
+
+ case EGA_ADAPTOR:
+ printf("ega");
+ break;
+
+ case VGA_ADAPTOR:
+ printf("%s, ", (char *)vga_string(vga_type));
+ if(can_do_132col)
+ printf("80/132 col");
+ else
+ printf("80 col");
+ vgapelinit();
+ break;
+
+ default:
+ printf("unknown");
+ break;
+ }
+
+ if(color == 0)
+ printf(", mono");
+ else
+ printf(", color");
+
+ printf(", %d scr, ", totalscreens);
+
+ switch(keyboard_type)
+ {
+ case KB_AT:
+ printf("at-");
+ break;
+
+ case KB_MFII:
+ printf("mf2-");
+ break;
+
+ default:
+ printf("unknown ");
+ break;
+ }
+
+ printf("kbd, [R%s]\n", PCVT_REL);
+
+#if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
+
+ for(i = 0; i < totalscreens; i++)
+ {
+
+#if PCVT_NETBSD
+ pc_tty[i] = ttymalloc();
+ vs[i].vs_tty = pc_tty[i];
+#else /* !PCVT_NETBSD */
+ pccons[i] = ttymalloc(pccons[i]);
+ vs[i].vs_tty = pccons[i];
+#endif /* PCVT_NETBSD */
+
+ }
+
+#if PCVT_EMU_MOUSE
+#if PCVT_NETBSD
+ pc_tty[totalscreens] = ttymalloc(); /* the mouse emulator tty */
+#else /* !PCVT_NETBSD */
+ /* the mouse emulator tty */
+ pc_tty[totalscreens] = ttymalloc(pccons[totalscreens]);
+#endif /* PCVT_NETBSD */
+#endif /* PCVT_EMU_MOUSE */
+
+#if PCVT_NETBSD
+ pcconsp = pc_tty[0];
+#else /* !PCVT_NETBSD */
+ pcconsp = pccons[0];
+#endif /* PCVT_NETBSD */
+
+#endif /* #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
+
+#else /* !PCVT_NETBSD && !PCVT_FREEBSD*/
+
+ switch(adaptor_type)
+ {
+ case MDA_ADAPTOR:
+ printf(" <mda");
+ break;
+
+ case CGA_ADAPTOR:
+ printf(" <cga");
+ break;
+
+ case EGA_ADAPTOR:
+ printf(" <ega");
+ break;
+
+ case VGA_ADAPTOR:
+ printf(" <%s,", (char *)vga_string(vga_type));
+ if(can_do_132col)
+ printf("80/132 col");
+ else
+ printf("80 col");
+ vgapelinit();
+ break;
+
+ default:
+ printf(" <unknown");
+ break;
+ }
+
+ if(color == 0)
+ printf(",mono");
+ else
+ printf(",color");
+
+ printf(",%d scr,", totalscreens);
+
+ switch(keyboard_type)
+ {
+ case KB_AT:
+ printf("at-");
+ break;
+
+ case KB_MFII:
+ printf("mf2-");
+ break;
+
+ default:
+ printf("unknown ");
+ break;
+ }
+
+ printf("kbd,[R%s]>", PCVT_REL);
+
+#endif /* PCVT_NETBSD || PCVT_FREEBSD */
+
+#if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
+ for(i = 0; i < totalscreens; i++)
+ vs[i].vs_tty = &pccons[i];
+#endif /* !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
+
+ async_update(UPDATE_START); /* start asynchronous updates */
+
+#if PCVT_NETBSD > 9
+ vthand.ih_fun = pcrint;
+ vthand.ih_arg = 0;
+ vthand.ih_level = IPL_TTY;
+ intr_establish(ia->ia_irq, &vthand);
+#else
+ return 1;
+#endif /* PCVT_NETBSD > 9 */
+}
+
+/* had a look at the friedl driver */
+
+#if !PCVT_NETBSD
+
+struct tty *
+get_pccons(Dev_t dev)
+{
+ register int i = minor(dev);
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+#if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
+ return(&pccons[i]);
+#else
+ return(pccons[i]);
+#endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
+#endif /* PCVT_EMU_MOUSE */
+
+ if(i >= PCVT_NSCREENS)
+ return(NULL);
+#if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
+ return(&pccons[i]);
+#else
+ return(pccons[i]);
+#endif
+}
+
+#else
+
+struct tty *
+get_pccons(Dev_t dev)
+{
+ register int i = minor(dev);
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+ return(pc_tty[i]);
+#endif /* PCVT_EMU_MOUSE */
+
+ if(i >= PCVT_NSCREENS)
+ return(NULL);
+ return(pc_tty[i]);
+}
+
+#endif /* !PCVT_NETBSD */
+
+/*---------------------------------------------------------------------------*
+ * /dev/ttyc0, /dev/ttyc1, etc.
+ *---------------------------------------------------------------------------*/
+int
+pcopen(Dev_t dev, int flag, int mode, struct proc *p)
+{
+ register struct tty *tp;
+ register struct video_state *vsx;
+ int s, retval;
+ int winsz = 0;
+ int i = minor(dev);
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+ vsx = 0;
+ else
+#endif /* PCVT_EMU_MOUSE */
+
+ vsx = &vs[i];
+
+ if((tp = get_pccons(dev)) == NULL)
+ return ENXIO;
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+ {
+ if(mouse.opened == 0)
+ mouse.buttons = mouse.extendedseen =
+ mouse.breakseen = mouse.lastmove.tv_sec = 0;
+ mouse.minor = i;
+ mouse.opened++;
+ }
+ else
+#endif /* PCVT_EMU_MOUSE */
+
+ vsx->openf++;
+
+ tp->t_oproc = pcstart;
+ tp->t_param = pcparam;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ {
+
+#if !(PCVT_FREEBSD > 114)
+ tp->t_state |= TS_WOPEN;
+#endif /* !(PCVT_FREEBSD > 114) */
+
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ pcparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ }
+ else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+
+ tp->t_state |= TS_CARR_ON;
+ tp->t_cflag |= CLOCAL; /* cannot be a modem (:-) */
+
+ if ((tp->t_state & TS_ISOPEN) == 0) /* is this a "cold" open ? */
+ winsz = 1; /* yes, set winsize later */
+
+#if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
+ retval = ((*linesw[tp->t_line].l_open)(dev, tp));
+#else
+ retval = ((*linesw[tp->t_line].l_open)(dev, tp, flag));
+#endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
+
+ if(winsz == 1)
+ {
+
+ /*
+ * The line discipline has clobbered t_winsize if TS_ISOPEN
+ * was clear. (NetBSD PR #400 from Bill Sommerfeld)
+ * We have to do this after calling the open routine, because
+ * it does some other things in other/older *BSD releases -hm
+ */
+
+ s = spltty();
+
+ tp->t_winsize.ws_col = vsx->maxcol;
+ tp->t_winsize.ws_row = vsx->screen_rows;
+ tp->t_winsize.ws_xpixel = (vsx->maxcol == 80)? 720: 1056;
+ tp->t_winsize.ws_ypixel = 400;
+
+ splx(s);
+ }
+
+ return(retval);
+}
+
+int
+pcclose(Dev_t dev, int flag, int mode, struct proc *p)
+{
+ register struct tty *tp;
+ register struct video_state *vsx;
+ int i = minor(dev);
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+ vsx = 0;
+ else
+#endif /* PCVT_EMU_MOUSE */
+
+ vsx = &vs[i];
+
+ if((tp = get_pccons(dev)) == NULL)
+ return ENXIO;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+
+#if PCVT_EMU_MOUSE
+ if(i == totalscreens)
+ mouse.opened = 0;
+ else
+#endif /* PCVT_EMU_MOUSE */
+
+ vsx->openf = 0;
+
+#if PCVT_USL_VT_COMPAT
+#if PCVT_EMU_MOUSE
+
+ if(i == totalscreens)
+ return (0);
+
+#endif /* PCVT_EMU_MOUSE */
+
+ if(vsx->vt_status & VT_WAIT_ACT)
+ wakeup((caddr_t)&vsx->smode);
+ vsx->proc = 0;
+ vsx->vt_status = vsx->pid = 0;
+ vsx->smode.mode = VT_AUTO;
+
+#endif /* PCVT_USL_VT_COMPAT */
+
+ return(0);
+}
+
+int
+pcread(Dev_t dev, struct uio *uio, int flag)
+{
+ register struct tty *tp;
+
+ if((tp = get_pccons(dev)) == NULL)
+ return ENXIO;
+
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+pcwrite(Dev_t dev, struct uio *uio, int flag)
+{
+ register struct tty *tp;
+
+ if((tp = get_pccons(dev)) == NULL)
+ return ENXIO;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+int
+pcioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+{
+ register error;
+ register struct tty *tp;
+
+ if((tp = get_pccons(dev)) == NULL)
+ return(ENXIO);
+
+ /* note that some ioctl's are global, e.g. KBSTPMAT: There is
+ * only one keyboard and different repeat rates for instance between
+ * sessions are a suspicious wish. If you really need this make the
+ * appropriate variables arrays
+ */
+
+#if PCVT_EMU_MOUSE
+ if(minor(dev) == totalscreens)
+ {
+ if((error = mouse_ioctl(dev, cmd, data)) >= 0)
+ return error;
+ goto do_standard;
+ }
+#endif /* PCVT_EMU_MOUSE */
+
+#ifdef XSERVER
+#if PCVT_USL_VT_COMPAT
+
+ if((error = usl_vt_ioctl(dev, cmd, data, flag, p)) >= 0)
+ return error;
+
+ /*
+ * just for compatibility:
+ * XFree86 < 2.0 and SuperProbe still might use it
+ *
+ * NB: THIS IS A HACK! Do not use it unless you explicitly need.
+ * Especially, since the vty is not put into process-controlled
+ * mode (this would require the application to co-operate), any
+ * attempts to switch vtys while this kind of X mode is active
+ * may cause serious trouble.
+ */
+ switch(cmd)
+ {
+ case CONSOLE_X_MODE_ON:
+ {
+ int i;
+
+ if((error = usl_vt_ioctl(dev, KDENABIO, 0, flag, p)) > 0)
+ return error;
+
+ i = KD_GRAPHICS;
+ if((error = usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, p))
+ > 0)
+ return error;
+
+ i = K_RAW;
+ error = usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, p);
+ return error;
+ }
+
+ case CONSOLE_X_MODE_OFF:
+ {
+ int i;
+
+ (void)usl_vt_ioctl(dev, KDDISABIO, 0, flag, p);
+
+ i = KD_TEXT;
+ (void)usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, p);
+
+ i = K_XLATE;
+ (void)usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, p);
+ return 0;
+ }
+
+
+ case CONSOLE_X_BELL:
+ /*
+ * If `data' is non-null, it points to int[2], the first
+ * value denotes the pitch in Hz, the second a duration
+ * in ms (??? jw - 333 us). Otherwise, behaves like BEL.
+ */
+ if (data)
+ sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
+ ((int *)data)[1] * hz / 3000);
+ else
+ sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
+ return (0);
+
+ default: /* fall through */ ;
+ }
+
+#else /* PCVT_USL_VT_COMPAT */
+
+ switch(cmd)
+ {
+ case CONSOLE_X_MODE_ON:
+ return pcvt_xmode_set(1, p);
+
+ case CONSOLE_X_MODE_OFF:
+ return pcvt_xmode_set(0, p);
+
+ case CONSOLE_X_BELL:
+ /*
+ * If `data' is non-null, it points to int[2], the first
+ * value denotes the pitch in Hz, the second a duration
+ * in ms (??? jw - 333 us). Otherwise, behaves like BEL.
+ */
+ if (data)
+ sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
+ ((int *)data)[1] * hz / 3000);
+ else
+ sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
+ return (0);
+
+ default: /* fall through */ ;
+ }
+
+#endif /* PCVT_USL_VT_COMPAT */
+#endif /* XSERVER */
+
+ if((error = kbdioctl(dev,cmd,data,flag)) >= 0)
+ return error;
+
+ if((error = vgaioctl(dev,cmd,data,flag)) >= 0)
+ return error;
+
+do_standard:
+
+#if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
+ if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p)) >= 0)
+ return (error);
+#else
+ if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag)) >= 0)
+ return(error);
+#endif /* PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200 */
+
+#if PCVT_NETBSD > 9
+ if((error = ttioctl(tp, cmd, data, flag, p)) >= 0)
+ return (error);
+#else
+ if((error = ttioctl(tp, cmd, data, flag)) >= 0)
+ return (error);
+#endif /* PCVT_NETBSD > 9 */
+
+ return (ENOTTY);
+}
+
+int
+pcmmap(Dev_t dev, int offset, int nprot)
+{
+ if (offset > 0x20000)
+ return -1;
+ return i386_btop((0xa0000 + offset));
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * handle a keyboard receive interrupt
+ *
+ * NOTE: the keyboard is multiplexed by means of "pcconsp"
+ * between virtual screens. pcconsp - switching is done in
+ * the vgapage() routine
+ *
+ *---------------------------------------------------------------------------*/
+
+#if PCVT_KBD_FIFO
+ u_char pcvt_kbd_fifo[PCVT_KBD_FIFO_SZ];
+ int pcvt_kbd_wptr = 0;
+ int pcvt_kbd_rptr = 0;
+ short pcvt_kbd_count= 0;
+static u_char pcvt_timeout_scheduled = 0;
+
+static void pcvt_timeout (void *arg)
+{
+ u_char *cp;
+
+#if PCVT_SLOW_INTERRUPT
+ int s;
+#endif
+
+ pcvt_timeout_scheduled = 0;
+
+#if PCVT_SCREENSAVER
+ pcvt_scrnsv_reset();
+#endif /* PCVT_SCREENSAVER */
+
+ while (pcvt_kbd_count)
+ {
+ if (((cp = sgetc(1)) != 0) &&
+ (vs[current_video_screen].openf))
+ {
+
+#if PCVT_NULLCHARS
+ if(*cp == '\0')
+ {
+ /* pass a NULL character */
+ (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
+ }
+/* XXX */ else
+#endif /* PCVT_NULLCHARS */
+
+ while (*cp)
+ (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
+ }
+
+ PCVT_DISABLE_INTR ();
+
+ if (!pcvt_kbd_count)
+ pcvt_timeout_scheduled = 0;
+
+ PCVT_ENABLE_INTR ();
+ }
+
+ return;
+}
+#endif
+
+
+int
+pcrint(void)
+{
+
+#if PCVT_KBD_FIFO
+ u_char dt;
+ u_char ret = -1;
+
+# if PCVT_SLOW_INTERRUPT
+ int s;
+# endif
+
+#else /* !PCVT_KBD_FIFO */
+ u_char *cp;
+#endif /* PCVT_KBD_FIFO */
+
+#if PCVT_SCREENSAVER
+ pcvt_scrnsv_reset();
+#endif /* PCVT_SCREENSAVER */
+
+#if PCVT_KBD_FIFO
+ if (kbd_polling)
+ {
+ if(sgetc(1) == 0)
+ return -1;
+ else
+ return 1;
+ }
+
+ while (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) /* check 8042 buffer */
+ {
+ ret = 1; /* got something */
+
+ dt = inb(CONTROLLER_DATA); /* get it 8042 data */
+
+ if (pcvt_kbd_count >= PCVT_KBD_FIFO_SZ) /* fifo overflow ? */
+ {
+ log (LOG_WARNING, "pcvt: keyboard buffer overflow\n");
+ }
+ else
+ {
+ pcvt_kbd_fifo[pcvt_kbd_wptr++] = dt; /* data -> fifo */
+
+ PCVT_DISABLE_INTR (); /* XXX necessary ? */
+ pcvt_kbd_count++; /* update fifo count */
+ PCVT_ENABLE_INTR ();
+
+ if (pcvt_kbd_wptr >= PCVT_KBD_FIFO_SZ)
+ pcvt_kbd_wptr = 0; /* wraparound pointer */
+ }
+ }
+
+ if (ret == 1) /* got data from keyboard ? */
+ {
+ if (!pcvt_timeout_scheduled) /* if not already active .. */
+ {
+ PCVT_DISABLE_INTR ();
+ pcvt_timeout_scheduled = 1; /* flag active */
+ timeout((TIMEOUT_FUNC_T)pcvt_timeout, (caddr_t) 0, 1); /* fire off */
+ PCVT_ENABLE_INTR ();
+ }
+ }
+ return (ret);
+
+#else /* !PCVT_KBD_FIFO */
+
+ if((cp = sgetc(1)) == 0)
+ return -1;
+
+ if (kbd_polling)
+ return 1;
+
+ if(!(vs[current_video_screen].openf)) /* XXX was vs[minor(dev)] */
+ return 1;
+
+#if PCVT_NULLCHARS
+ if(*cp == '\0')
+ {
+ /* pass a NULL character */
+ (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
+ return 1;
+ }
+#endif /* PCVT_NULLCHARS */
+
+ while (*cp)
+ (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
+ return 1;
+
+#endif /* PCVT_KBD_FIFO */
+}
+
+
+#if PCVT_NETBSD || PCVT_FREEBSD >= 200
+
+#if PCVT_NETBSD == 9
+extern void ttrstrt();
+#endif /* PCVT_NETBSD == 9 */
+
+void
+pcstart(register struct tty *tp)
+{
+ register struct clist *rbp;
+ int s, len, n;
+ u_char buf[PCVT_PCBURST];
+
+ s = spltty();
+
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+
+ tp->t_state |= TS_BUSY;
+
+ splx(s);
+
+ async_update(UPDATE_KERN);
+
+ /*
+ * We need to do this outside spl since it could be fairly
+ * expensive and we don't want our serial ports to overflow.
+ */
+
+ rbp = &tp->t_outq;
+
+ while (len = q_to_b(rbp, buf, PCVT_PCBURST))
+ sput(&buf[0], 0, len, minor(tp->t_dev));
+
+ s = spltty();
+
+ tp->t_state &= ~TS_BUSY;
+
+ if (rbp->c_cc)
+ {
+ tp->t_state |= TS_TIMEOUT;
+ timeout(ttrstrt, tp, 1);
+ }
+
+ if (rbp->c_cc <= tp->t_lowat)
+ {
+ if (tp->t_state&TS_ASLEEP)
+ {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)rbp);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+out:
+ splx(s);
+}
+
+#else /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
+
+void
+pcstart(struct tty *tp)
+{
+ int s;
+ unsigned char c;
+
+ s = spltty();
+
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ {
+ goto out;
+ }
+
+ for(;;)
+ {
+
+#if !(PCVT_FREEBSD > 114)
+
+#if !(PCVT_FREEBSD > 111)
+ if (RB_LEN(&tp->t_out) <= tp->t_lowat)
+#else
+ if (RB_LEN(tp->t_out) <= tp->t_lowat)
+#endif
+ {
+ if (tp->t_state&TS_ASLEEP)
+ {
+ tp->t_state &= ~TS_ASLEEP;
+#if !(PCVT_FREEBSD > 111)
+ wakeup((caddr_t)&tp->t_out);
+#else
+ wakeup((caddr_t)tp->t_out);
+#endif
+ }
+
+ if (tp->t_wsel)
+ {
+ selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
+ tp->t_wsel = 0;
+ tp->t_state &= ~TS_WCOLL;
+ }
+ }
+
+#else /* PCVT_FREEBSD > 114 */
+ if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT)
+ || tp->t_wsel) {
+ ttwwakeup(tp);
+ }
+#endif /* !PCVT_FREEBSD > 114 */
+
+#if !(PCVT_FREEBSD > 111)
+ if (RB_LEN(&tp->t_out) == 0)
+#else
+ if (RB_LEN(tp->t_out) == 0)
+#endif
+ {
+ goto out;
+ }
+
+#if !(PCVT_FREEBSD > 111)
+ c = getc(&tp->t_out);
+#else
+ c = getc(tp->t_out);
+#endif
+
+ tp->t_state |= TS_BUSY; /* patch from Frank Maclachlan */
+ splx(s);
+ sput(&c, 0, 1, minor(tp->t_dev));
+ spltty();
+ tp->t_state &= ~TS_BUSY; /* patch from Frank Maclachlan */
+ }
+out:
+ splx(s);
+}
+
+#endif /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
+
+/*---------------------------------------------------------------------------*
+ * /dev/console
+ *---------------------------------------------------------------------------*/
+
+#if !PCVT_NETBSD /* has moved to cons.c in netbsd-current */
+void
+consinit() /* init for kernel messages during boot */
+{
+}
+#endif /* PCVT_NETBSD */
+
+int
+pccnprobe(struct consdev *cp)
+{
+ int maj;
+
+ /* locate the major number */
+
+ for (maj = 0; maj < nchrdev; maj++)
+ {
+ if ((u_int)cdevsw[maj].d_open == (u_int)pcopen)
+ break;
+ }
+
+ /* initialize required fields */
+
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_INTERNAL;
+
+#if !PCVT_NETBSD
+
+#if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
+ cp->cn_tp = &pccons[0];
+#else
+ cp->cn_tp = pccons[0];
+#endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
+
+#endif /* !PCVT_NETBSD */
+
+ return 1;
+}
+
+int
+pccninit(struct consdev *cp)
+{
+ return 0;
+}
+
+int
+pccnputc(Dev_t dev, U_char c)
+{
+
+#if PCVT_SW0CNOUTP
+
+ if(current_video_screen != 0)
+ {
+
+#if !PCVT_USL_VT_COMPAT
+ vgapage(0);
+#else
+ switch_screen(0, 0);
+#endif /* !PCVT_USL_VT_COMPAT */
+
+ }
+
+#endif /* PCVT_SW0CNOUTP */
+
+ if (c == '\n')
+ sput("\r", 1, 1, 0);
+
+ sput((char *) &c, 1, 1, 0);
+
+ async_update(UPDATE_KERN);
+
+ return 0;
+}
+
+int
+pccngetc(Dev_t dev)
+{
+ register int s;
+ register u_char *cp;
+
+#ifdef XSERVER
+
+#if !PCVT_USL_VT_COMPAT
+ if (pcvt_xmode)
+ return 0;
+#else /* !PCVT_USL_VT_COMPAT */
+ if (pcvt_kbd_raw)
+ return 0;
+#endif /* !PCVT_USL_VT_COMPAT */
+
+#endif /* XSERVER */
+
+ s = spltty(); /* block pcrint while we poll */
+ cp = sgetc(0);
+ splx(s);
+
+#if ! (PCVT_FREEBSD >= 201)
+ /* this belongs to cons.c */
+ if (*cp == '\r')
+ return('\n');
+#endif /* ! (PCVT_FREEBSD >= 201) */
+
+ return (*cp);
+}
+
+#if PCVT_FREEBSD >= 200
+int
+pccncheckc(Dev_t dev)
+{
+ return (sgetc(1) != 0); /* did someone press the "Any" key? */
+}
+#endif /* PCVT_FREEBSD >= 200 */
+
+#if PCVT_NETBSD >= 100
+void
+pccnpollc(Dev_t dev, int on)
+{
+ kbd_polling = on;
+ if (!on) {
+ register int s;
+
+ /*
+ * If disabling polling, make sure there are no bytes left in
+ * the FIFO, holding up the interrupt line. Otherwise we
+ * won't get any further interrupts.
+ */
+ s = spltty();
+ pcrint();
+ splx(s);
+ }
+}
+#endif /* PCVT_NETBSD >= 100 */
+
+/*---------------------------------------------------------------------------*
+ * Set line parameters
+ *---------------------------------------------------------------------------*/
+int
+pcparam(struct tty *tp, struct termios *t)
+{
+ register int cflag = t->c_cflag;
+
+ /* and copy to tty */
+
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+
+ return(0);
+}
+
+#if PCVT_NEEDPG /* this is moved to cons.c in patchkit 0.2.2 and higher */
+
+int
+pg (char *p,
+ int q, int r, int s, int t, int u,
+ int v, int w, int x, int y, int z)
+{
+
+#if !PCVT_USL_VT_COMPAT
+ vgapage(0);
+#else
+ switch_screen(0, 0);
+#endif /* !PCVT_USL_VT_COMPAT */
+
+ printf(p,q,r,s,t,u,v,w,x,y,z);
+ printf("\n");
+ return(getchar());
+}
+
+#endif /* PCVT_NEEDPG */
+
+/* special characters */
+#define bs 8
+#define lf 10
+#define cr 13
+#define cntlc 3
+#define del 0177
+#define cntld 4
+
+int
+getchar(void)
+{
+ u_char thechar;
+ int x;
+
+ kbd_polling = 1;
+
+ x = splhigh();
+
+ sput(">", 1, 1, 0);
+
+ async_update(UPDATE_KERN);
+
+ thechar = *(sgetc(0));
+
+ kbd_polling = 0;
+
+ splx(x);
+
+ switch (thechar)
+ {
+ default:
+ if (thechar >= ' ')
+ sput(&thechar, 1, 1, 0);
+ return(thechar);
+
+ case cr:
+ case lf:
+ sput("\r\n", 1, 2, 0);
+ return(lf);
+
+ case bs:
+ case del:
+ sput("\b \b", 1, 3, 0);
+ return(thechar);
+
+ case cntlc:
+ sput("^C\r\n", 1, 4, 0) ;
+ cpu_reset();
+
+ case cntld:
+ sput("^D\r\n", 1, 4, 0) ;
+ return(0);
+ }
+}
+
+#define DPAUSE 1
+
+void
+dprintf(unsigned flgs, const char *fmt, ...)
+{
+ va_list ap;
+
+ if((flgs&__debug) > DPAUSE)
+ {
+ __color = ffs(flgs&__debug)+1;
+ va_start(ap,fmt);
+ kprintf(fmt, 1, (struct tty *)0, ap);
+ va_end(ap);
+
+ if (flgs & DPAUSE || nrow%24 == 23)
+ {
+ int x;
+ x = splhigh();
+ if(nrow%24 == 23)
+ nrow = 0;
+ (void)sgetc(0);
+ splx(x);
+ }
+ }
+ __color = 0;
+}
+
+/*----------------------------------------------------------------------*
+ * read initial VGA palette (as stored by VGA ROM BIOS) into
+ * palette save area
+ *----------------------------------------------------------------------*/
+void
+vgapelinit(void)
+{
+ register unsigned idx;
+ register struct rgb *val;
+
+ /* first, read all and store to first screen's save buffer */
+ for(idx = 0, val = vs[0].palette; idx < NVGAPEL; idx++, val++)
+ vgapaletteio(idx, val, 0 /* read it */);
+
+ /* now, duplicate for remaining screens */
+ for(idx = 1; idx < PCVT_NSCREENS; idx++)
+ bcopy(vs[0].palette, vs[idx].palette,
+ NVGAPEL * sizeof(struct rgb));
+}
+
+#if defined XSERVER && !PCVT_USL_VT_COMPAT
+/*----------------------------------------------------------------------*
+ * initialize for X mode
+ * i.e.: grant current process (the X server) all IO priviledges,
+ * and mark in static variable so other hooks can test for it,
+ * save all loaded fonts and screen pages to pageable buffers;
+ * if parameter `on' is false, the same procedure is done reverse.
+ *----------------------------------------------------------------------*/
+static int
+pcvt_xmode_set(int on, struct proc *p)
+{
+ static unsigned char *saved_fonts[NVGAFONTS];
+
+#if PCVT_SCREENSAVER
+ static unsigned saved_scrnsv_tmo = 0;
+#endif /* PCVT_SCREENSAVER */
+
+#if (PCVT_NETBSD > 9) || (PCVT_FREEBSD > 102)
+ struct trapframe *fp;
+#else
+ struct syscframe *fp;
+#endif /* PCVT_NETBSD > 9 */
+
+ int i;
+
+ /* X will only run on VGA and Hercules adaptors */
+
+ if(adaptor_type != VGA_ADAPTOR && adaptor_type != MDA_ADAPTOR)
+ return (EINVAL);
+
+#if PCVT_NETBSD > 9
+ fp = (struct trapframe *)p->p_regs;
+#else
+ fp = (struct syscframe *)p->p_regs;
+#endif /* PCVT_NETBSD > 9 */
+
+ if(on)
+ {
+ /*
+ * Test whether the calling process has super-user priviledges.
+ * This prevents us from granting the potential security hole
+ * `IO priv' to any process (effective uid is checked).
+ */
+
+ if(suser(p->p_ucred, &p->p_acflag) != 0)
+ return (EPERM);
+
+ if(pcvt_xmode)
+ return 0;
+
+ pcvt_xmode = pcvt_kbd_raw = 1;
+
+ for(i = 0; i < totalfonts; i++)
+ {
+ if(vgacs[i].loaded)
+ {
+ saved_fonts[i] = (unsigned char *)
+ malloc(32 * 256, M_DEVBUF, M_WAITOK);
+ if(saved_fonts[i] == 0)
+ {
+ printf(
+ "pcvt_xmode_set: no font buffer available\n");
+ return (EAGAIN);
+ }
+ else
+ {
+ vga_move_charset(i, saved_fonts[i], 1);
+ }
+ }
+ else
+ {
+ saved_fonts[i] = 0;
+ }
+ }
+
+#if PCVT_SCREENSAVER
+ if(saved_scrnsv_tmo = scrnsv_timeout)
+ pcvt_set_scrnsv_tmo(0); /* turn it off */
+#endif /* PCVT_SCREENSAVER */
+
+ async_update(UPDATE_STOP); /* turn off */
+
+ /* disable text output and save screen contents */
+ /* video board memory -> kernel memory */
+
+ bcopy(vsp->Crtat, vsp->Memory,
+ vsp->screen_rowsize * vsp->maxcol * CHR);
+
+ vsp->Crtat = vsp->Memory; /* operate in memory now */
+
+#if PCVT_SCANSET == 2
+ /* put keyboard to return ancient PC scan codes */
+ kbc_8042cmd(CONTR_WRITE);
+#if PCVT_USEKBDSEC /* security enabled */
+ outb(CONTROLLER_DATA,
+ (COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
+#else /* security disabled */
+ outb(CONTROLLER_DATA,
+ (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
+#endif /* PCVT_USEKBDSEC */
+#endif /* PCVT_SCANSET == 2 */
+
+#if PCVT_NETBSD > 9
+ fp->tf_eflags |= PSL_IOPL;
+#else
+ fp->sf_eflags |= PSL_IOPL;
+#endif /* PCVT_NETBSD > 9 */
+
+ }
+ else
+ {
+ if(!pcvt_xmode) /* verify if in X */
+ return 0;
+
+ pcvt_xmode = pcvt_kbd_raw = 0;
+
+ for(i = 0; i < totalfonts; i++)
+ {
+ if(saved_fonts[i])
+ {
+ vga_move_charset(i, saved_fonts[i], 0);
+ free(saved_fonts[i], M_DEVBUF);
+ saved_fonts[i] = 0;
+ }
+ }
+
+#if PCVT_NETBSD > 9
+ fp->tf_eflags &= ~PSL_IOPL;
+#else
+ fp->sf_eflags &= ~PSL_IOPL;
+#endif /* PCVT_NETBSD > 9 */
+
+#if PCVT_SCREENSAVER
+ if(saved_scrnsv_tmo)
+ pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
+#endif /* PCVT_SCREENSAVER */
+
+#if PCVT_SCANSET == 2
+ kbc_8042cmd(CONTR_WRITE);
+#if PCVT_USEKBDSEC /* security enabled */
+ outb(CONTROLLER_DATA,
+ (COMMAND_SYSFLG|COMMAND_IRQEN));
+#else /* security disabled */
+ outb(CONTROLLER_DATA,
+ (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN));
+#endif /* PCVT_USEKBDSEC */
+#endif /* PCVT_SCANSET == 2 */
+
+ if(adaptor_type == MDA_ADAPTOR)
+ {
+ /*
+ * Due to the fact that HGC registers are write-only,
+ * the Xserver can only make guesses about the state
+ * the HGC adaptor has been before turning on X mode.
+ * Thus, the display must be re-enabled now, and the
+ * cursor shape and location restored.
+ */
+ outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
+ outb(addr_6845, CRTC_CURSORH); /* select high register */
+ outb(addr_6845+1,
+ ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
+ outb(addr_6845, CRTC_CURSORL); /* select low register */
+ outb(addr_6845+1,
+ ((vsp->Crtat + vsp->cur_offset) - Crtat));
+
+ outb(addr_6845, CRTC_CURSTART); /* select high register */
+ outb(addr_6845+1, vsp->cursor_start);
+ outb(addr_6845, CRTC_CUREND); /* select low register */
+ outb(addr_6845+1, vsp->cursor_end);
+ }
+
+ /* restore screen and re-enable text output */
+ /* kernel memory -> video board memory */
+
+ bcopy(vsp->Memory, Crtat,
+ vsp->screen_rowsize * vsp->maxcol * CHR);
+
+ vsp->Crtat = Crtat; /* operate on-screen now */
+
+ /* set crtc screen memory start address */
+
+ outb(addr_6845, CRTC_STARTADRH);
+ outb(addr_6845+1, (vsp->Crtat - Crtat) >> 8);
+ outb(addr_6845, CRTC_STARTADRL);
+ outb(addr_6845+1, (vsp->Crtat - Crtat));
+
+ async_update(UPDATE_START);
+ }
+ return 0;
+}
+#endif /* XSERVER && !PCVT_USL_VT_COMPAT */
+
+#if PCVT_386BSD /* dummies required to work with patchkit 0.2.4 */
+void cons_highlight (void) {}
+void cons_normal (void) {}
+#endif /* PCVT_386BSD */
+
+#endif /* NVT > 0 */
+
+/*-------------------------- E O F -------------------------------------*/
OpenPOWER on IntegriCloud