1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* from S5R4 1.13 */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * Description: 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * The PTEM streams module is used as a pseudo driver emulator. Its purpose 37*7c478bd9Sstevel@tonic-gate * is to emulate the ioctl() functions of a terminal device driver. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/termio.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/pcb.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/strtty.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/jioctl.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/ptem.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/ptms.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate extern struct streamtab pteminfo; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 65*7c478bd9Sstevel@tonic-gate "ptem", 66*7c478bd9Sstevel@tonic-gate &pteminfo, 67*7c478bd9Sstevel@tonic-gate D_MTQPAIR | D_MP 68*7c478bd9Sstevel@tonic-gate }; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 71*7c478bd9Sstevel@tonic-gate &mod_strmodops, "pty hardware emulator", &fsw 72*7c478bd9Sstevel@tonic-gate }; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 75*7c478bd9Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL 76*7c478bd9Sstevel@tonic-gate }; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate int 79*7c478bd9Sstevel@tonic-gate _init() 80*7c478bd9Sstevel@tonic-gate { 81*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 82*7c478bd9Sstevel@tonic-gate } 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate int 85*7c478bd9Sstevel@tonic-gate _fini() 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate int 91*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * stream data structure definitions 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate static int ptemopen(queue_t *, dev_t *, int, int, cred_t *); 100*7c478bd9Sstevel@tonic-gate static int ptemclose(queue_t *, int, cred_t *); 101*7c478bd9Sstevel@tonic-gate static void ptemrput(queue_t *, mblk_t *); 102*7c478bd9Sstevel@tonic-gate static void ptemwput(queue_t *, mblk_t *); 103*7c478bd9Sstevel@tonic-gate static void ptemwsrv(queue_t *); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static struct module_info ptem_info = { 106*7c478bd9Sstevel@tonic-gate 0xabcd, 107*7c478bd9Sstevel@tonic-gate "ptem", 108*7c478bd9Sstevel@tonic-gate 0, 109*7c478bd9Sstevel@tonic-gate 512, 110*7c478bd9Sstevel@tonic-gate 512, 111*7c478bd9Sstevel@tonic-gate 128 112*7c478bd9Sstevel@tonic-gate }; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate static struct qinit ptemrinit = { 115*7c478bd9Sstevel@tonic-gate (int (*)()) ptemrput, 116*7c478bd9Sstevel@tonic-gate NULL, 117*7c478bd9Sstevel@tonic-gate ptemopen, 118*7c478bd9Sstevel@tonic-gate ptemclose, 119*7c478bd9Sstevel@tonic-gate NULL, 120*7c478bd9Sstevel@tonic-gate &ptem_info, 121*7c478bd9Sstevel@tonic-gate NULL 122*7c478bd9Sstevel@tonic-gate }; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate static struct qinit ptemwinit = { 125*7c478bd9Sstevel@tonic-gate (int (*)()) ptemwput, 126*7c478bd9Sstevel@tonic-gate (int (*)()) ptemwsrv, 127*7c478bd9Sstevel@tonic-gate ptemopen, 128*7c478bd9Sstevel@tonic-gate ptemclose, 129*7c478bd9Sstevel@tonic-gate nulldev, 130*7c478bd9Sstevel@tonic-gate &ptem_info, 131*7c478bd9Sstevel@tonic-gate NULL 132*7c478bd9Sstevel@tonic-gate }; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate struct streamtab pteminfo = { 135*7c478bd9Sstevel@tonic-gate &ptemrinit, 136*7c478bd9Sstevel@tonic-gate &ptemwinit, 137*7c478bd9Sstevel@tonic-gate NULL, 138*7c478bd9Sstevel@tonic-gate NULL 139*7c478bd9Sstevel@tonic-gate }; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static void ptioc(queue_t *, mblk_t *, int); 142*7c478bd9Sstevel@tonic-gate static int ptemwmsg(queue_t *, mblk_t *); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * ptemopen - open routine gets called when the module gets pushed onto the 146*7c478bd9Sstevel@tonic-gate * stream. 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 149*7c478bd9Sstevel@tonic-gate static int 150*7c478bd9Sstevel@tonic-gate ptemopen( 151*7c478bd9Sstevel@tonic-gate queue_t *q, /* pointer to the read side queue */ 152*7c478bd9Sstevel@tonic-gate dev_t *devp, /* pointer to stream tail's dev */ 153*7c478bd9Sstevel@tonic-gate int oflag, /* the user open(2) supplied flags */ 154*7c478bd9Sstevel@tonic-gate int sflag, /* open state flag */ 155*7c478bd9Sstevel@tonic-gate cred_t *credp) /* credentials */ 156*7c478bd9Sstevel@tonic-gate { 157*7c478bd9Sstevel@tonic-gate struct ptem *ntp; /* ptem entry for this PTEM module */ 158*7c478bd9Sstevel@tonic-gate mblk_t *mop; /* an setopts mblk */ 159*7c478bd9Sstevel@tonic-gate struct stroptions *sop; 160*7c478bd9Sstevel@tonic-gate struct termios *termiosp; 161*7c478bd9Sstevel@tonic-gate int len; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate if (sflag != MODOPEN) 164*7c478bd9Sstevel@tonic-gate return (EINVAL); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) { 167*7c478bd9Sstevel@tonic-gate /* It's already attached. */ 168*7c478bd9Sstevel@tonic-gate return (0); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Allocate state structure. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Allocate a message block, used to pass the zero length message for 178*7c478bd9Sstevel@tonic-gate * "stty 0". 179*7c478bd9Sstevel@tonic-gate * 180*7c478bd9Sstevel@tonic-gate * NOTE: it's better to find out if such a message block can be 181*7c478bd9Sstevel@tonic-gate * allocated before it's needed than to not be able to 182*7c478bd9Sstevel@tonic-gate * deliver (for possible lack of buffers) when a hang-up 183*7c478bd9Sstevel@tonic-gate * occurs. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) { 186*7c478bd9Sstevel@tonic-gate kmem_free(ntp, sizeof (*ntp)); 187*7c478bd9Sstevel@tonic-gate return (EAGAIN); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Initialize an M_SETOPTS message to set up hi/lo water marks on 192*7c478bd9Sstevel@tonic-gate * stream head read queue and add controlling tty if not set. 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate mop = allocb(sizeof (struct stroptions), BPRI_MED); 195*7c478bd9Sstevel@tonic-gate if (mop == NULL) { 196*7c478bd9Sstevel@tonic-gate freemsg(ntp->dack_ptr); 197*7c478bd9Sstevel@tonic-gate kmem_free(ntp, sizeof (*ntp)); 198*7c478bd9Sstevel@tonic-gate return (EAGAIN); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate mop->b_datap->db_type = M_SETOPTS; 201*7c478bd9Sstevel@tonic-gate mop->b_wptr += sizeof (struct stroptions); 202*7c478bd9Sstevel@tonic-gate sop = (struct stroptions *)mop->b_rptr; 203*7c478bd9Sstevel@tonic-gate sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY; 204*7c478bd9Sstevel@tonic-gate sop->so_hiwat = 512; 205*7c478bd9Sstevel@tonic-gate sop->so_lowat = 256; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * Cross-link. 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate ntp->q_ptr = q; 211*7c478bd9Sstevel@tonic-gate q->q_ptr = ntp; 212*7c478bd9Sstevel@tonic-gate WR(q)->q_ptr = ntp; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Get termios defaults. These are stored as 216*7c478bd9Sstevel@tonic-gate * a property in the "options" node. 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes", 219*7c478bd9Sstevel@tonic-gate (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS && 220*7c478bd9Sstevel@tonic-gate len == sizeof (struct termios)) { 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate ntp->cflags = termiosp->c_cflag; 223*7c478bd9Sstevel@tonic-gate kmem_free(termiosp, len); 224*7c478bd9Sstevel@tonic-gate } else { 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Gack! Whine about it. 227*7c478bd9Sstevel@tonic-gate */ 228*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!"); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate ntp->wsz.ws_row = 0; 231*7c478bd9Sstevel@tonic-gate ntp->wsz.ws_col = 0; 232*7c478bd9Sstevel@tonic-gate ntp->wsz.ws_xpixel = 0; 233*7c478bd9Sstevel@tonic-gate ntp->wsz.ws_ypixel = 0; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate ntp->state = 0; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate * Commit to the open and send the M_SETOPTS off to the stream head. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate qprocson(q); 241*7c478bd9Sstevel@tonic-gate putnext(q, mop); 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate return (0); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * ptemclose - This routine gets called when the module gets popped off of the 249*7c478bd9Sstevel@tonic-gate * stream. 250*7c478bd9Sstevel@tonic-gate */ 251*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 252*7c478bd9Sstevel@tonic-gate static int 253*7c478bd9Sstevel@tonic-gate ptemclose(queue_t *q, int flag, cred_t *credp) 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate struct ptem *ntp; /* ptem entry for this PTEM module */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate qprocsoff(q); 258*7c478bd9Sstevel@tonic-gate ntp = (struct ptem *)q->q_ptr; 259*7c478bd9Sstevel@tonic-gate freemsg(ntp->dack_ptr); 260*7c478bd9Sstevel@tonic-gate kmem_free(ntp, sizeof (*ntp)); 261*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 262*7c478bd9Sstevel@tonic-gate return (0); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * ptemrput - Module read queue put procedure. 268*7c478bd9Sstevel@tonic-gate * 269*7c478bd9Sstevel@tonic-gate * This is called from the module or driver downstream. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate static void 272*7c478bd9Sstevel@tonic-gate ptemrput(queue_t *q, mblk_t *mp) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; /* M_IOCTL data */ 275*7c478bd9Sstevel@tonic-gate struct copyresp *resp; /* transparent ioctl response struct */ 276*7c478bd9Sstevel@tonic-gate int error; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 279*7c478bd9Sstevel@tonic-gate case M_DELAY: 280*7c478bd9Sstevel@tonic-gate case M_READ: 281*7c478bd9Sstevel@tonic-gate freemsg(mp); 282*7c478bd9Sstevel@tonic-gate break; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate case M_IOCTL: 285*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 288*7c478bd9Sstevel@tonic-gate case TCSBRK: 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Send a break message upstream. 291*7c478bd9Sstevel@tonic-gate * 292*7c478bd9Sstevel@tonic-gate * XXX: Shouldn't the argument come into play in 293*7c478bd9Sstevel@tonic-gate * determining whether or not so send an M_BREAK? 294*7c478bd9Sstevel@tonic-gate * It certainly does in the write-side direction. 295*7c478bd9Sstevel@tonic-gate */ 296*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (int)); 297*7c478bd9Sstevel@tonic-gate if (error != 0) { 298*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate if (!(*(int *)mp->b_cont->b_rptr)) { 302*7c478bd9Sstevel@tonic-gate if (!putnextctl(q, M_BREAK)) { 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * Send an NAK reply back 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * ACK it. 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 314*7c478bd9Sstevel@tonic-gate qreply(q, mp); 315*7c478bd9Sstevel@tonic-gate break; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate case JWINSIZE: 318*7c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 319*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 320*7c478bd9Sstevel@tonic-gate ptioc(q, mp, RDSIDE); 321*7c478bd9Sstevel@tonic-gate break; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate case TIOCSIGNAL: 324*7c478bd9Sstevel@tonic-gate /* 325*7c478bd9Sstevel@tonic-gate * The following subtle logic is due to the fact that 326*7c478bd9Sstevel@tonic-gate * `mp' may be in any one of three distinct formats: 327*7c478bd9Sstevel@tonic-gate * 328*7c478bd9Sstevel@tonic-gate * 1. A transparent M_IOCTL with an intptr_t-sized 329*7c478bd9Sstevel@tonic-gate * payload containing the signal number. 330*7c478bd9Sstevel@tonic-gate * 331*7c478bd9Sstevel@tonic-gate * 2. An I_STR M_IOCTL with an int-sized payload 332*7c478bd9Sstevel@tonic-gate * containing the signal number. 333*7c478bd9Sstevel@tonic-gate * 334*7c478bd9Sstevel@tonic-gate * 3. An M_IOCDATA with an int-sized payload 335*7c478bd9Sstevel@tonic-gate * containing the signal number. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) { 338*7c478bd9Sstevel@tonic-gate intptr_t sig = *(intptr_t *)mp->b_cont->b_rptr; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate if (sig < 1 || sig >= NSIG) { 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * it's transparent with pointer 343*7c478bd9Sstevel@tonic-gate * to the arg 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate mcopyin(mp, NULL, sizeof (int), NULL); 346*7c478bd9Sstevel@tonic-gate qreply(q, mp); 347*7c478bd9Sstevel@tonic-gate break; 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate ptioc(q, mp, RDSIDE); 351*7c478bd9Sstevel@tonic-gate break; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate case TIOCREMOTE: 354*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) 355*7c478bd9Sstevel@tonic-gate ptioc(q, mp, RDSIDE); 356*7c478bd9Sstevel@tonic-gate else { 357*7c478bd9Sstevel@tonic-gate mcopyin(mp, NULL, sizeof (int), NULL); 358*7c478bd9Sstevel@tonic-gate qreply(q, mp); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate default: 363*7c478bd9Sstevel@tonic-gate putnext(q, mp); 364*7c478bd9Sstevel@tonic-gate break; 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate break; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate case M_IOCDATA: 369*7c478bd9Sstevel@tonic-gate resp = (struct copyresp *)mp->b_rptr; 370*7c478bd9Sstevel@tonic-gate if (resp->cp_rval) { 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Just free message on failure. 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate freemsg(mp); 375*7c478bd9Sstevel@tonic-gate break; 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * Only need to copy data for the SET case. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate switch (resp->cp_cmd) { 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 384*7c478bd9Sstevel@tonic-gate case TIOCSIGNAL: 385*7c478bd9Sstevel@tonic-gate case TIOCREMOTE: 386*7c478bd9Sstevel@tonic-gate ptioc(q, mp, RDSIDE); 387*7c478bd9Sstevel@tonic-gate break; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate case JWINSIZE: 390*7c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 391*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 392*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 393*7c478bd9Sstevel@tonic-gate qreply(q, mp); 394*7c478bd9Sstevel@tonic-gate break; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate default: 397*7c478bd9Sstevel@tonic-gate freemsg(mp); 398*7c478bd9Sstevel@tonic-gate break; 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate break; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate case M_IOCACK: 403*7c478bd9Sstevel@tonic-gate case M_IOCNAK: 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * We only pass write-side ioctls through to the master that 406*7c478bd9Sstevel@tonic-gate * we've already ACKed or NAKed to the stream head. Thus, we 407*7c478bd9Sstevel@tonic-gate * discard ones arriving from below, since they're redundant 408*7c478bd9Sstevel@tonic-gate * from the point of view of modules above us. 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate freemsg(mp); 411*7c478bd9Sstevel@tonic-gate break; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate case M_HANGUP: 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * clear blocked state. 416*7c478bd9Sstevel@tonic-gate */ 417*7c478bd9Sstevel@tonic-gate { 418*7c478bd9Sstevel@tonic-gate struct ptem *ntp = (struct ptem *)q->q_ptr; 419*7c478bd9Sstevel@tonic-gate if (ntp->state & OFLOW_CTL) { 420*7c478bd9Sstevel@tonic-gate ntp->state &= ~OFLOW_CTL; 421*7c478bd9Sstevel@tonic-gate qenable(WR(q)); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate default: 425*7c478bd9Sstevel@tonic-gate putnext(q, mp); 426*7c478bd9Sstevel@tonic-gate break; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /* 432*7c478bd9Sstevel@tonic-gate * ptemwput - Module write queue put procedure. 433*7c478bd9Sstevel@tonic-gate * 434*7c478bd9Sstevel@tonic-gate * This is called from the module or stream head upstream. 435*7c478bd9Sstevel@tonic-gate * 436*7c478bd9Sstevel@tonic-gate * XXX: This routine is quite lazy about handling allocation failures, 437*7c478bd9Sstevel@tonic-gate * basically just giving up and reporting failure. It really ought to 438*7c478bd9Sstevel@tonic-gate * set up bufcalls and only fail when it's absolutely necessary. 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate static void 441*7c478bd9Sstevel@tonic-gate ptemwput(queue_t *q, mblk_t *mp) 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate struct ptem *ntp = (struct ptem *)q->q_ptr; 444*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; /* outgoing ioctl structure */ 445*7c478bd9Sstevel@tonic-gate struct copyresp *resp; 446*7c478bd9Sstevel@tonic-gate unsigned char type = mp->b_datap->db_type; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (type >= QPCTL) { 449*7c478bd9Sstevel@tonic-gate switch (type) { 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate case M_IOCDATA: 452*7c478bd9Sstevel@tonic-gate resp = (struct copyresp *)mp->b_rptr; 453*7c478bd9Sstevel@tonic-gate if (resp->cp_rval) { 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * Just free message on failure. 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate freemsg(mp); 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * Only need to copy data for the SET case. 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate switch (resp->cp_cmd) { 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 467*7c478bd9Sstevel@tonic-gate ptioc(q, mp, WRSIDE); 468*7c478bd9Sstevel@tonic-gate break; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate case JWINSIZE: 471*7c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 472*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 473*7c478bd9Sstevel@tonic-gate qreply(q, mp); 474*7c478bd9Sstevel@tonic-gate break; 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate default: 477*7c478bd9Sstevel@tonic-gate freemsg(mp); 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate break; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate case M_FLUSH: 482*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 483*7c478bd9Sstevel@tonic-gate if ((ntp->state & IS_PTSTTY) && 484*7c478bd9Sstevel@tonic-gate (*mp->b_rptr & FLUSHBAND)) 485*7c478bd9Sstevel@tonic-gate flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 486*7c478bd9Sstevel@tonic-gate else 487*7c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate putnext(q, mp); 490*7c478bd9Sstevel@tonic-gate break; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate case M_READ: 493*7c478bd9Sstevel@tonic-gate freemsg(mp); 494*7c478bd9Sstevel@tonic-gate break; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate case M_STOP: 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * Set the output flow control state. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate ntp->state |= OFLOW_CTL; 501*7c478bd9Sstevel@tonic-gate putnext(q, mp); 502*7c478bd9Sstevel@tonic-gate break; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate case M_START: 505*7c478bd9Sstevel@tonic-gate /* 506*7c478bd9Sstevel@tonic-gate * Relieve the output flow control state. 507*7c478bd9Sstevel@tonic-gate */ 508*7c478bd9Sstevel@tonic-gate ntp->state &= ~OFLOW_CTL; 509*7c478bd9Sstevel@tonic-gate putnext(q, mp); 510*7c478bd9Sstevel@tonic-gate qenable(q); 511*7c478bd9Sstevel@tonic-gate break; 512*7c478bd9Sstevel@tonic-gate default: 513*7c478bd9Sstevel@tonic-gate putnext(q, mp); 514*7c478bd9Sstevel@tonic-gate break; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate return; 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate /* 519*7c478bd9Sstevel@tonic-gate * If our queue is nonempty or flow control persists 520*7c478bd9Sstevel@tonic-gate * downstream or module in stopped state, queue this message. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if (q->q_first != NULL || !bcanputnext(q, mp->b_band)) { 523*7c478bd9Sstevel@tonic-gate /* 524*7c478bd9Sstevel@tonic-gate * Exception: ioctls, except for those defined to 525*7c478bd9Sstevel@tonic-gate * take effect after output has drained, should be 526*7c478bd9Sstevel@tonic-gate * processed immediately. 527*7c478bd9Sstevel@tonic-gate */ 528*7c478bd9Sstevel@tonic-gate switch (type) { 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate case M_IOCTL: 531*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 532*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate * Queue these. 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate case TCSETSW: 537*7c478bd9Sstevel@tonic-gate case TCSETSF: 538*7c478bd9Sstevel@tonic-gate case TCSETAW: 539*7c478bd9Sstevel@tonic-gate case TCSETAF: 540*7c478bd9Sstevel@tonic-gate case TCSBRK: 541*7c478bd9Sstevel@tonic-gate break; 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* 544*7c478bd9Sstevel@tonic-gate * Handle all others immediately. 545*7c478bd9Sstevel@tonic-gate */ 546*7c478bd9Sstevel@tonic-gate default: 547*7c478bd9Sstevel@tonic-gate (void) ptemwmsg(q, mp); 548*7c478bd9Sstevel@tonic-gate return; 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate break; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate case M_DELAY: /* tty delays not supported */ 553*7c478bd9Sstevel@tonic-gate freemsg(mp); 554*7c478bd9Sstevel@tonic-gate return; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate case M_DATA: 557*7c478bd9Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) < 0) { 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * Free all bad length messages. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate freemsg(mp); 562*7c478bd9Sstevel@tonic-gate return; 563*7c478bd9Sstevel@tonic-gate } else if ((mp->b_wptr - mp->b_rptr) == 0) { 564*7c478bd9Sstevel@tonic-gate if (!(ntp->state & IS_PTSTTY)) { 565*7c478bd9Sstevel@tonic-gate freemsg(mp); 566*7c478bd9Sstevel@tonic-gate return; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate } 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 571*7c478bd9Sstevel@tonic-gate return; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate /* 574*7c478bd9Sstevel@tonic-gate * fast path into ptemwmsg to dispose of mp. 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate if (!ptemwmsg(q, mp)) 577*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * ptem write queue service procedure. 582*7c478bd9Sstevel@tonic-gate */ 583*7c478bd9Sstevel@tonic-gate static void 584*7c478bd9Sstevel@tonic-gate ptemwsrv(queue_t *q) 585*7c478bd9Sstevel@tonic-gate { 586*7c478bd9Sstevel@tonic-gate mblk_t *mp; 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 589*7c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band) || !ptemwmsg(q, mp)) { 590*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 591*7c478bd9Sstevel@tonic-gate break; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* 598*7c478bd9Sstevel@tonic-gate * This routine is called from both ptemwput and ptemwsrv to do the 599*7c478bd9Sstevel@tonic-gate * actual work of dealing with mp. ptmewput will have already 600*7c478bd9Sstevel@tonic-gate * dealt with high priority messages. 601*7c478bd9Sstevel@tonic-gate * 602*7c478bd9Sstevel@tonic-gate * Return 1 if the message was processed completely and 0 if not. 603*7c478bd9Sstevel@tonic-gate */ 604*7c478bd9Sstevel@tonic-gate static int 605*7c478bd9Sstevel@tonic-gate ptemwmsg(queue_t *q, mblk_t *mp) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate struct ptem *ntp = (struct ptem *)q->q_ptr; 608*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; /* outgoing ioctl structure */ 609*7c478bd9Sstevel@tonic-gate struct termio *termiop; 610*7c478bd9Sstevel@tonic-gate struct termios *termiosp; 611*7c478bd9Sstevel@tonic-gate mblk_t *dack_ptr; /* disconnect message ACK block */ 612*7c478bd9Sstevel@tonic-gate mblk_t *pckt_msgp; /* message sent to the PCKT module */ 613*7c478bd9Sstevel@tonic-gate mblk_t *dp; /* ioctl reply data */ 614*7c478bd9Sstevel@tonic-gate tcflag_t cflags; 615*7c478bd9Sstevel@tonic-gate int error; 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate case M_IOCTL: 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * Note: for each "set" type operation a copy 622*7c478bd9Sstevel@tonic-gate * of the M_IOCTL message is made and passed 623*7c478bd9Sstevel@tonic-gate * downstream. Eventually the PCKT module, if 624*7c478bd9Sstevel@tonic-gate * it has been pushed, should pick up this message. 625*7c478bd9Sstevel@tonic-gate * If the PCKT module has not been pushed the master 626*7c478bd9Sstevel@tonic-gate * side stream head will free it. 627*7c478bd9Sstevel@tonic-gate */ 628*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 629*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate case TCSETAF: 632*7c478bd9Sstevel@tonic-gate case TCSETSF: 633*7c478bd9Sstevel@tonic-gate /* 634*7c478bd9Sstevel@tonic-gate * Flush the read queue. 635*7c478bd9Sstevel@tonic-gate */ 636*7c478bd9Sstevel@tonic-gate if (putnextctl1(q, M_FLUSH, FLUSHR) == 0) { 637*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 638*7c478bd9Sstevel@tonic-gate break; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate case TCSETA: 643*7c478bd9Sstevel@tonic-gate case TCSETAW: 644*7c478bd9Sstevel@tonic-gate case TCSETS: 645*7c478bd9Sstevel@tonic-gate case TCSETSW: 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 648*7c478bd9Sstevel@tonic-gate case TCSETAF: 649*7c478bd9Sstevel@tonic-gate case TCSETA: 650*7c478bd9Sstevel@tonic-gate case TCSETAW: 651*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termio)); 652*7c478bd9Sstevel@tonic-gate if (error != 0) { 653*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 654*7c478bd9Sstevel@tonic-gate goto out; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate cflags = ((struct termio *) 657*7c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr)->c_cflag; 658*7c478bd9Sstevel@tonic-gate ntp->cflags = 659*7c478bd9Sstevel@tonic-gate (ntp->cflags & 0xffff0000 | cflags); 660*7c478bd9Sstevel@tonic-gate break; 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate case TCSETSF: 663*7c478bd9Sstevel@tonic-gate case TCSETS: 664*7c478bd9Sstevel@tonic-gate case TCSETSW: 665*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termios)); 666*7c478bd9Sstevel@tonic-gate if (error != 0) { 667*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 668*7c478bd9Sstevel@tonic-gate goto out; 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate cflags = ((struct termios *) 671*7c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr)->c_cflag; 672*7c478bd9Sstevel@tonic-gate ntp->cflags = cflags; 673*7c478bd9Sstevel@tonic-gate break; 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate if ((cflags & CBAUD) == B0) { 677*7c478bd9Sstevel@tonic-gate /* 678*7c478bd9Sstevel@tonic-gate * Hang-up: Send a zero length message. 679*7c478bd9Sstevel@tonic-gate */ 680*7c478bd9Sstevel@tonic-gate dack_ptr = ntp->dack_ptr; 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (dack_ptr) { 683*7c478bd9Sstevel@tonic-gate ntp->dack_ptr = NULL; 684*7c478bd9Sstevel@tonic-gate /* 685*7c478bd9Sstevel@tonic-gate * Send a zero length message 686*7c478bd9Sstevel@tonic-gate * downstream. 687*7c478bd9Sstevel@tonic-gate */ 688*7c478bd9Sstevel@tonic-gate putnext(q, dack_ptr); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate } else { 691*7c478bd9Sstevel@tonic-gate /* 692*7c478bd9Sstevel@tonic-gate * Make a copy of this message and pass it on 693*7c478bd9Sstevel@tonic-gate * to the PCKT module. 694*7c478bd9Sstevel@tonic-gate */ 695*7c478bd9Sstevel@tonic-gate if ((pckt_msgp = copymsg(mp)) == NULL) { 696*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 697*7c478bd9Sstevel@tonic-gate break; 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate putnext(q, pckt_msgp); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate /* 702*7c478bd9Sstevel@tonic-gate * Send ACK upstream. 703*7c478bd9Sstevel@tonic-gate */ 704*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 705*7c478bd9Sstevel@tonic-gate qreply(q, mp); 706*7c478bd9Sstevel@tonic-gate out: 707*7c478bd9Sstevel@tonic-gate break; 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate case TCGETA: 710*7c478bd9Sstevel@tonic-gate dp = allocb(sizeof (struct termio), BPRI_MED); 711*7c478bd9Sstevel@tonic-gate if (dp == NULL) { 712*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 713*7c478bd9Sstevel@tonic-gate break; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate termiop = (struct termio *)dp->b_rptr; 716*7c478bd9Sstevel@tonic-gate termiop->c_cflag = (ushort_t)ntp->cflags; 717*7c478bd9Sstevel@tonic-gate mioc2ack(mp, dp, sizeof (struct termio), 0); 718*7c478bd9Sstevel@tonic-gate qreply(q, mp); 719*7c478bd9Sstevel@tonic-gate break; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate case TCGETS: 722*7c478bd9Sstevel@tonic-gate dp = allocb(sizeof (struct termios), BPRI_MED); 723*7c478bd9Sstevel@tonic-gate if (dp == NULL) { 724*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate termiosp = (struct termios *)dp->b_rptr; 728*7c478bd9Sstevel@tonic-gate termiosp->c_cflag = ntp->cflags; 729*7c478bd9Sstevel@tonic-gate mioc2ack(mp, dp, sizeof (struct termios), 0); 730*7c478bd9Sstevel@tonic-gate qreply(q, mp); 731*7c478bd9Sstevel@tonic-gate break; 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate case TCSBRK: 734*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (int)); 735*7c478bd9Sstevel@tonic-gate if (error != 0) { 736*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 737*7c478bd9Sstevel@tonic-gate break; 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate /* 741*7c478bd9Sstevel@tonic-gate * Need a copy of this message to pass it on to 742*7c478bd9Sstevel@tonic-gate * the PCKT module. 743*7c478bd9Sstevel@tonic-gate */ 744*7c478bd9Sstevel@tonic-gate if ((pckt_msgp = copymsg(mp)) == NULL) { 745*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 746*7c478bd9Sstevel@tonic-gate break; 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * Send a copy of the M_IOCTL to the PCKT module. 750*7c478bd9Sstevel@tonic-gate */ 751*7c478bd9Sstevel@tonic-gate putnext(q, pckt_msgp); 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * TCSBRK meaningful if data part of message is 0 755*7c478bd9Sstevel@tonic-gate * cf. termio(7). 756*7c478bd9Sstevel@tonic-gate */ 757*7c478bd9Sstevel@tonic-gate if (!(*(int *)mp->b_cont->b_rptr)) 758*7c478bd9Sstevel@tonic-gate (void) putnextctl(q, M_BREAK); 759*7c478bd9Sstevel@tonic-gate /* 760*7c478bd9Sstevel@tonic-gate * ACK the ioctl. 761*7c478bd9Sstevel@tonic-gate */ 762*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 763*7c478bd9Sstevel@tonic-gate qreply(q, mp); 764*7c478bd9Sstevel@tonic-gate break; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate case JWINSIZE: 767*7c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 768*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 769*7c478bd9Sstevel@tonic-gate ptioc(q, mp, WRSIDE); 770*7c478bd9Sstevel@tonic-gate break; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate case TIOCSTI: 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * Simulate typing of a character at the terminal. In 775*7c478bd9Sstevel@tonic-gate * all cases, we acknowledge the ioctl and pass a copy 776*7c478bd9Sstevel@tonic-gate * of it along for the PCKT module to encapsulate. If 777*7c478bd9Sstevel@tonic-gate * not in remote mode, we also process the ioctl 778*7c478bd9Sstevel@tonic-gate * itself, looping the character given as its argument 779*7c478bd9Sstevel@tonic-gate * back around to the read side. 780*7c478bd9Sstevel@tonic-gate */ 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate /* 783*7c478bd9Sstevel@tonic-gate * Need a copy of this message to pass on to the PCKT 784*7c478bd9Sstevel@tonic-gate * module. 785*7c478bd9Sstevel@tonic-gate */ 786*7c478bd9Sstevel@tonic-gate if ((pckt_msgp = copymsg(mp)) == NULL) { 787*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 788*7c478bd9Sstevel@tonic-gate break; 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate if ((ntp->state & REMOTEMODE) == 0) { 791*7c478bd9Sstevel@tonic-gate mblk_t *bp; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (char)); 794*7c478bd9Sstevel@tonic-gate if (error != 0) { 795*7c478bd9Sstevel@tonic-gate freemsg(pckt_msgp); 796*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 797*7c478bd9Sstevel@tonic-gate break; 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * The permission checking has already been 802*7c478bd9Sstevel@tonic-gate * done at the stream head, since it has to be 803*7c478bd9Sstevel@tonic-gate * done in the context of the process doing 804*7c478bd9Sstevel@tonic-gate * the call. 805*7c478bd9Sstevel@tonic-gate */ 806*7c478bd9Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) == NULL) { 807*7c478bd9Sstevel@tonic-gate freemsg(pckt_msgp); 808*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 809*7c478bd9Sstevel@tonic-gate break; 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate /* 812*7c478bd9Sstevel@tonic-gate * XXX: Is EAGAIN really the right response to 813*7c478bd9Sstevel@tonic-gate * flow control blockage? 814*7c478bd9Sstevel@tonic-gate */ 815*7c478bd9Sstevel@tonic-gate if (!bcanputnext(RD(q), mp->b_band)) { 816*7c478bd9Sstevel@tonic-gate freemsg(bp); 817*7c478bd9Sstevel@tonic-gate freemsg(pckt_msgp); 818*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 819*7c478bd9Sstevel@tonic-gate break; 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate *bp->b_wptr++ = *mp->b_cont->b_rptr; 822*7c478bd9Sstevel@tonic-gate qreply(q, bp); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate putnext(q, pckt_msgp); 826*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 827*7c478bd9Sstevel@tonic-gate qreply(q, mp); 828*7c478bd9Sstevel@tonic-gate break; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate case PTSSTTY: 831*7c478bd9Sstevel@tonic-gate if (ntp->state & IS_PTSTTY) { 832*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EEXIST); 833*7c478bd9Sstevel@tonic-gate } else { 834*7c478bd9Sstevel@tonic-gate ntp->state |= IS_PTSTTY; 835*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 836*7c478bd9Sstevel@tonic-gate qreply(q, mp); 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate break; 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate default: 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * End of the line. The slave driver doesn't see any 843*7c478bd9Sstevel@tonic-gate * ioctls that we don't explicitly pass along to it. 844*7c478bd9Sstevel@tonic-gate */ 845*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 846*7c478bd9Sstevel@tonic-gate break; 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate break; 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate case M_DELAY: /* tty delays not supported */ 851*7c478bd9Sstevel@tonic-gate freemsg(mp); 852*7c478bd9Sstevel@tonic-gate break; 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate case M_DATA: 855*7c478bd9Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) < 0) { 856*7c478bd9Sstevel@tonic-gate /* 857*7c478bd9Sstevel@tonic-gate * Free all bad length messages. 858*7c478bd9Sstevel@tonic-gate */ 859*7c478bd9Sstevel@tonic-gate freemsg(mp); 860*7c478bd9Sstevel@tonic-gate break; 861*7c478bd9Sstevel@tonic-gate } else if ((mp->b_wptr - mp->b_rptr) == 0) { 862*7c478bd9Sstevel@tonic-gate if (!(ntp->state & IS_PTSTTY)) { 863*7c478bd9Sstevel@tonic-gate freemsg(mp); 864*7c478bd9Sstevel@tonic-gate break; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate if (ntp->state & OFLOW_CTL) 868*7c478bd9Sstevel@tonic-gate return (0); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate default: 871*7c478bd9Sstevel@tonic-gate putnext(q, mp); 872*7c478bd9Sstevel@tonic-gate break; 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate return (1); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate /* 880*7c478bd9Sstevel@tonic-gate * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called. 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate static void 883*7c478bd9Sstevel@tonic-gate ptioc(queue_t *q, mblk_t *mp, int qside) 884*7c478bd9Sstevel@tonic-gate { 885*7c478bd9Sstevel@tonic-gate struct ptem *tp; 886*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 887*7c478bd9Sstevel@tonic-gate struct winsize *wb; 888*7c478bd9Sstevel@tonic-gate struct jwinsize *jwb; 889*7c478bd9Sstevel@tonic-gate mblk_t *tmp; 890*7c478bd9Sstevel@tonic-gate mblk_t *pckt_msgp; /* message sent to the PCKT module */ 891*7c478bd9Sstevel@tonic-gate int error; 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 894*7c478bd9Sstevel@tonic-gate tp = (struct ptem *)q->q_ptr; 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate case JWINSIZE: 899*7c478bd9Sstevel@tonic-gate /* 900*7c478bd9Sstevel@tonic-gate * For compatibility: If all zeros, NAK the message for dumb 901*7c478bd9Sstevel@tonic-gate * terminals. 902*7c478bd9Sstevel@tonic-gate */ 903*7c478bd9Sstevel@tonic-gate if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) && 904*7c478bd9Sstevel@tonic-gate (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) { 905*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 906*7c478bd9Sstevel@tonic-gate return; 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate tmp = allocb(sizeof (struct jwinsize), BPRI_MED); 910*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 911*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 912*7c478bd9Sstevel@tonic-gate return; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) 916*7c478bd9Sstevel@tonic-gate mcopyout(mp, NULL, sizeof (struct jwinsize), NULL, tmp); 917*7c478bd9Sstevel@tonic-gate else 918*7c478bd9Sstevel@tonic-gate mioc2ack(mp, tmp, sizeof (struct jwinsize), 0); 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate jwb = (struct jwinsize *)mp->b_cont->b_rptr; 921*7c478bd9Sstevel@tonic-gate jwb->bytesx = tp->wsz.ws_col; 922*7c478bd9Sstevel@tonic-gate jwb->bytesy = tp->wsz.ws_row; 923*7c478bd9Sstevel@tonic-gate jwb->bitsx = tp->wsz.ws_xpixel; 924*7c478bd9Sstevel@tonic-gate jwb->bitsy = tp->wsz.ws_ypixel; 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate qreply(q, mp); 927*7c478bd9Sstevel@tonic-gate return; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 930*7c478bd9Sstevel@tonic-gate /* 931*7c478bd9Sstevel@tonic-gate * If all zeros NAK the message for dumb terminals. 932*7c478bd9Sstevel@tonic-gate */ 933*7c478bd9Sstevel@tonic-gate if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) && 934*7c478bd9Sstevel@tonic-gate (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) { 935*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 936*7c478bd9Sstevel@tonic-gate return; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate tmp = allocb(sizeof (struct winsize), BPRI_MED); 940*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 941*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 942*7c478bd9Sstevel@tonic-gate return; 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate mioc2ack(mp, tmp, sizeof (struct winsize), 0); 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate wb = (struct winsize *)mp->b_cont->b_rptr; 948*7c478bd9Sstevel@tonic-gate wb->ws_row = tp->wsz.ws_row; 949*7c478bd9Sstevel@tonic-gate wb->ws_col = tp->wsz.ws_col; 950*7c478bd9Sstevel@tonic-gate wb->ws_xpixel = tp->wsz.ws_xpixel; 951*7c478bd9Sstevel@tonic-gate wb->ws_ypixel = tp->wsz.ws_ypixel; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate qreply(q, mp); 954*7c478bd9Sstevel@tonic-gate return; 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 957*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct winsize)); 958*7c478bd9Sstevel@tonic-gate if (error != 0) { 959*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 960*7c478bd9Sstevel@tonic-gate return; 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate wb = (struct winsize *)mp->b_cont->b_rptr; 964*7c478bd9Sstevel@tonic-gate /* 965*7c478bd9Sstevel@tonic-gate * Send a SIGWINCH signal if the row/col information has 966*7c478bd9Sstevel@tonic-gate * changed. 967*7c478bd9Sstevel@tonic-gate */ 968*7c478bd9Sstevel@tonic-gate if ((tp->wsz.ws_row != wb->ws_row) || 969*7c478bd9Sstevel@tonic-gate (tp->wsz.ws_col != wb->ws_col) || 970*7c478bd9Sstevel@tonic-gate (tp->wsz.ws_xpixel != wb->ws_xpixel) || 971*7c478bd9Sstevel@tonic-gate (tp->wsz.ws_ypixel != wb->ws_xpixel)) { 972*7c478bd9Sstevel@tonic-gate /* 973*7c478bd9Sstevel@tonic-gate * SIGWINCH is always sent upstream. 974*7c478bd9Sstevel@tonic-gate */ 975*7c478bd9Sstevel@tonic-gate if (qside == WRSIDE) 976*7c478bd9Sstevel@tonic-gate (void) putnextctl1(RD(q), M_SIG, SIGWINCH); 977*7c478bd9Sstevel@tonic-gate else if (qside == RDSIDE) 978*7c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_SIG, SIGWINCH); 979*7c478bd9Sstevel@tonic-gate /* 980*7c478bd9Sstevel@tonic-gate * Message may have come in as an M_IOCDATA; pass it 981*7c478bd9Sstevel@tonic-gate * to the master side as an M_IOCTL. 982*7c478bd9Sstevel@tonic-gate */ 983*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCTL; 984*7c478bd9Sstevel@tonic-gate if (qside == WRSIDE) { 985*7c478bd9Sstevel@tonic-gate /* 986*7c478bd9Sstevel@tonic-gate * Need a copy of this message to pass on to 987*7c478bd9Sstevel@tonic-gate * the PCKT module, only if the M_IOCTL 988*7c478bd9Sstevel@tonic-gate * orginated from the slave side. 989*7c478bd9Sstevel@tonic-gate */ 990*7c478bd9Sstevel@tonic-gate if ((pckt_msgp = copymsg(mp)) == NULL) { 991*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 992*7c478bd9Sstevel@tonic-gate return; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate putnext(q, pckt_msgp); 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate tp->wsz.ws_row = wb->ws_row; 997*7c478bd9Sstevel@tonic-gate tp->wsz.ws_col = wb->ws_col; 998*7c478bd9Sstevel@tonic-gate tp->wsz.ws_xpixel = wb->ws_xpixel; 999*7c478bd9Sstevel@tonic-gate tp->wsz.ws_ypixel = wb->ws_ypixel; 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 1003*7c478bd9Sstevel@tonic-gate qreply(q, mp); 1004*7c478bd9Sstevel@tonic-gate return; 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate case TIOCSIGNAL: { 1007*7c478bd9Sstevel@tonic-gate /* 1008*7c478bd9Sstevel@tonic-gate * This ioctl can emanate from the master side in remote 1009*7c478bd9Sstevel@tonic-gate * mode only. 1010*7c478bd9Sstevel@tonic-gate */ 1011*7c478bd9Sstevel@tonic-gate int sig; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_IOCTL && iocp->ioc_count != TRANSPARENT) { 1014*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (int)); 1015*7c478bd9Sstevel@tonic-gate if (error != 0) { 1016*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 1017*7c478bd9Sstevel@tonic-gate return; 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_IOCDATA || iocp->ioc_count != TRANSPARENT) 1022*7c478bd9Sstevel@tonic-gate sig = *(int *)mp->b_cont->b_rptr; 1023*7c478bd9Sstevel@tonic-gate else 1024*7c478bd9Sstevel@tonic-gate sig = (int)*(intptr_t *)mp->b_cont->b_rptr; 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate if (sig < 1 || sig >= NSIG) { 1027*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 1028*7c478bd9Sstevel@tonic-gate return; 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * Send an M_PCSIG message up the slave's read side and 1033*7c478bd9Sstevel@tonic-gate * respond back to the master with an ACK or NAK as 1034*7c478bd9Sstevel@tonic-gate * appropriate. 1035*7c478bd9Sstevel@tonic-gate */ 1036*7c478bd9Sstevel@tonic-gate if (putnextctl1(q, M_PCSIG, sig) == 0) { 1037*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 1038*7c478bd9Sstevel@tonic-gate return; 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 1042*7c478bd9Sstevel@tonic-gate qreply(q, mp); 1043*7c478bd9Sstevel@tonic-gate return; 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate case TIOCREMOTE: { 1047*7c478bd9Sstevel@tonic-gate int onoff; 1048*7c478bd9Sstevel@tonic-gate mblk_t *mctlp; 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_IOCTL) { 1051*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (int)); 1052*7c478bd9Sstevel@tonic-gate if (error != 0) { 1053*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 1054*7c478bd9Sstevel@tonic-gate return; 1055*7c478bd9Sstevel@tonic-gate } 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate onoff = *(int *)mp->b_cont->b_rptr; 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate /* 1061*7c478bd9Sstevel@tonic-gate * Send M_CTL up using the iocblk format. 1062*7c478bd9Sstevel@tonic-gate */ 1063*7c478bd9Sstevel@tonic-gate mctlp = mkiocb(onoff ? MC_NO_CANON : MC_DO_CANON); 1064*7c478bd9Sstevel@tonic-gate if (mctlp == NULL) { 1065*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 1066*7c478bd9Sstevel@tonic-gate return; 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate mctlp->b_datap->db_type = M_CTL; 1069*7c478bd9Sstevel@tonic-gate putnext(q, mctlp); 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate /* 1072*7c478bd9Sstevel@tonic-gate * ACK the ioctl. 1073*7c478bd9Sstevel@tonic-gate */ 1074*7c478bd9Sstevel@tonic-gate mioc2ack(mp, NULL, 0, 0); 1075*7c478bd9Sstevel@tonic-gate qreply(q, mp); 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate /* 1078*7c478bd9Sstevel@tonic-gate * Record state change. 1079*7c478bd9Sstevel@tonic-gate */ 1080*7c478bd9Sstevel@tonic-gate if (onoff) 1081*7c478bd9Sstevel@tonic-gate tp->state |= REMOTEMODE; 1082*7c478bd9Sstevel@tonic-gate else 1083*7c478bd9Sstevel@tonic-gate tp->state &= ~REMOTEMODE; 1084*7c478bd9Sstevel@tonic-gate return; 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate default: 1088*7c478bd9Sstevel@tonic-gate putnext(q, mp); 1089*7c478bd9Sstevel@tonic-gate return; 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate } 1092