/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:tty_tb.c 12.0$ */
/* $ACIS:tty_tb.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/sys/RCS/tty_tb.c,v $ */

#if !defined(lint) && !defined(NO_RCS_HDRS)
static char *rcsid = "$Header:tty_tb.c 12.0$";
#endif

/*
 * Copyright (c) 1982, 1986 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 */

/*	tty_tb.c	6.2	83/09/22	*/

#include "tb.h"
#if NTB > 0

#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/ioctl.h"
#include "../h/tty.h"
#include "../h/proc.h"
#include "../h/file.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/uio.h"

#include "../machinecons/screen_conf.h"
#include "../h/tbdefs.h"
#include "../h/tbioctl.h"

/*
 * Line discipline for RS232 tablets.
 * Supplies binary coordinate data.
 *
 * MAKE TABLET TYPE AN ioctl TO AVOID HAVING ONE DISCIPLINE PER TABLET TYPE.
 */

int tbdecodea(),tbdecodeb(),tbdecodec(),tbdecoded(),tbdecodee(),tbdecodef();

struct tbdata {

	int (*decode)();		/* Pointer to apropriate decode func */
	unsigned char data_bytes;	/* Number of bytes in data format */
	unsigned char sync_mask;	/* Mask used to obtain sync bit(s) */
	unsigned char sync_value;	/* Actual sync value */
	unsigned char data_type;	/* 1 = ASCII  0 = BINARY */

}Tablet_Data[] = {

	{tbdecodea,	5,	0x80,	0x80,	1},	/* HITACHI_DISC     */
							/*   hitachi format */
	{tbdecodeb,	6,	0x80,	0x80,	1},	/* GTCO_DISC        */
							/*   gtco format    */
	{tbdecodec,	5,	0x40,	0x40,	0},	/* CALCOMP_DISC     */
							/*   Bit Pad One &  */
							/*   calcomp format */
	{tbdecoded,	5,	0xF0,	0x80,	0},	/* PCMS_DISC        */
							/*   pc mouse fmt   */
#ifdef IBMRTPC
	{tbdecodee,	4,	0xFF,	0x0B,	0},	/* PLANMS_DISC      */
							/*   planar mouse   */
							/* 3 Button emul    */
	{tbdecodef,	4,	0xFF,	0x0B,	0},	/* PLANMS_DISC      */
							/*   planar mouse   */
							/* 2 Button emul    */
#endif IBMRTPC

#ifdef ATR
	{tbdecodee,	3,	0x0c,	0x08,	0},	/* PLANMS_DISC      */
							/* PS/2 planar mouse*/
							/* 3 Button emul    */
	{tbdecodef,	3,	0x0c,	0x08,	0},	/* PLANMS_DISC      */
							/* PS/2 planar mouse*/
							/* 2 Button emul    */
#endif ATR

};

#define MAXTABLDISC   ((sizeof(Tablet_Data)/sizeof(struct tbdata))-1)

/* Generic Button definitions */
#define RIGHT_BUT	0x04
#define MIDDLE_BUT	0x02
#define LEFT_BUT	0x01
#define NO_BUT		0x00

struct tb tb[NTBS];

/* Emulator support */
extern SCREEN_INFO cons_info[];
extern int cons_if;
#define ms_info (cons_info[cons_if])

int tb_debug = 0;

/*
 * Open as tablet discipline.  Called when discipline changed
 * with ioctl, and changes the interpretation of the information
 * in the tty structure.
 */
/*ARGSUSED*/
tbopen(dev, tp)
	dev_t dev;
	register struct tty *tp;
{
	register struct tb *tbp;

	ttywflush(tp);
	for (tbp = tb; tbp < &tb[NTBS]; tbp++)
		if (!tbp->used)
			break;
	if (tbp >= &tb[NTBS])
		return (EBUSY);
	tbp->used++;
	tbp->lastindex = tbp->curindex = 0;
	tp->t_cp = tbp->cbuf;
	tp->t_inbuf = 0;
	tp->T_LINEP = (caddr_t) tbp;
	return (0);
}

/*
 * Break down... called when discipline changed or from device
 * close routine.
 */
