xref: /titanic_50/usr/src/uts/common/io/ttcompat.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 /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
32*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
33*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
36*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
37*7c478bd9Sstevel@tonic-gate  * contributors.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * Module to intercept old V7 and 4BSD "ioctl" calls.
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/termios.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/ttcompat.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * This is the loadable module wrapper.
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
68*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /* See os/streamio.c */
71*7c478bd9Sstevel@tonic-gate extern int sgttyb_handling;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate static struct streamtab ttcoinfo;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
76*7c478bd9Sstevel@tonic-gate 	"ttcompat",
77*7c478bd9Sstevel@tonic-gate 	&ttcoinfo,
78*7c478bd9Sstevel@tonic-gate 	D_MTQPAIR | D_MP
79*7c478bd9Sstevel@tonic-gate };
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
86*7c478bd9Sstevel@tonic-gate 	&mod_strmodops,
87*7c478bd9Sstevel@tonic-gate 	"alt ioctl calls",
88*7c478bd9Sstevel@tonic-gate 	&fsw
89*7c478bd9Sstevel@tonic-gate };
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
92*7c478bd9Sstevel@tonic-gate 	MODREV_1, &modlstrmod, NULL
93*7c478bd9Sstevel@tonic-gate };
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate int
96*7c478bd9Sstevel@tonic-gate _init(void)
97*7c478bd9Sstevel@tonic-gate {
98*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
99*7c478bd9Sstevel@tonic-gate }
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate int
102*7c478bd9Sstevel@tonic-gate _fini(void)
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate int
108*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
109*7c478bd9Sstevel@tonic-gate {
110*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate static int ttcompatopen(queue_t *, dev_t *, int, int, cred_t *);
114*7c478bd9Sstevel@tonic-gate static int ttcompatclose(queue_t *, int, cred_t *);
115*7c478bd9Sstevel@tonic-gate static void ttcompatrput(queue_t *, mblk_t *);
116*7c478bd9Sstevel@tonic-gate static void ttcompatwput(queue_t *, mblk_t *);
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate static struct module_info ttycompatmiinfo = {
119*7c478bd9Sstevel@tonic-gate 	0,
120*7c478bd9Sstevel@tonic-gate 	"ttcompat",
121*7c478bd9Sstevel@tonic-gate 	0,
122*7c478bd9Sstevel@tonic-gate 	INFPSZ,
123*7c478bd9Sstevel@tonic-gate 	2048,
124*7c478bd9Sstevel@tonic-gate 	128
125*7c478bd9Sstevel@tonic-gate };
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate static struct qinit ttycompatrinit = {
128*7c478bd9Sstevel@tonic-gate 	(int (*)())ttcompatrput,
129*7c478bd9Sstevel@tonic-gate 	NULL,
130*7c478bd9Sstevel@tonic-gate 	ttcompatopen,
131*7c478bd9Sstevel@tonic-gate 	ttcompatclose,
132*7c478bd9Sstevel@tonic-gate 	NULL,
133*7c478bd9Sstevel@tonic-gate 	&ttycompatmiinfo
134*7c478bd9Sstevel@tonic-gate };
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate static struct module_info ttycompatmoinfo = {
137*7c478bd9Sstevel@tonic-gate 	42,
138*7c478bd9Sstevel@tonic-gate 	"ttcompat",
139*7c478bd9Sstevel@tonic-gate 	0,
140*7c478bd9Sstevel@tonic-gate 	INFPSZ,
141*7c478bd9Sstevel@tonic-gate 	300,
142*7c478bd9Sstevel@tonic-gate 	200
143*7c478bd9Sstevel@tonic-gate };
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate static struct qinit ttycompatwinit = {
146*7c478bd9Sstevel@tonic-gate 	(int (*)())ttcompatwput,
147*7c478bd9Sstevel@tonic-gate 	NULL,
148*7c478bd9Sstevel@tonic-gate 	ttcompatopen,
149*7c478bd9Sstevel@tonic-gate 	ttcompatclose,
150*7c478bd9Sstevel@tonic-gate 	NULL,
151*7c478bd9Sstevel@tonic-gate 	&ttycompatmoinfo
152*7c478bd9Sstevel@tonic-gate };
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate static struct streamtab ttcoinfo = {
155*7c478bd9Sstevel@tonic-gate 	&ttycompatrinit,
156*7c478bd9Sstevel@tonic-gate 	&ttycompatwinit,
157*7c478bd9Sstevel@tonic-gate 	NULL,
158*7c478bd9Sstevel@tonic-gate 	NULL
159*7c478bd9Sstevel@tonic-gate };
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate static void ttcompat_do_ioctl(ttcompat_state_t *, queue_t *, mblk_t *);
162*7c478bd9Sstevel@tonic-gate static void ttcompat_ioctl_ack(queue_t *, mblk_t *);
163*7c478bd9Sstevel@tonic-gate static void ttcopyout(queue_t *, mblk_t *);
164*7c478bd9Sstevel@tonic-gate static void ttcompat_ioctl_nak(queue_t *, mblk_t *);
165*7c478bd9Sstevel@tonic-gate static void from_compat(compat_state_t *, struct termios *);
166*7c478bd9Sstevel@tonic-gate static void to_compat(struct termios *, compat_state_t *);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate /*
169*7c478bd9Sstevel@tonic-gate  * Open - get the current modes and translate them to the V7/4BSD equivalent.
170*7c478bd9Sstevel@tonic-gate  */
171*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
172*7c478bd9Sstevel@tonic-gate static int
173*7c478bd9Sstevel@tonic-gate ttcompatopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
174*7c478bd9Sstevel@tonic-gate {
175*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	if (q->q_ptr != NULL)  {
178*7c478bd9Sstevel@tonic-gate 		tp = (ttcompat_state_t *)q->q_ptr;
179*7c478bd9Sstevel@tonic-gate 		/* fail open if TIOCEXCL was done and its not privileged */
180*7c478bd9Sstevel@tonic-gate 		if ((tp->t_new_lflags & XCLUDE) &&
181*7c478bd9Sstevel@tonic-gate 		    secpolicy_excl_open(crp) != 0) {
182*7c478bd9Sstevel@tonic-gate 			return (EBUSY);
183*7c478bd9Sstevel@tonic-gate 		}
184*7c478bd9Sstevel@tonic-gate 		return (0);		/* already attached */
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 	tp = kmem_zalloc(sizeof (ttcompat_state_t), KM_SLEEP);
187*7c478bd9Sstevel@tonic-gate 	tp->t_iocpending = NULL;
188*7c478bd9Sstevel@tonic-gate 	tp->t_state = 0;
189*7c478bd9Sstevel@tonic-gate 	tp->t_iocid = 0;
190*7c478bd9Sstevel@tonic-gate 	tp->t_ioccmd = 0;
191*7c478bd9Sstevel@tonic-gate 	tp->t_new_lflags = 0;
192*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_flags = 0;
193*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_ispeed = B0;
194*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_ospeed = B0;
195*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_erase = '\0';
196*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_kill = '\0';
197*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_intrc = '\0';
198*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_quitc = '\0';
199*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_startc = '\0';
200*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_stopc = '\0';
201*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_eofc = '\0';
202*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_brkc = '\0';
203*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_suspc = '\0';
204*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_dsuspc = '\0';
205*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_rprntc = '\0';
206*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_flushc = '\0';
207*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_werasc = '\0';
208*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_lnextc = '\0';
209*7c478bd9Sstevel@tonic-gate 	tp->t_curstate.t_xflags = 0;
210*7c478bd9Sstevel@tonic-gate 	tp->t_bufcallid = 0;
211*7c478bd9Sstevel@tonic-gate 	tp->t_arg = 0;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	q->q_ptr = tp;
214*7c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = tp;
215*7c478bd9Sstevel@tonic-gate 	qprocson(q);
216*7c478bd9Sstevel@tonic-gate 	return (0);
217*7c478bd9Sstevel@tonic-gate }
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
220*7c478bd9Sstevel@tonic-gate static int
221*7c478bd9Sstevel@tonic-gate ttcompatclose(queue_t *q, int flag, cred_t *crp)
222*7c478bd9Sstevel@tonic-gate {
223*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp = (ttcompat_state_t *)q->q_ptr;
224*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	/* Dump the state structure, then unlink it */
227*7c478bd9Sstevel@tonic-gate 	qprocsoff(q);
228*7c478bd9Sstevel@tonic-gate 	if (tp->t_bufcallid != 0) {
229*7c478bd9Sstevel@tonic-gate 		qunbufcall(q, tp->t_bufcallid);
230*7c478bd9Sstevel@tonic-gate 		tp->t_bufcallid = 0;
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	if ((mp = tp->t_iocpending) != NULL)
233*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
234*7c478bd9Sstevel@tonic-gate 	kmem_free(tp, sizeof (ttcompat_state_t));
235*7c478bd9Sstevel@tonic-gate 	q->q_ptr = NULL;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	return (0);
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate /*
241*7c478bd9Sstevel@tonic-gate  * Put procedure for input from driver end of stream (read queue).
242*7c478bd9Sstevel@tonic-gate  * Most messages just get passed to the next guy up; we intercept
243*7c478bd9Sstevel@tonic-gate  * "ioctl" replies, and if it's an "ioctl" whose reply we plan to do
244*7c478bd9Sstevel@tonic-gate  * something with, we do it.
245*7c478bd9Sstevel@tonic-gate  */
246*7c478bd9Sstevel@tonic-gate static void
247*7c478bd9Sstevel@tonic-gate ttcompatrput(queue_t *q, mblk_t *mp)
248*7c478bd9Sstevel@tonic-gate {
249*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	case M_IOCACK:
252*7c478bd9Sstevel@tonic-gate 		ttcompat_ioctl_ack(q, mp);
253*7c478bd9Sstevel@tonic-gate 		break;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	case M_IOCNAK:
256*7c478bd9Sstevel@tonic-gate 		ttcompat_ioctl_nak(q, mp);
257*7c478bd9Sstevel@tonic-gate 		break;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	default:
260*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
261*7c478bd9Sstevel@tonic-gate 		break;
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate }
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate /*
266*7c478bd9Sstevel@tonic-gate  * Line discipline output queue put procedure: speeds M_IOCTL
267*7c478bd9Sstevel@tonic-gate  * messages.
268*7c478bd9Sstevel@tonic-gate  */
269*7c478bd9Sstevel@tonic-gate static void
270*7c478bd9Sstevel@tonic-gate ttcompatwput(queue_t *q, mblk_t *mp)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
273*7c478bd9Sstevel@tonic-gate 	struct copyreq *cqp;
274*7c478bd9Sstevel@tonic-gate 	struct copyresp *csp;
275*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocbp;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	tp = (ttcompat_state_t *)q->q_ptr;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	/*
280*7c478bd9Sstevel@tonic-gate 	 * Process some M_IOCTL messages here; pass everything else down.
281*7c478bd9Sstevel@tonic-gate 	 */
282*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	default:
285*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
286*7c478bd9Sstevel@tonic-gate 		return;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	case M_IOCTL:
289*7c478bd9Sstevel@tonic-gate 		iocbp = (struct iocblk *)mp->b_rptr;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 		switch (iocbp->ioc_cmd) {
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		default:
294*7c478bd9Sstevel@tonic-gate 	/* these are ioctls with no arguments or are known to stream head */
295*7c478bd9Sstevel@tonic-gate 	/* process them right away */
296*7c478bd9Sstevel@tonic-gate 			ttcompat_do_ioctl(tp, q, mp);
297*7c478bd9Sstevel@tonic-gate 			return;
298*7c478bd9Sstevel@tonic-gate 		case TIOCSETN:
299*7c478bd9Sstevel@tonic-gate 		case TIOCSLTC:
300*7c478bd9Sstevel@tonic-gate 		case TIOCSETC:
301*7c478bd9Sstevel@tonic-gate 		case TIOCLBIS:
302*7c478bd9Sstevel@tonic-gate 		case TIOCLBIC:
303*7c478bd9Sstevel@tonic-gate 		case TIOCLSET:
304*7c478bd9Sstevel@tonic-gate 		case TIOCFLUSH:
305*7c478bd9Sstevel@tonic-gate 			if (iocbp->ioc_count != TRANSPARENT) {
306*7c478bd9Sstevel@tonic-gate 				putnext(q, mp);
307*7c478bd9Sstevel@tonic-gate 				return;
308*7c478bd9Sstevel@tonic-gate 			}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_COPYIN;
311*7c478bd9Sstevel@tonic-gate 			cqp = (struct copyreq *)mp->b_rptr;
312*7c478bd9Sstevel@tonic-gate 			cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr;
313*7c478bd9Sstevel@tonic-gate 			switch (iocbp->ioc_cmd) {
314*7c478bd9Sstevel@tonic-gate 				case TIOCSETN:
315*7c478bd9Sstevel@tonic-gate 					cqp->cq_size = sizeof (struct sgttyb);
316*7c478bd9Sstevel@tonic-gate 					break;
317*7c478bd9Sstevel@tonic-gate 				case TIOCSLTC:
318*7c478bd9Sstevel@tonic-gate 					cqp->cq_size = sizeof (struct ltchars);
319*7c478bd9Sstevel@tonic-gate 					break;
320*7c478bd9Sstevel@tonic-gate 				case TIOCSETC:
321*7c478bd9Sstevel@tonic-gate 					cqp->cq_size = sizeof (struct tchars);
322*7c478bd9Sstevel@tonic-gate 					break;
323*7c478bd9Sstevel@tonic-gate 				case TIOCLBIS:
324*7c478bd9Sstevel@tonic-gate 				case TIOCLBIC:
325*7c478bd9Sstevel@tonic-gate 				case TIOCLSET:
326*7c478bd9Sstevel@tonic-gate 				case TIOCFLUSH:
327*7c478bd9Sstevel@tonic-gate 					cqp->cq_size = sizeof (int);
328*7c478bd9Sstevel@tonic-gate 					break;
329*7c478bd9Sstevel@tonic-gate 				default:
330*7c478bd9Sstevel@tonic-gate 					break;
331*7c478bd9Sstevel@tonic-gate 			}
332*7c478bd9Sstevel@tonic-gate 			cqp->cq_flag = 0;
333*7c478bd9Sstevel@tonic-gate 			cqp->cq_private = NULL;
334*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
335*7c478bd9Sstevel@tonic-gate 			mp->b_cont = NULL;
336*7c478bd9Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
337*7c478bd9Sstevel@tonic-gate 			tp->t_ioccmd = iocbp->ioc_cmd;
338*7c478bd9Sstevel@tonic-gate 			tp->t_state |= TS_W_IN;
339*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
340*7c478bd9Sstevel@tonic-gate 			return;
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 		} /* switch ioc_cmd */
343*7c478bd9Sstevel@tonic-gate 	case M_IOCDATA:
344*7c478bd9Sstevel@tonic-gate 		csp = (struct copyresp *)mp->b_rptr;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 		switch (csp->cp_cmd) {
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 		default:
349*7c478bd9Sstevel@tonic-gate 			putnext(q, mp);
350*7c478bd9Sstevel@tonic-gate 			return;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 		case TIOCSETN:
353*7c478bd9Sstevel@tonic-gate 		case TIOCSLTC:
354*7c478bd9Sstevel@tonic-gate 		case TIOCSETC:
355*7c478bd9Sstevel@tonic-gate 		case TIOCLBIS:
356*7c478bd9Sstevel@tonic-gate 		case TIOCLBIC:
357*7c478bd9Sstevel@tonic-gate 		case TIOCLSET:
358*7c478bd9Sstevel@tonic-gate 		case TIOCFLUSH:
359*7c478bd9Sstevel@tonic-gate 			tp->t_state &= ~TS_W_IN;
360*7c478bd9Sstevel@tonic-gate 			if (csp->cp_rval != 0) {	/* failure */
361*7c478bd9Sstevel@tonic-gate 				freemsg(mp);
362*7c478bd9Sstevel@tonic-gate 				return;
363*7c478bd9Sstevel@tonic-gate 			}
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 			/* make it look like an ioctl */
366*7c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCTL;
367*7c478bd9Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
368*7c478bd9Sstevel@tonic-gate 			iocbp = (struct iocblk *)mp->b_rptr;
369*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_count = MBLKL(mp->b_cont);
370*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_error = 0;
371*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_rval = 0;
372*7c478bd9Sstevel@tonic-gate 			ttcompat_do_ioctl(tp, q, mp);
373*7c478bd9Sstevel@tonic-gate 			return;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 		case TIOCGLTC:
376*7c478bd9Sstevel@tonic-gate 		case TIOCLGET:
377*7c478bd9Sstevel@tonic-gate 		case TIOCGETC:
378*7c478bd9Sstevel@tonic-gate 			tp->t_state &= ~TS_W_OUT;
379*7c478bd9Sstevel@tonic-gate 			if (csp->cp_rval != 0) {	/* failure */
380*7c478bd9Sstevel@tonic-gate 				freemsg(mp);
381*7c478bd9Sstevel@tonic-gate 				return;
382*7c478bd9Sstevel@tonic-gate 			}
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 			iocbp = (struct iocblk *)mp->b_rptr;
385*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_count = 0;
386*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_error = 0;
387*7c478bd9Sstevel@tonic-gate 			iocbp->ioc_rval = 0;
388*7c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCACK;
389*7c478bd9Sstevel@tonic-gate 			qreply(q, mp);
390*7c478bd9Sstevel@tonic-gate 			return;
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 		} /* switch cp_cmd */
393*7c478bd9Sstevel@tonic-gate 	} /* end message switch */
394*7c478bd9Sstevel@tonic-gate }
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate /*
397*7c478bd9Sstevel@tonic-gate  * Retry an "ioctl", now that "bufcall" claims we may be able to allocate
398*7c478bd9Sstevel@tonic-gate  * the buffer we need.
399*7c478bd9Sstevel@tonic-gate  */
400*7c478bd9Sstevel@tonic-gate static void
401*7c478bd9Sstevel@tonic-gate ttcompat_reioctl(void *arg)
402*7c478bd9Sstevel@tonic-gate {
403*7c478bd9Sstevel@tonic-gate 	queue_t *q = arg;
404*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
405*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	tp = (ttcompat_state_t *)q->q_ptr;
408*7c478bd9Sstevel@tonic-gate 	tp->t_bufcallid = 0;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	if ((mp = tp->t_iocpending) != NULL) {
411*7c478bd9Sstevel@tonic-gate 		tp->t_iocpending = NULL;	/* not pending any more */
412*7c478bd9Sstevel@tonic-gate 		ttcompat_do_ioctl(tp, q, mp);
413*7c478bd9Sstevel@tonic-gate 	}
414*7c478bd9Sstevel@tonic-gate }
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate /*
417*7c478bd9Sstevel@tonic-gate  * Handle old-style "ioctl" messages; pass the rest down unmolested.
418*7c478bd9Sstevel@tonic-gate  */
419*7c478bd9Sstevel@tonic-gate static void
420*7c478bd9Sstevel@tonic-gate ttcompat_do_ioctl(ttcompat_state_t *tp, queue_t *q, mblk_t *mp)
421*7c478bd9Sstevel@tonic-gate {
422*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
423*7c478bd9Sstevel@tonic-gate 	int error;
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 	/*
426*7c478bd9Sstevel@tonic-gate 	 * Most of the miocpullup()'s below aren't needed because the
427*7c478bd9Sstevel@tonic-gate 	 * ioctls in question are actually transparent M_IOCDATA messages
428*7c478bd9Sstevel@tonic-gate 	 * dummied to look like M_IOCTL messages.  However, for clarity and
429*7c478bd9Sstevel@tonic-gate 	 * robustness against future changes, we've included them anyway.
430*7c478bd9Sstevel@tonic-gate 	 */
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
433*7c478bd9Sstevel@tonic-gate 	switch (iocp->ioc_cmd) {
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	/*
436*7c478bd9Sstevel@tonic-gate 	 * "get"-style calls that get translated data from the "termios"
437*7c478bd9Sstevel@tonic-gate 	 * structure.  Save the existing code and pass it down as a TCGETS.
438*7c478bd9Sstevel@tonic-gate 	 */
439*7c478bd9Sstevel@tonic-gate 	case TIOCGETC:
440*7c478bd9Sstevel@tonic-gate 	case TIOCLGET:
441*7c478bd9Sstevel@tonic-gate 	case TIOCGLTC:
442*7c478bd9Sstevel@tonic-gate 		if (iocp->ioc_count != TRANSPARENT) {
443*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, EINVAL);
444*7c478bd9Sstevel@tonic-gate 			return;
445*7c478bd9Sstevel@tonic-gate 		}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 		/*
448*7c478bd9Sstevel@tonic-gate 		 * We can get here with t_arg != 0, iff the stream head
449*7c478bd9Sstevel@tonic-gate 		 * has for some reason given up on the ioctl in progress.
450*7c478bd9Sstevel@tonic-gate 		 * The most likely cause is an interrupted ioctl syscall.
451*7c478bd9Sstevel@tonic-gate 		 * We will behave robustly because (given our perimeter)
452*7c478bd9Sstevel@tonic-gate 		 * the ttcompat_state_t will get set up for the new ioctl,
453*7c478bd9Sstevel@tonic-gate 		 * and when the response we were waiting for appears it
454*7c478bd9Sstevel@tonic-gate 		 * will be passed on to the stream head which will discard
455*7c478bd9Sstevel@tonic-gate 		 * it as non-current.
456*7c478bd9Sstevel@tonic-gate 		 */
457*7c478bd9Sstevel@tonic-gate 		ASSERT(mp->b_cont != NULL);
458*7c478bd9Sstevel@tonic-gate 		tp->t_arg = *(intptr_t *)mp->b_cont->b_rptr;
459*7c478bd9Sstevel@tonic-gate 		/* free the data buffer - it might not be sufficient */
460*7c478bd9Sstevel@tonic-gate 		/* driver will allocate one for termios size */
461*7c478bd9Sstevel@tonic-gate 		freemsg(mp->b_cont);
462*7c478bd9Sstevel@tonic-gate 		mp->b_cont = NULL;
463*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;
464*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
465*7c478bd9Sstevel@tonic-gate 	case TIOCGETP:
466*7c478bd9Sstevel@tonic-gate 		goto dogets;
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	/*
469*7c478bd9Sstevel@tonic-gate 	 * "set"-style calls that set translated data into a "termios"
470*7c478bd9Sstevel@tonic-gate 	 * structure.  Set our idea of the new state from the value
471*7c478bd9Sstevel@tonic-gate 	 * given to us.  We then have to get the current state, so we
472*7c478bd9Sstevel@tonic-gate 	 * turn this guy into a TCGETS and pass it down.  When the
473*7c478bd9Sstevel@tonic-gate 	 * ACK comes back, we modify the state we got back and shove it
474*7c478bd9Sstevel@tonic-gate 	 * back down as the appropriate type of TCSETS.
475*7c478bd9Sstevel@tonic-gate 	 */
476*7c478bd9Sstevel@tonic-gate 	case TIOCSETP:
477*7c478bd9Sstevel@tonic-gate 	case TIOCSETN:
478*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (struct sgttyb));
479*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
480*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
481*7c478bd9Sstevel@tonic-gate 			return;
482*7c478bd9Sstevel@tonic-gate 		}
483*7c478bd9Sstevel@tonic-gate 		tp->t_new_sgttyb = *((struct sgttyb *)mp->b_cont->b_rptr);
484*7c478bd9Sstevel@tonic-gate 		goto dogets;
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 	case TIOCSETC:
487*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (struct tchars));
488*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
489*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
490*7c478bd9Sstevel@tonic-gate 			return;
491*7c478bd9Sstevel@tonic-gate 		}
492*7c478bd9Sstevel@tonic-gate 		tp->t_new_tchars = *((struct tchars *)mp->b_cont->b_rptr);
493*7c478bd9Sstevel@tonic-gate 		goto dogets;
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	case TIOCSLTC:
496*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (struct ltchars));
497*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
498*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
499*7c478bd9Sstevel@tonic-gate 			return;
500*7c478bd9Sstevel@tonic-gate 		}
501*7c478bd9Sstevel@tonic-gate 		tp->t_new_ltchars = *((struct ltchars *)mp->b_cont->b_rptr);
502*7c478bd9Sstevel@tonic-gate 		goto dogets;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	case TIOCLBIS:
505*7c478bd9Sstevel@tonic-gate 	case TIOCLBIC:
506*7c478bd9Sstevel@tonic-gate 	case TIOCLSET:
507*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (int));
508*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
509*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
510*7c478bd9Sstevel@tonic-gate 			return;
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 		tp->t_new_lflags = *(int *)mp->b_cont->b_rptr;
513*7c478bd9Sstevel@tonic-gate 		goto dogets;
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 	/*
516*7c478bd9Sstevel@tonic-gate 	 * "set"-style call that sets a particular bit in a "termios"
517*7c478bd9Sstevel@tonic-gate 	 * structure.  We then have to get the current state, so we
518*7c478bd9Sstevel@tonic-gate 	 * turn this guy into a TCGETS and pass it down.  When the
519*7c478bd9Sstevel@tonic-gate 	 * ACK comes back, we modify the state we got back and shove it
520*7c478bd9Sstevel@tonic-gate 	 * back down as the appropriate type of TCSETS.
521*7c478bd9Sstevel@tonic-gate 	 */
522*7c478bd9Sstevel@tonic-gate 	case TIOCHPCL:
523*7c478bd9Sstevel@tonic-gate 	dogets:
524*7c478bd9Sstevel@tonic-gate 		tp->t_ioccmd = iocp->ioc_cmd;
525*7c478bd9Sstevel@tonic-gate 		tp->t_iocid = iocp->ioc_id;
526*7c478bd9Sstevel@tonic-gate 		tp->t_state |= TS_IOCWAIT;
527*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCGETS;
528*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;	/* no data returned unless we say so */
529*7c478bd9Sstevel@tonic-gate 		break;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	/*
532*7c478bd9Sstevel@tonic-gate 	 * "set"-style call that sets DTR.  Pretend that it was a TIOCMBIS
533*7c478bd9Sstevel@tonic-gate 	 * with TIOCM_DTR set.
534*7c478bd9Sstevel@tonic-gate 	 */
535*7c478bd9Sstevel@tonic-gate 	case TIOCSDTR: {
536*7c478bd9Sstevel@tonic-gate 		mblk_t *datap;
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)
539*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
540*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = TIOCM_DTR;
541*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
542*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TIOCMBIS;	/* turn it into a TIOCMBIS */
543*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
544*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
545*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;	/* attach the data */
546*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);	/* in case driver checks */
547*7c478bd9Sstevel@tonic-gate 		break;
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	/*
551*7c478bd9Sstevel@tonic-gate 	 * "set"-style call that clears DTR.  Pretend that it was a TIOCMBIC
552*7c478bd9Sstevel@tonic-gate 	 * with TIOCM_DTR set.
553*7c478bd9Sstevel@tonic-gate 	 */
554*7c478bd9Sstevel@tonic-gate 	case TIOCCDTR: {
555*7c478bd9Sstevel@tonic-gate 		mblk_t *datap;
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)
558*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
559*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = TIOCM_DTR;
560*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
561*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TIOCMBIC;	/* turn it into a TIOCMBIC */
562*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
563*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
564*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;	/* attach the data */
565*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);	/* in case driver checks */
566*7c478bd9Sstevel@tonic-gate 		break;
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	/*
570*7c478bd9Sstevel@tonic-gate 	 * Translate into the S5 form of TCFLSH.
571*7c478bd9Sstevel@tonic-gate 	 */
572*7c478bd9Sstevel@tonic-gate 	case TIOCFLUSH: {
573*7c478bd9Sstevel@tonic-gate 		int flags;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (int));
576*7c478bd9Sstevel@tonic-gate 		if (error != 0) {
577*7c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
578*7c478bd9Sstevel@tonic-gate 			return;
579*7c478bd9Sstevel@tonic-gate 		}
580*7c478bd9Sstevel@tonic-gate 		flags = *(int *)mp->b_cont->b_rptr;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		switch (flags&(FREAD|FWRITE)) {
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 		case 0:
585*7c478bd9Sstevel@tonic-gate 		case FREAD|FWRITE:
586*7c478bd9Sstevel@tonic-gate 			flags = 2;	/* flush 'em both */
587*7c478bd9Sstevel@tonic-gate 			break;
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 		case FREAD:
590*7c478bd9Sstevel@tonic-gate 			flags = 0;	/* flush read */
591*7c478bd9Sstevel@tonic-gate 			break;
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 		case FWRITE:
594*7c478bd9Sstevel@tonic-gate 			flags = 1;	/* flush write */
595*7c478bd9Sstevel@tonic-gate 			break;
596*7c478bd9Sstevel@tonic-gate 		}
597*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCFLSH;	/* turn it into a TCFLSH */
598*7c478bd9Sstevel@tonic-gate 		*(int *)mp->b_cont->b_rptr = flags;	/* fiddle the arg */
599*7c478bd9Sstevel@tonic-gate 		break;
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	/*
603*7c478bd9Sstevel@tonic-gate 	 * Turn into a TCXONC.
604*7c478bd9Sstevel@tonic-gate 	 */
605*7c478bd9Sstevel@tonic-gate 	case TIOCSTOP: {
606*7c478bd9Sstevel@tonic-gate 		mblk_t *datap;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)
609*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
610*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = 0;	/* stop */
611*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
612*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCXONC;	/* turn it into a XONC */
613*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
614*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
615*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
616*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;	/* attach the data */
617*7c478bd9Sstevel@tonic-gate 		break;
618*7c478bd9Sstevel@tonic-gate 	}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	case TIOCSTART: {
621*7c478bd9Sstevel@tonic-gate 		mblk_t *datap;
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL)
624*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
625*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = 1;	/* start */
626*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
627*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCXONC;	/* turn it into a XONC */
628*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
629*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
630*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
631*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;	/* attach the data */
632*7c478bd9Sstevel@tonic-gate 		break;
633*7c478bd9Sstevel@tonic-gate 	}
634*7c478bd9Sstevel@tonic-gate 	case TIOCSETD:
635*7c478bd9Sstevel@tonic-gate 	case TIOCGETD:
636*7c478bd9Sstevel@tonic-gate 	case DIOCSETP:
637*7c478bd9Sstevel@tonic-gate 	case DIOCGETP:
638*7c478bd9Sstevel@tonic-gate 	case LDOPEN:
639*7c478bd9Sstevel@tonic-gate 	case LDCLOSE:
640*7c478bd9Sstevel@tonic-gate 	case LDCHG:
641*7c478bd9Sstevel@tonic-gate 	case LDSETT:
642*7c478bd9Sstevel@tonic-gate 	case LDGETT:
643*7c478bd9Sstevel@tonic-gate 		/*
644*7c478bd9Sstevel@tonic-gate 		 * All of these ioctls are just ACK'd, except for
645*7c478bd9Sstevel@tonic-gate 		 * TIOCSETD, which must be for line discipline zero.
646*7c478bd9Sstevel@tonic-gate 		 */
647*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
648*7c478bd9Sstevel@tonic-gate 		if (iocp->ioc_cmd == TIOCSETD) {
649*7c478bd9Sstevel@tonic-gate 			iocp->ioc_error = miocpullup(mp, sizeof (uchar_t));
650*7c478bd9Sstevel@tonic-gate 			if (iocp->ioc_error == 0 && (*mp->b_cont->b_rptr != 0))
651*7c478bd9Sstevel@tonic-gate 				mp->b_datap->db_type = M_IOCNAK;
652*7c478bd9Sstevel@tonic-gate 		}
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = 0;
655*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;
656*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
657*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
658*7c478bd9Sstevel@tonic-gate 		return;
659*7c478bd9Sstevel@tonic-gate 	case IOCTYPE:
660*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
661*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = 0;
662*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;
663*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = TIOC;
664*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
665*7c478bd9Sstevel@tonic-gate 		return;
666*7c478bd9Sstevel@tonic-gate 	case TIOCEXCL:
667*7c478bd9Sstevel@tonic-gate 		/* check for binary value of XCLUDE flag ???? */
668*7c478bd9Sstevel@tonic-gate 		tp->t_new_lflags |= XCLUDE;
669*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
670*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = 0;
671*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;
672*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
673*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
674*7c478bd9Sstevel@tonic-gate 		return;
675*7c478bd9Sstevel@tonic-gate 	case TIOCNXCL:
676*7c478bd9Sstevel@tonic-gate 		tp->t_new_lflags &= ~XCLUDE;
677*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
678*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = 0;
679*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;
680*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
681*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
682*7c478bd9Sstevel@tonic-gate 		return;
683*7c478bd9Sstevel@tonic-gate 	}
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 	/*
686*7c478bd9Sstevel@tonic-gate 	 * We don't reply to most calls, we just pass them down,
687*7c478bd9Sstevel@tonic-gate 	 * possibly after modifying the arguments.
688*7c478bd9Sstevel@tonic-gate 	 */
689*7c478bd9Sstevel@tonic-gate 	putnext(q, mp);
690*7c478bd9Sstevel@tonic-gate 	return;
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate allocfailure:
693*7c478bd9Sstevel@tonic-gate 	/*
694*7c478bd9Sstevel@tonic-gate 	 * We needed to allocate something to handle this "ioctl", but
695*7c478bd9Sstevel@tonic-gate 	 * couldn't; save this "ioctl" and arrange to get called back when
696*7c478bd9Sstevel@tonic-gate 	 * it's more likely that we can get what we need.
697*7c478bd9Sstevel@tonic-gate 	 * If there's already one being saved, throw it out, since it
698*7c478bd9Sstevel@tonic-gate 	 * must have timed out.
699*7c478bd9Sstevel@tonic-gate 	 */
700*7c478bd9Sstevel@tonic-gate 	if (tp->t_iocpending != NULL)
701*7c478bd9Sstevel@tonic-gate 		freemsg(tp->t_iocpending);
702*7c478bd9Sstevel@tonic-gate 	tp->t_iocpending = mp;	/* hold this ioctl */
703*7c478bd9Sstevel@tonic-gate 	if (tp->t_bufcallid != 0)
704*7c478bd9Sstevel@tonic-gate 		qunbufcall(q, tp->t_bufcallid);
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	tp->t_bufcallid = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
707*7c478bd9Sstevel@tonic-gate 	    ttcompat_reioctl, q);
708*7c478bd9Sstevel@tonic-gate }
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate /*
711*7c478bd9Sstevel@tonic-gate  * Called when an M_IOCACK message is seen on the read queue; if this
712*7c478bd9Sstevel@tonic-gate  * is the response we were waiting for, we either:
713*7c478bd9Sstevel@tonic-gate  *    modify the data going up (if the "ioctl" read data); since in all
714*7c478bd9Sstevel@tonic-gate  *    cases, the old-style returned information is smaller than or the same
715*7c478bd9Sstevel@tonic-gate  *    size as the new-style returned information, we just overwrite the old
716*7c478bd9Sstevel@tonic-gate  *    stuff with the new stuff (beware of changing structure sizes, in case
717*7c478bd9Sstevel@tonic-gate  *    you invalidate this)
718*7c478bd9Sstevel@tonic-gate  * or
719*7c478bd9Sstevel@tonic-gate  *    take this data, modify it appropriately, and send it back down (if
720*7c478bd9Sstevel@tonic-gate  *    the "ioctl" wrote data).
721*7c478bd9Sstevel@tonic-gate  * In either case, we cancel the "wait"; the final response to a "write"
722*7c478bd9Sstevel@tonic-gate  * ioctl goes back up to the user.
723*7c478bd9Sstevel@tonic-gate  * If this wasn't the response we were waiting for, just pass it up.
724*7c478bd9Sstevel@tonic-gate  */
725*7c478bd9Sstevel@tonic-gate static void
726*7c478bd9Sstevel@tonic-gate ttcompat_ioctl_ack(queue_t *q, 	mblk_t *mp)
727*7c478bd9Sstevel@tonic-gate {
728*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
729*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
730*7c478bd9Sstevel@tonic-gate 	mblk_t *datap;
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 	tp = (ttcompat_state_t *)q->q_ptr;
733*7c478bd9Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 	if (!(tp->t_state&TS_IOCWAIT) || iocp->ioc_id != tp->t_iocid) {
736*7c478bd9Sstevel@tonic-gate 		/*
737*7c478bd9Sstevel@tonic-gate 		 * This isn't the reply we're looking for.  Move along.
738*7c478bd9Sstevel@tonic-gate 		 */
739*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
740*7c478bd9Sstevel@tonic-gate 		return;
741*7c478bd9Sstevel@tonic-gate 	}
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	datap = mp->b_cont;	/* mblk containing data going up */
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate 	switch (tp->t_ioccmd) {
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 	case TIOCGETP: {
748*7c478bd9Sstevel@tonic-gate 		struct sgttyb *cb;
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
751*7c478bd9Sstevel@tonic-gate 		datap->b_rptr = datap->b_wptr = datap->b_datap->db_base;
752*7c478bd9Sstevel@tonic-gate 			/* recycle the reply's buffer */
753*7c478bd9Sstevel@tonic-gate 		cb = (struct sgttyb *)datap->b_wptr;
754*7c478bd9Sstevel@tonic-gate 		/*
755*7c478bd9Sstevel@tonic-gate 		 * This is used for TIOCGETP handling of sg_ispeed and
756*7c478bd9Sstevel@tonic-gate 		 * sg_ospeed.  If the current speed is over 38400 (the
757*7c478bd9Sstevel@tonic-gate 		 * sgttyb limit), then we report 38400.  Note that
758*7c478bd9Sstevel@tonic-gate 		 * when "compatibility with old releases" is enabled
759*7c478bd9Sstevel@tonic-gate 		 * (sgttyb_handling == 0), then t_[io]speed will have
760*7c478bd9Sstevel@tonic-gate 		 * garbled nonsense, as in prior releases.  (See
761*7c478bd9Sstevel@tonic-gate 		 * to_compat() below).
762*7c478bd9Sstevel@tonic-gate 		 */
763*7c478bd9Sstevel@tonic-gate 		cb->sg_ispeed = tp->t_curstate.t_ispeed > B38400 ? B38400 :
764*7c478bd9Sstevel@tonic-gate 		    tp->t_curstate.t_ispeed;
765*7c478bd9Sstevel@tonic-gate 		cb->sg_ospeed = tp->t_curstate.t_ospeed > B38400 ? B38400 :
766*7c478bd9Sstevel@tonic-gate 		    tp->t_curstate.t_ospeed;
767*7c478bd9Sstevel@tonic-gate 		cb->sg_erase = tp->t_curstate.t_erase;
768*7c478bd9Sstevel@tonic-gate 		cb->sg_kill = tp->t_curstate.t_kill;
769*7c478bd9Sstevel@tonic-gate 		cb->sg_flags = tp->t_curstate.t_flags;
770*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (struct sgttyb);
771*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (struct sgttyb);
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 		/* you are lucky - stream head knows how to copy you out */
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 		tp->t_state &= ~TS_IOCWAIT;	/* we got what we wanted */
776*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
777*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd =  tp->t_ioccmd;
778*7c478bd9Sstevel@tonic-gate 		putnext(q, mp);
779*7c478bd9Sstevel@tonic-gate 		return;
780*7c478bd9Sstevel@tonic-gate 	}
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 	case TIOCGETC:
783*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
784*7c478bd9Sstevel@tonic-gate 		datap->b_rptr = datap->b_wptr = datap->b_datap->db_base;
785*7c478bd9Sstevel@tonic-gate 			/* recycle the reply's buffer */
786*7c478bd9Sstevel@tonic-gate 		bcopy(&tp->t_curstate.t_intrc, datap->b_wptr,
787*7c478bd9Sstevel@tonic-gate 		    sizeof (struct tchars));
788*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (struct tchars);
789*7c478bd9Sstevel@tonic-gate 		break;
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 	case TIOCGLTC:
792*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
793*7c478bd9Sstevel@tonic-gate 		datap->b_rptr = datap->b_wptr = datap->b_datap->db_base;
794*7c478bd9Sstevel@tonic-gate 			/* recycle the reply's buffer */
795*7c478bd9Sstevel@tonic-gate 		bcopy(&tp->t_curstate.t_suspc, datap->b_wptr,
796*7c478bd9Sstevel@tonic-gate 		    sizeof (struct ltchars));
797*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (struct ltchars);
798*7c478bd9Sstevel@tonic-gate 		break;
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	case TIOCLGET:
801*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
802*7c478bd9Sstevel@tonic-gate 		datap->b_rptr = datap->b_wptr = datap->b_datap->db_base;
803*7c478bd9Sstevel@tonic-gate 			/* recycle the reply's buffer */
804*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr =
805*7c478bd9Sstevel@tonic-gate 		    ((unsigned)tp->t_curstate.t_flags) >> 16;
806*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
807*7c478bd9Sstevel@tonic-gate 		break;
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 	case TIOCSETP:
810*7c478bd9Sstevel@tonic-gate 	case TIOCSETN:
811*7c478bd9Sstevel@tonic-gate 		/*
812*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
813*7c478bd9Sstevel@tonic-gate 		 * update it.
814*7c478bd9Sstevel@tonic-gate 		 */
815*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
816*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_erase = tp->t_new_sgttyb.sg_erase;
817*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_kill = tp->t_new_sgttyb.sg_kill;
818*7c478bd9Sstevel@tonic-gate 		/*
819*7c478bd9Sstevel@tonic-gate 		 * For new-style handling, we ignore requests to set
820*7c478bd9Sstevel@tonic-gate 		 * B38400 when the current speed is over B38400.  This
821*7c478bd9Sstevel@tonic-gate 		 * means that we change the speed as requested if:
822*7c478bd9Sstevel@tonic-gate 		 *	old style (sgttyb_handling == 0) is requested
823*7c478bd9Sstevel@tonic-gate 		 *	the requested new speed isn't B38400
824*7c478bd9Sstevel@tonic-gate 		 *	the current speed is at or below B38400
825*7c478bd9Sstevel@tonic-gate 		 * Note that when old style is requested, both speeds
826*7c478bd9Sstevel@tonic-gate 		 * in t_curstate are set to <= B38400 by to_compat, so
827*7c478bd9Sstevel@tonic-gate 		 * the first test isn't needed here.
828*7c478bd9Sstevel@tonic-gate 		 * Also note that we silently allow the user to set
829*7c478bd9Sstevel@tonic-gate 		 * speeds above B38400 through this interface,
830*7c478bd9Sstevel@tonic-gate 		 * regardless of the style setting.  This allows
831*7c478bd9Sstevel@tonic-gate 		 * greater compatibility with current BSD releases.
832*7c478bd9Sstevel@tonic-gate 		 */
833*7c478bd9Sstevel@tonic-gate 		if (tp->t_new_sgttyb.sg_ispeed != B38400 ||
834*7c478bd9Sstevel@tonic-gate 		    tp->t_curstate.t_ispeed <= B38400)
835*7c478bd9Sstevel@tonic-gate 			tp->t_curstate.t_ispeed = tp->t_new_sgttyb.sg_ispeed;
836*7c478bd9Sstevel@tonic-gate 		if (tp->t_new_sgttyb.sg_ospeed != B38400 ||
837*7c478bd9Sstevel@tonic-gate 		    tp->t_curstate.t_ospeed <= B38400)
838*7c478bd9Sstevel@tonic-gate 			tp->t_curstate.t_ospeed = tp->t_new_sgttyb.sg_ospeed;
839*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_flags =
840*7c478bd9Sstevel@tonic-gate 		    (tp->t_curstate.t_flags & 0xffff0000) |
841*7c478bd9Sstevel@tonic-gate 		    (tp->t_new_sgttyb.sg_flags & 0xffff);
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 		/*
844*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
845*7c478bd9Sstevel@tonic-gate 		 */
846*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 		/*
849*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS or TCSETSF.
850*7c478bd9Sstevel@tonic-gate 		 */
851*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = (tp->t_ioccmd == TIOCSETP) ? TCSETSF : TCSETS;
852*7c478bd9Sstevel@tonic-gate 		goto senddown;
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	case TIOCSETC:
855*7c478bd9Sstevel@tonic-gate 		/*
856*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
857*7c478bd9Sstevel@tonic-gate 		 * update it.
858*7c478bd9Sstevel@tonic-gate 		 */
859*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
860*7c478bd9Sstevel@tonic-gate 		bcopy(&tp->t_new_tchars,
861*7c478bd9Sstevel@tonic-gate 		    &tp->t_curstate.t_intrc, sizeof (struct tchars));
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 		/*
864*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
865*7c478bd9Sstevel@tonic-gate 		 */
866*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 		/*
869*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
870*7c478bd9Sstevel@tonic-gate 		 */
871*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
872*7c478bd9Sstevel@tonic-gate 		goto senddown;
873*7c478bd9Sstevel@tonic-gate 
874*7c478bd9Sstevel@tonic-gate 	case TIOCSLTC:
875*7c478bd9Sstevel@tonic-gate 		/*
876*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
877*7c478bd9Sstevel@tonic-gate 		 * update it.
878*7c478bd9Sstevel@tonic-gate 		 */
879*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
880*7c478bd9Sstevel@tonic-gate 		bcopy(&tp->t_new_ltchars,
881*7c478bd9Sstevel@tonic-gate 		    &tp->t_curstate.t_suspc, sizeof (struct ltchars));
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 		/*
884*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
885*7c478bd9Sstevel@tonic-gate 		 */
886*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
887*7c478bd9Sstevel@tonic-gate 
888*7c478bd9Sstevel@tonic-gate 		/*
889*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
890*7c478bd9Sstevel@tonic-gate 		 */
891*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
892*7c478bd9Sstevel@tonic-gate 		goto senddown;
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	case TIOCLBIS:
895*7c478bd9Sstevel@tonic-gate 		/*
896*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
897*7c478bd9Sstevel@tonic-gate 		 * update it.
898*7c478bd9Sstevel@tonic-gate 		 */
899*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
900*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_flags |= (tp->t_new_lflags << 16);
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 		/*
903*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
904*7c478bd9Sstevel@tonic-gate 		 */
905*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate 		/*
908*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
909*7c478bd9Sstevel@tonic-gate 		 */
910*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
911*7c478bd9Sstevel@tonic-gate 		goto senddown;
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	case TIOCLBIC:
914*7c478bd9Sstevel@tonic-gate 		/*
915*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
916*7c478bd9Sstevel@tonic-gate 		 * update it.
917*7c478bd9Sstevel@tonic-gate 		 */
918*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
919*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_flags &= ~(tp->t_new_lflags << 16);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 		/*
922*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
923*7c478bd9Sstevel@tonic-gate 		 */
924*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 		/*
927*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
928*7c478bd9Sstevel@tonic-gate 		 */
929*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
930*7c478bd9Sstevel@tonic-gate 		goto senddown;
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	case TIOCLSET:
933*7c478bd9Sstevel@tonic-gate 		/*
934*7c478bd9Sstevel@tonic-gate 		 * Get the current state from the GETS data, and
935*7c478bd9Sstevel@tonic-gate 		 * update it.
936*7c478bd9Sstevel@tonic-gate 		 */
937*7c478bd9Sstevel@tonic-gate 		to_compat((struct termios *)datap->b_rptr, &tp->t_curstate);
938*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_flags &= 0xffff;
939*7c478bd9Sstevel@tonic-gate 		tp->t_curstate.t_flags |= (tp->t_new_lflags << 16);
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 		/*
942*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
943*7c478bd9Sstevel@tonic-gate 		 */
944*7c478bd9Sstevel@tonic-gate 		from_compat(&tp->t_curstate, (struct termios *)datap->b_rptr);
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 		/*
947*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
948*7c478bd9Sstevel@tonic-gate 		 */
949*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
950*7c478bd9Sstevel@tonic-gate 		goto senddown;
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate 	case TIOCHPCL:
953*7c478bd9Sstevel@tonic-gate 		/*
954*7c478bd9Sstevel@tonic-gate 		 * Replace the data that came up with the updated data.
955*7c478bd9Sstevel@tonic-gate 		 */
956*7c478bd9Sstevel@tonic-gate 		((struct termios *)datap->b_rptr)->c_cflag |= HUPCL;
957*7c478bd9Sstevel@tonic-gate 
958*7c478bd9Sstevel@tonic-gate 		/*
959*7c478bd9Sstevel@tonic-gate 		 * Send it back down as a TCSETS.
960*7c478bd9Sstevel@tonic-gate 		 */
961*7c478bd9Sstevel@tonic-gate 		iocp->ioc_cmd = TCSETS;
962*7c478bd9Sstevel@tonic-gate 		goto senddown;
963*7c478bd9Sstevel@tonic-gate 
964*7c478bd9Sstevel@tonic-gate 	default:
965*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ttcompat: Unexpected ioctl acknowledgment\n");
966*7c478bd9Sstevel@tonic-gate 	}
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	/*
969*7c478bd9Sstevel@tonic-gate 	 * All the calls that return something return 0.
970*7c478bd9Sstevel@tonic-gate 	 */
971*7c478bd9Sstevel@tonic-gate 	tp->t_state &= ~TS_IOCWAIT;	/* we got what we wanted */
972*7c478bd9Sstevel@tonic-gate 	iocp->ioc_rval = 0;
973*7c478bd9Sstevel@tonic-gate 
974*7c478bd9Sstevel@tonic-gate 	/* copy out the data - ioctl transparency */
975*7c478bd9Sstevel@tonic-gate 	iocp->ioc_cmd =  tp->t_ioccmd;
976*7c478bd9Sstevel@tonic-gate 	ttcopyout(q, mp);
977*7c478bd9Sstevel@tonic-gate 	return;
978*7c478bd9Sstevel@tonic-gate 
979*7c478bd9Sstevel@tonic-gate senddown:
980*7c478bd9Sstevel@tonic-gate 	/*
981*7c478bd9Sstevel@tonic-gate 	 * Send a "get state" reply back down, with suitably-modified
982*7c478bd9Sstevel@tonic-gate 	 * state, as a "set state" "ioctl".
983*7c478bd9Sstevel@tonic-gate 	 */
984*7c478bd9Sstevel@tonic-gate 	tp->t_state &= ~TS_IOCWAIT;
985*7c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_IOCTL;
986*7c478bd9Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
987*7c478bd9Sstevel@tonic-gate 	putnext(WR(q), mp);
988*7c478bd9Sstevel@tonic-gate }
989*7c478bd9Sstevel@tonic-gate /* Called from ttcompatrput M_IOCACK processing. */
990*7c478bd9Sstevel@tonic-gate /* Copies out the data using M_COPYOUT messages */
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate static void
993*7c478bd9Sstevel@tonic-gate ttcopyout(queue_t *q, mblk_t *mp)
994*7c478bd9Sstevel@tonic-gate {
995*7c478bd9Sstevel@tonic-gate 	struct copyreq *cqp;
996*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 	tp = (ttcompat_state_t *)q->q_ptr;
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_COPYOUT;
1001*7c478bd9Sstevel@tonic-gate 	cqp = (struct copyreq *)mp->b_rptr;
1002*7c478bd9Sstevel@tonic-gate 	cqp->cq_addr = (caddr_t)tp->t_arg; /* retrieve the 3rd argument */
1003*7c478bd9Sstevel@tonic-gate 	tp->t_arg = 0; /* clear it since we don't need it anymore */
1004*7c478bd9Sstevel@tonic-gate 	switch (tp->t_ioccmd) {
1005*7c478bd9Sstevel@tonic-gate 		case TIOCGLTC:
1006*7c478bd9Sstevel@tonic-gate 			cqp->cq_size = sizeof (struct ltchars);
1007*7c478bd9Sstevel@tonic-gate 			break;
1008*7c478bd9Sstevel@tonic-gate 		case TIOCGETC:
1009*7c478bd9Sstevel@tonic-gate 			cqp->cq_size = sizeof (struct tchars);
1010*7c478bd9Sstevel@tonic-gate 			break;
1011*7c478bd9Sstevel@tonic-gate 		case TIOCLGET:
1012*7c478bd9Sstevel@tonic-gate 			cqp->cq_size = sizeof (int);
1013*7c478bd9Sstevel@tonic-gate 			break;
1014*7c478bd9Sstevel@tonic-gate 		default:
1015*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN,
1016*7c478bd9Sstevel@tonic-gate 			    "ttcompat: Unknown ioctl to copyout\n");
1017*7c478bd9Sstevel@tonic-gate 			break;
1018*7c478bd9Sstevel@tonic-gate 		}
1019*7c478bd9Sstevel@tonic-gate 	cqp->cq_flag = 0;
1020*7c478bd9Sstevel@tonic-gate 	cqp->cq_private = NULL;
1021*7c478bd9Sstevel@tonic-gate 	tp->t_state |= TS_W_OUT;
1022*7c478bd9Sstevel@tonic-gate 	putnext(q, mp);
1023*7c478bd9Sstevel@tonic-gate }
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate /*
1027*7c478bd9Sstevel@tonic-gate  * Called when an M_IOCNAK message is seen on the read queue; if this is
1028*7c478bd9Sstevel@tonic-gate  * the response we were waiting for, cancel the wait.  Pass the reply up;
1029*7c478bd9Sstevel@tonic-gate  * if we were waiting for this response, we can't complete the "ioctl" and
1030*7c478bd9Sstevel@tonic-gate  * the NAK will tell that to the guy above us.
1031*7c478bd9Sstevel@tonic-gate  * If this wasn't the response we were waiting for, just pass it up.
1032*7c478bd9Sstevel@tonic-gate  */
1033*7c478bd9Sstevel@tonic-gate static void
1034*7c478bd9Sstevel@tonic-gate ttcompat_ioctl_nak(queue_t *q, mblk_t *mp)
1035*7c478bd9Sstevel@tonic-gate {
1036*7c478bd9Sstevel@tonic-gate 	ttcompat_state_t *tp;
1037*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
1040*7c478bd9Sstevel@tonic-gate 	tp = (ttcompat_state_t *)q->q_ptr;
1041*7c478bd9Sstevel@tonic-gate 
1042*7c478bd9Sstevel@tonic-gate 	if (tp->t_state&TS_IOCWAIT && iocp->ioc_id == tp->t_iocid) {
1043*7c478bd9Sstevel@tonic-gate 		tp->t_state &= ~TS_IOCWAIT; /* this call isn't going through */
1044*7c478bd9Sstevel@tonic-gate 		tp->t_arg = 0;	/* we may have stashed the 3rd argument */
1045*7c478bd9Sstevel@tonic-gate 	}
1046*7c478bd9Sstevel@tonic-gate 	putnext(q, mp);
1047*7c478bd9Sstevel@tonic-gate }
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate #define	FROM_COMPAT_CHAR(to, from) { if ((to = from) == 0377) to = 0; }
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate static void
1052*7c478bd9Sstevel@tonic-gate from_compat(compat_state_t *csp, struct termios *termiosp)
1053*7c478bd9Sstevel@tonic-gate {
1054*7c478bd9Sstevel@tonic-gate 	termiosp->c_iflag = 0;
1055*7c478bd9Sstevel@tonic-gate 	termiosp->c_oflag &= (ONLRET|ONOCR);
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	termiosp->c_cflag = (termiosp->c_cflag &
1058*7c478bd9Sstevel@tonic-gate 	    (CRTSCTS|CRTSXOFF|PAREXT|LOBLK|HUPCL)) | CREAD;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	if (csp->t_ospeed > CBAUD) {
1061*7c478bd9Sstevel@tonic-gate 		termiosp->c_cflag |= ((csp->t_ospeed - CBAUD - 1) & CBAUD) |
1062*7c478bd9Sstevel@tonic-gate 		    CBAUDEXT;
1063*7c478bd9Sstevel@tonic-gate 	} else {
1064*7c478bd9Sstevel@tonic-gate 		termiosp->c_cflag |= csp->t_ospeed & CBAUD;
1065*7c478bd9Sstevel@tonic-gate 	}
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	if (csp->t_ospeed != csp->t_ispeed) {
1068*7c478bd9Sstevel@tonic-gate 		if (csp->t_ispeed > (CIBAUD >> IBSHIFT)) {
1069*7c478bd9Sstevel@tonic-gate 			termiosp->c_cflag |= CIBAUDEXT |
1070*7c478bd9Sstevel@tonic-gate 			    (((csp->t_ispeed - (CIBAUD >> IBSHIFT) - 1) <<
1071*7c478bd9Sstevel@tonic-gate 				IBSHIFT) & CIBAUD);
1072*7c478bd9Sstevel@tonic-gate 		} else {
1073*7c478bd9Sstevel@tonic-gate 			termiosp->c_cflag |= (csp->t_ispeed << IBSHIFT) &
1074*7c478bd9Sstevel@tonic-gate 			    CIBAUD;
1075*7c478bd9Sstevel@tonic-gate 		}
1076*7c478bd9Sstevel@tonic-gate 		/* hang up if ispeed=0 */
1077*7c478bd9Sstevel@tonic-gate 		if (csp->t_ispeed == 0)
1078*7c478bd9Sstevel@tonic-gate 			termiosp->c_cflag &= ~CBAUD & ~CBAUDEXT;
1079*7c478bd9Sstevel@tonic-gate 	}
1080*7c478bd9Sstevel@tonic-gate 	if (csp->t_ispeed == B110 || csp->t_xflags & STOPB)
1081*7c478bd9Sstevel@tonic-gate 		termiosp->c_cflag |= CSTOPB;
1082*7c478bd9Sstevel@tonic-gate 	termiosp->c_lflag = ECHOK;
1083*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VERASE], csp->t_erase);
1084*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VKILL], csp->t_kill);
1085*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VINTR], csp->t_intrc);
1086*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VQUIT], csp->t_quitc);
1087*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VSTART], csp->t_startc);
1088*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VSTOP], csp->t_stopc);
1089*7c478bd9Sstevel@tonic-gate 	termiosp->c_cc[VEOL2] = 0;
1090*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VSUSP], csp->t_suspc);
1091*7c478bd9Sstevel@tonic-gate 	/* is this useful? */
1092*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VDSUSP], csp->t_dsuspc);
1093*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VREPRINT], csp->t_rprntc);
1094*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VDISCARD], csp->t_flushc);
1095*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VWERASE], csp->t_werasc);
1096*7c478bd9Sstevel@tonic-gate 	FROM_COMPAT_CHAR(termiosp->c_cc[VLNEXT], csp->t_lnextc);
1097*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_TANDEM)
1098*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag |= IXOFF;
1099*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_LCASE) {
1100*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag |= IUCLC;
1101*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= OLCUC;
1102*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= XCASE;
1103*7c478bd9Sstevel@tonic-gate 	}
1104*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_ECHO)
1105*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= ECHO;
1106*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_CRMOD) {
1107*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag |= ICRNL;
1108*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= ONLCR;
1109*7c478bd9Sstevel@tonic-gate 		switch (csp->t_flags & O_CRDELAY) {
1110*7c478bd9Sstevel@tonic-gate 
1111*7c478bd9Sstevel@tonic-gate 		case O_CR1:
1112*7c478bd9Sstevel@tonic-gate 			termiosp->c_oflag |= CR2;
1113*7c478bd9Sstevel@tonic-gate 			break;
1114*7c478bd9Sstevel@tonic-gate 
1115*7c478bd9Sstevel@tonic-gate 		case O_CR2:
1116*7c478bd9Sstevel@tonic-gate 			termiosp->c_oflag |= CR3;
1117*7c478bd9Sstevel@tonic-gate 			break;
1118*7c478bd9Sstevel@tonic-gate 		}
1119*7c478bd9Sstevel@tonic-gate 	} else {
1120*7c478bd9Sstevel@tonic-gate 		if ((csp->t_flags & O_NLDELAY) == O_NL1)
1121*7c478bd9Sstevel@tonic-gate 			termiosp->c_oflag |= ONLRET|CR1;	/* tty37 */
1122*7c478bd9Sstevel@tonic-gate 	}
1123*7c478bd9Sstevel@tonic-gate 	if ((csp->t_flags & O_NLDELAY) == O_NL2)
1124*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= NL1;
1125*7c478bd9Sstevel@tonic-gate 	/*
1126*7c478bd9Sstevel@tonic-gate 	 * When going into RAW mode, the special characters controlled by the
1127*7c478bd9Sstevel@tonic-gate 	 * POSIX IEXTEN bit no longer apply; when leaving, they do.
1128*7c478bd9Sstevel@tonic-gate 	 */
1129*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_RAW) {
1130*7c478bd9Sstevel@tonic-gate 		termiosp->c_cflag |= CS8;
1131*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag &= ~(ICRNL|IUCLC);
1132*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag &= ~(XCASE|IEXTEN);
1133*7c478bd9Sstevel@tonic-gate 	} else {
1134*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag |= IMAXBEL|BRKINT|IGNPAR;
1135*7c478bd9Sstevel@tonic-gate 		if (termiosp->c_cc[VSTOP] != 0 && termiosp->c_cc[VSTART] != 0)
1136*7c478bd9Sstevel@tonic-gate 			termiosp->c_iflag |= IXON;
1137*7c478bd9Sstevel@tonic-gate 		if (csp->t_flags & O_LITOUT)
1138*7c478bd9Sstevel@tonic-gate 			termiosp->c_cflag |= CS8;
1139*7c478bd9Sstevel@tonic-gate 		else {
1140*7c478bd9Sstevel@tonic-gate 			if (csp->t_flags & O_PASS8)
1141*7c478bd9Sstevel@tonic-gate 				termiosp->c_cflag |= CS8;
1142*7c478bd9Sstevel@tonic-gate 				/* XXX - what about 8 bits plus parity? */
1143*7c478bd9Sstevel@tonic-gate 			else {
1144*7c478bd9Sstevel@tonic-gate 				switch (csp->t_flags & (O_EVENP|O_ODDP)) {
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate 				case 0:
1147*7c478bd9Sstevel@tonic-gate 					termiosp->c_iflag |= ISTRIP;
1148*7c478bd9Sstevel@tonic-gate 					termiosp->c_cflag |= CS8;
1149*7c478bd9Sstevel@tonic-gate 					break;
1150*7c478bd9Sstevel@tonic-gate 
1151*7c478bd9Sstevel@tonic-gate 				case O_EVENP:
1152*7c478bd9Sstevel@tonic-gate 					termiosp->c_iflag |= INPCK|ISTRIP;
1153*7c478bd9Sstevel@tonic-gate 					termiosp->c_cflag |= CS7|PARENB;
1154*7c478bd9Sstevel@tonic-gate 					break;
1155*7c478bd9Sstevel@tonic-gate 
1156*7c478bd9Sstevel@tonic-gate 				case O_ODDP:
1157*7c478bd9Sstevel@tonic-gate 					termiosp->c_iflag |= INPCK|ISTRIP;
1158*7c478bd9Sstevel@tonic-gate 					termiosp->c_cflag |= CS7|PARENB|PARODD;
1159*7c478bd9Sstevel@tonic-gate 					break;
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 				case O_EVENP|O_ODDP:
1162*7c478bd9Sstevel@tonic-gate 					termiosp->c_iflag |= ISTRIP;
1163*7c478bd9Sstevel@tonic-gate 					termiosp->c_cflag |= CS7|PARENB;
1164*7c478bd9Sstevel@tonic-gate 					break;
1165*7c478bd9Sstevel@tonic-gate 				}
1166*7c478bd9Sstevel@tonic-gate 			}
1167*7c478bd9Sstevel@tonic-gate 			if (!(csp->t_xflags & NOPOST))
1168*7c478bd9Sstevel@tonic-gate 				termiosp->c_oflag |= OPOST;
1169*7c478bd9Sstevel@tonic-gate 		}
1170*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= IEXTEN;
1171*7c478bd9Sstevel@tonic-gate 		if (!(csp->t_xflags & NOISIG))
1172*7c478bd9Sstevel@tonic-gate 			termiosp->c_lflag |= ISIG;
1173*7c478bd9Sstevel@tonic-gate 		if (!(csp->t_flags & O_CBREAK))
1174*7c478bd9Sstevel@tonic-gate 			termiosp->c_lflag |= ICANON;
1175*7c478bd9Sstevel@tonic-gate 		if (csp->t_flags & O_CTLECH)
1176*7c478bd9Sstevel@tonic-gate 			termiosp->c_lflag |= ECHOCTL;
1177*7c478bd9Sstevel@tonic-gate 	}
1178*7c478bd9Sstevel@tonic-gate 	switch (csp->t_flags & O_TBDELAY) {
1179*7c478bd9Sstevel@tonic-gate 
1180*7c478bd9Sstevel@tonic-gate 	case O_TAB1:
1181*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= TAB1;
1182*7c478bd9Sstevel@tonic-gate 		break;
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate 	case O_TAB2:
1185*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= TAB2;
1186*7c478bd9Sstevel@tonic-gate 		break;
1187*7c478bd9Sstevel@tonic-gate 
1188*7c478bd9Sstevel@tonic-gate 	case O_XTABS:
1189*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= TAB3;
1190*7c478bd9Sstevel@tonic-gate 		break;
1191*7c478bd9Sstevel@tonic-gate 	}
1192*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_VTDELAY)
1193*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= FFDLY;
1194*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_BSDELAY)
1195*7c478bd9Sstevel@tonic-gate 		termiosp->c_oflag |= BSDLY;
1196*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_PRTERA)
1197*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= ECHOPRT;
1198*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_CRTERA)
1199*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= ECHOE;
1200*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_TOSTOP)
1201*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= TOSTOP;
1202*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_FLUSHO)
1203*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= FLUSHO;
1204*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_NOHANG)
1205*7c478bd9Sstevel@tonic-gate 		termiosp->c_cflag |= CLOCAL;
1206*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_CRTKIL)
1207*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= ECHOKE;
1208*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_PENDIN)
1209*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= PENDIN;
1210*7c478bd9Sstevel@tonic-gate 	if (!(csp->t_flags & O_DECCTQ))
1211*7c478bd9Sstevel@tonic-gate 		termiosp->c_iflag |= IXANY;
1212*7c478bd9Sstevel@tonic-gate 	if (csp->t_flags & O_NOFLSH)
1213*7c478bd9Sstevel@tonic-gate 		termiosp->c_lflag |= NOFLSH;
1214*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & ICANON) {
1215*7c478bd9Sstevel@tonic-gate 		FROM_COMPAT_CHAR(termiosp->c_cc[VEOF], csp->t_eofc);
1216*7c478bd9Sstevel@tonic-gate 		FROM_COMPAT_CHAR(termiosp->c_cc[VEOL], csp->t_brkc);
1217*7c478bd9Sstevel@tonic-gate 	} else {
1218*7c478bd9Sstevel@tonic-gate 		termiosp->c_cc[VMIN] = 1;
1219*7c478bd9Sstevel@tonic-gate 		termiosp->c_cc[VTIME] = 0;
1220*7c478bd9Sstevel@tonic-gate 	}
1221*7c478bd9Sstevel@tonic-gate }
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate #define	TO_COMPAT_CHAR(to, from) { if ((to = from) == 0) to = (uchar_t)0377; }
1224*7c478bd9Sstevel@tonic-gate 
1225*7c478bd9Sstevel@tonic-gate static void
1226*7c478bd9Sstevel@tonic-gate to_compat(struct termios *termiosp, compat_state_t *csp)
1227*7c478bd9Sstevel@tonic-gate {
1228*7c478bd9Sstevel@tonic-gate 	csp->t_xflags &= (NOISIG|NOPOST);
1229*7c478bd9Sstevel@tonic-gate 	csp->t_ospeed = termiosp->c_cflag & CBAUD;
1230*7c478bd9Sstevel@tonic-gate 	csp->t_ispeed = (termiosp->c_cflag & CIBAUD) >> IBSHIFT;
1231*7c478bd9Sstevel@tonic-gate 	if (sgttyb_handling > 0) {
1232*7c478bd9Sstevel@tonic-gate 		if (termiosp->c_cflag & CBAUDEXT)
1233*7c478bd9Sstevel@tonic-gate 			csp->t_ospeed += CBAUD + 1;
1234*7c478bd9Sstevel@tonic-gate 		if (termiosp->c_cflag & CIBAUDEXT)
1235*7c478bd9Sstevel@tonic-gate 			csp->t_ispeed += (CIBAUD >> IBSHIFT) + 1;
1236*7c478bd9Sstevel@tonic-gate 	}
1237*7c478bd9Sstevel@tonic-gate 	if (csp->t_ispeed == 0)
1238*7c478bd9Sstevel@tonic-gate 		csp->t_ispeed = csp->t_ospeed;
1239*7c478bd9Sstevel@tonic-gate 	if ((termiosp->c_cflag & CSTOPB) && csp->t_ispeed != B110)
1240*7c478bd9Sstevel@tonic-gate 		csp->t_xflags |= STOPB;
1241*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_erase, termiosp->c_cc[VERASE]);
1242*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_kill, termiosp->c_cc[VKILL]);
1243*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_intrc, termiosp->c_cc[VINTR]);
1244*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_quitc, termiosp->c_cc[VQUIT]);
1245*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_startc, termiosp->c_cc[VSTART]);
1246*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_stopc, termiosp->c_cc[VSTOP]);
1247*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_suspc, termiosp->c_cc[VSUSP]);
1248*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_dsuspc, termiosp->c_cc[VDSUSP]);
1249*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_rprntc, termiosp->c_cc[VREPRINT]);
1250*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_flushc, termiosp->c_cc[VDISCARD]);
1251*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_werasc, termiosp->c_cc[VWERASE]);
1252*7c478bd9Sstevel@tonic-gate 	TO_COMPAT_CHAR(csp->t_lnextc, termiosp->c_cc[VLNEXT]);
1253*7c478bd9Sstevel@tonic-gate 	csp->t_flags &= (O_CTLECH|O_LITOUT|O_PASS8|O_ODDP|O_EVENP);
1254*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_iflag & IXOFF)
1255*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_TANDEM;
1256*7c478bd9Sstevel@tonic-gate 	if (!(termiosp->c_iflag &
1257*7c478bd9Sstevel@tonic-gate 	    (IMAXBEL|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|
1258*7c478bd9Sstevel@tonic-gate 	    INLCR|IGNCR|ICRNL|IUCLC|IXON)) &&
1259*7c478bd9Sstevel@tonic-gate 	    !(termiosp->c_oflag & OPOST) &&
1260*7c478bd9Sstevel@tonic-gate 	    (termiosp->c_cflag & (CSIZE|PARENB)) == CS8 &&
1261*7c478bd9Sstevel@tonic-gate 	    !(termiosp->c_lflag & (ISIG|ICANON|XCASE|IEXTEN)))
1262*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_RAW;
1263*7c478bd9Sstevel@tonic-gate 	else {
1264*7c478bd9Sstevel@tonic-gate 		if (!(termiosp->c_iflag & IXON)) {
1265*7c478bd9Sstevel@tonic-gate 			csp->t_startc = (uchar_t)0377;
1266*7c478bd9Sstevel@tonic-gate 			csp->t_stopc = (uchar_t)0377;
1267*7c478bd9Sstevel@tonic-gate 		}
1268*7c478bd9Sstevel@tonic-gate 		if ((termiosp->c_cflag & (CSIZE|PARENB)) == CS8 &&
1269*7c478bd9Sstevel@tonic-gate 		    !(termiosp->c_oflag & OPOST))
1270*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_LITOUT;
1271*7c478bd9Sstevel@tonic-gate 		else {
1272*7c478bd9Sstevel@tonic-gate 			csp->t_flags &= ~O_LITOUT;
1273*7c478bd9Sstevel@tonic-gate 			if ((termiosp->c_cflag & (CSIZE|PARENB)) == CS8) {
1274*7c478bd9Sstevel@tonic-gate 				if (!(termiosp->c_iflag & ISTRIP))
1275*7c478bd9Sstevel@tonic-gate 					csp->t_flags |= O_PASS8;
1276*7c478bd9Sstevel@tonic-gate 			} else {
1277*7c478bd9Sstevel@tonic-gate 				csp->t_flags &= ~(O_ODDP|O_EVENP|O_PASS8);
1278*7c478bd9Sstevel@tonic-gate 				if (termiosp->c_cflag & PARODD)
1279*7c478bd9Sstevel@tonic-gate 					csp->t_flags |= O_ODDP;
1280*7c478bd9Sstevel@tonic-gate 				else if (termiosp->c_iflag & INPCK)
1281*7c478bd9Sstevel@tonic-gate 					csp->t_flags |= O_EVENP;
1282*7c478bd9Sstevel@tonic-gate 				else
1283*7c478bd9Sstevel@tonic-gate 					csp->t_flags |= O_ODDP|O_EVENP;
1284*7c478bd9Sstevel@tonic-gate 			}
1285*7c478bd9Sstevel@tonic-gate 			if (!(termiosp->c_oflag & OPOST))
1286*7c478bd9Sstevel@tonic-gate 				csp->t_xflags |= NOPOST;
1287*7c478bd9Sstevel@tonic-gate 			else
1288*7c478bd9Sstevel@tonic-gate 				csp->t_xflags &= ~NOPOST;
1289*7c478bd9Sstevel@tonic-gate 		}
1290*7c478bd9Sstevel@tonic-gate 		if (!(termiosp->c_lflag & ISIG))
1291*7c478bd9Sstevel@tonic-gate 			csp->t_xflags |= NOISIG;
1292*7c478bd9Sstevel@tonic-gate 		else
1293*7c478bd9Sstevel@tonic-gate 			csp->t_xflags &= ~NOISIG;
1294*7c478bd9Sstevel@tonic-gate 		if (!(termiosp->c_lflag & ICANON))
1295*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_CBREAK;
1296*7c478bd9Sstevel@tonic-gate 		if (termiosp->c_lflag & ECHOCTL)
1297*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_CTLECH;
1298*7c478bd9Sstevel@tonic-gate 		else
1299*7c478bd9Sstevel@tonic-gate 			csp->t_flags &= ~O_CTLECH;
1300*7c478bd9Sstevel@tonic-gate 	}
1301*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_oflag & OLCUC)
1302*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_LCASE;
1303*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag&ECHO)
1304*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_ECHO;
1305*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_oflag & ONLCR) {
1306*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_CRMOD;
1307*7c478bd9Sstevel@tonic-gate 		switch (termiosp->c_oflag & CRDLY) {
1308*7c478bd9Sstevel@tonic-gate 
1309*7c478bd9Sstevel@tonic-gate 		case CR2:
1310*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_CR1;
1311*7c478bd9Sstevel@tonic-gate 			break;
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 		case CR3:
1314*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_CR2;
1315*7c478bd9Sstevel@tonic-gate 			break;
1316*7c478bd9Sstevel@tonic-gate 		}
1317*7c478bd9Sstevel@tonic-gate 	} else {
1318*7c478bd9Sstevel@tonic-gate 		if ((termiosp->c_oflag & CR1) &&
1319*7c478bd9Sstevel@tonic-gate 		    (termiosp->c_oflag & ONLRET))
1320*7c478bd9Sstevel@tonic-gate 			csp->t_flags |= O_NL1;	/* tty37 */
1321*7c478bd9Sstevel@tonic-gate 	}
1322*7c478bd9Sstevel@tonic-gate 	if ((termiosp->c_oflag & ONLRET) && (termiosp->c_oflag & NL1))
1323*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_NL2;
1324*7c478bd9Sstevel@tonic-gate 	switch (termiosp->c_oflag & TABDLY) {
1325*7c478bd9Sstevel@tonic-gate 
1326*7c478bd9Sstevel@tonic-gate 	case TAB1:
1327*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_TAB1;
1328*7c478bd9Sstevel@tonic-gate 		break;
1329*7c478bd9Sstevel@tonic-gate 
1330*7c478bd9Sstevel@tonic-gate 	case TAB2:
1331*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_TAB2;
1332*7c478bd9Sstevel@tonic-gate 		break;
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 	case XTABS:
1335*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_XTABS;
1336*7c478bd9Sstevel@tonic-gate 		break;
1337*7c478bd9Sstevel@tonic-gate 	}
1338*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_oflag & FFDLY)
1339*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_VTDELAY;
1340*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_oflag & BSDLY)
1341*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_BSDELAY;
1342*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & ECHOPRT)
1343*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_PRTERA;
1344*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & ECHOE)
1345*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= (O_CRTERA|O_CRTBS);
1346*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & TOSTOP)
1347*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_TOSTOP;
1348*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & FLUSHO)
1349*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_FLUSHO;
1350*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_cflag & CLOCAL)
1351*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_NOHANG;
1352*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & ECHOKE)
1353*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_CRTKIL;
1354*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & PENDIN)
1355*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_PENDIN;
1356*7c478bd9Sstevel@tonic-gate 	if (!(termiosp->c_iflag & IXANY))
1357*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_DECCTQ;
1358*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & NOFLSH)
1359*7c478bd9Sstevel@tonic-gate 		csp->t_flags |= O_NOFLSH;
1360*7c478bd9Sstevel@tonic-gate 	if (termiosp->c_lflag & ICANON) {
1361*7c478bd9Sstevel@tonic-gate 		TO_COMPAT_CHAR(csp->t_eofc, termiosp->c_cc[VEOF]);
1362*7c478bd9Sstevel@tonic-gate 		TO_COMPAT_CHAR(csp->t_brkc, termiosp->c_cc[VEOL]);
1363*7c478bd9Sstevel@tonic-gate 	} else {
1364*7c478bd9Sstevel@tonic-gate 		termiosp->c_cc[VMIN] = 1;
1365*7c478bd9Sstevel@tonic-gate 		termiosp->c_cc[VTIME] = 0;
1366*7c478bd9Sstevel@tonic-gate 	}
1367*7c478bd9Sstevel@tonic-gate }
1368