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