tbclose(tp)
	register struct tty *tp;
{
	register int s = spl5();

	((struct tb *) tp->T_LINEP)->used = 0;
	tp->t_cp = 0;
	tp->t_inbuf = 0;
	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
	tp->t_canq.c_cc = 0;
	tp->t_line = 0;			/* paranoid: avoid races */
	splx(s);
}

/*
 * Read from a tablet line.
 * Characters have been buffered in a buffer and
 * decoded. The coordinates are now sluffed back to the user.
 */
tbread(tp, uio)
	register struct tty *tp;
	struct uio *uio;
{
	struct tbmspos *tbpos;
	struct tb *tbp;
	register int s;

	if ((tp->t_state&TS_CARR_ON)==0)
		return (EIO);

	tbp = (struct tb *) (tp->T_LINEP);
	tbpos = &(tbp->tbpos[tbp->lastindex]);

	s = spl5();
	while (tbp->curindex == tbp->lastindex)
		sleep((caddr_t)tbpos, TTIPRI);
	tbp->lastindex = (tbp->lastindex + 1) % TBQUEUESIZE;
	splx(s);

	return (uiomove(tbpos, sizeof *tbpos, UIO_READ, uio));
}

/*
 * Low level character input routine.
 * Stuff the character in the buffer, and decode the it
 * if all the chars are there.
 *
 * This routine could be expanded in-line in the receiver
 * interrupt routine of the dh-11 to make it run as fast as possible.
 */
int	LASTTABC;

tbinput(c, tp)
	register int c;
	register struct tty *tp;
{
	register SCREEN_INFO *si = &ms_info;
	register struct tb *tbp = (struct tb *) tp->T_LINEP;

	register struct tbdata *td;

	if (tp->t_line <= MAXTABLDISC) {
		register int Sync_Flag = 0;

		td = &Tablet_Data[tbp->d_line];
#ifdef ATR
		/*
		 * this is really a Generic change
		 */
		if (((tp->t_inbuf == 0) &&  !((c&td->sync_mask) == td->sync_value)))  {
			return;
		}

		if (td->data_type) {
			*tp->t_cp++ = c&0177;
		} else	{
			*tp->t_cp++ = c;
		}
		if (++tp->t_inbuf == td->data_bytes) {
			if ((*td->decode)(tbp->cbuf, &tbp->tbpos[tbp->curindex],tp,si))
			{
				record_pos (tbp, tp, si);
			}
			tp->t_cp = tbp->cbuf;
			tp->t_inbuf = 0;
		}
#else
		if ((Sync_Flag = ((c&td->sync_mask) == td->sync_value)) ||
							(tp->t_inbuf > 0)) 
		{
			if (Sync_Flag) {
				tp->t_cp = tbp->cbuf;
				tp->t_inbuf = 0;
			}

			if (td->data_type) {
				*tp->t_cp++ = c&0177;
			} else	{
				*tp->t_cp++ = c;
			}
			if (++tp->t_inbuf == td->data_bytes) {
				if ((*td->decode)(tbp->cbuf, &tbp->tbpos[tbp->curindex],tp,si))
				{
					record_pos (tbp, tp, si);
					tp->t_cp = tbp->cbuf;
					tp->t_inbuf = 0;
				} 
			}
		}
#endif
	}
}

/*
 * Decode tablet coordinates from ascii to binary.
 *	(gtco 6 character format)
 */
tbdecodeb(cp, tbpos)
	register char *cp;
	register struct tbmspos *tbpos;
{

	tbpos->status = *cp>>2;	/* this needs to be decoded */
	tbpos->xpos = ((*cp++)&03)<<14;
	tbpos->xpos |= (*cp++)<<7;
	tbpos->xpos |= (*cp++);
	tbpos->ypos = ((*cp++)&03)<<14;
	tbpos->ypos |= (*cp++)<<7;
	tbpos->ypos |= (*cp++);
	return (1);
}

/*
 * Decode tablet coordinates from ascii to binary.
 *	(hitachi 5 character format)
 */
