17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23544f04c0Swnelson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * DESCRIPTION 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * ttymux_ioctl - Handler for ttymux specific ioctl calls. 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 377c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 387c478bd9Sstevel@tonic-gate #include <sys/errno.h> 397c478bd9Sstevel@tonic-gate #include <sys/stat.h> 407c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 417c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 427c478bd9Sstevel@tonic-gate #include <sys/termio.h> 437c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 447c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 457c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 467c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 477c478bd9Sstevel@tonic-gate #include <sys/promif.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include <sys/ttymux.h> 507c478bd9Sstevel@tonic-gate #include "ttymux_impl.h" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 537c478bd9Sstevel@tonic-gate * Extern declarations 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate extern mblk_t *mkiocb(uint_t); 567c478bd9Sstevel@tonic-gate extern int nulldev(); 577c478bd9Sstevel@tonic-gate extern uintptr_t space_fetch(char *key); 587c478bd9Sstevel@tonic-gate extern void prom_interpret(char *, uintptr_t, uintptr_t, uintptr_t, 597c478bd9Sstevel@tonic-gate uintptr_t, uintptr_t); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * Imported ttymux routines 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate extern void sm_debug(char *, ...); 657c478bd9Sstevel@tonic-gate extern void sm_log(char *, ...); 667c478bd9Sstevel@tonic-gate extern sm_lqi_t *get_lqi_byid(int); 677c478bd9Sstevel@tonic-gate extern sm_lqi_t *get_lqi_bydevt(dev_t); 687c478bd9Sstevel@tonic-gate extern int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *); 697c478bd9Sstevel@tonic-gate extern int sm_disassociate(int, sm_lqi_t *, ulong_t); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Exported ttymux routines 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate int ttymux_abort_ioctl(mblk_t *); 757c478bd9Sstevel@tonic-gate int ttymux_device_init(sm_lqi_t *); 767c478bd9Sstevel@tonic-gate int ttymux_device_fini(sm_lqi_t *); 777c478bd9Sstevel@tonic-gate int sm_ioctl_cmd(sm_uqi_t *, mblk_t *); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * Imported ttymux variables 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate extern sm_ss_t *sm_ssp; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate static int 857c478bd9Sstevel@tonic-gate mblk2assoc(mblk_t *mp, ttymux_assoc_t *assoc) 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate sm_dbg('M', ("mblk2assoc:\n")); 907c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) 917c478bd9Sstevel@tonic-gate return (EINVAL); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 947c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 957c478bd9Sstevel@tonic-gate ttymux_assoc32_t *assoc32; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate sm_dbg('I', ("mblk2assoc: b_cont 0x%p count %d (sz %d)\n", 987c478bd9Sstevel@tonic-gate mp->b_cont, iobp->ioc_count, sizeof (*assoc32))); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate if (iobp->ioc_count < sizeof (ttymux_assoc32_t)) 1017c478bd9Sstevel@tonic-gate return (EINVAL); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; 1047c478bd9Sstevel@tonic-gate assoc->ttymux_udev = expldev(assoc32->ttymux32_udev); 1057c478bd9Sstevel@tonic-gate assoc->ttymux_ldev = expldev(assoc32->ttymux32_ldev); 1067c478bd9Sstevel@tonic-gate assoc->ttymux_linkid = assoc32->ttymux32_linkid; 1077c478bd9Sstevel@tonic-gate assoc->ttymux_tag = assoc32->ttymux32_tag; 1087c478bd9Sstevel@tonic-gate assoc->ttymux_ioflag = assoc32->ttymux32_ioflag; 1097c478bd9Sstevel@tonic-gate (void) strncpy(assoc->ttymux_path, assoc32->ttymux32_path, 1107c478bd9Sstevel@tonic-gate MAXPATHLEN); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate } else 1137c478bd9Sstevel@tonic-gate #endif 1147c478bd9Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*assoc)) { 1157c478bd9Sstevel@tonic-gate return (EINVAL); 1167c478bd9Sstevel@tonic-gate } else { 1177c478bd9Sstevel@tonic-gate *assoc = *(ttymux_assoc_t *)mp->b_cont->b_rptr; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate sm_dbg('M', ("mblk2assoc (%d): dev %d:%d not found\n", 1207c478bd9Sstevel@tonic-gate assoc->ttymux_linkid, getmajor(assoc->ttymux_ldev), 1217c478bd9Sstevel@tonic-gate getminor(assoc->ttymux_ldev))); 1227c478bd9Sstevel@tonic-gate return (0); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Given a device path return an OBP alias for it if it exists. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static char * 129*fa9e4066Sahrens val2alias(pnode_t node, char *path) 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate char *buf1; 1327c478bd9Sstevel@tonic-gate char *buf2; 1337c478bd9Sstevel@tonic-gate char *propname, *propval; 1347c478bd9Sstevel@tonic-gate int proplen; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate if (node == OBP_BADNODE) 1377c478bd9Sstevel@tonic-gate return (NULL); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate sm_dbg('A', ("Looking for an alias for: %s (len %d)\n", 1407c478bd9Sstevel@tonic-gate path, strlen(path))); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Ask for first property by passing a NULL string 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate buf1 = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP); 1467c478bd9Sstevel@tonic-gate buf2 = kmem_zalloc(OBP_MAXPROPNAME, KM_SLEEP); 1477c478bd9Sstevel@tonic-gate buf1[0] = '\0'; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate while (propname = (char *)prom_nextprop(node, buf1, buf2)) { 1507c478bd9Sstevel@tonic-gate if (strlen(propname) == 0) 1517c478bd9Sstevel@tonic-gate break; /* end of prop list */ 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate (void) strcpy(buf1, propname); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate proplen = prom_getproplen(node, propname); 1567c478bd9Sstevel@tonic-gate if (proplen == 0) 1577c478bd9Sstevel@tonic-gate continue; 1587c478bd9Sstevel@tonic-gate propval = kmem_zalloc(proplen + 1, KM_SLEEP); 1597c478bd9Sstevel@tonic-gate (void) prom_getprop(node, propname, propval); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (strcmp(propval, path) == 0) { 1627c478bd9Sstevel@tonic-gate kmem_free(propval, proplen + 1); 1637c478bd9Sstevel@tonic-gate kmem_free(buf1, OBP_MAXPROPNAME); 1647c478bd9Sstevel@tonic-gate sm_dbg('A', ("Alias is : %s\n", buf2)); 1657c478bd9Sstevel@tonic-gate return (buf2); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate kmem_free(propval, proplen + 1); 1697c478bd9Sstevel@tonic-gate bzero(buf2, OBP_MAXPROPNAME); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate kmem_free(buf1, OBP_MAXPROPNAME); 1737c478bd9Sstevel@tonic-gate kmem_free(buf2, OBP_MAXPROPNAME); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate return (NULL); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * Tell OBP that this device is now usable 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate static void 1827c478bd9Sstevel@tonic-gate enable_device(sm_mux_state_t *ms, sm_console_t *cn) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate char *enb_str = "\" enable-device\" rot $call-method"; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (!cn->sm_obp_con) 1877c478bd9Sstevel@tonic-gate return; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate sm_dbg('A', ("ttymux: enabling %d:%d\n", 1907c478bd9Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (cn->sm_i_ihdl != 0) 1937c478bd9Sstevel@tonic-gate prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, 1947c478bd9Sstevel@tonic-gate (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) 1977c478bd9Sstevel@tonic-gate prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, 1987c478bd9Sstevel@tonic-gate (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Tell OBP that this device is no longer usable 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static void 2057c478bd9Sstevel@tonic-gate disable_device(sm_mux_state_t *ms, sm_console_t *cn) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate char *dis_str = "\" disable-device\" rot $call-method"; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (!cn->sm_obp_con) 2107c478bd9Sstevel@tonic-gate return; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate sm_dbg('A', ("ttymux: disabling %d:%d\n", 2137c478bd9Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (cn->sm_i_ihdl != 0) 2167c478bd9Sstevel@tonic-gate prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, 2177c478bd9Sstevel@tonic-gate (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); 2187c478bd9Sstevel@tonic-gate if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) 2197c478bd9Sstevel@tonic-gate prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, 2207c478bd9Sstevel@tonic-gate (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static void 2247c478bd9Sstevel@tonic-gate device_init_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate uint_t flags = 0; 2277c478bd9Sstevel@tonic-gate dev_info_t *ldip; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate sm_dbg('I', ("device_init_impl:\n")); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if (plqi == NULL || cn == NULL) 2327c478bd9Sstevel@tonic-gate return; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate flags = (uint_t)cn->sm_mode; 2357c478bd9Sstevel@tonic-gate sm_dbg('I', ("device_init_impl: flgs %d con %d\n", flags, 2367c478bd9Sstevel@tonic-gate cn->sm_obp_con)); 2377c478bd9Sstevel@tonic-gate if (ldip = e_ddi_hold_devi_by_dev(cn->sm_dev, 0)) { 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Indicate to the linked device that it is 2417c478bd9Sstevel@tonic-gate * providing a multiplexed console. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate if (flags & (uint_t)FORINPUT) 2447c478bd9Sstevel@tonic-gate (void) e_ddi_prop_create(cn->sm_dev, ldip, 2457c478bd9Sstevel@tonic-gate DDI_PROP_CANSLEEP, "obp-input-console", 0, 0); 2467c478bd9Sstevel@tonic-gate if (flags & (uint_t)FOROUTPUT) 2477c478bd9Sstevel@tonic-gate (void) e_ddi_prop_create(cn->sm_dev, ldip, 2487c478bd9Sstevel@tonic-gate DDI_PROP_CANSLEEP, "obp-output-console", 0, 0); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate ddi_release_devi(ldip); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (flags) { 2547c478bd9Sstevel@tonic-gate plqi->sm_ioflag = flags; 2557c478bd9Sstevel@tonic-gate if (cn->sm_obp_con) 2567c478bd9Sstevel@tonic-gate plqi->sm_uqflags |= SM_OBPCNDEV; 2577c478bd9Sstevel@tonic-gate plqi->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on; 2587c478bd9Sstevel@tonic-gate plqi->sm_break_abort_on = sm_ssp->sm_break_abort_on; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * Tell OBP that its ok to use this console 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate enable_device(ms, cn); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static void 2687c478bd9Sstevel@tonic-gate device_fini_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate dev_info_t *ldip; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (plqi == NULL || cn == NULL) 2737c478bd9Sstevel@tonic-gate return; 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Indicate to the linked device that it is no longer 2767c478bd9Sstevel@tonic-gate * providing a multiplexed console. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate if (ldip = e_ddi_hold_devi_by_dev(plqi->sm_dev, 0)) { 2797c478bd9Sstevel@tonic-gate if (plqi->sm_ioflag & (uint_t)FORINPUT) 2807c478bd9Sstevel@tonic-gate (void) e_ddi_prop_remove(plqi->sm_dev, 2817c478bd9Sstevel@tonic-gate ldip, "obp-input-console"); 2827c478bd9Sstevel@tonic-gate if (plqi->sm_ioflag & (uint_t)FOROUTPUT) 2837c478bd9Sstevel@tonic-gate (void) e_ddi_prop_remove(plqi->sm_dev, 2847c478bd9Sstevel@tonic-gate ldip, "obp-output-console"); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate ddi_release_devi(ldip); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate plqi->sm_ioflag = 0; 2897c478bd9Sstevel@tonic-gate plqi->sm_uqflags &= ~SM_OBPCNDEV; 2907c478bd9Sstevel@tonic-gate disable_device(ms, cn); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate static int 294*fa9e4066Sahrens read_prop(pnode_t node, char *propname, char **propval) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate int proplen = prom_getproplen(node, propname); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (proplen < 0) 2997c478bd9Sstevel@tonic-gate return (proplen); 3007c478bd9Sstevel@tonic-gate *propval = kmem_zalloc(proplen + 1, KM_SLEEP); 3017c478bd9Sstevel@tonic-gate if (proplen > 0) 3027c478bd9Sstevel@tonic-gate (void) prom_getprop(node, propname, *propval); 3037c478bd9Sstevel@tonic-gate else 3047c478bd9Sstevel@tonic-gate *propval = 0; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate return (proplen); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * Parse a list of tokens 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate static char * 3137c478bd9Sstevel@tonic-gate sm_strtok_r(char *p, char *sep, char **lasts) 3147c478bd9Sstevel@tonic-gate { 3157c478bd9Sstevel@tonic-gate char *e, *tok = NULL; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if (p == 0 || *p == 0) 3187c478bd9Sstevel@tonic-gate return (NULL); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate e = p + strlen(p); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate do { 3237c478bd9Sstevel@tonic-gate if (strchr(sep, *p) != NULL) { 3247c478bd9Sstevel@tonic-gate if (tok != NULL) { 3257c478bd9Sstevel@tonic-gate *p = 0; 3267c478bd9Sstevel@tonic-gate *lasts = p + 1; 3277c478bd9Sstevel@tonic-gate return (tok); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate } else if (tok == NULL) { 3307c478bd9Sstevel@tonic-gate tok = p; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate } while (++p < e); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate *lasts = NULL; 3357c478bd9Sstevel@tonic-gate if (tok != NULL) 3367c478bd9Sstevel@tonic-gate return (tok); 3377c478bd9Sstevel@tonic-gate return (NULL); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * Add or remove an alias from a property list of aliases: 3427c478bd9Sstevel@tonic-gate * path: an OBP device path 3437c478bd9Sstevel@tonic-gate * pname: property name containing a space separated list of aliases 3447c478bd9Sstevel@tonic-gate * append: if true include the alias for path in the property list 3457c478bd9Sstevel@tonic-gate * otherwise remove the alias from the list. 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate static int 3487c478bd9Sstevel@tonic-gate upd_config(boolean_t append, char *pname, char *path) 3497c478bd9Sstevel@tonic-gate { 350*fa9e4066Sahrens pnode_t onode, anode; 3517c478bd9Sstevel@tonic-gate size_t plen; /* length of property name */ 3527c478bd9Sstevel@tonic-gate char *pval; /* value of property */ 3537c478bd9Sstevel@tonic-gate char *tok, *lasts; 3547c478bd9Sstevel@tonic-gate char *aliases[TTYMUX_MAX_LINKS]; 3557c478bd9Sstevel@tonic-gate size_t i, cnt, len; 3567c478bd9Sstevel@tonic-gate boolean_t found; 3577c478bd9Sstevel@tonic-gate char *nval, *alias = NULL; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if ((anode = prom_alias_node()) == OBP_BADNODE || 3607c478bd9Sstevel@tonic-gate (onode = prom_optionsnode()) == OBP_BADNODE) { 3617c478bd9Sstevel@tonic-gate sm_dbg('I', ("upd_config: no alias or options node.\n")); 3627c478bd9Sstevel@tonic-gate return (1); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if ((plen = read_prop(onode, pname, &pval)) < 0) 3667c478bd9Sstevel@tonic-gate return (1); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate sm_dbg('I', ("upd_config: %s=%s (%s)\n", pname, pval, path)); 3697c478bd9Sstevel@tonic-gate found = B_FALSE; 3707c478bd9Sstevel@tonic-gate for (len = 0, cnt = 0, tok = sm_strtok_r(pval, " \t", &lasts); 3717c478bd9Sstevel@tonic-gate tok != NULL && cnt < TTYMUX_MAX_LINKS; 3727c478bd9Sstevel@tonic-gate tok = sm_strtok_r(lasts, " \t", &lasts)) { 3737c478bd9Sstevel@tonic-gate char *aval; 3747c478bd9Sstevel@tonic-gate size_t alen; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if ((alen = read_prop(anode, tok, &aval)) < 0) 3777c478bd9Sstevel@tonic-gate continue; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* does this alias match the requested path */ 3807c478bd9Sstevel@tonic-gate if (strcmp(aval, path) == 0 || 3817c478bd9Sstevel@tonic-gate (strstr(path, aval) != NULL && 3827c478bd9Sstevel@tonic-gate strchr(aval, ':') == NULL && strchr(path, ':') != NULL && 3837c478bd9Sstevel@tonic-gate strcmp(strchr(path, ':'), ":a") == 0)) { 3847c478bd9Sstevel@tonic-gate if (!found && append) { 3857c478bd9Sstevel@tonic-gate kmem_free(aval, alen + 1); 3867c478bd9Sstevel@tonic-gate goto out; 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate found = B_TRUE; 3897c478bd9Sstevel@tonic-gate } else { 3907c478bd9Sstevel@tonic-gate aliases[cnt++] = tok; 3917c478bd9Sstevel@tonic-gate len += strlen(tok) + 1; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate kmem_free(aval, alen + 1); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d aliases\n", cnt)); 3977c478bd9Sstevel@tonic-gate if (append) { 3987c478bd9Sstevel@tonic-gate if (cnt + 1 == TTYMUX_MAX_LINKS) 3997c478bd9Sstevel@tonic-gate goto out; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate if ((alias = val2alias(anode, path)) == NULL) { 4027c478bd9Sstevel@tonic-gate char *mnode = strstr(path, ":a"); 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate if (mnode != 0) { 4057c478bd9Sstevel@tonic-gate *mnode = '\0'; 4067c478bd9Sstevel@tonic-gate alias = val2alias(anode, path); 4077c478bd9Sstevel@tonic-gate *mnode = ':'; 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate if (alias == NULL) { 4117c478bd9Sstevel@tonic-gate sm_dbg('I', ("No alias for %s\n", path)); 4127c478bd9Sstevel@tonic-gate goto out; 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate aliases[cnt++] = alias; 4157c478bd9Sstevel@tonic-gate len += strlen(alias) + 1; 4167c478bd9Sstevel@tonic-gate } else if (!found) { 4177c478bd9Sstevel@tonic-gate goto out; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d aliases (len %d)\n", cnt, len)); 4217c478bd9Sstevel@tonic-gate if (len == 0) 4227c478bd9Sstevel@tonic-gate goto out; 4237c478bd9Sstevel@tonic-gate ASSERT(len > 1 && cnt > 0); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate nval = kmem_zalloc(len, KM_SLEEP); 4267c478bd9Sstevel@tonic-gate for (i = 0; ; ) { 4277c478bd9Sstevel@tonic-gate ASSERT(strlen(nval) + strlen(aliases[i]) + 1 <= len); 4287c478bd9Sstevel@tonic-gate sm_dbg('I', ("alias %s\n", aliases[i])); 4297c478bd9Sstevel@tonic-gate (void) strcat(nval, aliases[i]); 4307c478bd9Sstevel@tonic-gate if (++i == cnt) 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate (void) strcat(nval, " "); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate sm_dbg('I', ("setprop: %s=%s (%d)\n", pname, nval, len)); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate (void) prom_setprop(onode, pname, nval, len); 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate kmem_free(nval, len); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate if (alias != NULL) 4427c478bd9Sstevel@tonic-gate kmem_free(alias, OBP_MAXPROPNAME); 4437c478bd9Sstevel@tonic-gate out: 4447c478bd9Sstevel@tonic-gate sm_dbg('I', ("upd_config: returning.\n")); 4457c478bd9Sstevel@tonic-gate kmem_free(pval, plen + 1); 4467c478bd9Sstevel@tonic-gate return (0); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* 4507c478bd9Sstevel@tonic-gate * 4517c478bd9Sstevel@tonic-gate */ 4527c478bd9Sstevel@tonic-gate static int 4537c478bd9Sstevel@tonic-gate update_config(sm_mux_state_t *ms, char *path, io_mode_t mode, int cmd) 4547c478bd9Sstevel@tonic-gate { 4557c478bd9Sstevel@tonic-gate sm_dbg('I', ("update_config: path %s io %d\n", path ? path : "", mode)); 4567c478bd9Sstevel@tonic-gate if (path == 0 || *path == 0) { 4577c478bd9Sstevel@tonic-gate sm_dbg('I', ("update_config: EINVAL - no path\n")); 4587c478bd9Sstevel@tonic-gate return (1); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate if (prom_is_openprom() == 0) 4617c478bd9Sstevel@tonic-gate return (0); 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate if ((mode & FORINPUT) && ms->sm_ialias != NULL) 4647c478bd9Sstevel@tonic-gate (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_ialias, path); 4657c478bd9Sstevel@tonic-gate if ((mode & FOROUTPUT) && ms->sm_oalias != NULL) 4667c478bd9Sstevel@tonic-gate (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_oalias, path); 4677c478bd9Sstevel@tonic-gate return (0); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Convert a dev_t to a device path 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate static char * 4747c478bd9Sstevel@tonic-gate sm_di_path(dev_t dev) 4757c478bd9Sstevel@tonic-gate { 4767c478bd9Sstevel@tonic-gate char *p, *path; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (dev == NODEV) 4797c478bd9Sstevel@tonic-gate return (NULL); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate p = kmem_zalloc(MAXPATHLEN + 1, KM_SLEEP); 4827c478bd9Sstevel@tonic-gate if (ddi_dev_pathname(dev, S_IFCHR, p) == DDI_SUCCESS) { 4837c478bd9Sstevel@tonic-gate path = kmem_alloc(strlen(p) + 1, KM_SLEEP); 4847c478bd9Sstevel@tonic-gate (void) strcpy(path, p); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate kmem_free(p, MAXPATHLEN + 1); 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate return (path); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate static int 4927c478bd9Sstevel@tonic-gate console_cmd(int cmd, ttymux_assoc_t *assoc) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate sm_mux_state_t *ms; 4957c478bd9Sstevel@tonic-gate sm_console_t *cn; 4967c478bd9Sstevel@tonic-gate uint_t j; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd ENTER: %s\n", cmd == TTYMUX_DISASSOC ? 4997c478bd9Sstevel@tonic-gate "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate if (assoc->ttymux_ldev == NODEV && *assoc->ttymux_path != '/') { 5027c478bd9Sstevel@tonic-gate sm_lqi_t *lqi = get_lqi_byid(assoc->ttymux_linkid); 5037c478bd9Sstevel@tonic-gate if (lqi == 0 || lqi->sm_dev == NODEV) { 5047c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: no id link %d cmd %d\n", 5057c478bd9Sstevel@tonic-gate assoc->ttymux_linkid, cmd)); 5067c478bd9Sstevel@tonic-gate return (EINVAL); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate assoc->ttymux_ldev = lqi->sm_dev; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: path %s\n", assoc->ttymux_path)); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if ((ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR)) == 0) { 5147c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: No muxstate\n")); 5157c478bd9Sstevel@tonic-gate return (0); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate for (cn = ms->sm_cons_links, j = 0; 5217c478bd9Sstevel@tonic-gate j < ms->sm_cons_cnt; cn++, j++) { 5227c478bd9Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV && assoc->ttymux_ldev == 5237c478bd9Sstevel@tonic-gate cn->sm_dev) { 5247c478bd9Sstevel@tonic-gate break; 5257c478bd9Sstevel@tonic-gate } else if (cn->sm_path != NULL && 5267c478bd9Sstevel@tonic-gate strncmp(cn->sm_path, assoc->ttymux_path, MAXPATHLEN) == 0) { 5277c478bd9Sstevel@tonic-gate break; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate assoc->ttymux_path[MAXPATHLEN - 1] = 0; 5327c478bd9Sstevel@tonic-gate if (cmd == TTYMUX_DISASSOC) { 5337c478bd9Sstevel@tonic-gate if (j == ms->sm_cons_cnt) { 5347c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 5357c478bd9Sstevel@tonic-gate return (0); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate /* 5397c478bd9Sstevel@tonic-gate * Disable the console in OBP and then delete this console 5407c478bd9Sstevel@tonic-gate * this console - note that this also deletes OBP 5417c478bd9Sstevel@tonic-gate * information - i.e. once it is disassociated it cannot 5427c478bd9Sstevel@tonic-gate * be reused as an OBP console - roll on polled I/O! 5437c478bd9Sstevel@tonic-gate */ 5447c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: cleaning up\n")); 5457c478bd9Sstevel@tonic-gate device_fini_impl(ms, cn, get_lqi_bydevt(assoc->ttymux_ldev)); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if (cn->sm_path == NULL) { 5487c478bd9Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV) 5497c478bd9Sstevel@tonic-gate cn->sm_path = sm_di_path(assoc->ttymux_ldev); 5507c478bd9Sstevel@tonic-gate else 5517c478bd9Sstevel@tonic-gate (void) update_config(ms, assoc->ttymux_path, 5527c478bd9Sstevel@tonic-gate assoc->ttymux_ioflag, cmd); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate if (cn->sm_path) { 5557c478bd9Sstevel@tonic-gate (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); 5567c478bd9Sstevel@tonic-gate kmem_free(cn->sm_path, strlen(cn->sm_path) + 1); 5577c478bd9Sstevel@tonic-gate cn->sm_path = NULL; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate ms->sm_cons_cnt -= 1; 5607c478bd9Sstevel@tonic-gate if (ms->sm_cons_cnt > 0) 5617c478bd9Sstevel@tonic-gate *cn = ms->sm_cons_links[ms->sm_cons_cnt]; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: console %d removed (cnt %d)\n", 5647c478bd9Sstevel@tonic-gate j, ms->sm_cons_cnt)); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate } else if (cmd == TTYMUX_ASSOC) { 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if (j == ms->sm_cons_cnt) { 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (j == TTYMUX_MAX_LINKS) { 5717c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 5727c478bd9Sstevel@tonic-gate return (ENOMEM); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate ms->sm_cons_cnt += 1; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate bzero((caddr_t)cn, sizeof (*cn)); 5787c478bd9Sstevel@tonic-gate cn->sm_dev = assoc->ttymux_ldev; 5797c478bd9Sstevel@tonic-gate cn->sm_muxid = assoc->ttymux_linkid; 5807c478bd9Sstevel@tonic-gate cn->sm_mode = assoc->ttymux_ioflag; 5817c478bd9Sstevel@tonic-gate device_init_impl(ms, cn, 5827c478bd9Sstevel@tonic-gate get_lqi_bydevt(assoc->ttymux_ldev)); 5837c478bd9Sstevel@tonic-gate } else { 5847c478bd9Sstevel@tonic-gate cn->sm_dev = assoc->ttymux_ldev; 5857c478bd9Sstevel@tonic-gate cn->sm_muxid = assoc->ttymux_linkid; 5867c478bd9Sstevel@tonic-gate cn->sm_mode = assoc->ttymux_ioflag; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate if (assoc->ttymux_ldev != NODEV) { 5907c478bd9Sstevel@tonic-gate cn->sm_path = sm_di_path(assoc->ttymux_ldev); 5917c478bd9Sstevel@tonic-gate } else { 5927c478bd9Sstevel@tonic-gate cn->sm_path = kmem_alloc(strlen(assoc->ttymux_path) + 1, 5937c478bd9Sstevel@tonic-gate KM_SLEEP); 5947c478bd9Sstevel@tonic-gate (void) strcpy(cn->sm_path, assoc->ttymux_path); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate if (cn->sm_path != NULL) 5977c478bd9Sstevel@tonic-gate (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); 5987c478bd9Sstevel@tonic-gate else 5997c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd: ASSOC No path info")); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6027c478bd9Sstevel@tonic-gate sm_dbg('I', ("console_cmd EXIT: %s\n", cmd == TTYMUX_DISASSOC ? 6037c478bd9Sstevel@tonic-gate "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); 6047c478bd9Sstevel@tonic-gate return (0); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate static int 6087c478bd9Sstevel@tonic-gate get_unconfigured_consoles(sm_mux_state_t *ms, ttymux_assoc_t *a) 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate sm_console_t *cn; 6117c478bd9Sstevel@tonic-gate int j, cnt; 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate if (ms == 0) 6147c478bd9Sstevel@tonic-gate return (0); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6177c478bd9Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6187c478bd9Sstevel@tonic-gate cn++, j++) { 6197c478bd9Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { 6207c478bd9Sstevel@tonic-gate a->ttymux_linkid = cn->sm_muxid; 6217c478bd9Sstevel@tonic-gate a->ttymux_tag = (uint_t)0; 6227c478bd9Sstevel@tonic-gate a->ttymux_ioflag = cn->sm_mode; 6237c478bd9Sstevel@tonic-gate a->ttymux_udev = cn->sm_mode & FORINPUT ? 6247c478bd9Sstevel@tonic-gate ms->sm_cons_stdin.sm_dev : 6257c478bd9Sstevel@tonic-gate ms->sm_cons_stdout.sm_dev; 6267c478bd9Sstevel@tonic-gate a->ttymux_ldev = NODEV; 6277c478bd9Sstevel@tonic-gate (void) strncpy(a->ttymux_path, cn->sm_path, MAXPATHLEN); 6287c478bd9Sstevel@tonic-gate cnt++; 6297c478bd9Sstevel@tonic-gate a++; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6337c478bd9Sstevel@tonic-gate return (cnt); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 6377c478bd9Sstevel@tonic-gate /* 6387c478bd9Sstevel@tonic-gate * Look for any consoles that are not currently plumbed under the multiplexer. 6397c478bd9Sstevel@tonic-gate */ 6407c478bd9Sstevel@tonic-gate static int 6417c478bd9Sstevel@tonic-gate get_unconfigured_consoles32(sm_mux_state_t *ms, ttymux_assoc32_t *a) 6427c478bd9Sstevel@tonic-gate { 6437c478bd9Sstevel@tonic-gate sm_console_t *cn; 6447c478bd9Sstevel@tonic-gate int j, cnt; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate if (ms == 0) 6477c478bd9Sstevel@tonic-gate return (0); 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6507c478bd9Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6517c478bd9Sstevel@tonic-gate cn++, j++) { 6527c478bd9Sstevel@tonic-gate sm_dbg('I', ("get_unconfigured_consoles: check %s (%d:%d)", 6537c478bd9Sstevel@tonic-gate cn->sm_path ? cn->sm_path : "NULL", 6547c478bd9Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 6557c478bd9Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { 6567c478bd9Sstevel@tonic-gate a->ttymux32_linkid = 0; 6577c478bd9Sstevel@tonic-gate a->ttymux32_tag = (uint32_t)0; 6587c478bd9Sstevel@tonic-gate a->ttymux32_ioflag = (uint32_t)cn->sm_mode; 6597c478bd9Sstevel@tonic-gate a->ttymux32_ldev = NODEV32; 6607c478bd9Sstevel@tonic-gate (void) cmpldev(&a->ttymux32_udev, cn->sm_mode & 6617c478bd9Sstevel@tonic-gate FORINPUT ? ms->sm_cons_stdin.sm_dev : 6627c478bd9Sstevel@tonic-gate ms->sm_cons_stdout.sm_dev); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate (void) strncpy(a->ttymux32_path, cn->sm_path, 6657c478bd9Sstevel@tonic-gate MAXPATHLEN); 6667c478bd9Sstevel@tonic-gate cnt++; 6677c478bd9Sstevel@tonic-gate a++; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6717c478bd9Sstevel@tonic-gate return (cnt); 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate #endif 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate static int 6767c478bd9Sstevel@tonic-gate count_unconfigured_consoles(sm_mux_state_t *ms) 6777c478bd9Sstevel@tonic-gate { 6787c478bd9Sstevel@tonic-gate sm_console_t *cn; 6797c478bd9Sstevel@tonic-gate int j, cnt; 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate if (ms == 0) 6827c478bd9Sstevel@tonic-gate return (0); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 6857c478bd9Sstevel@tonic-gate for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; 6867c478bd9Sstevel@tonic-gate cn++, j++) { 6877c478bd9Sstevel@tonic-gate sm_dbg('I', ("cnt_unconfigured_consoles: check %s (%d:%d)", 6887c478bd9Sstevel@tonic-gate cn->sm_path ? cn->sm_path : "NULL", 6897c478bd9Sstevel@tonic-gate getmajor(cn->sm_dev), getminor(cn->sm_dev))); 6907c478bd9Sstevel@tonic-gate if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) 6917c478bd9Sstevel@tonic-gate cnt++; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 6947c478bd9Sstevel@tonic-gate return (cnt); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* 6987c478bd9Sstevel@tonic-gate * Exported interfaces 6997c478bd9Sstevel@tonic-gate */ 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* 7027c478bd9Sstevel@tonic-gate * A console device is no longer associated. 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate int 7057c478bd9Sstevel@tonic-gate ttymux_device_fini(sm_lqi_t *plqi) 7067c478bd9Sstevel@tonic-gate { 7077c478bd9Sstevel@tonic-gate int j; 7087c478bd9Sstevel@tonic-gate sm_mux_state_t *ms; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if (plqi == NULL || ms == NULL) 7137c478bd9Sstevel@tonic-gate return (0); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate for (j = 0; j < ms->sm_cons_cnt; j++) { 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate device_fini_impl(ms, &ms->sm_cons_links[j], plqi); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7247c478bd9Sstevel@tonic-gate return (0); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate return (1); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * A console device is being introduced. 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate int 7367c478bd9Sstevel@tonic-gate ttymux_device_init(sm_lqi_t *plqi) 7377c478bd9Sstevel@tonic-gate { 7387c478bd9Sstevel@tonic-gate int j; 7397c478bd9Sstevel@tonic-gate sm_mux_state_t *ms; 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (ms == NULL) 7447c478bd9Sstevel@tonic-gate return (0); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate mutex_enter(&ms->sm_cons_mutex); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate for (j = 0; j < ms->sm_cons_cnt; j++) { 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate device_init_impl(ms, &ms->sm_cons_links[j], plqi); 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7557c478bd9Sstevel@tonic-gate return (0); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate mutex_exit(&ms->sm_cons_mutex); 7597c478bd9Sstevel@tonic-gate return (1); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * Process a TTYMUX_ASSOCIATE or TTYMUX_DISASSOCIATE ioctl. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate static int 7667c478bd9Sstevel@tonic-gate ttymux_link_ioctl(mblk_t *mp) 7677c478bd9Sstevel@tonic-gate { 7687c478bd9Sstevel@tonic-gate ttymux_assoc_t assoc; 7697c478bd9Sstevel@tonic-gate int err; 7707c478bd9Sstevel@tonic-gate sm_lqi_t *lqi; 7717c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 7727c478bd9Sstevel@tonic-gate dev_t cidev, codev; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate sm_dbg('I', ("ttymux_link_ioctl:\n")); 7757c478bd9Sstevel@tonic-gate if ((err = mblk2assoc(mp, &assoc)) != 0) 7767c478bd9Sstevel@tonic-gate return (err); 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate sm_dbg('I', ("uminor is %d\n", getminor(assoc.ttymux_udev))); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate if (assoc.ttymux_udev == NODEV) 7817c478bd9Sstevel@tonic-gate return (EINVAL); 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate err = 0; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL) { 7867c478bd9Sstevel@tonic-gate if (assoc.ttymux_linkid < 0) 7877c478bd9Sstevel@tonic-gate err = EINVAL; 7887c478bd9Sstevel@tonic-gate else if ((lqi = get_lqi_byid(assoc.ttymux_linkid)) == 0) 7897c478bd9Sstevel@tonic-gate err = ENOLINK; 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (sm_ssp->sm_ms) { 7937c478bd9Sstevel@tonic-gate mutex_enter(&sm_ssp->sm_ms->sm_cons_mutex); 7947c478bd9Sstevel@tonic-gate cidev = sm_ssp->sm_ms->sm_cons_stdin.sm_dev; 7957c478bd9Sstevel@tonic-gate codev = sm_ssp->sm_ms->sm_cons_stdout.sm_dev; 7967c478bd9Sstevel@tonic-gate mutex_exit(&sm_ssp->sm_ms->sm_cons_mutex); 7977c478bd9Sstevel@tonic-gate } else { 7987c478bd9Sstevel@tonic-gate cidev = codev = NODEV; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if (err != 0) { 8027c478bd9Sstevel@tonic-gate if (assoc.ttymux_udev != cidev && assoc.ttymux_udev != codev) 8037c478bd9Sstevel@tonic-gate return (err); 8047c478bd9Sstevel@tonic-gate (void) console_cmd(iobp->ioc_cmd, &assoc); 8057c478bd9Sstevel@tonic-gate return (0); 8067c478bd9Sstevel@tonic-gate } else if (assoc.ttymux_udev == cidev || assoc.ttymux_udev == codev) { 8077c478bd9Sstevel@tonic-gate (void) console_cmd(iobp->ioc_cmd, &assoc); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if (iobp->ioc_cmd == TTYMUX_ASSOC) 8117c478bd9Sstevel@tonic-gate return (sm_associate(sm_dev2unit(assoc.ttymux_udev), 8127c478bd9Sstevel@tonic-gate lqi, assoc.ttymux_tag, assoc.ttymux_ioflag, 8137c478bd9Sstevel@tonic-gate assoc.ttymux_path)); 8147c478bd9Sstevel@tonic-gate else if (iobp->ioc_cmd == TTYMUX_DISASSOC) 8157c478bd9Sstevel@tonic-gate return (sm_disassociate(sm_dev2unit(assoc.ttymux_udev), 8167c478bd9Sstevel@tonic-gate lqi, assoc.ttymux_tag)); 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate return (0); 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * Process a TTYMUX_GETLINK ioctl. 8237c478bd9Sstevel@tonic-gate */ 8247c478bd9Sstevel@tonic-gate int 8257c478bd9Sstevel@tonic-gate ttymux_query_link_ioctl(mblk_t *mp) 8267c478bd9Sstevel@tonic-gate { 8277c478bd9Sstevel@tonic-gate sm_lqi_t *lqi; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate sm_dbg('I', ("ttymux_query_link_ioctl:\n")); 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) 8347c478bd9Sstevel@tonic-gate return (EINVAL); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 8377c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 8387c478bd9Sstevel@tonic-gate ttymux_assoc32_t *assoc32; 8397c478bd9Sstevel@tonic-gate ttymux_assoc_t assoc; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (mblk2assoc(mp, &assoc) != 0) 8427c478bd9Sstevel@tonic-gate return (EINVAL); 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL && 8457c478bd9Sstevel@tonic-gate (lqi = get_lqi_byid(assoc.ttymux_linkid)) == NULL) { 8467c478bd9Sstevel@tonic-gate sm_dbg('M', ("Query Link (%d): dev %d:%d not found\n", 8477c478bd9Sstevel@tonic-gate assoc.ttymux_linkid, 8487c478bd9Sstevel@tonic-gate getmajor(assoc.ttymux_ldev), 8497c478bd9Sstevel@tonic-gate getminor(assoc.ttymux_ldev))); 8507c478bd9Sstevel@tonic-gate return (ENOLINK); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; 8537c478bd9Sstevel@tonic-gate LQI2ASSOC32(assoc32, lqi); 8547c478bd9Sstevel@tonic-gate } else 8557c478bd9Sstevel@tonic-gate #endif 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate ttymux_assoc_t *assoc; 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate if (iobp->ioc_count < sizeof (ttymux_assoc_t)) 8607c478bd9Sstevel@tonic-gate return (EINVAL); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate assoc = (ttymux_assoc_t *)mp->b_cont->b_rptr; 8637c478bd9Sstevel@tonic-gate if ((lqi = get_lqi_bydevt(assoc->ttymux_ldev)) == NULL && 8647c478bd9Sstevel@tonic-gate (lqi = get_lqi_byid(assoc->ttymux_linkid)) == NULL) { 8657c478bd9Sstevel@tonic-gate return (ENOLINK); 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate LQI2ASSOC(assoc, lqi); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate return (0); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * Response to receiving an M_IOCDATA message for the TTYMUX_LIST ioctl. 8747c478bd9Sstevel@tonic-gate */ 8757c478bd9Sstevel@tonic-gate static int 8767c478bd9Sstevel@tonic-gate sm_iocresp(mblk_t *mp) 8777c478bd9Sstevel@tonic-gate { 8787c478bd9Sstevel@tonic-gate struct copyresp *csp = (struct copyresp *)mp->b_rptr; 8797c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 8807c478bd9Sstevel@tonic-gate mblk_t *pmp; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: cmd %d)\n", csp->cp_cmd)); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate if (csp->cp_cmd != TTYMUX_LIST) { 8857c478bd9Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: unknown cmd)\n")); 8867c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 8877c478bd9Sstevel@tonic-gate return (EINVAL); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate if (csp->cp_rval) { 8907c478bd9Sstevel@tonic-gate if (csp->cp_private) 8917c478bd9Sstevel@tonic-gate freemsg((mblk_t *)csp->cp_private); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate sm_dbg('M', ("M_IOCDATA: result is %d\n", csp->cp_rval)); 8947c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 895544f04c0Swnelson iobp->ioc_error = (int)(uintptr_t)csp->cp_rval; 8967c478bd9Sstevel@tonic-gate iobp->ioc_rval = 0; 897544f04c0Swnelson return (iobp->ioc_error); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate pmp = (mblk_t *)csp->cp_private; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 9037c478bd9Sstevel@tonic-gate if ((csp->cp_flag & IOC_MODELS) != IOC_NATIVE) { 9047c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (ttymux_assocs32_t); 9057c478bd9Sstevel@tonic-gate iobp->ioc_rval = pmp == NULL ? 0 : 9067c478bd9Sstevel@tonic-gate ((ttymux_assocs32_t *)pmp->b_rptr)->ttymux32_nlinks; 9077c478bd9Sstevel@tonic-gate } else 9087c478bd9Sstevel@tonic-gate #endif 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (ttymux_assocs_t); 9117c478bd9Sstevel@tonic-gate iobp->ioc_rval = pmp == NULL ? 0 : 9127c478bd9Sstevel@tonic-gate ((ttymux_assocs_t *)pmp->b_rptr)->ttymux_nlinks; 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate DB_TYPE(mp) = (pmp) ? M_IOCACK : M_IOCNAK; 9177c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct iocblk); 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (mp->b_cont) 9207c478bd9Sstevel@tonic-gate freemsg(unlinkb(mp)); 9217c478bd9Sstevel@tonic-gate if (pmp) 9227c478bd9Sstevel@tonic-gate linkb(mp, pmp); 9237c478bd9Sstevel@tonic-gate else 9247c478bd9Sstevel@tonic-gate iobp->ioc_count = 0; 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate iobp->ioc_error = 0; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate sm_dbg('M', ("(M_IOCDATA: rval %d cnt %d private 0x%p)\n", 9297c478bd9Sstevel@tonic-gate iobp->ioc_rval, iobp->ioc_count, pmp)); 9307c478bd9Sstevel@tonic-gate return (0); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * Process a TTYMUX_LIST ioctl. 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate int 9377c478bd9Sstevel@tonic-gate ttymux_query_links_ioctl(mblk_t *mp) 9387c478bd9Sstevel@tonic-gate { 9397c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 9407c478bd9Sstevel@tonic-gate struct copyreq *cqp; 9417c478bd9Sstevel@tonic-gate int unit; 9427c478bd9Sstevel@tonic-gate sm_lqi_t *lqi; 9437c478bd9Sstevel@tonic-gate mblk_t *nmp; 9447c478bd9Sstevel@tonic-gate int cnt; 9457c478bd9Sstevel@tonic-gate void *asl; 9467c478bd9Sstevel@tonic-gate void *uaddr; 9477c478bd9Sstevel@tonic-gate size_t sz; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_IOCDATA) { 9507c478bd9Sstevel@tonic-gate return (sm_iocresp(mp)); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate /* 9537c478bd9Sstevel@tonic-gate * Is this a query for the number of linked devices? 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate if (iobp->ioc_count == 0) { 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate for (unit = 0, iobp->ioc_rval = 0; 9587c478bd9Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 9597c478bd9Sstevel@tonic-gate unit++) 9607c478bd9Sstevel@tonic-gate if (lqi->sm_linkid != 0) 9617c478bd9Sstevel@tonic-gate iobp->ioc_rval += 1; 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate iobp->ioc_rval += count_unconfigured_consoles(sm_ssp->sm_ms); 9647c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCACK; 9657c478bd9Sstevel@tonic-gate iobp->ioc_error = 0; 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate return (0); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) { 9717c478bd9Sstevel@tonic-gate sm_dbg('Y', ("TTYMUX_LIST: b_cont is NULL\n")); 9727c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 9737c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 9747c478bd9Sstevel@tonic-gate return (EINVAL); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate asl = mp->b_cont->b_rptr; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 9807c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 9817c478bd9Sstevel@tonic-gate cnt = ((ttymux_assocs32_t *)asl)->ttymux32_nlinks; 9827c478bd9Sstevel@tonic-gate sz = cnt * sizeof (ttymux_assoc32_t); 983544f04c0Swnelson uaddr = (void *)(uintptr_t) 984544f04c0Swnelson ((ttymux_assocs32_t *)asl)->ttymux32_assocs; 9857c478bd9Sstevel@tonic-gate } else 9867c478bd9Sstevel@tonic-gate #endif 9877c478bd9Sstevel@tonic-gate { 9887c478bd9Sstevel@tonic-gate cnt = ((ttymux_assocs_t *)asl)->ttymux_nlinks; 9897c478bd9Sstevel@tonic-gate sz = cnt * sizeof (ttymux_assoc_t); 9907c478bd9Sstevel@tonic-gate uaddr = (void *)((ttymux_assocs_t *)asl)->ttymux_assocs; 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate if ((nmp = sm_allocb(sz, BPRI_MED)) == NULL) { 9937c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 9947c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 9957c478bd9Sstevel@tonic-gate return (EAGAIN); 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate sm_dbg('Y', ("TTYMUX_LIST: cnt %d sz %d uaddr 0x%p\n", cnt, sz, uaddr)); 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate iobp->ioc_rval = 0; 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 10037c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 10047c478bd9Sstevel@tonic-gate ttymux_assoc32_t *assoc; 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate sm_dbg('Y', ("!Native: %d structures\n", cnt)); 10077c478bd9Sstevel@tonic-gate assoc = (ttymux_assoc32_t *)nmp->b_rptr; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate for (unit = 0; 10107c478bd9Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 10117c478bd9Sstevel@tonic-gate unit++) { 10127c478bd9Sstevel@tonic-gate if (lqi->sm_linkid != 0) { 10137c478bd9Sstevel@tonic-gate if (cnt-- == 0) 10147c478bd9Sstevel@tonic-gate break; 10157c478bd9Sstevel@tonic-gate LQI2ASSOC32(assoc, lqi); 10167c478bd9Sstevel@tonic-gate assoc++; 10177c478bd9Sstevel@tonic-gate iobp->ioc_rval += 1; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate if (cnt > 0) { 10217c478bd9Sstevel@tonic-gate /* see if there are unconfigured consoles */ 10227c478bd9Sstevel@tonic-gate iobp->ioc_rval += 10237c478bd9Sstevel@tonic-gate get_unconfigured_consoles32(sm_ssp->sm_ms, assoc); 10247c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d unconfigured consoles\n", 10257c478bd9Sstevel@tonic-gate iobp->ioc_rval)); 10267c478bd9Sstevel@tonic-gate } else { 10277c478bd9Sstevel@tonic-gate sm_dbg('I', ("no more space in user addr\n")); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate ((ttymux_assocs32_t *)asl)->ttymux32_nlinks = iobp->ioc_rval; 10307c478bd9Sstevel@tonic-gate } else 10317c478bd9Sstevel@tonic-gate #endif 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate ttymux_assoc_t *assoc; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate sm_dbg('Y', ("!Native: %d structures\n", cnt)); 10367c478bd9Sstevel@tonic-gate assoc = (ttymux_assoc_t *)nmp->b_wptr; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate for (unit = 0; 10397c478bd9Sstevel@tonic-gate unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); 10407c478bd9Sstevel@tonic-gate unit++) { 10417c478bd9Sstevel@tonic-gate if (lqi->sm_linkid != 0) { 10427c478bd9Sstevel@tonic-gate if (cnt-- == 0) 10437c478bd9Sstevel@tonic-gate break; 10447c478bd9Sstevel@tonic-gate LQI2ASSOC(assoc, lqi); 10457c478bd9Sstevel@tonic-gate assoc++; 10467c478bd9Sstevel@tonic-gate iobp->ioc_rval += 1; 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate if (cnt > 0) { 10507c478bd9Sstevel@tonic-gate /* see if there are unconfigured consoles */ 10517c478bd9Sstevel@tonic-gate iobp->ioc_rval += 10527c478bd9Sstevel@tonic-gate get_unconfigured_consoles(sm_ssp->sm_ms, assoc); 10537c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d unconfigured consoles\n", 10547c478bd9Sstevel@tonic-gate iobp->ioc_rval)); 10557c478bd9Sstevel@tonic-gate } else { 10567c478bd9Sstevel@tonic-gate sm_dbg('I', ("no more space in user addr\n")); 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate ((ttymux_assocs_t *)asl)->ttymux_nlinks = iobp->ioc_rval; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 10627c478bd9Sstevel@tonic-gate cqp->cq_addr = uaddr; 10637c478bd9Sstevel@tonic-gate cqp->cq_size = sz; 10647c478bd9Sstevel@tonic-gate cqp->cq_flag = 0; 10657c478bd9Sstevel@tonic-gate cqp->cq_private = mp->b_cont; 10667c478bd9Sstevel@tonic-gate mp->b_cont = nmp; 10677c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sz; 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_COPYOUT; 10707c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate return (0); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate /* 10767c478bd9Sstevel@tonic-gate * Process a TTYMUX_CONSDEV ioctl. 10777c478bd9Sstevel@tonic-gate */ 10787c478bd9Sstevel@tonic-gate static int 10797c478bd9Sstevel@tonic-gate ttymux_console_ioctl(mblk_t *mp) 10807c478bd9Sstevel@tonic-gate { 10817c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 10827c478bd9Sstevel@tonic-gate int err = EINVAL; 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate sm_dbg('I', ("ttymux_console_ioctl:\n")); 10857c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 10867c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 10877c478bd9Sstevel@tonic-gate if (mp->b_cont && iobp->ioc_count >= sizeof (dev32_t)) { 10887c478bd9Sstevel@tonic-gate dev32_t dev; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate (void) cmpldev(&dev, rconsdev); 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate *(dev32_t *)mp->b_cont->b_rptr = dev; 10937c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (dev); 10947c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (dev); 10957c478bd9Sstevel@tonic-gate err = 0; 10967c478bd9Sstevel@tonic-gate } else { 10977c478bd9Sstevel@tonic-gate sm_dbg('I', ("TTYMUX_CONSDEV: b_cont 0x%p count %d\n", 10987c478bd9Sstevel@tonic-gate mp->b_cont, iobp->ioc_count)); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate } else 11017c478bd9Sstevel@tonic-gate #endif 11027c478bd9Sstevel@tonic-gate if (mp->b_cont && iobp->ioc_count >= sizeof (dev_t)) { 11037c478bd9Sstevel@tonic-gate *(dev_t *)mp->b_cont->b_rptr = rconsdev; 11047c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (rconsdev); 11057c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (rconsdev); 11067c478bd9Sstevel@tonic-gate err = 0; 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate return (err); 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate /* 11127c478bd9Sstevel@tonic-gate * Process a ioctl relating to aborting on the console. 11137c478bd9Sstevel@tonic-gate */ 11147c478bd9Sstevel@tonic-gate int 11157c478bd9Sstevel@tonic-gate ttymux_abort_ioctl(mblk_t *mp) 11167c478bd9Sstevel@tonic-gate { 11177c478bd9Sstevel@tonic-gate struct iocblk *iobp; 11187c478bd9Sstevel@tonic-gate int cmd, err = 0; 11197c478bd9Sstevel@tonic-gate sm_lqi_t *lqi; 11207c478bd9Sstevel@tonic-gate ttymux_abort_t *abreq; 11217c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11227c478bd9Sstevel@tonic-gate struct ttymux_abort32 { 11237c478bd9Sstevel@tonic-gate dev32_t ldev; 11247c478bd9Sstevel@tonic-gate enum ttymux_break_type method; 11257c478bd9Sstevel@tonic-gate uint32_t enable; 11267c478bd9Sstevel@tonic-gate } *abreq32; 11277c478bd9Sstevel@tonic-gate #endif 11287c478bd9Sstevel@tonic-gate dev_t ldev; 11297c478bd9Sstevel@tonic-gate enum ttymux_break_type method; 11307c478bd9Sstevel@tonic-gate uint_t enable; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate iobp = (struct iocblk *)mp->b_rptr; 11337c478bd9Sstevel@tonic-gate cmd = iobp->ioc_cmd; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate iobp->ioc_error = 0; 11367c478bd9Sstevel@tonic-gate iobp->ioc_rval = 0; 11377c478bd9Sstevel@tonic-gate sm_dbg('I', ("ttymux_abort_ioctl:\n")); 11387c478bd9Sstevel@tonic-gate switch (cmd) { 11397c478bd9Sstevel@tonic-gate case CONSSETABORTENABLE: 11407c478bd9Sstevel@tonic-gate lqi = (sm_ssp->sm_lconsole) ? sm_ssp->sm_lconsole->sm_lqs : 0; 11417c478bd9Sstevel@tonic-gate enable = (*(intptr_t *)mp->b_cont->b_rptr) ? 1 : 0; 11427c478bd9Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = sm_ssp->sm_break_abort_on = enable; 11437c478bd9Sstevel@tonic-gate for (; lqi != 0; lqi = lqi->sm_nlqi) { 11447c478bd9Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 11457c478bd9Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate break; 11487c478bd9Sstevel@tonic-gate case CONSGETABORTENABLE: 11497c478bd9Sstevel@tonic-gate if (mp->b_cont == 0 || iobp->ioc_count < sizeof (intptr_t)) { 11507c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 11517c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 11527c478bd9Sstevel@tonic-gate } else { 11537c478bd9Sstevel@tonic-gate *(intptr_t *)mp->b_cont->b_rptr = 11547c478bd9Sstevel@tonic-gate (sm_ssp->sm_ctrla_abort_on || 11557c478bd9Sstevel@tonic-gate sm_ssp->sm_break_abort_on); 11567c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = 11577c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr + sizeof (intptr_t); 11587c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (intptr_t); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate break; 11617c478bd9Sstevel@tonic-gate case TTYMUX_GETABORTSTR: 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate if (iobp->ioc_count < strlen(sm_ssp->sm_abs) + 1 || 11647c478bd9Sstevel@tonic-gate mp->b_cont == 0 || 11657c478bd9Sstevel@tonic-gate mp->b_cont->b_cont) { 11667c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 11677c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 11687c478bd9Sstevel@tonic-gate } else { 11697c478bd9Sstevel@tonic-gate (void) strcpy((char *)mp->b_cont->b_rptr, 11707c478bd9Sstevel@tonic-gate sm_ssp->sm_abs); 11717c478bd9Sstevel@tonic-gate iobp->ioc_count = strlen(sm_ssp->sm_abs) + 1; 11727c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = 11737c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr + iobp->ioc_count; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate break; 11767c478bd9Sstevel@tonic-gate case TTYMUX_GETABORT: 11777c478bd9Sstevel@tonic-gate case TTYMUX_SETABORT: 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate lqi = 0; 11807c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11817c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 11827c478bd9Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*abreq32) || 11837c478bd9Sstevel@tonic-gate mp->b_cont == 0) { 11847c478bd9Sstevel@tonic-gate err = EINVAL; 11857c478bd9Sstevel@tonic-gate } else { 11867c478bd9Sstevel@tonic-gate abreq32 = (struct ttymux_abort32 *) 11877c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr; 11887c478bd9Sstevel@tonic-gate ldev = expldev(abreq32->ldev); 11897c478bd9Sstevel@tonic-gate method = abreq32->method; 11907c478bd9Sstevel@tonic-gate enable = (uint_t)abreq32->enable; 11917c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (*abreq32); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate } else 11947c478bd9Sstevel@tonic-gate #endif 11957c478bd9Sstevel@tonic-gate if (iobp->ioc_count < sizeof (*abreq) || 11967c478bd9Sstevel@tonic-gate mp->b_cont == 0) { 11977c478bd9Sstevel@tonic-gate err = EINVAL; 11987c478bd9Sstevel@tonic-gate } else { 11997c478bd9Sstevel@tonic-gate abreq = (ttymux_abort_t *)mp->b_cont->b_rptr; 12007c478bd9Sstevel@tonic-gate ldev = abreq->ttymux_ldev; 12017c478bd9Sstevel@tonic-gate method = abreq->ttymux_method; 12027c478bd9Sstevel@tonic-gate enable = abreq->ttymux_enable; 12037c478bd9Sstevel@tonic-gate iobp->ioc_count = sizeof (*abreq); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate if (err != 0) { 12077c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 12087c478bd9Sstevel@tonic-gate return ((iobp->ioc_error = err)); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate sm_dbg('Y', ("ttymux_abort_ioctl: type %d how %d ldev %d:%d\n", 12127c478bd9Sstevel@tonic-gate method, enable, getmajor(ldev), getminor(ldev))); 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate lqi = get_lqi_bydevt(ldev); 12157c478bd9Sstevel@tonic-gate if (ldev != NODEV && lqi == 0) { 12167c478bd9Sstevel@tonic-gate err = ENOLINK; 12177c478bd9Sstevel@tonic-gate } else if (cmd == TTYMUX_GETABORT && lqi == 0) { 12187c478bd9Sstevel@tonic-gate err = ENODEV; 12197c478bd9Sstevel@tonic-gate } else if (cmd == TTYMUX_GETABORT) { 12207c478bd9Sstevel@tonic-gate if (lqi->sm_break_abort_on == 0 && 12217c478bd9Sstevel@tonic-gate lqi->sm_ctrla_abort_on == 0) { 12227c478bd9Sstevel@tonic-gate method = SOFTHARD_BREAK; 12237c478bd9Sstevel@tonic-gate enable = 0; 12247c478bd9Sstevel@tonic-gate } else { 12257c478bd9Sstevel@tonic-gate enable = 1; 12267c478bd9Sstevel@tonic-gate if (lqi->sm_break_abort_on == 0) 12277c478bd9Sstevel@tonic-gate method = SOFTWARE_BREAK; 12287c478bd9Sstevel@tonic-gate else if (lqi->sm_ctrla_abort_on == 0) 12297c478bd9Sstevel@tonic-gate method = HARDWARE_BREAK; 12307c478bd9Sstevel@tonic-gate else 12317c478bd9Sstevel@tonic-gate method = SOFTHARD_BREAK; 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 12357c478bd9Sstevel@tonic-gate if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { 12367c478bd9Sstevel@tonic-gate abreq32->method = method; 12377c478bd9Sstevel@tonic-gate abreq32->enable = (uint32_t)enable; 12387c478bd9Sstevel@tonic-gate } else 12397c478bd9Sstevel@tonic-gate #endif 12407c478bd9Sstevel@tonic-gate { 12417c478bd9Sstevel@tonic-gate abreq->ttymux_method = method; 12427c478bd9Sstevel@tonic-gate abreq->ttymux_enable = enable; 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate } else { 12457c478bd9Sstevel@tonic-gate iobp->ioc_count = 0; 12467c478bd9Sstevel@tonic-gate sm_dbg('I', ("lqi is 0x%p\n", lqi)); 12477c478bd9Sstevel@tonic-gate if (lqi == 0) { 12487c478bd9Sstevel@tonic-gate if (method == HARDWARE_BREAK) 12497c478bd9Sstevel@tonic-gate sm_ssp->sm_break_abort_on = enable; 12507c478bd9Sstevel@tonic-gate else if (method == SOFTWARE_BREAK) 12517c478bd9Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = enable; 12527c478bd9Sstevel@tonic-gate else if (method == SOFTHARD_BREAK) { 12537c478bd9Sstevel@tonic-gate sm_ssp->sm_break_abort_on = enable; 12547c478bd9Sstevel@tonic-gate sm_ssp->sm_ctrla_abort_on = enable; 12557c478bd9Sstevel@tonic-gate } else { 12567c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d - invalid\n", method)); 12577c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 12587c478bd9Sstevel@tonic-gate return ((iobp->ioc_error = EINVAL)); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (sm_ssp->sm_lconsole) { 12627c478bd9Sstevel@tonic-gate sm_dbg('I', ("lconsole 0x%p (0x%p)\n", 12637c478bd9Sstevel@tonic-gate sm_ssp->sm_lconsole, 12647c478bd9Sstevel@tonic-gate sm_ssp->sm_lconsole->sm_lqs)); 12657c478bd9Sstevel@tonic-gate } else { 12667c478bd9Sstevel@tonic-gate sm_dbg('I', ("lconsole is null\n")); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate lqi = (sm_ssp->sm_lconsole) ? 12707c478bd9Sstevel@tonic-gate sm_ssp->sm_lconsole->sm_lqs : 0; 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate while (lqi) { 12737c478bd9Sstevel@tonic-gate if (method == HARDWARE_BREAK) 12747c478bd9Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 12757c478bd9Sstevel@tonic-gate else if (method == SOFTWARE_BREAK) 12767c478bd9Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 12777c478bd9Sstevel@tonic-gate else if (method == SOFTHARD_BREAK) { 12787c478bd9Sstevel@tonic-gate lqi->sm_break_abort_on = enable; 12797c478bd9Sstevel@tonic-gate lqi->sm_ctrla_abort_on = enable; 12807c478bd9Sstevel@tonic-gate } else { 12817c478bd9Sstevel@tonic-gate sm_dbg('I', ("%d: invalid\n", method)); 12827c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 12837c478bd9Sstevel@tonic-gate return ((iobp->ioc_error = EINVAL)); 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate lqi = (ldev == NODEV) ? lqi->sm_nlqi : 0; 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate iobp->ioc_rval = err ? -1 : 0; 12907c478bd9Sstevel@tonic-gate iobp->ioc_error = err; 12917c478bd9Sstevel@tonic-gate break; 12927c478bd9Sstevel@tonic-gate default: 12937c478bd9Sstevel@tonic-gate iobp->ioc_rval = -1; 12947c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate return (iobp->ioc_error); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* 13007c478bd9Sstevel@tonic-gate * Process ioctls specific to the ttymux driver. 13017c478bd9Sstevel@tonic-gate */ 13027c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 13037c478bd9Sstevel@tonic-gate int 13047c478bd9Sstevel@tonic-gate sm_ioctl_cmd(sm_uqi_t *uqi, mblk_t *mp) 13057c478bd9Sstevel@tonic-gate { 13067c478bd9Sstevel@tonic-gate struct iocblk *iobp = (struct iocblk *)mp->b_rptr; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate iobp->ioc_rval = 0; 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* 13117c478bd9Sstevel@tonic-gate * This routine does not support transparent ioctls 13127c478bd9Sstevel@tonic-gate */ 13137c478bd9Sstevel@tonic-gate if (iobp->ioc_count == TRANSPARENT) { 13147c478bd9Sstevel@tonic-gate sm_dbg('Y', ("sm_ioctl_cmd: unsupported ioctl\n")); 13157c478bd9Sstevel@tonic-gate iobp->ioc_error = ENOTSUP; 13167c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_IOCNAK; 13177c478bd9Sstevel@tonic-gate if (mp->b_cont) 13187c478bd9Sstevel@tonic-gate freemsg(unlinkb(mp)); 13197c478bd9Sstevel@tonic-gate return (ENOTSUP); 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate switch (iobp->ioc_cmd) { 13237c478bd9Sstevel@tonic-gate case TTYMUX_CONSDEV: 13247c478bd9Sstevel@tonic-gate iobp->ioc_error = ttymux_console_ioctl(mp); 13257c478bd9Sstevel@tonic-gate break; 13267c478bd9Sstevel@tonic-gate case TTYMUX_ASSOC: 13277c478bd9Sstevel@tonic-gate case TTYMUX_DISASSOC: 13287c478bd9Sstevel@tonic-gate iobp->ioc_error = ttymux_link_ioctl(mp); 13297c478bd9Sstevel@tonic-gate break; 13307c478bd9Sstevel@tonic-gate case TTYMUX_GETLINK: 13317c478bd9Sstevel@tonic-gate iobp->ioc_error = ttymux_query_link_ioctl(mp); 13327c478bd9Sstevel@tonic-gate break; 13337c478bd9Sstevel@tonic-gate case TTYMUX_LIST: 13347c478bd9Sstevel@tonic-gate return (ttymux_query_links_ioctl(mp)); 13357c478bd9Sstevel@tonic-gate case TTYMUX_SETCTL: 13367c478bd9Sstevel@tonic-gate case TTYMUX_GETCTL: 13377c478bd9Sstevel@tonic-gate iobp->ioc_error = ENOTSUP; 13387c478bd9Sstevel@tonic-gate break; 13397c478bd9Sstevel@tonic-gate case TTYMUX_GETABORTSTR: 13407c478bd9Sstevel@tonic-gate case TTYMUX_SETABORT: 13417c478bd9Sstevel@tonic-gate case TTYMUX_GETABORT: 13427c478bd9Sstevel@tonic-gate iobp->ioc_error = ttymux_abort_ioctl(mp); 13437c478bd9Sstevel@tonic-gate break; 13447c478bd9Sstevel@tonic-gate default: 13457c478bd9Sstevel@tonic-gate iobp->ioc_error = EINVAL; 13467c478bd9Sstevel@tonic-gate break; 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if ((iobp->ioc_error || iobp->ioc_count == 0) && mp->b_cont) 13527c478bd9Sstevel@tonic-gate freemsg(unlinkb(mp)); 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate sm_dbg('I', ("TTYMUX IOCTL: err %d rval %d count %d\n", 13557c478bd9Sstevel@tonic-gate iobp->ioc_error, iobp->ioc_rval, iobp->ioc_count)); 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate return (iobp->ioc_error); 13587c478bd9Sstevel@tonic-gate } 1359