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.
29 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
35 * The PTEM streams module is used as a pseudo driver emulator. Its purpose
36 * is to emulate the ioctl() functions of a terminal device driver.
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/stream.h>
42 #include <sys/stropts.h>
43 #include <sys/strsun.h>
44 #include <sys/termio.h>
46 #include <sys/signal.h>
48 #include <sys/strtty.h>
49 #include <sys/errno.h>
50 #include <sys/cmn_err.h>
51 #include <sys/jioctl.h>
54 #include <sys/debug.h>
57 #include <sys/sunddi.h>
59 #include <sys/modctl.h>
61 extern struct streamtab pteminfo
;
63 static struct fmodsw fsw
= {
66 D_MTQPAIR
| D_MP
| _D_SINGLE_INSTANCE
69 static struct modlstrmod modlstrmod
= {
70 &mod_strmodops
, "pty hardware emulator", &fsw
73 static struct modlinkage modlinkage
= {
74 MODREV_1
, &modlstrmod
, NULL
80 return (mod_install(&modlinkage
));
86 return (mod_remove(&modlinkage
));
90 _info(struct modinfo
*modinfop
)
92 return (mod_info(&modlinkage
, modinfop
));
96 * stream data structure definitions
98 static int ptemopen(queue_t
*, dev_t
*, int, int, cred_t
*);
99 static int ptemclose(queue_t
*, int, cred_t
*);
100 static void ptemrput(queue_t
*, mblk_t
*);
101 static void ptemwput(queue_t
*, mblk_t
*);
102 static void ptemwsrv(queue_t
*);
104 static struct module_info ptem_info
= {
113 static struct qinit ptemrinit
= {
114 (int (*)()) ptemrput
,
123 static struct qinit ptemwinit
= {
124 (int (*)()) ptemwput
,
125 (int (*)()) ptemwsrv
,
133 struct streamtab pteminfo
= {
140 static void ptioc(queue_t
*, mblk_t
*, int);
141 static int ptemwmsg(queue_t
*, mblk_t
*);
144 * ptemopen - open routine gets called when the module gets pushed onto the
150 queue_t
*q
, /* pointer to the read side queue */
151 dev_t
*devp
, /* pointer to stream tail's dev */
152 int oflag
, /* the user open(2) supplied flags */
153 int sflag
, /* open state flag */
154 cred_t
*credp
) /* credentials */
156 struct ptem
*ntp
; /* ptem entry for this PTEM module */
157 mblk_t
*mop
; /* an setopts mblk */
158 struct stroptions
*sop
;
159 struct termios
*termiosp
;
162 if (sflag
!= MODOPEN
)
165 if (q
->q_ptr
!= NULL
) {
166 /* It's already attached. */
171 * Allocate state structure.
173 ntp
= kmem_alloc(sizeof (*ntp
), KM_SLEEP
);
176 * Allocate a message block, used to pass the zero length message for
179 * NOTE: it's better to find out if such a message block can be
180 * allocated before it's needed than to not be able to
181 * deliver (for possible lack of buffers) when a hang-up
184 if ((ntp
->dack_ptr
= allocb(4, BPRI_MED
)) == NULL
) {
185 kmem_free(ntp
, sizeof (*ntp
));
190 * Initialize an M_SETOPTS message to set up hi/lo water marks on
191 * stream head read queue and add controlling tty if not set.
193 mop
= allocb(sizeof (struct stroptions
), BPRI_MED
);
195 freemsg(ntp
->dack_ptr
);
196 kmem_free(ntp
, sizeof (*ntp
));
199 mop
->b_datap
->db_type
= M_SETOPTS
;
200 mop
->b_wptr
+= sizeof (struct stroptions
);
201 sop
= (struct stroptions
*)mop
->b_rptr
;
202 sop
->so_flags
= SO_HIWAT
| SO_LOWAT
| SO_ISTTY
;
203 sop
->so_hiwat
= _TTY_BUFSIZ
;
214 * Get termios defaults. These are stored as
215 * a property in the "options" node.
217 if (ddi_getlongprop(DDI_DEV_T_ANY
, ddi_root_node(), 0, "ttymodes",
218 (caddr_t
)&termiosp
, &len
) == DDI_PROP_SUCCESS
&&
219 len
== sizeof (struct termios
)) {
221 ntp
->cflags
= termiosp
->c_cflag
;
222 kmem_free(termiosp
, len
);
225 * Gack! Whine about it.
227 cmn_err(CE_WARN
, "ptem: Couldn't get ttymodes property!");
231 ntp
->wsz
.ws_xpixel
= 0;
232 ntp
->wsz
.ws_ypixel
= 0;
237 * Commit to the open and send the M_SETOPTS off to the stream head.
247 * ptemclose - This routine gets called when the module gets popped off of the
252 ptemclose(queue_t
*q
, int flag
, cred_t
*credp
)
254 struct ptem
*ntp
; /* ptem entry for this PTEM module */
257 ntp
= (struct ptem
*)q
->q_ptr
;
258 freemsg(ntp
->dack_ptr
);
259 kmem_free(ntp
, sizeof (*ntp
));
260 q
->q_ptr
= WR(q
)->q_ptr
= NULL
;
266 * ptemrput - Module read queue put procedure.
268 * This is called from the module or driver downstream.
271 ptemrput(queue_t
*q
, mblk_t
*mp
)
273 struct iocblk
*iocp
; /* M_IOCTL data */
274 struct copyresp
*resp
; /* transparent ioctl response struct */
277 switch (mp
->b_datap
->db_type
) {
284 iocp
= (struct iocblk
*)mp
->b_rptr
;
286 switch (iocp
->ioc_cmd
) {
289 * Send a break message upstream.
291 * XXX: Shouldn't the argument come into play in
292 * determining whether or not so send an M_BREAK?
293 * It certainly does in the write-side direction.
295 error
= miocpullup(mp
, sizeof (int));
297 miocnak(q
, mp
, 0, error
);
300 if (!(*(int *)mp
->b_cont
->b_rptr
)) {
301 if (!putnextctl(q
, M_BREAK
)) {
303 * Send an NAK reply back
305 miocnak(q
, mp
, 0, EAGAIN
);
312 mioc2ack(mp
, NULL
, 0, 0);
319 ptioc(q
, mp
, RDSIDE
);
324 * The following subtle logic is due to the fact that
325 * `mp' may be in any one of three distinct formats:
327 * 1. A transparent M_IOCTL with an intptr_t-sized
328 * payload containing the signal number.
330 * 2. An I_STR M_IOCTL with an int-sized payload
331 * containing the signal number.
333 * 3. An M_IOCDATA with an int-sized payload
334 * containing the signal number.
336 if (iocp
->ioc_count
== TRANSPARENT
) {
337 intptr_t sig
= *(intptr_t *)mp
->b_cont
->b_rptr
;
339 if (sig
< 1 || sig
>= NSIG
) {
341 * it's transparent with pointer
344 mcopyin(mp
, NULL
, sizeof (int), NULL
);
349 ptioc(q
, mp
, RDSIDE
);
353 if (iocp
->ioc_count
!= TRANSPARENT
)
354 ptioc(q
, mp
, RDSIDE
);
356 mcopyin(mp
, NULL
, sizeof (int), NULL
);
368 resp
= (struct copyresp
*)mp
->b_rptr
;
371 * Just free message on failure.
378 * Only need to copy data for the SET case.
380 switch (resp
->cp_cmd
) {
385 ptioc(q
, mp
, RDSIDE
);
390 mp
->b_datap
->db_type
= M_IOCACK
;
391 mioc2ack(mp
, NULL
, 0, 0);
404 * We only pass write-side ioctls through to the master that
405 * we've already ACKed or NAKed to the stream head. Thus, we
406 * discard ones arriving from below, since they're redundant
407 * from the point of view of modules above us.
414 * clear blocked state.
417 struct ptem
*ntp
= (struct ptem
*)q
->q_ptr
;
418 if (ntp
->state
& OFLOW_CTL
) {
419 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),
488 flushq(q
, FLUSHDATA
);
499 * Set the output flow control state.
501 ntp
->state
|= OFLOW_CTL
;
507 * Relieve the output flow control state.
509 ntp
->state
&= ~OFLOW_CTL
;
520 * If our queue is nonempty or flow control persists
521 * downstream or module in stopped state, queue this message.
523 if (q
->q_first
!= NULL
|| !bcanputnext(q
, mp
->b_band
)) {
525 * Exception: ioctls, except for those defined to
526 * take effect after output has drained, should be
527 * processed immediately.
532 iocp
= (struct iocblk
*)mp
->b_rptr
;
533 switch (iocp
->ioc_cmd
) {
545 * Handle all others immediately.
548 (void) ptemwmsg(q
, mp
);
553 case M_DELAY
: /* tty delays not supported */
558 if ((mp
->b_wptr
- mp
->b_rptr
) < 0) {
560 * Free all bad length messages.
564 } else if ((mp
->b_wptr
- mp
->b_rptr
) == 0) {
565 if (!(ntp
->state
& IS_PTSTTY
)) {
575 * fast path into ptemwmsg to dispose of mp.
577 if (!ptemwmsg(q
, mp
))
582 * ptem write queue service procedure.
589 while ((mp
= getq(q
)) != NULL
) {
590 if (!bcanputnext(q
, mp
->b_band
) || !ptemwmsg(q
, mp
)) {
599 * This routine is called from both ptemwput and ptemwsrv to do the
600 * actual work of dealing with mp. ptmewput will have already
601 * dealt with high priority messages.
603 * Return 1 if the message was processed completely and 0 if not.
606 ptemwmsg(queue_t
*q
, mblk_t
*mp
)
608 struct ptem
*ntp
= (struct ptem
*)q
->q_ptr
;
609 struct iocblk
*iocp
; /* outgoing ioctl structure */
610 struct termio
*termiop
;
611 struct termios
*termiosp
;
612 mblk_t
*dack_ptr
; /* disconnect message ACK block */
613 mblk_t
*pckt_msgp
; /* message sent to the PCKT module */
614 mblk_t
*dp
; /* ioctl reply data */
618 switch (mp
->b_datap
->db_type
) {
622 * Note: for each "set" type operation a copy
623 * of the M_IOCTL message is made and passed
624 * downstream. Eventually the PCKT module, if
625 * it has been pushed, should pick up this message.
626 * If the PCKT module has not been pushed the master
627 * side stream head will free it.
629 iocp
= (struct iocblk
*)mp
->b_rptr
;
630 switch (iocp
->ioc_cmd
) {
635 * Flush the read queue.
637 if (putnextctl1(q
, M_FLUSH
, FLUSHR
) == 0) {
638 miocnak(q
, mp
, 0, EAGAIN
);
648 switch (iocp
->ioc_cmd
) {
652 error
= miocpullup(mp
, sizeof (struct termio
));
654 miocnak(q
, mp
, 0, error
);
657 cflags
= ((struct termio
*)
658 mp
->b_cont
->b_rptr
)->c_cflag
;
660 (ntp
->cflags
& 0xffff0000 | cflags
);
666 error
= miocpullup(mp
, sizeof (struct termios
));
668 miocnak(q
, mp
, 0, error
);
671 cflags
= ((struct termios
*)
672 mp
->b_cont
->b_rptr
)->c_cflag
;
673 ntp
->cflags
= cflags
;
677 if ((cflags
& CBAUD
) == B0
) {
679 * Hang-up: Send a zero length message.
681 dack_ptr
= ntp
->dack_ptr
;
684 ntp
->dack_ptr
= NULL
;
686 * Send a zero length message
689 putnext(q
, dack_ptr
);
693 * Make a copy of this message and pass it on
694 * to the PCKT module.
696 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
697 miocnak(q
, mp
, 0, EAGAIN
);
700 putnext(q
, pckt_msgp
);
705 mioc2ack(mp
, NULL
, 0, 0);
711 dp
= allocb(sizeof (struct termio
), BPRI_MED
);
713 miocnak(q
, mp
, 0, EAGAIN
);
716 termiop
= (struct termio
*)dp
->b_rptr
;
717 termiop
->c_cflag
= (ushort_t
)ntp
->cflags
;
718 mioc2ack(mp
, dp
, sizeof (struct termio
), 0);
723 dp
= allocb(sizeof (struct termios
), BPRI_MED
);
725 miocnak(q
, mp
, 0, EAGAIN
);
728 termiosp
= (struct termios
*)dp
->b_rptr
;
729 termiosp
->c_cflag
= ntp
->cflags
;
730 mioc2ack(mp
, dp
, sizeof (struct termios
), 0);
735 error
= miocpullup(mp
, sizeof (int));
737 miocnak(q
, mp
, 0, error
);
742 * Need a copy of this message to pass it on to
745 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
746 miocnak(q
, mp
, 0, EAGAIN
);
750 * Send a copy of the M_IOCTL to the PCKT module.
752 putnext(q
, pckt_msgp
);
755 * TCSBRK meaningful if data part of message is 0
758 if (!(*(int *)mp
->b_cont
->b_rptr
))
759 (void) putnextctl(q
, M_BREAK
);
763 mioc2ack(mp
, NULL
, 0, 0);
770 ptioc(q
, mp
, WRSIDE
);
775 * Simulate typing of a character at the terminal. In
776 * all cases, we acknowledge the ioctl and pass a copy
777 * of it along for the PCKT module to encapsulate. If
778 * not in remote mode, we also process the ioctl
779 * itself, looping the character given as its argument
780 * back around to the read side.
784 * Need a copy of this message to pass on to the PCKT
787 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
788 miocnak(q
, mp
, 0, EAGAIN
);
791 if ((ntp
->state
& REMOTEMODE
) == 0) {
794 error
= miocpullup(mp
, sizeof (char));
797 miocnak(q
, mp
, 0, error
);
802 * The permission checking has already been
803 * done at the stream head, since it has to be
804 * done in the context of the process doing
807 if ((bp
= allocb(1, BPRI_MED
)) == NULL
) {
809 miocnak(q
, mp
, 0, EAGAIN
);
813 * XXX: Is EAGAIN really the right response to
814 * flow control blockage?
816 if (!bcanputnext(RD(q
), mp
->b_band
)) {
819 miocnak(q
, mp
, 0, EAGAIN
);
822 *bp
->b_wptr
++ = *mp
->b_cont
->b_rptr
;
826 putnext(q
, pckt_msgp
);
827 mioc2ack(mp
, NULL
, 0, 0);
832 if (ntp
->state
& IS_PTSTTY
) {
833 miocnak(q
, mp
, 0, EEXIST
);
835 ntp
->state
|= IS_PTSTTY
;
836 mioc2ack(mp
, NULL
, 0, 0);
843 * End of the line. The slave driver doesn't see any
844 * ioctls that we don't explicitly pass along to it.
846 miocnak(q
, mp
, 0, EINVAL
);
851 case M_DELAY
: /* tty delays not supported */
856 if ((mp
->b_wptr
- mp
->b_rptr
) < 0) {
858 * Free all bad length messages.
862 } else if ((mp
->b_wptr
- mp
->b_rptr
) == 0) {
863 if (!(ntp
->state
& IS_PTSTTY
)) {
868 if (ntp
->state
& OFLOW_CTL
)
882 * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
885 ptioc(queue_t
*q
, mblk_t
*mp
, int qside
)
890 struct jwinsize
*jwb
;
892 mblk_t
*pckt_msgp
; /* message sent to the PCKT module */
895 iocp
= (struct iocblk
*)mp
->b_rptr
;
896 tp
= (struct ptem
*)q
->q_ptr
;
898 switch (iocp
->ioc_cmd
) {
902 * For compatibility: If all zeros, NAK the message for dumb
905 if ((tp
->wsz
.ws_row
== 0) && (tp
->wsz
.ws_col
== 0) &&
906 (tp
->wsz
.ws_xpixel
== 0) && (tp
->wsz
.ws_ypixel
== 0)) {
907 miocnak(q
, mp
, 0, EINVAL
);
911 tmp
= allocb(sizeof (struct jwinsize
), BPRI_MED
);
913 miocnak(q
, mp
, 0, EAGAIN
);
917 if (iocp
->ioc_count
== TRANSPARENT
)
918 mcopyout(mp
, NULL
, sizeof (struct jwinsize
), NULL
, tmp
);
920 mioc2ack(mp
, tmp
, sizeof (struct jwinsize
), 0);
922 jwb
= (struct jwinsize
*)mp
->b_cont
->b_rptr
;
923 jwb
->bytesx
= tp
->wsz
.ws_col
;
924 jwb
->bytesy
= tp
->wsz
.ws_row
;
925 jwb
->bitsx
= tp
->wsz
.ws_xpixel
;
926 jwb
->bitsy
= tp
->wsz
.ws_ypixel
;
933 * If all zeros NAK the message for dumb terminals.
935 if ((tp
->wsz
.ws_row
== 0) && (tp
->wsz
.ws_col
== 0) &&
936 (tp
->wsz
.ws_xpixel
== 0) && (tp
->wsz
.ws_ypixel
== 0)) {
937 miocnak(q
, mp
, 0, EINVAL
);
941 tmp
= allocb(sizeof (struct winsize
), BPRI_MED
);
943 miocnak(q
, mp
, 0, EAGAIN
);
947 mioc2ack(mp
, tmp
, sizeof (struct winsize
), 0);
949 wb
= (struct winsize
*)mp
->b_cont
->b_rptr
;
950 wb
->ws_row
= tp
->wsz
.ws_row
;
951 wb
->ws_col
= tp
->wsz
.ws_col
;
952 wb
->ws_xpixel
= tp
->wsz
.ws_xpixel
;
953 wb
->ws_ypixel
= tp
->wsz
.ws_ypixel
;
959 error
= miocpullup(mp
, sizeof (struct winsize
));
961 miocnak(q
, mp
, 0, error
);
965 wb
= (struct winsize
*)mp
->b_cont
->b_rptr
;
967 * Send a SIGWINCH signal if the row/col information has
970 if ((tp
->wsz
.ws_row
!= wb
->ws_row
) ||
971 (tp
->wsz
.ws_col
!= wb
->ws_col
) ||
972 (tp
->wsz
.ws_xpixel
!= wb
->ws_xpixel
) ||
973 (tp
->wsz
.ws_ypixel
!= wb
->ws_xpixel
)) {
975 * SIGWINCH is always sent upstream.
978 (void) putnextctl1(RD(q
), M_SIG
, SIGWINCH
);
979 else if (qside
== RDSIDE
)
980 (void) putnextctl1(q
, M_SIG
, SIGWINCH
);
982 * Message may have come in as an M_IOCDATA; pass it
983 * to the master side as an M_IOCTL.
985 mp
->b_datap
->db_type
= M_IOCTL
;
986 if (qside
== WRSIDE
) {
988 * Need a copy of this message to pass on to
989 * the PCKT module, only if the M_IOCTL
990 * orginated from the slave side.
992 if ((pckt_msgp
= copymsg(mp
)) == NULL
) {
993 miocnak(q
, mp
, 0, EAGAIN
);
996 putnext(q
, pckt_msgp
);
998 tp
->wsz
.ws_row
= wb
->ws_row
;
999 tp
->wsz
.ws_col
= wb
->ws_col
;
1000 tp
->wsz
.ws_xpixel
= wb
->ws_xpixel
;
1001 tp
->wsz
.ws_ypixel
= wb
->ws_ypixel
;
1004 mioc2ack(mp
, NULL
, 0, 0);
1010 * This ioctl can emanate from the master side in remote
1015 if (DB_TYPE(mp
) == M_IOCTL
&& iocp
->ioc_count
!= TRANSPARENT
) {
1016 error
= miocpullup(mp
, sizeof (int));
1018 miocnak(q
, mp
, 0, error
);
1023 if (DB_TYPE(mp
) == M_IOCDATA
|| iocp
->ioc_count
!= TRANSPARENT
)
1024 sig
= *(int *)mp
->b_cont
->b_rptr
;
1026 sig
= (int)*(intptr_t *)mp
->b_cont
->b_rptr
;
1028 if (sig
< 1 || sig
>= NSIG
) {
1029 miocnak(q
, mp
, 0, EINVAL
);
1034 * Send an M_PCSIG message up the slave's read side and
1035 * respond back to the master with an ACK or NAK as
1038 if (putnextctl1(q
, M_PCSIG
, sig
) == 0) {
1039 miocnak(q
, mp
, 0, EAGAIN
);
1043 mioc2ack(mp
, NULL
, 0, 0);
1052 if (DB_TYPE(mp
) == M_IOCTL
) {
1053 error
= miocpullup(mp
, sizeof (int));
1055 miocnak(q
, mp
, 0, error
);
1060 onoff
= *(int *)mp
->b_cont
->b_rptr
;
1063 * Send M_CTL up using the iocblk format.
1065 mctlp
= mkiocb(onoff
? MC_NO_CANON
: MC_DO_CANON
);
1066 if (mctlp
== NULL
) {
1067 miocnak(q
, mp
, 0, EAGAIN
);
1070 mctlp
->b_datap
->db_type
= M_CTL
;
1076 mioc2ack(mp
, NULL
, 0, 0);
1080 * Record state change.
1083 tp
->state
|= REMOTEMODE
;
1085 tp
->state
&= ~REMOTEMODE
;