tbdecodea(cp, tbpos)
	register char *cp;
	register struct tbmspos *tbpos;
{
	register int status;
	register char byte;

	byte = *cp++;
	status = (byte&0100) ? 0100000 : 0;
	byte &= ~0100;
	if (byte > 036)
		status |= 1<<((byte-040)/2);
	tbpos->xpos = (*cp++)<<7;
	tbpos->xpos |= (*cp++);
	if (tbpos->xpos < 256)		/* tablet wraps around at 256 */
		status &= 077777;	/* make it out of proximity */
	tbpos->ypos = (*cp++)<<7;
	tbpos->ypos |= (*cp++);
	tbpos->status  = status;
	return (1);
}

#define TB_XY_BITS              0x3F
#define TB_BUTTONS              0x3C
 
/*
 * Decode tablet coordinates from binary data stream
 */
tbdecodec(cp, tbpos)
        register char *cp;
        register struct tbmspos *tbpos;
{
/*
 *       SUPPORTS:                                                              
 *              CALCOMP 2000 Digitizer
 *              BIT PAD ONE Digitizer
 * 
 *      DATA FORMAT:
 *              MODIFIED BIT PAD ONE
 *
 *      Stop   P   6   5   4   3   2   1   0   Start
 *      Bit                                     Bit
 *      --------------------------------------------
 *      1      P   1   B4  B3  B2  B1  0   0     0
 *      1      P   0   X5  X4  X3  X2  X1  X0    0
 *      1      P   0   X11 X10 X9  X8  X7  X6    0
 *      1      P   0   Y5  Y4  Y3  Y2  Y1  Y0    0
 *      1      P   0   Y11 Y10 Y9  Y8  Y7  Y6    0
 *      --------------------------------------------
 *
 *      key:
 *
 *      P       = Parity (even)
 *      Bit 6   = Sync bit
 *                1 identifies first byte in the format;
 *                0 identifies subsequent bytes
 *      B1      = Button 1
 *      B2      = Button 2
 *      B3      = Button 3
 *      B4      = Button 4  (This button was added to data format)
 *      B1-B4   = Action Key indicators: 1 = key pressed
 *                                       0 = key not pressed
 *      X0-X11  = X Bits
 *      Y0-Y11  = Y Bits
 *      X0,Y0   = Least Significant Bit
 *
 */
 
        tbpos->status = ((*cp++) & TB_BUTTONS) >> 2;
 
        tbpos->xpos = ((*cp++) & TB_XY_BITS);
        tbpos->xpos |= ((*cp++) & TB_XY_BITS) << 6;
 
        tbpos->ypos = ((*cp++) & TB_XY_BITS);
        tbpos->ypos |= (*cp & TB_XY_BITS) << 6;

	return (1);
}

#ifndef SIGNEXTEND
#undef SIGNEXTEND
#endif

#ifdef  ibm032
#define SIGNEXTEND(c)  ((int)(c)>=128 ? (int)(c)-256 : (int)(c))
#else
#define SIGNEXTEND(n)  (n)
#endif

#define MCS_BUTTONS_MASK	0x07
#define MCS_RIGHT_BUT		0x01
#define MCS_MIDDLE_BUT		0x02
#define MCS_LEFT_BUT		0x04

#define MCS_BIGSTEP		64


