4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI" /* from S5R4 1.13 */
36 * The PTEM streams module is used as a pseudo driver emulator. Its purpose
37 * is to emulate the ioctl() functions of a terminal device driver.
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/stream.h>
43 #include <sys/stropts.h>
44 #include <sys/strsun.h>
45 #include <sys/termio.h>
47 #include <sys/signal.h>
49 #include <sys/strtty.h>
50 #include <sys/errno.h>
51 #include <sys/cmn_err.h>
52 #include <sys/jioctl.h>
55 #include <sys/debug.h>
58 #include <sys/sunddi.h>
60 #include <sys/modctl.h>
62 extern struct streamtab pteminfo
;
64 static struct fmodsw fsw
= {
70 static struct modlstrmod modlstrmod
= {
71 &mod_strmodops
, "pty hardware emulator", &fsw
74 static struct modlinkage modlinkage
= {
75 MODREV_1
, &modlstrmod
, NULL
81 return (mod_install(&modlinkage
));
87 return (mod_remove(&modlinkage
));
91 _info(struct modinfo
*modinfop
)
93 return (mod_info(&modlinkage
, modinfop
));
97 * stream data structure definitions
99 static int ptemopen(queue_t
*, dev_t
*, int, int, cred_t
*);
100 static int ptemclose(queue_t
*, int, cred_t
*);
101 static void ptemrput(queue_t
*, mblk_t
*);
102 static void ptemwput(queue_t
*, mblk_t
*);
103 static void ptemwsrv(queue_t
*);
105 static struct module_info ptem_info
= {
114 static struct qinit ptemrinit
= {
115 (int (*)()) ptemrput
,
124 static struct qinit ptemwinit
= {
125 (int (*)()) ptemwput
,
126 (int (*)()) ptemwsrv
,
134 struct streamtab pteminfo
= {
141 static void ptioc(queue_t
*, mblk_t
*, int);
142 static int ptemwmsg(queue_t
*, mblk_t
*);
145 * ptemopen - open routine gets called when the module gets pushed onto the
151 queue_t
*q
, /* pointer to the read side queue */
152 dev_t
*devp
, /* pointer to stream tail's dev */
153 int oflag
, /* the user open(2) supplied flags */
154 int sflag
, /* open state flag */
155 cred_t
*credp
) /* credentials */
157 struct ptem
*ntp
; /* ptem entry for this PTEM module */
158 mblk_t
*mop
; /* an setopts mblk */
159 struct stroptions
*sop
;
160 struct termios
*termiosp
;
163 if (sflag
!= MODOPEN
)
166 if (q
->q_ptr
!= NULL
) {
167 /* It's already attached. */
172 * Allocate state structure.
174 ntp
= kmem_alloc(sizeof (*ntp
), KM_SLEEP
);
177 * Allocate a message block, used to pass the zero length message for
180 * NOTE: it's better to find out if such a message block can be
181 * allocated before it's needed than to not be able to
182 * deliver (for possible lack of buffers) when a hang-up
185 if ((ntp
->dack_ptr
= allocb(4, BPRI_MED
)) == NULL
) {
186 kmem_free(ntp
, sizeof (*ntp
));
191 * Initialize an M_SETOPTS message to set up hi/lo water marks on
192 * stream head read queue and add controlling tty if not set.
194 mop
= allocb(sizeof (struct stroptions
), BPRI_MED
);
196 freemsg(ntp
->dack_ptr
);
197 kmem_free(ntp
, sizeof (*ntp
));
200 mop
->b_datap
->db_type
= M_SETOPTS
;
201 mop
->b_wptr
+= sizeof (struct stroptions
);
202 sop
= (struct stroptions
*)mop
->b_rptr
;
203 sop
->so_flags
= SO_HIWAT
| SO_LOWAT
| SO_ISTTY
;
215 * Get termios defaults. These are stored as
216 * a property in the "options" node.
218 if (ddi_getlongprop(DDI_DEV_T_ANY
, ddi_root_node(), 0, "ttymodes",
219 (caddr_t
)&termiosp
, &len
) == DDI_PROP_SUCCESS
&&
220 len
== sizeof (struct termios
)) {
222 ntp
->cflags
= termiosp
->c_cflag
;
223 kmem_free(termiosp
, len
);
226 * Gack! Whine about it.
228 cmn_err(CE_WARN
, "ptem: Couldn't get ttymodes property!");
232 ntp
->wsz
.ws_xpixel
= 0;
233 ntp
->wsz
.ws_ypixel
= 0;
238 * Commit to the open and send the M_SETOPTS off to the stream head.
248 * ptemclose - This routine gets called when the module gets popped off of the
253 ptemclose(queue_t
*q
, int flag
, cred_t
*credp
)
255 struct ptem
*ntp
; /* ptem entry for this PTEM module */
258 ntp
= (struct ptem
*)q
->q_ptr
;
259 freemsg(ntp
->dack_ptr
);
260 kmem_free(ntp
, sizeof (*ntp
));
261 q
->q_ptr
= WR(q
)->q_ptr
= NULL
;
267 * ptemrput - Module read queue put procedure.
269 * This is called from the module or driver downstream.
272 ptemrput(queue_t
*q
, mblk_t
*mp
)
274 struct iocblk
*iocp
; /* M_IOCTL data */
275 struct copyresp
*resp
; /* transparent ioctl response struct */
278 switch (mp
->b_datap
->db_type
) {
285 iocp
= (struct iocblk
*)mp
->b_rptr
;
287 switch (iocp
->ioc_cmd
) {
290 * Send a break message upstream.
292 * XXX: Shouldn't the argument come into play in
293 * determining whether or not so send an M_BREAK?
294 * It certainly does in the write-side direction.
296 error
= miocpullup(mp
, sizeof (int));
298 miocnak(q
, mp
, 0, error
);
301 if (!(*(int *)mp
->b_cont
->b_rptr
)) {
302 if (!putnextctl(q
, M_BREAK
)) {
304 * Send an NAK reply back
306 miocnak(q
, mp
, 0, EAGAIN
);
313 mioc2ack(mp
, NULL
, 0, 0);
320 ptioc(q
, mp
, RDSIDE
);
325 * The following subtle logic is due to the fact that
326 * `mp' may be in any one of three distinct formats:
328 * 1. A transparent M_IOCTL with an intptr_t-sized
329 * payload containing the signal number.
331 * 2. An I_STR M_IOCTL with an int-sized payload
332 * containing the signal number.
334 * 3. An M_IOCDATA with an int-sized payload
335 * containing the signal number.
337 if (iocp
->ioc_count
== TRANSPARENT
) {
338 intptr_t sig
= *(intptr_t *)mp
->b_cont
->b_rptr
;
340 if (sig
< 1 || sig
>= NSIG
) {
342 * it's transparent with pointer
345 mcopyin(mp
, NULL
, sizeof (int), NULL
);
350 ptioc(q
, mp
, RDSIDE
);
354 if (iocp
->ioc_count
!= TRANSPARENT
)
355 ptioc(q
, mp
, RDSIDE
);
357 mcopyin(mp
, NULL
, sizeof (int), NULL
);
369 resp
= (struct copyresp
*)mp
->b_rptr
;
372 * Just free message on failure.
379 * Only need to copy data for the SET case.
381 switch (resp
->cp_cmd
) {
386 ptioc(q
, mp
, RDSIDE
);
391 mp
->b_datap
->db_type
= M_IOCACK
;
392 mioc2ack(mp
, NULL
, 0, 0);
405 * We only pass write-side ioctls through to the master that
406 * we've already ACKed or NAKed to the stream head. Thus, we
407 * discard ones arriving from below, since they're redundant
408 * from the point of view of modules above us.
415 * clear blocked state.
418 struct ptem
*ntp
= (struct ptem
*)q
->q_ptr
;
419 if (ntp
->state
& OFLOW_CTL
) {
420 ntp
->state
&= ~OFLOW_CTL
;
432 * ptemwput - Module write queue put procedure.
434 * This is called from the module or stream head upstream.
436 * XXX: This routine is quite lazy about handling allocation failures,
437 * basically just giving up and reporting failure. It really ought to
438 * set up bufcalls and only fail when it's absolutely necessary.
441 ptemwput(queue_t
*q
, mblk_t
*mp
)
443 struct ptem
*ntp
= (struct ptem
*)q
->q_ptr
;
444 struct iocblk
*iocp
; /* outgoing ioctl structure */
445 struct copyresp
*resp
;
446 unsigned char type
= mp
->b_datap
->db_type
;
452 resp
= (struct copyresp
*)mp
->b_rptr
;
455 * Just free message on failure.
462 * Only need to copy data for the SET case.
464 switch (resp
->cp_cmd
) {
467 ptioc(q
, mp
, WRSIDE
);
472 mioc2ack(mp
, NULL
, 0, 0);
482 if (*mp
->b_rptr
& FLUSHW
) {
483 if ((ntp
->state
& IS_PTSTTY
) &&
484 (*mp
->b_rptr
& FLUSHBAND
))
485 flushband(q
, *(mp
->b_rptr
+ 1), FLUSHDATA
);
487 flushq(q
, FLUSHDATA
);
498 * Set the output flow control state.
500 ntp
->state
|= OFLOW_CTL
;
506 * Relieve the output flow control state.
508 ntp
->state
&= ~OFLOW_CTL
;
519 * If our queue is nonempty or flow control persists
520 * downstream or module in stopped state, queue this message.
522 if (q
->q_first
!= NULL
|| !bcanputnext(q
, mp
->b_band
)) {
524 * Exception: ioctls, except for those defined to
525 * take effect after output has drained, should be
526 * processed immediately.
531 iocp
= (struct iocblk
*)mp
->b_rptr
;
532 switch (iocp
->ioc_cmd
) {
544 * Handle all others immediately.
547 (void) ptemwmsg(q
, mp
);
552 case M_DELAY
: /* tty delays not supported */
557 if ((mp
->b_wptr
- mp
->b_rptr
) < 0) {
559 * Free all bad length messages.
563 } else if ((mp
->b_wptr
- mp
->b_rptr
) == 0) {
564 if (!(ntp
->state
& IS_PTSTTY
)) {
574 * fast path into ptemwmsg to dispose of mp.
576 if (!ptemwmsg(q
, mp
))
581 * ptem write queue service procedure.
588 while ((mp
= getq(q
)) != NULL
) {
589 if (!bcanputnext(q
, mp
->b_band
) || !ptemwmsg(q
, mp
)) {
598 * This routine is called from both ptemwput and ptemwsrv to do the
599 * actual work of dealing with mp. ptmewput will have already
600 * dealt with high priority messages.
602 * Return 1 if the message was processed completely and 0 if not.
605 ptemwmsg(queue_t
*q
, mblk_t
*mp
)
607 struct ptem
*ntp
= (struct ptem
*)q
->q_ptr
;
608 struct iocblk
*iocp
; /* outgoing ioctl structure */
609 struct termio
*termiop
;
610 struct termios
*termiosp
;
611 mblk_t
*dack_ptr
; /* disconnect message ACK block */
612 mblk_t
*pckt_msgp
; /* message sent to the PCKT module */
613 mblk_t
*dp
; /* ioctl reply data */
617 switch (mp
->b_datap
->db_type
) {
621 * Note: for each "set" type operation a copy
622 * of the M_IOCTL message is made and passed
623 * downstream. Eventually the PCKT module, if
624 * it has been pushed, should pick up this message.
625 * If the PCKT module has not been pushed the master
626 * side stream head will free it.
628 iocp
= (struct iocblk
*)mp
->b_rptr
;
629 switch (iocp
->ioc_cmd
) {
634 * Flush the read queue.
636 if (putnextctl1(q
, M_FLUSH
, FLUSHR
) == 0) {
637 miocnak(q
, mp
, 0, EAGAIN
);
647 switch (iocp
->ioc_cmd
) {
651 error
= miocpullup(mp
, sizeof (struct termio
));
653 miocnak(q
, mp
, 0, error
);
656 cflags
= ((struct termio
*)
657 mp
->b_cont
->b_rptr
)->c_cflag
;
659 (ntp
->cflags
& 0xffff0000 | cflags
);
665 error
= miocpullup(mp
, sizeof (struct termios
));
667 miocnak(q
, mp
, 0, error
);
670 cflags
= ((struct termios
*)
671 mp
->b_cont
->b_rptr
)->c_cflag
;
672 ntp
->cflags
= cflags
;
676 if ((cflags
& CBAUD
) == B0
) {
678 * Hang-up: Send a zero length message.
680 dack_ptr
= ntp
->dack_ptr
;
683 ntp
->dack_ptr
= NULL
;
685 * Send a zero length message
688 putnext(q
, dack_ptr
);
692 * Make a copy of this message and pass it on
693 * to the PCKT module.
695 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
696 miocnak(q
, mp
, 0, EAGAIN
);
699 putnext(q
, pckt_msgp
);
704 mioc2ack(mp
, NULL
, 0, 0);
710 dp
= allocb(sizeof (struct termio
), BPRI_MED
);
712 miocnak(q
, mp
, 0, EAGAIN
);
715 termiop
= (struct termio
*)dp
->b_rptr
;
716 termiop
->c_cflag
= (ushort_t
)ntp
->cflags
;
717 mioc2ack(mp
, dp
, sizeof (struct termio
), 0);
722 dp
= allocb(sizeof (struct termios
), BPRI_MED
);
724 miocnak(q
, mp
, 0, EAGAIN
);
727 termiosp
= (struct termios
*)dp
->b_rptr
;
728 termiosp
->c_cflag
= ntp
->cflags
;
729 mioc2ack(mp
, dp
, sizeof (struct termios
), 0);
734 error
= miocpullup(mp
, sizeof (int));
736 miocnak(q
, mp
, 0, error
);
741 * Need a copy of this message to pass it on to
744 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
745 miocnak(q
, mp
, 0, EAGAIN
);
749 * Send a copy of the M_IOCTL to the PCKT module.
751 putnext(q
, pckt_msgp
);
754 * TCSBRK meaningful if data part of message is 0
757 if (!(*(int *)mp
->b_cont
->b_rptr
))
758 (void) putnextctl(q
, M_BREAK
);
762 mioc2ack(mp
, NULL
, 0, 0);
769 ptioc(q
, mp
, WRSIDE
);
774 * Simulate typing of a character at the terminal. In
775 * all cases, we acknowledge the ioctl and pass a copy
776 * of it along for the PCKT module to encapsulate. If
777 * not in remote mode, we also process the ioctl
778 * itself, looping the character given as its argument
779 * back around to the read side.
783 * Need a copy of this message to pass on to the PCKT
786 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
787 miocnak(q
, mp
, 0, EAGAIN
);
790 if ((ntp
->state
& REMOTEMODE
) == 0) {
793 error
= miocpullup(mp
, sizeof (char));
796 miocnak(q
, mp
, 0, error
);
801 * The permission checking has already been
802 * done at the stream head, since it has to be
803 * done in the context of the process doing
806 if ((bp
= allocb(1, BPRI_MED
)) == NULL
) {
808 miocnak(q
, mp
, 0, EAGAIN
);
812 * XXX: Is EAGAIN really the right response to
813 * flow control blockage?
815 if (!bcanputnext(RD(q
), mp
->b_band
)) {
818 miocnak(q
, mp
, 0, EAGAIN
);
821 *bp
->b_wptr
++ = *mp
->b_cont
->b_rptr
;
825 putnext(q
, pckt_msgp
);
826 mioc2ack(mp
, NULL
, 0, 0);
831 if (ntp
->state
& IS_PTSTTY
) {
832 miocnak(q
, mp
, 0, EEXIST
);
834 ntp
->state
|= IS_PTSTTY
;
835 mioc2ack(mp
, NULL
, 0, 0);
842 * End of the line. The slave driver doesn't see any
843 * ioctls that we don't explicitly pass along to it.
845 miocnak(q
, mp
, 0, EINVAL
);
850 case M_DELAY
: /* tty delays not supported */
855 if ((mp
->b_wptr
- mp
->b_rptr
) < 0) {
857 * Free all bad length messages.
861 } else if ((mp
->b_wptr
- mp
->b_rptr
) == 0) {
862 if (!(ntp
->state
& IS_PTSTTY
)) {
867 if (ntp
->state
& OFLOW_CTL
)
880 * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
883 ptioc(queue_t
*q
, mblk_t
*mp
, int qside
)
888 struct jwinsize
*jwb
;
890 mblk_t
*pckt_msgp
; /* message sent to the PCKT module */
893 iocp
= (struct iocblk
*)mp
->b_rptr
;
894 tp
= (struct ptem
*)q
->q_ptr
;
896 switch (iocp
->ioc_cmd
) {
900 * For compatibility: If all zeros, NAK the message for dumb
903 if ((tp
->wsz
.ws_row
== 0) && (tp
->wsz
.ws_col
== 0) &&
904 (tp
->wsz
.ws_xpixel
== 0) && (tp
->wsz
.ws_ypixel
== 0)) {
905 miocnak(q
, mp
, 0, EINVAL
);
909 tmp
= allocb(sizeof (struct jwinsize
), BPRI_MED
);
911 miocnak(q
, mp
, 0, EAGAIN
);
915 if (iocp
->ioc_count
== TRANSPARENT
)
916 mcopyout(mp
, NULL
, sizeof (struct jwinsize
), NULL
, tmp
);
918 mioc2ack(mp
, tmp
, sizeof (struct jwinsize
), 0);
920 jwb
= (struct jwinsize
*)mp
->b_cont
->b_rptr
;
921 jwb
->bytesx
= tp
->wsz
.ws_col
;
922 jwb
->bytesy
= tp
->wsz
.ws_row
;
923 jwb
->bitsx
= tp
->wsz
.ws_xpixel
;
924 jwb
->bitsy
= tp
->wsz
.ws_ypixel
;
931 * If all zeros NAK the message for dumb terminals.
933 if ((tp
->wsz
.ws_row
== 0) && (tp
->wsz
.ws_col
== 0) &&
934 (tp
->wsz
.ws_xpixel
== 0) && (tp
->wsz
.ws_ypixel
== 0)) {
935 miocnak(q
, mp
, 0, EINVAL
);
939 tmp
= allocb(sizeof (struct winsize
), BPRI_MED
);
941 miocnak(q
, mp
, 0, EAGAIN
);
945 mioc2ack(mp
, tmp
, sizeof (struct winsize
), 0);
947 wb
= (struct winsize
*)mp
->b_cont
->b_rptr
;
948 wb
->ws_row
= tp
->wsz
.ws_row
;
949 wb
->ws_col
= tp
->wsz
.ws_col
;
950 wb
->ws_xpixel
= tp
->wsz
.ws_xpixel
;
951 wb
->ws_ypixel
= tp
->wsz
.ws_ypixel
;
957 error
= miocpullup(mp
, sizeof (struct winsize
));
959 miocnak(q
, mp
, 0, error
);
963 wb
= (struct winsize
*)mp
->b_cont
->b_rptr
;
965 * Send a SIGWINCH signal if the row/col information has
968 if ((tp
->wsz
.ws_row
!= wb
->ws_row
) ||
969 (tp
->wsz
.ws_col
!= wb
->ws_col
) ||
970 (tp
->wsz
.ws_xpixel
!= wb
->ws_xpixel
) ||
971 (tp
->wsz
.ws_ypixel
!= wb
->ws_xpixel
)) {
973 * SIGWINCH is always sent upstream.
976 (void) putnextctl1(RD(q
), M_SIG
, SIGWINCH
);
977 else if (qside
== RDSIDE
)
978 (void) putnextctl1(q
, M_SIG
, SIGWINCH
);
980 * Message may have come in as an M_IOCDATA; pass it
981 * to the master side as an M_IOCTL.
983 mp
->b_datap
->db_type
= M_IOCTL
;
984 if (qside
== WRSIDE
) {
986 * Need a copy of this message to pass on to
987 * the PCKT module, only if the M_IOCTL
988 * orginated from the slave side.
990 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
991 miocnak(q
, mp
, 0, EAGAIN
);
994 putnext(q
, pckt_msgp
);
996 tp
->wsz
.ws_row
= wb
->ws_row
;
997 tp
->wsz
.ws_col
= wb
->ws_col
;
998 tp
->wsz
.ws_xpixel
= wb
->ws_xpixel
;
999 tp
->wsz
.ws_ypixel
= wb
->ws_ypixel
;
1002 mioc2ack(mp
, NULL
, 0, 0);
1008 * This ioctl can emanate from the master side in remote
1013 if (DB_TYPE(mp
) == M_IOCTL
&& iocp
->ioc_count
!= TRANSPARENT
) {
1014 error
= miocpullup(mp
, sizeof (int));
1016 miocnak(q
, mp
, 0, error
);
1021 if (DB_TYPE(mp
) == M_IOCDATA
|| iocp
->ioc_count
!= TRANSPARENT
)
1022 sig
= *(int *)mp
->b_cont
->b_rptr
;
1024 sig
= (int)*(intptr_t *)mp
->b_cont
->b_rptr
;
1026 if (sig
< 1 || sig
>= NSIG
) {
1027 miocnak(q
, mp
, 0, EINVAL
);
1032 * Send an M_PCSIG message up the slave's read side and
1033 * respond back to the master with an ACK or NAK as
1036 if (putnextctl1(q
, M_PCSIG
, sig
) == 0) {
1037 miocnak(q
, mp
, 0, EAGAIN
);
1041 mioc2ack(mp
, NULL
, 0, 0);
1050 if (DB_TYPE(mp
) == M_IOCTL
) {
1051 error
= miocpullup(mp
, sizeof (int));
1053 miocnak(q
, mp
, 0, error
);
1058 onoff
= *(int *)mp
->b_cont
->b_rptr
;
1061 * Send M_CTL up using the iocblk format.
1063 mctlp
= mkiocb(onoff
? MC_NO_CANON
: MC_DO_CANON
);
1064 if (mctlp
== NULL
) {
1065 miocnak(q
, mp
, 0, EAGAIN
);
1068 mctlp
->b_datap
->db_type
= M_CTL
;
1074 mioc2ack(mp
, NULL
, 0, 0);
1078 * Record state change.
1081 tp
->state
|= REMOTEMODE
;
1083 tp
->state
&= ~REMOTEMODE
;