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