File:  [DragonFly] / src / sys / dev / video / pcvt / i386 / Attic / pcvt_drv.c
Revision 1.10: download - view: text, annotated - select for diffs
Wed May 19 22:52:54 2004 UTC (9 years, 11 months ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_Snap13Sep2004, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

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