1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1990 Mentat Inc. */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate #include <inet/common.h> /* for various inet/mi.h and inet/nd.h needs */ 32*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 36*7c478bd9Sstevel@tonic-gate #include <inet/nd.h> 37*7c478bd9Sstevel@tonic-gate #include <inet/mi.h> 38*7c478bd9Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 39*7c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/timod.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/suntpi.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') 52*7c478bd9Sstevel@tonic-gate #define ISUPPER(ch) ((ch) >= 'A' && (ch) <= 'Z') 53*7c478bd9Sstevel@tonic-gate #define tolower(ch) ('a' + ((ch) - 'A')) 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define MI_IS_TRANSPARENT(mp) (mp->b_cont && \ 56*7c478bd9Sstevel@tonic-gate (mp->b_cont->b_rptr != mp->b_cont->b_wptr)) 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * NOTE: Whenever anything is allocated by mi_alloc or mi_alloc_sleep (below), 60*7c478bd9Sstevel@tonic-gate * the size of the requested allocation is increased by one word. This extra 61*7c478bd9Sstevel@tonic-gate * word is used to store the size of the object being allocated, and is located 62*7c478bd9Sstevel@tonic-gate * at the beginning of the allocated block. The pointer returned to the caller 63*7c478bd9Sstevel@tonic-gate * is a pointer to the *second* word in the newly-allocated block. The IP 64*7c478bd9Sstevel@tonic-gate * module of mdb is aware of this, and will need to be changed if this 65*7c478bd9Sstevel@tonic-gate * allocation strategy is changed. 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate typedef struct stroptions *STROPTP; 69*7c478bd9Sstevel@tonic-gate typedef union T_primitives *TPRIMP; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* Timer block states. */ 72*7c478bd9Sstevel@tonic-gate #define TB_RUNNING 1 73*7c478bd9Sstevel@tonic-gate #define TB_IDLE 2 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * Could not stop/free before putq 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate #define TB_RESCHED 3 /* mtb_time_left contains tick count */ 78*7c478bd9Sstevel@tonic-gate #define TB_CANCELLED 4 79*7c478bd9Sstevel@tonic-gate #define TB_TO_BE_FREED 5 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate typedef struct mtb_s { 82*7c478bd9Sstevel@tonic-gate int mtb_state; 83*7c478bd9Sstevel@tonic-gate timeout_id_t mtb_tid; 84*7c478bd9Sstevel@tonic-gate queue_t *mtb_q; 85*7c478bd9Sstevel@tonic-gate MBLKP mtb_mp; 86*7c478bd9Sstevel@tonic-gate clock_t mtb_time_left; 87*7c478bd9Sstevel@tonic-gate } MTB, *MTBP; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate static int mi_timer_fire(MTBP); 90*7c478bd9Sstevel@tonic-gate static int mi_iprintf(char *, va_list, pfi_t, char *); 91*7c478bd9Sstevel@tonic-gate static void mi_tpi_addr_and_opt(MBLKP, char *, t_scalar_t, char *, t_scalar_t); 92*7c478bd9Sstevel@tonic-gate static MBLKP mi_tpi_trailer_alloc(MBLKP, size_t, t_scalar_t); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 95*7c478bd9Sstevel@tonic-gate void * 96*7c478bd9Sstevel@tonic-gate mi_alloc(size_t size, uint_t pri) 97*7c478bd9Sstevel@tonic-gate { 98*7c478bd9Sstevel@tonic-gate size_t *ptr; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate size += sizeof (size); 101*7c478bd9Sstevel@tonic-gate if (ptr = kmem_alloc(size, KM_NOSLEEP)) { 102*7c478bd9Sstevel@tonic-gate *ptr = size; 103*7c478bd9Sstevel@tonic-gate return (ptr + 1); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate return (NULL); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 109*7c478bd9Sstevel@tonic-gate void * 110*7c478bd9Sstevel@tonic-gate mi_alloc_sleep(size_t size, uint_t pri) 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate size_t *ptr; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate size += sizeof (size); 115*7c478bd9Sstevel@tonic-gate ptr = kmem_alloc(size, KM_SLEEP); 116*7c478bd9Sstevel@tonic-gate *ptr = size; 117*7c478bd9Sstevel@tonic-gate return (ptr + 1); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate int 121*7c478bd9Sstevel@tonic-gate mi_close_comm(void **mi_headp, queue_t *q) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate IDP ptr; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate ptr = q->q_ptr; 126*7c478bd9Sstevel@tonic-gate mi_close_unlink(mi_headp, ptr); 127*7c478bd9Sstevel@tonic-gate mi_close_free(ptr); 128*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 129*7c478bd9Sstevel@tonic-gate return (0); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate void 133*7c478bd9Sstevel@tonic-gate mi_close_unlink(void **mi_headp, IDP ptr) 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 136*7c478bd9Sstevel@tonic-gate MI_OP mi_o; 137*7c478bd9Sstevel@tonic-gate dev_t dev; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 140*7c478bd9Sstevel@tonic-gate if (!mi_o) 141*7c478bd9Sstevel@tonic-gate return; 142*7c478bd9Sstevel@tonic-gate mi_o--; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate if (mi_o->mi_o_next == NULL) { 145*7c478bd9Sstevel@tonic-gate /* Not in list */ 146*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev == NULL); 147*7c478bd9Sstevel@tonic-gate return; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* Free minor number */ 151*7c478bd9Sstevel@tonic-gate dev = mi_o->mi_o_dev; 152*7c478bd9Sstevel@tonic-gate if ((dev != OPENFAIL) && (dev != 0) && (dev <= MAXMIN)) 153*7c478bd9Sstevel@tonic-gate inet_minor_free(mi_head->mh_arena, dev); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* Unlink from list */ 156*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next != NULL); 157*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev != NULL); 158*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next->mi_o_prev == mi_o); 159*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev->mi_o_next == mi_o); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate mi_o->mi_o_next->mi_o_prev = mi_o->mi_o_prev; 162*7c478bd9Sstevel@tonic-gate mi_o->mi_o_prev->mi_o_next = mi_o->mi_o_next; 163*7c478bd9Sstevel@tonic-gate mi_o->mi_o_next = mi_o->mi_o_prev = NULL; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate mi_o->mi_o_dev = (dev_t)OPENFAIL; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* If list now empty free the list head */ 168*7c478bd9Sstevel@tonic-gate if (mi_head->mh_o.mi_o_next == &mi_head->mh_o) { 169*7c478bd9Sstevel@tonic-gate ASSERT(mi_head->mh_o.mi_o_prev == &mi_head->mh_o); 170*7c478bd9Sstevel@tonic-gate if (mi_head->mh_arena != NULL) 171*7c478bd9Sstevel@tonic-gate inet_minor_destroy(mi_head->mh_arena); 172*7c478bd9Sstevel@tonic-gate mi_free((IDP)mi_head); 173*7c478bd9Sstevel@tonic-gate *mi_headp = NULL; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate void 178*7c478bd9Sstevel@tonic-gate mi_close_free(IDP ptr) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate MI_OP mi_o; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 183*7c478bd9Sstevel@tonic-gate if (!mi_o) 184*7c478bd9Sstevel@tonic-gate return; 185*7c478bd9Sstevel@tonic-gate mi_o--; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next == NULL && mi_o->mi_o_prev == NULL); 188*7c478bd9Sstevel@tonic-gate mi_free((IDP)mi_o); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * mi_copyin - takes care of transparent or non-transparent ioctl for the 193*7c478bd9Sstevel@tonic-gate * calling function so that they have to deal with just M_IOCDATA type 194*7c478bd9Sstevel@tonic-gate * and not worry about M_COPYIN. 195*7c478bd9Sstevel@tonic-gate * 196*7c478bd9Sstevel@tonic-gate * mi_copyin checks to see if the ioctl is transparent or non transparent. 197*7c478bd9Sstevel@tonic-gate * In case of a non_transparent ioctl, it packs the data into a M_IOCDATA 198*7c478bd9Sstevel@tonic-gate * message and puts it back onto the current queue for further processing. 199*7c478bd9Sstevel@tonic-gate * In case of transparent ioctl, it sends a M_COPYIN message up to the 200*7c478bd9Sstevel@tonic-gate * streamhead so that a M_IOCDATA with the information comes back down. 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate void 203*7c478bd9Sstevel@tonic-gate mi_copyin(queue_t *q, MBLKP mp, char *uaddr, size_t len) 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 206*7c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr; 207*7c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)mp->b_rptr; 208*7c478bd9Sstevel@tonic-gate int err; 209*7c478bd9Sstevel@tonic-gate MBLKP mp1; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCTL && !uaddr); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* A transparent ioctl. Send a M_COPYIN message to the streamhead. */ 214*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) { 215*7c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 216*7c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 217*7c478bd9Sstevel@tonic-gate cq->cq_private = mp->b_cont; 218*7c478bd9Sstevel@tonic-gate cq->cq_size = len; 219*7c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 220*7c478bd9Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 221*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 222*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 223*7c478bd9Sstevel@tonic-gate qreply(q, mp); 224*7c478bd9Sstevel@tonic-gate return; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate * A non-transparent ioctl. Need to convert into M_IOCDATA message. 229*7c478bd9Sstevel@tonic-gate * 230*7c478bd9Sstevel@tonic-gate * We allocate a 0 byte message block and put its address in 231*7c478bd9Sstevel@tonic-gate * cp_private. It also makes the b_prev field = 1 and b_next 232*7c478bd9Sstevel@tonic-gate * field = MI_COPY_IN for this 0 byte block. This is done to 233*7c478bd9Sstevel@tonic-gate * maintain compatibility with old code in mi_copy_state 234*7c478bd9Sstevel@tonic-gate * (which removes the empty block). 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate err = miocpullup(mp, len); 237*7c478bd9Sstevel@tonic-gate if (err != 0) 238*7c478bd9Sstevel@tonic-gate goto err_ret; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED); 241*7c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 242*7c478bd9Sstevel@tonic-gate err = ENOMEM; 243*7c478bd9Sstevel@tonic-gate goto err_ret; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Temporarily insert mp1 between the M_IOCTL and M_DATA blocks so 248*7c478bd9Sstevel@tonic-gate * that we can use the MI_COPY_COUNT & MI_COPY_DIRECTION macros. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate mp1->b_cont = mp->b_cont; 251*7c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 252*7c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 253*7c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 254*7c478bd9Sstevel@tonic-gate mp->b_cont = mp1->b_cont; 255*7c478bd9Sstevel@tonic-gate mp1->b_cont = NULL; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Leave a pointer to the 0 byte block in cp_private field for 259*7c478bd9Sstevel@tonic-gate * future use by the mi_copy_* routines. 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA; 262*7c478bd9Sstevel@tonic-gate cp->cp_private = mp1; 263*7c478bd9Sstevel@tonic-gate cp->cp_rval = NULL; 264*7c478bd9Sstevel@tonic-gate put(q, mp); 265*7c478bd9Sstevel@tonic-gate return; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate err_ret: 268*7c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 269*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 270*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 271*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 272*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 275*7c478bd9Sstevel@tonic-gate qreply(q, mp); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * Allows transparent IOCTLs to have multiple copyins. This is needed 280*7c478bd9Sstevel@tonic-gate * for some variable-length structures, where the total size is only known 281*7c478bd9Sstevel@tonic-gate * after the first part is copied in. Rather than setting MI_COPY_COUNT to 282*7c478bd9Sstevel@tonic-gate * 1, as in mi_coypin(), it is simply incremented here. This value can 283*7c478bd9Sstevel@tonic-gate * then be checked in the returned IOCBLK. 284*7c478bd9Sstevel@tonic-gate * 285*7c478bd9Sstevel@tonic-gate * As this deals with copyins that follow the initial copyin, the byte 286*7c478bd9Sstevel@tonic-gate * offset into the user buffer from which copying should begin must be 287*7c478bd9Sstevel@tonic-gate * passed in in the offset parameter. 288*7c478bd9Sstevel@tonic-gate * 289*7c478bd9Sstevel@tonic-gate * Unlike mi_coypin(), this function expects to be passed an mblk chain 290*7c478bd9Sstevel@tonic-gate * headed by an M_IOCBLK, as that's the chain that will be in use for 291*7c478bd9Sstevel@tonic-gate * copies after the first one (copies where n != 1). 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate void 294*7c478bd9Sstevel@tonic-gate mi_copyin_n(queue_t *q, MBLKP mp, size_t offset, size_t len) 295*7c478bd9Sstevel@tonic-gate { 296*7c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCDATA); 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp)++; 301*7c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 302*7c478bd9Sstevel@tonic-gate cq->cq_private = mp->b_cont; 303*7c478bd9Sstevel@tonic-gate cq->cq_size = len; 304*7c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 305*7c478bd9Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 306*7c478bd9Sstevel@tonic-gate cq->cq_addr += offset; 307*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 308*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 309*7c478bd9Sstevel@tonic-gate qreply(q, mp); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate void 313*7c478bd9Sstevel@tonic-gate mi_copyout(queue_t *q, MBLKP mp) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 316*7c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)iocp; 317*7c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)cq; 318*7c478bd9Sstevel@tonic-gate MBLKP mp1; 319*7c478bd9Sstevel@tonic-gate MBLKP mp2; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type != M_IOCDATA || !mp->b_cont) { 322*7c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, EPROTO); 323*7c478bd9Sstevel@tonic-gate return; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate /* Check completion of previous copyout operation. */ 326*7c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 327*7c478bd9Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval || !mp1->b_cont) { 328*7c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 329*7c478bd9Sstevel@tonic-gate return; 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate if (!mp1->b_cont->b_cont && !MI_IS_TRANSPARENT(mp)) { 332*7c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 333*7c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 334*7c478bd9Sstevel@tonic-gate mp->b_cont = mp1->b_cont; 335*7c478bd9Sstevel@tonic-gate freeb(mp1); 336*7c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 337*7c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 338*7c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 339*7c478bd9Sstevel@tonic-gate iocp->ioc_count = mp1->b_wptr - mp1->b_rptr; 340*7c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; 341*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 342*7c478bd9Sstevel@tonic-gate qreply(q, mp); 343*7c478bd9Sstevel@tonic-gate return; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if (MI_COPY_DIRECTION(mp) == MI_COPY_IN) { 346*7c478bd9Sstevel@tonic-gate /* Set up for first copyout. */ 347*7c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 348*7c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 349*7c478bd9Sstevel@tonic-gate } else { 350*7c478bd9Sstevel@tonic-gate ++MI_COPY_COUNT(mp); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate cq->cq_private = mp1; 353*7c478bd9Sstevel@tonic-gate /* Find message preceding last. */ 354*7c478bd9Sstevel@tonic-gate for (mp2 = mp1; mp2->b_cont->b_cont; mp2 = mp2->b_cont) 355*7c478bd9Sstevel@tonic-gate ; 356*7c478bd9Sstevel@tonic-gate if (mp2 == mp1) 357*7c478bd9Sstevel@tonic-gate bcopy((char *)mp1->b_rptr, (char *)&cq->cq_addr, 358*7c478bd9Sstevel@tonic-gate sizeof (cq->cq_addr)); 359*7c478bd9Sstevel@tonic-gate else 360*7c478bd9Sstevel@tonic-gate cq->cq_addr = (char *)mp2->b_cont->b_next; 361*7c478bd9Sstevel@tonic-gate mp1 = mp2->b_cont; 362*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 363*7c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 364*7c478bd9Sstevel@tonic-gate mp2->b_cont = NULL; 365*7c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 366*7c478bd9Sstevel@tonic-gate cq->cq_size = mp1->b_wptr - mp1->b_rptr; 367*7c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 368*7c478bd9Sstevel@tonic-gate qreply(q, mp); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate MBLKP 372*7c478bd9Sstevel@tonic-gate mi_copyout_alloc(queue_t *q, MBLKP mp, char *uaddr, size_t len, 373*7c478bd9Sstevel@tonic-gate boolean_t free_on_error) 374*7c478bd9Sstevel@tonic-gate { 375*7c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 376*7c478bd9Sstevel@tonic-gate MBLKP mp1; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) { 379*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 380*7c478bd9Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED); 381*7c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 382*7c478bd9Sstevel@tonic-gate if (free_on_error) { 383*7c478bd9Sstevel@tonic-gate iocp->ioc_error = ENOMEM; 384*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 385*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 386*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 387*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 388*7c478bd9Sstevel@tonic-gate qreply(q, mp); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate return (NULL); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate mp1->b_cont = mp->b_cont; 393*7c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 0; 396*7c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 397*7c478bd9Sstevel@tonic-gate /* Make sure it looks clean to mi_copyout. */ 398*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA; 399*7c478bd9Sstevel@tonic-gate ((struct copyresp *)iocp)->cp_rval = NULL; 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate mp1 = allocb(len, BPRI_MED); 402*7c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 403*7c478bd9Sstevel@tonic-gate if (free_on_error) 404*7c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM); 405*7c478bd9Sstevel@tonic-gate return (NULL); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate linkb(mp, mp1); 408*7c478bd9Sstevel@tonic-gate mp1->b_next = (MBLKP)uaddr; 409*7c478bd9Sstevel@tonic-gate return (mp1); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate void 413*7c478bd9Sstevel@tonic-gate mi_copy_done(queue_t *q, MBLKP mp, int err) 414*7c478bd9Sstevel@tonic-gate { 415*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 416*7c478bd9Sstevel@tonic-gate MBLKP mp1; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate if (!mp) 419*7c478bd9Sstevel@tonic-gate return; 420*7c478bd9Sstevel@tonic-gate if (!q || (mp->b_wptr - mp->b_rptr) < sizeof (struct iocblk)) { 421*7c478bd9Sstevel@tonic-gate freemsg(mp); 422*7c478bd9Sstevel@tonic-gate return; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 425*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 426*7c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 429*7c478bd9Sstevel@tonic-gate if ((mp1 = mp->b_cont) != NULL) { 430*7c478bd9Sstevel@tonic-gate for (; mp1; mp1 = mp1->b_cont) { 431*7c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 432*7c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 435*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate qreply(q, mp); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate int 441*7c478bd9Sstevel@tonic-gate mi_copy_state(queue_t *q, MBLKP mp, MBLKP *mpp) 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 444*7c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)iocp; 445*7c478bd9Sstevel@tonic-gate MBLKP mp1; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 448*7c478bd9Sstevel@tonic-gate mp->b_cont = cp->cp_private; 449*7c478bd9Sstevel@tonic-gate if (mp1) { 450*7c478bd9Sstevel@tonic-gate if (mp1->b_cont && !pullupmsg(mp1, -1)) { 451*7c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM); 452*7c478bd9Sstevel@tonic-gate return (-1); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate linkb(mp->b_cont, mp1); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval) { 457*7c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 458*7c478bd9Sstevel@tonic-gate return (-1); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate if (mpp && MI_COPY_DIRECTION(mp) == MI_COPY_IN) 461*7c478bd9Sstevel@tonic-gate *mpp = mp1; 462*7c478bd9Sstevel@tonic-gate return (MI_COPY_STATE(mp)); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate void 466*7c478bd9Sstevel@tonic-gate mi_free(void *ptr) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate size_t size; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate if (!ptr) 471*7c478bd9Sstevel@tonic-gate return; 472*7c478bd9Sstevel@tonic-gate if ((size = ((size_t *)ptr)[-1]) <= 0) 473*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "mi_free"); 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate kmem_free((void *) ((size_t *)ptr - 1), size); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate static int 479*7c478bd9Sstevel@tonic-gate mi_iprintf(char *fmt, va_list ap, pfi_t putc_func, char *cookie) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate int base; 482*7c478bd9Sstevel@tonic-gate char buf[(sizeof (long) * 3) + 1]; 483*7c478bd9Sstevel@tonic-gate static char hex_val[] = "0123456789abcdef"; 484*7c478bd9Sstevel@tonic-gate int ch; 485*7c478bd9Sstevel@tonic-gate int count; 486*7c478bd9Sstevel@tonic-gate char *cp1; 487*7c478bd9Sstevel@tonic-gate int digits; 488*7c478bd9Sstevel@tonic-gate char *fcp; 489*7c478bd9Sstevel@tonic-gate boolean_t is_long; 490*7c478bd9Sstevel@tonic-gate ulong_t uval; 491*7c478bd9Sstevel@tonic-gate long val; 492*7c478bd9Sstevel@tonic-gate boolean_t zero_filled; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if (!fmt) 495*7c478bd9Sstevel@tonic-gate return (-1); 496*7c478bd9Sstevel@tonic-gate count = 0; 497*7c478bd9Sstevel@tonic-gate while (*fmt) { 498*7c478bd9Sstevel@tonic-gate if (*fmt != '%' || *++fmt == '%') { 499*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++); 500*7c478bd9Sstevel@tonic-gate continue; 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate if (*fmt == '0') { 503*7c478bd9Sstevel@tonic-gate zero_filled = B_TRUE; 504*7c478bd9Sstevel@tonic-gate fmt++; 505*7c478bd9Sstevel@tonic-gate if (!*fmt) 506*7c478bd9Sstevel@tonic-gate break; 507*7c478bd9Sstevel@tonic-gate } else 508*7c478bd9Sstevel@tonic-gate zero_filled = B_FALSE; 509*7c478bd9Sstevel@tonic-gate base = 0; 510*7c478bd9Sstevel@tonic-gate for (digits = 0; ISDIGIT(*fmt); fmt++) { 511*7c478bd9Sstevel@tonic-gate digits *= 10; 512*7c478bd9Sstevel@tonic-gate digits += (*fmt - '0'); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate if (!*fmt) 515*7c478bd9Sstevel@tonic-gate break; 516*7c478bd9Sstevel@tonic-gate is_long = B_FALSE; 517*7c478bd9Sstevel@tonic-gate if (*fmt == 'l') { 518*7c478bd9Sstevel@tonic-gate is_long = B_TRUE; 519*7c478bd9Sstevel@tonic-gate fmt++; 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate if (!*fmt) 522*7c478bd9Sstevel@tonic-gate break; 523*7c478bd9Sstevel@tonic-gate ch = *fmt++; 524*7c478bd9Sstevel@tonic-gate if (ISUPPER(ch)) { 525*7c478bd9Sstevel@tonic-gate ch = tolower(ch); 526*7c478bd9Sstevel@tonic-gate is_long = B_TRUE; 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate switch (ch) { 529*7c478bd9Sstevel@tonic-gate case 'c': 530*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, va_arg(ap, int *)); 531*7c478bd9Sstevel@tonic-gate continue; 532*7c478bd9Sstevel@tonic-gate case 'd': 533*7c478bd9Sstevel@tonic-gate base = 10; 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate case 'm': /* Print out memory, 2 hex chars per byte */ 536*7c478bd9Sstevel@tonic-gate if (is_long) 537*7c478bd9Sstevel@tonic-gate fcp = va_arg(ap, char *); 538*7c478bd9Sstevel@tonic-gate else { 539*7c478bd9Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL) 540*7c478bd9Sstevel@tonic-gate fcp = (char *)cp1; 541*7c478bd9Sstevel@tonic-gate else 542*7c478bd9Sstevel@tonic-gate fcp = NULL; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate if (!fcp) { 545*7c478bd9Sstevel@tonic-gate for (fcp = (char *)"(NULL)"; *fcp; fcp++) 546*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp); 547*7c478bd9Sstevel@tonic-gate } else { 548*7c478bd9Sstevel@tonic-gate while (digits--) { 549*7c478bd9Sstevel@tonic-gate int u1 = *fcp++ & 0xFF; 550*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, 551*7c478bd9Sstevel@tonic-gate hex_val[(u1>>4)& 0xF]); 552*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, 553*7c478bd9Sstevel@tonic-gate hex_val[u1& 0xF]); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate continue; 557*7c478bd9Sstevel@tonic-gate case 'o': 558*7c478bd9Sstevel@tonic-gate base = 8; 559*7c478bd9Sstevel@tonic-gate break; 560*7c478bd9Sstevel@tonic-gate case 'p': 561*7c478bd9Sstevel@tonic-gate is_long = B_TRUE; 562*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 563*7c478bd9Sstevel@tonic-gate case 'x': 564*7c478bd9Sstevel@tonic-gate base = 16; 565*7c478bd9Sstevel@tonic-gate break; 566*7c478bd9Sstevel@tonic-gate case 's': 567*7c478bd9Sstevel@tonic-gate if (is_long) 568*7c478bd9Sstevel@tonic-gate fcp = va_arg(ap, char *); 569*7c478bd9Sstevel@tonic-gate else { 570*7c478bd9Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL) 571*7c478bd9Sstevel@tonic-gate fcp = (char *)cp1; 572*7c478bd9Sstevel@tonic-gate else 573*7c478bd9Sstevel@tonic-gate fcp = NULL; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate if (!fcp) 576*7c478bd9Sstevel@tonic-gate fcp = (char *)"(NULL)"; 577*7c478bd9Sstevel@tonic-gate while (*fcp) { 578*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp++); 579*7c478bd9Sstevel@tonic-gate if (digits && --digits == 0) 580*7c478bd9Sstevel@tonic-gate break; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate while (digits > 0) { 583*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, ' '); 584*7c478bd9Sstevel@tonic-gate digits--; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate continue; 587*7c478bd9Sstevel@tonic-gate case 'u': 588*7c478bd9Sstevel@tonic-gate base = 10; 589*7c478bd9Sstevel@tonic-gate break; 590*7c478bd9Sstevel@tonic-gate default: 591*7c478bd9Sstevel@tonic-gate return (count); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate if (is_long) 594*7c478bd9Sstevel@tonic-gate val = va_arg(ap, long); 595*7c478bd9Sstevel@tonic-gate else 596*7c478bd9Sstevel@tonic-gate val = va_arg(ap, int); 597*7c478bd9Sstevel@tonic-gate if (base == 10 && ch != 'u') { 598*7c478bd9Sstevel@tonic-gate if (val < 0) { 599*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, '-'); 600*7c478bd9Sstevel@tonic-gate val = -val; 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate uval = val; 603*7c478bd9Sstevel@tonic-gate } else { 604*7c478bd9Sstevel@tonic-gate if (is_long) 605*7c478bd9Sstevel@tonic-gate uval = val; 606*7c478bd9Sstevel@tonic-gate else 607*7c478bd9Sstevel@tonic-gate uval = (uint_t)val; 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate /* Hand overload/restore the register variable 'fmt' */ 610*7c478bd9Sstevel@tonic-gate cp1 = fmt; 611*7c478bd9Sstevel@tonic-gate fmt = A_END(buf); 612*7c478bd9Sstevel@tonic-gate *--fmt = '\0'; 613*7c478bd9Sstevel@tonic-gate do { 614*7c478bd9Sstevel@tonic-gate if (fmt > buf) 615*7c478bd9Sstevel@tonic-gate *--fmt = hex_val[uval % base]; 616*7c478bd9Sstevel@tonic-gate if (digits && --digits == 0) 617*7c478bd9Sstevel@tonic-gate break; 618*7c478bd9Sstevel@tonic-gate } while (uval /= base); 619*7c478bd9Sstevel@tonic-gate if (zero_filled) { 620*7c478bd9Sstevel@tonic-gate while (digits > 0 && fmt > buf) { 621*7c478bd9Sstevel@tonic-gate *--fmt = '0'; 622*7c478bd9Sstevel@tonic-gate digits--; 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate while (*fmt) 626*7c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++); 627*7c478bd9Sstevel@tonic-gate fmt = cp1; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate return (count); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE2 */ 633*7c478bd9Sstevel@tonic-gate int 634*7c478bd9Sstevel@tonic-gate mi_mpprintf(MBLKP mp, char *fmt, ...) 635*7c478bd9Sstevel@tonic-gate { 636*7c478bd9Sstevel@tonic-gate va_list ap; 637*7c478bd9Sstevel@tonic-gate int count = -1; 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 640*7c478bd9Sstevel@tonic-gate if (mp) { 641*7c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 642*7c478bd9Sstevel@tonic-gate (char *)mp); 643*7c478bd9Sstevel@tonic-gate if (count != -1) 644*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0'); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate va_end(ap); 647*7c478bd9Sstevel@tonic-gate return (count); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE2 */ 651*7c478bd9Sstevel@tonic-gate int 652*7c478bd9Sstevel@tonic-gate mi_mpprintf_nr(MBLKP mp, char *fmt, ...) 653*7c478bd9Sstevel@tonic-gate { 654*7c478bd9Sstevel@tonic-gate va_list ap; 655*7c478bd9Sstevel@tonic-gate int count = -1; 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 658*7c478bd9Sstevel@tonic-gate if (mp) { 659*7c478bd9Sstevel@tonic-gate (void) adjmsg(mp, -1); 660*7c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 661*7c478bd9Sstevel@tonic-gate (char *)mp); 662*7c478bd9Sstevel@tonic-gate if (count != -1) 663*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0'); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate va_end(ap); 666*7c478bd9Sstevel@tonic-gate return (count); 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate int 670*7c478bd9Sstevel@tonic-gate mi_mpprintf_putc(char *cookie, int ch) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate MBLKP mp = (MBLKP)cookie; 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate while (mp->b_cont) 675*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 676*7c478bd9Sstevel@tonic-gate if (mp->b_wptr >= mp->b_datap->db_lim) { 677*7c478bd9Sstevel@tonic-gate mp->b_cont = allocb(1024, BPRI_HI); 678*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 679*7c478bd9Sstevel@tonic-gate if (!mp) 680*7c478bd9Sstevel@tonic-gate return (0); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate *mp->b_wptr++ = (unsigned char)ch; 683*7c478bd9Sstevel@tonic-gate return (1); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate IDP 687*7c478bd9Sstevel@tonic-gate mi_first_ptr(void **mi_headp) 688*7c478bd9Sstevel@tonic-gate { 689*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 690*7c478bd9Sstevel@tonic-gate MI_OP mi_op; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next; 693*7c478bd9Sstevel@tonic-gate if (mi_op && mi_op != &mi_head->mh_o) 694*7c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 695*7c478bd9Sstevel@tonic-gate return (NULL); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate /* 699*7c478bd9Sstevel@tonic-gate * Clients can choose to have both module instances and device instances 700*7c478bd9Sstevel@tonic-gate * in the same list. Return the first device instance in the list. 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate IDP 703*7c478bd9Sstevel@tonic-gate mi_first_dev_ptr(void **mi_headp) 704*7c478bd9Sstevel@tonic-gate { 705*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 706*7c478bd9Sstevel@tonic-gate MI_OP mi_op; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next; 709*7c478bd9Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 710*7c478bd9Sstevel@tonic-gate if (mi_op->mi_o_isdev) 711*7c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 712*7c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate return (NULL); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate IDP 718*7c478bd9Sstevel@tonic-gate mi_next_ptr(void **mi_headp, IDP ptr) 719*7c478bd9Sstevel@tonic-gate { 720*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 721*7c478bd9Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate if ((mi_op = mi_op->mi_o_next) != NULL && mi_op != &mi_head->mh_o) 724*7c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 725*7c478bd9Sstevel@tonic-gate return (NULL); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* 729*7c478bd9Sstevel@tonic-gate * Clients can choose to have both module instances and device instances 730*7c478bd9Sstevel@tonic-gate * in the same list. Return the next device instance in the list. 731*7c478bd9Sstevel@tonic-gate */ 732*7c478bd9Sstevel@tonic-gate IDP 733*7c478bd9Sstevel@tonic-gate mi_next_dev_ptr(void **mi_headp, IDP ptr) 734*7c478bd9Sstevel@tonic-gate { 735*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 736*7c478bd9Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1; 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 739*7c478bd9Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 740*7c478bd9Sstevel@tonic-gate if (mi_op->mi_o_isdev) 741*7c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 742*7c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate return (NULL); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate /* 748*7c478bd9Sstevel@tonic-gate * Self clone the device 749*7c478bd9Sstevel@tonic-gate * XXX - should we still support clone device 750*7c478bd9Sstevel@tonic-gate */ 751*7c478bd9Sstevel@tonic-gate /* ARGSUSED4 */ 752*7c478bd9Sstevel@tonic-gate int 753*7c478bd9Sstevel@tonic-gate mi_open_comm(void **mi_headp, size_t size, queue_t *q, dev_t *devp, 754*7c478bd9Sstevel@tonic-gate int flag, int sflag, cred_t *credp) 755*7c478bd9Sstevel@tonic-gate { 756*7c478bd9Sstevel@tonic-gate int error; 757*7c478bd9Sstevel@tonic-gate IDP ptr; 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) 760*7c478bd9Sstevel@tonic-gate return (0); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate ptr = mi_open_alloc_sleep(size); 763*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = ptr; 764*7c478bd9Sstevel@tonic-gate error = mi_open_link(mi_headp, ptr, devp, flag, sflag, credp); 765*7c478bd9Sstevel@tonic-gate if (error != 0) { 766*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 767*7c478bd9Sstevel@tonic-gate mi_close_free(ptr); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate return (error); 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate IDP 773*7c478bd9Sstevel@tonic-gate mi_open_alloc_sleep(size_t size) 774*7c478bd9Sstevel@tonic-gate { 775*7c478bd9Sstevel@tonic-gate MI_OP mi_o; 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O))) 778*7c478bd9Sstevel@tonic-gate return (NULL); 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate mi_o = (MI_OP)mi_zalloc_sleep(size + sizeof (MI_O)); 781*7c478bd9Sstevel@tonic-gate mi_o++; 782*7c478bd9Sstevel@tonic-gate return ((IDP)mi_o); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate IDP 786*7c478bd9Sstevel@tonic-gate mi_open_alloc(size_t size) 787*7c478bd9Sstevel@tonic-gate { 788*7c478bd9Sstevel@tonic-gate MI_OP mi_o; 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O))) 791*7c478bd9Sstevel@tonic-gate return (NULL); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate if ((mi_o = (MI_OP)mi_zalloc(size + sizeof (MI_O))) == NULL) 794*7c478bd9Sstevel@tonic-gate return (NULL); 795*7c478bd9Sstevel@tonic-gate mi_o++; 796*7c478bd9Sstevel@tonic-gate return ((IDP)mi_o); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * MODOPEN means just link in without respect of mi_o_dev. 801*7c478bd9Sstevel@tonic-gate * A NULL devp can be used to create a detached instance 802*7c478bd9Sstevel@tonic-gate * Otherwise self-clone the device. 803*7c478bd9Sstevel@tonic-gate */ 804*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 805*7c478bd9Sstevel@tonic-gate int 806*7c478bd9Sstevel@tonic-gate mi_open_link(void **mi_headp, IDP ptr, dev_t *devp, int flag, int sflag, 807*7c478bd9Sstevel@tonic-gate cred_t *credp) 808*7c478bd9Sstevel@tonic-gate { 809*7c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 810*7c478bd9Sstevel@tonic-gate MI_OP insert; 811*7c478bd9Sstevel@tonic-gate MI_OP mi_o; 812*7c478bd9Sstevel@tonic-gate dev_t dev; 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate if (mi_head == NULL) { 815*7c478bd9Sstevel@tonic-gate char arena_name[50]; 816*7c478bd9Sstevel@tonic-gate char *head_name; 817*7c478bd9Sstevel@tonic-gate ulong_t offset; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate head_name = kobj_getsymname((uintptr_t)mi_headp, &offset); 820*7c478bd9Sstevel@tonic-gate if (head_name != NULL && offset == 0) 821*7c478bd9Sstevel@tonic-gate (void) sprintf(arena_name, "%s_", head_name); 822*7c478bd9Sstevel@tonic-gate else 823*7c478bd9Sstevel@tonic-gate (void) sprintf(arena_name, "0x%p_", (void *)mi_headp); 824*7c478bd9Sstevel@tonic-gate (void) sprintf(strchr(arena_name, '_') + 1, "minor"); 825*7c478bd9Sstevel@tonic-gate mi_head = (mi_head_t *)mi_zalloc_sleep(sizeof (mi_head_t)); 826*7c478bd9Sstevel@tonic-gate *mi_headp = (void *)mi_head; 827*7c478bd9Sstevel@tonic-gate /* Setup doubly linked list */ 828*7c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_next = &mi_head->mh_o; 829*7c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_prev = &mi_head->mh_o; 830*7c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_dev = 0; /* For asserts only */ 831*7c478bd9Sstevel@tonic-gate mi_head->mh_arena = (vmem_t *)inet_minor_create(arena_name, 832*7c478bd9Sstevel@tonic-gate INET_MIN_DEV, KM_SLEEP); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate ASSERT(ptr != NULL); 835*7c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 836*7c478bd9Sstevel@tonic-gate mi_o--; 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (sflag == MODOPEN) { 839*7c478bd9Sstevel@tonic-gate devp = NULL; 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * Set device number to MAXMIN + incrementing number. 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate dev = MAXMIN + ++mi_head->mh_module_dev; 844*7c478bd9Sstevel@tonic-gate /* check for wraparound */ 845*7c478bd9Sstevel@tonic-gate if (dev <= MAXMIN) { 846*7c478bd9Sstevel@tonic-gate dev = MAXMIN + 1; 847*7c478bd9Sstevel@tonic-gate mi_head->mh_module_dev = 1; 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate } else if (devp == NULL) { 850*7c478bd9Sstevel@tonic-gate /* Detached open */ 851*7c478bd9Sstevel@tonic-gate dev = (dev_t)OPENFAIL; 852*7c478bd9Sstevel@tonic-gate } else if ((dev = inet_minor_alloc(mi_head->mh_arena)) == 0) { 853*7c478bd9Sstevel@tonic-gate return (EBUSY); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate mi_o->mi_o_dev = dev; 857*7c478bd9Sstevel@tonic-gate insert = (&mi_head->mh_o); 858*7c478bd9Sstevel@tonic-gate mi_o->mi_o_next = insert; 859*7c478bd9Sstevel@tonic-gate insert->mi_o_prev->mi_o_next = mi_o; 860*7c478bd9Sstevel@tonic-gate mi_o->mi_o_prev = insert->mi_o_prev; 861*7c478bd9Sstevel@tonic-gate insert->mi_o_prev = mi_o; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate if (sflag == MODOPEN) 864*7c478bd9Sstevel@tonic-gate mi_o->mi_o_isdev = B_FALSE; 865*7c478bd9Sstevel@tonic-gate else 866*7c478bd9Sstevel@tonic-gate mi_o->mi_o_isdev = B_TRUE; 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate if (devp) 869*7c478bd9Sstevel@tonic-gate *devp = makedevice(getemajor(*devp), (minor_t)dev); 870*7c478bd9Sstevel@tonic-gate return (0); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate uint8_t * 874*7c478bd9Sstevel@tonic-gate mi_offset_param(mblk_t *mp, size_t offset, size_t len) 875*7c478bd9Sstevel@tonic-gate { 876*7c478bd9Sstevel@tonic-gate size_t msg_len; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate if (!mp) 879*7c478bd9Sstevel@tonic-gate return (NULL); 880*7c478bd9Sstevel@tonic-gate msg_len = mp->b_wptr - mp->b_rptr; 881*7c478bd9Sstevel@tonic-gate if (msg_len == 0 || offset > msg_len || len > msg_len || 882*7c478bd9Sstevel@tonic-gate (offset + len) > msg_len || len == 0) 883*7c478bd9Sstevel@tonic-gate return (NULL); 884*7c478bd9Sstevel@tonic-gate return (&mp->b_rptr[offset]); 885*7c478bd9Sstevel@tonic-gate } 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate uint8_t * 888*7c478bd9Sstevel@tonic-gate mi_offset_paramc(mblk_t *mp, size_t offset, size_t len) 889*7c478bd9Sstevel@tonic-gate { 890*7c478bd9Sstevel@tonic-gate uint8_t *param; 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate for (; mp; mp = mp->b_cont) { 893*7c478bd9Sstevel@tonic-gate int type = mp->b_datap->db_type; 894*7c478bd9Sstevel@tonic-gate if (datamsg(type)) { 895*7c478bd9Sstevel@tonic-gate if (param = mi_offset_param(mp, offset, len)) 896*7c478bd9Sstevel@tonic-gate return (param); 897*7c478bd9Sstevel@tonic-gate if (offset < mp->b_wptr - mp->b_rptr) 898*7c478bd9Sstevel@tonic-gate break; 899*7c478bd9Sstevel@tonic-gate offset -= mp->b_wptr - mp->b_rptr; 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate return (NULL); 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate boolean_t 907*7c478bd9Sstevel@tonic-gate mi_set_sth_hiwat(queue_t *q, size_t size) 908*7c478bd9Sstevel@tonic-gate { 909*7c478bd9Sstevel@tonic-gate MBLKP mp; 910*7c478bd9Sstevel@tonic-gate STROPTP stropt; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 913*7c478bd9Sstevel@tonic-gate return (B_FALSE); 914*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 915*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 916*7c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 917*7c478bd9Sstevel@tonic-gate stropt->so_flags = SO_HIWAT; 918*7c478bd9Sstevel@tonic-gate stropt->so_hiwat = size; 919*7c478bd9Sstevel@tonic-gate putnext(q, mp); 920*7c478bd9Sstevel@tonic-gate return (B_TRUE); 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate boolean_t 924*7c478bd9Sstevel@tonic-gate mi_set_sth_lowat(queue_t *q, size_t size) 925*7c478bd9Sstevel@tonic-gate { 926*7c478bd9Sstevel@tonic-gate MBLKP mp; 927*7c478bd9Sstevel@tonic-gate STROPTP stropt; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 930*7c478bd9Sstevel@tonic-gate return (B_FALSE); 931*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 932*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 933*7c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 934*7c478bd9Sstevel@tonic-gate stropt->so_flags = SO_LOWAT; 935*7c478bd9Sstevel@tonic-gate stropt->so_lowat = size; 936*7c478bd9Sstevel@tonic-gate putnext(q, mp); 937*7c478bd9Sstevel@tonic-gate return (B_TRUE); 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 941*7c478bd9Sstevel@tonic-gate boolean_t 942*7c478bd9Sstevel@tonic-gate mi_set_sth_maxblk(queue_t *q, ssize_t size) 943*7c478bd9Sstevel@tonic-gate { 944*7c478bd9Sstevel@tonic-gate MBLKP mp; 945*7c478bd9Sstevel@tonic-gate STROPTP stropt; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 948*7c478bd9Sstevel@tonic-gate return (B_FALSE); 949*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 950*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 951*7c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 952*7c478bd9Sstevel@tonic-gate stropt->so_flags = SO_MAXBLK; 953*7c478bd9Sstevel@tonic-gate stropt->so_maxblk = size; 954*7c478bd9Sstevel@tonic-gate putnext(q, mp); 955*7c478bd9Sstevel@tonic-gate return (B_TRUE); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate boolean_t 959*7c478bd9Sstevel@tonic-gate mi_set_sth_copyopt(queue_t *q, int copyopt) 960*7c478bd9Sstevel@tonic-gate { 961*7c478bd9Sstevel@tonic-gate MBLKP mp; 962*7c478bd9Sstevel@tonic-gate STROPTP stropt; 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 965*7c478bd9Sstevel@tonic-gate return (B_FALSE); 966*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 967*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 968*7c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 969*7c478bd9Sstevel@tonic-gate stropt->so_flags = SO_COPYOPT; 970*7c478bd9Sstevel@tonic-gate stropt->so_copyopt = (ushort_t)copyopt; 971*7c478bd9Sstevel@tonic-gate putnext(q, mp); 972*7c478bd9Sstevel@tonic-gate return (B_TRUE); 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate boolean_t 976*7c478bd9Sstevel@tonic-gate mi_set_sth_wroff(queue_t *q, size_t size) 977*7c478bd9Sstevel@tonic-gate { 978*7c478bd9Sstevel@tonic-gate MBLKP mp; 979*7c478bd9Sstevel@tonic-gate STROPTP stropt; 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 982*7c478bd9Sstevel@tonic-gate return (B_FALSE); 983*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 984*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 985*7c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 986*7c478bd9Sstevel@tonic-gate stropt->so_flags = SO_WROFF; 987*7c478bd9Sstevel@tonic-gate stropt->so_wroff = (ushort_t)size; 988*7c478bd9Sstevel@tonic-gate putnext(q, mp); 989*7c478bd9Sstevel@tonic-gate return (B_TRUE); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate int 993*7c478bd9Sstevel@tonic-gate mi_sprintf(char *buf, char *fmt, ...) 994*7c478bd9Sstevel@tonic-gate { 995*7c478bd9Sstevel@tonic-gate va_list ap; 996*7c478bd9Sstevel@tonic-gate int count = -1; 997*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 998*7c478bd9Sstevel@tonic-gate if (buf) { 999*7c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_sprintf_putc, 1000*7c478bd9Sstevel@tonic-gate (char *)&buf); 1001*7c478bd9Sstevel@tonic-gate if (count != -1) 1002*7c478bd9Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&buf, '\0'); 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate va_end(ap); 1005*7c478bd9Sstevel@tonic-gate return (count); 1006*7c478bd9Sstevel@tonic-gate } 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate /* Used to count without writing data */ 1009*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 1010*7c478bd9Sstevel@tonic-gate static int 1011*7c478bd9Sstevel@tonic-gate mi_sprintf_noop(char *cookie, int ch) 1012*7c478bd9Sstevel@tonic-gate { 1013*7c478bd9Sstevel@tonic-gate char **cpp = (char **)cookie; 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate (*cpp)++; 1016*7c478bd9Sstevel@tonic-gate return (1); 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate int 1020*7c478bd9Sstevel@tonic-gate mi_sprintf_putc(char *cookie, int ch) 1021*7c478bd9Sstevel@tonic-gate { 1022*7c478bd9Sstevel@tonic-gate char **cpp = (char **)cookie; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate **cpp = (char)ch; 1025*7c478bd9Sstevel@tonic-gate (*cpp)++; 1026*7c478bd9Sstevel@tonic-gate return (1); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate int 1030*7c478bd9Sstevel@tonic-gate mi_strcmp(const char *cp1, const char *cp2) 1031*7c478bd9Sstevel@tonic-gate { 1032*7c478bd9Sstevel@tonic-gate while (*cp1++ == *cp2++) { 1033*7c478bd9Sstevel@tonic-gate if (!cp2[-1]) 1034*7c478bd9Sstevel@tonic-gate return (0); 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate return ((uint_t)cp2[-1] & 0xFF) - ((uint_t)cp1[-1] & 0xFF); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate size_t 1040*7c478bd9Sstevel@tonic-gate mi_strlen(const char *str) 1041*7c478bd9Sstevel@tonic-gate { 1042*7c478bd9Sstevel@tonic-gate const char *cp = str; 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate while (*cp != '\0') 1045*7c478bd9Sstevel@tonic-gate cp++; 1046*7c478bd9Sstevel@tonic-gate return ((int)(cp - str)); 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate int 1050*7c478bd9Sstevel@tonic-gate mi_strlog(queue_t *q, char level, ushort_t flags, char *fmt, ...) 1051*7c478bd9Sstevel@tonic-gate { 1052*7c478bd9Sstevel@tonic-gate va_list ap; 1053*7c478bd9Sstevel@tonic-gate char buf[200]; 1054*7c478bd9Sstevel@tonic-gate char *alloc_buf = buf; 1055*7c478bd9Sstevel@tonic-gate int count = -1; 1056*7c478bd9Sstevel@tonic-gate char *cp; 1057*7c478bd9Sstevel@tonic-gate short mid; 1058*7c478bd9Sstevel@tonic-gate int ret; 1059*7c478bd9Sstevel@tonic-gate short sid; 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate sid = 0; 1062*7c478bd9Sstevel@tonic-gate mid = 0; 1063*7c478bd9Sstevel@tonic-gate if (q != NULL) { 1064*7c478bd9Sstevel@tonic-gate mid = q->q_qinfo->qi_minfo->mi_idnum; 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate /* Find out how many bytes we need and allocate if necesary */ 1068*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1069*7c478bd9Sstevel@tonic-gate cp = buf; 1070*7c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_noop, (char *)&cp); 1071*7c478bd9Sstevel@tonic-gate if (count > sizeof (buf) && 1072*7c478bd9Sstevel@tonic-gate !(alloc_buf = mi_alloc((uint_t)count + 2, BPRI_MED))) { 1073*7c478bd9Sstevel@tonic-gate va_end(ap); 1074*7c478bd9Sstevel@tonic-gate return (-1); 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate va_end(ap); 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1079*7c478bd9Sstevel@tonic-gate cp = alloc_buf; 1080*7c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_putc, (char *)&cp); 1081*7c478bd9Sstevel@tonic-gate if (count != -1) 1082*7c478bd9Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&cp, '\0'); 1083*7c478bd9Sstevel@tonic-gate else 1084*7c478bd9Sstevel@tonic-gate alloc_buf[0] = '\0'; 1085*7c478bd9Sstevel@tonic-gate va_end(ap); 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate ret = strlog(mid, sid, level, flags, alloc_buf); 1088*7c478bd9Sstevel@tonic-gate if (alloc_buf != buf) 1089*7c478bd9Sstevel@tonic-gate mi_free(alloc_buf); 1090*7c478bd9Sstevel@tonic-gate return (ret); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate long 1094*7c478bd9Sstevel@tonic-gate mi_strtol(const char *str, char **ptr, int base) 1095*7c478bd9Sstevel@tonic-gate { 1096*7c478bd9Sstevel@tonic-gate const char *cp; 1097*7c478bd9Sstevel@tonic-gate int digits; 1098*7c478bd9Sstevel@tonic-gate long value; 1099*7c478bd9Sstevel@tonic-gate boolean_t is_negative; 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate cp = str; 1102*7c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t' || *cp == '\n') 1103*7c478bd9Sstevel@tonic-gate cp++; 1104*7c478bd9Sstevel@tonic-gate is_negative = (*cp == '-'); 1105*7c478bd9Sstevel@tonic-gate if (is_negative) 1106*7c478bd9Sstevel@tonic-gate cp++; 1107*7c478bd9Sstevel@tonic-gate if (base == 0) { 1108*7c478bd9Sstevel@tonic-gate base = 10; 1109*7c478bd9Sstevel@tonic-gate if (*cp == '0') { 1110*7c478bd9Sstevel@tonic-gate base = 8; 1111*7c478bd9Sstevel@tonic-gate cp++; 1112*7c478bd9Sstevel@tonic-gate if (*cp == 'x' || *cp == 'X') { 1113*7c478bd9Sstevel@tonic-gate base = 16; 1114*7c478bd9Sstevel@tonic-gate cp++; 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate value = 0; 1119*7c478bd9Sstevel@tonic-gate for (; *cp != '\0'; cp++) { 1120*7c478bd9Sstevel@tonic-gate if (*cp >= '0' && *cp <= '9') 1121*7c478bd9Sstevel@tonic-gate digits = *cp - '0'; 1122*7c478bd9Sstevel@tonic-gate else if (*cp >= 'a' && *cp <= 'f') 1123*7c478bd9Sstevel@tonic-gate digits = *cp - 'a' + 10; 1124*7c478bd9Sstevel@tonic-gate else if (*cp >= 'A' && *cp <= 'F') 1125*7c478bd9Sstevel@tonic-gate digits = *cp - 'A' + 10; 1126*7c478bd9Sstevel@tonic-gate else 1127*7c478bd9Sstevel@tonic-gate break; 1128*7c478bd9Sstevel@tonic-gate if (digits >= base) 1129*7c478bd9Sstevel@tonic-gate break; 1130*7c478bd9Sstevel@tonic-gate value = (value * base) + digits; 1131*7c478bd9Sstevel@tonic-gate } 1132*7c478bd9Sstevel@tonic-gate /* Note: we cast away const here deliberately */ 1133*7c478bd9Sstevel@tonic-gate if (ptr != NULL) 1134*7c478bd9Sstevel@tonic-gate *ptr = (char *)cp; 1135*7c478bd9Sstevel@tonic-gate if (is_negative) 1136*7c478bd9Sstevel@tonic-gate value = -value; 1137*7c478bd9Sstevel@tonic-gate return (value); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate /* 1141*7c478bd9Sstevel@tonic-gate * mi_timer mechanism. 1142*7c478bd9Sstevel@tonic-gate * 1143*7c478bd9Sstevel@tonic-gate * Each timer is represented by a timer mblk and a (streams) queue. When the 1144*7c478bd9Sstevel@tonic-gate * timer fires the timer mblk will be put on the associated streams queue 1145*7c478bd9Sstevel@tonic-gate * so that the streams module can process the timer even in its service 1146*7c478bd9Sstevel@tonic-gate * procedure. 1147*7c478bd9Sstevel@tonic-gate * 1148*7c478bd9Sstevel@tonic-gate * The interface consists of 4 entry points: 1149*7c478bd9Sstevel@tonic-gate * mi_timer_alloc - create a timer mblk 1150*7c478bd9Sstevel@tonic-gate * mi_timer_free - free a timer mblk 1151*7c478bd9Sstevel@tonic-gate * mi_timer - start, restart, stop, or move the 1152*7c478bd9Sstevel@tonic-gate * timer to a different queue 1153*7c478bd9Sstevel@tonic-gate * mi_timer_valid - called by streams module to verify that 1154*7c478bd9Sstevel@tonic-gate * the timer did indeed fire. 1155*7c478bd9Sstevel@tonic-gate */ 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate /* 1161*7c478bd9Sstevel@tonic-gate * Start, restart, stop, or move the timer to a new queue. 1162*7c478bd9Sstevel@tonic-gate * If "tim" is -2 the timer is moved to a different queue. 1163*7c478bd9Sstevel@tonic-gate * If "tim" is -1 the timer is stopped. 1164*7c478bd9Sstevel@tonic-gate * Otherwise, the timer is stopped if it is already running, and 1165*7c478bd9Sstevel@tonic-gate * set to fire tim milliseconds from now. 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate void 1169*7c478bd9Sstevel@tonic-gate mi_timer(queue_t *q, MBLKP mp, clock_t tim) 1170*7c478bd9Sstevel@tonic-gate { 1171*7c478bd9Sstevel@tonic-gate MTBP mtb; 1172*7c478bd9Sstevel@tonic-gate int state; 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate ASSERT(tim >= -2); 1175*7c478bd9Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1176*7c478bd9Sstevel@tonic-gate return; 1177*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1178*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 1179*7c478bd9Sstevel@tonic-gate if (tim >= 0) { 1180*7c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 1181*7c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 1182*7c478bd9Sstevel@tonic-gate tim = MSEC_TO_TICK(tim); 1183*7c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 1184*7c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 1185*7c478bd9Sstevel@tonic-gate /* Message has already been putq */ 1186*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1187*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1188*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED; 1189*7c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 1190*7c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 1191*7c478bd9Sstevel@tonic-gate return; 1192*7c478bd9Sstevel@tonic-gate } 1193*7c478bd9Sstevel@tonic-gate } else if (state != TB_IDLE) { 1194*7c478bd9Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED); 1195*7c478bd9Sstevel@tonic-gate if (state == TB_CANCELLED) { 1196*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1197*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1198*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED; 1199*7c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 1200*7c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 1201*7c478bd9Sstevel@tonic-gate return; 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate if (state == TB_RESCHED) { 1204*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1205*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1206*7c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 1207*7c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 1208*7c478bd9Sstevel@tonic-gate return; 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 1212*7c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 1213*7c478bd9Sstevel@tonic-gate return; 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate switch (tim) { 1216*7c478bd9Sstevel@tonic-gate case -1: 1217*7c478bd9Sstevel@tonic-gate mi_timer_stop(mp); 1218*7c478bd9Sstevel@tonic-gate break; 1219*7c478bd9Sstevel@tonic-gate case -2: 1220*7c478bd9Sstevel@tonic-gate mi_timer_move(q, mp); 1221*7c478bd9Sstevel@tonic-gate break; 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate /* 1226*7c478bd9Sstevel@tonic-gate * Allocate an M_PCSIG timer message. The space between db_base and 1227*7c478bd9Sstevel@tonic-gate * b_rptr is used by the mi_timer mechanism, and after b_rptr there are 1228*7c478bd9Sstevel@tonic-gate * "size" bytes that the caller can use for its own purposes. 1229*7c478bd9Sstevel@tonic-gate * 1230*7c478bd9Sstevel@tonic-gate * Note that db_type has to be a priority message since otherwise 1231*7c478bd9Sstevel@tonic-gate * the putq will not cause the service procedure to run when 1232*7c478bd9Sstevel@tonic-gate * there is flow control. 1233*7c478bd9Sstevel@tonic-gate */ 1234*7c478bd9Sstevel@tonic-gate MBLKP 1235*7c478bd9Sstevel@tonic-gate mi_timer_alloc(size_t size) 1236*7c478bd9Sstevel@tonic-gate { 1237*7c478bd9Sstevel@tonic-gate MBLKP mp; 1238*7c478bd9Sstevel@tonic-gate MTBP mtb; 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate if ((mp = allocb(size + sizeof (MTB), BPRI_HI)) != NULL) { 1241*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCSIG; 1242*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1243*7c478bd9Sstevel@tonic-gate mp->b_rptr = (uchar_t *)&mtb[1]; 1244*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + size; 1245*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 1246*7c478bd9Sstevel@tonic-gate mtb->mtb_mp = mp; 1247*7c478bd9Sstevel@tonic-gate mtb->mtb_q = NULL; 1248*7c478bd9Sstevel@tonic-gate return (mp); 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate return (NULL); 1251*7c478bd9Sstevel@tonic-gate } 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate /* 1254*7c478bd9Sstevel@tonic-gate * timeout() callback function. 1255*7c478bd9Sstevel@tonic-gate * Put the message on the current queue. 1256*7c478bd9Sstevel@tonic-gate * If the timer is stopped or moved to a different queue after 1257*7c478bd9Sstevel@tonic-gate * it has fired then mi_timer() and mi_timer_valid() will clean 1258*7c478bd9Sstevel@tonic-gate * things up. 1259*7c478bd9Sstevel@tonic-gate */ 1260*7c478bd9Sstevel@tonic-gate static int 1261*7c478bd9Sstevel@tonic-gate mi_timer_fire(MTBP mtb) 1262*7c478bd9Sstevel@tonic-gate { 1263*7c478bd9Sstevel@tonic-gate ASSERT(mtb == (MTBP)mtb->mtb_mp->b_datap->db_base); 1264*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_mp->b_datap->db_type == M_PCSIG); 1265*7c478bd9Sstevel@tonic-gate return (putq(mtb->mtb_q, mtb->mtb_mp)); 1266*7c478bd9Sstevel@tonic-gate } 1267*7c478bd9Sstevel@tonic-gate 1268*7c478bd9Sstevel@tonic-gate /* 1269*7c478bd9Sstevel@tonic-gate * Logically free a timer mblk (that might have a pending timeout().) 1270*7c478bd9Sstevel@tonic-gate * If the timer has fired and the mblk has been put on the queue then 1271*7c478bd9Sstevel@tonic-gate * mi_timer_valid will free the mblk. 1272*7c478bd9Sstevel@tonic-gate */ 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate void 1275*7c478bd9Sstevel@tonic-gate mi_timer_free(MBLKP mp) 1276*7c478bd9Sstevel@tonic-gate { 1277*7c478bd9Sstevel@tonic-gate MTBP mtb; 1278*7c478bd9Sstevel@tonic-gate int state; 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1281*7c478bd9Sstevel@tonic-gate return; 1282*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1283*7c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 1284*7c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 1285*7c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 1286*7c478bd9Sstevel@tonic-gate /* Message has already been putq */ 1287*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1288*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1289*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED; 1290*7c478bd9Sstevel@tonic-gate /* mi_timer_valid will free the mblk */ 1291*7c478bd9Sstevel@tonic-gate return; 1292*7c478bd9Sstevel@tonic-gate } 1293*7c478bd9Sstevel@tonic-gate } else if (state != TB_IDLE) { 1294*7c478bd9Sstevel@tonic-gate /* Message has already been putq */ 1295*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1296*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1297*7c478bd9Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED); 1298*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED; 1299*7c478bd9Sstevel@tonic-gate /* mi_timer_valid will free the mblk */ 1300*7c478bd9Sstevel@tonic-gate return; 1301*7c478bd9Sstevel@tonic-gate } 1302*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q == NULL || mtb->mtb_q->q_first != mp); 1303*7c478bd9Sstevel@tonic-gate freemsg(mp); 1304*7c478bd9Sstevel@tonic-gate } 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate /* 1307*7c478bd9Sstevel@tonic-gate * Called from mi_timer(,,-2) 1308*7c478bd9Sstevel@tonic-gate */ 1309*7c478bd9Sstevel@tonic-gate void 1310*7c478bd9Sstevel@tonic-gate mi_timer_move(queue_t *q, MBLKP mp) 1311*7c478bd9Sstevel@tonic-gate { 1312*7c478bd9Sstevel@tonic-gate MTBP mtb; 1313*7c478bd9Sstevel@tonic-gate clock_t tim; 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1316*7c478bd9Sstevel@tonic-gate return; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1319*7c478bd9Sstevel@tonic-gate /* 1320*7c478bd9Sstevel@tonic-gate * Need to untimeout and restart to make 1321*7c478bd9Sstevel@tonic-gate * sure that the mblk is not about to be putq on the old queue 1322*7c478bd9Sstevel@tonic-gate * by mi_timer_fire. 1323*7c478bd9Sstevel@tonic-gate */ 1324*7c478bd9Sstevel@tonic-gate if (mtb->mtb_state == TB_RUNNING) { 1325*7c478bd9Sstevel@tonic-gate if ((tim = untimeout(mtb->mtb_tid)) < 0) { 1326*7c478bd9Sstevel@tonic-gate /* 1327*7c478bd9Sstevel@tonic-gate * Message has already been putq. Move from old queue 1328*7c478bd9Sstevel@tonic-gate * to new queue. 1329*7c478bd9Sstevel@tonic-gate */ 1330*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1331*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1332*7c478bd9Sstevel@tonic-gate rmvq(mtb->mtb_q, mp); 1333*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp && 1334*7c478bd9Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL); 1335*7c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 1336*7c478bd9Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp); 1337*7c478bd9Sstevel@tonic-gate return; 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 1340*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 1341*7c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 1342*7c478bd9Sstevel@tonic-gate } else if (mtb->mtb_state != TB_IDLE) { 1343*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_state != TB_TO_BE_FREED); 1344*7c478bd9Sstevel@tonic-gate /* 1345*7c478bd9Sstevel@tonic-gate * Message is already sitting on queue. Move to new queue. 1346*7c478bd9Sstevel@tonic-gate */ 1347*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1348*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1349*7c478bd9Sstevel@tonic-gate rmvq(mtb->mtb_q, mp); 1350*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp && 1351*7c478bd9Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL); 1352*7c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 1353*7c478bd9Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp); 1354*7c478bd9Sstevel@tonic-gate } else 1355*7c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 1356*7c478bd9Sstevel@tonic-gate } 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate /* 1359*7c478bd9Sstevel@tonic-gate * Called from mi_timer(,,-1) 1360*7c478bd9Sstevel@tonic-gate */ 1361*7c478bd9Sstevel@tonic-gate void 1362*7c478bd9Sstevel@tonic-gate mi_timer_stop(MBLKP mp) 1363*7c478bd9Sstevel@tonic-gate { 1364*7c478bd9Sstevel@tonic-gate MTBP mtb; 1365*7c478bd9Sstevel@tonic-gate int state; 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1368*7c478bd9Sstevel@tonic-gate return; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1371*7c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 1372*7c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 1373*7c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 1374*7c478bd9Sstevel@tonic-gate /* Message has already been putq */ 1375*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1376*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1377*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED; 1378*7c478bd9Sstevel@tonic-gate } else { 1379*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate } else if (state == TB_RESCHED) { 1382*7c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 1383*7c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 1384*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED; 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate } 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate /* 1389*7c478bd9Sstevel@tonic-gate * The user of the mi_timer mechanism is required to call mi_timer_valid() for 1390*7c478bd9Sstevel@tonic-gate * each M_PCSIG message processed in the service procedures. 1391*7c478bd9Sstevel@tonic-gate * mi_timer_valid will return "true" if the timer actually did fire. 1392*7c478bd9Sstevel@tonic-gate */ 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate boolean_t 1395*7c478bd9Sstevel@tonic-gate mi_timer_valid(MBLKP mp) 1396*7c478bd9Sstevel@tonic-gate { 1397*7c478bd9Sstevel@tonic-gate MTBP mtb; 1398*7c478bd9Sstevel@tonic-gate int state; 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB) || 1401*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type != M_PCSIG) 1402*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1403*7c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 1404*7c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 1405*7c478bd9Sstevel@tonic-gate if (state != TB_RUNNING) { 1406*7c478bd9Sstevel@tonic-gate ASSERT(state != TB_IDLE); 1407*7c478bd9Sstevel@tonic-gate if (state == TB_TO_BE_FREED) { 1408*7c478bd9Sstevel@tonic-gate /* 1409*7c478bd9Sstevel@tonic-gate * mi_timer_free was called after the message 1410*7c478bd9Sstevel@tonic-gate * was putq'ed. 1411*7c478bd9Sstevel@tonic-gate */ 1412*7c478bd9Sstevel@tonic-gate freemsg(mp); 1413*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate if (state == TB_CANCELLED) { 1416*7c478bd9Sstevel@tonic-gate /* The timer was stopped after the mblk was putq'ed */ 1417*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 1418*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1419*7c478bd9Sstevel@tonic-gate } 1420*7c478bd9Sstevel@tonic-gate if (state == TB_RESCHED) { 1421*7c478bd9Sstevel@tonic-gate /* 1422*7c478bd9Sstevel@tonic-gate * The timer was stopped and then restarted after 1423*7c478bd9Sstevel@tonic-gate * the mblk was putq'ed. 1424*7c478bd9Sstevel@tonic-gate * mtb_time_left contains the number of ticks that 1425*7c478bd9Sstevel@tonic-gate * the timer was restarted with. 1426*7c478bd9Sstevel@tonic-gate */ 1427*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 1428*7c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, 1429*7c478bd9Sstevel@tonic-gate mtb, mtb->mtb_time_left); 1430*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1431*7c478bd9Sstevel@tonic-gate } 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 1434*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1435*7c478bd9Sstevel@tonic-gate } 1436*7c478bd9Sstevel@tonic-gate 1437*7c478bd9Sstevel@tonic-gate static void 1438*7c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(MBLKP mp, char *addr, t_scalar_t addr_length, 1439*7c478bd9Sstevel@tonic-gate char *opt, t_scalar_t opt_length) 1440*7c478bd9Sstevel@tonic-gate { 1441*7c478bd9Sstevel@tonic-gate struct T_unitdata_ind *tudi; 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate /* 1444*7c478bd9Sstevel@tonic-gate * This code is used more than just for unitdata ind 1445*7c478bd9Sstevel@tonic-gate * (also for T_CONN_IND and T_CONN_CON) and 1446*7c478bd9Sstevel@tonic-gate * relies on correct functioning on the happy 1447*7c478bd9Sstevel@tonic-gate * coincidence that the the address and option buffers 1448*7c478bd9Sstevel@tonic-gate * represented by length/offset in all these primitives 1449*7c478bd9Sstevel@tonic-gate * are isomorphic in terms of offset from start of data 1450*7c478bd9Sstevel@tonic-gate * structure 1451*7c478bd9Sstevel@tonic-gate */ 1452*7c478bd9Sstevel@tonic-gate tudi = (struct T_unitdata_ind *)mp->b_rptr; 1453*7c478bd9Sstevel@tonic-gate tudi->SRC_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1454*7c478bd9Sstevel@tonic-gate tudi->SRC_length = addr_length; 1455*7c478bd9Sstevel@tonic-gate if (addr_length > 0) { 1456*7c478bd9Sstevel@tonic-gate bcopy(addr, (char *)mp->b_wptr, addr_length); 1457*7c478bd9Sstevel@tonic-gate mp->b_wptr += addr_length; 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate tudi->OPT_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1460*7c478bd9Sstevel@tonic-gate tudi->OPT_length = opt_length; 1461*7c478bd9Sstevel@tonic-gate if (opt_length > 0) { 1462*7c478bd9Sstevel@tonic-gate bcopy(opt, (char *)mp->b_wptr, opt_length); 1463*7c478bd9Sstevel@tonic-gate mp->b_wptr += opt_length; 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate } 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate MBLKP 1468*7c478bd9Sstevel@tonic-gate mi_tpi_conn_con(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 1469*7c478bd9Sstevel@tonic-gate t_scalar_t opt_length) 1470*7c478bd9Sstevel@tonic-gate { 1471*7c478bd9Sstevel@tonic-gate size_t len; 1472*7c478bd9Sstevel@tonic-gate MBLKP mp; 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate len = sizeof (struct T_conn_con) + src_length + opt_length; 1475*7c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_CON)) != NULL) { 1476*7c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_con)]; 1477*7c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1478*7c478bd9Sstevel@tonic-gate } 1479*7c478bd9Sstevel@tonic-gate return (mp); 1480*7c478bd9Sstevel@tonic-gate } 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate MBLKP 1483*7c478bd9Sstevel@tonic-gate mi_tpi_conn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 1484*7c478bd9Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t seqnum) 1485*7c478bd9Sstevel@tonic-gate { 1486*7c478bd9Sstevel@tonic-gate size_t len; 1487*7c478bd9Sstevel@tonic-gate MBLKP mp; 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate len = sizeof (struct T_conn_ind) + src_length + opt_length; 1490*7c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_IND)) != NULL) { 1491*7c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_ind)]; 1492*7c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1493*7c478bd9Sstevel@tonic-gate ((struct T_conn_ind *)mp->b_rptr)->SEQ_number = seqnum; 1494*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 1495*7c478bd9Sstevel@tonic-gate } 1496*7c478bd9Sstevel@tonic-gate return (mp); 1497*7c478bd9Sstevel@tonic-gate } 1498*7c478bd9Sstevel@tonic-gate 1499*7c478bd9Sstevel@tonic-gate MBLKP 1500*7c478bd9Sstevel@tonic-gate mi_tpi_extconn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, 1501*7c478bd9Sstevel@tonic-gate char *opt, t_scalar_t opt_length, char *dst, t_scalar_t dst_length, 1502*7c478bd9Sstevel@tonic-gate t_scalar_t seqnum) 1503*7c478bd9Sstevel@tonic-gate { 1504*7c478bd9Sstevel@tonic-gate size_t len; 1505*7c478bd9Sstevel@tonic-gate MBLKP mp; 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate len = sizeof (struct T_extconn_ind) + src_length + opt_length + 1508*7c478bd9Sstevel@tonic-gate dst_length; 1509*7c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_EXTCONN_IND)) != 1510*7c478bd9Sstevel@tonic-gate NULL) { 1511*7c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_extconn_ind)]; 1512*7c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1513*7c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_length = dst_length; 1514*7c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_offset = 1515*7c478bd9Sstevel@tonic-gate (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1516*7c478bd9Sstevel@tonic-gate if (dst_length > 0) { 1517*7c478bd9Sstevel@tonic-gate bcopy(dst, (char *)mp->b_wptr, dst_length); 1518*7c478bd9Sstevel@tonic-gate mp->b_wptr += dst_length; 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->SEQ_number = seqnum; 1521*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate return (mp); 1524*7c478bd9Sstevel@tonic-gate } 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate MBLKP 1527*7c478bd9Sstevel@tonic-gate mi_tpi_discon_ind(MBLKP trailer_mp, t_scalar_t reason, t_scalar_t seqnum) 1528*7c478bd9Sstevel@tonic-gate { 1529*7c478bd9Sstevel@tonic-gate MBLKP mp; 1530*7c478bd9Sstevel@tonic-gate struct T_discon_ind *tdi; 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, 1533*7c478bd9Sstevel@tonic-gate sizeof (struct T_discon_ind), T_DISCON_IND)) != NULL) { 1534*7c478bd9Sstevel@tonic-gate tdi = (struct T_discon_ind *)mp->b_rptr; 1535*7c478bd9Sstevel@tonic-gate tdi->DISCON_reason = reason; 1536*7c478bd9Sstevel@tonic-gate tdi->SEQ_number = seqnum; 1537*7c478bd9Sstevel@tonic-gate } 1538*7c478bd9Sstevel@tonic-gate return (mp); 1539*7c478bd9Sstevel@tonic-gate } 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate /* 1542*7c478bd9Sstevel@tonic-gate * Allocate and fill in a TPI err ack packet using the 'mp' passed in 1543*7c478bd9Sstevel@tonic-gate * for the 'error_prim' context as well as sacrifice. 1544*7c478bd9Sstevel@tonic-gate */ 1545*7c478bd9Sstevel@tonic-gate MBLKP 1546*7c478bd9Sstevel@tonic-gate mi_tpi_err_ack_alloc(MBLKP mp, t_scalar_t tlierr, int unixerr) 1547*7c478bd9Sstevel@tonic-gate { 1548*7c478bd9Sstevel@tonic-gate struct T_error_ack *teackp; 1549*7c478bd9Sstevel@tonic-gate t_scalar_t error_prim; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate if (!mp) 1552*7c478bd9Sstevel@tonic-gate return (NULL); 1553*7c478bd9Sstevel@tonic-gate error_prim = ((TPRIMP)mp->b_rptr)->type; 1554*7c478bd9Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack), 1555*7c478bd9Sstevel@tonic-gate M_PCPROTO, T_ERROR_ACK)) != NULL) { 1556*7c478bd9Sstevel@tonic-gate teackp = (struct T_error_ack *)mp->b_rptr; 1557*7c478bd9Sstevel@tonic-gate teackp->ERROR_prim = error_prim; 1558*7c478bd9Sstevel@tonic-gate teackp->TLI_error = tlierr; 1559*7c478bd9Sstevel@tonic-gate teackp->UNIX_error = unixerr; 1560*7c478bd9Sstevel@tonic-gate } 1561*7c478bd9Sstevel@tonic-gate return (mp); 1562*7c478bd9Sstevel@tonic-gate } 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate MBLKP 1565*7c478bd9Sstevel@tonic-gate mi_tpi_ok_ack_alloc_extra(MBLKP mp, int extra) 1566*7c478bd9Sstevel@tonic-gate { 1567*7c478bd9Sstevel@tonic-gate t_scalar_t correct_prim; 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate if (!mp) 1570*7c478bd9Sstevel@tonic-gate return (NULL); 1571*7c478bd9Sstevel@tonic-gate correct_prim = ((TPRIMP)mp->b_rptr)->type; 1572*7c478bd9Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_ok_ack) + extra, 1573*7c478bd9Sstevel@tonic-gate M_PCPROTO, T_OK_ACK)) != NULL) { 1574*7c478bd9Sstevel@tonic-gate ((struct T_ok_ack *)mp->b_rptr)->CORRECT_prim = correct_prim; 1575*7c478bd9Sstevel@tonic-gate mp->b_wptr -= extra; 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate return (mp); 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate MBLKP 1581*7c478bd9Sstevel@tonic-gate mi_tpi_ok_ack_alloc(MBLKP mp) 1582*7c478bd9Sstevel@tonic-gate { 1583*7c478bd9Sstevel@tonic-gate return (mi_tpi_ok_ack_alloc_extra(mp, 0)); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate MBLKP 1587*7c478bd9Sstevel@tonic-gate mi_tpi_ordrel_ind(void) 1588*7c478bd9Sstevel@tonic-gate { 1589*7c478bd9Sstevel@tonic-gate MBLKP mp; 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (struct T_ordrel_ind), BPRI_HI)) != NULL) { 1592*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 1593*7c478bd9Sstevel@tonic-gate ((struct T_ordrel_ind *)mp->b_rptr)->PRIM_type = T_ORDREL_IND; 1594*7c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (struct T_ordrel_ind); 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate return (mp); 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate static MBLKP 1600*7c478bd9Sstevel@tonic-gate mi_tpi_trailer_alloc(MBLKP trailer_mp, size_t size, t_scalar_t type) 1601*7c478bd9Sstevel@tonic-gate { 1602*7c478bd9Sstevel@tonic-gate MBLKP mp; 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate if ((mp = allocb(size, BPRI_MED)) != NULL) { 1605*7c478bd9Sstevel@tonic-gate mp->b_cont = trailer_mp; 1606*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 1607*7c478bd9Sstevel@tonic-gate ((union T_primitives *)mp->b_rptr)->type = type; 1608*7c478bd9Sstevel@tonic-gate mp->b_wptr += size; 1609*7c478bd9Sstevel@tonic-gate } 1610*7c478bd9Sstevel@tonic-gate return (mp); 1611*7c478bd9Sstevel@tonic-gate } 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate MBLKP 1614*7c478bd9Sstevel@tonic-gate mi_tpi_uderror_ind(char *dest, t_scalar_t dest_length, char *opt, 1615*7c478bd9Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t error) 1616*7c478bd9Sstevel@tonic-gate { 1617*7c478bd9Sstevel@tonic-gate size_t len; 1618*7c478bd9Sstevel@tonic-gate MBLKP mp; 1619*7c478bd9Sstevel@tonic-gate struct T_uderror_ind *tudei; 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate len = sizeof (struct T_uderror_ind) + dest_length + opt_length; 1622*7c478bd9Sstevel@tonic-gate if ((mp = allocb(len, BPRI_HI)) != NULL) { 1623*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 1624*7c478bd9Sstevel@tonic-gate tudei = (struct T_uderror_ind *)mp->b_rptr; 1625*7c478bd9Sstevel@tonic-gate tudei->PRIM_type = T_UDERROR_IND; 1626*7c478bd9Sstevel@tonic-gate tudei->ERROR_type = error; 1627*7c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_uderror_ind)]; 1628*7c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, dest, dest_length, opt, opt_length); 1629*7c478bd9Sstevel@tonic-gate } 1630*7c478bd9Sstevel@tonic-gate return (mp); 1631*7c478bd9Sstevel@tonic-gate } 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate IDP 1634*7c478bd9Sstevel@tonic-gate mi_zalloc(size_t size) 1635*7c478bd9Sstevel@tonic-gate { 1636*7c478bd9Sstevel@tonic-gate IDP ptr; 1637*7c478bd9Sstevel@tonic-gate 1638*7c478bd9Sstevel@tonic-gate if (ptr = mi_alloc(size, BPRI_LO)) 1639*7c478bd9Sstevel@tonic-gate bzero(ptr, size); 1640*7c478bd9Sstevel@tonic-gate return (ptr); 1641*7c478bd9Sstevel@tonic-gate } 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate IDP 1644*7c478bd9Sstevel@tonic-gate mi_zalloc_sleep(size_t size) 1645*7c478bd9Sstevel@tonic-gate { 1646*7c478bd9Sstevel@tonic-gate IDP ptr; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate if (ptr = mi_alloc_sleep(size, BPRI_LO)) 1649*7c478bd9Sstevel@tonic-gate bzero(ptr, size); 1650*7c478bd9Sstevel@tonic-gate return (ptr); 1651*7c478bd9Sstevel@tonic-gate } 1652