10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53448Sdh155122 * Common Development and Distribution License (the "License").
63448Sdh155122 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11042SErik.Nordmark@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate /* Copyright (c) 1990 Mentat Inc. */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <inet/common.h> /* for various inet/mi.h and inet/nd.h needs */
290Sstevel@tonic-gate #include <sys/stream.h>
300Sstevel@tonic-gate #include <sys/stropts.h>
310Sstevel@tonic-gate #include <sys/strsun.h>
320Sstevel@tonic-gate #include <sys/sysmacros.h>
330Sstevel@tonic-gate #include <inet/nd.h>
340Sstevel@tonic-gate #include <inet/mi.h>
350Sstevel@tonic-gate #define _SUN_TPI_VERSION 2
360Sstevel@tonic-gate #include <sys/tihdr.h>
370Sstevel@tonic-gate #include <sys/timod.h>
380Sstevel@tonic-gate #include <sys/vtrace.h>
390Sstevel@tonic-gate #include <sys/kmem.h>
400Sstevel@tonic-gate #include <sys/mkdev.h>
410Sstevel@tonic-gate #include <sys/strlog.h>
420Sstevel@tonic-gate #include <sys/ddi.h>
430Sstevel@tonic-gate #include <sys/suntpi.h>
440Sstevel@tonic-gate #include <sys/cmn_err.h>
450Sstevel@tonic-gate #include <sys/debug.h>
460Sstevel@tonic-gate #include <sys/kobj.h>
478348SEric.Yu@Sun.COM #include <sys/stropts.h>
488348SEric.Yu@Sun.COM #include <sys/strsubr.h>
498348SEric.Yu@Sun.COM #include <inet/proto_set.h>
500Sstevel@tonic-gate
510Sstevel@tonic-gate #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9')
520Sstevel@tonic-gate #define ISUPPER(ch) ((ch) >= 'A' && (ch) <= 'Z')
530Sstevel@tonic-gate #define tolower(ch) ('a' + ((ch) - 'A'))
540Sstevel@tonic-gate
550Sstevel@tonic-gate #define MI_IS_TRANSPARENT(mp) (mp->b_cont && \
560Sstevel@tonic-gate (mp->b_cont->b_rptr != mp->b_cont->b_wptr))
570Sstevel@tonic-gate
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate * NOTE: Whenever anything is allocated by mi_alloc or mi_alloc_sleep (below),
600Sstevel@tonic-gate * the size of the requested allocation is increased by one word. This extra
610Sstevel@tonic-gate * word is used to store the size of the object being allocated, and is located
620Sstevel@tonic-gate * at the beginning of the allocated block. The pointer returned to the caller
630Sstevel@tonic-gate * is a pointer to the *second* word in the newly-allocated block. The IP
640Sstevel@tonic-gate * module of mdb is aware of this, and will need to be changed if this
650Sstevel@tonic-gate * allocation strategy is changed.
660Sstevel@tonic-gate */
670Sstevel@tonic-gate
688348SEric.Yu@Sun.COM typedef struct stroptions *STROPTP;
690Sstevel@tonic-gate typedef union T_primitives *TPRIMP;
700Sstevel@tonic-gate
710Sstevel@tonic-gate /* Timer block states. */
720Sstevel@tonic-gate #define TB_RUNNING 1
730Sstevel@tonic-gate #define TB_IDLE 2
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate * Could not stop/free before putq
760Sstevel@tonic-gate */
770Sstevel@tonic-gate #define TB_RESCHED 3 /* mtb_time_left contains tick count */
780Sstevel@tonic-gate #define TB_CANCELLED 4
790Sstevel@tonic-gate #define TB_TO_BE_FREED 5
800Sstevel@tonic-gate
810Sstevel@tonic-gate typedef struct mtb_s {
820Sstevel@tonic-gate int mtb_state;
830Sstevel@tonic-gate timeout_id_t mtb_tid;
840Sstevel@tonic-gate queue_t *mtb_q;
850Sstevel@tonic-gate MBLKP mtb_mp;
860Sstevel@tonic-gate clock_t mtb_time_left;
870Sstevel@tonic-gate } MTB, *MTBP;
880Sstevel@tonic-gate
890Sstevel@tonic-gate static int mi_timer_fire(MTBP);
900Sstevel@tonic-gate static int mi_iprintf(char *, va_list, pfi_t, char *);
910Sstevel@tonic-gate static void mi_tpi_addr_and_opt(MBLKP, char *, t_scalar_t, char *, t_scalar_t);
920Sstevel@tonic-gate static MBLKP mi_tpi_trailer_alloc(MBLKP, size_t, t_scalar_t);
930Sstevel@tonic-gate
940Sstevel@tonic-gate /* ARGSUSED1 */
950Sstevel@tonic-gate void *
mi_alloc(size_t size,uint_t pri)960Sstevel@tonic-gate mi_alloc(size_t size, uint_t pri)
970Sstevel@tonic-gate {
980Sstevel@tonic-gate size_t *ptr;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate size += sizeof (size);
1010Sstevel@tonic-gate if (ptr = kmem_alloc(size, KM_NOSLEEP)) {
1020Sstevel@tonic-gate *ptr = size;
1030Sstevel@tonic-gate return (ptr + 1);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate return (NULL);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate /* ARGSUSED1 */
1090Sstevel@tonic-gate void *
mi_alloc_sleep(size_t size,uint_t pri)1100Sstevel@tonic-gate mi_alloc_sleep(size_t size, uint_t pri)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate size_t *ptr;
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate size += sizeof (size);
1150Sstevel@tonic-gate ptr = kmem_alloc(size, KM_SLEEP);
1160Sstevel@tonic-gate *ptr = size;
1170Sstevel@tonic-gate return (ptr + 1);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate int
mi_close_comm(void ** mi_headp,queue_t * q)1210Sstevel@tonic-gate mi_close_comm(void **mi_headp, queue_t *q)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate IDP ptr;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate ptr = q->q_ptr;
1260Sstevel@tonic-gate mi_close_unlink(mi_headp, ptr);
1270Sstevel@tonic-gate mi_close_free(ptr);
1280Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL;
1290Sstevel@tonic-gate return (0);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate void
mi_close_unlink(void ** mi_headp,IDP ptr)1330Sstevel@tonic-gate mi_close_unlink(void **mi_headp, IDP ptr)
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
1360Sstevel@tonic-gate MI_OP mi_o;
1370Sstevel@tonic-gate dev_t dev;
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate mi_o = (MI_OP)ptr;
1400Sstevel@tonic-gate if (!mi_o)
1410Sstevel@tonic-gate return;
1420Sstevel@tonic-gate mi_o--;
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate if (mi_o->mi_o_next == NULL) {
1450Sstevel@tonic-gate /* Not in list */
1460Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev == NULL);
1470Sstevel@tonic-gate return;
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate /* Free minor number */
1510Sstevel@tonic-gate dev = mi_o->mi_o_dev;
1520Sstevel@tonic-gate if ((dev != OPENFAIL) && (dev != 0) && (dev <= MAXMIN))
1530Sstevel@tonic-gate inet_minor_free(mi_head->mh_arena, dev);
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate /* Unlink from list */
1560Sstevel@tonic-gate ASSERT(mi_o->mi_o_next != NULL);
1570Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev != NULL);
1580Sstevel@tonic-gate ASSERT(mi_o->mi_o_next->mi_o_prev == mi_o);
1590Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev->mi_o_next == mi_o);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate mi_o->mi_o_next->mi_o_prev = mi_o->mi_o_prev;
1620Sstevel@tonic-gate mi_o->mi_o_prev->mi_o_next = mi_o->mi_o_next;
1630Sstevel@tonic-gate mi_o->mi_o_next = mi_o->mi_o_prev = NULL;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate mi_o->mi_o_dev = (dev_t)OPENFAIL;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /* If list now empty free the list head */
1680Sstevel@tonic-gate if (mi_head->mh_o.mi_o_next == &mi_head->mh_o) {
1690Sstevel@tonic-gate ASSERT(mi_head->mh_o.mi_o_prev == &mi_head->mh_o);
1700Sstevel@tonic-gate if (mi_head->mh_arena != NULL)
1710Sstevel@tonic-gate inet_minor_destroy(mi_head->mh_arena);
1720Sstevel@tonic-gate mi_free((IDP)mi_head);
1730Sstevel@tonic-gate *mi_headp = NULL;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate void
mi_close_free(IDP ptr)1780Sstevel@tonic-gate mi_close_free(IDP ptr)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate MI_OP mi_o;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate mi_o = (MI_OP)ptr;
1830Sstevel@tonic-gate if (!mi_o)
1840Sstevel@tonic-gate return;
1850Sstevel@tonic-gate mi_o--;
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate ASSERT(mi_o->mi_o_next == NULL && mi_o->mi_o_prev == NULL);
1880Sstevel@tonic-gate mi_free((IDP)mi_o);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate * mi_copyin - takes care of transparent or non-transparent ioctl for the
1930Sstevel@tonic-gate * calling function so that they have to deal with just M_IOCDATA type
1940Sstevel@tonic-gate * and not worry about M_COPYIN.
1950Sstevel@tonic-gate *
1960Sstevel@tonic-gate * mi_copyin checks to see if the ioctl is transparent or non transparent.
1970Sstevel@tonic-gate * In case of a non_transparent ioctl, it packs the data into a M_IOCDATA
1980Sstevel@tonic-gate * message and puts it back onto the current queue for further processing.
1990Sstevel@tonic-gate * In case of transparent ioctl, it sends a M_COPYIN message up to the
2000Sstevel@tonic-gate * streamhead so that a M_IOCDATA with the information comes back down.
2010Sstevel@tonic-gate */
2020Sstevel@tonic-gate void
mi_copyin(queue_t * q,MBLKP mp,char * uaddr,size_t len)2030Sstevel@tonic-gate mi_copyin(queue_t *q, MBLKP mp, char *uaddr, size_t len)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
2060Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr;
2070Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)mp->b_rptr;
2080Sstevel@tonic-gate int err;
2090Sstevel@tonic-gate MBLKP mp1;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCTL && !uaddr);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /* A transparent ioctl. Send a M_COPYIN message to the streamhead. */
2140Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
2150Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1;
2160Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN;
2170Sstevel@tonic-gate cq->cq_private = mp->b_cont;
2180Sstevel@tonic-gate cq->cq_size = len;
2190Sstevel@tonic-gate cq->cq_flag = 0;
2200Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr));
2210Sstevel@tonic-gate mp->b_cont = NULL;
2220Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN;
2230Sstevel@tonic-gate qreply(q, mp);
2240Sstevel@tonic-gate return;
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate * A non-transparent ioctl. Need to convert into M_IOCDATA message.
2290Sstevel@tonic-gate *
2300Sstevel@tonic-gate * We allocate a 0 byte message block and put its address in
2310Sstevel@tonic-gate * cp_private. It also makes the b_prev field = 1 and b_next
2320Sstevel@tonic-gate * field = MI_COPY_IN for this 0 byte block. This is done to
2330Sstevel@tonic-gate * maintain compatibility with old code in mi_copy_state
2340Sstevel@tonic-gate * (which removes the empty block).
2350Sstevel@tonic-gate */
2360Sstevel@tonic-gate err = miocpullup(mp, len);
2370Sstevel@tonic-gate if (err != 0)
2380Sstevel@tonic-gate goto err_ret;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED);
2410Sstevel@tonic-gate if (mp1 == NULL) {
2420Sstevel@tonic-gate err = ENOMEM;
2430Sstevel@tonic-gate goto err_ret;
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * Temporarily insert mp1 between the M_IOCTL and M_DATA blocks so
2480Sstevel@tonic-gate * that we can use the MI_COPY_COUNT & MI_COPY_DIRECTION macros.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate mp1->b_cont = mp->b_cont;
2510Sstevel@tonic-gate mp->b_cont = mp1;
2520Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1;
2530Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN;
2540Sstevel@tonic-gate mp->b_cont = mp1->b_cont;
2550Sstevel@tonic-gate mp1->b_cont = NULL;
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate * Leave a pointer to the 0 byte block in cp_private field for
2590Sstevel@tonic-gate * future use by the mi_copy_* routines.
2600Sstevel@tonic-gate */
2610Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA;
2620Sstevel@tonic-gate cp->cp_private = mp1;
2630Sstevel@tonic-gate cp->cp_rval = NULL;
2640Sstevel@tonic-gate put(q, mp);
2650Sstevel@tonic-gate return;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate err_ret:
2680Sstevel@tonic-gate iocp->ioc_error = err;
2690Sstevel@tonic-gate iocp->ioc_count = 0;
2700Sstevel@tonic-gate if (mp->b_cont) {
2710Sstevel@tonic-gate freemsg(mp->b_cont);
2720Sstevel@tonic-gate mp->b_cont = NULL;
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
2750Sstevel@tonic-gate qreply(q, mp);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate * Allows transparent IOCTLs to have multiple copyins. This is needed
2800Sstevel@tonic-gate * for some variable-length structures, where the total size is only known
2810Sstevel@tonic-gate * after the first part is copied in. Rather than setting MI_COPY_COUNT to
2820Sstevel@tonic-gate * 1, as in mi_coypin(), it is simply incremented here. This value can
2830Sstevel@tonic-gate * then be checked in the returned IOCBLK.
2840Sstevel@tonic-gate *
2850Sstevel@tonic-gate * As this deals with copyins that follow the initial copyin, the byte
2860Sstevel@tonic-gate * offset into the user buffer from which copying should begin must be
2870Sstevel@tonic-gate * passed in in the offset parameter.
2880Sstevel@tonic-gate *
2890Sstevel@tonic-gate * Unlike mi_coypin(), this function expects to be passed an mblk chain
2900Sstevel@tonic-gate * headed by an M_IOCBLK, as that's the chain that will be in use for
2910Sstevel@tonic-gate * copies after the first one (copies where n != 1).
2920Sstevel@tonic-gate */
2930Sstevel@tonic-gate void
mi_copyin_n(queue_t * q,MBLKP mp,size_t offset,size_t len)2940Sstevel@tonic-gate mi_copyin_n(queue_t *q, MBLKP mp, size_t offset, size_t len)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr;
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCDATA);
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate MI_COPY_COUNT(mp)++;
3010Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN;
3020Sstevel@tonic-gate cq->cq_private = mp->b_cont;
3030Sstevel@tonic-gate cq->cq_size = len;
3040Sstevel@tonic-gate cq->cq_flag = 0;
3050Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr));
3060Sstevel@tonic-gate cq->cq_addr += offset;
3070Sstevel@tonic-gate mp->b_cont = NULL;
3080Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN;
3090Sstevel@tonic-gate qreply(q, mp);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate void
mi_copyout(queue_t * q,MBLKP mp)3130Sstevel@tonic-gate mi_copyout(queue_t *q, MBLKP mp)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
3160Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)iocp;
3170Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)cq;
3180Sstevel@tonic-gate MBLKP mp1;
3190Sstevel@tonic-gate MBLKP mp2;
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate if (mp->b_datap->db_type != M_IOCDATA || !mp->b_cont) {
3220Sstevel@tonic-gate mi_copy_done(q, mp, EPROTO);
3230Sstevel@tonic-gate return;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate /* Check completion of previous copyout operation. */
3260Sstevel@tonic-gate mp1 = mp->b_cont;
3270Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval || !mp1->b_cont) {
3280Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval);
3290Sstevel@tonic-gate return;
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate if (!mp1->b_cont->b_cont && !MI_IS_TRANSPARENT(mp)) {
3320Sstevel@tonic-gate mp1->b_next = NULL;
3330Sstevel@tonic-gate mp1->b_prev = NULL;
3340Sstevel@tonic-gate mp->b_cont = mp1->b_cont;
3350Sstevel@tonic-gate freeb(mp1);
3360Sstevel@tonic-gate mp1 = mp->b_cont;
3370Sstevel@tonic-gate mp1->b_next = NULL;
3380Sstevel@tonic-gate mp1->b_prev = NULL;
3390Sstevel@tonic-gate iocp->ioc_count = mp1->b_wptr - mp1->b_rptr;
3400Sstevel@tonic-gate iocp->ioc_error = 0;
3410Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
3420Sstevel@tonic-gate qreply(q, mp);
3430Sstevel@tonic-gate return;
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate if (MI_COPY_DIRECTION(mp) == MI_COPY_IN) {
3460Sstevel@tonic-gate /* Set up for first copyout. */
3470Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT;
3480Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1;
3490Sstevel@tonic-gate } else {
3500Sstevel@tonic-gate ++MI_COPY_COUNT(mp);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate cq->cq_private = mp1;
3530Sstevel@tonic-gate /* Find message preceding last. */
3540Sstevel@tonic-gate for (mp2 = mp1; mp2->b_cont->b_cont; mp2 = mp2->b_cont)
3550Sstevel@tonic-gate ;
3560Sstevel@tonic-gate if (mp2 == mp1)
3570Sstevel@tonic-gate bcopy((char *)mp1->b_rptr, (char *)&cq->cq_addr,
3580Sstevel@tonic-gate sizeof (cq->cq_addr));
3590Sstevel@tonic-gate else
3600Sstevel@tonic-gate cq->cq_addr = (char *)mp2->b_cont->b_next;
3610Sstevel@tonic-gate mp1 = mp2->b_cont;
3620Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT;
3630Sstevel@tonic-gate mp->b_cont = mp1;
3640Sstevel@tonic-gate mp2->b_cont = NULL;
3650Sstevel@tonic-gate mp1->b_next = NULL;
3660Sstevel@tonic-gate cq->cq_size = mp1->b_wptr - mp1->b_rptr;
3670Sstevel@tonic-gate cq->cq_flag = 0;
3680Sstevel@tonic-gate qreply(q, mp);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate MBLKP
mi_copyout_alloc(queue_t * q,MBLKP mp,char * uaddr,size_t len,boolean_t free_on_error)3720Sstevel@tonic-gate mi_copyout_alloc(queue_t *q, MBLKP mp, char *uaddr, size_t len,
3730Sstevel@tonic-gate boolean_t free_on_error)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
3760Sstevel@tonic-gate MBLKP mp1;
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) {
3790Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) {
3800Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED);
3810Sstevel@tonic-gate if (mp1 == NULL) {
3820Sstevel@tonic-gate if (free_on_error) {
3830Sstevel@tonic-gate iocp->ioc_error = ENOMEM;
3840Sstevel@tonic-gate iocp->ioc_count = 0;
3850Sstevel@tonic-gate freemsg(mp->b_cont);
3860Sstevel@tonic-gate mp->b_cont = NULL;
3870Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
3880Sstevel@tonic-gate qreply(q, mp);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate return (NULL);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate mp1->b_cont = mp->b_cont;
3930Sstevel@tonic-gate mp->b_cont = mp1;
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate MI_COPY_COUNT(mp) = 0;
3960Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT;
3970Sstevel@tonic-gate /* Make sure it looks clean to mi_copyout. */
3980Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA;
3990Sstevel@tonic-gate ((struct copyresp *)iocp)->cp_rval = NULL;
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate mp1 = allocb(len, BPRI_MED);
4020Sstevel@tonic-gate if (mp1 == NULL) {
4030Sstevel@tonic-gate if (free_on_error)
4040Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM);
4050Sstevel@tonic-gate return (NULL);
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate linkb(mp, mp1);
4080Sstevel@tonic-gate mp1->b_next = (MBLKP)uaddr;
4090Sstevel@tonic-gate return (mp1);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate void
mi_copy_done(queue_t * q,MBLKP mp,int err)4130Sstevel@tonic-gate mi_copy_done(queue_t *q, MBLKP mp, int err)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate struct iocblk *iocp;
4160Sstevel@tonic-gate MBLKP mp1;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate if (!mp)
4190Sstevel@tonic-gate return;
4200Sstevel@tonic-gate if (!q || (mp->b_wptr - mp->b_rptr) < sizeof (struct iocblk)) {
4210Sstevel@tonic-gate freemsg(mp);
4220Sstevel@tonic-gate return;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
4250Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
4260Sstevel@tonic-gate iocp->ioc_error = err;
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate iocp->ioc_count = 0;
4290Sstevel@tonic-gate if ((mp1 = mp->b_cont) != NULL) {
4300Sstevel@tonic-gate for (; mp1; mp1 = mp1->b_cont) {
4310Sstevel@tonic-gate mp1->b_prev = NULL;
4320Sstevel@tonic-gate mp1->b_next = NULL;
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate freemsg(mp->b_cont);
4350Sstevel@tonic-gate mp->b_cont = NULL;
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate qreply(q, mp);
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate int
mi_copy_state(queue_t * q,MBLKP mp,MBLKP * mpp)4410Sstevel@tonic-gate mi_copy_state(queue_t *q, MBLKP mp, MBLKP *mpp)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
4440Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)iocp;
4450Sstevel@tonic-gate MBLKP mp1;
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate mp1 = mp->b_cont;
4480Sstevel@tonic-gate mp->b_cont = cp->cp_private;
4490Sstevel@tonic-gate if (mp1) {
4500Sstevel@tonic-gate if (mp1->b_cont && !pullupmsg(mp1, -1)) {
4510Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM);
4520Sstevel@tonic-gate return (-1);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate linkb(mp->b_cont, mp1);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval) {
4570Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval);
4580Sstevel@tonic-gate return (-1);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate if (mpp && MI_COPY_DIRECTION(mp) == MI_COPY_IN)
4610Sstevel@tonic-gate *mpp = mp1;
4620Sstevel@tonic-gate return (MI_COPY_STATE(mp));
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate void
mi_free(void * ptr)4660Sstevel@tonic-gate mi_free(void *ptr)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate size_t size;
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate if (!ptr)
4710Sstevel@tonic-gate return;
4720Sstevel@tonic-gate if ((size = ((size_t *)ptr)[-1]) <= 0)
4730Sstevel@tonic-gate cmn_err(CE_PANIC, "mi_free");
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate kmem_free((void *) ((size_t *)ptr - 1), size);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate static int
mi_iprintf(char * fmt,va_list ap,pfi_t putc_func,char * cookie)4790Sstevel@tonic-gate mi_iprintf(char *fmt, va_list ap, pfi_t putc_func, char *cookie)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate int base;
4820Sstevel@tonic-gate char buf[(sizeof (long) * 3) + 1];
4830Sstevel@tonic-gate static char hex_val[] = "0123456789abcdef";
4840Sstevel@tonic-gate int ch;
4850Sstevel@tonic-gate int count;
4860Sstevel@tonic-gate char *cp1;
4870Sstevel@tonic-gate int digits;
4880Sstevel@tonic-gate char *fcp;
4890Sstevel@tonic-gate boolean_t is_long;
4900Sstevel@tonic-gate ulong_t uval;
4910Sstevel@tonic-gate long val;
4920Sstevel@tonic-gate boolean_t zero_filled;
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (!fmt)
4950Sstevel@tonic-gate return (-1);
4960Sstevel@tonic-gate count = 0;
4970Sstevel@tonic-gate while (*fmt) {
4980Sstevel@tonic-gate if (*fmt != '%' || *++fmt == '%') {
4990Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++);
5000Sstevel@tonic-gate continue;
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate if (*fmt == '0') {
5030Sstevel@tonic-gate zero_filled = B_TRUE;
5040Sstevel@tonic-gate fmt++;
5050Sstevel@tonic-gate if (!*fmt)
5060Sstevel@tonic-gate break;
5070Sstevel@tonic-gate } else
5080Sstevel@tonic-gate zero_filled = B_FALSE;
5090Sstevel@tonic-gate base = 0;
5100Sstevel@tonic-gate for (digits = 0; ISDIGIT(*fmt); fmt++) {
5110Sstevel@tonic-gate digits *= 10;
5120Sstevel@tonic-gate digits += (*fmt - '0');
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate if (!*fmt)
5150Sstevel@tonic-gate break;
5160Sstevel@tonic-gate is_long = B_FALSE;
5170Sstevel@tonic-gate if (*fmt == 'l') {
5180Sstevel@tonic-gate is_long = B_TRUE;
5190Sstevel@tonic-gate fmt++;
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate if (!*fmt)
5220Sstevel@tonic-gate break;
5230Sstevel@tonic-gate ch = *fmt++;
5240Sstevel@tonic-gate if (ISUPPER(ch)) {
5250Sstevel@tonic-gate ch = tolower(ch);
5260Sstevel@tonic-gate is_long = B_TRUE;
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate switch (ch) {
5290Sstevel@tonic-gate case 'c':
5300Sstevel@tonic-gate count += (*putc_func)(cookie, va_arg(ap, int *));
5310Sstevel@tonic-gate continue;
5320Sstevel@tonic-gate case 'd':
5330Sstevel@tonic-gate base = 10;
5340Sstevel@tonic-gate break;
5350Sstevel@tonic-gate case 'm': /* Print out memory, 2 hex chars per byte */
5360Sstevel@tonic-gate if (is_long)
5370Sstevel@tonic-gate fcp = va_arg(ap, char *);
5380Sstevel@tonic-gate else {
5390Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL)
5400Sstevel@tonic-gate fcp = (char *)cp1;
5410Sstevel@tonic-gate else
5420Sstevel@tonic-gate fcp = NULL;
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate if (!fcp) {
5450Sstevel@tonic-gate for (fcp = (char *)"(NULL)"; *fcp; fcp++)
5460Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp);
5470Sstevel@tonic-gate } else {
5480Sstevel@tonic-gate while (digits--) {
5490Sstevel@tonic-gate int u1 = *fcp++ & 0xFF;
5500Sstevel@tonic-gate count += (*putc_func)(cookie,
5510Sstevel@tonic-gate hex_val[(u1>>4)& 0xF]);
5520Sstevel@tonic-gate count += (*putc_func)(cookie,
5530Sstevel@tonic-gate hex_val[u1& 0xF]);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate continue;
5570Sstevel@tonic-gate case 'o':
5580Sstevel@tonic-gate base = 8;
5590Sstevel@tonic-gate break;
5600Sstevel@tonic-gate case 'p':
5610Sstevel@tonic-gate is_long = B_TRUE;
5620Sstevel@tonic-gate /* FALLTHRU */
5630Sstevel@tonic-gate case 'x':
5640Sstevel@tonic-gate base = 16;
5650Sstevel@tonic-gate break;
5660Sstevel@tonic-gate case 's':
5670Sstevel@tonic-gate if (is_long)
5680Sstevel@tonic-gate fcp = va_arg(ap, char *);
5690Sstevel@tonic-gate else {
5700Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL)
5710Sstevel@tonic-gate fcp = (char *)cp1;
5720Sstevel@tonic-gate else
5730Sstevel@tonic-gate fcp = NULL;
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate if (!fcp)
5760Sstevel@tonic-gate fcp = (char *)"(NULL)";
5770Sstevel@tonic-gate while (*fcp) {
5780Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp++);
5790Sstevel@tonic-gate if (digits && --digits == 0)
5800Sstevel@tonic-gate break;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate while (digits > 0) {
5830Sstevel@tonic-gate count += (*putc_func)(cookie, ' ');
5840Sstevel@tonic-gate digits--;
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate continue;
5870Sstevel@tonic-gate case 'u':
5880Sstevel@tonic-gate base = 10;
5890Sstevel@tonic-gate break;
5900Sstevel@tonic-gate default:
5910Sstevel@tonic-gate return (count);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate if (is_long)
5940Sstevel@tonic-gate val = va_arg(ap, long);
5950Sstevel@tonic-gate else
5960Sstevel@tonic-gate val = va_arg(ap, int);
5970Sstevel@tonic-gate if (base == 10 && ch != 'u') {
5980Sstevel@tonic-gate if (val < 0) {
5990Sstevel@tonic-gate count += (*putc_func)(cookie, '-');
6000Sstevel@tonic-gate val = -val;
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate uval = val;
6030Sstevel@tonic-gate } else {
6040Sstevel@tonic-gate if (is_long)
6050Sstevel@tonic-gate uval = val;
6060Sstevel@tonic-gate else
6070Sstevel@tonic-gate uval = (uint_t)val;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate /* Hand overload/restore the register variable 'fmt' */
6100Sstevel@tonic-gate cp1 = fmt;
6110Sstevel@tonic-gate fmt = A_END(buf);
6120Sstevel@tonic-gate *--fmt = '\0';
6130Sstevel@tonic-gate do {
6140Sstevel@tonic-gate if (fmt > buf)
6150Sstevel@tonic-gate *--fmt = hex_val[uval % base];
6160Sstevel@tonic-gate if (digits && --digits == 0)
6170Sstevel@tonic-gate break;
6180Sstevel@tonic-gate } while (uval /= base);
6190Sstevel@tonic-gate if (zero_filled) {
6200Sstevel@tonic-gate while (digits > 0 && fmt > buf) {
6210Sstevel@tonic-gate *--fmt = '0';
6220Sstevel@tonic-gate digits--;
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate while (*fmt)
6260Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++);
6270Sstevel@tonic-gate fmt = cp1;
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate return (count);
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate /* PRINTFLIKE2 */
6330Sstevel@tonic-gate int
mi_mpprintf(MBLKP mp,char * fmt,...)6340Sstevel@tonic-gate mi_mpprintf(MBLKP mp, char *fmt, ...)
6350Sstevel@tonic-gate {
6360Sstevel@tonic-gate va_list ap;
6370Sstevel@tonic-gate int count = -1;
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate va_start(ap, fmt);
6400Sstevel@tonic-gate if (mp) {
6410Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc,
6420Sstevel@tonic-gate (char *)mp);
6430Sstevel@tonic-gate if (count != -1)
6440Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0');
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate va_end(ap);
6470Sstevel@tonic-gate return (count);
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /* PRINTFLIKE2 */
6510Sstevel@tonic-gate int
mi_mpprintf_nr(MBLKP mp,char * fmt,...)6520Sstevel@tonic-gate mi_mpprintf_nr(MBLKP mp, char *fmt, ...)
6530Sstevel@tonic-gate {
6540Sstevel@tonic-gate va_list ap;
6550Sstevel@tonic-gate int count = -1;
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate va_start(ap, fmt);
6580Sstevel@tonic-gate if (mp) {
6590Sstevel@tonic-gate (void) adjmsg(mp, -1);
6600Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc,
6610Sstevel@tonic-gate (char *)mp);
6620Sstevel@tonic-gate if (count != -1)
6630Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0');
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate va_end(ap);
6660Sstevel@tonic-gate return (count);
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate int
mi_mpprintf_putc(char * cookie,int ch)6700Sstevel@tonic-gate mi_mpprintf_putc(char *cookie, int ch)
6710Sstevel@tonic-gate {
6720Sstevel@tonic-gate MBLKP mp = (MBLKP)cookie;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate while (mp->b_cont)
6750Sstevel@tonic-gate mp = mp->b_cont;
6760Sstevel@tonic-gate if (mp->b_wptr >= mp->b_datap->db_lim) {
6770Sstevel@tonic-gate mp->b_cont = allocb(1024, BPRI_HI);
6780Sstevel@tonic-gate mp = mp->b_cont;
6790Sstevel@tonic-gate if (!mp)
6800Sstevel@tonic-gate return (0);
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate *mp->b_wptr++ = (unsigned char)ch;
6830Sstevel@tonic-gate return (1);
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate IDP
mi_first_ptr(void ** mi_headp)6870Sstevel@tonic-gate mi_first_ptr(void **mi_headp)
6880Sstevel@tonic-gate {
6890Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
6900Sstevel@tonic-gate MI_OP mi_op;
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next;
6930Sstevel@tonic-gate if (mi_op && mi_op != &mi_head->mh_o)
6940Sstevel@tonic-gate return ((IDP)&mi_op[1]);
6950Sstevel@tonic-gate return (NULL);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate /*
6990Sstevel@tonic-gate * Clients can choose to have both module instances and device instances
7000Sstevel@tonic-gate * in the same list. Return the first device instance in the list.
7010Sstevel@tonic-gate */
7020Sstevel@tonic-gate IDP
mi_first_dev_ptr(void ** mi_headp)7030Sstevel@tonic-gate mi_first_dev_ptr(void **mi_headp)
7040Sstevel@tonic-gate {
7050Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
7060Sstevel@tonic-gate MI_OP mi_op;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next;
7090Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) {
7100Sstevel@tonic-gate if (mi_op->mi_o_isdev)
7110Sstevel@tonic-gate return ((IDP)&mi_op[1]);
7120Sstevel@tonic-gate mi_op = mi_op->mi_o_next;
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate return (NULL);
7150Sstevel@tonic-gate }
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate IDP
mi_next_ptr(void ** mi_headp,IDP ptr)7180Sstevel@tonic-gate mi_next_ptr(void **mi_headp, IDP ptr)
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
7210Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1;
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate if ((mi_op = mi_op->mi_o_next) != NULL && mi_op != &mi_head->mh_o)
7240Sstevel@tonic-gate return ((IDP)&mi_op[1]);
7250Sstevel@tonic-gate return (NULL);
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate /*
7290Sstevel@tonic-gate * Clients can choose to have both module instances and device instances
7300Sstevel@tonic-gate * in the same list. Return the next device instance in the list.
7310Sstevel@tonic-gate */
7320Sstevel@tonic-gate IDP
mi_next_dev_ptr(void ** mi_headp,IDP ptr)7330Sstevel@tonic-gate mi_next_dev_ptr(void **mi_headp, IDP ptr)
7340Sstevel@tonic-gate {
7350Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
7360Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1;
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate mi_op = mi_op->mi_o_next;
7390Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) {
7400Sstevel@tonic-gate if (mi_op->mi_o_isdev)
7410Sstevel@tonic-gate return ((IDP)&mi_op[1]);
7420Sstevel@tonic-gate mi_op = mi_op->mi_o_next;
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate return (NULL);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate /*
7480Sstevel@tonic-gate * Self clone the device
7490Sstevel@tonic-gate * XXX - should we still support clone device
7500Sstevel@tonic-gate */
7510Sstevel@tonic-gate /* ARGSUSED4 */
7520Sstevel@tonic-gate int
mi_open_comm(void ** mi_headp,size_t size,queue_t * q,dev_t * devp,int flag,int sflag,cred_t * credp)7530Sstevel@tonic-gate mi_open_comm(void **mi_headp, size_t size, queue_t *q, dev_t *devp,
7540Sstevel@tonic-gate int flag, int sflag, cred_t *credp)
7550Sstevel@tonic-gate {
7560Sstevel@tonic-gate int error;
7570Sstevel@tonic-gate IDP ptr;
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate if (q->q_ptr != NULL)
7600Sstevel@tonic-gate return (0);
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate ptr = mi_open_alloc_sleep(size);
7630Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = ptr;
7640Sstevel@tonic-gate error = mi_open_link(mi_headp, ptr, devp, flag, sflag, credp);
7650Sstevel@tonic-gate if (error != 0) {
7660Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL;
7670Sstevel@tonic-gate mi_close_free(ptr);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate return (error);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate IDP
mi_open_alloc_sleep(size_t size)7730Sstevel@tonic-gate mi_open_alloc_sleep(size_t size)
7740Sstevel@tonic-gate {
7750Sstevel@tonic-gate MI_OP mi_o;
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O)))
7780Sstevel@tonic-gate return (NULL);
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate mi_o = (MI_OP)mi_zalloc_sleep(size + sizeof (MI_O));
7810Sstevel@tonic-gate mi_o++;
7820Sstevel@tonic-gate return ((IDP)mi_o);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate IDP
mi_open_alloc(size_t size)7860Sstevel@tonic-gate mi_open_alloc(size_t size)
7870Sstevel@tonic-gate {
7880Sstevel@tonic-gate MI_OP mi_o;
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O)))
7910Sstevel@tonic-gate return (NULL);
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate if ((mi_o = (MI_OP)mi_zalloc(size + sizeof (MI_O))) == NULL)
7940Sstevel@tonic-gate return (NULL);
7950Sstevel@tonic-gate mi_o++;
7960Sstevel@tonic-gate return ((IDP)mi_o);
7970Sstevel@tonic-gate }
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /*
8000Sstevel@tonic-gate * MODOPEN means just link in without respect of mi_o_dev.
8010Sstevel@tonic-gate * A NULL devp can be used to create a detached instance
8020Sstevel@tonic-gate * Otherwise self-clone the device.
8030Sstevel@tonic-gate */
8040Sstevel@tonic-gate /* ARGSUSED3 */
8050Sstevel@tonic-gate int
mi_open_link(void ** mi_headp,IDP ptr,dev_t * devp,int flag,int sflag,cred_t * credp)8060Sstevel@tonic-gate mi_open_link(void **mi_headp, IDP ptr, dev_t *devp, int flag, int sflag,
8070Sstevel@tonic-gate cred_t *credp)
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp;
8100Sstevel@tonic-gate MI_OP insert;
8110Sstevel@tonic-gate MI_OP mi_o;
8120Sstevel@tonic-gate dev_t dev;
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate if (mi_head == NULL) {
8150Sstevel@tonic-gate char arena_name[50];
8160Sstevel@tonic-gate char *head_name;
8170Sstevel@tonic-gate ulong_t offset;
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate head_name = kobj_getsymname((uintptr_t)mi_headp, &offset);
8203448Sdh155122 if (head_name != NULL && offset == 0) {
8210Sstevel@tonic-gate (void) sprintf(arena_name, "%s_", head_name);
8223448Sdh155122 } else {
8233448Sdh155122 (void) sprintf(arena_name, "Hex0x%p_",
8243448Sdh155122 (void *)mi_headp);
8253448Sdh155122 }
8260Sstevel@tonic-gate (void) sprintf(strchr(arena_name, '_') + 1, "minor");
8270Sstevel@tonic-gate mi_head = (mi_head_t *)mi_zalloc_sleep(sizeof (mi_head_t));
8280Sstevel@tonic-gate *mi_headp = (void *)mi_head;
8290Sstevel@tonic-gate /* Setup doubly linked list */
8300Sstevel@tonic-gate mi_head->mh_o.mi_o_next = &mi_head->mh_o;
8310Sstevel@tonic-gate mi_head->mh_o.mi_o_prev = &mi_head->mh_o;
8320Sstevel@tonic-gate mi_head->mh_o.mi_o_dev = 0; /* For asserts only */
8330Sstevel@tonic-gate mi_head->mh_arena = (vmem_t *)inet_minor_create(arena_name,
8345815Sgt145670 INET_MIN_DEV, MAXMIN, KM_SLEEP);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate ASSERT(ptr != NULL);
8370Sstevel@tonic-gate mi_o = (MI_OP)ptr;
8380Sstevel@tonic-gate mi_o--;
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate if (sflag == MODOPEN) {
8410Sstevel@tonic-gate devp = NULL;
8420Sstevel@tonic-gate /*
8430Sstevel@tonic-gate * Set device number to MAXMIN + incrementing number.
8440Sstevel@tonic-gate */
8450Sstevel@tonic-gate dev = MAXMIN + ++mi_head->mh_module_dev;
8460Sstevel@tonic-gate /* check for wraparound */
8470Sstevel@tonic-gate if (dev <= MAXMIN) {
8480Sstevel@tonic-gate dev = MAXMIN + 1;
8490Sstevel@tonic-gate mi_head->mh_module_dev = 1;
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate } else if (devp == NULL) {
8520Sstevel@tonic-gate /* Detached open */
8530Sstevel@tonic-gate dev = (dev_t)OPENFAIL;
8540Sstevel@tonic-gate } else if ((dev = inet_minor_alloc(mi_head->mh_arena)) == 0) {
8550Sstevel@tonic-gate return (EBUSY);
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate
8580Sstevel@tonic-gate mi_o->mi_o_dev = dev;
8590Sstevel@tonic-gate insert = (&mi_head->mh_o);
8600Sstevel@tonic-gate mi_o->mi_o_next = insert;
8610Sstevel@tonic-gate insert->mi_o_prev->mi_o_next = mi_o;
8620Sstevel@tonic-gate mi_o->mi_o_prev = insert->mi_o_prev;
8630Sstevel@tonic-gate insert->mi_o_prev = mi_o;
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate if (sflag == MODOPEN)
8660Sstevel@tonic-gate mi_o->mi_o_isdev = B_FALSE;
8670Sstevel@tonic-gate else
8680Sstevel@tonic-gate mi_o->mi_o_isdev = B_TRUE;
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate if (devp)
8710Sstevel@tonic-gate *devp = makedevice(getemajor(*devp), (minor_t)dev);
8720Sstevel@tonic-gate return (0);
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate
8750Sstevel@tonic-gate uint8_t *
mi_offset_param(mblk_t * mp,size_t offset,size_t len)8760Sstevel@tonic-gate mi_offset_param(mblk_t *mp, size_t offset, size_t len)
8770Sstevel@tonic-gate {
8780Sstevel@tonic-gate size_t msg_len;
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate if (!mp)
8810Sstevel@tonic-gate return (NULL);
8820Sstevel@tonic-gate msg_len = mp->b_wptr - mp->b_rptr;
8830Sstevel@tonic-gate if (msg_len == 0 || offset > msg_len || len > msg_len ||
8840Sstevel@tonic-gate (offset + len) > msg_len || len == 0)
8850Sstevel@tonic-gate return (NULL);
8860Sstevel@tonic-gate return (&mp->b_rptr[offset]);
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate uint8_t *
mi_offset_paramc(mblk_t * mp,size_t offset,size_t len)8900Sstevel@tonic-gate mi_offset_paramc(mblk_t *mp, size_t offset, size_t len)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate uint8_t *param;
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate for (; mp; mp = mp->b_cont) {
8950Sstevel@tonic-gate int type = mp->b_datap->db_type;
8960Sstevel@tonic-gate if (datamsg(type)) {
8970Sstevel@tonic-gate if (param = mi_offset_param(mp, offset, len))
8980Sstevel@tonic-gate return (param);
8990Sstevel@tonic-gate if (offset < mp->b_wptr - mp->b_rptr)
9000Sstevel@tonic-gate break;
9010Sstevel@tonic-gate offset -= mp->b_wptr - mp->b_rptr;
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate }
9040Sstevel@tonic-gate return (NULL);
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate int
mi_sprintf(char * buf,char * fmt,...)9080Sstevel@tonic-gate mi_sprintf(char *buf, char *fmt, ...)
9090Sstevel@tonic-gate {
9100Sstevel@tonic-gate va_list ap;
9110Sstevel@tonic-gate int count = -1;
9120Sstevel@tonic-gate va_start(ap, fmt);
9130Sstevel@tonic-gate if (buf) {
9140Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_sprintf_putc,
9150Sstevel@tonic-gate (char *)&buf);
9160Sstevel@tonic-gate if (count != -1)
9170Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&buf, '\0');
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate va_end(ap);
9200Sstevel@tonic-gate return (count);
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate /* Used to count without writing data */
9240Sstevel@tonic-gate /* ARGSUSED1 */
9250Sstevel@tonic-gate static int
mi_sprintf_noop(char * cookie,int ch)9260Sstevel@tonic-gate mi_sprintf_noop(char *cookie, int ch)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate char **cpp = (char **)cookie;
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate (*cpp)++;
9310Sstevel@tonic-gate return (1);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate int
mi_sprintf_putc(char * cookie,int ch)9350Sstevel@tonic-gate mi_sprintf_putc(char *cookie, int ch)
9360Sstevel@tonic-gate {
9370Sstevel@tonic-gate char **cpp = (char **)cookie;
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate **cpp = (char)ch;
9400Sstevel@tonic-gate (*cpp)++;
9410Sstevel@tonic-gate return (1);
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate int
mi_strcmp(const char * cp1,const char * cp2)9450Sstevel@tonic-gate mi_strcmp(const char *cp1, const char *cp2)
9460Sstevel@tonic-gate {
9470Sstevel@tonic-gate while (*cp1++ == *cp2++) {
9480Sstevel@tonic-gate if (!cp2[-1])
9490Sstevel@tonic-gate return (0);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate return ((uint_t)cp2[-1] & 0xFF) - ((uint_t)cp1[-1] & 0xFF);
9520Sstevel@tonic-gate }
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate size_t
mi_strlen(const char * str)9550Sstevel@tonic-gate mi_strlen(const char *str)
9560Sstevel@tonic-gate {
9570Sstevel@tonic-gate const char *cp = str;
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate while (*cp != '\0')
9600Sstevel@tonic-gate cp++;
9610Sstevel@tonic-gate return ((int)(cp - str));
9620Sstevel@tonic-gate }
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate int
mi_strlog(queue_t * q,char level,ushort_t flags,char * fmt,...)9650Sstevel@tonic-gate mi_strlog(queue_t *q, char level, ushort_t flags, char *fmt, ...)
9660Sstevel@tonic-gate {
9670Sstevel@tonic-gate va_list ap;
9680Sstevel@tonic-gate char buf[200];
9690Sstevel@tonic-gate char *alloc_buf = buf;
9700Sstevel@tonic-gate int count = -1;
9710Sstevel@tonic-gate char *cp;
9720Sstevel@tonic-gate short mid;
9730Sstevel@tonic-gate int ret;
9740Sstevel@tonic-gate short sid;
9750Sstevel@tonic-gate
9760Sstevel@tonic-gate sid = 0;
9770Sstevel@tonic-gate mid = 0;
9780Sstevel@tonic-gate if (q != NULL) {
9790Sstevel@tonic-gate mid = q->q_qinfo->qi_minfo->mi_idnum;
9800Sstevel@tonic-gate }
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate /* Find out how many bytes we need and allocate if necesary */
9830Sstevel@tonic-gate va_start(ap, fmt);
9840Sstevel@tonic-gate cp = buf;
9850Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_noop, (char *)&cp);
9860Sstevel@tonic-gate if (count > sizeof (buf) &&
9870Sstevel@tonic-gate !(alloc_buf = mi_alloc((uint_t)count + 2, BPRI_MED))) {
9880Sstevel@tonic-gate va_end(ap);
9890Sstevel@tonic-gate return (-1);
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate va_end(ap);
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate va_start(ap, fmt);
9940Sstevel@tonic-gate cp = alloc_buf;
9950Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_putc, (char *)&cp);
9960Sstevel@tonic-gate if (count != -1)
9970Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&cp, '\0');
9980Sstevel@tonic-gate else
9990Sstevel@tonic-gate alloc_buf[0] = '\0';
10000Sstevel@tonic-gate va_end(ap);
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate ret = strlog(mid, sid, level, flags, alloc_buf);
10030Sstevel@tonic-gate if (alloc_buf != buf)
10040Sstevel@tonic-gate mi_free(alloc_buf);
10050Sstevel@tonic-gate return (ret);
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate long
mi_strtol(const char * str,char ** ptr,int base)10090Sstevel@tonic-gate mi_strtol(const char *str, char **ptr, int base)
10100Sstevel@tonic-gate {
10110Sstevel@tonic-gate const char *cp;
10120Sstevel@tonic-gate int digits;
10130Sstevel@tonic-gate long value;
10140Sstevel@tonic-gate boolean_t is_negative;
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate cp = str;
10170Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t' || *cp == '\n')
10180Sstevel@tonic-gate cp++;
10190Sstevel@tonic-gate is_negative = (*cp == '-');
10200Sstevel@tonic-gate if (is_negative)
10210Sstevel@tonic-gate cp++;
10220Sstevel@tonic-gate if (base == 0) {
10230Sstevel@tonic-gate base = 10;
10240Sstevel@tonic-gate if (*cp == '0') {
10250Sstevel@tonic-gate base = 8;
10260Sstevel@tonic-gate cp++;
10270Sstevel@tonic-gate if (*cp == 'x' || *cp == 'X') {
10280Sstevel@tonic-gate base = 16;
10290Sstevel@tonic-gate cp++;
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate value = 0;
10340Sstevel@tonic-gate for (; *cp != '\0'; cp++) {
10350Sstevel@tonic-gate if (*cp >= '0' && *cp <= '9')
10360Sstevel@tonic-gate digits = *cp - '0';
10370Sstevel@tonic-gate else if (*cp >= 'a' && *cp <= 'f')
10380Sstevel@tonic-gate digits = *cp - 'a' + 10;
10390Sstevel@tonic-gate else if (*cp >= 'A' && *cp <= 'F')
10400Sstevel@tonic-gate digits = *cp - 'A' + 10;
10410Sstevel@tonic-gate else
10420Sstevel@tonic-gate break;
10430Sstevel@tonic-gate if (digits >= base)
10440Sstevel@tonic-gate break;
10450Sstevel@tonic-gate value = (value * base) + digits;
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate /* Note: we cast away const here deliberately */
10480Sstevel@tonic-gate if (ptr != NULL)
10490Sstevel@tonic-gate *ptr = (char *)cp;
10500Sstevel@tonic-gate if (is_negative)
10510Sstevel@tonic-gate value = -value;
10520Sstevel@tonic-gate return (value);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate /*
10560Sstevel@tonic-gate * mi_timer mechanism.
10570Sstevel@tonic-gate *
10580Sstevel@tonic-gate * Each timer is represented by a timer mblk and a (streams) queue. When the
10590Sstevel@tonic-gate * timer fires the timer mblk will be put on the associated streams queue
10600Sstevel@tonic-gate * so that the streams module can process the timer even in its service
10610Sstevel@tonic-gate * procedure.
10620Sstevel@tonic-gate *
10630Sstevel@tonic-gate * The interface consists of 4 entry points:
10640Sstevel@tonic-gate * mi_timer_alloc - create a timer mblk
10650Sstevel@tonic-gate * mi_timer_free - free a timer mblk
10660Sstevel@tonic-gate * mi_timer - start, restart, stop, or move the
10670Sstevel@tonic-gate * timer to a different queue
10680Sstevel@tonic-gate * mi_timer_valid - called by streams module to verify that
10690Sstevel@tonic-gate * the timer did indeed fire.
10700Sstevel@tonic-gate */
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate /*
10760Sstevel@tonic-gate * Start, restart, stop, or move the timer to a new queue.
10770Sstevel@tonic-gate * If "tim" is -2 the timer is moved to a different queue.
10780Sstevel@tonic-gate * If "tim" is -1 the timer is stopped.
10790Sstevel@tonic-gate * Otherwise, the timer is stopped if it is already running, and
10800Sstevel@tonic-gate * set to fire tim milliseconds from now.
10810Sstevel@tonic-gate */
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate void
mi_timer(queue_t * q,MBLKP mp,clock_t tim)10840Sstevel@tonic-gate mi_timer(queue_t *q, MBLKP mp, clock_t tim)
10850Sstevel@tonic-gate {
10860Sstevel@tonic-gate MTBP mtb;
10870Sstevel@tonic-gate int state;
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate ASSERT(tim >= -2);
10900Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB))
10910Sstevel@tonic-gate return;
10920Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
10930Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG);
10940Sstevel@tonic-gate if (tim >= 0) {
10950Sstevel@tonic-gate mtb->mtb_q = q;
10960Sstevel@tonic-gate state = mtb->mtb_state;
10970Sstevel@tonic-gate tim = MSEC_TO_TICK(tim);
10980Sstevel@tonic-gate if (state == TB_RUNNING) {
10990Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) {
11000Sstevel@tonic-gate /* Message has already been putq */
11010Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
11020Sstevel@tonic-gate mp->b_prev || mp->b_next);
11030Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED;
11040Sstevel@tonic-gate mtb->mtb_time_left = tim;
11050Sstevel@tonic-gate /* mi_timer_valid will start timer */
11060Sstevel@tonic-gate return;
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate } else if (state != TB_IDLE) {
11090Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED);
11100Sstevel@tonic-gate if (state == TB_CANCELLED) {
11110Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
11120Sstevel@tonic-gate mp->b_prev || mp->b_next);
11130Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED;
11140Sstevel@tonic-gate mtb->mtb_time_left = tim;
11150Sstevel@tonic-gate /* mi_timer_valid will start timer */
11160Sstevel@tonic-gate return;
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate if (state == TB_RESCHED) {
11190Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
11200Sstevel@tonic-gate mp->b_prev || mp->b_next);
11210Sstevel@tonic-gate mtb->mtb_time_left = tim;
11220Sstevel@tonic-gate /* mi_timer_valid will start timer */
11230Sstevel@tonic-gate return;
11240Sstevel@tonic-gate }
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING;
11270Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim);
11280Sstevel@tonic-gate return;
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate switch (tim) {
11310Sstevel@tonic-gate case -1:
11320Sstevel@tonic-gate mi_timer_stop(mp);
11330Sstevel@tonic-gate break;
11340Sstevel@tonic-gate case -2:
11350Sstevel@tonic-gate mi_timer_move(q, mp);
11360Sstevel@tonic-gate break;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate }
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate /*
11410Sstevel@tonic-gate * Allocate an M_PCSIG timer message. The space between db_base and
11420Sstevel@tonic-gate * b_rptr is used by the mi_timer mechanism, and after b_rptr there are
11430Sstevel@tonic-gate * "size" bytes that the caller can use for its own purposes.
11440Sstevel@tonic-gate *
11450Sstevel@tonic-gate * Note that db_type has to be a priority message since otherwise
11460Sstevel@tonic-gate * the putq will not cause the service procedure to run when
11470Sstevel@tonic-gate * there is flow control.
11480Sstevel@tonic-gate */
11490Sstevel@tonic-gate MBLKP
mi_timer_alloc(size_t size)11500Sstevel@tonic-gate mi_timer_alloc(size_t size)
11510Sstevel@tonic-gate {
11520Sstevel@tonic-gate MBLKP mp;
11530Sstevel@tonic-gate MTBP mtb;
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate if ((mp = allocb(size + sizeof (MTB), BPRI_HI)) != NULL) {
11560Sstevel@tonic-gate mp->b_datap->db_type = M_PCSIG;
11570Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
11580Sstevel@tonic-gate mp->b_rptr = (uchar_t *)&mtb[1];
11590Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + size;
11600Sstevel@tonic-gate mtb->mtb_state = TB_IDLE;
11610Sstevel@tonic-gate mtb->mtb_mp = mp;
11620Sstevel@tonic-gate mtb->mtb_q = NULL;
11630Sstevel@tonic-gate return (mp);
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate return (NULL);
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate * timeout() callback function.
11700Sstevel@tonic-gate * Put the message on the current queue.
11710Sstevel@tonic-gate * If the timer is stopped or moved to a different queue after
11720Sstevel@tonic-gate * it has fired then mi_timer() and mi_timer_valid() will clean
11730Sstevel@tonic-gate * things up.
11740Sstevel@tonic-gate */
11750Sstevel@tonic-gate static int
mi_timer_fire(MTBP mtb)11760Sstevel@tonic-gate mi_timer_fire(MTBP mtb)
11770Sstevel@tonic-gate {
11780Sstevel@tonic-gate ASSERT(mtb == (MTBP)mtb->mtb_mp->b_datap->db_base);
11790Sstevel@tonic-gate ASSERT(mtb->mtb_mp->b_datap->db_type == M_PCSIG);
11800Sstevel@tonic-gate return (putq(mtb->mtb_q, mtb->mtb_mp));
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate /*
11840Sstevel@tonic-gate * Logically free a timer mblk (that might have a pending timeout().)
11850Sstevel@tonic-gate * If the timer has fired and the mblk has been put on the queue then
11860Sstevel@tonic-gate * mi_timer_valid will free the mblk.
11870Sstevel@tonic-gate */
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate void
mi_timer_free(MBLKP mp)11900Sstevel@tonic-gate mi_timer_free(MBLKP mp)
11910Sstevel@tonic-gate {
11920Sstevel@tonic-gate MTBP mtb;
11930Sstevel@tonic-gate int state;
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB))
11960Sstevel@tonic-gate return;
11970Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
11980Sstevel@tonic-gate state = mtb->mtb_state;
11990Sstevel@tonic-gate if (state == TB_RUNNING) {
12000Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) {
12010Sstevel@tonic-gate /* Message has already been putq */
12020Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12030Sstevel@tonic-gate mp->b_prev || mp->b_next);
12040Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED;
12050Sstevel@tonic-gate /* mi_timer_valid will free the mblk */
12060Sstevel@tonic-gate return;
12070Sstevel@tonic-gate }
12080Sstevel@tonic-gate } else if (state != TB_IDLE) {
12090Sstevel@tonic-gate /* Message has already been putq */
12100Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12110Sstevel@tonic-gate mp->b_prev || mp->b_next);
12120Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED);
12130Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED;
12140Sstevel@tonic-gate /* mi_timer_valid will free the mblk */
12150Sstevel@tonic-gate return;
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate ASSERT(mtb->mtb_q == NULL || mtb->mtb_q->q_first != mp);
12180Sstevel@tonic-gate freemsg(mp);
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate /*
12220Sstevel@tonic-gate * Called from mi_timer(,,-2)
12230Sstevel@tonic-gate */
12240Sstevel@tonic-gate void
mi_timer_move(queue_t * q,MBLKP mp)12250Sstevel@tonic-gate mi_timer_move(queue_t *q, MBLKP mp)
12260Sstevel@tonic-gate {
12270Sstevel@tonic-gate MTBP mtb;
12280Sstevel@tonic-gate clock_t tim;
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB))
12310Sstevel@tonic-gate return;
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
12340Sstevel@tonic-gate /*
12350Sstevel@tonic-gate * Need to untimeout and restart to make
12360Sstevel@tonic-gate * sure that the mblk is not about to be putq on the old queue
12370Sstevel@tonic-gate * by mi_timer_fire.
12380Sstevel@tonic-gate */
12390Sstevel@tonic-gate if (mtb->mtb_state == TB_RUNNING) {
12400Sstevel@tonic-gate if ((tim = untimeout(mtb->mtb_tid)) < 0) {
12410Sstevel@tonic-gate /*
12420Sstevel@tonic-gate * Message has already been putq. Move from old queue
12430Sstevel@tonic-gate * to new queue.
12440Sstevel@tonic-gate */
12450Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12460Sstevel@tonic-gate mp->b_prev || mp->b_next);
12470Sstevel@tonic-gate rmvq(mtb->mtb_q, mp);
12480Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp &&
12490Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL);
12500Sstevel@tonic-gate mtb->mtb_q = q;
12510Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp);
12520Sstevel@tonic-gate return;
12530Sstevel@tonic-gate }
12540Sstevel@tonic-gate mtb->mtb_q = q;
12550Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING;
12560Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim);
12570Sstevel@tonic-gate } else if (mtb->mtb_state != TB_IDLE) {
12580Sstevel@tonic-gate ASSERT(mtb->mtb_state != TB_TO_BE_FREED);
12590Sstevel@tonic-gate /*
12600Sstevel@tonic-gate * Message is already sitting on queue. Move to new queue.
12610Sstevel@tonic-gate */
12620Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12630Sstevel@tonic-gate mp->b_prev || mp->b_next);
12640Sstevel@tonic-gate rmvq(mtb->mtb_q, mp);
12650Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp &&
12660Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL);
12670Sstevel@tonic-gate mtb->mtb_q = q;
12680Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp);
12690Sstevel@tonic-gate } else
12700Sstevel@tonic-gate mtb->mtb_q = q;
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate * Called from mi_timer(,,-1)
12750Sstevel@tonic-gate */
12760Sstevel@tonic-gate void
mi_timer_stop(MBLKP mp)12770Sstevel@tonic-gate mi_timer_stop(MBLKP mp)
12780Sstevel@tonic-gate {
12790Sstevel@tonic-gate MTBP mtb;
12800Sstevel@tonic-gate int state;
12810Sstevel@tonic-gate
12820Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB))
12830Sstevel@tonic-gate return;
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
12860Sstevel@tonic-gate state = mtb->mtb_state;
12870Sstevel@tonic-gate if (state == TB_RUNNING) {
12880Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) {
12890Sstevel@tonic-gate /* Message has already been putq */
12900Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12910Sstevel@tonic-gate mp->b_prev || mp->b_next);
12920Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED;
12930Sstevel@tonic-gate } else {
12940Sstevel@tonic-gate mtb->mtb_state = TB_IDLE;
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate } else if (state == TB_RESCHED) {
12970Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp ||
12980Sstevel@tonic-gate mp->b_prev || mp->b_next);
12990Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate }
13020Sstevel@tonic-gate
13030Sstevel@tonic-gate /*
13040Sstevel@tonic-gate * The user of the mi_timer mechanism is required to call mi_timer_valid() for
13050Sstevel@tonic-gate * each M_PCSIG message processed in the service procedures.
13060Sstevel@tonic-gate * mi_timer_valid will return "true" if the timer actually did fire.
13070Sstevel@tonic-gate */
13080Sstevel@tonic-gate
13090Sstevel@tonic-gate boolean_t
mi_timer_valid(MBLKP mp)13100Sstevel@tonic-gate mi_timer_valid(MBLKP mp)
13110Sstevel@tonic-gate {
13120Sstevel@tonic-gate MTBP mtb;
13130Sstevel@tonic-gate int state;
13140Sstevel@tonic-gate
13150Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB) ||
13160Sstevel@tonic-gate mp->b_datap->db_type != M_PCSIG)
13170Sstevel@tonic-gate return (B_FALSE);
13180Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base;
13190Sstevel@tonic-gate state = mtb->mtb_state;
13200Sstevel@tonic-gate if (state != TB_RUNNING) {
13210Sstevel@tonic-gate ASSERT(state != TB_IDLE);
13220Sstevel@tonic-gate if (state == TB_TO_BE_FREED) {
13230Sstevel@tonic-gate /*
13240Sstevel@tonic-gate * mi_timer_free was called after the message
13250Sstevel@tonic-gate * was putq'ed.
13260Sstevel@tonic-gate */
13270Sstevel@tonic-gate freemsg(mp);
13280Sstevel@tonic-gate return (B_FALSE);
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate if (state == TB_CANCELLED) {
13310Sstevel@tonic-gate /* The timer was stopped after the mblk was putq'ed */
13320Sstevel@tonic-gate mtb->mtb_state = TB_IDLE;
13330Sstevel@tonic-gate return (B_FALSE);
13340Sstevel@tonic-gate }
13350Sstevel@tonic-gate if (state == TB_RESCHED) {
13360Sstevel@tonic-gate /*
13370Sstevel@tonic-gate * The timer was stopped and then restarted after
13380Sstevel@tonic-gate * the mblk was putq'ed.
13390Sstevel@tonic-gate * mtb_time_left contains the number of ticks that
13400Sstevel@tonic-gate * the timer was restarted with.
13410Sstevel@tonic-gate */
13420Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING;
13430Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire,
13440Sstevel@tonic-gate mtb, mtb->mtb_time_left);
13450Sstevel@tonic-gate return (B_FALSE);
13460Sstevel@tonic-gate }
13470Sstevel@tonic-gate }
13480Sstevel@tonic-gate mtb->mtb_state = TB_IDLE;
13490Sstevel@tonic-gate return (B_TRUE);
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate static void
mi_tpi_addr_and_opt(MBLKP mp,char * addr,t_scalar_t addr_length,char * opt,t_scalar_t opt_length)13530Sstevel@tonic-gate mi_tpi_addr_and_opt(MBLKP mp, char *addr, t_scalar_t addr_length,
13540Sstevel@tonic-gate char *opt, t_scalar_t opt_length)
13550Sstevel@tonic-gate {
13560Sstevel@tonic-gate struct T_unitdata_ind *tudi;
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate /*
13590Sstevel@tonic-gate * This code is used more than just for unitdata ind
13600Sstevel@tonic-gate * (also for T_CONN_IND and T_CONN_CON) and
13610Sstevel@tonic-gate * relies on correct functioning on the happy
1362*11042SErik.Nordmark@Sun.COM * coincidence that the address and option buffers
13630Sstevel@tonic-gate * represented by length/offset in all these primitives
13640Sstevel@tonic-gate * are isomorphic in terms of offset from start of data
13650Sstevel@tonic-gate * structure
13660Sstevel@tonic-gate */
13670Sstevel@tonic-gate tudi = (struct T_unitdata_ind *)mp->b_rptr;
13680Sstevel@tonic-gate tudi->SRC_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr);
13690Sstevel@tonic-gate tudi->SRC_length = addr_length;
13700Sstevel@tonic-gate if (addr_length > 0) {
13710Sstevel@tonic-gate bcopy(addr, (char *)mp->b_wptr, addr_length);
13720Sstevel@tonic-gate mp->b_wptr += addr_length;
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate tudi->OPT_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr);
13750Sstevel@tonic-gate tudi->OPT_length = opt_length;
13760Sstevel@tonic-gate if (opt_length > 0) {
13770Sstevel@tonic-gate bcopy(opt, (char *)mp->b_wptr, opt_length);
13780Sstevel@tonic-gate mp->b_wptr += opt_length;
13790Sstevel@tonic-gate }
13800Sstevel@tonic-gate }
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate MBLKP
mi_tpi_conn_con(MBLKP trailer_mp,char * src,t_scalar_t src_length,char * opt,t_scalar_t opt_length)13830Sstevel@tonic-gate mi_tpi_conn_con(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt,
13840Sstevel@tonic-gate t_scalar_t opt_length)
13850Sstevel@tonic-gate {
13860Sstevel@tonic-gate size_t len;
13870Sstevel@tonic-gate MBLKP mp;
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate len = sizeof (struct T_conn_con) + src_length + opt_length;
13900Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_CON)) != NULL) {
13910Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_con)];
13920Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length);
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate return (mp);
13950Sstevel@tonic-gate }
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate MBLKP
mi_tpi_conn_ind(MBLKP trailer_mp,char * src,t_scalar_t src_length,char * opt,t_scalar_t opt_length,t_scalar_t seqnum)13980Sstevel@tonic-gate mi_tpi_conn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt,
13990Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t seqnum)
14000Sstevel@tonic-gate {
14010Sstevel@tonic-gate size_t len;
14020Sstevel@tonic-gate MBLKP mp;
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate len = sizeof (struct T_conn_ind) + src_length + opt_length;
14050Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_IND)) != NULL) {
14060Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_ind)];
14070Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length);
14080Sstevel@tonic-gate ((struct T_conn_ind *)mp->b_rptr)->SEQ_number = seqnum;
14090Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO;
14100Sstevel@tonic-gate }
14110Sstevel@tonic-gate return (mp);
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate MBLKP
mi_tpi_extconn_ind(MBLKP trailer_mp,char * src,t_scalar_t src_length,char * opt,t_scalar_t opt_length,char * dst,t_scalar_t dst_length,t_scalar_t seqnum)14150Sstevel@tonic-gate mi_tpi_extconn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length,
14160Sstevel@tonic-gate char *opt, t_scalar_t opt_length, char *dst, t_scalar_t dst_length,
14170Sstevel@tonic-gate t_scalar_t seqnum)
14180Sstevel@tonic-gate {
14190Sstevel@tonic-gate size_t len;
14200Sstevel@tonic-gate MBLKP mp;
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate len = sizeof (struct T_extconn_ind) + src_length + opt_length +
14230Sstevel@tonic-gate dst_length;
14240Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_EXTCONN_IND)) !=
14250Sstevel@tonic-gate NULL) {
14260Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_extconn_ind)];
14270Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length);
14280Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_length = dst_length;
14290Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_offset =
14305815Sgt145670 (t_scalar_t)(mp->b_wptr - mp->b_rptr);
14310Sstevel@tonic-gate if (dst_length > 0) {
14320Sstevel@tonic-gate bcopy(dst, (char *)mp->b_wptr, dst_length);
14330Sstevel@tonic-gate mp->b_wptr += dst_length;
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->SEQ_number = seqnum;
14360Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO;
14370Sstevel@tonic-gate }
14380Sstevel@tonic-gate return (mp);
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate MBLKP
mi_tpi_discon_ind(MBLKP trailer_mp,t_scalar_t reason,t_scalar_t seqnum)14420Sstevel@tonic-gate mi_tpi_discon_ind(MBLKP trailer_mp, t_scalar_t reason, t_scalar_t seqnum)
14430Sstevel@tonic-gate {
14440Sstevel@tonic-gate MBLKP mp;
14450Sstevel@tonic-gate struct T_discon_ind *tdi;
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp,
14480Sstevel@tonic-gate sizeof (struct T_discon_ind), T_DISCON_IND)) != NULL) {
14490Sstevel@tonic-gate tdi = (struct T_discon_ind *)mp->b_rptr;
14500Sstevel@tonic-gate tdi->DISCON_reason = reason;
14510Sstevel@tonic-gate tdi->SEQ_number = seqnum;
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate return (mp);
14540Sstevel@tonic-gate }
14550Sstevel@tonic-gate
14560Sstevel@tonic-gate /*
14570Sstevel@tonic-gate * Allocate and fill in a TPI err ack packet using the 'mp' passed in
14580Sstevel@tonic-gate * for the 'error_prim' context as well as sacrifice.
14590Sstevel@tonic-gate */
14600Sstevel@tonic-gate MBLKP
mi_tpi_err_ack_alloc(MBLKP mp,t_scalar_t tlierr,int unixerr)14610Sstevel@tonic-gate mi_tpi_err_ack_alloc(MBLKP mp, t_scalar_t tlierr, int unixerr)
14620Sstevel@tonic-gate {
14630Sstevel@tonic-gate struct T_error_ack *teackp;
14640Sstevel@tonic-gate t_scalar_t error_prim;
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate if (!mp)
14670Sstevel@tonic-gate return (NULL);
14680Sstevel@tonic-gate error_prim = ((TPRIMP)mp->b_rptr)->type;
14690Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack),
14700Sstevel@tonic-gate M_PCPROTO, T_ERROR_ACK)) != NULL) {
14710Sstevel@tonic-gate teackp = (struct T_error_ack *)mp->b_rptr;
14720Sstevel@tonic-gate teackp->ERROR_prim = error_prim;
14730Sstevel@tonic-gate teackp->TLI_error = tlierr;
14740Sstevel@tonic-gate teackp->UNIX_error = unixerr;
14750Sstevel@tonic-gate }
14760Sstevel@tonic-gate return (mp);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate MBLKP
mi_tpi_ok_ack_alloc_extra(MBLKP mp,int extra)14800Sstevel@tonic-gate mi_tpi_ok_ack_alloc_extra(MBLKP mp, int extra)
14810Sstevel@tonic-gate {
14820Sstevel@tonic-gate t_scalar_t correct_prim;
14830Sstevel@tonic-gate
14840Sstevel@tonic-gate if (!mp)
14850Sstevel@tonic-gate return (NULL);
14860Sstevel@tonic-gate correct_prim = ((TPRIMP)mp->b_rptr)->type;
14870Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_ok_ack) + extra,
14880Sstevel@tonic-gate M_PCPROTO, T_OK_ACK)) != NULL) {
14890Sstevel@tonic-gate ((struct T_ok_ack *)mp->b_rptr)->CORRECT_prim = correct_prim;
14900Sstevel@tonic-gate mp->b_wptr -= extra;
14910Sstevel@tonic-gate }
14920Sstevel@tonic-gate return (mp);
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate
14950Sstevel@tonic-gate MBLKP
mi_tpi_ok_ack_alloc(MBLKP mp)14960Sstevel@tonic-gate mi_tpi_ok_ack_alloc(MBLKP mp)
14970Sstevel@tonic-gate {
14980Sstevel@tonic-gate return (mi_tpi_ok_ack_alloc_extra(mp, 0));
14990Sstevel@tonic-gate }
15000Sstevel@tonic-gate
15010Sstevel@tonic-gate MBLKP
mi_tpi_ordrel_ind(void)15020Sstevel@tonic-gate mi_tpi_ordrel_ind(void)
15030Sstevel@tonic-gate {
15040Sstevel@tonic-gate MBLKP mp;
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate if ((mp = allocb(sizeof (struct T_ordrel_ind), BPRI_HI)) != NULL) {
15070Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO;
15080Sstevel@tonic-gate ((struct T_ordrel_ind *)mp->b_rptr)->PRIM_type = T_ORDREL_IND;
15090Sstevel@tonic-gate mp->b_wptr += sizeof (struct T_ordrel_ind);
15100Sstevel@tonic-gate }
15110Sstevel@tonic-gate return (mp);
15120Sstevel@tonic-gate }
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate static MBLKP
mi_tpi_trailer_alloc(MBLKP trailer_mp,size_t size,t_scalar_t type)15150Sstevel@tonic-gate mi_tpi_trailer_alloc(MBLKP trailer_mp, size_t size, t_scalar_t type)
15160Sstevel@tonic-gate {
15170Sstevel@tonic-gate MBLKP mp;
15180Sstevel@tonic-gate
15190Sstevel@tonic-gate if ((mp = allocb(size, BPRI_MED)) != NULL) {
15200Sstevel@tonic-gate mp->b_cont = trailer_mp;
15210Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO;
15220Sstevel@tonic-gate ((union T_primitives *)mp->b_rptr)->type = type;
15230Sstevel@tonic-gate mp->b_wptr += size;
15240Sstevel@tonic-gate }
15250Sstevel@tonic-gate return (mp);
15260Sstevel@tonic-gate }
15270Sstevel@tonic-gate
15280Sstevel@tonic-gate MBLKP
mi_tpi_uderror_ind(char * dest,t_scalar_t dest_length,char * opt,t_scalar_t opt_length,t_scalar_t error)15290Sstevel@tonic-gate mi_tpi_uderror_ind(char *dest, t_scalar_t dest_length, char *opt,
15300Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t error)
15310Sstevel@tonic-gate {
15320Sstevel@tonic-gate size_t len;
15330Sstevel@tonic-gate MBLKP mp;
15340Sstevel@tonic-gate struct T_uderror_ind *tudei;
15350Sstevel@tonic-gate
15360Sstevel@tonic-gate len = sizeof (struct T_uderror_ind) + dest_length + opt_length;
15370Sstevel@tonic-gate if ((mp = allocb(len, BPRI_HI)) != NULL) {
15380Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO;
15390Sstevel@tonic-gate tudei = (struct T_uderror_ind *)mp->b_rptr;
15400Sstevel@tonic-gate tudei->PRIM_type = T_UDERROR_IND;
15410Sstevel@tonic-gate tudei->ERROR_type = error;
15420Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_uderror_ind)];
15430Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, dest, dest_length, opt, opt_length);
15440Sstevel@tonic-gate }
15450Sstevel@tonic-gate return (mp);
15460Sstevel@tonic-gate }
15470Sstevel@tonic-gate
15480Sstevel@tonic-gate IDP
mi_zalloc(size_t size)15490Sstevel@tonic-gate mi_zalloc(size_t size)
15500Sstevel@tonic-gate {
15510Sstevel@tonic-gate IDP ptr;
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate if (ptr = mi_alloc(size, BPRI_LO))
15540Sstevel@tonic-gate bzero(ptr, size);
15550Sstevel@tonic-gate return (ptr);
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate IDP
mi_zalloc_sleep(size_t size)15590Sstevel@tonic-gate mi_zalloc_sleep(size_t size)
15600Sstevel@tonic-gate {
15610Sstevel@tonic-gate IDP ptr;
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate if (ptr = mi_alloc_sleep(size, BPRI_LO))
15640Sstevel@tonic-gate bzero(ptr, size);
15650Sstevel@tonic-gate return (ptr);
15660Sstevel@tonic-gate }
1567