diff options
Diffstat (limited to 'usr/src/uts/common/io/ptm.c')
-rw-r--r-- | usr/src/uts/common/io/ptm.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/usr/src/uts/common/io/ptm.c b/usr/src/uts/common/io/ptm.c index bd4dc10511..7910b58cc8 100644 --- a/usr/src/uts/common/io/ptm.c +++ b/usr/src/uts/common/io/ptm.c @@ -449,6 +449,18 @@ ptmclose(queue_t *rqp, int flag, cred_t *credp) return (0); } +static boolean_t +ptmptsopencb(ptmptsopencb_arg_t arg) +{ + struct pt_ttys *ptmp = (struct pt_ttys *)arg; + boolean_t rval; + + PT_ENTER_READ(ptmp); + rval = (ptmp->pt_nullmsg != NULL); + PT_EXIT_READ(ptmp); + return (rval); +} + /* * The wput procedure will only handle ioctl and flush messages. */ @@ -572,6 +584,41 @@ ptmwput(queue_t *qp, mblk_t *mp) miocack(qp, mp, 0, 0); break; } + case PTMPTSOPENCB: + { + mblk_t *dp; /* ioctl reply data */ + ptmptsopencb_t *ppocb; + + /* only allow the kernel to invoke this ioctl */ + if (iocp->ioc_cr != kcred) { + miocnak(qp, mp, 0, EINVAL); + break; + } + + /* we don't support transparent ioctls */ + ASSERT(iocp->ioc_count != TRANSPARENT); + if (iocp->ioc_count == TRANSPARENT) { + miocnak(qp, mp, 0, EINVAL); + break; + } + + /* allocate a response message */ + dp = allocb(sizeof (ptmptsopencb_t), BPRI_MED); + if (dp == NULL) { + miocnak(qp, mp, 0, EAGAIN); + break; + } + + /* initialize the ioctl results */ + ppocb = (ptmptsopencb_t *)dp->b_rptr; + ppocb->ppocb_func = ptmptsopencb; + ppocb->ppocb_arg = (ptmptsopencb_arg_t)ptmp; + + /* send the reply data */ + mioc2ack(mp, dp, sizeof (ptmptsopencb_t), 0); + qreply(qp, mp); + break; + } } break; @@ -643,6 +690,13 @@ ptmwsrv(queue_t *qp) ASSERT(qp->q_ptr); ptmp = (struct pt_ttys *)qp->q_ptr; + + if ((mp = getq(qp)) == NULL) { + /* If there are no messages there's nothing to do. */ + DBG(("leaving ptmwsrv (no messages)\n")); + return; + } + PT_ENTER_READ(ptmp); if ((ptmp->pt_state & PTLOCK) || (ptmp->pts_rdq == NULL)) { DBG(("in master write srv proc but no slave\n")); @@ -652,12 +706,12 @@ ptmwsrv(queue_t *qp) * the user process waiting for ACK/NAK from * the ioctl invocation */ - while ((mp = getq(qp)) != NULL) { + do { if (mp->b_datap->db_type == M_IOCTL) miocnak(qp, mp, 0, EINVAL); else freemsg(mp); - } + } while ((mp = getq(qp)) != NULL); flushq(qp, FLUSHALL); mp = mexchange(NULL, NULL, 2, M_ERROR, -1); @@ -672,7 +726,7 @@ ptmwsrv(queue_t *qp) /* * while there are messages on this write queue... */ - while ((mp = getq(qp)) != NULL) { + do { /* * if don't have control message and cannot put * msg. on slave's read queue, put it back on @@ -689,7 +743,7 @@ ptmwsrv(queue_t *qp) */ DBG(("send message to slave\n")); putnext(ptmp->pts_rdq, mp); - } + } while ((mp = getq(qp)) != NULL); DBG(("leaving ptmwsrv\n")); PT_EXIT_READ(ptmp); } |