tbdecoded(cp, tbpos)
        register char *cp;
        register struct tbmspos *tbpos;
{
/*
 *       SUPPORTS:                                                              
 *              PC MOUSE by Mouse Systems
 * 
 *      DATA FORMAT:
 *              8-BIT 3-BYTE BINARY DELTA
 *
 *      Stop   7   6   5   4   3   2   1   0   Start
 *      Bit                                     Bit
 *      --------------------------------------------
 *      1      1   0   0   0   0   L   M   R     0
 *      1      X7  X6  X5  X4  X3  X2  X1  X0    0
 *      1      Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0    0
 *      1      X7  X6  X5  X4  X3  X2  X1  X0    0
 *      1      Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0    0
 *      --------------------------------------------
 *
 *      key:
 *
 *      Bits 4-7  = Sync bits
 *                1000 -  identifies first byte in the format;

 *      L      = Left   Button
 *      M      = middle Button
 *      R      = Right  Button
 *      L,M,R  = Action Key indicators: 0 = key pressed
 *                                      1 = key not pressed

 *      X0-X7  = X Bits (2's complement)
 *      Y0-Y7  = Y Bits (2's complement)
 *      X0,Y0  = Least Significant Bit
 *
 */
	register short status;
	register short *pstatus;
	register int xpos = 0;
	register int ypos = 0;
	register    incr;
	int i;

	*(pstatus = &tbpos->status) = 0;
	status =  (~(*cp++)) & 7;

	if (status & MCS_LEFT_BUT)
		*pstatus |= LEFT_BUT;
	if (status & MCS_MIDDLE_BUT)
		*pstatus |= MIDDLE_BUT;
	if (status & MCS_RIGHT_BUT)
		*pstatus |= RIGHT_BUT;

	for (i = 1; i <= 4; i++) {
		if ((*cp > MCS_BIGSTEP) && (*cp < (256-MCS_BIGSTEP))) {
			tbpos->xpos = 0;
			tbpos->ypos = 0;
			return (0);
		}
		incr = *cp++;
		incr = SIGNEXTEND(incr);
		if (tb_debug & 0x01)
			printf ("TBED: incr (%d) xpos (%d) ypos (%d)\n",
				incr, xpos, ypos);

		switch (i) {
		case 1: 
		case 3: 
			xpos += incr;
			break;
		case 2: 
		case 4: 
			ypos -= incr;
			break;
		}
	}
	tbpos->xpos = xpos;
	tbpos->ypos = ypos;

	return (1);
}
#include "../machineio/mouseio.h"

#ifdef IBMRTPC
#define XNEG		0x04
#define YNEG		0x02

#define BUT_MASK	0xA0
#define BUT_SHIFT	5
#endif IBMRTPC

#ifdef ATR
/*
 *
 *	SUPPORTS:                                                              
 *		PS/2 PLANAR MOUSE
 *
 *	DATA FORMAT:
 *		3-BYTE BINARY
 *
 *
 *	BYTE 1 - Status/Sync
 *
 *		Bit 0	Left button status	1 = Depressed
 *		Bit 1	Right button status	1 = Depressed
 *		Bit 2	Sync bit		Always 0
 *		Bit 3	Sync bit		Always 1
 *		Bit 4	X Data Sign		1 = Negative
 *		Bit 5	Y Data Sign		1 = Negative
 *		Bit 6	X Data Overflow		1 = Overflow
 *		Bit 7	Y Data Overflow		1 = Overflow
 *
 *	BYTE 2 - X Data Byte  (Two's complement, Bit 0 = LSB)
 *
 *	BYTE 3 - Y Data Byte  (Two's complement, Bit 0 = LSB)
 *
 */
#define XNEG		0x10
#define YNEG		0x20

#define ATR_RIGHT_BUT	0x02
#define ATR_LEFT_BUT	0x01
#define BUT_MASK	0x03

#define STATUS_STRING	"\20\01LEFT\02RIGHT\05XNEG\06YNEG\07XOV\10YOV"

#define ATR_X_OVER	0x40
#define ATR_Y_OVER	0x80
#endif ATR

#define BUT_DEFS	"\20\01LEFT\02MIDDLE\03RIGHT"

#define SETTIMEOUT(a,b,c) {\
				ptp = tp; psi = si;\
				timeout(a,b,c);\
			}

int single_but = 0;
int lastbut = 0;
struct tty *ptp;
SCREEN_INFO *psi;

