xref: /onnv-gate/usr/src/uts/sun/io/ttymux/ttymux_ioctl.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate  * DESCRIPTION
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  * ttymux_ioctl - Handler for ttymux specific ioctl calls.
32*0Sstevel@tonic-gate  *
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <sys/strsubr.h>
37*0Sstevel@tonic-gate #include <sys/strsun.h>
38*0Sstevel@tonic-gate #include <sys/errno.h>
39*0Sstevel@tonic-gate #include <sys/stat.h>
40*0Sstevel@tonic-gate #include <sys/kmem.h>
41*0Sstevel@tonic-gate #include <sys/ddi.h>
42*0Sstevel@tonic-gate #include <sys/termio.h>
43*0Sstevel@tonic-gate #include <sys/mkdev.h>
44*0Sstevel@tonic-gate #include <sys/sunddi.h>
45*0Sstevel@tonic-gate #include <sys/esunddi.h>
46*0Sstevel@tonic-gate #include <sys/consdev.h>
47*0Sstevel@tonic-gate #include <sys/promif.h>
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate #include <sys/ttymux.h>
50*0Sstevel@tonic-gate #include "ttymux_impl.h"
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate  * Extern declarations
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate extern mblk_t *mkiocb(uint_t);
56*0Sstevel@tonic-gate extern int nulldev();
57*0Sstevel@tonic-gate extern uintptr_t space_fetch(char *key);
58*0Sstevel@tonic-gate extern void prom_interpret(char *, uintptr_t, uintptr_t, uintptr_t,
59*0Sstevel@tonic-gate     uintptr_t, uintptr_t);
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate  * Imported ttymux routines
63*0Sstevel@tonic-gate  */
64*0Sstevel@tonic-gate extern void sm_debug(char *, ...);
65*0Sstevel@tonic-gate extern void sm_log(char *, ...);
66*0Sstevel@tonic-gate extern sm_lqi_t *get_lqi_byid(int);
67*0Sstevel@tonic-gate extern sm_lqi_t *get_lqi_bydevt(dev_t);
68*0Sstevel@tonic-gate extern int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *);
69*0Sstevel@tonic-gate extern int sm_disassociate(int, sm_lqi_t *, ulong_t);
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate /*
72*0Sstevel@tonic-gate  * Exported ttymux routines
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate int ttymux_abort_ioctl(mblk_t *);
75*0Sstevel@tonic-gate int ttymux_device_init(sm_lqi_t *);
76*0Sstevel@tonic-gate int ttymux_device_fini(sm_lqi_t *);
77*0Sstevel@tonic-gate int sm_ioctl_cmd(sm_uqi_t *, mblk_t *);
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate /*
80*0Sstevel@tonic-gate  * Imported ttymux variables
81*0Sstevel@tonic-gate  */
82*0Sstevel@tonic-gate extern sm_ss_t	*sm_ssp;
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate static int
85*0Sstevel@tonic-gate mblk2assoc(mblk_t *mp, ttymux_assoc_t *assoc)
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	struct iocblk *iobp = (struct iocblk *)mp->b_rptr;
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate 	sm_dbg('M', ("mblk2assoc:\n"));
90*0Sstevel@tonic-gate 	if (mp->b_cont == NULL)
91*0Sstevel@tonic-gate 		return (EINVAL);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
94*0Sstevel@tonic-gate 	if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
95*0Sstevel@tonic-gate 		ttymux_assoc32_t *assoc32;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 		sm_dbg('I', ("mblk2assoc: b_cont 0x%p count %d (sz %d)\n",
98*0Sstevel@tonic-gate 		    mp->b_cont, iobp->ioc_count, sizeof (*assoc32)));
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 		if (iobp->ioc_count < sizeof (ttymux_assoc32_t))
101*0Sstevel@tonic-gate 			return (EINVAL);
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 		assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr;
104*0Sstevel@tonic-gate 		assoc->ttymux_udev = expldev(assoc32->ttymux32_udev);
105*0Sstevel@tonic-gate 		assoc->ttymux_ldev = expldev(assoc32->ttymux32_ldev);
106*0Sstevel@tonic-gate 		assoc->ttymux_linkid = assoc32->ttymux32_linkid;
107*0Sstevel@tonic-gate 		assoc->ttymux_tag = assoc32->ttymux32_tag;
108*0Sstevel@tonic-gate 		assoc->ttymux_ioflag = assoc32->ttymux32_ioflag;
109*0Sstevel@tonic-gate 		(void) strncpy(assoc->ttymux_path, assoc32->ttymux32_path,
110*0Sstevel@tonic-gate 				MAXPATHLEN);
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	} else
113*0Sstevel@tonic-gate #endif
114*0Sstevel@tonic-gate 	if (iobp->ioc_count < sizeof (*assoc)) {
115*0Sstevel@tonic-gate 		return (EINVAL);
116*0Sstevel@tonic-gate 	} else {
117*0Sstevel@tonic-gate 		*assoc = *(ttymux_assoc_t *)mp->b_cont->b_rptr;
118*0Sstevel@tonic-gate 	}
119*0Sstevel@tonic-gate 	sm_dbg('M', ("mblk2assoc (%d): dev %d:%d not found\n",
120*0Sstevel@tonic-gate 	    assoc->ttymux_linkid, getmajor(assoc->ttymux_ldev),
121*0Sstevel@tonic-gate 			getminor(assoc->ttymux_ldev)));
122*0Sstevel@tonic-gate 	return (0);
123*0Sstevel@tonic-gate }
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate /*
126*0Sstevel@tonic-gate  * Given a device path return an OBP alias for it if it exists.
127*0Sstevel@tonic-gate  */
128*0Sstevel@tonic-gate static char *
129*0Sstevel@tonic-gate val2alias(dnode_t node, char *path)
130*0Sstevel@tonic-gate {
131*0Sstevel@tonic-gate 	char *buf1;
132*0Sstevel@tonic-gate 	char *buf2;
133*0Sstevel@tonic-gate 	char *propname, *propval;
134*0Sstevel@tonic-gate 	int proplen;
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	if (node == OBP_BADNODE)
137*0Sstevel@tonic-gate 		return (NULL);
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	sm_dbg('A', ("Looking for an alias for: %s (len %d)\n",
140*0Sstevel@tonic-gate 	    path, strlen(path)));
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * Ask for first property by passing a NULL string
144*0Sstevel@tonic-gate 	 */
145*0Sstevel@tonic-gate 	buf1 = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP);
146*0Sstevel@tonic-gate 	buf2 = kmem_zalloc(OBP_MAXPROPNAME, KM_SLEEP);
147*0Sstevel@tonic-gate 	buf1[0] = '\0';
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	while (propname = (char *)prom_nextprop(node, buf1, buf2)) {
150*0Sstevel@tonic-gate 		if (strlen(propname) == 0)
151*0Sstevel@tonic-gate 			break;	  /* end of prop list */
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 		(void) strcpy(buf1, propname);
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 		proplen = prom_getproplen(node, propname);
156*0Sstevel@tonic-gate 		if (proplen == 0)
157*0Sstevel@tonic-gate 			continue;
158*0Sstevel@tonic-gate 		propval = kmem_zalloc(proplen + 1, KM_SLEEP);
159*0Sstevel@tonic-gate 		(void) prom_getprop(node, propname, propval);
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 		if (strcmp(propval, path) == 0) {
162*0Sstevel@tonic-gate 			kmem_free(propval, proplen + 1);
163*0Sstevel@tonic-gate 			kmem_free(buf1, OBP_MAXPROPNAME);
164*0Sstevel@tonic-gate 			sm_dbg('A', ("Alias is : %s\n", buf2));
165*0Sstevel@tonic-gate 			return (buf2);
166*0Sstevel@tonic-gate 		}
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 		kmem_free(propval, proplen + 1);
169*0Sstevel@tonic-gate 		bzero(buf2, OBP_MAXPROPNAME);
170*0Sstevel@tonic-gate 	}
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	kmem_free(buf1, OBP_MAXPROPNAME);
173*0Sstevel@tonic-gate 	kmem_free(buf2, OBP_MAXPROPNAME);
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	return (NULL);
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate /*
179*0Sstevel@tonic-gate  * Tell OBP that this device is now usable
180*0Sstevel@tonic-gate  */
181*0Sstevel@tonic-gate static void
182*0Sstevel@tonic-gate enable_device(sm_mux_state_t *ms, sm_console_t *cn)
183*0Sstevel@tonic-gate {
184*0Sstevel@tonic-gate 	char *enb_str = "\" enable-device\" rot $call-method";
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	if (!cn->sm_obp_con)
187*0Sstevel@tonic-gate 		return;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	sm_dbg('A', ("ttymux: enabling %d:%d\n",
190*0Sstevel@tonic-gate 		getmajor(cn->sm_dev), getminor(cn->sm_dev)));
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	if (cn->sm_i_ihdl != 0)
193*0Sstevel@tonic-gate 		prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl,
194*0Sstevel@tonic-gate 			(caddr32_t)cn->sm_i_ihdl, 0, 0, 0);
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl)
197*0Sstevel@tonic-gate 		prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl,
198*0Sstevel@tonic-gate 			(caddr32_t)cn->sm_o_ihdl, 0, 0, 0);
199*0Sstevel@tonic-gate }
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate /*
202*0Sstevel@tonic-gate  * Tell OBP that this device is no longer usable
203*0Sstevel@tonic-gate  */
204*0Sstevel@tonic-gate static void
205*0Sstevel@tonic-gate disable_device(sm_mux_state_t *ms, sm_console_t *cn)
206*0Sstevel@tonic-gate {
207*0Sstevel@tonic-gate 	char *dis_str = "\" disable-device\" rot $call-method";
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	if (!cn->sm_obp_con)
210*0Sstevel@tonic-gate 		return;
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	sm_dbg('A', ("ttymux: disabling %d:%d\n",
213*0Sstevel@tonic-gate 		getmajor(cn->sm_dev), getminor(cn->sm_dev)));
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	if (cn->sm_i_ihdl != 0)
216*0Sstevel@tonic-gate 		prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl,
217*0Sstevel@tonic-gate 			(caddr32_t)cn->sm_i_ihdl, 0, 0, 0);
218*0Sstevel@tonic-gate 	if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl)
219*0Sstevel@tonic-gate 		prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl,
220*0Sstevel@tonic-gate 			(caddr32_t)cn->sm_o_ihdl, 0, 0, 0);
221*0Sstevel@tonic-gate }
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate static void
224*0Sstevel@tonic-gate device_init_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi)
225*0Sstevel@tonic-gate {
226*0Sstevel@tonic-gate 	uint_t		flags = 0;
227*0Sstevel@tonic-gate 	dev_info_t	*ldip;
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	sm_dbg('I', ("device_init_impl:\n"));
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	if (plqi == NULL || cn == NULL)
232*0Sstevel@tonic-gate 		return;
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	flags = (uint_t)cn->sm_mode;
235*0Sstevel@tonic-gate 	sm_dbg('I', ("device_init_impl: flgs %d con %d\n", flags,
236*0Sstevel@tonic-gate 			cn->sm_obp_con));
237*0Sstevel@tonic-gate 	if (ldip = e_ddi_hold_devi_by_dev(cn->sm_dev, 0)) {
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 		/*
240*0Sstevel@tonic-gate 		 * Indicate to the linked device that it is
241*0Sstevel@tonic-gate 		 * providing a multiplexed console.
242*0Sstevel@tonic-gate 		 */
243*0Sstevel@tonic-gate 		if (flags & (uint_t)FORINPUT)
244*0Sstevel@tonic-gate 			(void) e_ddi_prop_create(cn->sm_dev, ldip,
245*0Sstevel@tonic-gate 			    DDI_PROP_CANSLEEP, "obp-input-console", 0, 0);
246*0Sstevel@tonic-gate 		if (flags & (uint_t)FOROUTPUT)
247*0Sstevel@tonic-gate 			(void) e_ddi_prop_create(cn->sm_dev, ldip,
248*0Sstevel@tonic-gate 			    DDI_PROP_CANSLEEP, "obp-output-console", 0, 0);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 		ddi_release_devi(ldip);
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	if (flags) {
254*0Sstevel@tonic-gate 		plqi->sm_ioflag = flags;
255*0Sstevel@tonic-gate 		if (cn->sm_obp_con)
256*0Sstevel@tonic-gate 			plqi->sm_uqflags |= SM_OBPCNDEV;
257*0Sstevel@tonic-gate 		plqi->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on;
258*0Sstevel@tonic-gate 		plqi->sm_break_abort_on = sm_ssp->sm_break_abort_on;
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	/*
262*0Sstevel@tonic-gate 	 * Tell OBP that its ok to use this console
263*0Sstevel@tonic-gate 	 */
264*0Sstevel@tonic-gate 	enable_device(ms, cn);
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate static void
268*0Sstevel@tonic-gate device_fini_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi)
269*0Sstevel@tonic-gate {
270*0Sstevel@tonic-gate 	dev_info_t	*ldip;
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	if (plqi == NULL || cn == NULL)
273*0Sstevel@tonic-gate 		return;
274*0Sstevel@tonic-gate 	/*
275*0Sstevel@tonic-gate 	 * Indicate to the linked device that it is no longer
276*0Sstevel@tonic-gate 	 * providing a multiplexed console.
277*0Sstevel@tonic-gate 	 */
278*0Sstevel@tonic-gate 	if (ldip = e_ddi_hold_devi_by_dev(plqi->sm_dev, 0)) {
279*0Sstevel@tonic-gate 		if (plqi->sm_ioflag & (uint_t)FORINPUT)
280*0Sstevel@tonic-gate 			(void) e_ddi_prop_remove(plqi->sm_dev,
281*0Sstevel@tonic-gate 			    ldip, "obp-input-console");
282*0Sstevel@tonic-gate 		if (plqi->sm_ioflag & (uint_t)FOROUTPUT)
283*0Sstevel@tonic-gate 			(void) e_ddi_prop_remove(plqi->sm_dev,
284*0Sstevel@tonic-gate 			    ldip, "obp-output-console");
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 		ddi_release_devi(ldip);
287*0Sstevel@tonic-gate 	}
288*0Sstevel@tonic-gate 	plqi->sm_ioflag = 0;
289*0Sstevel@tonic-gate 	plqi->sm_uqflags &= ~SM_OBPCNDEV;
290*0Sstevel@tonic-gate 	disable_device(ms, cn);
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate static int
294*0Sstevel@tonic-gate read_prop(dnode_t node, char *propname, char **propval)
295*0Sstevel@tonic-gate {
296*0Sstevel@tonic-gate 	int	proplen = prom_getproplen(node, propname);
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	if (proplen < 0)
299*0Sstevel@tonic-gate 		return (proplen);
300*0Sstevel@tonic-gate 	*propval = kmem_zalloc(proplen + 1, KM_SLEEP);
301*0Sstevel@tonic-gate 	if (proplen > 0)
302*0Sstevel@tonic-gate 		(void) prom_getprop(node, propname, *propval);
303*0Sstevel@tonic-gate 	else
304*0Sstevel@tonic-gate 		*propval = 0;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	return (proplen);
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate /*
310*0Sstevel@tonic-gate  * Parse a list of tokens
311*0Sstevel@tonic-gate  */
312*0Sstevel@tonic-gate static char *
313*0Sstevel@tonic-gate sm_strtok_r(char *p, char *sep, char **lasts)
314*0Sstevel@tonic-gate {
315*0Sstevel@tonic-gate 	char    *e, *tok = NULL;
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	if (p == 0 || *p == 0)
318*0Sstevel@tonic-gate 		return (NULL);
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 	e = p + strlen(p);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	do {
323*0Sstevel@tonic-gate 		if (strchr(sep, *p) != NULL) {
324*0Sstevel@tonic-gate 			if (tok != NULL) {
325*0Sstevel@tonic-gate 				*p = 0;
326*0Sstevel@tonic-gate 				*lasts = p + 1;
327*0Sstevel@tonic-gate 				return (tok);
328*0Sstevel@tonic-gate 			}
329*0Sstevel@tonic-gate 		} else if (tok == NULL) {
330*0Sstevel@tonic-gate 			tok = p;
331*0Sstevel@tonic-gate 		}
332*0Sstevel@tonic-gate 	} while (++p < e);
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	*lasts = NULL;
335*0Sstevel@tonic-gate 	if (tok != NULL)
336*0Sstevel@tonic-gate 		return (tok);
337*0Sstevel@tonic-gate 	return (NULL);
338*0Sstevel@tonic-gate }
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate /*
341*0Sstevel@tonic-gate  * Add or remove an alias from a property list of aliases:
342*0Sstevel@tonic-gate  * path:	an OBP device path
343*0Sstevel@tonic-gate  * pname:	property name containing a space separated list of aliases
344*0Sstevel@tonic-gate  * append:	if true include the alias for path in the property list
345*0Sstevel@tonic-gate  *		otherwise remove the alias from the list.
346*0Sstevel@tonic-gate  */
347*0Sstevel@tonic-gate static int
348*0Sstevel@tonic-gate upd_config(boolean_t append, char *pname, char *path)
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 	dnode_t		onode, anode;
351*0Sstevel@tonic-gate 	size_t		plen;		/* length of property name */
352*0Sstevel@tonic-gate 	char		*pval;		/* value of property */
353*0Sstevel@tonic-gate 	char		*tok, *lasts;
354*0Sstevel@tonic-gate 	char		*aliases[TTYMUX_MAX_LINKS];
355*0Sstevel@tonic-gate 	size_t		i, cnt, len;
356*0Sstevel@tonic-gate 	boolean_t	found;
357*0Sstevel@tonic-gate 	char		*nval, *alias = NULL;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	if ((anode = prom_alias_node()) == OBP_BADNODE ||
360*0Sstevel@tonic-gate 	    (onode = prom_optionsnode()) == OBP_BADNODE) {
361*0Sstevel@tonic-gate 		sm_dbg('I', ("upd_config: no alias or options node.\n"));
362*0Sstevel@tonic-gate 		return (1);
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	if ((plen = read_prop(onode, pname, &pval)) < 0)
366*0Sstevel@tonic-gate 		return (1);
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	sm_dbg('I', ("upd_config: %s=%s (%s)\n", pname, pval, path));
369*0Sstevel@tonic-gate 	found = B_FALSE;
370*0Sstevel@tonic-gate 	for (len = 0, cnt = 0, tok = sm_strtok_r(pval, " \t", &lasts);
371*0Sstevel@tonic-gate 	    tok != NULL && cnt < TTYMUX_MAX_LINKS;
372*0Sstevel@tonic-gate 	    tok = sm_strtok_r(lasts, " \t", &lasts)) {
373*0Sstevel@tonic-gate 		char	*aval;
374*0Sstevel@tonic-gate 		size_t	alen;
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 		if ((alen = read_prop(anode, tok, &aval)) < 0)
377*0Sstevel@tonic-gate 			continue;
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 		/* does this alias match the requested path */
380*0Sstevel@tonic-gate 		if (strcmp(aval, path) == 0 ||
381*0Sstevel@tonic-gate 		    (strstr(path, aval) != NULL &&
382*0Sstevel@tonic-gate 		    strchr(aval, ':') == NULL && strchr(path, ':') != NULL &&
383*0Sstevel@tonic-gate 		    strcmp(strchr(path, ':'), ":a") == 0)) {
384*0Sstevel@tonic-gate 			if (!found && append) {
385*0Sstevel@tonic-gate 				kmem_free(aval, alen + 1);
386*0Sstevel@tonic-gate 				goto out;
387*0Sstevel@tonic-gate 			}
388*0Sstevel@tonic-gate 			found = B_TRUE;
389*0Sstevel@tonic-gate 		} else {
390*0Sstevel@tonic-gate 			aliases[cnt++] = tok;
391*0Sstevel@tonic-gate 			len += strlen(tok) + 1;
392*0Sstevel@tonic-gate 		}
393*0Sstevel@tonic-gate 		kmem_free(aval, alen + 1);
394*0Sstevel@tonic-gate 	}
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	sm_dbg('I', ("%d aliases\n", cnt));
397*0Sstevel@tonic-gate 	if (append) {
398*0Sstevel@tonic-gate 		if (cnt + 1 == TTYMUX_MAX_LINKS)
399*0Sstevel@tonic-gate 			goto out;
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 		if ((alias = val2alias(anode, path)) == NULL) {
402*0Sstevel@tonic-gate 			char *mnode = strstr(path, ":a");
403*0Sstevel@tonic-gate 
404*0Sstevel@tonic-gate 			if (mnode != 0) {
405*0Sstevel@tonic-gate 				*mnode = '\0';
406*0Sstevel@tonic-gate 				alias = val2alias(anode, path);
407*0Sstevel@tonic-gate 				*mnode = ':';
408*0Sstevel@tonic-gate 			}
409*0Sstevel@tonic-gate 		}
410*0Sstevel@tonic-gate 		if (alias == NULL) {
411*0Sstevel@tonic-gate 			sm_dbg('I', ("No alias for %s\n", path));
412*0Sstevel@tonic-gate 			goto out;
413*0Sstevel@tonic-gate 		}
414*0Sstevel@tonic-gate 		aliases[cnt++] = alias;
415*0Sstevel@tonic-gate 		len += strlen(alias) + 1;
416*0Sstevel@tonic-gate 	} else if (!found) {
417*0Sstevel@tonic-gate 		goto out;
418*0Sstevel@tonic-gate 	}
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	sm_dbg('I', ("%d aliases (len %d)\n", cnt, len));
421*0Sstevel@tonic-gate 	if (len == 0)
422*0Sstevel@tonic-gate 		goto out;
423*0Sstevel@tonic-gate 	ASSERT(len > 1 && cnt > 0);
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate 	nval = kmem_zalloc(len, KM_SLEEP);
426*0Sstevel@tonic-gate 	for (i = 0; ; ) {
427*0Sstevel@tonic-gate 		ASSERT(strlen(nval) + strlen(aliases[i]) + 1 <= len);
428*0Sstevel@tonic-gate 		sm_dbg('I', ("alias %s\n", aliases[i]));
429*0Sstevel@tonic-gate 		(void) strcat(nval, aliases[i]);
430*0Sstevel@tonic-gate 		if (++i == cnt)
431*0Sstevel@tonic-gate 			break;
432*0Sstevel@tonic-gate 		(void) strcat(nval, " ");
433*0Sstevel@tonic-gate 	}
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	sm_dbg('I', ("setprop: %s=%s (%d)\n", pname, nval, len));
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	(void) prom_setprop(onode, pname, nval, len);
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	kmem_free(nval, len);
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	if (alias != NULL)
442*0Sstevel@tonic-gate 		kmem_free(alias, OBP_MAXPROPNAME);
443*0Sstevel@tonic-gate out:
444*0Sstevel@tonic-gate 	sm_dbg('I', ("upd_config: returning.\n"));
445*0Sstevel@tonic-gate 	kmem_free(pval, plen + 1);
446*0Sstevel@tonic-gate 	return (0);
447*0Sstevel@tonic-gate }
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate /*
450*0Sstevel@tonic-gate  *
451*0Sstevel@tonic-gate  */
452*0Sstevel@tonic-gate static int
453*0Sstevel@tonic-gate update_config(sm_mux_state_t *ms, char *path, io_mode_t mode, int cmd)
454*0Sstevel@tonic-gate {
455*0Sstevel@tonic-gate 	sm_dbg('I', ("update_config: path %s io %d\n", path ? path : "", mode));
456*0Sstevel@tonic-gate 	if (path == 0 || *path == 0) {
457*0Sstevel@tonic-gate 		sm_dbg('I', ("update_config: EINVAL - no path\n"));
458*0Sstevel@tonic-gate 		return (1);
459*0Sstevel@tonic-gate 	}
460*0Sstevel@tonic-gate 	if (prom_is_openprom() == 0)
461*0Sstevel@tonic-gate 		return (0);
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 	if ((mode & FORINPUT) && ms->sm_ialias != NULL)
464*0Sstevel@tonic-gate 		(void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_ialias, path);
465*0Sstevel@tonic-gate 	if ((mode & FOROUTPUT) && ms->sm_oalias != NULL)
466*0Sstevel@tonic-gate 		(void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_oalias, path);
467*0Sstevel@tonic-gate 	return (0);
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate /*
471*0Sstevel@tonic-gate  * Convert a dev_t to a device path
472*0Sstevel@tonic-gate  */
473*0Sstevel@tonic-gate static char *
474*0Sstevel@tonic-gate sm_di_path(dev_t dev)
475*0Sstevel@tonic-gate {
476*0Sstevel@tonic-gate 	char *p, *path;
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	if (dev == NODEV)
479*0Sstevel@tonic-gate 		return (NULL);
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 	p = kmem_zalloc(MAXPATHLEN + 1, KM_SLEEP);
482*0Sstevel@tonic-gate 	if (ddi_dev_pathname(dev, S_IFCHR, p) == DDI_SUCCESS) {
483*0Sstevel@tonic-gate 		path = kmem_alloc(strlen(p) + 1, KM_SLEEP);
484*0Sstevel@tonic-gate 		(void) strcpy(path, p);
485*0Sstevel@tonic-gate 	}
486*0Sstevel@tonic-gate 	kmem_free(p, MAXPATHLEN + 1);
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	return (path);
489*0Sstevel@tonic-gate }
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate static int
492*0Sstevel@tonic-gate console_cmd(int cmd, ttymux_assoc_t *assoc)
493*0Sstevel@tonic-gate {
494*0Sstevel@tonic-gate 	sm_mux_state_t	*ms;
495*0Sstevel@tonic-gate 	sm_console_t	*cn;
496*0Sstevel@tonic-gate 	uint_t		j;
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate 	sm_dbg('I', ("console_cmd ENTER: %s\n", cmd == TTYMUX_DISASSOC ?
499*0Sstevel@tonic-gate 		"TTYMUX_DISASSOC" : "TTYMUX_ASSOC"));
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	if (assoc->ttymux_ldev == NODEV && *assoc->ttymux_path != '/') {
502*0Sstevel@tonic-gate 		sm_lqi_t *lqi = get_lqi_byid(assoc->ttymux_linkid);
503*0Sstevel@tonic-gate 		if (lqi == 0 || lqi->sm_dev == NODEV) {
504*0Sstevel@tonic-gate 			sm_dbg('I', ("console_cmd: no id link %d cmd %d\n",
505*0Sstevel@tonic-gate 			    assoc->ttymux_linkid, cmd));
506*0Sstevel@tonic-gate 			return (EINVAL);
507*0Sstevel@tonic-gate 		}
508*0Sstevel@tonic-gate 		assoc->ttymux_ldev = lqi->sm_dev;
509*0Sstevel@tonic-gate 	}
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 	sm_dbg('I', ("console_cmd: path %s\n", assoc->ttymux_path));
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	if ((ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR)) == 0) {
514*0Sstevel@tonic-gate 		sm_dbg('I', ("console_cmd: No muxstate\n"));
515*0Sstevel@tonic-gate 		return (0);
516*0Sstevel@tonic-gate 	}
517*0Sstevel@tonic-gate 
518*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	for (cn = ms->sm_cons_links, j = 0;
521*0Sstevel@tonic-gate 	    j < ms->sm_cons_cnt; cn++, j++) {
522*0Sstevel@tonic-gate 		if (assoc->ttymux_ldev != NODEV && assoc->ttymux_ldev ==
523*0Sstevel@tonic-gate 				cn->sm_dev) {
524*0Sstevel@tonic-gate 			break;
525*0Sstevel@tonic-gate 		} else if (cn->sm_path != NULL &&
526*0Sstevel@tonic-gate 		    strncmp(cn->sm_path, assoc->ttymux_path, MAXPATHLEN) == 0) {
527*0Sstevel@tonic-gate 			break;
528*0Sstevel@tonic-gate 		}
529*0Sstevel@tonic-gate 	}
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	assoc->ttymux_path[MAXPATHLEN - 1] = 0;
532*0Sstevel@tonic-gate 	if (cmd == TTYMUX_DISASSOC) {
533*0Sstevel@tonic-gate 		if (j == ms->sm_cons_cnt) {
534*0Sstevel@tonic-gate 			mutex_exit(&ms->sm_cons_mutex);
535*0Sstevel@tonic-gate 			return (0);
536*0Sstevel@tonic-gate 		}
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 		/*
539*0Sstevel@tonic-gate 		 * Disable the console in OBP and then delete this console
540*0Sstevel@tonic-gate 		 * this console - note that this also deletes OBP
541*0Sstevel@tonic-gate 		 * information - i.e. once it is disassociated it cannot
542*0Sstevel@tonic-gate 		 * be reused as an OBP console - roll on polled I/O!
543*0Sstevel@tonic-gate 		 */
544*0Sstevel@tonic-gate 		sm_dbg('I', ("console_cmd: cleaning up\n"));
545*0Sstevel@tonic-gate 		device_fini_impl(ms, cn, get_lqi_bydevt(assoc->ttymux_ldev));
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 		if (cn->sm_path == NULL) {
548*0Sstevel@tonic-gate 			if (assoc->ttymux_ldev != NODEV)
549*0Sstevel@tonic-gate 				cn->sm_path = sm_di_path(assoc->ttymux_ldev);
550*0Sstevel@tonic-gate 			else
551*0Sstevel@tonic-gate 				(void) update_config(ms, assoc->ttymux_path,
552*0Sstevel@tonic-gate 				    assoc->ttymux_ioflag, cmd);
553*0Sstevel@tonic-gate 		}
554*0Sstevel@tonic-gate 		if (cn->sm_path) {
555*0Sstevel@tonic-gate 			(void) update_config(ms, cn->sm_path, cn->sm_mode, cmd);
556*0Sstevel@tonic-gate 			kmem_free(cn->sm_path, strlen(cn->sm_path) + 1);
557*0Sstevel@tonic-gate 			cn->sm_path = NULL;
558*0Sstevel@tonic-gate 		}
559*0Sstevel@tonic-gate 		ms->sm_cons_cnt -= 1;
560*0Sstevel@tonic-gate 		if (ms->sm_cons_cnt > 0)
561*0Sstevel@tonic-gate 			*cn = ms->sm_cons_links[ms->sm_cons_cnt];
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 		sm_dbg('I', ("console_cmd: console %d removed (cnt %d)\n",
564*0Sstevel@tonic-gate 		    j, ms->sm_cons_cnt));
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 	} else if (cmd == TTYMUX_ASSOC) {
567*0Sstevel@tonic-gate 
568*0Sstevel@tonic-gate 		if (j == ms->sm_cons_cnt) {
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 			if (j == TTYMUX_MAX_LINKS) {
571*0Sstevel@tonic-gate 				mutex_exit(&ms->sm_cons_mutex);
572*0Sstevel@tonic-gate 				return (ENOMEM);
573*0Sstevel@tonic-gate 			}
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate 			ms->sm_cons_cnt += 1;
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 			bzero((caddr_t)cn, sizeof (*cn));
578*0Sstevel@tonic-gate 			cn->sm_dev = assoc->ttymux_ldev;
579*0Sstevel@tonic-gate 			cn->sm_muxid = assoc->ttymux_linkid;
580*0Sstevel@tonic-gate 			cn->sm_mode = assoc->ttymux_ioflag;
581*0Sstevel@tonic-gate 			device_init_impl(ms, cn,
582*0Sstevel@tonic-gate 				get_lqi_bydevt(assoc->ttymux_ldev));
583*0Sstevel@tonic-gate 		} else {
584*0Sstevel@tonic-gate 			cn->sm_dev = assoc->ttymux_ldev;
585*0Sstevel@tonic-gate 			cn->sm_muxid = assoc->ttymux_linkid;
586*0Sstevel@tonic-gate 			cn->sm_mode = assoc->ttymux_ioflag;
587*0Sstevel@tonic-gate 		}
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 		if (assoc->ttymux_ldev != NODEV) {
590*0Sstevel@tonic-gate 			cn->sm_path = sm_di_path(assoc->ttymux_ldev);
591*0Sstevel@tonic-gate 		} else {
592*0Sstevel@tonic-gate 			cn->sm_path = kmem_alloc(strlen(assoc->ttymux_path) + 1,
593*0Sstevel@tonic-gate 			    KM_SLEEP);
594*0Sstevel@tonic-gate 			(void) strcpy(cn->sm_path, assoc->ttymux_path);
595*0Sstevel@tonic-gate 		}
596*0Sstevel@tonic-gate 		if (cn->sm_path != NULL)
597*0Sstevel@tonic-gate 			(void) update_config(ms, cn->sm_path, cn->sm_mode, cmd);
598*0Sstevel@tonic-gate 		else
599*0Sstevel@tonic-gate 			sm_dbg('I', ("console_cmd: ASSOC No path info"));
600*0Sstevel@tonic-gate 	}
601*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
602*0Sstevel@tonic-gate 	sm_dbg('I', ("console_cmd EXIT: %s\n", cmd == TTYMUX_DISASSOC ?
603*0Sstevel@tonic-gate 		"TTYMUX_DISASSOC" : "TTYMUX_ASSOC"));
604*0Sstevel@tonic-gate 	return (0);
605*0Sstevel@tonic-gate }
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate static int
608*0Sstevel@tonic-gate get_unconfigured_consoles(sm_mux_state_t *ms, ttymux_assoc_t *a)
609*0Sstevel@tonic-gate {
610*0Sstevel@tonic-gate 	sm_console_t	*cn;
611*0Sstevel@tonic-gate 	int		j, cnt;
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	if (ms == 0)
614*0Sstevel@tonic-gate 		return (0);
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
617*0Sstevel@tonic-gate 	for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt;
618*0Sstevel@tonic-gate 							cn++, j++) {
619*0Sstevel@tonic-gate 		if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) {
620*0Sstevel@tonic-gate 			a->ttymux_linkid = cn->sm_muxid;
621*0Sstevel@tonic-gate 			a->ttymux_tag = (uint_t)0;
622*0Sstevel@tonic-gate 			a->ttymux_ioflag = cn->sm_mode;
623*0Sstevel@tonic-gate 			a->ttymux_udev = cn->sm_mode & FORINPUT ?
624*0Sstevel@tonic-gate 						ms->sm_cons_stdin.sm_dev :
625*0Sstevel@tonic-gate 						ms->sm_cons_stdout.sm_dev;
626*0Sstevel@tonic-gate 			a->ttymux_ldev = NODEV;
627*0Sstevel@tonic-gate 			(void) strncpy(a->ttymux_path, cn->sm_path, MAXPATHLEN);
628*0Sstevel@tonic-gate 			cnt++;
629*0Sstevel@tonic-gate 			a++;
630*0Sstevel@tonic-gate 		}
631*0Sstevel@tonic-gate 	}
632*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
633*0Sstevel@tonic-gate 	return (cnt);
634*0Sstevel@tonic-gate }
635*0Sstevel@tonic-gate 
636*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
637*0Sstevel@tonic-gate /*
638*0Sstevel@tonic-gate  * Look for any consoles that are not currently plumbed under the multiplexer.
639*0Sstevel@tonic-gate  */
640*0Sstevel@tonic-gate static int
641*0Sstevel@tonic-gate get_unconfigured_consoles32(sm_mux_state_t *ms, ttymux_assoc32_t *a)
642*0Sstevel@tonic-gate {
643*0Sstevel@tonic-gate 	sm_console_t	*cn;
644*0Sstevel@tonic-gate 	int		j, cnt;
645*0Sstevel@tonic-gate 
646*0Sstevel@tonic-gate 	if (ms == 0)
647*0Sstevel@tonic-gate 		return (0);
648*0Sstevel@tonic-gate 
649*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
650*0Sstevel@tonic-gate 	for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt;
651*0Sstevel@tonic-gate 							cn++, j++) {
652*0Sstevel@tonic-gate 		sm_dbg('I', ("get_unconfigured_consoles: check %s (%d:%d)",
653*0Sstevel@tonic-gate 		    cn->sm_path ? cn->sm_path : "NULL",
654*0Sstevel@tonic-gate 		    getmajor(cn->sm_dev), getminor(cn->sm_dev)));
655*0Sstevel@tonic-gate 		if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) {
656*0Sstevel@tonic-gate 			a->ttymux32_linkid = 0;
657*0Sstevel@tonic-gate 			a->ttymux32_tag = (uint32_t)0;
658*0Sstevel@tonic-gate 			a->ttymux32_ioflag = (uint32_t)cn->sm_mode;
659*0Sstevel@tonic-gate 			a->ttymux32_ldev = NODEV32;
660*0Sstevel@tonic-gate 			(void) cmpldev(&a->ttymux32_udev, cn->sm_mode &
661*0Sstevel@tonic-gate 					FORINPUT ? ms->sm_cons_stdin.sm_dev :
662*0Sstevel@tonic-gate 					ms->sm_cons_stdout.sm_dev);
663*0Sstevel@tonic-gate 
664*0Sstevel@tonic-gate 			(void) strncpy(a->ttymux32_path, cn->sm_path,
665*0Sstevel@tonic-gate 					MAXPATHLEN);
666*0Sstevel@tonic-gate 			cnt++;
667*0Sstevel@tonic-gate 			a++;
668*0Sstevel@tonic-gate 		}
669*0Sstevel@tonic-gate 	}
670*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
671*0Sstevel@tonic-gate 	return (cnt);
672*0Sstevel@tonic-gate }
673*0Sstevel@tonic-gate #endif
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate static int
676*0Sstevel@tonic-gate count_unconfigured_consoles(sm_mux_state_t *ms)
677*0Sstevel@tonic-gate {
678*0Sstevel@tonic-gate 	sm_console_t	*cn;
679*0Sstevel@tonic-gate 	int		j, cnt;
680*0Sstevel@tonic-gate 
681*0Sstevel@tonic-gate 	if (ms == 0)
682*0Sstevel@tonic-gate 		return (0);
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
685*0Sstevel@tonic-gate 	for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt;
686*0Sstevel@tonic-gate 							cn++, j++) {
687*0Sstevel@tonic-gate 		sm_dbg('I', ("cnt_unconfigured_consoles: check %s (%d:%d)",
688*0Sstevel@tonic-gate 		    cn->sm_path ? cn->sm_path : "NULL",
689*0Sstevel@tonic-gate 		    getmajor(cn->sm_dev), getminor(cn->sm_dev)));
690*0Sstevel@tonic-gate 		if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL)
691*0Sstevel@tonic-gate 			cnt++;
692*0Sstevel@tonic-gate 	}
693*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
694*0Sstevel@tonic-gate 	return (cnt);
695*0Sstevel@tonic-gate }
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate /*
698*0Sstevel@tonic-gate  * Exported interfaces
699*0Sstevel@tonic-gate  */
700*0Sstevel@tonic-gate 
701*0Sstevel@tonic-gate /*
702*0Sstevel@tonic-gate  * A console device is no longer associated.
703*0Sstevel@tonic-gate  */
704*0Sstevel@tonic-gate int
705*0Sstevel@tonic-gate ttymux_device_fini(sm_lqi_t *plqi)
706*0Sstevel@tonic-gate {
707*0Sstevel@tonic-gate 	int		j;
708*0Sstevel@tonic-gate 	sm_mux_state_t	*ms;
709*0Sstevel@tonic-gate 
710*0Sstevel@tonic-gate 	ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR);
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 	if (plqi == NULL || ms == NULL)
713*0Sstevel@tonic-gate 		return (0);
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
716*0Sstevel@tonic-gate 
717*0Sstevel@tonic-gate 	for (j = 0; j < ms->sm_cons_cnt; j++) {
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 		if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) {
720*0Sstevel@tonic-gate 
721*0Sstevel@tonic-gate 			device_fini_impl(ms, &ms->sm_cons_links[j], plqi);
722*0Sstevel@tonic-gate 
723*0Sstevel@tonic-gate 			mutex_exit(&ms->sm_cons_mutex);
724*0Sstevel@tonic-gate 			return (0);
725*0Sstevel@tonic-gate 		}
726*0Sstevel@tonic-gate 	}
727*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 	return (1);
730*0Sstevel@tonic-gate }
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate /*
733*0Sstevel@tonic-gate  * A console device is being introduced.
734*0Sstevel@tonic-gate  */
735*0Sstevel@tonic-gate int
736*0Sstevel@tonic-gate ttymux_device_init(sm_lqi_t *plqi)
737*0Sstevel@tonic-gate {
738*0Sstevel@tonic-gate 	int j;
739*0Sstevel@tonic-gate 	sm_mux_state_t *ms;
740*0Sstevel@tonic-gate 
741*0Sstevel@tonic-gate 	ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR);
742*0Sstevel@tonic-gate 
743*0Sstevel@tonic-gate 	if (ms == NULL)
744*0Sstevel@tonic-gate 		return (0);
745*0Sstevel@tonic-gate 
746*0Sstevel@tonic-gate 	mutex_enter(&ms->sm_cons_mutex);
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	for (j = 0; j < ms->sm_cons_cnt; j++) {
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 		if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) {
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 			device_init_impl(ms, &ms->sm_cons_links[j], plqi);
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate 			mutex_exit(&ms->sm_cons_mutex);
755*0Sstevel@tonic-gate 			return (0);
756*0Sstevel@tonic-gate 		}
757*0Sstevel@tonic-gate 	}
758*0Sstevel@tonic-gate 	mutex_exit(&ms->sm_cons_mutex);
759*0Sstevel@tonic-gate 	return (1);
760*0Sstevel@tonic-gate }
761*0Sstevel@tonic-gate 
762*0Sstevel@tonic-gate /*
763*0Sstevel@tonic-gate  * Process a TTYMUX_ASSOCIATE or TTYMUX_DISASSOCIATE ioctl.
764*0Sstevel@tonic-gate  */
765*0Sstevel@tonic-gate static int
766*0Sstevel@tonic-gate ttymux_link_ioctl(mblk_t *mp)
767*0Sstevel@tonic-gate {
768*0Sstevel@tonic-gate 	ttymux_assoc_t	assoc;
769*0Sstevel@tonic-gate 	int		err;
770*0Sstevel@tonic-gate 	sm_lqi_t		*lqi;
771*0Sstevel@tonic-gate 	struct iocblk	*iobp = (struct iocblk *)mp->b_rptr;
772*0Sstevel@tonic-gate 	dev_t		cidev, codev;
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	sm_dbg('I', ("ttymux_link_ioctl:\n"));
775*0Sstevel@tonic-gate 	if ((err = mblk2assoc(mp, &assoc)) != 0)
776*0Sstevel@tonic-gate 		return (err);
777*0Sstevel@tonic-gate 
778*0Sstevel@tonic-gate 	sm_dbg('I', ("uminor is %d\n", getminor(assoc.ttymux_udev)));
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	if (assoc.ttymux_udev == NODEV)
781*0Sstevel@tonic-gate 		return (EINVAL);
782*0Sstevel@tonic-gate 
783*0Sstevel@tonic-gate 	err = 0;
784*0Sstevel@tonic-gate 
785*0Sstevel@tonic-gate 	if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL) {
786*0Sstevel@tonic-gate 		if (assoc.ttymux_linkid < 0)
787*0Sstevel@tonic-gate 			err = EINVAL;
788*0Sstevel@tonic-gate 		else if ((lqi = get_lqi_byid(assoc.ttymux_linkid)) == 0)
789*0Sstevel@tonic-gate 			err = ENOLINK;
790*0Sstevel@tonic-gate 	}
791*0Sstevel@tonic-gate 
792*0Sstevel@tonic-gate 	if (sm_ssp->sm_ms) {
793*0Sstevel@tonic-gate 		mutex_enter(&sm_ssp->sm_ms->sm_cons_mutex);
794*0Sstevel@tonic-gate 		cidev = sm_ssp->sm_ms->sm_cons_stdin.sm_dev;
795*0Sstevel@tonic-gate 		codev = sm_ssp->sm_ms->sm_cons_stdout.sm_dev;
796*0Sstevel@tonic-gate 		mutex_exit(&sm_ssp->sm_ms->sm_cons_mutex);
797*0Sstevel@tonic-gate 	} else {
798*0Sstevel@tonic-gate 		cidev = codev = NODEV;
799*0Sstevel@tonic-gate 	}
800*0Sstevel@tonic-gate 
801*0Sstevel@tonic-gate 	if (err != 0) {
802*0Sstevel@tonic-gate 		if (assoc.ttymux_udev != cidev && assoc.ttymux_udev != codev)
803*0Sstevel@tonic-gate 			return (err);
804*0Sstevel@tonic-gate 		(void) console_cmd(iobp->ioc_cmd, &assoc);
805*0Sstevel@tonic-gate 		return (0);
806*0Sstevel@tonic-gate 	} else if (assoc.ttymux_udev == cidev || assoc.ttymux_udev == codev) {
807*0Sstevel@tonic-gate 		(void) console_cmd(iobp->ioc_cmd, &assoc);
808*0Sstevel@tonic-gate 	}
809*0Sstevel@tonic-gate 
810*0Sstevel@tonic-gate 	if (iobp->ioc_cmd == TTYMUX_ASSOC)
811*0Sstevel@tonic-gate 		return (sm_associate(sm_dev2unit(assoc.ttymux_udev),
812*0Sstevel@tonic-gate 		    lqi, assoc.ttymux_tag, assoc.ttymux_ioflag,
813*0Sstevel@tonic-gate 			assoc.ttymux_path));
814*0Sstevel@tonic-gate 	else if (iobp->ioc_cmd == TTYMUX_DISASSOC)
815*0Sstevel@tonic-gate 		return (sm_disassociate(sm_dev2unit(assoc.ttymux_udev),
816*0Sstevel@tonic-gate 		    lqi, assoc.ttymux_tag));
817*0Sstevel@tonic-gate 
818*0Sstevel@tonic-gate 	return (0);
819*0Sstevel@tonic-gate }
820*0Sstevel@tonic-gate 
821*0Sstevel@tonic-gate /*
822*0Sstevel@tonic-gate  * Process a TTYMUX_GETLINK ioctl.
823*0Sstevel@tonic-gate  */
824*0Sstevel@tonic-gate int
825*0Sstevel@tonic-gate ttymux_query_link_ioctl(mblk_t *mp)
826*0Sstevel@tonic-gate {
827*0Sstevel@tonic-gate 	sm_lqi_t		*lqi;
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 	struct iocblk *iobp = (struct iocblk *)mp->b_rptr;
830*0Sstevel@tonic-gate 
831*0Sstevel@tonic-gate 	sm_dbg('I', ("ttymux_query_link_ioctl:\n"));
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	if (mp->b_cont == NULL)
834*0Sstevel@tonic-gate 		return (EINVAL);
835*0Sstevel@tonic-gate 
836*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
837*0Sstevel@tonic-gate 	if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
838*0Sstevel@tonic-gate 		ttymux_assoc32_t	*assoc32;
839*0Sstevel@tonic-gate 		ttymux_assoc_t	assoc;
840*0Sstevel@tonic-gate 
841*0Sstevel@tonic-gate 		if (mblk2assoc(mp, &assoc) != 0)
842*0Sstevel@tonic-gate 			return (EINVAL);
843*0Sstevel@tonic-gate 
844*0Sstevel@tonic-gate 		if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL &&
845*0Sstevel@tonic-gate 		    (lqi = get_lqi_byid(assoc.ttymux_linkid)) == NULL) {
846*0Sstevel@tonic-gate 			sm_dbg('M', ("Query Link (%d): dev %d:%d not found\n",
847*0Sstevel@tonic-gate 			    assoc.ttymux_linkid,
848*0Sstevel@tonic-gate 			    getmajor(assoc.ttymux_ldev),
849*0Sstevel@tonic-gate 				getminor(assoc.ttymux_ldev)));
850*0Sstevel@tonic-gate 			return (ENOLINK);
851*0Sstevel@tonic-gate 		}
852*0Sstevel@tonic-gate 		assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr;
853*0Sstevel@tonic-gate 		LQI2ASSOC32(assoc32, lqi);
854*0Sstevel@tonic-gate 	} else
855*0Sstevel@tonic-gate #endif
856*0Sstevel@tonic-gate 	{
857*0Sstevel@tonic-gate 		ttymux_assoc_t	*assoc;
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate 		if (iobp->ioc_count < sizeof (ttymux_assoc_t))
860*0Sstevel@tonic-gate 			return (EINVAL);
861*0Sstevel@tonic-gate 
862*0Sstevel@tonic-gate 		assoc = (ttymux_assoc_t *)mp->b_cont->b_rptr;
863*0Sstevel@tonic-gate 		if ((lqi = get_lqi_bydevt(assoc->ttymux_ldev)) == NULL &&
864*0Sstevel@tonic-gate 		    (lqi = get_lqi_byid(assoc->ttymux_linkid)) == NULL) {
865*0Sstevel@tonic-gate 			return (ENOLINK);
866*0Sstevel@tonic-gate 		}
867*0Sstevel@tonic-gate 		LQI2ASSOC(assoc, lqi);
868*0Sstevel@tonic-gate 	}
869*0Sstevel@tonic-gate 	return (0);
870*0Sstevel@tonic-gate }
871*0Sstevel@tonic-gate 
872*0Sstevel@tonic-gate /*
873*0Sstevel@tonic-gate  * Response to receiving an M_IOCDATA message for the TTYMUX_LIST ioctl.
874*0Sstevel@tonic-gate  */
875*0Sstevel@tonic-gate static int
876*0Sstevel@tonic-gate sm_iocresp(mblk_t *mp)
877*0Sstevel@tonic-gate {
878*0Sstevel@tonic-gate 	struct copyresp *csp = (struct copyresp *)mp->b_rptr;
879*0Sstevel@tonic-gate 	struct iocblk	*iobp = (struct iocblk *)mp->b_rptr;
880*0Sstevel@tonic-gate 	mblk_t		*pmp;
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate 	sm_dbg('M', ("(M_IOCDATA: cmd %d)\n", csp->cp_cmd));
883*0Sstevel@tonic-gate 
884*0Sstevel@tonic-gate 	if (csp->cp_cmd != TTYMUX_LIST) {
885*0Sstevel@tonic-gate 		sm_dbg('M', ("(M_IOCDATA: unknown cmd)\n"));
886*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCNAK;
887*0Sstevel@tonic-gate 		return (EINVAL);
888*0Sstevel@tonic-gate 	}
889*0Sstevel@tonic-gate 	if (csp->cp_rval) {
890*0Sstevel@tonic-gate 		if (csp->cp_private)
891*0Sstevel@tonic-gate 			freemsg((mblk_t *)csp->cp_private);
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 		sm_dbg('M', ("M_IOCDATA: result is %d\n", csp->cp_rval));
894*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCNAK;
895*0Sstevel@tonic-gate 		iobp->ioc_error = (int)csp->cp_rval;
896*0Sstevel@tonic-gate 		iobp->ioc_rval = 0;
897*0Sstevel@tonic-gate 		return ((int)csp->cp_rval);
898*0Sstevel@tonic-gate 	}
899*0Sstevel@tonic-gate 
900*0Sstevel@tonic-gate 	pmp = (mblk_t *)csp->cp_private;
901*0Sstevel@tonic-gate 
902*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
903*0Sstevel@tonic-gate 	if ((csp->cp_flag & IOC_MODELS) != IOC_NATIVE) {
904*0Sstevel@tonic-gate 		iobp->ioc_count = sizeof (ttymux_assocs32_t);
905*0Sstevel@tonic-gate 		iobp->ioc_rval = pmp == NULL ? 0 :
906*0Sstevel@tonic-gate 		    ((ttymux_assocs32_t *)pmp->b_rptr)->ttymux32_nlinks;
907*0Sstevel@tonic-gate 	} else
908*0Sstevel@tonic-gate #endif
909*0Sstevel@tonic-gate 	{
910*0Sstevel@tonic-gate 		iobp->ioc_count = sizeof (ttymux_assocs_t);
911*0Sstevel@tonic-gate 		iobp->ioc_rval = pmp == NULL ? 0 :
912*0Sstevel@tonic-gate 		    ((ttymux_assocs_t *)pmp->b_rptr)->ttymux_nlinks;
913*0Sstevel@tonic-gate 
914*0Sstevel@tonic-gate 	}
915*0Sstevel@tonic-gate 
916*0Sstevel@tonic-gate 	DB_TYPE(mp) = (pmp) ? M_IOCACK : M_IOCNAK;
917*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
918*0Sstevel@tonic-gate 
919*0Sstevel@tonic-gate 	if (mp->b_cont)
920*0Sstevel@tonic-gate 		freemsg(unlinkb(mp));
921*0Sstevel@tonic-gate 	if (pmp)
922*0Sstevel@tonic-gate 		linkb(mp, pmp);
923*0Sstevel@tonic-gate 	else
924*0Sstevel@tonic-gate 		iobp->ioc_count = 0;
925*0Sstevel@tonic-gate 
926*0Sstevel@tonic-gate 	iobp->ioc_error = 0;
927*0Sstevel@tonic-gate 
928*0Sstevel@tonic-gate 	sm_dbg('M', ("(M_IOCDATA: rval %d cnt %d private 0x%p)\n",
929*0Sstevel@tonic-gate 	    iobp->ioc_rval, iobp->ioc_count, pmp));
930*0Sstevel@tonic-gate 	return (0);
931*0Sstevel@tonic-gate }
932*0Sstevel@tonic-gate 
933*0Sstevel@tonic-gate /*
934*0Sstevel@tonic-gate  * Process a TTYMUX_LIST ioctl.
935*0Sstevel@tonic-gate  */
936*0Sstevel@tonic-gate int
937*0Sstevel@tonic-gate ttymux_query_links_ioctl(mblk_t *mp)
938*0Sstevel@tonic-gate {
939*0Sstevel@tonic-gate 	struct iocblk	*iobp = (struct iocblk *)mp->b_rptr;
940*0Sstevel@tonic-gate 	struct copyreq	*cqp;
941*0Sstevel@tonic-gate 	int		unit;
942*0Sstevel@tonic-gate 	sm_lqi_t		*lqi;
943*0Sstevel@tonic-gate 	mblk_t		*nmp;
944*0Sstevel@tonic-gate 	int		cnt;
945*0Sstevel@tonic-gate 	void		*asl;
946*0Sstevel@tonic-gate 	void		*uaddr;
947*0Sstevel@tonic-gate 	size_t		sz;
948*0Sstevel@tonic-gate 
949*0Sstevel@tonic-gate 	if (DB_TYPE(mp) == M_IOCDATA) {
950*0Sstevel@tonic-gate 		return (sm_iocresp(mp));
951*0Sstevel@tonic-gate 	}
952*0Sstevel@tonic-gate 	/*
953*0Sstevel@tonic-gate 	 * Is this a query for the number of linked devices?
954*0Sstevel@tonic-gate 	 */
955*0Sstevel@tonic-gate 	if (iobp->ioc_count == 0) {
956*0Sstevel@tonic-gate 
957*0Sstevel@tonic-gate 		for (unit = 0, iobp->ioc_rval = 0;
958*0Sstevel@tonic-gate 		    unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit));
959*0Sstevel@tonic-gate 		    unit++)
960*0Sstevel@tonic-gate 			if (lqi->sm_linkid != 0)
961*0Sstevel@tonic-gate 				iobp->ioc_rval += 1;
962*0Sstevel@tonic-gate 
963*0Sstevel@tonic-gate 		iobp->ioc_rval += count_unconfigured_consoles(sm_ssp->sm_ms);
964*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCACK;
965*0Sstevel@tonic-gate 		iobp->ioc_error = 0;
966*0Sstevel@tonic-gate 
967*0Sstevel@tonic-gate 		return (0);
968*0Sstevel@tonic-gate 	}
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 	if (mp->b_cont == NULL) {
971*0Sstevel@tonic-gate 		sm_dbg('Y', ("TTYMUX_LIST: b_cont is NULL\n"));
972*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCNAK;
973*0Sstevel@tonic-gate 		iobp->ioc_error = EINVAL;
974*0Sstevel@tonic-gate 		return (EINVAL);
975*0Sstevel@tonic-gate 	}
976*0Sstevel@tonic-gate 
977*0Sstevel@tonic-gate 	asl = mp->b_cont->b_rptr;
978*0Sstevel@tonic-gate 
979*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
980*0Sstevel@tonic-gate 	if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
981*0Sstevel@tonic-gate 		cnt = ((ttymux_assocs32_t *)asl)->ttymux32_nlinks;
982*0Sstevel@tonic-gate 		sz = cnt * sizeof (ttymux_assoc32_t);
983*0Sstevel@tonic-gate 		uaddr = (void *)((ttymux_assocs32_t *)asl)->ttymux32_assocs;
984*0Sstevel@tonic-gate 	} else
985*0Sstevel@tonic-gate #endif
986*0Sstevel@tonic-gate 	{
987*0Sstevel@tonic-gate 		cnt = ((ttymux_assocs_t *)asl)->ttymux_nlinks;
988*0Sstevel@tonic-gate 		sz = cnt * sizeof (ttymux_assoc_t);
989*0Sstevel@tonic-gate 		uaddr = (void *)((ttymux_assocs_t *)asl)->ttymux_assocs;
990*0Sstevel@tonic-gate 	}
991*0Sstevel@tonic-gate 	if ((nmp = sm_allocb(sz, BPRI_MED)) == NULL) {
992*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCNAK;
993*0Sstevel@tonic-gate 		iobp->ioc_error = EINVAL;
994*0Sstevel@tonic-gate 		return (EAGAIN);
995*0Sstevel@tonic-gate 	}
996*0Sstevel@tonic-gate 
997*0Sstevel@tonic-gate 	sm_dbg('Y', ("TTYMUX_LIST: cnt %d sz %d uaddr 0x%p\n", cnt, sz, uaddr));
998*0Sstevel@tonic-gate 
999*0Sstevel@tonic-gate 	iobp->ioc_rval = 0;
1000*0Sstevel@tonic-gate 
1001*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1002*0Sstevel@tonic-gate 	if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
1003*0Sstevel@tonic-gate 		ttymux_assoc32_t	*assoc;
1004*0Sstevel@tonic-gate 
1005*0Sstevel@tonic-gate 		sm_dbg('Y', ("!Native: %d structures\n", cnt));
1006*0Sstevel@tonic-gate 		assoc = (ttymux_assoc32_t *)nmp->b_rptr;
1007*0Sstevel@tonic-gate 
1008*0Sstevel@tonic-gate 		for (unit = 0;
1009*0Sstevel@tonic-gate 		    unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit));
1010*0Sstevel@tonic-gate 		    unit++) {
1011*0Sstevel@tonic-gate 			if (lqi->sm_linkid != 0) {
1012*0Sstevel@tonic-gate 				if (cnt-- == 0)
1013*0Sstevel@tonic-gate 					break;
1014*0Sstevel@tonic-gate 				LQI2ASSOC32(assoc, lqi);
1015*0Sstevel@tonic-gate 				assoc++;
1016*0Sstevel@tonic-gate 				iobp->ioc_rval += 1;
1017*0Sstevel@tonic-gate 			}
1018*0Sstevel@tonic-gate 		}
1019*0Sstevel@tonic-gate 		if (cnt > 0) {
1020*0Sstevel@tonic-gate 			/* see if there are unconfigured consoles */
1021*0Sstevel@tonic-gate 			iobp->ioc_rval +=
1022*0Sstevel@tonic-gate 			    get_unconfigured_consoles32(sm_ssp->sm_ms, assoc);
1023*0Sstevel@tonic-gate 			sm_dbg('I', ("%d unconfigured consoles\n",
1024*0Sstevel@tonic-gate 			    iobp->ioc_rval));
1025*0Sstevel@tonic-gate 		} else {
1026*0Sstevel@tonic-gate 			sm_dbg('I', ("no more space in user addr\n"));
1027*0Sstevel@tonic-gate 		}
1028*0Sstevel@tonic-gate 		((ttymux_assocs32_t *)asl)->ttymux32_nlinks = iobp->ioc_rval;
1029*0Sstevel@tonic-gate 	} else
1030*0Sstevel@tonic-gate #endif
1031*0Sstevel@tonic-gate 	{
1032*0Sstevel@tonic-gate 		ttymux_assoc_t	*assoc;
1033*0Sstevel@tonic-gate 
1034*0Sstevel@tonic-gate 		sm_dbg('Y', ("!Native: %d structures\n", cnt));
1035*0Sstevel@tonic-gate 		assoc = (ttymux_assoc_t *)nmp->b_wptr;
1036*0Sstevel@tonic-gate 
1037*0Sstevel@tonic-gate 		for (unit = 0;
1038*0Sstevel@tonic-gate 		    unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit));
1039*0Sstevel@tonic-gate 		    unit++) {
1040*0Sstevel@tonic-gate 			if (lqi->sm_linkid != 0) {
1041*0Sstevel@tonic-gate 				if (cnt-- == 0)
1042*0Sstevel@tonic-gate 					break;
1043*0Sstevel@tonic-gate 				LQI2ASSOC(assoc, lqi);
1044*0Sstevel@tonic-gate 				assoc++;
1045*0Sstevel@tonic-gate 				iobp->ioc_rval += 1;
1046*0Sstevel@tonic-gate 			}
1047*0Sstevel@tonic-gate 		}
1048*0Sstevel@tonic-gate 		if (cnt > 0) {
1049*0Sstevel@tonic-gate 			/* see if there are unconfigured consoles */
1050*0Sstevel@tonic-gate 			iobp->ioc_rval +=
1051*0Sstevel@tonic-gate 			    get_unconfigured_consoles(sm_ssp->sm_ms, assoc);
1052*0Sstevel@tonic-gate 			sm_dbg('I', ("%d unconfigured consoles\n",
1053*0Sstevel@tonic-gate 			    iobp->ioc_rval));
1054*0Sstevel@tonic-gate 		} else {
1055*0Sstevel@tonic-gate 			sm_dbg('I', ("no more space in user addr\n"));
1056*0Sstevel@tonic-gate 		}
1057*0Sstevel@tonic-gate 		((ttymux_assocs_t *)asl)->ttymux_nlinks = iobp->ioc_rval;
1058*0Sstevel@tonic-gate 	}
1059*0Sstevel@tonic-gate 
1060*0Sstevel@tonic-gate 	cqp = (struct copyreq *)mp->b_rptr;
1061*0Sstevel@tonic-gate 	cqp->cq_addr = uaddr;
1062*0Sstevel@tonic-gate 	cqp->cq_size = sz;
1063*0Sstevel@tonic-gate 	cqp->cq_flag = 0;
1064*0Sstevel@tonic-gate 	cqp->cq_private = mp->b_cont;
1065*0Sstevel@tonic-gate 	mp->b_cont = nmp;
1066*0Sstevel@tonic-gate 	nmp->b_wptr = nmp->b_rptr + sz;
1067*0Sstevel@tonic-gate 
1068*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_COPYOUT;
1069*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
1070*0Sstevel@tonic-gate 
1071*0Sstevel@tonic-gate 	return (0);
1072*0Sstevel@tonic-gate }
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate /*
1075*0Sstevel@tonic-gate  * Process a TTYMUX_CONSDEV ioctl.
1076*0Sstevel@tonic-gate  */
1077*0Sstevel@tonic-gate static int
1078*0Sstevel@tonic-gate ttymux_console_ioctl(mblk_t *mp)
1079*0Sstevel@tonic-gate {
1080*0Sstevel@tonic-gate 	struct iocblk *iobp = (struct iocblk *)mp->b_rptr;
1081*0Sstevel@tonic-gate 	int	err = EINVAL;
1082*0Sstevel@tonic-gate 
1083*0Sstevel@tonic-gate 	sm_dbg('I', ("ttymux_console_ioctl:\n"));
1084*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1085*0Sstevel@tonic-gate 	if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
1086*0Sstevel@tonic-gate 		if (mp->b_cont && iobp->ioc_count >= sizeof (dev32_t)) {
1087*0Sstevel@tonic-gate 			dev32_t dev;
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 			(void) cmpldev(&dev, rconsdev);
1090*0Sstevel@tonic-gate 
1091*0Sstevel@tonic-gate 			*(dev32_t *)mp->b_cont->b_rptr = dev;
1092*0Sstevel@tonic-gate 			mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (dev);
1093*0Sstevel@tonic-gate 			iobp->ioc_count = sizeof (dev);
1094*0Sstevel@tonic-gate 			err = 0;
1095*0Sstevel@tonic-gate 		} else {
1096*0Sstevel@tonic-gate 			sm_dbg('I', ("TTYMUX_CONSDEV: b_cont 0x%p count %d\n",
1097*0Sstevel@tonic-gate 			    mp->b_cont, iobp->ioc_count));
1098*0Sstevel@tonic-gate 		}
1099*0Sstevel@tonic-gate 	} else
1100*0Sstevel@tonic-gate #endif
1101*0Sstevel@tonic-gate 	if (mp->b_cont && iobp->ioc_count >= sizeof (dev_t)) {
1102*0Sstevel@tonic-gate 		*(dev_t *)mp->b_cont->b_rptr = rconsdev;
1103*0Sstevel@tonic-gate 		mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (rconsdev);
1104*0Sstevel@tonic-gate 		iobp->ioc_count = sizeof (rconsdev);
1105*0Sstevel@tonic-gate 		err = 0;
1106*0Sstevel@tonic-gate 	}
1107*0Sstevel@tonic-gate 	return (err);
1108*0Sstevel@tonic-gate }
1109*0Sstevel@tonic-gate 
1110*0Sstevel@tonic-gate /*
1111*0Sstevel@tonic-gate  * Process a ioctl relating to aborting on the console.
1112*0Sstevel@tonic-gate  */
1113*0Sstevel@tonic-gate int
1114*0Sstevel@tonic-gate ttymux_abort_ioctl(mblk_t *mp)
1115*0Sstevel@tonic-gate {
1116*0Sstevel@tonic-gate 	struct iocblk	*iobp;
1117*0Sstevel@tonic-gate 	int		cmd, err = 0;
1118*0Sstevel@tonic-gate 	sm_lqi_t		*lqi;
1119*0Sstevel@tonic-gate 	ttymux_abort_t	*abreq;
1120*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1121*0Sstevel@tonic-gate 	struct ttymux_abort32 {
1122*0Sstevel@tonic-gate 		dev32_t			ldev;
1123*0Sstevel@tonic-gate 		enum ttymux_break_type  method;
1124*0Sstevel@tonic-gate 		uint32_t		enable;
1125*0Sstevel@tonic-gate 	} *abreq32;
1126*0Sstevel@tonic-gate #endif
1127*0Sstevel@tonic-gate 	dev_t			ldev;
1128*0Sstevel@tonic-gate 	enum ttymux_break_type  method;
1129*0Sstevel@tonic-gate 	uint_t			enable;
1130*0Sstevel@tonic-gate 
1131*0Sstevel@tonic-gate 	iobp = (struct iocblk *)mp->b_rptr;
1132*0Sstevel@tonic-gate 	cmd = iobp->ioc_cmd;
1133*0Sstevel@tonic-gate 
1134*0Sstevel@tonic-gate 	iobp->ioc_error = 0;
1135*0Sstevel@tonic-gate 	iobp->ioc_rval = 0;
1136*0Sstevel@tonic-gate 	sm_dbg('I', ("ttymux_abort_ioctl:\n"));
1137*0Sstevel@tonic-gate 	switch (cmd) {
1138*0Sstevel@tonic-gate 	case CONSSETABORTENABLE:
1139*0Sstevel@tonic-gate 		lqi = (sm_ssp->sm_lconsole) ? sm_ssp->sm_lconsole->sm_lqs : 0;
1140*0Sstevel@tonic-gate 		enable = (*(intptr_t *)mp->b_cont->b_rptr) ? 1 : 0;
1141*0Sstevel@tonic-gate 		sm_ssp->sm_ctrla_abort_on = sm_ssp->sm_break_abort_on = enable;
1142*0Sstevel@tonic-gate 		for (; lqi != 0; lqi = lqi->sm_nlqi) {
1143*0Sstevel@tonic-gate 			lqi->sm_ctrla_abort_on = enable;
1144*0Sstevel@tonic-gate 			lqi->sm_break_abort_on = enable;
1145*0Sstevel@tonic-gate 		}
1146*0Sstevel@tonic-gate 		break;
1147*0Sstevel@tonic-gate 	case CONSGETABORTENABLE:
1148*0Sstevel@tonic-gate 		if (mp->b_cont == 0 || iobp->ioc_count < sizeof (intptr_t)) {
1149*0Sstevel@tonic-gate 			iobp->ioc_error = EINVAL;
1150*0Sstevel@tonic-gate 			iobp->ioc_rval = -1;
1151*0Sstevel@tonic-gate 		} else {
1152*0Sstevel@tonic-gate 			*(intptr_t *)mp->b_cont->b_rptr =
1153*0Sstevel@tonic-gate 			    (sm_ssp->sm_ctrla_abort_on ||
1154*0Sstevel@tonic-gate 			    sm_ssp->sm_break_abort_on);
1155*0Sstevel@tonic-gate 			mp->b_cont->b_wptr =
1156*0Sstevel@tonic-gate 				mp->b_cont->b_rptr + sizeof (intptr_t);
1157*0Sstevel@tonic-gate 			iobp->ioc_count = sizeof (intptr_t);
1158*0Sstevel@tonic-gate 		}
1159*0Sstevel@tonic-gate 		break;
1160*0Sstevel@tonic-gate 	case TTYMUX_GETABORTSTR:
1161*0Sstevel@tonic-gate 
1162*0Sstevel@tonic-gate 		if (iobp->ioc_count < strlen(sm_ssp->sm_abs) + 1 ||
1163*0Sstevel@tonic-gate 		    mp->b_cont == 0 ||
1164*0Sstevel@tonic-gate 		    mp->b_cont->b_cont) {
1165*0Sstevel@tonic-gate 			iobp->ioc_error = EINVAL;
1166*0Sstevel@tonic-gate 			iobp->ioc_rval = -1;
1167*0Sstevel@tonic-gate 		} else {
1168*0Sstevel@tonic-gate 			(void) strcpy((char *)mp->b_cont->b_rptr,
1169*0Sstevel@tonic-gate 					sm_ssp->sm_abs);
1170*0Sstevel@tonic-gate 			iobp->ioc_count = strlen(sm_ssp->sm_abs) + 1;
1171*0Sstevel@tonic-gate 			mp->b_cont->b_wptr =
1172*0Sstevel@tonic-gate 				mp->b_cont->b_rptr + iobp->ioc_count;
1173*0Sstevel@tonic-gate 		}
1174*0Sstevel@tonic-gate 		break;
1175*0Sstevel@tonic-gate 	case TTYMUX_GETABORT:
1176*0Sstevel@tonic-gate 	case TTYMUX_SETABORT:
1177*0Sstevel@tonic-gate 
1178*0Sstevel@tonic-gate 		lqi = 0;
1179*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1180*0Sstevel@tonic-gate 		if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
1181*0Sstevel@tonic-gate 			if (iobp->ioc_count < sizeof (*abreq32) ||
1182*0Sstevel@tonic-gate 			    mp->b_cont == 0) {
1183*0Sstevel@tonic-gate 				err = EINVAL;
1184*0Sstevel@tonic-gate 			} else {
1185*0Sstevel@tonic-gate 				abreq32 = (struct ttymux_abort32 *)
1186*0Sstevel@tonic-gate 				    mp->b_cont->b_rptr;
1187*0Sstevel@tonic-gate 				ldev = expldev(abreq32->ldev);
1188*0Sstevel@tonic-gate 				method = abreq32->method;
1189*0Sstevel@tonic-gate 				enable = (uint_t)abreq32->enable;
1190*0Sstevel@tonic-gate 				iobp->ioc_count = sizeof (*abreq32);
1191*0Sstevel@tonic-gate 			}
1192*0Sstevel@tonic-gate 		} else
1193*0Sstevel@tonic-gate #endif
1194*0Sstevel@tonic-gate 		if (iobp->ioc_count < sizeof (*abreq) ||
1195*0Sstevel@tonic-gate 		    mp->b_cont == 0) {
1196*0Sstevel@tonic-gate 			err = EINVAL;
1197*0Sstevel@tonic-gate 		} else {
1198*0Sstevel@tonic-gate 			abreq = (ttymux_abort_t *)mp->b_cont->b_rptr;
1199*0Sstevel@tonic-gate 			ldev = abreq->ttymux_ldev;
1200*0Sstevel@tonic-gate 			method = abreq->ttymux_method;
1201*0Sstevel@tonic-gate 			enable = abreq->ttymux_enable;
1202*0Sstevel@tonic-gate 			iobp->ioc_count = sizeof (*abreq);
1203*0Sstevel@tonic-gate 		}
1204*0Sstevel@tonic-gate 
1205*0Sstevel@tonic-gate 		if (err != 0) {
1206*0Sstevel@tonic-gate 			iobp->ioc_rval = -1;
1207*0Sstevel@tonic-gate 			return ((iobp->ioc_error = err));
1208*0Sstevel@tonic-gate 		}
1209*0Sstevel@tonic-gate 
1210*0Sstevel@tonic-gate 		sm_dbg('Y', ("ttymux_abort_ioctl: type %d how %d ldev %d:%d\n",
1211*0Sstevel@tonic-gate 		    method, enable, getmajor(ldev), getminor(ldev)));
1212*0Sstevel@tonic-gate 
1213*0Sstevel@tonic-gate 		lqi = get_lqi_bydevt(ldev);
1214*0Sstevel@tonic-gate 		if (ldev != NODEV && lqi == 0) {
1215*0Sstevel@tonic-gate 			err = ENOLINK;
1216*0Sstevel@tonic-gate 		} else if (cmd == TTYMUX_GETABORT && lqi == 0) {
1217*0Sstevel@tonic-gate 			err = ENODEV;
1218*0Sstevel@tonic-gate 		} else if (cmd == TTYMUX_GETABORT) {
1219*0Sstevel@tonic-gate 			if (lqi->sm_break_abort_on == 0 &&
1220*0Sstevel@tonic-gate 			    lqi->sm_ctrla_abort_on == 0) {
1221*0Sstevel@tonic-gate 				method = SOFTHARD_BREAK;
1222*0Sstevel@tonic-gate 				enable = 0;
1223*0Sstevel@tonic-gate 			} else {
1224*0Sstevel@tonic-gate 				enable = 1;
1225*0Sstevel@tonic-gate 				if (lqi->sm_break_abort_on == 0)
1226*0Sstevel@tonic-gate 					method = SOFTWARE_BREAK;
1227*0Sstevel@tonic-gate 				else if (lqi->sm_ctrla_abort_on == 0)
1228*0Sstevel@tonic-gate 					method = HARDWARE_BREAK;
1229*0Sstevel@tonic-gate 				else
1230*0Sstevel@tonic-gate 					method = SOFTHARD_BREAK;
1231*0Sstevel@tonic-gate 			}
1232*0Sstevel@tonic-gate 
1233*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1234*0Sstevel@tonic-gate 			if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) {
1235*0Sstevel@tonic-gate 				abreq32->method = method;
1236*0Sstevel@tonic-gate 				abreq32->enable = (uint32_t)enable;
1237*0Sstevel@tonic-gate 			} else
1238*0Sstevel@tonic-gate #endif
1239*0Sstevel@tonic-gate 			{
1240*0Sstevel@tonic-gate 				abreq->ttymux_method = method;
1241*0Sstevel@tonic-gate 				abreq->ttymux_enable = enable;
1242*0Sstevel@tonic-gate 			}
1243*0Sstevel@tonic-gate 		} else {
1244*0Sstevel@tonic-gate 			iobp->ioc_count = 0;
1245*0Sstevel@tonic-gate 			sm_dbg('I', ("lqi is 0x%p\n", lqi));
1246*0Sstevel@tonic-gate 			if (lqi == 0) {
1247*0Sstevel@tonic-gate 				if (method == HARDWARE_BREAK)
1248*0Sstevel@tonic-gate 					sm_ssp->sm_break_abort_on = enable;
1249*0Sstevel@tonic-gate 				else if (method == SOFTWARE_BREAK)
1250*0Sstevel@tonic-gate 					sm_ssp->sm_ctrla_abort_on = enable;
1251*0Sstevel@tonic-gate 				else if (method == SOFTHARD_BREAK) {
1252*0Sstevel@tonic-gate 					sm_ssp->sm_break_abort_on = enable;
1253*0Sstevel@tonic-gate 					sm_ssp->sm_ctrla_abort_on = enable;
1254*0Sstevel@tonic-gate 				} else {
1255*0Sstevel@tonic-gate 					sm_dbg('I', ("%d - invalid\n", method));
1256*0Sstevel@tonic-gate 					iobp->ioc_rval = -1;
1257*0Sstevel@tonic-gate 					return ((iobp->ioc_error = EINVAL));
1258*0Sstevel@tonic-gate 				}
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate 				if (sm_ssp->sm_lconsole) {
1261*0Sstevel@tonic-gate 					sm_dbg('I', ("lconsole 0x%p (0x%p)\n",
1262*0Sstevel@tonic-gate 					    sm_ssp->sm_lconsole,
1263*0Sstevel@tonic-gate 					    sm_ssp->sm_lconsole->sm_lqs));
1264*0Sstevel@tonic-gate 				} else {
1265*0Sstevel@tonic-gate 					sm_dbg('I', ("lconsole is null\n"));
1266*0Sstevel@tonic-gate 				}
1267*0Sstevel@tonic-gate 
1268*0Sstevel@tonic-gate 				lqi = (sm_ssp->sm_lconsole) ?
1269*0Sstevel@tonic-gate 				    sm_ssp->sm_lconsole->sm_lqs : 0;
1270*0Sstevel@tonic-gate 			}
1271*0Sstevel@tonic-gate 			while (lqi) {
1272*0Sstevel@tonic-gate 				if (method == HARDWARE_BREAK)
1273*0Sstevel@tonic-gate 					lqi->sm_break_abort_on = enable;
1274*0Sstevel@tonic-gate 				else if (method == SOFTWARE_BREAK)
1275*0Sstevel@tonic-gate 					lqi->sm_ctrla_abort_on = enable;
1276*0Sstevel@tonic-gate 				else if (method == SOFTHARD_BREAK) {
1277*0Sstevel@tonic-gate 					lqi->sm_break_abort_on = enable;
1278*0Sstevel@tonic-gate 					lqi->sm_ctrla_abort_on = enable;
1279*0Sstevel@tonic-gate 				} else {
1280*0Sstevel@tonic-gate 					sm_dbg('I', ("%d: invalid\n", method));
1281*0Sstevel@tonic-gate 					iobp->ioc_rval = -1;
1282*0Sstevel@tonic-gate 					return ((iobp->ioc_error = EINVAL));
1283*0Sstevel@tonic-gate 				}
1284*0Sstevel@tonic-gate 
1285*0Sstevel@tonic-gate 				lqi = (ldev == NODEV) ? lqi->sm_nlqi : 0;
1286*0Sstevel@tonic-gate 			}
1287*0Sstevel@tonic-gate 		}
1288*0Sstevel@tonic-gate 		iobp->ioc_rval = err ? -1 : 0;
1289*0Sstevel@tonic-gate 		iobp->ioc_error = err;
1290*0Sstevel@tonic-gate 		break;
1291*0Sstevel@tonic-gate 	default:
1292*0Sstevel@tonic-gate 		iobp->ioc_rval = -1;
1293*0Sstevel@tonic-gate 		iobp->ioc_error = EINVAL;
1294*0Sstevel@tonic-gate 	}
1295*0Sstevel@tonic-gate 	return (iobp->ioc_error);
1296*0Sstevel@tonic-gate }
1297*0Sstevel@tonic-gate 
1298*0Sstevel@tonic-gate /*
1299*0Sstevel@tonic-gate  * Process ioctls specific to the ttymux driver.
1300*0Sstevel@tonic-gate  */
1301*0Sstevel@tonic-gate /*ARGSUSED*/
1302*0Sstevel@tonic-gate int
1303*0Sstevel@tonic-gate sm_ioctl_cmd(sm_uqi_t *uqi, mblk_t *mp)
1304*0Sstevel@tonic-gate {
1305*0Sstevel@tonic-gate 	struct iocblk *iobp = (struct iocblk *)mp->b_rptr;
1306*0Sstevel@tonic-gate 
1307*0Sstevel@tonic-gate 	iobp->ioc_rval = 0;
1308*0Sstevel@tonic-gate 
1309*0Sstevel@tonic-gate 	/*
1310*0Sstevel@tonic-gate 	 * This routine does not support transparent ioctls
1311*0Sstevel@tonic-gate 	 */
1312*0Sstevel@tonic-gate 	if (iobp->ioc_count == TRANSPARENT) {
1313*0Sstevel@tonic-gate 		sm_dbg('Y', ("sm_ioctl_cmd: unsupported ioctl\n"));
1314*0Sstevel@tonic-gate 		iobp->ioc_error = ENOTSUP;
1315*0Sstevel@tonic-gate 		DB_TYPE(mp) = M_IOCNAK;
1316*0Sstevel@tonic-gate 		if (mp->b_cont)
1317*0Sstevel@tonic-gate 			freemsg(unlinkb(mp));
1318*0Sstevel@tonic-gate 		return (ENOTSUP);
1319*0Sstevel@tonic-gate 	}
1320*0Sstevel@tonic-gate 
1321*0Sstevel@tonic-gate 	switch (iobp->ioc_cmd) {
1322*0Sstevel@tonic-gate 	case TTYMUX_CONSDEV:
1323*0Sstevel@tonic-gate 		iobp->ioc_error = ttymux_console_ioctl(mp);
1324*0Sstevel@tonic-gate 		break;
1325*0Sstevel@tonic-gate 	case TTYMUX_ASSOC:
1326*0Sstevel@tonic-gate 	case TTYMUX_DISASSOC:
1327*0Sstevel@tonic-gate 		iobp->ioc_error = ttymux_link_ioctl(mp);
1328*0Sstevel@tonic-gate 		break;
1329*0Sstevel@tonic-gate 	case TTYMUX_GETLINK:
1330*0Sstevel@tonic-gate 		iobp->ioc_error = ttymux_query_link_ioctl(mp);
1331*0Sstevel@tonic-gate 		break;
1332*0Sstevel@tonic-gate 	case TTYMUX_LIST:
1333*0Sstevel@tonic-gate 		return (ttymux_query_links_ioctl(mp));
1334*0Sstevel@tonic-gate 	case TTYMUX_SETCTL:
1335*0Sstevel@tonic-gate 	case TTYMUX_GETCTL:
1336*0Sstevel@tonic-gate 		iobp->ioc_error = ENOTSUP;
1337*0Sstevel@tonic-gate 		break;
1338*0Sstevel@tonic-gate 	case TTYMUX_GETABORTSTR:
1339*0Sstevel@tonic-gate 	case TTYMUX_SETABORT:
1340*0Sstevel@tonic-gate 	case TTYMUX_GETABORT:
1341*0Sstevel@tonic-gate 		iobp->ioc_error = ttymux_abort_ioctl(mp);
1342*0Sstevel@tonic-gate 		break;
1343*0Sstevel@tonic-gate 	default:
1344*0Sstevel@tonic-gate 		iobp->ioc_error = EINVAL;
1345*0Sstevel@tonic-gate 		break;
1346*0Sstevel@tonic-gate 	}
1347*0Sstevel@tonic-gate 
1348*0Sstevel@tonic-gate 	DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK;
1349*0Sstevel@tonic-gate 
1350*0Sstevel@tonic-gate 	if ((iobp->ioc_error || iobp->ioc_count == 0) && mp->b_cont)
1351*0Sstevel@tonic-gate 	    freemsg(unlinkb(mp));
1352*0Sstevel@tonic-gate 
1353*0Sstevel@tonic-gate 	sm_dbg('I', ("TTYMUX IOCTL: err %d rval %d count %d\n",
1354*0Sstevel@tonic-gate 	    iobp->ioc_error, iobp->ioc_rval, iobp->ioc_count));
1355*0Sstevel@tonic-gate 
1356*0Sstevel@tonic-gate 	return (iobp->ioc_error);
1357*0Sstevel@tonic-gate }
1358