xref: /onnv-gate/usr/src/uts/common/io/tirdwr.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI" /* from S5R4 1.4 */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate /*
34*0Sstevel@tonic-gate  * Transport Interface Library read/write module - issue 1
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include	<sys/types.h>
38*0Sstevel@tonic-gate #include	<sys/param.h>
39*0Sstevel@tonic-gate #include	<sys/stream.h>
40*0Sstevel@tonic-gate #include	<sys/stropts.h>
41*0Sstevel@tonic-gate #include	<sys/tihdr.h>
42*0Sstevel@tonic-gate #include	<sys/debug.h>
43*0Sstevel@tonic-gate #include	<sys/errno.h>
44*0Sstevel@tonic-gate #include	<sys/kmem.h>
45*0Sstevel@tonic-gate #include	<sys/tirdwr.h>
46*0Sstevel@tonic-gate #include	<sys/conf.h>
47*0Sstevel@tonic-gate #include	<sys/modctl.h>
48*0Sstevel@tonic-gate #include	<sys/ddi.h>
49*0Sstevel@tonic-gate #include	<sys/sunddi.h>
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #define	ORDREL		002
52*0Sstevel@tonic-gate #define	DISCON		004
53*0Sstevel@tonic-gate #define	FATAL		010
54*0Sstevel@tonic-gate #define	WAITACK		020
55*0Sstevel@tonic-gate #define	TIRDWR_ID	4
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate /*
58*0Sstevel@tonic-gate  * Per-Stream private data structure.
59*0Sstevel@tonic-gate  */
60*0Sstevel@tonic-gate struct trw_trw {
61*0Sstevel@tonic-gate 	queue_t	*trw_rdq;
62*0Sstevel@tonic-gate 	uint_t	trw_flags;
63*0Sstevel@tonic-gate };
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * stream data structure definitions
67*0Sstevel@tonic-gate  */
68*0Sstevel@tonic-gate static	int tirdwropen(queue_t *q, dev_t *dev,
69*0Sstevel@tonic-gate     int flag, int sflag, cred_t	*cr);
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate static	int tirdwrclose(queue_t *q, int flag, cred_t *cr);
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate static	int check_strhead(queue_t *q);
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate /*
76*0Sstevel@tonic-gate  * To save instructions, since STREAMS ignores the return value
77*0Sstevel@tonic-gate  * from these functions, they are defined as void here. Kind of icky, but...
78*0Sstevel@tonic-gate  */
79*0Sstevel@tonic-gate static void tirdwrrput(queue_t *q, mblk_t *mp);
80*0Sstevel@tonic-gate static void tirdwrwput(queue_t *q, mblk_t *mp);
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate static struct module_info tirdwr_info = {
83*0Sstevel@tonic-gate 	TIRDWR_ID,
84*0Sstevel@tonic-gate 	"tirdwr",
85*0Sstevel@tonic-gate 	0,
86*0Sstevel@tonic-gate 	INFPSZ,
87*0Sstevel@tonic-gate 	4096,
88*0Sstevel@tonic-gate 	1024
89*0Sstevel@tonic-gate };
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate static struct qinit tirdwrrinit = {
92*0Sstevel@tonic-gate 	(int (*)())tirdwrrput,
93*0Sstevel@tonic-gate 	(int (*)())NULL,
94*0Sstevel@tonic-gate 	tirdwropen,
95*0Sstevel@tonic-gate 	tirdwrclose,
96*0Sstevel@tonic-gate 	nulldev,
97*0Sstevel@tonic-gate 	&tirdwr_info,
98*0Sstevel@tonic-gate 	NULL
99*0Sstevel@tonic-gate };
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate static struct qinit tirdwrwinit = {
102*0Sstevel@tonic-gate 	(int (*)())tirdwrwput,
103*0Sstevel@tonic-gate 	(int (*)())NULL,
104*0Sstevel@tonic-gate 	tirdwropen,
105*0Sstevel@tonic-gate 	tirdwrclose,
106*0Sstevel@tonic-gate 	nulldev,
107*0Sstevel@tonic-gate 	&tirdwr_info,
108*0Sstevel@tonic-gate 	NULL
109*0Sstevel@tonic-gate };
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate static struct streamtab trwinfo = {
112*0Sstevel@tonic-gate 	&tirdwrrinit,
113*0Sstevel@tonic-gate 	&tirdwrwinit,
114*0Sstevel@tonic-gate 	NULL,
115*0Sstevel@tonic-gate 	NULL
116*0Sstevel@tonic-gate };
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate static struct fmodsw fsw = {
119*0Sstevel@tonic-gate 	"tirdwr",
120*0Sstevel@tonic-gate 	&trwinfo,
121*0Sstevel@tonic-gate 	D_NEW|D_MTQPAIR|D_MP
122*0Sstevel@tonic-gate };
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
125*0Sstevel@tonic-gate 	&mod_strmodops, "xport interface rd/wr str mod", &fsw
126*0Sstevel@tonic-gate };
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate static struct modlinkage modlinkage = {
129*0Sstevel@tonic-gate 	MODREV_1, &modlstrmod, NULL
130*0Sstevel@tonic-gate };
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate int
_init(void)133*0Sstevel@tonic-gate _init(void)
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate 	return (mod_install(&modlinkage));
136*0Sstevel@tonic-gate }
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate int
_fini(void)139*0Sstevel@tonic-gate _fini(void)
140*0Sstevel@tonic-gate {
141*0Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
142*0Sstevel@tonic-gate }
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate int
_info(struct modinfo * modinfop)145*0Sstevel@tonic-gate _info(struct modinfo *modinfop)
146*0Sstevel@tonic-gate {
147*0Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
148*0Sstevel@tonic-gate }
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate static void send_fatal(queue_t *q, mblk_t *mp);
151*0Sstevel@tonic-gate static void strip_strhead(queue_t *q);
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * tirdwropen - open routine gets called when the
156*0Sstevel@tonic-gate  *		module gets pushed onto the stream.
157*0Sstevel@tonic-gate  */
158*0Sstevel@tonic-gate /*ARGSUSED*/
159*0Sstevel@tonic-gate static int
tirdwropen(queue_t * q,dev_t * dev,int flag,int sflag,cred_t * cr)160*0Sstevel@tonic-gate tirdwropen(
161*0Sstevel@tonic-gate 	queue_t *q,
162*0Sstevel@tonic-gate 	dev_t	*dev,
163*0Sstevel@tonic-gate 	int flag,
164*0Sstevel@tonic-gate 	int sflag,
165*0Sstevel@tonic-gate 	cred_t	*cr)
166*0Sstevel@tonic-gate {
167*0Sstevel@tonic-gate 	struct trw_trw *trwptr;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	/* check if already open */
170*0Sstevel@tonic-gate 	if (q->q_ptr) {
171*0Sstevel@tonic-gate 		return (0);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	/*
175*0Sstevel@tonic-gate 	 * Allocate a new trw_trw struct.
176*0Sstevel@tonic-gate 	 */
177*0Sstevel@tonic-gate 	trwptr = kmem_alloc(sizeof (struct trw_trw), KM_SLEEP);
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	/* initialize data structure */
180*0Sstevel@tonic-gate 	trwptr->trw_flags = 0;
181*0Sstevel@tonic-gate 	trwptr->trw_rdq = q;
182*0Sstevel@tonic-gate 	q->q_ptr = (caddr_t)trwptr;
183*0Sstevel@tonic-gate 	WR(q)->q_ptr = (caddr_t)trwptr;
184*0Sstevel@tonic-gate 	qprocson(q);
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	freezestr(q);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	(void) strqset(WR(q), QMAXPSZ, 0, (uintptr_t)WR(q)->q_next->q_maxpsz);
189*0Sstevel@tonic-gate 	(void) strqset(q, QMAXPSZ, 0, (uintptr_t)q->q_next->q_maxpsz);
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	if (!check_strhead(q)) {
192*0Sstevel@tonic-gate 		unfreezestr(q);
193*0Sstevel@tonic-gate 		qprocsoff(q);
194*0Sstevel@tonic-gate 		kmem_free(trwptr, sizeof (struct trw_trw));
195*0Sstevel@tonic-gate 		return (EPROTO);
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 	strip_strhead(q);
198*0Sstevel@tonic-gate 	unfreezestr(q);
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	return (0);
201*0Sstevel@tonic-gate }
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate /*
204*0Sstevel@tonic-gate  * tirdwrclose - This routine gets called when the module
205*0Sstevel@tonic-gate  *		gets popped off of the stream.
206*0Sstevel@tonic-gate  */
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate /*ARGSUSED1*/
209*0Sstevel@tonic-gate static int
tirdwrclose(queue_t * q,int flag,cred_t * cr)210*0Sstevel@tonic-gate tirdwrclose(queue_t *q, int flag, cred_t *cr)
211*0Sstevel@tonic-gate {
212*0Sstevel@tonic-gate 	struct trw_trw *trwptr;
213*0Sstevel@tonic-gate 	mblk_t *mp;
214*0Sstevel@tonic-gate 	union T_primitives *pptr;
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	qprocsoff(q);
217*0Sstevel@tonic-gate 	trwptr = (struct trw_trw *)q->q_ptr;
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	ASSERT(trwptr != NULL);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	/*
222*0Sstevel@tonic-gate 	 * Send up a T_DISCON_IND if necessary.
223*0Sstevel@tonic-gate 	 */
224*0Sstevel@tonic-gate 	if ((trwptr->trw_flags & ORDREL) && !(trwptr->trw_flags & FATAL))
225*0Sstevel@tonic-gate 		if (mp = allocb(sizeof (struct T_discon_req), BPRI_LO)) {
226*0Sstevel@tonic-gate 			pptr = (union T_primitives *)mp->b_rptr;
227*0Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr + sizeof (struct T_ordrel_req);
228*0Sstevel@tonic-gate 			pptr->type = T_ORDREL_REQ;
229*0Sstevel@tonic-gate 			mp->b_datap->db_type = M_PROTO;
230*0Sstevel@tonic-gate 			putnext(WR(q), mp);
231*0Sstevel@tonic-gate 		}
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 	kmem_free(trwptr, sizeof (struct trw_trw));
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	return (0);
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate /*
239*0Sstevel@tonic-gate  * tirdwrrput - Module read queue put procedure.
240*0Sstevel@tonic-gate  *		This is called from the module or
241*0Sstevel@tonic-gate  *		driver downstream.
242*0Sstevel@tonic-gate  */
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate static void
tirdwrrput(queue_t * q,mblk_t * mp)245*0Sstevel@tonic-gate tirdwrrput(queue_t *q, mblk_t *mp)
246*0Sstevel@tonic-gate {
247*0Sstevel@tonic-gate 	union T_primitives *pptr;
248*0Sstevel@tonic-gate 	struct trw_trw *trwptr;
249*0Sstevel@tonic-gate 	mblk_t *tmp;
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	trwptr = (struct trw_trw *)q->q_ptr;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	ASSERT(trwptr != NULL);
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	if ((trwptr->trw_flags & FATAL) && !(trwptr->trw_flags & WAITACK)) {
256*0Sstevel@tonic-gate 		freemsg(mp);
257*0Sstevel@tonic-gate 		return;
258*0Sstevel@tonic-gate 	}
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	default:
263*0Sstevel@tonic-gate 		putnext(q, mp);
264*0Sstevel@tonic-gate 		break;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	case M_DATA:
267*0Sstevel@tonic-gate 		putnext(q, mp);
268*0Sstevel@tonic-gate 		break;
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	case M_PCPROTO:
271*0Sstevel@tonic-gate 	case M_PROTO:
272*0Sstevel@tonic-gate 		/* is there enough data to check type */
273*0Sstevel@tonic-gate 		if ((mp->b_wptr - mp->b_rptr) < sizeof (t_scalar_t)) {
274*0Sstevel@tonic-gate 			/* malformed message */
275*0Sstevel@tonic-gate 			freemsg(mp);
276*0Sstevel@tonic-gate 			break;
277*0Sstevel@tonic-gate 		}
278*0Sstevel@tonic-gate 		pptr = (union T_primitives *)mp->b_rptr;
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate 		switch (pptr->type) {
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 		case T_EXDATA_IND:
283*0Sstevel@tonic-gate 			send_fatal(q, mp);
284*0Sstevel@tonic-gate 			break;
285*0Sstevel@tonic-gate 		case T_DATA_IND:
286*0Sstevel@tonic-gate 			if (msgdsize(mp) == 0) {
287*0Sstevel@tonic-gate 				freemsg(mp);
288*0Sstevel@tonic-gate 				break;
289*0Sstevel@tonic-gate 			}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 			tmp = (mblk_t *)unlinkb(mp);
292*0Sstevel@tonic-gate 			freemsg(mp);
293*0Sstevel@tonic-gate 			putnext(q, tmp);
294*0Sstevel@tonic-gate 			break;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 		case T_ORDREL_IND:
297*0Sstevel@tonic-gate 			trwptr->trw_flags |= ORDREL;
298*0Sstevel@tonic-gate 			mp->b_datap->db_type = M_DATA;
299*0Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr;
300*0Sstevel@tonic-gate 			putnext(q, mp);
301*0Sstevel@tonic-gate 			break;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 		case T_DISCON_IND:
304*0Sstevel@tonic-gate 			trwptr->trw_flags |= DISCON;
305*0Sstevel@tonic-gate 			trwptr->trw_flags &= ~ORDREL;
306*0Sstevel@tonic-gate 			if (msgdsize(mp) != 0) {
307*0Sstevel@tonic-gate 				tmp = (mblk_t *)unlinkb(mp);
308*0Sstevel@tonic-gate 				putnext(q, tmp);
309*0Sstevel@tonic-gate 			}
310*0Sstevel@tonic-gate 			mp->b_datap->db_type = M_HANGUP;
311*0Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr;
312*0Sstevel@tonic-gate 			putnext(q, mp);
313*0Sstevel@tonic-gate 			break;
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 		default:
316*0Sstevel@tonic-gate 			send_fatal(q, mp);
317*0Sstevel@tonic-gate 			break;
318*0Sstevel@tonic-gate 		}
319*0Sstevel@tonic-gate 	}
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate /*
324*0Sstevel@tonic-gate  * tirdwrwput - Module write queue put procedure.
325*0Sstevel@tonic-gate  *		This is called from the module or
326*0Sstevel@tonic-gate  *		stream head upstream.
327*0Sstevel@tonic-gate  */
328*0Sstevel@tonic-gate static void
tirdwrwput(queue_t * q,mblk_t * mp)329*0Sstevel@tonic-gate tirdwrwput(queue_t *q, mblk_t *mp)
330*0Sstevel@tonic-gate {
331*0Sstevel@tonic-gate 	struct trw_trw *trwptr;
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate 	trwptr = (struct trw_trw *)q->q_ptr;
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	ASSERT(trwptr != NULL);
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	if (trwptr->trw_flags & FATAL) {
338*0Sstevel@tonic-gate 		freemsg(mp);
339*0Sstevel@tonic-gate 		return;
340*0Sstevel@tonic-gate 	}
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
343*0Sstevel@tonic-gate 	default:
344*0Sstevel@tonic-gate 		putnext(q, mp);
345*0Sstevel@tonic-gate 		break;
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	case M_DATA:
348*0Sstevel@tonic-gate 		putnext(q, mp);
349*0Sstevel@tonic-gate 		break;
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 	case M_PROTO:
352*0Sstevel@tonic-gate 	case M_PCPROTO:
353*0Sstevel@tonic-gate 		send_fatal(q, mp);
354*0Sstevel@tonic-gate 		break;
355*0Sstevel@tonic-gate 	}
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate static void
send_fatal(queue_t * q,mblk_t * mp)360*0Sstevel@tonic-gate send_fatal(queue_t *q, mblk_t *mp)
361*0Sstevel@tonic-gate {
362*0Sstevel@tonic-gate 	struct trw_trw *trwptr;
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	trwptr = (struct trw_trw *)q->q_ptr;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	trwptr->trw_flags |= FATAL;
367*0Sstevel@tonic-gate 	mp->b_datap->db_type = M_ERROR;
368*0Sstevel@tonic-gate 	*mp->b_datap->db_base = EPROTO;
369*0Sstevel@tonic-gate 	mp->b_rptr = mp->b_datap->db_base;
370*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_datap->db_base + sizeof (char);
371*0Sstevel@tonic-gate 	freemsg(unlinkb(mp));
372*0Sstevel@tonic-gate 	if (q->q_flag&QREADR)
373*0Sstevel@tonic-gate 		putnext(q, mp);
374*0Sstevel@tonic-gate 	else
375*0Sstevel@tonic-gate 		qreply(q, mp);
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate static int
check_strhead(queue_t * q)379*0Sstevel@tonic-gate check_strhead(queue_t *q)
380*0Sstevel@tonic-gate {
381*0Sstevel@tonic-gate 	mblk_t *mp;
382*0Sstevel@tonic-gate 	union T_primitives *pptr;
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 	for (mp = q->q_next->q_first; mp != NULL; mp = mp->b_next) {
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 		switch (mp->b_datap->db_type) {
387*0Sstevel@tonic-gate 		case M_PROTO:
388*0Sstevel@tonic-gate 			pptr = (union T_primitives *)mp->b_rptr;
389*0Sstevel@tonic-gate 			if ((mp->b_wptr - mp->b_rptr) < sizeof (t_scalar_t))
390*0Sstevel@tonic-gate 				return (0);
391*0Sstevel@tonic-gate 			switch (pptr->type) {
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 			case T_EXDATA_IND:
394*0Sstevel@tonic-gate 				return (0);
395*0Sstevel@tonic-gate 			case T_DATA_IND:
396*0Sstevel@tonic-gate 				if (mp->b_cont &&
397*0Sstevel@tonic-gate 				    (mp->b_cont->b_datap->db_type != M_DATA))
398*0Sstevel@tonic-gate 					return (0);
399*0Sstevel@tonic-gate 				break;
400*0Sstevel@tonic-gate 			default:
401*0Sstevel@tonic-gate 				return (0);
402*0Sstevel@tonic-gate 			}
403*0Sstevel@tonic-gate 			break;
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 		case M_PCPROTO:
406*0Sstevel@tonic-gate 			return (0);
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 		case M_DATA:
409*0Sstevel@tonic-gate 		case M_SIG:
410*0Sstevel@tonic-gate 			break;
411*0Sstevel@tonic-gate 		default:
412*0Sstevel@tonic-gate 			return (0);
413*0Sstevel@tonic-gate 		}
414*0Sstevel@tonic-gate 	}
415*0Sstevel@tonic-gate 	return (1);
416*0Sstevel@tonic-gate }
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate static void
strip_strhead(queue_t * q)419*0Sstevel@tonic-gate strip_strhead(queue_t *q)
420*0Sstevel@tonic-gate {
421*0Sstevel@tonic-gate 	mblk_t *mp;
422*0Sstevel@tonic-gate 	mblk_t *emp;
423*0Sstevel@tonic-gate 	mblk_t *tmp;
424*0Sstevel@tonic-gate 	union T_primitives *pptr;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	q = q->q_next;
427*0Sstevel@tonic-gate 	/*CSTYLED*/
428*0Sstevel@tonic-gate 	for (mp = q->q_first; mp != NULL; ) {
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 		switch (mp->b_datap->db_type) {
431*0Sstevel@tonic-gate 		case M_PROTO:
432*0Sstevel@tonic-gate 			pptr = (union T_primitives *)mp->b_rptr;
433*0Sstevel@tonic-gate 			switch (pptr->type) {
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 			case T_DATA_IND:
436*0Sstevel@tonic-gate 				if (msgdsize(mp) == 0) {
437*0Sstevel@tonic-gate strip0:
438*0Sstevel@tonic-gate 					tmp = mp->b_next;
439*0Sstevel@tonic-gate 					rmvq(q, mp);
440*0Sstevel@tonic-gate 					freemsg(mp);
441*0Sstevel@tonic-gate 					mp = tmp;
442*0Sstevel@tonic-gate 					break;
443*0Sstevel@tonic-gate 				}
444*0Sstevel@tonic-gate 				emp = mp->b_next;
445*0Sstevel@tonic-gate 				rmvq(q, mp);
446*0Sstevel@tonic-gate 				tmp = (mblk_t *)unlinkb(mp);
447*0Sstevel@tonic-gate 				freeb(mp);
448*0Sstevel@tonic-gate 				(void) insq(q, emp, tmp);
449*0Sstevel@tonic-gate 				mp = emp;
450*0Sstevel@tonic-gate 				break;
451*0Sstevel@tonic-gate 			}
452*0Sstevel@tonic-gate 			break;
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 		case M_DATA:
455*0Sstevel@tonic-gate 			if (msgdsize(mp) == 0)
456*0Sstevel@tonic-gate 				goto strip0;
457*0Sstevel@tonic-gate 			mp = mp->b_next;
458*0Sstevel@tonic-gate 			break;
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 		case M_SIG:
461*0Sstevel@tonic-gate 			mp = mp->b_next;
462*0Sstevel@tonic-gate 			break;
463*0Sstevel@tonic-gate 		}
464*0Sstevel@tonic-gate 	}
465*0Sstevel@tonic-gate }
466