/* 3 Button Emulation for Planar Mouse */
tbdecodee(cp, tbpos, tp, si)
        register char *cp;
        register struct tbmspos *tbpos;
	struct tty *tp;
	SCREEN_INFO *si;
{
	register short status;
	register int xpos, ypos;
	int pollms();
	struct tb *tbp;

	tbp = (struct tb *) (tp->T_LINEP);

	/* Check if this was a poll timeout */
	if (cp == 0) {
		if (single_but) {
			if (++single_but > 2)
				single_but = 0;
			else
				SETTIMEOUT (pollms, tbpos, 2);
		}
		return(!single_but);
	}

	/* Check if both buttons are down and simulate a middle button */
#ifdef IBMRTPC
	status = *++cp;
	if ((status & BUT_MASK) == BUT_MASK)
		tbpos->status = MIDDLE_BUT;
	else
		tbpos->status = ((status & BUT_MASK) >> BUT_SHIFT);
#endif IBMRTPC

#ifdef ATR
	status = *cp;	/* sync byte is status byte for PS/2 so don't bump cp */

	switch (status & BUT_MASK) {

	case NO_BUT:			/* check no buttons first */
		tbpos->status = NO_BUT;
		break;
	case ATR_RIGHT_BUT:
		tbpos->status = RIGHT_BUT;
		break;
	case ATR_LEFT_BUT:
		tbpos->status = LEFT_BUT;
		break;
	default:			/* must be both */
		tbpos->status = MIDDLE_BUT;
	}
#endif ATR

#ifdef IBMRTPC
	/* Figure x delta */
	xpos = (*++cp)>>1;
        xpos = (status & XNEG)? (xpos) | 0xffffffC0 : (xpos);

	/* Figure y delta (negative since downward movement of mouse
	 * causes a negative delta and most applications wand that to be
	 * a possitive delta)
	 */
	ypos = (*++cp)>>1;
        ypos = -((status & YNEG)? (ypos) | 0xffffffC0 : (ypos));
#endif IBMRTPC

#ifdef ATR
	/* Figure x delta */
	xpos = (*++cp);
        xpos = (status & XNEG)? (xpos) | 0xffffff80 : (xpos);

	/*
	 * Figure y delta (negative since downward movement of mouse
	 * causes a negative delta and most applications want that to be
	 * a positive delta)
	 */
	ypos = (*++cp);
        ypos = -((status & YNEG)? (ypos) | 0xffffff80 : (ypos));
#endif ATR

	if (tb_debug & 0x01)
		printf ("TB: xpos (%d) ypos (%d)\n", xpos, ypos);

	tbpos->ypos = ypos;
	tbpos->xpos = xpos;
	
	if (tb_debug & 0x01)
		printf ("sb (%x) last (%b) cur (%b)\n", single_but, 
			lastbut, BUT_DEFS, tbpos->status, BUT_DEFS);
	if (!single_but && (lastbut != tbpos->status)) {
		if ((lastbut == MIDDLE_BUT) && (tbpos->status != NO_BUT)) {
			tbpos->status = MIDDLE_BUT;
			single_but = 0;
		} else if ((lastbut == NO_BUT)&&(tbpos->status != MIDDLE_BUT)) {
			SETTIMEOUT (pollms, tbpos, 4);
			single_but++;
		}
	} else if ((single_but) && (lastbut == tbpos->status)) {
		untimeout(pollms, tbpos);
		if (++single_but > 2)
			single_but = 0;
		else
			SETTIMEOUT (pollms, tbpos, 4);
	} else if (single_but) {
		untimeout(pollms, tbpos);
		single_but = 0;
		if (tbpos->status == NO_BUT) {
			/* Record the Previous down button */
			tbpos->status = lastbut;
			record_pos (tbp, tp, si);

			/* Record the up motion */
			tbp->curindex = (tbp->curindex + 1) % TBQUEUESIZE;
			tbpos = &tbp->tbpos[tbp->curindex];
			tbpos->xpos = tbpos->ypos = tbpos->status = 0;
		}
	}
	lastbut = tbpos->status;
	return(!single_but);
}

pollms (tbpos)
register struct tbmspos *tbpos;
{
	register struct tb *tbp;

	if (tb_debug & 0x01)
		printf ("In pollms\n");
	
	tbp = (struct tb *) (ptp->T_LINEP);
	if (tbdecodee (0, tbpos, ptp, psi)) {
		record_pos (tbp, ptp, psi);
	}
	/*msioctl (0,MSIC_READXY,0,0);	No polling until it is reliable*/
}

