xref: /titanic_50/usr/src/uts/common/io/ptem.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI" /* from S5R4 1.13 */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * Description:
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * The PTEM streams module is used as a pseudo driver emulator.  Its purpose
37*7c478bd9Sstevel@tonic-gate  * is to emulate the ioctl() functions of a terminal device driver.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/termio.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/pcb.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/strtty.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/jioctl.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/ptem.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/ptms.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate extern struct streamtab pteminfo;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
65*7c478bd9Sstevel@tonic-gate 	"ptem",
66*7c478bd9Sstevel@tonic-gate 	&pteminfo,
67*7c478bd9Sstevel@tonic-gate 	D_MTQPAIR | D_MP
68*7c478bd9Sstevel@tonic-gate };
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
71*7c478bd9Sstevel@tonic-gate 	&mod_strmodops, "pty hardware emulator", &fsw
72*7c478bd9Sstevel@tonic-gate };
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
75*7c478bd9Sstevel@tonic-gate 	MODREV_1, &modlstrmod, NULL
76*7c478bd9Sstevel@tonic-gate };
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate int
_init()79*7c478bd9Sstevel@tonic-gate _init()
80*7c478bd9Sstevel@tonic-gate {
81*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
82*7c478bd9Sstevel@tonic-gate }
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate int
_fini()85*7c478bd9Sstevel@tonic-gate _fini()
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)91*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
92*7c478bd9Sstevel@tonic-gate {
93*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
94*7c478bd9Sstevel@tonic-gate }
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /*
97*7c478bd9Sstevel@tonic-gate  * stream data structure definitions
98*7c478bd9Sstevel@tonic-gate  */
99*7c478bd9Sstevel@tonic-gate static int ptemopen(queue_t *, dev_t  *, int, int, cred_t *);
100*7c478bd9Sstevel@tonic-gate static int ptemclose(queue_t *, int, cred_t *);
101*7c478bd9Sstevel@tonic-gate static void ptemrput(queue_t *, mblk_t *);
102*7c478bd9Sstevel@tonic-gate static void ptemwput(queue_t *, mblk_t *);
103*7c478bd9Sstevel@tonic-gate static void ptemwsrv(queue_t *);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate static struct module_info ptem_info = {
106*7c478bd9Sstevel@tonic-gate 	0xabcd,
107*7c478bd9Sstevel@tonic-gate 	"ptem",
108*7c478bd9Sstevel@tonic-gate 	0,
109*7c478bd9Sstevel@tonic-gate 	512,
110*7c478bd9Sstevel@tonic-gate 	512,
111*7c478bd9Sstevel@tonic-gate 	128
112*7c478bd9Sstevel@tonic-gate };
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate static struct qinit ptemrinit = {
115*7c478bd9Sstevel@tonic-gate 	(int (*)()) ptemrput,
116*7c478bd9Sstevel@tonic-gate 	NULL,
117*7c478bd9Sstevel@tonic-gate 	ptemopen,
118*7c478bd9Sstevel@tonic-gate 	ptemclose,
119*7c478bd9Sstevel@tonic-gate 	NULL,
120*7c478bd9Sstevel@tonic-gate 	&ptem_info,
121*7c478bd9Sstevel@tonic-gate 	NULL
122*7c478bd9Sstevel@tonic-gate };
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static struct qinit ptemwinit = {
125*7c478bd9Sstevel@tonic-gate 	(int (*)()) ptemwput,
126*7c478bd9Sstevel@tonic-gate 	(int (*)()) ptemwsrv,
127*7c478bd9Sstevel@tonic-gate 	ptemopen,
128*7c478bd9Sstevel@tonic-gate 	ptemclose,
129*7c478bd9Sstevel@tonic-gate 	nulldev,
130*7c478bd9Sstevel@tonic-gate 	&ptem_info,
131*7c478bd9Sstevel@tonic-gate 	NULL
132*7c478bd9Sstevel@tonic-gate };
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate struct streamtab pteminfo = {
135*7c478bd9Sstevel@tonic-gate 	&ptemrinit,
136*7c478bd9Sstevel@tonic-gate 	&ptemwinit,
137*7c478bd9Sstevel@tonic-gate 	NULL,
138*7c478bd9Sstevel@tonic-gate 	NULL
139*7c478bd9Sstevel@tonic-gate };
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate static void	ptioc(queue_t *, mblk_t *, int);
142*7c478bd9Sstevel@tonic-gate static int	ptemwmsg(queue_t *, mblk_t *);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate  * ptemopen - open routine gets called when the module gets pushed onto the
146*7c478bd9Sstevel@tonic-gate  * stream.
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
149*7c478bd9Sstevel@tonic-gate static int
ptemopen(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * credp)150*7c478bd9Sstevel@tonic-gate ptemopen(
151*7c478bd9Sstevel@tonic-gate 	queue_t    *q,		/* pointer to the read side queue */
152*7c478bd9Sstevel@tonic-gate 	dev_t   *devp,		/* pointer to stream tail's dev */
153*7c478bd9Sstevel@tonic-gate 	int	oflag,		/* the user open(2) supplied flags */
154*7c478bd9Sstevel@tonic-gate 	int	sflag,		/* open state flag */
155*7c478bd9Sstevel@tonic-gate 	cred_t *credp)		/* credentials */
156*7c478bd9Sstevel@tonic-gate {
157*7c478bd9Sstevel@tonic-gate 	struct ptem *ntp;	/* ptem entry for this PTEM module */
158*7c478bd9Sstevel@tonic-gate 	mblk_t *mop;		/* an setopts mblk */
159*7c478bd9Sstevel@tonic-gate 	struct stroptions *sop;
160*7c478bd9Sstevel@tonic-gate 	struct termios *termiosp;
161*7c478bd9Sstevel@tonic-gate 	int len;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	if (sflag != MODOPEN)
164*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	if (q->q_ptr != NULL) {
167*7c478bd9Sstevel@tonic-gate 		/* It's already attached. */
168*7c478bd9Sstevel@tonic-gate 		return (0);
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	/*
172*7c478bd9Sstevel@tonic-gate 	 * Allocate state structure.
173*7c478bd9Sstevel@tonic-gate 	 */
174*7c478bd9Sstevel@tonic-gate 	ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	/*
177*7c478bd9Sstevel@tonic-gate 	 * Allocate a message block, used to pass the zero length message for
178*7c478bd9Sstevel@tonic-gate 	 * "stty 0".
179*7c478bd9Sstevel@tonic-gate 	 *
180*7c478bd9Sstevel@tonic-gate 	 * NOTE: it's better to find out if such a message block can be
181*7c478bd9Sstevel@tonic-gate 	 *	 allocated before it's needed than to not be able to
182*7c478bd9Sstevel@tonic-gate 	 *	 deliver (for possible lack of buffers) when a hang-up
183*7c478bd9Sstevel@tonic-gate 	 *	 occurs.
184*7c478bd9Sstevel@tonic-gate 	 */
185*7c478bd9Sstevel@tonic-gate 	if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) {
186*7c478bd9Sstevel@tonic-gate 		kmem_free(ntp, sizeof (*ntp));
187*7c478bd9Sstevel@tonic-gate 		return (EAGAIN);
188*7c478bd9Sstevel@tonic-gate 	}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * Initialize an M_SETOPTS message to set up hi/lo water marks on
192*7c478bd9Sstevel@tonic-gate 	 * stream head read queue and add controlling tty if not set.
193*7c478bd9Sstevel@tonic-gate 	 */
194*7c478bd9Sstevel@tonic-gate 	mop = allocb(sizeof (struct stroptions), BPRI_MED);
195*7c478bd9Sstevel@tonic-gate 	if (mop == NULL) {
196*7c478bd9Sstevel@tonic-gate 		freemsg(ntp->dack_ptr);
197*7c478bd9Sstevel@tonic-gate 		kmem_free(ntp, sizeof (*ntp));
198*7c478bd9Sstevel@tonic-gate 		return (EAGAIN);
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 	mop->b_datap->db_type = M_SETOPTS;
201*7c478bd9Sstevel@tonic-gate 	mop->b_wptr += sizeof (struct stroptions);
202*7c478bd9Sstevel@tonic-gate 	sop = (struct stroptions *)mop->b_rptr;
203*7c478bd9Sstevel@tonic-gate 	sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
204*7c478bd9Sstevel@tonic-gate 	sop->so_hiwat = 512;
205*7c478bd9Sstevel@tonic-gate 	sop->so_lowat = 256;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	/*
208*7c478bd9Sstevel@tonic-gate 	 * Cross-link.
209*7c478bd9Sstevel@tonic-gate 	 */
210*7c478bd9Sstevel@tonic-gate 	ntp->q_ptr = q;
211*7c478bd9Sstevel@tonic-gate 	q->q_ptr = ntp;
212*7c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = ntp;
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	/*
215*7c478bd9Sstevel@tonic-gate 	 * Get termios defaults.  These are stored as
216*7c478bd9Sstevel@tonic-gate 	 * a property in the "options" node.
217*7c478bd9Sstevel@tonic-gate 	 */
218*7c478bd9Sstevel@tonic-gate 	if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes",
219*7c478bd9Sstevel@tonic-gate 	    (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS &&
220*7c478bd9Sstevel@tonic-gate 	    len == sizeof (struct termios)) {
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 		ntp->cflags = termiosp->c_cflag;
223*7c478bd9Sstevel@tonic-gate 		kmem_free(termiosp, len);
224*7c478bd9Sstevel@tonic-gate 	} else {
225*7c478bd9Sstevel@tonic-gate 		/*
226*7c478bd9Sstevel@tonic-gate 		 * Gack!  Whine about it.
227*7c478bd9Sstevel@tonic-gate 		 */
228*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!");
229*7c478bd9Sstevel@tonic-gate 	}
230*7c478bd9Sstevel@tonic-gate 	ntp->wsz.ws_row = 0;
231*7c478bd9Sstevel@tonic-gate 	ntp->wsz.ws_col = 0;
232*7c478bd9Sstevel@tonic-gate 	ntp->wsz.ws_xpixel = 0;
233*7c478bd9Sstevel@tonic-gate 	ntp->wsz.ws_ypixel = 0;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	ntp->state = 0;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/*
238*7c478bd9Sstevel@tonic-gate 	 * Commit to the open and send the M_SETOPTS off to the stream head.
239*7c478bd9Sstevel@tonic-gate 	 */
240*7c478bd9Sstevel@tonic-gate 	qprocson(q);
241*7c478bd9Sstevel@tonic-gate 	putnext(q, mop);
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	return (0);
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate /*
248*7c478bd9Sstevel@tonic-gate  * ptemclose - This routine gets called when the module gets popped off of the
249*7c478bd9Sstevel@tonic-gate  * stream.
250*7c478bd9Sstevel@tonic-gate  */
251*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
252*7c478bd9Sstevel@tonic-gate static int
ptemclose(queue_t * q,int flag,cred_t * credp)253*7c478bd9Sstevel@tonic-gate ptemclose(queue_t *q, int flag, cred_t *credp)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	struct ptem *ntp;	/* ptem entry for this PTEM module */
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	qprocsoff(q);
258*7c478bd9Sstevel@tonic-gate 	ntp = (struct ptem *)q->q_ptr;
259*7c478bd9Sstevel@tonic-gate 	freemsg(ntp->dack_ptr);
260*7c478bd9Sstevel@tonic-gate 	kmem_free(ntp, sizeof (*ntp));
261*7c478bd9Sstevel@tonic-gate 	q->q_ptr = WR(q)->q_ptr = NULL;
262*7c478bd9Sstevel@tonic-gate 	return (0);
263*7c478bd9Sstevel@tonic-gate }
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate /*
267*7c478bd9Sstevel@tonic-gate  * ptemrput - Module read queue put procedure.
268*7c478bd9Sstevel@tonic-gate  *
269*7c478bd9Sstevel@tonic-gate  * This is called from the module or driver downstream.
270*7c478bd9Sstevel@tonic-gate  */
271*7c478bd9Sstevel@tonic-gate static void
ptemrput(queue_t * q,mblk_t * mp)272*7c478bd9Sstevel@tonic-gate ptemrput(queue_t *q, mblk_t *mp)
273*7c478bd9Sstevel@tonic-gate {
274*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;	/* M_IOCTL data */
275*7c478bd9Sstevel@tonic-gate 	struct copyresp *resp;	/* transparent ioctl response struct */
276*7c478bd9Sstevel@tonic-gate 	int error;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
279*7c478bd9Sstevel@tonic-gate 	case M_DELAY:
280*7c478bd9Sstevel@tonic-gate 	case M_READ:
281*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
282*7c478bd9Sstevel@tonic-gate 		break;
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	case M_IOCTL:
285*7c478bd9Sstevel@tonic-gate 		iocp = (struct iocblk *)mp->b_rptr;
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 		switch (iocp->ioc_cmd) {
288*7c478bd9Sstevel@tonic-gate 		case TCSBRK:
289*7c478bd9Sstevel@tonic-gate 			/*
290*7c478bd9Sstevel@tonic-gate 			 * Send a break message upstream.
291*7c478bd9Sstevel@tonic-gate 			 *
292*7c478bd9Sstevel@tonic-gate 			 * XXX:	Shouldn't the argument come into play in
293*7c478bd9Sstevel@tonic-gate 			 *	determining whether or not so send an M_BREAK?
294*7c478bd9Sstevel@tonic-gate 			 *	It certainly does in the write-side direction.
295*7c478bd9Sstevel@tonic-gate 			 */
296*7c478bd9Sstevel@tonic-gate 			error = miocpullup(mp, sizeof (int));
297*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
298*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, error);
299*7c478bd9Sstevel@tonic-gate 				break;
300*7c478bd9Sstevel@tonic-gate 			}
301*7c478bd9Sstevel@tonic-gate 			if (!(*(int *)mp->b_cont->b_rptr)) {
302*7c478bd9Sstevel@tonic-gate 				if (!putnextctl(q, M_BREAK)) {
303*7c478bd9Sstevel@tonic-gate 					/*
304*7c478bd9Sstevel@tonic-gate 					 * Send an NAK reply back
305*7c478bd9Sstevel@tonic-gate 					 */
306*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, EAGAIN);
307*7c478bd9Sstevel@tonic-gate 					break;
308*7c478bd9Sstevel@tonic-gate 				}
309*7c478bd9Sstevel@tonic-gate 			}
310*7c478bd9Sstevel@tonic-gate 			/*
311*7c478bd9Sstevel@tonic-gate 			 * ACK it.
312*7c478bd9Sstevel@tonic-gate 			 */
313*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, NULL, 0, 0);
314*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
315*7c478bd9Sstevel@tonic-gate 			break;
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 		case JWINSIZE:
318*7c478bd9Sstevel@tonic-gate 		case TIOCGWINSZ:
319*7c478bd9Sstevel@tonic-gate 		case TIOCSWINSZ:
320*7c478bd9Sstevel@tonic-gate 			ptioc(q, mp, RDSIDE);
321*7c478bd9Sstevel@tonic-gate 			break;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 		case TIOCSIGNAL:
324*7c478bd9Sstevel@tonic-gate 			/*
325*7c478bd9Sstevel@tonic-gate 			 * The following subtle logic is due to the fact that
326*7c478bd9Sstevel@tonic-gate 			 * `mp' may be in any one of three distinct formats:
327*7c478bd9Sstevel@tonic-gate 			 *
328*7c478bd9Sstevel@tonic-gate 			 *	1. A transparent M_IOCTL with an intptr_t-sized
329*7c478bd9Sstevel@tonic-gate 			 *	   payload containing the signal number.
330*7c478bd9Sstevel@tonic-gate 			 *
331*7c478bd9Sstevel@tonic-gate 			 *	2. An I_STR M_IOCTL with an int-sized payload
332*7c478bd9Sstevel@tonic-gate 			 *	   containing the signal number.
333*7c478bd9Sstevel@tonic-gate 			 *
334*7c478bd9Sstevel@tonic-gate 			 *	3. An M_IOCDATA with an int-sized payload
335*7c478bd9Sstevel@tonic-gate 			 *	   containing the signal number.
336*7c478bd9Sstevel@tonic-gate 			 */
337*7c478bd9Sstevel@tonic-gate 			if (iocp->ioc_count == TRANSPARENT) {
338*7c478bd9Sstevel@tonic-gate 				intptr_t sig = *(intptr_t *)mp->b_cont->b_rptr;
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 				if (sig < 1 || sig >= NSIG) {
341*7c478bd9Sstevel@tonic-gate 					/*
342*7c478bd9Sstevel@tonic-gate 					 * it's transparent with pointer
343*7c478bd9Sstevel@tonic-gate 					 * to the arg
344*7c478bd9Sstevel@tonic-gate 					 */
345*7c478bd9Sstevel@tonic-gate 					mcopyin(mp, NULL, sizeof (int), NULL);
346*7c478bd9Sstevel@tonic-gate 					qreply(q, mp);
347*7c478bd9Sstevel@tonic-gate 					break;
348*7c478bd9Sstevel@tonic-gate 				}
349*7c478bd9Sstevel@tonic-gate 			}
350*7c478bd9Sstevel@tonic-gate 			ptioc(q, mp, RDSIDE);
351*7c478bd9Sstevel@tonic-gate 			break;
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		case TIOCREMOTE:
354*7c478bd9Sstevel@tonic-gate 			if (iocp->ioc_count != TRANSPARENT)
355*7c478bd9Sstevel@tonic-gate 				ptioc(q, mp, RDSIDE);
356*7c478bd9Sstevel@tonic-gate 			else {
357*7c478bd9Sstevel@tonic-gate 				mcopyin(mp, NULL, sizeof (int), NULL);
358*7c478bd9Sstevel@tonic-gate 				qreply(q, mp);
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 			break;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 		default:
363*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
364*7c478bd9Sstevel@tonic-gate 			break;
365*7c478bd9Sstevel@tonic-gate 		}
366*7c478bd9Sstevel@tonic-gate 		break;
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	case M_IOCDATA:
369*7c478bd9Sstevel@tonic-gate 		resp = (struct copyresp *)mp->b_rptr;
370*7c478bd9Sstevel@tonic-gate 		if (resp->cp_rval) {
371*7c478bd9Sstevel@tonic-gate 			/*
372*7c478bd9Sstevel@tonic-gate 			 * Just free message on failure.
373*7c478bd9Sstevel@tonic-gate 			 */
374*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
375*7c478bd9Sstevel@tonic-gate 			break;
376*7c478bd9Sstevel@tonic-gate 		}
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 		/*
379*7c478bd9Sstevel@tonic-gate 		 * Only need to copy data for the SET case.
380*7c478bd9Sstevel@tonic-gate 		 */
381*7c478bd9Sstevel@tonic-gate 		switch (resp->cp_cmd) {
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 		case TIOCSWINSZ:
384*7c478bd9Sstevel@tonic-gate 		case TIOCSIGNAL:
385*7c478bd9Sstevel@tonic-gate 		case TIOCREMOTE:
386*7c478bd9Sstevel@tonic-gate 			ptioc(q, mp, RDSIDE);
387*7c478bd9Sstevel@tonic-gate 			break;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 		case JWINSIZE:
390*7c478bd9Sstevel@tonic-gate 		case TIOCGWINSZ:
391*7c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCACK;
392*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, NULL, 0, 0);
393*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
394*7c478bd9Sstevel@tonic-gate 			break;
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 		default:
397*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
398*7c478bd9Sstevel@tonic-gate 			break;
399*7c478bd9Sstevel@tonic-gate 	}
400*7c478bd9Sstevel@tonic-gate 	break;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	case M_IOCACK:
403*7c478bd9Sstevel@tonic-gate 	case M_IOCNAK:
404*7c478bd9Sstevel@tonic-gate 		/*
405*7c478bd9Sstevel@tonic-gate 		 * We only pass write-side ioctls through to the master that
406*7c478bd9Sstevel@tonic-gate 		 * we've already ACKed or NAKed to the stream head.  Thus, we
407*7c478bd9Sstevel@tonic-gate 		 * discard ones arriving from below, since they're redundant
408*7c478bd9Sstevel@tonic-gate 		 * from the point of view of modules above us.
409*7c478bd9Sstevel@tonic-gate 		 */
410*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
411*7c478bd9Sstevel@tonic-gate 		break;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	case M_HANGUP:
414*7c478bd9Sstevel@tonic-gate 		/*
415*7c478bd9Sstevel@tonic-gate 		 * clear blocked state.
416*7c478bd9Sstevel@tonic-gate 		 */
417*7c478bd9Sstevel@tonic-gate 		{
418*7c478bd9Sstevel@tonic-gate 			struct ptem *ntp = (struct ptem *)q->q_ptr;
419*7c478bd9Sstevel@tonic-gate 			if (ntp->state & OFLOW_CTL) {
420*7c478bd9Sstevel@tonic-gate 				ntp->state &= ~OFLOW_CTL;
421*7c478bd9Sstevel@tonic-gate 				qenable(WR(q));
422*7c478bd9Sstevel@tonic-gate 			}
423*7c478bd9Sstevel@tonic-gate 		}
424*7c478bd9Sstevel@tonic-gate 	default:
425*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
426*7c478bd9Sstevel@tonic-gate 		break;
427*7c478bd9Sstevel@tonic-gate 	}
428*7c478bd9Sstevel@tonic-gate }
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate /*
432*7c478bd9Sstevel@tonic-gate  * ptemwput - Module write queue put procedure.
433*7c478bd9Sstevel@tonic-gate  *
434*7c478bd9Sstevel@tonic-gate  * This is called from the module or stream head upstream.
435*7c478bd9Sstevel@tonic-gate  *
436*7c478bd9Sstevel@tonic-gate  * XXX:	This routine is quite lazy about handling allocation failures,
437*7c478bd9Sstevel@tonic-gate  *	basically just giving up and reporting failure.  It really ought to
438*7c478bd9Sstevel@tonic-gate  *	set up bufcalls and only fail when it's absolutely necessary.
439*7c478bd9Sstevel@tonic-gate  */
440*7c478bd9Sstevel@tonic-gate static void
ptemwput(queue_t * q,mblk_t * mp)441*7c478bd9Sstevel@tonic-gate ptemwput(queue_t *q, mblk_t *mp)
442*7c478bd9Sstevel@tonic-gate {
443*7c478bd9Sstevel@tonic-gate 	struct ptem *ntp = (struct ptem *)q->q_ptr;
444*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;	/* outgoing ioctl structure */
445*7c478bd9Sstevel@tonic-gate 	struct copyresp *resp;
446*7c478bd9Sstevel@tonic-gate 	unsigned char type = mp->b_datap->db_type;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	if (type >= QPCTL) {
449*7c478bd9Sstevel@tonic-gate 		switch (type) {
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 		case M_IOCDATA:
452*7c478bd9Sstevel@tonic-gate 			resp = (struct copyresp *)mp->b_rptr;
453*7c478bd9Sstevel@tonic-gate 			if (resp->cp_rval) {
454*7c478bd9Sstevel@tonic-gate 				/*
455*7c478bd9Sstevel@tonic-gate 				 * Just free message on failure.
456*7c478bd9Sstevel@tonic-gate 				 */
457*7c478bd9Sstevel@tonic-gate 				freemsg(mp);
458*7c478bd9Sstevel@tonic-gate 				break;
459*7c478bd9Sstevel@tonic-gate 			}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 			/*
462*7c478bd9Sstevel@tonic-gate 			 * Only need to copy data for the SET case.
463*7c478bd9Sstevel@tonic-gate 			 */
464*7c478bd9Sstevel@tonic-gate 			switch (resp->cp_cmd) {
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 				case TIOCSWINSZ:
467*7c478bd9Sstevel@tonic-gate 					ptioc(q, mp, WRSIDE);
468*7c478bd9Sstevel@tonic-gate 					break;
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 				case JWINSIZE:
471*7c478bd9Sstevel@tonic-gate 				case TIOCGWINSZ:
472*7c478bd9Sstevel@tonic-gate 					mioc2ack(mp, NULL, 0, 0);
473*7c478bd9Sstevel@tonic-gate 					qreply(q, mp);
474*7c478bd9Sstevel@tonic-gate 					break;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 				default:
477*7c478bd9Sstevel@tonic-gate 					freemsg(mp);
478*7c478bd9Sstevel@tonic-gate 			}
479*7c478bd9Sstevel@tonic-gate 			break;
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 		case M_FLUSH:
482*7c478bd9Sstevel@tonic-gate 			if (*mp->b_rptr & FLUSHW) {
483*7c478bd9Sstevel@tonic-gate 			    if ((ntp->state & IS_PTSTTY) &&
484*7c478bd9Sstevel@tonic-gate 					(*mp->b_rptr & FLUSHBAND))
485*7c478bd9Sstevel@tonic-gate 				flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
486*7c478bd9Sstevel@tonic-gate 			    else
487*7c478bd9Sstevel@tonic-gate 				flushq(q, FLUSHDATA);
488*7c478bd9Sstevel@tonic-gate 			}
489*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
490*7c478bd9Sstevel@tonic-gate 			break;
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 		case M_READ:
493*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
494*7c478bd9Sstevel@tonic-gate 			break;
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 		case M_STOP:
497*7c478bd9Sstevel@tonic-gate 			/*
498*7c478bd9Sstevel@tonic-gate 			 * Set the output flow control state.
499*7c478bd9Sstevel@tonic-gate 			 */
500*7c478bd9Sstevel@tonic-gate 			ntp->state |= OFLOW_CTL;
501*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
502*7c478bd9Sstevel@tonic-gate 			break;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 		case M_START:
505*7c478bd9Sstevel@tonic-gate 			/*
506*7c478bd9Sstevel@tonic-gate 			 * Relieve the output flow control state.
507*7c478bd9Sstevel@tonic-gate 			 */
508*7c478bd9Sstevel@tonic-gate 			ntp->state &= ~OFLOW_CTL;
509*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
510*7c478bd9Sstevel@tonic-gate 			qenable(q);
511*7c478bd9Sstevel@tonic-gate 			break;
512*7c478bd9Sstevel@tonic-gate 		default:
513*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
514*7c478bd9Sstevel@tonic-gate 			break;
515*7c478bd9Sstevel@tonic-gate 		}
516*7c478bd9Sstevel@tonic-gate 		return;
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 	/*
519*7c478bd9Sstevel@tonic-gate 	 * If our queue is nonempty or flow control persists
520*7c478bd9Sstevel@tonic-gate 	 * downstream or module in stopped state, queue this message.
521*7c478bd9Sstevel@tonic-gate 	 */
522*7c478bd9Sstevel@tonic-gate 	if (q->q_first != NULL || !bcanputnext(q, mp->b_band)) {
523*7c478bd9Sstevel@tonic-gate 		/*
524*7c478bd9Sstevel@tonic-gate 		 * Exception: ioctls, except for those defined to
525*7c478bd9Sstevel@tonic-gate 		 * take effect after output has drained, should be
526*7c478bd9Sstevel@tonic-gate 		 * processed immediately.
527*7c478bd9Sstevel@tonic-gate 		 */
528*7c478bd9Sstevel@tonic-gate 		switch (type) {
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 		case M_IOCTL:
531*7c478bd9Sstevel@tonic-gate 			iocp = (struct iocblk *)mp->b_rptr;
532*7c478bd9Sstevel@tonic-gate 			switch (iocp->ioc_cmd) {
533*7c478bd9Sstevel@tonic-gate 			/*
534*7c478bd9Sstevel@tonic-gate 			 * Queue these.
535*7c478bd9Sstevel@tonic-gate 			 */
536*7c478bd9Sstevel@tonic-gate 			case TCSETSW:
537*7c478bd9Sstevel@tonic-gate 			case TCSETSF:
538*7c478bd9Sstevel@tonic-gate 			case TCSETAW:
539*7c478bd9Sstevel@tonic-gate 			case TCSETAF:
540*7c478bd9Sstevel@tonic-gate 			case TCSBRK:
541*7c478bd9Sstevel@tonic-gate 				break;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 			/*
544*7c478bd9Sstevel@tonic-gate 			 * Handle all others immediately.
545*7c478bd9Sstevel@tonic-gate 			 */
546*7c478bd9Sstevel@tonic-gate 			default:
547*7c478bd9Sstevel@tonic-gate 				(void) ptemwmsg(q, mp);
548*7c478bd9Sstevel@tonic-gate 				return;
549*7c478bd9Sstevel@tonic-gate 			}
550*7c478bd9Sstevel@tonic-gate 			break;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 		case M_DELAY: /* tty delays not supported */
553*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
554*7c478bd9Sstevel@tonic-gate 			return;
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 		case M_DATA:
557*7c478bd9Sstevel@tonic-gate 			if ((mp->b_wptr - mp->b_rptr) < 0) {
558*7c478bd9Sstevel@tonic-gate 				/*
559*7c478bd9Sstevel@tonic-gate 				 * Free all bad length messages.
560*7c478bd9Sstevel@tonic-gate 				 */
561*7c478bd9Sstevel@tonic-gate 				freemsg(mp);
562*7c478bd9Sstevel@tonic-gate 				return;
563*7c478bd9Sstevel@tonic-gate 			} else if ((mp->b_wptr - mp->b_rptr) == 0) {
564*7c478bd9Sstevel@tonic-gate 				if (!(ntp->state & IS_PTSTTY)) {
565*7c478bd9Sstevel@tonic-gate 					freemsg(mp);
566*7c478bd9Sstevel@tonic-gate 					return;
567*7c478bd9Sstevel@tonic-gate 				}
568*7c478bd9Sstevel@tonic-gate 			}
569*7c478bd9Sstevel@tonic-gate 		}
570*7c478bd9Sstevel@tonic-gate 		(void) putq(q, mp);
571*7c478bd9Sstevel@tonic-gate 		return;
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 	/*
574*7c478bd9Sstevel@tonic-gate 	 * fast path into ptemwmsg to dispose of mp.
575*7c478bd9Sstevel@tonic-gate 	 */
576*7c478bd9Sstevel@tonic-gate 	if (!ptemwmsg(q, mp))
577*7c478bd9Sstevel@tonic-gate 		(void) putq(q, mp);
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate /*
581*7c478bd9Sstevel@tonic-gate  * ptem write queue service procedure.
582*7c478bd9Sstevel@tonic-gate  */
583*7c478bd9Sstevel@tonic-gate static void
ptemwsrv(queue_t * q)584*7c478bd9Sstevel@tonic-gate ptemwsrv(queue_t *q)
585*7c478bd9Sstevel@tonic-gate {
586*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	while ((mp = getq(q)) != NULL) {
589*7c478bd9Sstevel@tonic-gate 		if (!bcanputnext(q, mp->b_band) || !ptemwmsg(q, mp)) {
590*7c478bd9Sstevel@tonic-gate 			(void) putbq(q, mp);
591*7c478bd9Sstevel@tonic-gate 			break;
592*7c478bd9Sstevel@tonic-gate 		}
593*7c478bd9Sstevel@tonic-gate 	}
594*7c478bd9Sstevel@tonic-gate }
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 
597*7c478bd9Sstevel@tonic-gate /*
598*7c478bd9Sstevel@tonic-gate  * This routine is called from both ptemwput and ptemwsrv to do the
599*7c478bd9Sstevel@tonic-gate  * actual work of dealing with mp.  ptmewput will have already
600*7c478bd9Sstevel@tonic-gate  * dealt with high priority messages.
601*7c478bd9Sstevel@tonic-gate  *
602*7c478bd9Sstevel@tonic-gate  * Return 1 if the message was processed completely and 0 if not.
603*7c478bd9Sstevel@tonic-gate  */
604*7c478bd9Sstevel@tonic-gate static int
ptemwmsg(queue_t * q,mblk_t * mp)605*7c478bd9Sstevel@tonic-gate ptemwmsg(queue_t *q, mblk_t *mp)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate 	struct ptem *ntp = (struct ptem *)q->q_ptr;
608*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;	/* outgoing ioctl structure */
609*7c478bd9Sstevel@tonic-gate 	struct termio *termiop;
610*7c478bd9Sstevel@tonic-gate 	struct termios *termiosp;
611*7c478bd9Sstevel@tonic-gate 	mblk_t *dack_ptr;		/* disconnect message ACK block */
612*7c478bd9Sstevel@tonic-gate 	mblk_t *pckt_msgp;		/* message sent to the PCKT module */
613*7c478bd9Sstevel@tonic-gate 	mblk_t *dp;			/* ioctl reply data */
614*7c478bd9Sstevel@tonic-gate 	tcflag_t cflags;
615*7c478bd9Sstevel@tonic-gate 	int error;
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	case M_IOCTL:
620*7c478bd9Sstevel@tonic-gate 		/*
621*7c478bd9Sstevel@tonic-gate 		 * Note:  for each "set" type operation a copy
622*7c478bd9Sstevel@tonic-gate 		 * of the M_IOCTL message is made and passed
623*7c478bd9Sstevel@tonic-gate 		 * downstream.  Eventually the PCKT module, if
624*7c478bd9Sstevel@tonic-gate 		 * it has been pushed, should pick up this message.
625*7c478bd9Sstevel@tonic-gate 		 * If the PCKT module has not been pushed the master
626*7c478bd9Sstevel@tonic-gate 		 * side stream head will free it.
627*7c478bd9Sstevel@tonic-gate 		 */
628*7c478bd9Sstevel@tonic-gate 		iocp = (struct iocblk *)mp->b_rptr;
629*7c478bd9Sstevel@tonic-gate 		switch (iocp->ioc_cmd) {
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 		case TCSETAF:
632*7c478bd9Sstevel@tonic-gate 		case TCSETSF:
633*7c478bd9Sstevel@tonic-gate 			/*
634*7c478bd9Sstevel@tonic-gate 			 * Flush the read queue.
635*7c478bd9Sstevel@tonic-gate 			 */
636*7c478bd9Sstevel@tonic-gate 			if (putnextctl1(q, M_FLUSH, FLUSHR) == 0) {
637*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EAGAIN);
638*7c478bd9Sstevel@tonic-gate 				break;
639*7c478bd9Sstevel@tonic-gate 			}
640*7c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 		case TCSETA:
643*7c478bd9Sstevel@tonic-gate 		case TCSETAW:
644*7c478bd9Sstevel@tonic-gate 		case TCSETS:
645*7c478bd9Sstevel@tonic-gate 		case TCSETSW:
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 			switch (iocp->ioc_cmd) {
648*7c478bd9Sstevel@tonic-gate 			case TCSETAF:
649*7c478bd9Sstevel@tonic-gate 			case TCSETA:
650*7c478bd9Sstevel@tonic-gate 			case TCSETAW:
651*7c478bd9Sstevel@tonic-gate 				error = miocpullup(mp, sizeof (struct termio));
652*7c478bd9Sstevel@tonic-gate 				if (error != 0) {
653*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, error);
654*7c478bd9Sstevel@tonic-gate 					goto out;
655*7c478bd9Sstevel@tonic-gate 				}
656*7c478bd9Sstevel@tonic-gate 				cflags = ((struct termio *)
657*7c478bd9Sstevel@tonic-gate 				    mp->b_cont->b_rptr)->c_cflag;
658*7c478bd9Sstevel@tonic-gate 				ntp->cflags =
659*7c478bd9Sstevel@tonic-gate 				    (ntp->cflags & 0xffff0000 | cflags);
660*7c478bd9Sstevel@tonic-gate 				break;
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate 			case TCSETSF:
663*7c478bd9Sstevel@tonic-gate 			case TCSETS:
664*7c478bd9Sstevel@tonic-gate 			case TCSETSW:
665*7c478bd9Sstevel@tonic-gate 				error = miocpullup(mp, sizeof (struct termios));
666*7c478bd9Sstevel@tonic-gate 				if (error != 0) {
667*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, error);
668*7c478bd9Sstevel@tonic-gate 					goto out;
669*7c478bd9Sstevel@tonic-gate 				}
670*7c478bd9Sstevel@tonic-gate 				cflags = ((struct termios *)
671*7c478bd9Sstevel@tonic-gate 				    mp->b_cont->b_rptr)->c_cflag;
672*7c478bd9Sstevel@tonic-gate 				ntp->cflags = cflags;
673*7c478bd9Sstevel@tonic-gate 				break;
674*7c478bd9Sstevel@tonic-gate 			}
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 			if ((cflags & CBAUD) == B0) {
677*7c478bd9Sstevel@tonic-gate 				/*
678*7c478bd9Sstevel@tonic-gate 				 * Hang-up: Send a zero length message.
679*7c478bd9Sstevel@tonic-gate 				 */
680*7c478bd9Sstevel@tonic-gate 				dack_ptr = ntp->dack_ptr;
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 				if (dack_ptr) {
683*7c478bd9Sstevel@tonic-gate 					ntp->dack_ptr = NULL;
684*7c478bd9Sstevel@tonic-gate 					/*
685*7c478bd9Sstevel@tonic-gate 					 * Send a zero length message
686*7c478bd9Sstevel@tonic-gate 					 * downstream.
687*7c478bd9Sstevel@tonic-gate 					 */
688*7c478bd9Sstevel@tonic-gate 					putnext(q, dack_ptr);
689*7c478bd9Sstevel@tonic-gate 				}
690*7c478bd9Sstevel@tonic-gate 			} else {
691*7c478bd9Sstevel@tonic-gate 				/*
692*7c478bd9Sstevel@tonic-gate 				 * Make a copy of this message and pass it on
693*7c478bd9Sstevel@tonic-gate 				 * to the PCKT module.
694*7c478bd9Sstevel@tonic-gate 				 */
695*7c478bd9Sstevel@tonic-gate 				if ((pckt_msgp = copymsg(mp)) == NULL) {
696*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, EAGAIN);
697*7c478bd9Sstevel@tonic-gate 					break;
698*7c478bd9Sstevel@tonic-gate 				}
699*7c478bd9Sstevel@tonic-gate 				putnext(q, pckt_msgp);
700*7c478bd9Sstevel@tonic-gate 			}
701*7c478bd9Sstevel@tonic-gate 			/*
702*7c478bd9Sstevel@tonic-gate 			 * Send ACK upstream.
703*7c478bd9Sstevel@tonic-gate 			 */
704*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, NULL, 0, 0);
705*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
706*7c478bd9Sstevel@tonic-gate out:
707*7c478bd9Sstevel@tonic-gate 			break;
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 		case TCGETA:
710*7c478bd9Sstevel@tonic-gate 			dp = allocb(sizeof (struct termio), BPRI_MED);
711*7c478bd9Sstevel@tonic-gate 			if (dp == NULL) {
712*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EAGAIN);
713*7c478bd9Sstevel@tonic-gate 				break;
714*7c478bd9Sstevel@tonic-gate 			}
715*7c478bd9Sstevel@tonic-gate 			termiop = (struct termio *)dp->b_rptr;
716*7c478bd9Sstevel@tonic-gate 			termiop->c_cflag = (ushort_t)ntp->cflags;
717*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, dp, sizeof (struct termio), 0);
718*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
719*7c478bd9Sstevel@tonic-gate 			break;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 		case TCGETS:
722*7c478bd9Sstevel@tonic-gate 			dp = allocb(sizeof (struct termios), BPRI_MED);
723*7c478bd9Sstevel@tonic-gate 			if (dp == NULL) {
724*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EAGAIN);
725*7c478bd9Sstevel@tonic-gate 				break;
726*7c478bd9Sstevel@tonic-gate 			}
727*7c478bd9Sstevel@tonic-gate 			termiosp = (struct termios *)dp->b_rptr;
728*7c478bd9Sstevel@tonic-gate 			termiosp->c_cflag = ntp->cflags;
729*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, dp, sizeof (struct termios), 0);
730*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
731*7c478bd9Sstevel@tonic-gate 			break;
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate 		case TCSBRK:
734*7c478bd9Sstevel@tonic-gate 			error = miocpullup(mp, sizeof (int));
735*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
736*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, error);
737*7c478bd9Sstevel@tonic-gate 				break;
738*7c478bd9Sstevel@tonic-gate 			}
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 			/*
741*7c478bd9Sstevel@tonic-gate 			 * Need a copy of this message to pass it on to
742*7c478bd9Sstevel@tonic-gate 			 * the PCKT module.
743*7c478bd9Sstevel@tonic-gate 			 */
744*7c478bd9Sstevel@tonic-gate 			if ((pckt_msgp = copymsg(mp)) == NULL) {
745*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EAGAIN);
746*7c478bd9Sstevel@tonic-gate 				break;
747*7c478bd9Sstevel@tonic-gate 			}
748*7c478bd9Sstevel@tonic-gate 			/*
749*7c478bd9Sstevel@tonic-gate 			 * Send a copy of the M_IOCTL to the PCKT module.
750*7c478bd9Sstevel@tonic-gate 			 */
751*7c478bd9Sstevel@tonic-gate 			putnext(q, pckt_msgp);
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 			/*
754*7c478bd9Sstevel@tonic-gate 			 * TCSBRK meaningful if data part of message is 0
755*7c478bd9Sstevel@tonic-gate 			 * cf. termio(7).
756*7c478bd9Sstevel@tonic-gate 			 */
757*7c478bd9Sstevel@tonic-gate 			if (!(*(int *)mp->b_cont->b_rptr))
758*7c478bd9Sstevel@tonic-gate 				(void) putnextctl(q, M_BREAK);
759*7c478bd9Sstevel@tonic-gate 			/*
760*7c478bd9Sstevel@tonic-gate 			 * ACK the ioctl.
761*7c478bd9Sstevel@tonic-gate 			 */
762*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, NULL, 0, 0);
763*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
764*7c478bd9Sstevel@tonic-gate 			break;
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 		case JWINSIZE:
767*7c478bd9Sstevel@tonic-gate 		case TIOCGWINSZ:
768*7c478bd9Sstevel@tonic-gate 		case TIOCSWINSZ:
769*7c478bd9Sstevel@tonic-gate 			ptioc(q, mp, WRSIDE);
770*7c478bd9Sstevel@tonic-gate 			break;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 		case TIOCSTI:
773*7c478bd9Sstevel@tonic-gate 			/*
774*7c478bd9Sstevel@tonic-gate 			 * Simulate typing of a character at the terminal.  In
775*7c478bd9Sstevel@tonic-gate 			 * all cases, we acknowledge the ioctl and pass a copy
776*7c478bd9Sstevel@tonic-gate 			 * of it along for the PCKT module to encapsulate.  If
777*7c478bd9Sstevel@tonic-gate 			 * not in remote mode, we also process the ioctl
778*7c478bd9Sstevel@tonic-gate 			 * itself, looping the character given as its argument
779*7c478bd9Sstevel@tonic-gate 			 * back around to the read side.
780*7c478bd9Sstevel@tonic-gate 			 */
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 			/*
783*7c478bd9Sstevel@tonic-gate 			 * Need a copy of this message to pass on to the PCKT
784*7c478bd9Sstevel@tonic-gate 			 * module.
785*7c478bd9Sstevel@tonic-gate 			 */
786*7c478bd9Sstevel@tonic-gate 			if ((pckt_msgp = copymsg(mp)) == NULL) {
787*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EAGAIN);
788*7c478bd9Sstevel@tonic-gate 				break;
789*7c478bd9Sstevel@tonic-gate 			}
790*7c478bd9Sstevel@tonic-gate 			if ((ntp->state & REMOTEMODE) == 0) {
791*7c478bd9Sstevel@tonic-gate 				mblk_t *bp;
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 				error = miocpullup(mp, sizeof (char));
794*7c478bd9Sstevel@tonic-gate 				if (error != 0) {
795*7c478bd9Sstevel@tonic-gate 					freemsg(pckt_msgp);
796*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, error);
797*7c478bd9Sstevel@tonic-gate 					break;
798*7c478bd9Sstevel@tonic-gate 				}
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 				/*
801*7c478bd9Sstevel@tonic-gate 				 * The permission checking has already been
802*7c478bd9Sstevel@tonic-gate 				 * done at the stream head, since it has to be
803*7c478bd9Sstevel@tonic-gate 				 * done in the context of the process doing
804*7c478bd9Sstevel@tonic-gate 				 * the call.
805*7c478bd9Sstevel@tonic-gate 				 */
806*7c478bd9Sstevel@tonic-gate 				if ((bp = allocb(1, BPRI_MED)) == NULL) {
807*7c478bd9Sstevel@tonic-gate 					freemsg(pckt_msgp);
808*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, EAGAIN);
809*7c478bd9Sstevel@tonic-gate 					break;
810*7c478bd9Sstevel@tonic-gate 				}
811*7c478bd9Sstevel@tonic-gate 				/*
812*7c478bd9Sstevel@tonic-gate 				 * XXX:	Is EAGAIN really the right response to
813*7c478bd9Sstevel@tonic-gate 				 *	flow control blockage?
814*7c478bd9Sstevel@tonic-gate 				 */
815*7c478bd9Sstevel@tonic-gate 				if (!bcanputnext(RD(q), mp->b_band)) {
816*7c478bd9Sstevel@tonic-gate 					freemsg(bp);
817*7c478bd9Sstevel@tonic-gate 					freemsg(pckt_msgp);
818*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, EAGAIN);
819*7c478bd9Sstevel@tonic-gate 					break;
820*7c478bd9Sstevel@tonic-gate 				}
821*7c478bd9Sstevel@tonic-gate 				*bp->b_wptr++ = *mp->b_cont->b_rptr;
822*7c478bd9Sstevel@tonic-gate 				qreply(q, bp);
823*7c478bd9Sstevel@tonic-gate 			}
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 			putnext(q, pckt_msgp);
826*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, NULL, 0, 0);
827*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
828*7c478bd9Sstevel@tonic-gate 			break;
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate 		case PTSSTTY:
831*7c478bd9Sstevel@tonic-gate 			if (ntp->state & IS_PTSTTY) {
832*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EEXIST);
833*7c478bd9Sstevel@tonic-gate 			} else {
834*7c478bd9Sstevel@tonic-gate 				ntp->state |= IS_PTSTTY;
835*7c478bd9Sstevel@tonic-gate 				mioc2ack(mp, NULL, 0, 0);
836*7c478bd9Sstevel@tonic-gate 				qreply(q, mp);
837*7c478bd9Sstevel@tonic-gate 			}
838*7c478bd9Sstevel@tonic-gate 			break;
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 		default:
841*7c478bd9Sstevel@tonic-gate 			/*
842*7c478bd9Sstevel@tonic-gate 			 * End of the line.  The slave driver doesn't see any
843*7c478bd9Sstevel@tonic-gate 			 * ioctls that we don't explicitly pass along to it.
844*7c478bd9Sstevel@tonic-gate 			 */
845*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EINVAL);
846*7c478bd9Sstevel@tonic-gate 			break;
847*7c478bd9Sstevel@tonic-gate 		}
848*7c478bd9Sstevel@tonic-gate 		break;
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	case M_DELAY: /* tty delays not supported */
851*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
852*7c478bd9Sstevel@tonic-gate 		break;
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	case M_DATA:
855*7c478bd9Sstevel@tonic-gate 		if ((mp->b_wptr - mp->b_rptr) < 0) {
856*7c478bd9Sstevel@tonic-gate 			/*
857*7c478bd9Sstevel@tonic-gate 			 * Free all bad length messages.
858*7c478bd9Sstevel@tonic-gate 			 */
859*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
860*7c478bd9Sstevel@tonic-gate 			break;
861*7c478bd9Sstevel@tonic-gate 		} else if ((mp->b_wptr - mp->b_rptr) == 0) {
862*7c478bd9Sstevel@tonic-gate 			if (!(ntp->state & IS_PTSTTY)) {
863*7c478bd9Sstevel@tonic-gate 				freemsg(mp);
864*7c478bd9Sstevel@tonic-gate 				break;
865*7c478bd9Sstevel@tonic-gate 			}
866*7c478bd9Sstevel@tonic-gate 		}
867*7c478bd9Sstevel@tonic-gate 		if (ntp->state & OFLOW_CTL)
868*7c478bd9Sstevel@tonic-gate 			return (0);
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	default:
871*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
872*7c478bd9Sstevel@tonic-gate 		break;
873*7c478bd9Sstevel@tonic-gate 
874*7c478bd9Sstevel@tonic-gate 	}
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	return (1);
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate /*
880*7c478bd9Sstevel@tonic-gate  * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
881*7c478bd9Sstevel@tonic-gate  */
882*7c478bd9Sstevel@tonic-gate static void
ptioc(queue_t * q,mblk_t * mp,int qside)883*7c478bd9Sstevel@tonic-gate ptioc(queue_t *q, mblk_t *mp, int qside)
884*7c478bd9Sstevel@tonic-gate {
885*7c478bd9Sstevel@tonic-gate 	struct ptem *tp;
886*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
887*7c478bd9Sstevel@tonic-gate 	struct winsize *wb;
888*7c478bd9Sstevel@tonic-gate 	struct jwinsize *jwb;
889*7c478bd9Sstevel@tonic-gate 	mblk_t *tmp;
890*7c478bd9Sstevel@tonic-gate 	mblk_t *pckt_msgp;	/* message sent to the PCKT module */
891*7c478bd9Sstevel@tonic-gate 	int error;
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
894*7c478bd9Sstevel@tonic-gate 	tp = (struct ptem *)q->q_ptr;
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 	switch (iocp->ioc_cmd) {
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 	case JWINSIZE:
899*7c478bd9Sstevel@tonic-gate 		/*
900*7c478bd9Sstevel@tonic-gate 		 * For compatibility:  If all zeros, NAK the message for dumb
901*7c478bd9Sstevel@tonic-gate 		 * terminals.
902*7c478bd9Sstevel@tonic-gate 		 */
903*7c478bd9Sstevel@tonic-gate 		if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
904*7c478bd9Sstevel@tonic-gate 		    (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
905*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EINVAL);
906*7c478bd9Sstevel@tonic-gate 			return;
907*7c478bd9Sstevel@tonic-gate 		}
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 		tmp = allocb(sizeof (struct jwinsize), BPRI_MED);
910*7c478bd9Sstevel@tonic-gate 		if (tmp == NULL) {
911*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EAGAIN);
912*7c478bd9Sstevel@tonic-gate 			return;
913*7c478bd9Sstevel@tonic-gate 		}
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 		if (iocp->ioc_count == TRANSPARENT)
916*7c478bd9Sstevel@tonic-gate 			mcopyout(mp, NULL, sizeof (struct jwinsize), NULL, tmp);
917*7c478bd9Sstevel@tonic-gate 		else
918*7c478bd9Sstevel@tonic-gate 			mioc2ack(mp, tmp, sizeof (struct jwinsize), 0);
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 		jwb = (struct jwinsize *)mp->b_cont->b_rptr;
921*7c478bd9Sstevel@tonic-gate 		jwb->bytesx = tp->wsz.ws_col;
922*7c478bd9Sstevel@tonic-gate 		jwb->bytesy = tp->wsz.ws_row;
923*7c478bd9Sstevel@tonic-gate 		jwb->bitsx = tp->wsz.ws_xpixel;
924*7c478bd9Sstevel@tonic-gate 		jwb->bitsy = tp->wsz.ws_ypixel;
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
927*7c478bd9Sstevel@tonic-gate 		return;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	case TIOCGWINSZ:
930*7c478bd9Sstevel@tonic-gate 		/*
931*7c478bd9Sstevel@tonic-gate 		 * If all zeros NAK the message for dumb terminals.
932*7c478bd9Sstevel@tonic-gate 		 */
933*7c478bd9Sstevel@tonic-gate 		if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
934*7c478bd9Sstevel@tonic-gate 		    (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
935*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EINVAL);
936*7c478bd9Sstevel@tonic-gate 			return;
937*7c478bd9Sstevel@tonic-gate 		}
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate 		tmp = allocb(sizeof (struct winsize), BPRI_MED);
940*7c478bd9Sstevel@tonic-gate 		if (tmp == NULL) {
941*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EAGAIN);
942*7c478bd9Sstevel@tonic-gate 			return;
943*7c478bd9Sstevel@tonic-gate 		}
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate 		mioc2ack(mp, tmp, sizeof (struct winsize), 0);
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 		wb = (struct winsize *)mp->b_cont->b_rptr;
948*7c478bd9Sstevel@tonic-gate 		wb->ws_row = tp->wsz.ws_row;
949*7c478bd9Sstevel@tonic-gate 		wb->ws_col = tp->wsz.ws_col;
950*7c478bd9Sstevel@tonic-gate 		wb->ws_xpixel = tp->wsz.ws_xpixel;
951*7c478bd9Sstevel@tonic-gate 		wb->ws_ypixel = tp->wsz.ws_ypixel;
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
954*7c478bd9Sstevel@tonic-gate 		return;
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate 	case TIOCSWINSZ:
957*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (struct winsize));
958*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
959*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
960*7c478bd9Sstevel@tonic-gate 			return;
961*7c478bd9Sstevel@tonic-gate 		}
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 		wb = (struct winsize *)mp->b_cont->b_rptr;
964*7c478bd9Sstevel@tonic-gate 		/*
965*7c478bd9Sstevel@tonic-gate 		 * Send a SIGWINCH signal if the row/col information has
966*7c478bd9Sstevel@tonic-gate 		 * changed.
967*7c478bd9Sstevel@tonic-gate 		 */
968*7c478bd9Sstevel@tonic-gate 		if ((tp->wsz.ws_row != wb->ws_row) ||
969*7c478bd9Sstevel@tonic-gate 		    (tp->wsz.ws_col != wb->ws_col) ||
970*7c478bd9Sstevel@tonic-gate 		    (tp->wsz.ws_xpixel != wb->ws_xpixel) ||
971*7c478bd9Sstevel@tonic-gate 		    (tp->wsz.ws_ypixel != wb->ws_xpixel)) {
972*7c478bd9Sstevel@tonic-gate 			/*
973*7c478bd9Sstevel@tonic-gate 			 * SIGWINCH is always sent upstream.
974*7c478bd9Sstevel@tonic-gate 			 */
975*7c478bd9Sstevel@tonic-gate 			if (qside == WRSIDE)
976*7c478bd9Sstevel@tonic-gate 				(void) putnextctl1(RD(q), M_SIG, SIGWINCH);
977*7c478bd9Sstevel@tonic-gate 			else if (qside == RDSIDE)
978*7c478bd9Sstevel@tonic-gate 				(void) putnextctl1(q, M_SIG, SIGWINCH);
979*7c478bd9Sstevel@tonic-gate 			/*
980*7c478bd9Sstevel@tonic-gate 			 * Message may have come in as an M_IOCDATA; pass it
981*7c478bd9Sstevel@tonic-gate 			 * to the master side as an M_IOCTL.
982*7c478bd9Sstevel@tonic-gate 			 */
983*7c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCTL;
984*7c478bd9Sstevel@tonic-gate 			if (qside == WRSIDE) {
985*7c478bd9Sstevel@tonic-gate 				/*
986*7c478bd9Sstevel@tonic-gate 				 * Need a copy of this message to pass on to
987*7c478bd9Sstevel@tonic-gate 				 * the PCKT module, only if the M_IOCTL
988*7c478bd9Sstevel@tonic-gate 				 * orginated from the slave side.
989*7c478bd9Sstevel@tonic-gate 				 */
990*7c478bd9Sstevel@tonic-gate 				if ((pckt_msgp = copymsg(mp)) == NULL) {
991*7c478bd9Sstevel@tonic-gate 					miocnak(q, mp, 0, EAGAIN);
992*7c478bd9Sstevel@tonic-gate 					return;
993*7c478bd9Sstevel@tonic-gate 				}
994*7c478bd9Sstevel@tonic-gate 				putnext(q, pckt_msgp);
995*7c478bd9Sstevel@tonic-gate 			}
996*7c478bd9Sstevel@tonic-gate 			tp->wsz.ws_row = wb->ws_row;
997*7c478bd9Sstevel@tonic-gate 			tp->wsz.ws_col = wb->ws_col;
998*7c478bd9Sstevel@tonic-gate 			tp->wsz.ws_xpixel = wb->ws_xpixel;
999*7c478bd9Sstevel@tonic-gate 			tp->wsz.ws_ypixel = wb->ws_ypixel;
1000*7c478bd9Sstevel@tonic-gate 		}
1001*7c478bd9Sstevel@tonic-gate 
1002*7c478bd9Sstevel@tonic-gate 		mioc2ack(mp, NULL, 0, 0);
1003*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
1004*7c478bd9Sstevel@tonic-gate 		return;
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 	case TIOCSIGNAL: {
1007*7c478bd9Sstevel@tonic-gate 		/*
1008*7c478bd9Sstevel@tonic-gate 		 * This ioctl can emanate from the master side in remote
1009*7c478bd9Sstevel@tonic-gate 		 * mode only.
1010*7c478bd9Sstevel@tonic-gate 		 */
1011*7c478bd9Sstevel@tonic-gate 		int	sig;
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 		if (DB_TYPE(mp) == M_IOCTL && iocp->ioc_count != TRANSPARENT) {
1014*7c478bd9Sstevel@tonic-gate 			error = miocpullup(mp, sizeof (int));
1015*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
1016*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, error);
1017*7c478bd9Sstevel@tonic-gate 				return;
1018*7c478bd9Sstevel@tonic-gate 			}
1019*7c478bd9Sstevel@tonic-gate 		}
1020*7c478bd9Sstevel@tonic-gate 
1021*7c478bd9Sstevel@tonic-gate 		if (DB_TYPE(mp) == M_IOCDATA || iocp->ioc_count != TRANSPARENT)
1022*7c478bd9Sstevel@tonic-gate 			sig = *(int *)mp->b_cont->b_rptr;
1023*7c478bd9Sstevel@tonic-gate 		else
1024*7c478bd9Sstevel@tonic-gate 			sig = (int)*(intptr_t *)mp->b_cont->b_rptr;
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 		if (sig < 1 || sig >= NSIG) {
1027*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EINVAL);
1028*7c478bd9Sstevel@tonic-gate 			return;
1029*7c478bd9Sstevel@tonic-gate 		}
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 		/*
1032*7c478bd9Sstevel@tonic-gate 		 * Send an M_PCSIG message up the slave's read side and
1033*7c478bd9Sstevel@tonic-gate 		 * respond back to the master with an ACK or NAK as
1034*7c478bd9Sstevel@tonic-gate 		 * appropriate.
1035*7c478bd9Sstevel@tonic-gate 		 */
1036*7c478bd9Sstevel@tonic-gate 		if (putnextctl1(q, M_PCSIG, sig) == 0) {
1037*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EAGAIN);
1038*7c478bd9Sstevel@tonic-gate 			return;
1039*7c478bd9Sstevel@tonic-gate 		}
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate 		mioc2ack(mp, NULL, 0, 0);
1042*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
1043*7c478bd9Sstevel@tonic-gate 		return;
1044*7c478bd9Sstevel@tonic-gate 	    }
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate 	case TIOCREMOTE: {
1047*7c478bd9Sstevel@tonic-gate 		int	onoff;
1048*7c478bd9Sstevel@tonic-gate 		mblk_t	*mctlp;
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 		if (DB_TYPE(mp) == M_IOCTL) {
1051*7c478bd9Sstevel@tonic-gate 			error = miocpullup(mp, sizeof (int));
1052*7c478bd9Sstevel@tonic-gate 			if (error != 0) {
1053*7c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, error);
1054*7c478bd9Sstevel@tonic-gate 				return;
1055*7c478bd9Sstevel@tonic-gate 			}
1056*7c478bd9Sstevel@tonic-gate 		}
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 		onoff = *(int *)mp->b_cont->b_rptr;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 		/*
1061*7c478bd9Sstevel@tonic-gate 		 * Send M_CTL up using the iocblk format.
1062*7c478bd9Sstevel@tonic-gate 		 */
1063*7c478bd9Sstevel@tonic-gate 		mctlp = mkiocb(onoff ? MC_NO_CANON : MC_DO_CANON);
1064*7c478bd9Sstevel@tonic-gate 		if (mctlp == NULL) {
1065*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EAGAIN);
1066*7c478bd9Sstevel@tonic-gate 			return;
1067*7c478bd9Sstevel@tonic-gate 		}
1068*7c478bd9Sstevel@tonic-gate 		mctlp->b_datap->db_type = M_CTL;
1069*7c478bd9Sstevel@tonic-gate 		putnext(q, mctlp);
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 		/*
1072*7c478bd9Sstevel@tonic-gate 		 * ACK the ioctl.
1073*7c478bd9Sstevel@tonic-gate 		 */
1074*7c478bd9Sstevel@tonic-gate 		mioc2ack(mp, NULL, 0, 0);
1075*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate 		/*
1078*7c478bd9Sstevel@tonic-gate 		 * Record state change.
1079*7c478bd9Sstevel@tonic-gate 		 */
1080*7c478bd9Sstevel@tonic-gate 		if (onoff)
1081*7c478bd9Sstevel@tonic-gate 			tp->state |= REMOTEMODE;
1082*7c478bd9Sstevel@tonic-gate 		else
1083*7c478bd9Sstevel@tonic-gate 			tp->state &= ~REMOTEMODE;
1084*7c478bd9Sstevel@tonic-gate 		return;
1085*7c478bd9Sstevel@tonic-gate 	    }
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	default:
1088*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
1089*7c478bd9Sstevel@tonic-gate 		return;
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate }
1092