10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*434Swnelson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * DESCRIPTION 300Sstevel@tonic-gate * 310Sstevel@tonic-gate * ttymux_ioctl - Handler for ttymux specific ioctl calls. 320Sstevel@tonic-gate * 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <sys/types.h> 360Sstevel@tonic-gate #include <sys/strsubr.h> 370Sstevel@tonic-gate #include <sys/strsun.h> 380Sstevel@tonic-gate #include <sys/errno.h> 390Sstevel@tonic-gate #include <sys/stat.h> 400Sstevel@tonic-gate #include <sys/kmem.h> 410Sstevel@tonic-gate #include <sys/ddi.h> 420Sstevel@tonic-gate #include <sys/termio.h> 430Sstevel@tonic-gate #include <sys/mkdev.h> 440Sstevel@tonic-gate #include <sys/sunddi.h> 450Sstevel@tonic-gate #include <sys/esunddi.h> 460Sstevel@tonic-gate #include <sys/consdev.h> 470Sstevel@tonic-gate #include <sys/promif.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate #include <sys/ttymux.h> 500Sstevel@tonic-gate #include "ttymux_impl.h" 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * Extern declarations 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate extern mblk_t *mkiocb(uint_t); 560Sstevel@tonic-gate extern int nulldev(); 570Sstevel@tonic-gate extern uintptr_t space_fetch(char *key); 580Sstevel@tonic-gate extern void prom_interpret(char *, uintptr_t, uintptr_t, uintptr_t, 590Sstevel@tonic-gate uintptr_t, uintptr_t); 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 620Sstevel@tonic-gate * Imported ttymux routines 630Sstevel@tonic-gate */ 640Sstevel@tonic-gate extern void sm_debug(char *, ...); 650Sstevel@tonic-gate extern void sm_log(char *, ...); 660Sstevel@tonic-gate extern sm_lqi_t *get_lqi_byid(int); 670Sstevel@tonic-gate extern sm_lqi_t *get_lqi_bydevt(dev_t); 680Sstevel@tonic-gate extern int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *); 690Sstevel@tonic-gate extern int sm_disassociate(int, sm_lqi_t *, ulong_t); 700Sstevel@tonic-gate 710Sstevel@tonic-gate /* 720Sstevel@tonic-gate * Exported ttymux routines 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate int ttymux_abort_ioctl(mblk_t *); 750Sstevel@tonic-gate int ttymux_device_init(sm_lqi_t *); 760Sstevel@tonic-gate int ttymux_device_fini(sm_lqi_t *); 770Sstevel@tonic-gate int sm_ioctl_cmd(sm_uqi_t *, mblk_t *); 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* 800Sstevel@tonic-gate * Imported ttymux variables 810Sstevel@tonic-gate */ 820Sstevel@tonic-gate extern sm_ss_t *sm_ssp; 830Sstevel@tonic-gate 840Sstevel@tonic-gate static int 850Sstevel@tonic-gate mblk2assoc(mblk_t *mp, ttymux_assoc_t *assoc) 860Sstevel@tonic-gate { 870Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 880Sstevel@tonic-gate 890Sstevel@tonic-gate sm_dbg('M', ("mblk2assoc:\n")); 900Sstevel@tonic-gate if (mp->b_cont == NULL) 910Sstevel@tonic-gate return (EINVAL); 920Sstevel@tonic-gate 930Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 940Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 950Sstevel@tonic-gate ttymux_assoc32_t *assoc32; 960Sstevel@tonic-gate 970Sstevel@tonic-gate sm_dbg('I', ("mblk2assoc: b_cont 0x%p count %d (sz %d)\n", 980Sstevel@tonic-gate mp->b_cont, iobp->ioc_count, sizeof (*assoc32))); 990Sstevel@tonic-gate 1000Sstevel@tonic-gate if (iobp->ioc_count < sizeof (ttymux_assoc32_t)) 1010Sstevel@tonic-gate return (EINVAL); 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; 1040Sstevel@tonic-gate assoc->ttymux_udev = expldev(assoc32->ttymux32_udev); 1050Sstevel@tonic-gate assoc->ttymux_ldev = expldev(assoc32->ttymux32_ldev); 1060Sstevel@tonic-gate assoc->ttymux_linkid = assoc32->ttymux32_linkid; 1070Sstevel@tonic-gate assoc->ttymux_tag = assoc32->ttymux32_tag; 1080Sstevel@tonic-gate assoc->ttymux_ioflag = assoc32->ttymux32_ioflag; 1090Sstevel@tonic-gate (void) strncpy(assoc->ttymux_path, assoc32->ttymux32_path, 1100Sstevel@tonic-gate MAXPATHLEN); 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate } else 1130Sstevel@tonic-gate #endif 1140Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*assoc)) { 1150Sstevel@tonic-gate return (EINVAL); 1160Sstevel@tonic-gate } else { 1170Sstevel@tonic-gate *assoc = *(ttymux_assoc_t *)mp->b_cont->b_rptr; 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate sm_dbg('M', ("mblk2assoc (%d): dev %d:%d not found\n", 1200Sstevel@tonic-gate assoc->ttymux_linkid, getmajor(assoc->ttymux_ldev), 1210Sstevel@tonic-gate getminor(assoc->ttymux_ldev))); 1220Sstevel@tonic-gate return (0); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* 1260Sstevel@tonic-gate * Given a device path return an OBP alias for it if it exists. 1270Sstevel@tonic-gate */ 1280Sstevel@tonic-gate static char * 1290Sstevel@tonic-gate val2alias(dnode_t node, char *path) 1300Sstevel@tonic-gate { 1310Sstevel@tonic-gate char *buf1; 1320Sstevel@tonic-gate char *buf2; 1330Sstevel@tonic-gate char *propname, *propval; 1340Sstevel@tonic-gate int proplen; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate if (node == OBP_BADNODE) 1370Sstevel@tonic-gate return (NULL); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate sm_dbg('A', ("Looking for an alias for: %s (len %d)\n", 1400Sstevel@tonic-gate path, strlen(path))); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * Ask for first property by passing a NULL string 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate buf1 = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP); 1460Sstevel@tonic-gate buf2 = kmem_zalloc(OBP_MAXPROPNAME, KM_SLEEP); 1470Sstevel@tonic-gate buf1[0] = '\0'; 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate while (propname = (char *)prom_nextprop(node, buf1, buf2)) { 1500Sstevel@tonic-gate if (strlen(propname) == 0) 1510Sstevel@tonic-gate break; /* end of prop list */ 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate (void) strcpy(buf1, propname); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate proplen = prom_getproplen(node, propname); 1560Sstevel@tonic-gate if (proplen == 0) 1570Sstevel@tonic-gate continue; 1580Sstevel@tonic-gate propval = kmem_zalloc(proplen + 1, KM_SLEEP); 1590Sstevel@tonic-gate (void) prom_getprop(node, propname, propval); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate if (strcmp(propval, path) == 0) { 1620Sstevel@tonic-gate kmem_free(propval, proplen + 1); 1630Sstevel@tonic-gate kmem_free(buf1, OBP_MAXPROPNAME); 1640Sstevel@tonic-gate sm_dbg('A', ("Alias is : %s\n", buf2)); 1650Sstevel@tonic-gate return (buf2); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate kmem_free(propval, proplen + 1); 1690Sstevel@tonic-gate bzero(buf2, OBP_MAXPROPNAME); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate kmem_free(buf1, OBP_MAXPROPNAME); 1730Sstevel@tonic-gate kmem_free(buf2, OBP_MAXPROPNAME); 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate return (NULL); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate /* 1790Sstevel@tonic-gate * Tell OBP that this device is now usable 1800Sstevel@tonic-gate */ 1810Sstevel@tonic-gate static void 1820Sstevel@tonic-gate enable_device(sm_mux_state_t *ms, sm_console_t *cn) 1830Sstevel@tonic-gate { 1840Sstevel@tonic-gate char *enb_str = "\" enable-device\" rot $call-method"; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if (!cn->sm_obp_con) 1870Sstevel@tonic-gate return; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate sm_dbg('A', ("ttymux: enabling %d:%d\n", 1900Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate if (cn->sm_i_ihdl != 0) 1930Sstevel@tonic-gate prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, 1940Sstevel@tonic-gate (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) 1970Sstevel@tonic-gate prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, 1980Sstevel@tonic-gate (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * Tell OBP that this device is no longer usable 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate static void 2050Sstevel@tonic-gate disable_device(sm_mux_state_t *ms, sm_console_t *cn) 2060Sstevel@tonic-gate { 2070Sstevel@tonic-gate char *dis_str = "\" disable-device\" rot $call-method"; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if (!cn->sm_obp_con) 2100Sstevel@tonic-gate return; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate sm_dbg('A', ("ttymux: disabling %d:%d\n", 2130Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate if (cn->sm_i_ihdl != 0) 2160Sstevel@tonic-gate prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, 2170Sstevel@tonic-gate (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); 2180Sstevel@tonic-gate if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) 2190Sstevel@tonic-gate prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, 2200Sstevel@tonic-gate (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate static void 2240Sstevel@tonic-gate device_init_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) 2250Sstevel@tonic-gate { 2260Sstevel@tonic-gate uint_t flags = 0; 2270Sstevel@tonic-gate dev_info_t *ldip; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate sm_dbg('I', ("device_init_impl:\n")); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if (plqi == NULL || cn == NULL) 2320Sstevel@tonic-gate return; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate flags = (uint_t)cn->sm_mode; 2350Sstevel@tonic-gate sm_dbg('I', ("device_init_impl: flgs %d con %d\n", flags, 2360Sstevel@tonic-gate cn->sm_obp_con)); 2370Sstevel@tonic-gate if (ldip = e_ddi_hold_devi_by_dev(cn->sm_dev, 0)) { 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* 2400Sstevel@tonic-gate * Indicate to the linked device that it is 2410Sstevel@tonic-gate * providing a multiplexed console. 2420Sstevel@tonic-gate */ 2430Sstevel@tonic-gate if (flags & (uint_t)FORINPUT) 2440Sstevel@tonic-gate (void) e_ddi_prop_create(cn->sm_dev, ldip, 2450Sstevel@tonic-gate DDI_PROP_CANSLEEP, "obp-input-console", 0, 0); 2460Sstevel@tonic-gate if (flags & (uint_t)FOROUTPUT) 2470Sstevel@tonic-gate (void) e_ddi_prop_create(cn->sm_dev, ldip, 2480Sstevel@tonic-gate DDI_PROP_CANSLEEP, "obp-output-console", 0, 0); 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate ddi_release_devi(ldip); 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate if (flags) { 2540Sstevel@tonic-gate plqi->sm_ioflag = flags; 2550Sstevel@tonic-gate if (cn->sm_obp_con) 2560Sstevel@tonic-gate plqi->sm_uqflags |= SM_OBPCNDEV; 2570Sstevel@tonic-gate plqi->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on; 2580Sstevel@tonic-gate plqi->sm_break_abort_on = sm_ssp->sm_break_abort_on; 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * Tell OBP that its ok to use this console 2630Sstevel@tonic-gate */ 2640Sstevel@tonic-gate enable_device(ms, cn); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate static void 2680Sstevel@tonic-gate device_fini_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) 2690Sstevel@tonic-gate { 2700Sstevel@tonic-gate dev_info_t *ldip; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate if (plqi == NULL || cn == NULL) 2730Sstevel@tonic-gate return; 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * Indicate to the linked device that it is no longer 2760Sstevel@tonic-gate * providing a multiplexed console. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate if (ldip = e_ddi_hold_devi_by_dev(plqi->sm_dev, 0)) { 2790Sstevel@tonic-gate if (plqi->sm_ioflag & (uint_t)FORINPUT) 2800Sstevel@tonic-gate (void) e_ddi_prop_remove(plqi->sm_dev, 2810Sstevel@tonic-gate ldip, "obp-input-console"); 2820Sstevel@tonic-gate if (plqi->sm_ioflag & (uint_t)FOROUTPUT) 2830Sstevel@tonic-gate (void) e_ddi_prop_remove(plqi->sm_dev, 2840Sstevel@tonic-gate ldip, "obp-output-console"); 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate ddi_release_devi(ldip); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate plqi->sm_ioflag = 0; 2890Sstevel@tonic-gate plqi->sm_uqflags &= ~SM_OBPCNDEV; 2900Sstevel@tonic-gate disable_device(ms, cn); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate static int 2940Sstevel@tonic-gate read_prop(dnode_t node, char *propname, char **propval) 2950Sstevel@tonic-gate { 2960Sstevel@tonic-gate int proplen = prom_getproplen(node, propname); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate if (proplen < 0) 2990Sstevel@tonic-gate return (proplen); 3000Sstevel@tonic-gate *propval = kmem_zalloc(proplen + 1, KM_SLEEP); 3010Sstevel@tonic-gate if (proplen > 0) 3020Sstevel@tonic-gate (void) prom_getprop(node, propname, *propval); 3030Sstevel@tonic-gate else 3040Sstevel@tonic-gate *propval = 0; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate return (proplen); 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate /* 3100Sstevel@tonic-gate * Parse a list of tokens 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate static char * 3130Sstevel@tonic-gate sm_strtok_r(char *p, char *sep, char **lasts) 3140Sstevel@tonic-gate { 3150Sstevel@tonic-gate char *e, *tok = NULL; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate if (p == 0 || *p == 0) 3180Sstevel@tonic-gate return (NULL); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate e = p + strlen(p); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate do { 3230Sstevel@tonic-gate if (strchr(sep, *p) != NULL) { 3240Sstevel@tonic-gate if (tok != NULL) { 3250Sstevel@tonic-gate *p = 0; 3260Sstevel@tonic-gate *lasts = p + 1; 3270Sstevel@tonic-gate return (tok); 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate } else if (tok == NULL) { 3300Sstevel@tonic-gate tok = p; 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate } while (++p < e); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate *lasts = NULL; 3350Sstevel@tonic-gate if (tok != NULL) 3360Sstevel@tonic-gate return (tok); 3370Sstevel@tonic-gate return (NULL); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* 3410Sstevel@tonic-gate * Add or remove an alias from a property list of aliases: 3420Sstevel@tonic-gate * path: an OBP device path 3430Sstevel@tonic-gate * pname: property name containing a space separated list of aliases 3440Sstevel@tonic-gate * append: if true include the alias for path in the property list 3450Sstevel@tonic-gate * otherwise remove the alias from the list. 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate static int 3480Sstevel@tonic-gate upd_config(boolean_t append, char *pname, char *path) 3490Sstevel@tonic-gate { 3500Sstevel@tonic-gate dnode_t onode, anode; 3510Sstevel@tonic-gate size_t plen; /* length of property name */ 3520Sstevel@tonic-gate char *pval; /* value of property */ 3530Sstevel@tonic-gate char *tok, *lasts; 3540Sstevel@tonic-gate char *aliases[TTYMUX_MAX_LINKS]; 3550Sstevel@tonic-gate size_t i, cnt, len; 3560Sstevel@tonic-gate boolean_t found; 3570Sstevel@tonic-gate char *nval, *alias = NULL; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate if ((anode = prom_alias_node()) == OBP_BADNODE || 3600Sstevel@tonic-gate (onode = prom_optionsnode()) == OBP_BADNODE) { 3610Sstevel@tonic-gate sm_dbg('I', ("upd_config: no alias or options node.\n")); 3620Sstevel@tonic-gate return (1); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate if ((plen = read_prop(onode, pname, &pval)) < 0) 3660Sstevel@tonic-gate return (1); 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate sm_dbg('I', ("upd_config: %s=%s (%s)\n", pname, pval, path)); 3690Sstevel@tonic-gate found = B_FALSE; 3700Sstevel@tonic-gate for (len = 0, cnt = 0, tok = sm_strtok_r(pval, " \t", &lasts); 3710Sstevel@tonic-gate tok != NULL && cnt < TTYMUX_MAX_LINKS; 3720Sstevel@tonic-gate tok = sm_strtok_r(lasts, " \t", &lasts)) { 3730Sstevel@tonic-gate char *aval; 3740Sstevel@tonic-gate size_t alen; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate if ((alen = read_prop(anode, tok, &aval)) < 0) 3770Sstevel@tonic-gate continue; 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate /* does this alias match the requested path */ 3800Sstevel@tonic-gate if (strcmp(aval, path) == 0 || 3810Sstevel@tonic-gate (strstr(path, aval) != NULL && 3820Sstevel@tonic-gate strchr(aval, ':') == NULL && strchr(path, ':') != NULL && 3830Sstevel@tonic-gate strcmp(strchr(path, ':'), ":a") == 0)) { 3840Sstevel@tonic-gate if (!found && append) { 3850Sstevel@tonic-gate kmem_free(aval, alen + 1); 3860Sstevel@tonic-gate goto out; 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate found = B_TRUE; 3890Sstevel@tonic-gate } else { 3900Sstevel@tonic-gate aliases[cnt++] = tok; 3910Sstevel@tonic-gate len += strlen(tok) + 1; 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate kmem_free(aval, alen + 1); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate sm_dbg('I', ("%d aliases\n", cnt)); 3970Sstevel@tonic-gate if (append) { 3980Sstevel@tonic-gate if (cnt + 1 == TTYMUX_MAX_LINKS) 3990Sstevel@tonic-gate goto out; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate if ((alias = val2alias(anode, path)) == NULL) { 4020Sstevel@tonic-gate char *mnode = strstr(path, ":a"); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate if (mnode != 0) { 4050Sstevel@tonic-gate *mnode = '\0'; 4060Sstevel@tonic-gate alias = val2alias(anode, path); 4070Sstevel@tonic-gate *mnode = ':'; 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate if (alias == NULL) { 4110Sstevel@tonic-gate sm_dbg('I', ("No alias for %s\n", path)); 4120Sstevel@tonic-gate goto out; 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate aliases[cnt++] = alias; 4150Sstevel@tonic-gate len += strlen(alias) + 1; 4160Sstevel@tonic-gate } else if (!found) { 4170Sstevel@tonic-gate goto out; 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate sm_dbg('I', ("%d aliases (len %d)\n", cnt, len)); 4210Sstevel@tonic-gate if (len == 0) 4220Sstevel@tonic-gate goto out; 4230Sstevel@tonic-gate ASSERT(len > 1 && cnt > 0); 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate nval = kmem_zalloc(len, KM_SLEEP); 4260Sstevel@tonic-gate for (i = 0; ; ) { 4270Sstevel@tonic-gate ASSERT(strlen(nval) + strlen(aliases[i]) + 1 <= len); 4280Sstevel@tonic-gate sm_dbg('I', ("alias %s\n", aliases[i])); 4290Sstevel@tonic-gate (void) strcat(nval, aliases[i]); 4300Sstevel@tonic-gate if (++i == cnt) 4310Sstevel@tonic-gate break; 4320Sstevel@tonic-gate (void) strcat(nval, " "); 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate sm_dbg('I', ("setprop: %s=%s (%d)\n", pname, nval, len)); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate (void) prom_setprop(onode, pname, nval, len); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate kmem_free(nval, len); 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate if (alias != NULL) 4420Sstevel@tonic-gate kmem_free(alias, OBP_MAXPROPNAME); 4430Sstevel@tonic-gate out: 4440Sstevel@tonic-gate sm_dbg('I', ("upd_config: returning.\n")); 4450Sstevel@tonic-gate kmem_free(pval, plen + 1); 4460Sstevel@tonic-gate return (0); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate /* 4500Sstevel@tonic-gate * 4510Sstevel@tonic-gate */ 4520Sstevel@tonic-gate static int 4530Sstevel@tonic-gate update_config(sm_mux_state_t *ms, char *path, io_mode_t mode, int cmd) 4540Sstevel@tonic-gate { 4550Sstevel@tonic-gate sm_dbg('I', ("update_config: path %s io %d\n", path ? path : "", mode)); 4560Sstevel@tonic-gate if (path == 0 || *path == 0) { 4570Sstevel@tonic-gate sm_dbg('I', ("update_config: EINVAL - no path\n")); 4580Sstevel@tonic-gate return (1); 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate if (prom_is_openprom() == 0) 4610Sstevel@tonic-gate return (0); 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate if ((mode & FORINPUT) && ms->sm_ialias != NULL) 4640Sstevel@tonic-gate (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_ialias, path); 4650Sstevel@tonic-gate if ((mode & FOROUTPUT) && ms->sm_oalias != NULL) 4660Sstevel@tonic-gate (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_oalias, path); 4670Sstevel@tonic-gate return (0); 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * Convert a dev_t to a device path 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate static char * 4740Sstevel@tonic-gate sm_di_path(dev_t dev) 4750Sstevel@tonic-gate { 4760Sstevel@tonic-gate char *p, *path; 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate if (dev == NODEV) 4790Sstevel@tonic-gate return (NULL); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate p = kmem_zalloc(MAXPATHLEN + 1, KM_SLEEP); 4820Sstevel@tonic-gate if (ddi_dev_pathname(dev, S_IFCHR, p) == DDI_SUCCESS) { 4830Sstevel@tonic-gate path = kmem_alloc(strlen(p) + 1, KM_SLEEP); 4840Sstevel@tonic-gate (void) strcpy(path, p); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate kmem_free(p, MAXPATHLEN + 1); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate return (path); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate static int 4920Sstevel@tonic-gate console_cmd(int cmd, ttymux_assoc_t *assoc) 4930Sstevel@tonic-gate { 4940Sstevel@tonic-gate sm_mux_state_t *ms; 4950Sstevel@tonic-gate sm_console_t *cn; 4960Sstevel@tonic-gate uint_t j; 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate sm_dbg('I', ("console_cmd ENTER: %s\n", cmd == TTYMUX_DISASSOC ? 4990Sstevel@tonic-gate "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate if (assoc->ttymux_ldev == NODEV && *assoc->ttymux_path != '/') { 5020Sstevel@tonic-gate sm_lqi_t *lqi = get_lqi_byid(assoc->ttymux_linkid); 5030Sstevel@tonic-gate if (lqi == 0 || lqi->sm_dev == NODEV) { 5040Sstevel@tonic-gate sm_dbg('I', ("console_cmd: no id link %d cmd %d\n", 5050Sstevel@tonic-gate assoc->ttymux_linkid, cmd)); 5060Sstevel@tonic-gate return (EINVAL); 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate assoc->ttymux_ldev = lqi->sm_dev; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate sm_dbg('I', ("console_cmd: path %s\n", assoc->ttymux_path)); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate if ((ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR)) == 0) { 5140Sstevel@tonic-gate sm_dbg('I', ("console_cmd: No muxstate\n")); 5150Sstevel@tonic-gate return (0); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate for (cn = ms->sm_cons_links, j = 0; 5210Sstevel@tonic-gate j < ms->sm_cons_cnt; cn++, j++) { 5220Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV && assoc->ttymux_ldev == 5230Sstevel@tonic-gate cn->sm_dev) { 5240Sstevel@tonic-gate break; 5250Sstevel@tonic-gate } else if (cn->sm_path != NULL && 5260Sstevel@tonic-gate strncmp(cn->sm_path, assoc->ttymux_path, MAXPATHLEN) == 0) { 5270Sstevel@tonic-gate break; 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate assoc->ttymux_path[MAXPATHLEN - 1] = 0; 5320Sstevel@tonic-gate if (cmd == TTYMUX_DISASSOC) { 5330Sstevel@tonic-gate if (j == ms->sm_cons_cnt) { 5340Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 5350Sstevel@tonic-gate return (0); 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate /* 5390Sstevel@tonic-gate * Disable the console in OBP and then delete this console 5400Sstevel@tonic-gate * this console - note that this also deletes OBP 5410Sstevel@tonic-gate * information - i.e. once it is disassociated it cannot 5420Sstevel@tonic-gate * be reused as an OBP console - roll on polled I/O! 5430Sstevel@tonic-gate */ 5440Sstevel@tonic-gate sm_dbg('I', ("console_cmd: cleaning up\n")); 5450Sstevel@tonic-gate device_fini_impl(ms, cn, get_lqi_bydevt(assoc->ttymux_ldev)); 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate if (cn->sm_path == NULL) { 5480Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV) 5490Sstevel@tonic-gate cn->sm_path = sm_di_path(assoc->ttymux_ldev); 5500Sstevel@tonic-gate else 5510Sstevel@tonic-gate (void) update_config(ms, assoc->ttymux_path, 5520Sstevel@tonic-gate assoc->ttymux_ioflag, cmd); 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate if (cn->sm_path) { 5550Sstevel@tonic-gate (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); 5560Sstevel@tonic-gate kmem_free(cn->sm_path, strlen(cn->sm_path) + 1); 5570Sstevel@tonic-gate cn->sm_path = NULL; 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate ms->sm_cons_cnt -= 1; 5600Sstevel@tonic-gate if (ms->sm_cons_cnt > 0) 5610Sstevel@tonic-gate *cn = ms->sm_cons_links[ms->sm_cons_cnt]; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate sm_dbg('I', ("console_cmd: console %d removed (cnt %d)\n", 5640Sstevel@tonic-gate j, ms->sm_cons_cnt)); 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate } else if (cmd == TTYMUX_ASSOC) { 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate if (j == ms->sm_cons_cnt) { 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate if (j == TTYMUX_MAX_LINKS) { 5710Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 5720Sstevel@tonic-gate return (ENOMEM); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate ms->sm_cons_cnt += 1; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate bzero((caddr_t)cn, sizeof (*cn)); 5780Sstevel@tonic-gate cn->sm_dev = assoc->ttymux_ldev; 5790Sstevel@tonic-gate cn->sm_muxid = assoc->ttymux_linkid; 5800Sstevel@tonic-gate cn->sm_mode = assoc->ttymux_ioflag; 5810Sstevel@tonic-gate device_init_impl(ms, cn, 5820Sstevel@tonic-gate get_lqi_bydevt(assoc->ttymux_ldev)); 5830Sstevel@tonic-gate } else { 5840Sstevel@tonic-gate cn->sm_dev = assoc->ttymux_ldev; 5850Sstevel@tonic-gate cn->sm_muxid = assoc->ttymux_linkid; 5860Sstevel@tonic-gate cn->sm_mode = assoc->ttymux_ioflag; 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV) { 5900Sstevel@tonic-gate cn->sm_path = sm_di_path(assoc->ttymux_ldev); 5910Sstevel@tonic-gate } else { 5920Sstevel@tonic-gate cn->sm_path = kmem_alloc(strlen(assoc->ttymux_path) + 1, 5930Sstevel@tonic-gate KM_SLEEP); 5940Sstevel@tonic-gate (void) strcpy(cn->sm_path, assoc->ttymux_path); 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate if (cn->sm_path != NULL) 5970Sstevel@tonic-gate (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); 5980Sstevel@tonic-gate else 5990Sstevel@tonic-gate sm_dbg('I', ("console_cmd: ASSOC No path info")); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6020Sstevel@tonic-gate sm_dbg('I', ("console_cmd EXIT: %s\n", cmd == TTYMUX_DISASSOC ? 6030Sstevel@tonic-gate "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); 6040Sstevel@tonic-gate return (0); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate static int 6080Sstevel@tonic-gate get_unconfigured_consoles(sm_mux_state_t *ms, ttymux_assoc_t *a) 6090Sstevel@tonic-gate { 6100Sstevel@tonic-gate sm_console_t *cn; 6110Sstevel@tonic-gate int j, cnt; 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate if (ms == 0) 6140Sstevel@tonic-gate return (0); 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6170Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6180Sstevel@tonic-gate cn++, j++) { 6190Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { 6200Sstevel@tonic-gate a->ttymux_linkid = cn->sm_muxid; 6210Sstevel@tonic-gate a->ttymux_tag = (uint_t)0; 6220Sstevel@tonic-gate a->ttymux_ioflag = cn->sm_mode; 6230Sstevel@tonic-gate a->ttymux_udev = cn->sm_mode & FORINPUT ? 6240Sstevel@tonic-gate ms->sm_cons_stdin.sm_dev : 6250Sstevel@tonic-gate ms->sm_cons_stdout.sm_dev; 6260Sstevel@tonic-gate a->ttymux_ldev = NODEV; 6270Sstevel@tonic-gate (void) strncpy(a->ttymux_path, cn->sm_path, MAXPATHLEN); 6280Sstevel@tonic-gate cnt++; 6290Sstevel@tonic-gate a++; 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6330Sstevel@tonic-gate return (cnt); 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 6370Sstevel@tonic-gate /* 6380Sstevel@tonic-gate * Look for any consoles that are not currently plumbed under the multiplexer. 6390Sstevel@tonic-gate */ 6400Sstevel@tonic-gate static int 6410Sstevel@tonic-gate get_unconfigured_consoles32(sm_mux_state_t *ms, ttymux_assoc32_t *a) 6420Sstevel@tonic-gate { 6430Sstevel@tonic-gate sm_console_t *cn; 6440Sstevel@tonic-gate int j, cnt; 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate if (ms == 0) 6470Sstevel@tonic-gate return (0); 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6500Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6510Sstevel@tonic-gate cn++, j++) { 6520Sstevel@tonic-gate sm_dbg('I', ("get_unconfigured_consoles: check %s (%d:%d)", 6530Sstevel@tonic-gate cn->sm_path ? cn->sm_path : "NULL", 6540Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 6550Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { 6560Sstevel@tonic-gate a->ttymux32_linkid = 0; 6570Sstevel@tonic-gate a->ttymux32_tag = (uint32_t)0; 6580Sstevel@tonic-gate a->ttymux32_ioflag = (uint32_t)cn->sm_mode; 6590Sstevel@tonic-gate a->ttymux32_ldev = NODEV32; 6600Sstevel@tonic-gate (void) cmpldev(&a->ttymux32_udev, cn->sm_mode & 6610Sstevel@tonic-gate FORINPUT ? ms->sm_cons_stdin.sm_dev : 6620Sstevel@tonic-gate ms->sm_cons_stdout.sm_dev); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate (void) strncpy(a->ttymux32_path, cn->sm_path, 6650Sstevel@tonic-gate MAXPATHLEN); 6660Sstevel@tonic-gate cnt++; 6670Sstevel@tonic-gate a++; 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6710Sstevel@tonic-gate return (cnt); 6720Sstevel@tonic-gate } 6730Sstevel@tonic-gate #endif 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate static int 6760Sstevel@tonic-gate count_unconfigured_consoles(sm_mux_state_t *ms) 6770Sstevel@tonic-gate { 6780Sstevel@tonic-gate sm_console_t *cn; 6790Sstevel@tonic-gate int j, cnt; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate if (ms == 0) 6820Sstevel@tonic-gate return (0); 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6850Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6860Sstevel@tonic-gate cn++, j++) { 6870Sstevel@tonic-gate sm_dbg('I', ("cnt_unconfigured_consoles: check %s (%d:%d)", 6880Sstevel@tonic-gate cn->sm_path ? cn->sm_path : "NULL", 6890Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 6900Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) 6910Sstevel@tonic-gate cnt++; 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6940Sstevel@tonic-gate return (cnt); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate /* 6980Sstevel@tonic-gate * Exported interfaces 6990Sstevel@tonic-gate */ 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate /* 7020Sstevel@tonic-gate * A console device is no longer associated. 7030Sstevel@tonic-gate */ 7040Sstevel@tonic-gate int 7050Sstevel@tonic-gate ttymux_device_fini(sm_lqi_t *plqi) 7060Sstevel@tonic-gate { 7070Sstevel@tonic-gate int j; 7080Sstevel@tonic-gate sm_mux_state_t *ms; 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate if (plqi == NULL || ms == NULL) 7130Sstevel@tonic-gate return (0); 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate for (j = 0; j < ms->sm_cons_cnt; j++) { 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate device_fini_impl(ms, &ms->sm_cons_links[j], plqi); 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7240Sstevel@tonic-gate return (0); 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate return (1); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate /* 7330Sstevel@tonic-gate * A console device is being introduced. 7340Sstevel@tonic-gate */ 7350Sstevel@tonic-gate int 7360Sstevel@tonic-gate ttymux_device_init(sm_lqi_t *plqi) 7370Sstevel@tonic-gate { 7380Sstevel@tonic-gate int j; 7390Sstevel@tonic-gate sm_mux_state_t *ms; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate if (ms == NULL) 7440Sstevel@tonic-gate return (0); 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate for (j = 0; j < ms->sm_cons_cnt; j++) { 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate device_init_impl(ms, &ms->sm_cons_links[j], plqi); 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7550Sstevel@tonic-gate return (0); 7560Sstevel@tonic-gate } 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7590Sstevel@tonic-gate return (1); 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate /* 7630Sstevel@tonic-gate * Process a TTYMUX_ASSOCIATE or TTYMUX_DISASSOCIATE ioctl. 7640Sstevel@tonic-gate */ 7650Sstevel@tonic-gate static int 7660Sstevel@tonic-gate ttymux_link_ioctl(mblk_t *mp) 7670Sstevel@tonic-gate { 7680Sstevel@tonic-gate ttymux_assoc_t assoc; 7690Sstevel@tonic-gate int err; 7700Sstevel@tonic-gate sm_lqi_t *lqi; 7710Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 7720Sstevel@tonic-gate dev_t cidev, codev; 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate sm_dbg('I', ("ttymux_link_ioctl:\n")); 7750Sstevel@tonic-gate if ((err = mblk2assoc(mp, &assoc)) != 0) 7760Sstevel@tonic-gate return (err); 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate sm_dbg('I', ("uminor is %d\n", getminor(assoc.ttymux_udev))); 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate if (assoc.ttymux_udev == NODEV) 7810Sstevel@tonic-gate return (EINVAL); 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate err = 0; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL) { 7860Sstevel@tonic-gate if (assoc.ttymux_linkid < 0) 7870Sstevel@tonic-gate err = EINVAL; 7880Sstevel@tonic-gate else if ((lqi = get_lqi_byid(assoc.ttymux_linkid)) == 0) 7890Sstevel@tonic-gate err = ENOLINK; 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate if (sm_ssp->sm_ms) { 7930Sstevel@tonic-gate mutex_enter(&sm_ssp->sm_ms->sm_cons_mutex); 7940Sstevel@tonic-gate cidev = sm_ssp->sm_ms->sm_cons_stdin.sm_dev; 7950Sstevel@tonic-gate codev = sm_ssp->sm_ms->sm_cons_stdout.sm_dev; 7960Sstevel@tonic-gate mutex_exit(&sm_ssp->sm_ms->sm_cons_mutex); 7970Sstevel@tonic-gate } else { 7980Sstevel@tonic-gate cidev = codev = NODEV; 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate if (err != 0) { 8020Sstevel@tonic-gate if (assoc.ttymux_udev != cidev && assoc.ttymux_udev != codev) 8030Sstevel@tonic-gate return (err); 8040Sstevel@tonic-gate (void) console_cmd(iobp->ioc_cmd, &assoc); 8050Sstevel@tonic-gate return (0); 8060Sstevel@tonic-gate } else if (assoc.ttymux_udev == cidev || assoc.ttymux_udev == codev) { 8070Sstevel@tonic-gate (void) console_cmd(iobp->ioc_cmd, &assoc); 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate if (iobp->ioc_cmd == TTYMUX_ASSOC) 8110Sstevel@tonic-gate return (sm_associate(sm_dev2unit(assoc.ttymux_udev), 8120Sstevel@tonic-gate lqi, assoc.ttymux_tag, assoc.ttymux_ioflag, 8130Sstevel@tonic-gate assoc.ttymux_path)); 8140Sstevel@tonic-gate else if (iobp->ioc_cmd == TTYMUX_DISASSOC) 8150Sstevel@tonic-gate return (sm_disassociate(sm_dev2unit(assoc.ttymux_udev), 8160Sstevel@tonic-gate lqi, assoc.ttymux_tag)); 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate return (0); 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* 8220Sstevel@tonic-gate * Process a TTYMUX_GETLINK ioctl. 8230Sstevel@tonic-gate */ 8240Sstevel@tonic-gate int 8250Sstevel@tonic-gate ttymux_query_link_ioctl(mblk_t *mp) 8260Sstevel@tonic-gate { 8270Sstevel@tonic-gate sm_lqi_t *lqi; 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate sm_dbg('I', ("ttymux_query_link_ioctl:\n")); 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate if (mp->b_cont == NULL) 8340Sstevel@tonic-gate return (EINVAL); 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 8370Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 8380Sstevel@tonic-gate ttymux_assoc32_t *assoc32; 8390Sstevel@tonic-gate ttymux_assoc_t assoc; 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate if (mblk2assoc(mp, &assoc) != 0) 8420Sstevel@tonic-gate return (EINVAL); 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL && 8450Sstevel@tonic-gate (lqi = get_lqi_byid(assoc.ttymux_linkid)) == NULL) { 8460Sstevel@tonic-gate sm_dbg('M', ("Query Link (%d): dev %d:%d not found\n", 8470Sstevel@tonic-gate assoc.ttymux_linkid, 8480Sstevel@tonic-gate getmajor(assoc.ttymux_ldev), 8490Sstevel@tonic-gate getminor(assoc.ttymux_ldev))); 8500Sstevel@tonic-gate return (ENOLINK); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; 8530Sstevel@tonic-gate LQI2ASSOC32(assoc32, lqi); 8540Sstevel@tonic-gate } else 8550Sstevel@tonic-gate #endif 8560Sstevel@tonic-gate { 8570Sstevel@tonic-gate ttymux_assoc_t *assoc; 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate if (iobp->ioc_count < sizeof (ttymux_assoc_t)) 8600Sstevel@tonic-gate return (EINVAL); 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate assoc = (ttymux_assoc_t *)mp->b_cont->b_rptr; 8630Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc->ttymux_ldev)) == NULL && 8640Sstevel@tonic-gate (lqi = get_lqi_byid(assoc->ttymux_linkid)) == NULL) { 8650Sstevel@tonic-gate return (ENOLINK); 8660Sstevel@tonic-gate } 8670Sstevel@tonic-gate LQI2ASSOC(assoc, lqi); 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate return (0); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate /* 8730Sstevel@tonic-gate * Response to receiving an M_IOCDATA message for the TTYMUX_LIST ioctl. 8740Sstevel@tonic-gate */ 8750Sstevel@tonic-gate static int 8760Sstevel@tonic-gate sm_iocresp(mblk_t *mp) 8770Sstevel@tonic-gate { 8780Sstevel@tonic-gate struct copyresp *csp = (struct copyresp *)mp->b_rptr; 8790Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 8800Sstevel@tonic-gate mblk_t *pmp; 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: cmd %d)\n", csp->cp_cmd)); 8830Sstevel@tonic-gate 8840Sstevel@tonic-gate if (csp->cp_cmd != TTYMUX_LIST) { 8850Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: unknown cmd)\n")); 8860Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 8870Sstevel@tonic-gate return (EINVAL); 8880Sstevel@tonic-gate } 8890Sstevel@tonic-gate if (csp->cp_rval) { 8900Sstevel@tonic-gate if (csp->cp_private) 8910Sstevel@tonic-gate freemsg((mblk_t *)csp->cp_private); 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate sm_dbg('M', ("M_IOCDATA: result is %d\n", csp->cp_rval)); 8940Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 895*434Swnelson iobp->ioc_error = (int)(uintptr_t)csp->cp_rval; 8960Sstevel@tonic-gate iobp->ioc_rval = 0; 897*434Swnelson return (iobp->ioc_error); 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate pmp = (mblk_t *)csp->cp_private; 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 9030Sstevel@tonic-gate if ((csp->cp_flag & IOC_MODELS) != IOC_NATIVE) { 9040Sstevel@tonic-gate iobp->ioc_count = sizeof (ttymux_assocs32_t); 9050Sstevel@tonic-gate iobp->ioc_rval = pmp == NULL ? 0 : 9060Sstevel@tonic-gate ((ttymux_assocs32_t *)pmp->b_rptr)->ttymux32_nlinks; 9070Sstevel@tonic-gate } else 9080Sstevel@tonic-gate #endif 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate iobp->ioc_count = sizeof (ttymux_assocs_t); 9110Sstevel@tonic-gate iobp->ioc_rval = pmp == NULL ? 0 : 9120Sstevel@tonic-gate ((ttymux_assocs_t *)pmp->b_rptr)->ttymux_nlinks; 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate } 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate DB_TYPE(mp) = (pmp) ? M_IOCACK : M_IOCNAK; 9170Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct iocblk); 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate if (mp->b_cont) 9200Sstevel@tonic-gate freemsg(unlinkb(mp)); 9210Sstevel@tonic-gate if (pmp) 9220Sstevel@tonic-gate linkb(mp, pmp); 9230Sstevel@tonic-gate else 9240Sstevel@tonic-gate iobp->ioc_count = 0; 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate iobp->ioc_error = 0; 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: rval %d cnt %d private 0x%p)\n", 9290Sstevel@tonic-gate iobp->ioc_rval, iobp->ioc_count, pmp)); 9300Sstevel@tonic-gate return (0); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate /* 9340Sstevel@tonic-gate * Process a TTYMUX_LIST ioctl. 9350Sstevel@tonic-gate */ 9360Sstevel@tonic-gate int 9370Sstevel@tonic-gate ttymux_query_links_ioctl(mblk_t *mp) 9380Sstevel@tonic-gate { 9390Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 9400Sstevel@tonic-gate struct copyreq *cqp; 9410Sstevel@tonic-gate int unit; 9420Sstevel@tonic-gate sm_lqi_t *lqi; 9430Sstevel@tonic-gate mblk_t *nmp; 9440Sstevel@tonic-gate int cnt; 9450Sstevel@tonic-gate void *asl; 9460Sstevel@tonic-gate void *uaddr; 9470Sstevel@tonic-gate size_t sz; 9480Sstevel@tonic-gate 9490Sstevel@tonic-gate if (DB_TYPE(mp) == M_IOCDATA) { 9500Sstevel@tonic-gate return (sm_iocresp(mp)); 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate /* 9530Sstevel@tonic-gate * Is this a query for the number of linked devices? 9540Sstevel@tonic-gate */ 9550Sstevel@tonic-gate if (iobp->ioc_count == 0) { 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate for (unit = 0, iobp->ioc_rval = 0; 9580Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 9590Sstevel@tonic-gate unit++) 9600Sstevel@tonic-gate if (lqi->sm_linkid != 0) 9610Sstevel@tonic-gate iobp->ioc_rval += 1; 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate iobp->ioc_rval += count_unconfigured_consoles(sm_ssp->sm_ms); 9640Sstevel@tonic-gate DB_TYPE(mp) = M_IOCACK; 9650Sstevel@tonic-gate iobp->ioc_error = 0; 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate return (0); 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate if (mp->b_cont == NULL) { 9710Sstevel@tonic-gate sm_dbg('Y', ("TTYMUX_LIST: b_cont is NULL\n")); 9720Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 9730Sstevel@tonic-gate iobp->ioc_error = EINVAL; 9740Sstevel@tonic-gate return (EINVAL); 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate asl = mp->b_cont->b_rptr; 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 9800Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 9810Sstevel@tonic-gate cnt = ((ttymux_assocs32_t *)asl)->ttymux32_nlinks; 9820Sstevel@tonic-gate sz = cnt * sizeof (ttymux_assoc32_t); 983*434Swnelson uaddr = (void *)(uintptr_t) 984*434Swnelson ((ttymux_assocs32_t *)asl)->ttymux32_assocs; 9850Sstevel@tonic-gate } else 9860Sstevel@tonic-gate #endif 9870Sstevel@tonic-gate { 9880Sstevel@tonic-gate cnt = ((ttymux_assocs_t *)asl)->ttymux_nlinks; 9890Sstevel@tonic-gate sz = cnt * sizeof (ttymux_assoc_t); 9900Sstevel@tonic-gate uaddr = (void *)((ttymux_assocs_t *)asl)->ttymux_assocs; 9910Sstevel@tonic-gate } 9920Sstevel@tonic-gate if ((nmp = sm_allocb(sz, BPRI_MED)) == NULL) { 9930Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 9940Sstevel@tonic-gate iobp->ioc_error = EINVAL; 9950Sstevel@tonic-gate return (EAGAIN); 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate sm_dbg('Y', ("TTYMUX_LIST: cnt %d sz %d uaddr 0x%p\n", cnt, sz, uaddr)); 9990Sstevel@tonic-gate 10000Sstevel@tonic-gate iobp->ioc_rval = 0; 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 10030Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 10040Sstevel@tonic-gate ttymux_assoc32_t *assoc; 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate sm_dbg('Y', ("!Native: %d structures\n", cnt)); 10070Sstevel@tonic-gate assoc = (ttymux_assoc32_t *)nmp->b_rptr; 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate for (unit = 0; 10100Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 10110Sstevel@tonic-gate unit++) { 10120Sstevel@tonic-gate if (lqi->sm_linkid != 0) { 10130Sstevel@tonic-gate if (cnt-- == 0) 10140Sstevel@tonic-gate break; 10150Sstevel@tonic-gate LQI2ASSOC32(assoc, lqi); 10160Sstevel@tonic-gate assoc++; 10170Sstevel@tonic-gate iobp->ioc_rval += 1; 10180Sstevel@tonic-gate } 10190Sstevel@tonic-gate } 10200Sstevel@tonic-gate if (cnt > 0) { 10210Sstevel@tonic-gate /* see if there are unconfigured consoles */ 10220Sstevel@tonic-gate iobp->ioc_rval += 10230Sstevel@tonic-gate get_unconfigured_consoles32(sm_ssp->sm_ms, assoc); 10240Sstevel@tonic-gate sm_dbg('I', ("%d unconfigured consoles\n", 10250Sstevel@tonic-gate iobp->ioc_rval)); 10260Sstevel@tonic-gate } else { 10270Sstevel@tonic-gate sm_dbg('I', ("no more space in user addr\n")); 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate ((ttymux_assocs32_t *)asl)->ttymux32_nlinks = iobp->ioc_rval; 10300Sstevel@tonic-gate } else 10310Sstevel@tonic-gate #endif 10320Sstevel@tonic-gate { 10330Sstevel@tonic-gate ttymux_assoc_t *assoc; 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate sm_dbg('Y', ("!Native: %d structures\n", cnt)); 10360Sstevel@tonic-gate assoc = (ttymux_assoc_t *)nmp->b_wptr; 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate for (unit = 0; 10390Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 10400Sstevel@tonic-gate unit++) { 10410Sstevel@tonic-gate if (lqi->sm_linkid != 0) { 10420Sstevel@tonic-gate if (cnt-- == 0) 10430Sstevel@tonic-gate break; 10440Sstevel@tonic-gate LQI2ASSOC(assoc, lqi); 10450Sstevel@tonic-gate assoc++; 10460Sstevel@tonic-gate iobp->ioc_rval += 1; 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate } 10490Sstevel@tonic-gate if (cnt > 0) { 10500Sstevel@tonic-gate /* see if there are unconfigured consoles */ 10510Sstevel@tonic-gate iobp->ioc_rval += 10520Sstevel@tonic-gate get_unconfigured_consoles(sm_ssp->sm_ms, assoc); 10530Sstevel@tonic-gate sm_dbg('I', ("%d unconfigured consoles\n", 10540Sstevel@tonic-gate iobp->ioc_rval)); 10550Sstevel@tonic-gate } else { 10560Sstevel@tonic-gate sm_dbg('I', ("no more space in user addr\n")); 10570Sstevel@tonic-gate } 10580Sstevel@tonic-gate ((ttymux_assocs_t *)asl)->ttymux_nlinks = iobp->ioc_rval; 10590Sstevel@tonic-gate } 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 10620Sstevel@tonic-gate cqp->cq_addr = uaddr; 10630Sstevel@tonic-gate cqp->cq_size = sz; 10640Sstevel@tonic-gate cqp->cq_flag = 0; 10650Sstevel@tonic-gate cqp->cq_private = mp->b_cont; 10660Sstevel@tonic-gate mp->b_cont = nmp; 10670Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sz; 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate DB_TYPE(mp) = M_COPYOUT; 10700Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate return (0); 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate /* 10760Sstevel@tonic-gate * Process a TTYMUX_CONSDEV ioctl. 10770Sstevel@tonic-gate */ 10780Sstevel@tonic-gate static int 10790Sstevel@tonic-gate ttymux_console_ioctl(mblk_t *mp) 10800Sstevel@tonic-gate { 10810Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 10820Sstevel@tonic-gate int err = EINVAL; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate sm_dbg('I', ("ttymux_console_ioctl:\n")); 10850Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 10860Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 10870Sstevel@tonic-gate if (mp->b_cont && iobp->ioc_count >= sizeof (dev32_t)) { 10880Sstevel@tonic-gate dev32_t dev; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate (void) cmpldev(&dev, rconsdev); 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate *(dev32_t *)mp->b_cont->b_rptr = dev; 10930Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (dev); 10940Sstevel@tonic-gate iobp->ioc_count = sizeof (dev); 10950Sstevel@tonic-gate err = 0; 10960Sstevel@tonic-gate } else { 10970Sstevel@tonic-gate sm_dbg('I', ("TTYMUX_CONSDEV: b_cont 0x%p count %d\n", 10980Sstevel@tonic-gate mp->b_cont, iobp->ioc_count)); 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate } else 11010Sstevel@tonic-gate #endif 11020Sstevel@tonic-gate if (mp->b_cont && iobp->ioc_count >= sizeof (dev_t)) { 11030Sstevel@tonic-gate *(dev_t *)mp->b_cont->b_rptr = rconsdev; 11040Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (rconsdev); 11050Sstevel@tonic-gate iobp->ioc_count = sizeof (rconsdev); 11060Sstevel@tonic-gate err = 0; 11070Sstevel@tonic-gate } 11080Sstevel@tonic-gate return (err); 11090Sstevel@tonic-gate } 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate /* 11120Sstevel@tonic-gate * Process a ioctl relating to aborting on the console. 11130Sstevel@tonic-gate */ 11140Sstevel@tonic-gate int 11150Sstevel@tonic-gate ttymux_abort_ioctl(mblk_t *mp) 11160Sstevel@tonic-gate { 11170Sstevel@tonic-gate struct iocblk *iobp; 11180Sstevel@tonic-gate int cmd, err = 0; 11190Sstevel@tonic-gate sm_lqi_t *lqi; 11200Sstevel@tonic-gate ttymux_abort_t *abreq; 11210Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11220Sstevel@tonic-gate struct ttymux_abort32 { 11230Sstevel@tonic-gate dev32_t ldev; 11240Sstevel@tonic-gate enum ttymux_break_type method; 11250Sstevel@tonic-gate uint32_t enable; 11260Sstevel@tonic-gate } *abreq32; 11270Sstevel@tonic-gate #endif 11280Sstevel@tonic-gate dev_t ldev; 11290Sstevel@tonic-gate enum ttymux_break_type method; 11300Sstevel@tonic-gate uint_t enable; 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate iobp = (struct iocblk *)mp->b_rptr; 11330Sstevel@tonic-gate cmd = iobp->ioc_cmd; 11340Sstevel@tonic-gate 11350Sstevel@tonic-gate iobp->ioc_error = 0; 11360Sstevel@tonic-gate iobp->ioc_rval = 0; 11370Sstevel@tonic-gate sm_dbg('I', ("ttymux_abort_ioctl:\n")); 11380Sstevel@tonic-gate switch (cmd) { 11390Sstevel@tonic-gate case CONSSETABORTENABLE: 11400Sstevel@tonic-gate lqi = (sm_ssp->sm_lconsole) ? sm_ssp->sm_lconsole->sm_lqs : 0; 11410Sstevel@tonic-gate enable = (*(intptr_t *)mp->b_cont->b_rptr) ? 1 : 0; 11420Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = sm_ssp->sm_break_abort_on = enable; 11430Sstevel@tonic-gate for (; lqi != 0; lqi = lqi->sm_nlqi) { 11440Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 11450Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 11460Sstevel@tonic-gate } 11470Sstevel@tonic-gate break; 11480Sstevel@tonic-gate case CONSGETABORTENABLE: 11490Sstevel@tonic-gate if (mp->b_cont == 0 || iobp->ioc_count < sizeof (intptr_t)) { 11500Sstevel@tonic-gate iobp->ioc_error = EINVAL; 11510Sstevel@tonic-gate iobp->ioc_rval = -1; 11520Sstevel@tonic-gate } else { 11530Sstevel@tonic-gate *(intptr_t *)mp->b_cont->b_rptr = 11540Sstevel@tonic-gate (sm_ssp->sm_ctrla_abort_on || 11550Sstevel@tonic-gate sm_ssp->sm_break_abort_on); 11560Sstevel@tonic-gate mp->b_cont->b_wptr = 11570Sstevel@tonic-gate mp->b_cont->b_rptr + sizeof (intptr_t); 11580Sstevel@tonic-gate iobp->ioc_count = sizeof (intptr_t); 11590Sstevel@tonic-gate } 11600Sstevel@tonic-gate break; 11610Sstevel@tonic-gate case TTYMUX_GETABORTSTR: 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate if (iobp->ioc_count < strlen(sm_ssp->sm_abs) + 1 || 11640Sstevel@tonic-gate mp->b_cont == 0 || 11650Sstevel@tonic-gate mp->b_cont->b_cont) { 11660Sstevel@tonic-gate iobp->ioc_error = EINVAL; 11670Sstevel@tonic-gate iobp->ioc_rval = -1; 11680Sstevel@tonic-gate } else { 11690Sstevel@tonic-gate (void) strcpy((char *)mp->b_cont->b_rptr, 11700Sstevel@tonic-gate sm_ssp->sm_abs); 11710Sstevel@tonic-gate iobp->ioc_count = strlen(sm_ssp->sm_abs) + 1; 11720Sstevel@tonic-gate mp->b_cont->b_wptr = 11730Sstevel@tonic-gate mp->b_cont->b_rptr + iobp->ioc_count; 11740Sstevel@tonic-gate } 11750Sstevel@tonic-gate break; 11760Sstevel@tonic-gate case TTYMUX_GETABORT: 11770Sstevel@tonic-gate case TTYMUX_SETABORT: 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate lqi = 0; 11800Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11810Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 11820Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*abreq32) || 11830Sstevel@tonic-gate mp->b_cont == 0) { 11840Sstevel@tonic-gate err = EINVAL; 11850Sstevel@tonic-gate } else { 11860Sstevel@tonic-gate abreq32 = (struct ttymux_abort32 *) 11870Sstevel@tonic-gate mp->b_cont->b_rptr; 11880Sstevel@tonic-gate ldev = expldev(abreq32->ldev); 11890Sstevel@tonic-gate method = abreq32->method; 11900Sstevel@tonic-gate enable = (uint_t)abreq32->enable; 11910Sstevel@tonic-gate iobp->ioc_count = sizeof (*abreq32); 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate } else 11940Sstevel@tonic-gate #endif 11950Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*abreq) || 11960Sstevel@tonic-gate mp->b_cont == 0) { 11970Sstevel@tonic-gate err = EINVAL; 11980Sstevel@tonic-gate } else { 11990Sstevel@tonic-gate abreq = (ttymux_abort_t *)mp->b_cont->b_rptr; 12000Sstevel@tonic-gate ldev = abreq->ttymux_ldev; 12010Sstevel@tonic-gate method = abreq->ttymux_method; 12020Sstevel@tonic-gate enable = abreq->ttymux_enable; 12030Sstevel@tonic-gate iobp->ioc_count = sizeof (*abreq); 12040Sstevel@tonic-gate } 12050Sstevel@tonic-gate 12060Sstevel@tonic-gate if (err != 0) { 12070Sstevel@tonic-gate iobp->ioc_rval = -1; 12080Sstevel@tonic-gate return ((iobp->ioc_error = err)); 12090Sstevel@tonic-gate } 12100Sstevel@tonic-gate 12110Sstevel@tonic-gate sm_dbg('Y', ("ttymux_abort_ioctl: type %d how %d ldev %d:%d\n", 12120Sstevel@tonic-gate method, enable, getmajor(ldev), getminor(ldev))); 12130Sstevel@tonic-gate 12140Sstevel@tonic-gate lqi = get_lqi_bydevt(ldev); 12150Sstevel@tonic-gate if (ldev != NODEV && lqi == 0) { 12160Sstevel@tonic-gate err = ENOLINK; 12170Sstevel@tonic-gate } else if (cmd == TTYMUX_GETABORT && lqi == 0) { 12180Sstevel@tonic-gate err = ENODEV; 12190Sstevel@tonic-gate } else if (cmd == TTYMUX_GETABORT) { 12200Sstevel@tonic-gate if (lqi->sm_break_abort_on == 0 && 12210Sstevel@tonic-gate lqi->sm_ctrla_abort_on == 0) { 12220Sstevel@tonic-gate method = SOFTHARD_BREAK; 12230Sstevel@tonic-gate enable = 0; 12240Sstevel@tonic-gate } else { 12250Sstevel@tonic-gate enable = 1; 12260Sstevel@tonic-gate if (lqi->sm_break_abort_on == 0) 12270Sstevel@tonic-gate method = SOFTWARE_BREAK; 12280Sstevel@tonic-gate else if (lqi->sm_ctrla_abort_on == 0) 12290Sstevel@tonic-gate method = HARDWARE_BREAK; 12300Sstevel@tonic-gate else 12310Sstevel@tonic-gate method = SOFTHARD_BREAK; 12320Sstevel@tonic-gate } 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 12350Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 12360Sstevel@tonic-gate abreq32->method = method; 12370Sstevel@tonic-gate abreq32->enable = (uint32_t)enable; 12380Sstevel@tonic-gate } else 12390Sstevel@tonic-gate #endif 12400Sstevel@tonic-gate { 12410Sstevel@tonic-gate abreq->ttymux_method = method; 12420Sstevel@tonic-gate abreq->ttymux_enable = enable; 12430Sstevel@tonic-gate } 12440Sstevel@tonic-gate } else { 12450Sstevel@tonic-gate iobp->ioc_count = 0; 12460Sstevel@tonic-gate sm_dbg('I', ("lqi is 0x%p\n", lqi)); 12470Sstevel@tonic-gate if (lqi == 0) { 12480Sstevel@tonic-gate if (method == HARDWARE_BREAK) 12490Sstevel@tonic-gate sm_ssp->sm_break_abort_on = enable; 12500Sstevel@tonic-gate else if (method == SOFTWARE_BREAK) 12510Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = enable; 12520Sstevel@tonic-gate else if (method == SOFTHARD_BREAK) { 12530Sstevel@tonic-gate sm_ssp->sm_break_abort_on = enable; 12540Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = enable; 12550Sstevel@tonic-gate } else { 12560Sstevel@tonic-gate sm_dbg('I', ("%d - invalid\n", method)); 12570Sstevel@tonic-gate iobp->ioc_rval = -1; 12580Sstevel@tonic-gate return ((iobp->ioc_error = EINVAL)); 12590Sstevel@tonic-gate } 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate if (sm_ssp->sm_lconsole) { 12620Sstevel@tonic-gate sm_dbg('I', ("lconsole 0x%p (0x%p)\n", 12630Sstevel@tonic-gate sm_ssp->sm_lconsole, 12640Sstevel@tonic-gate sm_ssp->sm_lconsole->sm_lqs)); 12650Sstevel@tonic-gate } else { 12660Sstevel@tonic-gate sm_dbg('I', ("lconsole is null\n")); 12670Sstevel@tonic-gate } 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate lqi = (sm_ssp->sm_lconsole) ? 12700Sstevel@tonic-gate sm_ssp->sm_lconsole->sm_lqs : 0; 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate while (lqi) { 12730Sstevel@tonic-gate if (method == HARDWARE_BREAK) 12740Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 12750Sstevel@tonic-gate else if (method == SOFTWARE_BREAK) 12760Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 12770Sstevel@tonic-gate else if (method == SOFTHARD_BREAK) { 12780Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 12790Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 12800Sstevel@tonic-gate } else { 12810Sstevel@tonic-gate sm_dbg('I', ("%d: invalid\n", method)); 12820Sstevel@tonic-gate iobp->ioc_rval = -1; 12830Sstevel@tonic-gate return ((iobp->ioc_error = EINVAL)); 12840Sstevel@tonic-gate } 12850Sstevel@tonic-gate 12860Sstevel@tonic-gate lqi = (ldev == NODEV) ? lqi->sm_nlqi : 0; 12870Sstevel@tonic-gate } 12880Sstevel@tonic-gate } 12890Sstevel@tonic-gate iobp->ioc_rval = err ? -1 : 0; 12900Sstevel@tonic-gate iobp->ioc_error = err; 12910Sstevel@tonic-gate break; 12920Sstevel@tonic-gate default: 12930Sstevel@tonic-gate iobp->ioc_rval = -1; 12940Sstevel@tonic-gate iobp->ioc_error = EINVAL; 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate return (iobp->ioc_error); 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate 12990Sstevel@tonic-gate /* 13000Sstevel@tonic-gate * Process ioctls specific to the ttymux driver. 13010Sstevel@tonic-gate */ 13020Sstevel@tonic-gate /*ARGSUSED*/ 13030Sstevel@tonic-gate int 13040Sstevel@tonic-gate sm_ioctl_cmd(sm_uqi_t *uqi, mblk_t *mp) 13050Sstevel@tonic-gate { 13060Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate iobp->ioc_rval = 0; 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate /* 13110Sstevel@tonic-gate * This routine does not support transparent ioctls 13120Sstevel@tonic-gate */ 13130Sstevel@tonic-gate if (iobp->ioc_count == TRANSPARENT) { 13140Sstevel@tonic-gate sm_dbg('Y', ("sm_ioctl_cmd: unsupported ioctl\n")); 13150Sstevel@tonic-gate iobp->ioc_error = ENOTSUP; 13160Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 13170Sstevel@tonic-gate if (mp->b_cont) 13180Sstevel@tonic-gate freemsg(unlinkb(mp)); 13190Sstevel@tonic-gate return (ENOTSUP); 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate switch (iobp->ioc_cmd) { 13230Sstevel@tonic-gate case TTYMUX_CONSDEV: 13240Sstevel@tonic-gate iobp->ioc_error = ttymux_console_ioctl(mp); 13250Sstevel@tonic-gate break; 13260Sstevel@tonic-gate case TTYMUX_ASSOC: 13270Sstevel@tonic-gate case TTYMUX_DISASSOC: 13280Sstevel@tonic-gate iobp->ioc_error = ttymux_link_ioctl(mp); 13290Sstevel@tonic-gate break; 13300Sstevel@tonic-gate case TTYMUX_GETLINK: 13310Sstevel@tonic-gate iobp->ioc_error = ttymux_query_link_ioctl(mp); 13320Sstevel@tonic-gate break; 13330Sstevel@tonic-gate case TTYMUX_LIST: 13340Sstevel@tonic-gate return (ttymux_query_links_ioctl(mp)); 13350Sstevel@tonic-gate case TTYMUX_SETCTL: 13360Sstevel@tonic-gate case TTYMUX_GETCTL: 13370Sstevel@tonic-gate iobp->ioc_error = ENOTSUP; 13380Sstevel@tonic-gate break; 13390Sstevel@tonic-gate case TTYMUX_GETABORTSTR: 13400Sstevel@tonic-gate case TTYMUX_SETABORT: 13410Sstevel@tonic-gate case TTYMUX_GETABORT: 13420Sstevel@tonic-gate iobp->ioc_error = ttymux_abort_ioctl(mp); 13430Sstevel@tonic-gate break; 13440Sstevel@tonic-gate default: 13450Sstevel@tonic-gate iobp->ioc_error = EINVAL; 13460Sstevel@tonic-gate break; 13470Sstevel@tonic-gate } 13480Sstevel@tonic-gate 13490Sstevel@tonic-gate DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK; 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate if ((iobp->ioc_error || iobp->ioc_count == 0) && mp->b_cont) 13520Sstevel@tonic-gate freemsg(unlinkb(mp)); 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate sm_dbg('I', ("TTYMUX IOCTL: err %d rval %d count %d\n", 13550Sstevel@tonic-gate iobp->ioc_error, iobp->ioc_rval, iobp->ioc_count)); 13560Sstevel@tonic-gate 13570Sstevel@tonic-gate return (iobp->ioc_error); 13580Sstevel@tonic-gate } 1359