record_pos (tbp, tp, si)
struct tb *tbp;
struct tty *tp;
SCREEN_INFO *si;
{
	register struct tbmspos *tbpos = &(tbp->tbpos[tbp->curindex]);
	register int s;

	if (tb_debug & 0x02) {
		printf ("record_pos: status(BUT) (%b)\n", tbpos->status, BUT_DEFS);
		printf ("record_pos: tbpos(%x) curindex(%d)\n",tbpos,tbp->curindex);
	}
	tbpos->scount++;
	tbp->curindex = (tbp->curindex + 1) % TBQUEUESIZE;
	wakeup ((caddr_t)tbpos);

	/* Give the emulator the data */
	s = spl5();
	si->ine.intr_reason = E_INT_MOUSE;
	if ((*emulsw[si->ine.emulator].e_rint)(0, tp, si)) {
		tbp->lastindex = tbp->curindex;
	}
	splx(s);
}


/* 2 Button reporting for Planar Mouse */
tbdecodef(cp, tbpos, tp, si)
        register char *cp;
        register struct tbmspos *tbpos;
{
	register short status;
	register int xpos, ypos;

	/* Return Generic Left and/or Right Button */
#ifdef IBMRTPC
	status = *++cp;
	if ((status & BUT_MASK) == BUT_MASK)
		tbpos->status = LEFT_BUT | RIGHT_BUT;
	else
		tbpos->status = ((status & BUT_MASK) >> BUT_SHIFT);
#endif IBMRTPC

#ifdef ATR
	status = *cp;	/* sync byte is status byte for PS/2 so don't bump cp */

	switch (status & BUT_MASK) {

	case NO_BUT:			/* check no buttons first */
		tbpos->status = NO_BUT;
	case ATR_RIGHT_BUT:
		tbpos->status = RIGHT_BUT;
		break;
	case ATR_LEFT_BUT:
		tbpos->status = LEFT_BUT;
		break;
	default:			/* must be both */
		tbpos->status = LEFT_BUT | RIGHT_BUT;
	}
#endif ATR

	/* Figure x delta */
	xpos = (*++cp)>>1;
        xpos = (status & XNEG)? (xpos) | 0xffffffC0 : (xpos);

	/* Figure y delta (negative since downward movement of mouse
	 * causes a negative delta and most applications want that to be
	 * a possitive delta)
	 */
	ypos = (*++cp)>>1;
        ypos = -((status & YNEG)? (ypos) | 0xffffffC0 : (ypos));

	tbpos->ypos = ypos;
	tbpos->xpos = xpos;
	
	return(1);
}
#define SPLRETURN(r) { splx(s); return(r); }

/*
 * This routine is called whenever a ioctl is about to be performed
 * and gets a chance to reject the ioctl.  We reject all teletype
 * oriented ioctl's except those which set the discipline, and
 * those which get parameters (gtty and get special characters).
 */
/*ARGSUSED*/
tbioctl(tp, cmd, data)
	register struct tty *tp;
	register caddr_t data;
{
	register int save;
	register int s;
	int error;

	s = spl5();
	if (tb_debug & 0x04)
		printf ("tbioctl: switch (%x) against (%x) & (%x)\n",
			cmd, TBIOGETD, TBIOSETD);

	switch (cmd) {

	/* get mouse decode discipline number */
	case TBIOGETD:
		*(int *)data = (((struct tb *) (tp->T_LINEP))->d_line);
		error = 0;
		break;

	/* set mouse decode discipline number */
	case TBIOSETD:
		save = (((struct tb *) (tp->T_LINEP))->d_line);
		(((struct tb *) (tp->T_LINEP))->d_line) = *(int *)data;
		*(int *)data = save;
		error = 0;
		if (tb_debug & 0x04)
			printf ("TBIOSETD: was (%d) is (%d)\n",
				save, (((struct tb *) (tp->T_LINEP))->d_line));
		break;

	default:
		error = -1;
		break;
	}
	SPLRETURN (error);
}

tbselect(dev, rw)
	dev_t dev;
	int rw;
{
	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
	struct tb *tbp;
	int s = spl5();

	tbp = (struct tb *) (tp->T_LINEP);

	switch (rw) {

	case FREAD:
		if (tbp->curindex != tbp->lastindex)
			goto win;
		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
			tp->t_state |= TS_RCOLL;
		else
			tp->t_rsel = u.u_procp;
		break;

	case FWRITE:
		goto win;
	}
	splx(s);
	return (0);
win:
	splx(s);
	return (1);
}
#endif NTB
