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]
23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
24 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.10 */
38 #include <sys/stream.h>
39 #define _SUN_TPI_VERSION 2
40 #include <sys/tihdr.h>
41 #include <sys/timod.h>
48 _tx_rcvdis(int fd
, struct t_discon
*discon
, int api_semantics
)
51 struct strbuf databuf
;
53 union T_primitives
*pptr
;
54 struct _ti_user
*tiptr
;
57 int didalloc
, didralloc
;
60 if ((tiptr
= _t_checkfd(fd
, 0, api_semantics
)) == NULL
)
64 * Acquire per thread lock.
65 * Note: Lock is held across most of this routine
66 * including the blocking getmsg() call. This is fine
67 * because it is first verfied that an event is pending
69 sig_mutex_lock(&tiptr
->ti_lock
);
71 if (tiptr
->ti_servtype
== T_CLTS
) {
72 t_errno
= TNOTSUPPORT
;
73 sig_mutex_unlock(&tiptr
->ti_lock
);
77 if (_T_IS_XTI(api_semantics
)) {
79 * User level state verification only done for XTI
80 * because doing for TLI may break existing applications
82 if (!(tiptr
->ti_state
== T_DATAXFER
||
83 tiptr
->ti_state
== T_OUTCON
||
84 tiptr
->ti_state
== T_OUTREL
||
85 tiptr
->ti_state
== T_INREL
||
86 (tiptr
->ti_state
== T_INCON
&& tiptr
->ti_ocnt
> 0))) {
88 sig_mutex_unlock(&tiptr
->ti_lock
);
93 * Handle likely scenario as special case:
94 * Is there a discon in look buffer as the first
95 * event in the lookbuffer, is so just get it.
97 if ((tiptr
->ti_lookcnt
> 0) &&
98 /* LINTED pointer cast */
99 (*((t_scalar_t
*)tiptr
->ti_lookbufs
.tl_lookcbuf
) == T_DISCON_IND
)) {
101 * The T_DISCON_IND is already in the look buffer
103 ctlbuf
.len
= tiptr
->ti_lookbufs
.tl_lookclen
;
104 ctlbuf
.buf
= tiptr
->ti_lookbufs
.tl_lookcbuf
;
105 /* Note: ctlbuf.maxlen not used in this case */
107 databuf
.len
= tiptr
->ti_lookbufs
.tl_lookdlen
;
108 databuf
.buf
= tiptr
->ti_lookbufs
.tl_lookdbuf
;
109 /* Note databuf.maxlen not used in this case */
115 if ((retval
= _t_look_locked(fd
, tiptr
, 0,
116 api_semantics
)) < 0) {
118 sig_mutex_unlock(&tiptr
->ti_lock
);
123 if (retval
!= T_DISCONNECT
) {
125 sig_mutex_unlock(&tiptr
->ti_lock
);
130 * get disconnect off read queue.
131 * use ctl and rcv buffers
133 * Acquire ctlbuf for use in sending/receiving control part
136 if (_t_acquire_ctlbuf(tiptr
, &ctlbuf
, &didalloc
) < 0) {
138 sig_mutex_unlock(&tiptr
->ti_lock
);
144 * Acquire databuf for use in sending/receiving data part
146 if (_t_acquire_databuf(tiptr
, &databuf
, &didralloc
) < 0) {
151 tiptr
->ti_ctlbuf
= ctlbuf
.buf
;
152 sig_mutex_unlock(&tiptr
->ti_lock
);
158 * Since we already verified that a disconnect event
159 * is present, we assume that this getmsg() cannot
163 retval
= getmsg(fd
, &ctlbuf
, &databuf
, &flg
);
164 } while (retval
< 0 && errno
== EINTR
);
170 if (databuf
.len
== -1) databuf
.len
= 0;
173 * did I get entire message?
183 /* LINTED pointer cast */
184 pptr
= (union T_primitives
*)ctlbuf
.buf
;
186 if ((ctlbuf
.len
< (int)sizeof (struct T_discon_ind
)) ||
187 (pptr
->type
!= T_DISCON_IND
)) {
194 * clear more and expedited flags
196 tiptr
->ti_flags
&= ~(MORE
| EXPEDITED
);
198 if (tiptr
->ti_ocnt
<= 0) {
199 _T_TX_NEXTSTATE(T_RCVDIS1
, tiptr
,
200 "t_rcvdis: invalid state event T_RCVDIS1");
202 if (tiptr
->ti_ocnt
== 1) {
203 _T_TX_NEXTSTATE(T_RCVDIS2
, tiptr
,
204 "t_rcvdis: invalid state event T_RCVDIS2");
206 _T_TX_NEXTSTATE(T_RCVDIS3
, tiptr
,
207 "t_rcvdis: invalid state event T_RCVDIS3");
210 tiptr
->ti_flags
&= ~TX_TQFULL_NOTIFIED
;
213 if (discon
!= NULL
) {
214 if (_T_IS_TLI(api_semantics
) || discon
->udata
.maxlen
> 0) {
215 if (databuf
.len
> (int)discon
->udata
.maxlen
) {
219 (void) memcpy(discon
->udata
.buf
, databuf
.buf
,
220 (size_t)databuf
.len
);
221 discon
->udata
.len
= databuf
.len
;
223 discon
->reason
= pptr
->discon_ind
.DISCON_reason
;
224 discon
->sequence
= pptr
->discon_ind
.SEQ_number
;
227 _t_free_looklist_head(tiptr
);
232 tiptr
->ti_ctlbuf
= ctlbuf
.buf
;
236 tiptr
->ti_rcvbuf
= databuf
.buf
;
238 sig_mutex_unlock(&tiptr
->ti_lock
);
245 _t_free_looklist_head(tiptr
);
250 tiptr
->ti_ctlbuf
= ctlbuf
.buf
;
254 tiptr
->ti_rcvbuf
= databuf
.buf
;
256 sig_mutex_unlock(&tiptr
->ti_lock
);