xref: /illumos-gate/usr/src/uts/common/io/pckt.c (revision a0f9c00cd82d49a710cee8aeb83ce42b5fb293a9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Description: The pckt module packetizes messages on
337c478bd9Sstevel@tonic-gate  *		its read queue by pre-fixing an M_PROTO
347c478bd9Sstevel@tonic-gate  *		message type to certain incoming messages.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/param.h>
397c478bd9Sstevel@tonic-gate #include <sys/stream.h>
407c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
417c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
427c478bd9Sstevel@tonic-gate #include <sys/errno.h>
437c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
447c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
457c478bd9Sstevel@tonic-gate #include <sys/debug.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * This is the loadable module wrapper.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate #include <sys/conf.h>
517c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate static struct streamtab pcktinfo;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * Per queue instances are single-threaded since the q_ptr
577c478bd9Sstevel@tonic-gate  * field of queues need to be shared among threads.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
607c478bd9Sstevel@tonic-gate 	"pckt",
617c478bd9Sstevel@tonic-gate 	&pcktinfo,
627c478bd9Sstevel@tonic-gate 	D_NEW | D_MTPERQ | D_MP
637c478bd9Sstevel@tonic-gate };
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
707c478bd9Sstevel@tonic-gate 	&mod_strmodops,
717c478bd9Sstevel@tonic-gate 	"pckt module",
727c478bd9Sstevel@tonic-gate 	&fsw
737c478bd9Sstevel@tonic-gate };
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
767c478bd9Sstevel@tonic-gate 	MODREV_1, &modlstrmod, NULL
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int
817c478bd9Sstevel@tonic-gate _init(void)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate int
877c478bd9Sstevel@tonic-gate _fini(void)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate int
937c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static int	pcktopen(queue_t *, dev_t *, int, int, cred_t *);
997c478bd9Sstevel@tonic-gate static int	pcktclose(queue_t *, int, cred_t *);
1007c478bd9Sstevel@tonic-gate static void	pcktrput(queue_t *, mblk_t *);
1017c478bd9Sstevel@tonic-gate static void	pcktrsrv(queue_t *);
1027c478bd9Sstevel@tonic-gate static void	pcktwput(queue_t *, mblk_t *);
1037c478bd9Sstevel@tonic-gate static mblk_t	*add_ctl_info(queue_t *, mblk_t *);
1047c478bd9Sstevel@tonic-gate static void	add_ctl_wkup(void *);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * Stream module data structure definitions.
1097c478bd9Sstevel@tonic-gate  * Sits over the ptm module generally.
1107c478bd9Sstevel@tonic-gate  *
1117c478bd9Sstevel@tonic-gate  * Read side flow control strategy: Since we may be putting messages on
1127c478bd9Sstevel@tonic-gate  * the read q due to allocb failures, these failures must get
1137c478bd9Sstevel@tonic-gate  * reflected fairly quickly to the module below us.
1147c478bd9Sstevel@tonic-gate  * No sense in piling on messages in times of memory shortage.
1157c478bd9Sstevel@tonic-gate  * Further, for the case of upper level flow control, there is no
1167c478bd9Sstevel@tonic-gate  * compelling reason to have more buffering in this module.
1177c478bd9Sstevel@tonic-gate  * Thus use a hi-water mark of one.
1187c478bd9Sstevel@tonic-gate  * This module imposes no max packet size, there is no inherent reason
1197c478bd9Sstevel@tonic-gate  * in the code to do so.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate static struct module_info pcktiinfo = {
1227c478bd9Sstevel@tonic-gate 	0x9898,					/* module id number */
1237c478bd9Sstevel@tonic-gate 	"pckt",					/* module name */
1247c478bd9Sstevel@tonic-gate 	0,					/* minimum packet size */
1257c478bd9Sstevel@tonic-gate 	INFPSZ,					/* maximum packet size */
1267c478bd9Sstevel@tonic-gate 	1,					/* hi-water mark */
1277c478bd9Sstevel@tonic-gate 	0					/* lo-water mark */
1287c478bd9Sstevel@tonic-gate };
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate  * Write side flow control strategy: There is no write service procedure.
1327c478bd9Sstevel@tonic-gate  * The write put function is pass thru, thus there is no reason to have any
1337c478bd9Sstevel@tonic-gate  * limits on the maximum packet size.
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate static struct module_info pcktoinfo = {
1367c478bd9Sstevel@tonic-gate 	0x9898,					/* module id number */
1377c478bd9Sstevel@tonic-gate 	"pckt",					/* module name */
1387c478bd9Sstevel@tonic-gate 	0,					/* minimum packet size */
1397c478bd9Sstevel@tonic-gate 	INFPSZ,					/* maximum packet size */
1407c478bd9Sstevel@tonic-gate 	0,					/* hi-water mark */
1417c478bd9Sstevel@tonic-gate 	0					/* lo-water mark */
1427c478bd9Sstevel@tonic-gate };
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate static struct qinit pcktrinit = {
1457c478bd9Sstevel@tonic-gate 	(int (*)())pcktrput,
1467c478bd9Sstevel@tonic-gate 	(int (*)())pcktrsrv,
1477c478bd9Sstevel@tonic-gate 	pcktopen,
1487c478bd9Sstevel@tonic-gate 	pcktclose,
1497c478bd9Sstevel@tonic-gate 	NULL,
1507c478bd9Sstevel@tonic-gate 	&pcktiinfo,
1517c478bd9Sstevel@tonic-gate 	NULL
1527c478bd9Sstevel@tonic-gate };
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static struct qinit pcktwinit = {
1557c478bd9Sstevel@tonic-gate 	(int (*)())pcktwput,
1567c478bd9Sstevel@tonic-gate 	NULL,
1577c478bd9Sstevel@tonic-gate 	NULL,
1587c478bd9Sstevel@tonic-gate 	NULL,
1597c478bd9Sstevel@tonic-gate 	NULL,
1607c478bd9Sstevel@tonic-gate 	&pcktoinfo,
1617c478bd9Sstevel@tonic-gate 	NULL
1627c478bd9Sstevel@tonic-gate };
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate static struct streamtab pcktinfo = {
1657c478bd9Sstevel@tonic-gate 	&pcktrinit,
1667c478bd9Sstevel@tonic-gate 	&pcktwinit,
1677c478bd9Sstevel@tonic-gate 	NULL,
1687c478bd9Sstevel@tonic-gate 	NULL
1697c478bd9Sstevel@tonic-gate };
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * Per-instance state struct for the pckt module.
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate struct pckt_info {
1767c478bd9Sstevel@tonic-gate 	queue_t		*pi_qptr;		/* back pointer to q */
1777c478bd9Sstevel@tonic-gate 	bufcall_id_t	pi_bufcall_id;
1787c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
1797c478bd9Sstevel@tonic-gate 	model_t		model;
1807c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
1817c478bd9Sstevel@tonic-gate };
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * Dummy qbufcall callback routine used by open and close.
1857c478bd9Sstevel@tonic-gate  * The framework will wake up qwait_sig when we return from
1867c478bd9Sstevel@tonic-gate  * this routine (as part of leaving the perimeters.)
1877c478bd9Sstevel@tonic-gate  * (The framework enters the perimeters before calling the qbufcall() callback
1887c478bd9Sstevel@tonic-gate  * and leaves the perimeters after the callback routine has executed. The
1897c478bd9Sstevel@tonic-gate  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
1907c478bd9Sstevel@tonic-gate  * when it leaves the perimeter. See qwait(9E).)
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate /* ARGSUSED */
1937c478bd9Sstevel@tonic-gate static void
1947c478bd9Sstevel@tonic-gate dummy_callback(void *arg)
1957c478bd9Sstevel@tonic-gate {}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * pcktopen - open routine gets called when the
1997c478bd9Sstevel@tonic-gate  *	    module gets pushed onto the stream.
2007c478bd9Sstevel@tonic-gate  */
2017c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2027c478bd9Sstevel@tonic-gate static int
2037c478bd9Sstevel@tonic-gate pcktopen(
2047c478bd9Sstevel@tonic-gate 	queue_t *q,		/* pointer to the read side queue */
2057c478bd9Sstevel@tonic-gate 	dev_t   *devp,		/* pointer to stream tail's dev */
2067c478bd9Sstevel@tonic-gate 	int	oflag,		/* the user open(2) supplied flags */
2077c478bd9Sstevel@tonic-gate 	int	sflag,		/* open state flag */
2087c478bd9Sstevel@tonic-gate 	cred_t  *credp)		/* credentials */
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate 	struct pckt_info	*pip;
2117c478bd9Sstevel@tonic-gate 	mblk_t			*mop; /* ptr to a setopts msg block */
2127c478bd9Sstevel@tonic-gate 	struct stroptions	*sop;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (sflag != MODOPEN)
2157c478bd9Sstevel@tonic-gate 		return (EINVAL);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (q->q_ptr != NULL) {
2187c478bd9Sstevel@tonic-gate 		/* It's already attached. */
2197c478bd9Sstevel@tonic-gate 		return (0);
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * Allocate state structure.
2247c478bd9Sstevel@tonic-gate 	 */
225*a0f9c00cSJosef 'Jeff' Sipek 	pip = kmem_zalloc(sizeof (*pip), KM_SLEEP);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
2287c478bd9Sstevel@tonic-gate 	pip->model = ddi_model_convert_from(get_udatamodel());
2297c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	/*
2327c478bd9Sstevel@tonic-gate 	 * Cross-link.
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate 	pip->pi_qptr = q;
2357c478bd9Sstevel@tonic-gate 	q->q_ptr = pip;
2367c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = pip;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	qprocson(q);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	/*
2417c478bd9Sstevel@tonic-gate 	 * Initialize an M_SETOPTS message to set up hi/lo water marks on
2427c478bd9Sstevel@tonic-gate 	 * stream head read queue.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	while ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
2467c478bd9Sstevel@tonic-gate 		bufcall_id_t id = qbufcall(q, sizeof (struct stroptions),
2477c478bd9Sstevel@tonic-gate 		    BPRI_MED, dummy_callback, NULL);
2487c478bd9Sstevel@tonic-gate 		if (!qwait_sig(q)) {
2497c478bd9Sstevel@tonic-gate 			qunbufcall(q, id);
2507c478bd9Sstevel@tonic-gate 			kmem_free(pip, sizeof (*pip));
2517c478bd9Sstevel@tonic-gate 			qprocsoff(q);
2527c478bd9Sstevel@tonic-gate 			return (EINTR);
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 		qunbufcall(q, id);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/*
2597c478bd9Sstevel@tonic-gate 	 * XXX: Should this module really control the hi/low water marks?
2607c478bd9Sstevel@tonic-gate 	 * Is there any reason in this code to do so?
2617c478bd9Sstevel@tonic-gate 	 */
2627c478bd9Sstevel@tonic-gate 	mop->b_datap->db_type = M_SETOPTS;
2637c478bd9Sstevel@tonic-gate 	mop->b_wptr += sizeof (struct stroptions);
2647c478bd9Sstevel@tonic-gate 	sop = (struct stroptions *)mop->b_rptr;
2657c478bd9Sstevel@tonic-gate 	sop->so_flags = SO_HIWAT | SO_LOWAT;
2667c478bd9Sstevel@tonic-gate 	sop->so_hiwat = 512;
2677c478bd9Sstevel@tonic-gate 	sop->so_lowat = 256;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	/*
2707c478bd9Sstevel@tonic-gate 	 * Commit to the open and send the M_SETOPTS off to the stream head.
2717c478bd9Sstevel@tonic-gate 	 */
2727c478bd9Sstevel@tonic-gate 	putnext(q, mop);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	return (0);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate  * pcktclose - This routine gets called when the module
2807c478bd9Sstevel@tonic-gate  *	gets popped off of the stream.
2817c478bd9Sstevel@tonic-gate  */
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2847c478bd9Sstevel@tonic-gate static int
2857c478bd9Sstevel@tonic-gate pcktclose(
2867c478bd9Sstevel@tonic-gate 	queue_t *q,	/* Pointer to the read queue */
2877c478bd9Sstevel@tonic-gate 	int	flag,
2887c478bd9Sstevel@tonic-gate 	cred_t  *credp)
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate 	struct pckt_info	*pip = (struct pckt_info *)q->q_ptr;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	qprocsoff(q);
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * Cancel outstanding qbufcall
2957c478bd9Sstevel@tonic-gate 	 */
2967c478bd9Sstevel@tonic-gate 	if (pip->pi_bufcall_id) {
2977c478bd9Sstevel@tonic-gate 		qunbufcall(q, pip->pi_bufcall_id);
2987c478bd9Sstevel@tonic-gate 		pip->pi_bufcall_id = 0;
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	/*
3017c478bd9Sstevel@tonic-gate 	 * Do not worry about msgs queued on the q, the framework
3027c478bd9Sstevel@tonic-gate 	 * will free them up.
3037c478bd9Sstevel@tonic-gate 	 */
3047c478bd9Sstevel@tonic-gate 	kmem_free(q->q_ptr, sizeof (struct pckt_info));
3057c478bd9Sstevel@tonic-gate 	q->q_ptr = WR(q)->q_ptr = NULL;
3067c478bd9Sstevel@tonic-gate 	return (0);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate  * pcktrput - Module read queue put procedure.
3117c478bd9Sstevel@tonic-gate  *	This is called from the module or
3127c478bd9Sstevel@tonic-gate  *	driver downstream.
3137c478bd9Sstevel@tonic-gate  */
3147c478bd9Sstevel@tonic-gate static void
3157c478bd9Sstevel@tonic-gate pcktrput(
3167c478bd9Sstevel@tonic-gate 	queue_t *q,	/* Pointer to the read queue */
3177c478bd9Sstevel@tonic-gate 	mblk_t *mp)	/* Pointer to the current message block */
3187c478bd9Sstevel@tonic-gate {
3197c478bd9Sstevel@tonic-gate 	mblk_t		*pckt_msgp;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
3237c478bd9Sstevel@tonic-gate 	case M_FLUSH:
3247c478bd9Sstevel@tonic-gate 		/*
3257c478bd9Sstevel@tonic-gate 		 * The PTS driver swaps the FLUSHR and FLUSHW flags
3267c478bd9Sstevel@tonic-gate 		 * we need to swap them back to reflect the actual
3277c478bd9Sstevel@tonic-gate 		 * slave side FLUSH mode.
3287c478bd9Sstevel@tonic-gate 		 */
3297c478bd9Sstevel@tonic-gate 		if ((*mp->b_rptr & FLUSHRW) != FLUSHRW)
3307c478bd9Sstevel@tonic-gate 			if ((*mp->b_rptr & FLUSHRW) == FLUSHR)
3317c478bd9Sstevel@tonic-gate 				*mp->b_rptr = FLUSHW;
3327c478bd9Sstevel@tonic-gate 			else if ((*mp->b_rptr & FLUSHRW) == FLUSHW)
3337c478bd9Sstevel@tonic-gate 				*mp->b_rptr = FLUSHR;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		pckt_msgp = copymsg(mp);
3367c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW) {
3377c478bd9Sstevel@tonic-gate 			/*
3387c478bd9Sstevel@tonic-gate 			 * In the packet model we are not allowing
3397c478bd9Sstevel@tonic-gate 			 * flushes of the master's stream head read
3407c478bd9Sstevel@tonic-gate 			 * side queue. This is because all packet
3417c478bd9Sstevel@tonic-gate 			 * state information is stored there and
3427c478bd9Sstevel@tonic-gate 			 * a flush could destroy this data before
3437c478bd9Sstevel@tonic-gate 			 * it is read.
3447c478bd9Sstevel@tonic-gate 			 */
3457c478bd9Sstevel@tonic-gate 			*mp->b_rptr = FLUSHW;
3467c478bd9Sstevel@tonic-gate 			putnext(q, mp);
3477c478bd9Sstevel@tonic-gate 		} else {
3487c478bd9Sstevel@tonic-gate 			/*
3497c478bd9Sstevel@tonic-gate 			 * Free messages that only flush the
3507c478bd9Sstevel@tonic-gate 			 * master's read queue.
3517c478bd9Sstevel@tonic-gate 			 */
3527c478bd9Sstevel@tonic-gate 			freemsg(mp);
3537c478bd9Sstevel@tonic-gate 		}
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		if (pckt_msgp == NULL)
3567c478bd9Sstevel@tonic-gate 			break;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		mp = pckt_msgp;
3597c478bd9Sstevel@tonic-gate 		/*
3607c478bd9Sstevel@tonic-gate 		 * Prefix M_PROTO and putnext.
3617c478bd9Sstevel@tonic-gate 		 */
3627c478bd9Sstevel@tonic-gate 		goto prefix_head;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	case M_DATA:
3657c478bd9Sstevel@tonic-gate 	case M_IOCTL:
3667c478bd9Sstevel@tonic-gate 	case M_PROTO:
3677c478bd9Sstevel@tonic-gate 		/*
3687c478bd9Sstevel@tonic-gate 		 * For non-priority messages, follow flow-control rules.
3697c478bd9Sstevel@tonic-gate 		 * Also, if there are messages on the q already, keep
3707c478bd9Sstevel@tonic-gate 		 * queueing them since they need to be processed in order.
3717c478bd9Sstevel@tonic-gate 		 */
3727c478bd9Sstevel@tonic-gate 		if (!canputnext(q) || (qsize(q) > 0)) {
3737c478bd9Sstevel@tonic-gate 			(void) putq(q, mp);
3747c478bd9Sstevel@tonic-gate 			break;
3757c478bd9Sstevel@tonic-gate 		}
3767c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/*
3797c478bd9Sstevel@tonic-gate 	 * For high priority messages, skip flow control checks.
3807c478bd9Sstevel@tonic-gate 	 */
3817c478bd9Sstevel@tonic-gate 	case M_PCPROTO:
3827c478bd9Sstevel@tonic-gate 	case M_READ:
3837c478bd9Sstevel@tonic-gate 	case M_STOP:
3847c478bd9Sstevel@tonic-gate 	case M_START:
3857c478bd9Sstevel@tonic-gate 	case M_STARTI:
3867c478bd9Sstevel@tonic-gate 	case M_STOPI:
3877c478bd9Sstevel@tonic-gate prefix_head:
3887c478bd9Sstevel@tonic-gate 		/*
3897c478bd9Sstevel@tonic-gate 		 * Prefix an M_PROTO header to message and pass upstream.
3907c478bd9Sstevel@tonic-gate 		 */
3917c478bd9Sstevel@tonic-gate 		if ((mp = add_ctl_info(q, mp)) != NULL)
3927c478bd9Sstevel@tonic-gate 			putnext(q, mp);
3937c478bd9Sstevel@tonic-gate 		break;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	default:
3967c478bd9Sstevel@tonic-gate 		/*
3977c478bd9Sstevel@tonic-gate 		 * For data messages, queue them back on the queue if
3987c478bd9Sstevel@tonic-gate 		 * there are messages on the queue already. This is
3997c478bd9Sstevel@tonic-gate 		 * done to preserve the order of messages.
4007c478bd9Sstevel@tonic-gate 		 * For high priority messages or for no messages on the
4017c478bd9Sstevel@tonic-gate 		 * q, simply putnext() and pass it on.
4027c478bd9Sstevel@tonic-gate 		 */
4037c478bd9Sstevel@tonic-gate 		if ((datamsg(mp->b_datap->db_type)) && (qsize(q) > 0))
4047c478bd9Sstevel@tonic-gate 			(void) putq(q, mp);
4057c478bd9Sstevel@tonic-gate 		else
4067c478bd9Sstevel@tonic-gate 			putnext(q, mp);
4077c478bd9Sstevel@tonic-gate 		break;
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate  * pcktrsrv - module read service procedure
4137c478bd9Sstevel@tonic-gate  * This function deals with messages left in the queue due to
4147c478bd9Sstevel@tonic-gate  *	(a) not enough memory to allocate the header M_PROTO message
4157c478bd9Sstevel@tonic-gate  *	(b) flow control reasons
4167c478bd9Sstevel@tonic-gate  * The function will attempt to get the messages off the queue and
4177c478bd9Sstevel@tonic-gate  * process them.
4187c478bd9Sstevel@tonic-gate  */
4197c478bd9Sstevel@tonic-gate static void
4207c478bd9Sstevel@tonic-gate pcktrsrv(queue_t *q)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 	mblk_t *mp;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	while ((mp = getq(q)) != NULL) {
4257c478bd9Sstevel@tonic-gate 		if (!canputnext(q)) {
4267c478bd9Sstevel@tonic-gate 			/*
4277c478bd9Sstevel@tonic-gate 			 * For high priority messages, make sure there is no
4287c478bd9Sstevel@tonic-gate 			 * infinite loop. Disable the queue for this case.
4297c478bd9Sstevel@tonic-gate 			 * High priority messages get here only for buffer
4307c478bd9Sstevel@tonic-gate 			 * allocation failures. Thus the bufcall callout
4317c478bd9Sstevel@tonic-gate 			 * will reenable the q.
4327c478bd9Sstevel@tonic-gate 			 * XXX bug alert - nooenable will *not* prevent
4337c478bd9Sstevel@tonic-gate 			 * putbq of a hipri messages frm enabling the queue.
4347c478bd9Sstevel@tonic-gate 			 */
4357c478bd9Sstevel@tonic-gate 			if (!datamsg(mp->b_datap->db_type))
4367c478bd9Sstevel@tonic-gate 				noenable(q);
4377c478bd9Sstevel@tonic-gate 			(void) putbq(q, mp);
4387c478bd9Sstevel@tonic-gate 			return;
4397c478bd9Sstevel@tonic-gate 		}
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 		/*
4427c478bd9Sstevel@tonic-gate 		 * M_FLUSH msgs may also be here if there was a memory
4437c478bd9Sstevel@tonic-gate 		 * failure.
4447c478bd9Sstevel@tonic-gate 		 */
4457c478bd9Sstevel@tonic-gate 		switch (mp->b_datap->db_type) {
4467c478bd9Sstevel@tonic-gate 		case M_FLUSH:
4477c478bd9Sstevel@tonic-gate 		case M_PROTO:
4487c478bd9Sstevel@tonic-gate 		case M_PCPROTO:
4497c478bd9Sstevel@tonic-gate 		case M_STOP:
4507c478bd9Sstevel@tonic-gate 		case M_START:
4517c478bd9Sstevel@tonic-gate 		case M_IOCTL:
4527c478bd9Sstevel@tonic-gate 		case M_DATA:
4537c478bd9Sstevel@tonic-gate 		case M_READ:
4547c478bd9Sstevel@tonic-gate 		case M_STARTI:
4557c478bd9Sstevel@tonic-gate 		case M_STOPI:
4567c478bd9Sstevel@tonic-gate 			/*
4577c478bd9Sstevel@tonic-gate 			 * Prefix an M_PROTO header to msg and pass upstream.
4587c478bd9Sstevel@tonic-gate 			 */
4597c478bd9Sstevel@tonic-gate 			if ((mp = add_ctl_info(q, mp)) == NULL) {
4607c478bd9Sstevel@tonic-gate 				/*
4617c478bd9Sstevel@tonic-gate 				 * Running into memory or flow ctl problems.
4627c478bd9Sstevel@tonic-gate 				 */
4637c478bd9Sstevel@tonic-gate 				return;
4647c478bd9Sstevel@tonic-gate 			}
4657c478bd9Sstevel@tonic-gate 			/* FALL THROUGH */
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		default:
4687c478bd9Sstevel@tonic-gate 			putnext(q, mp);
4697c478bd9Sstevel@tonic-gate 			break;
4707c478bd9Sstevel@tonic-gate 		}
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /*
4757c478bd9Sstevel@tonic-gate  * pcktwput - Module write queue put procedure.
4767c478bd9Sstevel@tonic-gate  *	All messages are send downstream unchanged
4777c478bd9Sstevel@tonic-gate  */
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate static void
4807c478bd9Sstevel@tonic-gate pcktwput(
4817c478bd9Sstevel@tonic-gate 	queue_t *q,	/* Pointer to the read queue */
4827c478bd9Sstevel@tonic-gate 	mblk_t *mp)	/* Pointer to current message block */
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate 	putnext(q, mp);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate  * reallocb - copy the data block from the given message block into a new block.
4907c478bd9Sstevel@tonic-gate  * This function is used in case data block had another message block
4917c478bd9Sstevel@tonic-gate  * pointing to it (and hence we just copy this one data block).
4927c478bd9Sstevel@tonic-gate  *
4937c478bd9Sstevel@tonic-gate  * Returns new message block if successful. On failure it returns NULL.
4947c478bd9Sstevel@tonic-gate  * It also tries to do a qbufcall and if that also fails,
4957c478bd9Sstevel@tonic-gate  * it frees the message block.
4967c478bd9Sstevel@tonic-gate  */
4977c478bd9Sstevel@tonic-gate static mblk_t *
4987c478bd9Sstevel@tonic-gate pckt_reallocb(
4997c478bd9Sstevel@tonic-gate 	queue_t *q,	/* Pointer to the read queue */
5007c478bd9Sstevel@tonic-gate 	mblk_t *mp	/* Pointer to the message block to be changed */
5017c478bd9Sstevel@tonic-gate )
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate 	mblk_t	*nmp;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_datap->db_ref >= 1);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	/*
5087c478bd9Sstevel@tonic-gate 	 * No reallocation is needed if there is only one reference
5097c478bd9Sstevel@tonic-gate 	 * to this data block.
5107c478bd9Sstevel@tonic-gate 	 */
5117c478bd9Sstevel@tonic-gate 	if (mp->b_datap->db_ref == 1)
5127c478bd9Sstevel@tonic-gate 		return (mp);
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if ((nmp = copyb(mp)) == NULL) {
5157c478bd9Sstevel@tonic-gate 		struct pckt_info	*pip = (struct pckt_info *)q->q_ptr;
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 		noenable(q);
5187c478bd9Sstevel@tonic-gate 		if (pip->pi_bufcall_id = qbufcall(q, mp->b_wptr - mp->b_rptr,
5197c478bd9Sstevel@tonic-gate 		    BPRI_MED, add_ctl_wkup, q)) {
5207c478bd9Sstevel@tonic-gate 			/*
5217c478bd9Sstevel@tonic-gate 			 * Put the message back onto the q.
5227c478bd9Sstevel@tonic-gate 			 */
5237c478bd9Sstevel@tonic-gate 			(void) putq(q, mp);
5247c478bd9Sstevel@tonic-gate 		} else {
5257c478bd9Sstevel@tonic-gate 			/*
5267c478bd9Sstevel@tonic-gate 			 * Things are pretty bad and serious if bufcall fails!
5277c478bd9Sstevel@tonic-gate 			 * Drop the message in this case.
5287c478bd9Sstevel@tonic-gate 			 */
5297c478bd9Sstevel@tonic-gate 			freemsg(mp);
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 		return ((mblk_t *)0);
5327c478bd9Sstevel@tonic-gate 	}
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	nmp->b_cont = mp->b_cont;
5357c478bd9Sstevel@tonic-gate 	freeb(mp);
5367c478bd9Sstevel@tonic-gate 	return (nmp);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate  * add_ctl_info: add message control information to in coming
5427c478bd9Sstevel@tonic-gate  * 	message.
5437c478bd9Sstevel@tonic-gate  */
5447c478bd9Sstevel@tonic-gate static mblk_t *
5457c478bd9Sstevel@tonic-gate add_ctl_info(
5467c478bd9Sstevel@tonic-gate 	queue_t *q,		/* pointer to the read queue */
5477c478bd9Sstevel@tonic-gate 	mblk_t	*mp)		/* pointer to the raw data input message */
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate 	struct pckt_info	*pip = (struct pckt_info *)q->q_ptr;
5507c478bd9Sstevel@tonic-gate 	mblk_t	*bp;		/* pointer to the unmodified message block */
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	/*
5537c478bd9Sstevel@tonic-gate 	 * Waiting on space for previous message?
5547c478bd9Sstevel@tonic-gate 	 */
5557c478bd9Sstevel@tonic-gate 	if (pip->pi_bufcall_id) {
5567c478bd9Sstevel@tonic-gate 		/*
5577c478bd9Sstevel@tonic-gate 		 * Chain this message on to q for later processing.
5587c478bd9Sstevel@tonic-gate 		 */
5597c478bd9Sstevel@tonic-gate 		(void) putq(q, mp);
5607c478bd9Sstevel@tonic-gate 		return (NULL);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/*
5647c478bd9Sstevel@tonic-gate 	 * Need to add the message block header as
5657c478bd9Sstevel@tonic-gate 	 * an M_PROTO type message.
5667c478bd9Sstevel@tonic-gate 	 */
5677c478bd9Sstevel@tonic-gate 	if ((bp = allocb(sizeof (char), BPRI_MED)) == (mblk_t *)NULL) {
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 		/*
5707c478bd9Sstevel@tonic-gate 		 * There are two reasons to disable the q:
5717c478bd9Sstevel@tonic-gate 		 * (1) Flow control reasons should not wake up the q.
5727c478bd9Sstevel@tonic-gate 		 * (2) High priority messages will wakeup the q
5737c478bd9Sstevel@tonic-gate 		 *	immediately. Disallow this.
5747c478bd9Sstevel@tonic-gate 		 */
5757c478bd9Sstevel@tonic-gate 		noenable(q);
5767c478bd9Sstevel@tonic-gate 		if (pip->pi_bufcall_id = qbufcall(q, sizeof (char), BPRI_MED,
5777c478bd9Sstevel@tonic-gate 		    add_ctl_wkup, q)) {
5787c478bd9Sstevel@tonic-gate 			/*
5797c478bd9Sstevel@tonic-gate 			 * Add the message to the q.
5807c478bd9Sstevel@tonic-gate 			 */
5817c478bd9Sstevel@tonic-gate 			(void) putq(q, mp);
5827c478bd9Sstevel@tonic-gate 		} else {
5837c478bd9Sstevel@tonic-gate 			/*
5847c478bd9Sstevel@tonic-gate 			 * Things are pretty bad and serious if bufcall fails!
5857c478bd9Sstevel@tonic-gate 			 * Drop the message in this case.
5867c478bd9Sstevel@tonic-gate 			 */
5877c478bd9Sstevel@tonic-gate 			freemsg(mp);
5887c478bd9Sstevel@tonic-gate 		}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 		return (NULL);
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * Copy the message type information to this message.
5957c478bd9Sstevel@tonic-gate 	 */
5967c478bd9Sstevel@tonic-gate 	bp->b_datap->db_type = M_PROTO;
5977c478bd9Sstevel@tonic-gate 	*(unsigned char *)bp->b_rptr = mp->b_datap->db_type;
5987c478bd9Sstevel@tonic-gate 	bp->b_wptr++;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
6017c478bd9Sstevel@tonic-gate 	/*
6027c478bd9Sstevel@tonic-gate 	 * Check the datamodel and if the calling program is
6037c478bd9Sstevel@tonic-gate 	 * an ILP32 application then we covert the M_IOCTLs and M_READs
6047c478bd9Sstevel@tonic-gate 	 * into the native ILP32 format before passing them upstream
6057c478bd9Sstevel@tonic-gate 	 * to user mode.
6067c478bd9Sstevel@tonic-gate 	 */
6077c478bd9Sstevel@tonic-gate 	switch (pip->model) {
6087c478bd9Sstevel@tonic-gate 	case DDI_MODEL_ILP32:
6097c478bd9Sstevel@tonic-gate 		switch (mp->b_datap->db_type) {
6107c478bd9Sstevel@tonic-gate 			/*
6117c478bd9Sstevel@tonic-gate 			 * This structure must have the same shape as
6127c478bd9Sstevel@tonic-gate 			 * the * ILP32 compilation of `struct iocblk'
6137c478bd9Sstevel@tonic-gate 			 * from <sys/stream.h>.
6147c478bd9Sstevel@tonic-gate 			 */
6157c478bd9Sstevel@tonic-gate 			struct iocblk32 {
6167c478bd9Sstevel@tonic-gate 				int32_t   	ioc_cmd;
6177c478bd9Sstevel@tonic-gate 				caddr32_t	ioc_cr;
6187c478bd9Sstevel@tonic-gate 				uint32_t	ioc_id;
6197c478bd9Sstevel@tonic-gate 				int32_t   	ioc_count;
6207c478bd9Sstevel@tonic-gate 				int32_t   	ioc_error;
6217c478bd9Sstevel@tonic-gate 				int32_t   	ioc_rval;
6227c478bd9Sstevel@tonic-gate 				int32_t   	ioc_fill1;
6237c478bd9Sstevel@tonic-gate 				uint32_t	ioc_flag;
6247c478bd9Sstevel@tonic-gate 				int32_t   	ioc_filler[2];
6257c478bd9Sstevel@tonic-gate 			} niocblk_32;
6267c478bd9Sstevel@tonic-gate 			struct iocblk		*iocblk_64;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 		case M_IOCTL:
6297c478bd9Sstevel@tonic-gate 			if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
6307c478bd9Sstevel@tonic-gate 				return ((mblk_t *)0);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 			bzero(&niocblk_32, sizeof (niocblk_32));
6337c478bd9Sstevel@tonic-gate 			iocblk_64 = (struct iocblk *)mp->b_rptr;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 			/* Leave the pointer to cred_t structure as it is. */
6367c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_cmd = iocblk_64->ioc_cmd;
6377c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_cr = (caddr32_t)(uintptr_t)
6387c478bd9Sstevel@tonic-gate 			    iocblk_64->ioc_cr;
6397c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_id = iocblk_64->ioc_id;
6407c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_count = iocblk_64->ioc_count;
6417c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_error = iocblk_64->ioc_error;
6427c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_rval = iocblk_64->ioc_rval;
6437c478bd9Sstevel@tonic-gate 			niocblk_32.ioc_flag = iocblk_64->ioc_flag;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 			/* Copy the iocblk structure for ILP32 back */
6467c478bd9Sstevel@tonic-gate 			*(struct iocblk32 *)mp->b_rptr = niocblk_32;
6477c478bd9Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr + sizeof (struct iocblk32);
6487c478bd9Sstevel@tonic-gate 			break;
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 		case M_READ:
6517c478bd9Sstevel@tonic-gate 			if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
6527c478bd9Sstevel@tonic-gate 				return ((mblk_t *)0);
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 			/* change the size_t to size32_t for ILP32 */
6557c478bd9Sstevel@tonic-gate 			*(size32_t *)mp->b_rptr = *(size_t *)mp->b_rptr;
6567c478bd9Sstevel@tonic-gate 			mp->b_wptr = mp->b_rptr + sizeof (size32_t);
6577c478bd9Sstevel@tonic-gate 			break;
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 		break;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	case DATAMODEL_NONE:
6627c478bd9Sstevel@tonic-gate 		break;
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	/*
6677c478bd9Sstevel@tonic-gate 	 * Now change the orginal message type to M_DATA and tie them up.
6687c478bd9Sstevel@tonic-gate 	 */
6697c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_DATA;
6707c478bd9Sstevel@tonic-gate 	bp->b_cont = mp;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	return (bp);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate static void
6767c478bd9Sstevel@tonic-gate add_ctl_wkup(void *arg)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate 	queue_t *q = arg;	/* ptr to the read queue */
6797c478bd9Sstevel@tonic-gate 	struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	pip->pi_bufcall_id = 0;
6827c478bd9Sstevel@tonic-gate 	/*
6837c478bd9Sstevel@tonic-gate 	 * Allow enabling of the q to allow the service
6847c478bd9Sstevel@tonic-gate 	 * function to do its job.
6857c478bd9Sstevel@tonic-gate 	 *
6867c478bd9Sstevel@tonic-gate 	 * Also, qenable() to schedule the q immediately.
6877c478bd9Sstevel@tonic-gate 	 * This is to ensure timely processing of high priority
6887c478bd9Sstevel@tonic-gate 	 * messages if they are on the q.
6897c478bd9Sstevel@tonic-gate 	 */
6907c478bd9Sstevel@tonic-gate 	enableok(q);
6917c478bd9Sstevel@tonic-gate 	qenable(q);
6927c478bd9Sstevel@tonic-gate }
693