17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*f4b3ec61Sdh155122 * Common Development and Distribution License (the "License"). 6*f4b3ec61Sdh155122 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*f4b3ec61Sdh155122 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1990 Mentat Inc. */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <inet/common.h> /* for various inet/mi.h and inet/nd.h needs */ 317c478bd9Sstevel@tonic-gate #include <sys/stream.h> 327c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 337c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 357c478bd9Sstevel@tonic-gate #include <inet/nd.h> 367c478bd9Sstevel@tonic-gate #include <inet/mi.h> 377c478bd9Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 387c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 397c478bd9Sstevel@tonic-gate #include <sys/timod.h> 407c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 417c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 427c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 437c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 447c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 457c478bd9Sstevel@tonic-gate #include <sys/suntpi.h> 467c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 477c478bd9Sstevel@tonic-gate #include <sys/debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') 517c478bd9Sstevel@tonic-gate #define ISUPPER(ch) ((ch) >= 'A' && (ch) <= 'Z') 527c478bd9Sstevel@tonic-gate #define tolower(ch) ('a' + ((ch) - 'A')) 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define MI_IS_TRANSPARENT(mp) (mp->b_cont && \ 557c478bd9Sstevel@tonic-gate (mp->b_cont->b_rptr != mp->b_cont->b_wptr)) 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * NOTE: Whenever anything is allocated by mi_alloc or mi_alloc_sleep (below), 597c478bd9Sstevel@tonic-gate * the size of the requested allocation is increased by one word. This extra 607c478bd9Sstevel@tonic-gate * word is used to store the size of the object being allocated, and is located 617c478bd9Sstevel@tonic-gate * at the beginning of the allocated block. The pointer returned to the caller 627c478bd9Sstevel@tonic-gate * is a pointer to the *second* word in the newly-allocated block. The IP 637c478bd9Sstevel@tonic-gate * module of mdb is aware of this, and will need to be changed if this 647c478bd9Sstevel@tonic-gate * allocation strategy is changed. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate typedef struct stroptions *STROPTP; 687c478bd9Sstevel@tonic-gate typedef union T_primitives *TPRIMP; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* Timer block states. */ 717c478bd9Sstevel@tonic-gate #define TB_RUNNING 1 727c478bd9Sstevel@tonic-gate #define TB_IDLE 2 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Could not stop/free before putq 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate #define TB_RESCHED 3 /* mtb_time_left contains tick count */ 777c478bd9Sstevel@tonic-gate #define TB_CANCELLED 4 787c478bd9Sstevel@tonic-gate #define TB_TO_BE_FREED 5 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate typedef struct mtb_s { 817c478bd9Sstevel@tonic-gate int mtb_state; 827c478bd9Sstevel@tonic-gate timeout_id_t mtb_tid; 837c478bd9Sstevel@tonic-gate queue_t *mtb_q; 847c478bd9Sstevel@tonic-gate MBLKP mtb_mp; 857c478bd9Sstevel@tonic-gate clock_t mtb_time_left; 867c478bd9Sstevel@tonic-gate } MTB, *MTBP; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static int mi_timer_fire(MTBP); 897c478bd9Sstevel@tonic-gate static int mi_iprintf(char *, va_list, pfi_t, char *); 907c478bd9Sstevel@tonic-gate static void mi_tpi_addr_and_opt(MBLKP, char *, t_scalar_t, char *, t_scalar_t); 917c478bd9Sstevel@tonic-gate static MBLKP mi_tpi_trailer_alloc(MBLKP, size_t, t_scalar_t); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 947c478bd9Sstevel@tonic-gate void * 957c478bd9Sstevel@tonic-gate mi_alloc(size_t size, uint_t pri) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate size_t *ptr; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate size += sizeof (size); 1007c478bd9Sstevel@tonic-gate if (ptr = kmem_alloc(size, KM_NOSLEEP)) { 1017c478bd9Sstevel@tonic-gate *ptr = size; 1027c478bd9Sstevel@tonic-gate return (ptr + 1); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate return (NULL); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 1087c478bd9Sstevel@tonic-gate void * 1097c478bd9Sstevel@tonic-gate mi_alloc_sleep(size_t size, uint_t pri) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate size_t *ptr; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate size += sizeof (size); 1147c478bd9Sstevel@tonic-gate ptr = kmem_alloc(size, KM_SLEEP); 1157c478bd9Sstevel@tonic-gate *ptr = size; 1167c478bd9Sstevel@tonic-gate return (ptr + 1); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int 1207c478bd9Sstevel@tonic-gate mi_close_comm(void **mi_headp, queue_t *q) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate IDP ptr; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate ptr = q->q_ptr; 1257c478bd9Sstevel@tonic-gate mi_close_unlink(mi_headp, ptr); 1267c478bd9Sstevel@tonic-gate mi_close_free(ptr); 1277c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 1287c478bd9Sstevel@tonic-gate return (0); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate void 1327c478bd9Sstevel@tonic-gate mi_close_unlink(void **mi_headp, IDP ptr) 1337c478bd9Sstevel@tonic-gate { 1347c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 1357c478bd9Sstevel@tonic-gate MI_OP mi_o; 1367c478bd9Sstevel@tonic-gate dev_t dev; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 1397c478bd9Sstevel@tonic-gate if (!mi_o) 1407c478bd9Sstevel@tonic-gate return; 1417c478bd9Sstevel@tonic-gate mi_o--; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (mi_o->mi_o_next == NULL) { 1447c478bd9Sstevel@tonic-gate /* Not in list */ 1457c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev == NULL); 1467c478bd9Sstevel@tonic-gate return; 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* Free minor number */ 1507c478bd9Sstevel@tonic-gate dev = mi_o->mi_o_dev; 1517c478bd9Sstevel@tonic-gate if ((dev != OPENFAIL) && (dev != 0) && (dev <= MAXMIN)) 1527c478bd9Sstevel@tonic-gate inet_minor_free(mi_head->mh_arena, dev); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* Unlink from list */ 1557c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next != NULL); 1567c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev != NULL); 1577c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next->mi_o_prev == mi_o); 1587c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_prev->mi_o_next == mi_o); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate mi_o->mi_o_next->mi_o_prev = mi_o->mi_o_prev; 1617c478bd9Sstevel@tonic-gate mi_o->mi_o_prev->mi_o_next = mi_o->mi_o_next; 1627c478bd9Sstevel@tonic-gate mi_o->mi_o_next = mi_o->mi_o_prev = NULL; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate mi_o->mi_o_dev = (dev_t)OPENFAIL; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* If list now empty free the list head */ 1677c478bd9Sstevel@tonic-gate if (mi_head->mh_o.mi_o_next == &mi_head->mh_o) { 1687c478bd9Sstevel@tonic-gate ASSERT(mi_head->mh_o.mi_o_prev == &mi_head->mh_o); 1697c478bd9Sstevel@tonic-gate if (mi_head->mh_arena != NULL) 1707c478bd9Sstevel@tonic-gate inet_minor_destroy(mi_head->mh_arena); 1717c478bd9Sstevel@tonic-gate mi_free((IDP)mi_head); 1727c478bd9Sstevel@tonic-gate *mi_headp = NULL; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate void 1777c478bd9Sstevel@tonic-gate mi_close_free(IDP ptr) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate MI_OP mi_o; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 1827c478bd9Sstevel@tonic-gate if (!mi_o) 1837c478bd9Sstevel@tonic-gate return; 1847c478bd9Sstevel@tonic-gate mi_o--; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate ASSERT(mi_o->mi_o_next == NULL && mi_o->mi_o_prev == NULL); 1877c478bd9Sstevel@tonic-gate mi_free((IDP)mi_o); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * mi_copyin - takes care of transparent or non-transparent ioctl for the 1927c478bd9Sstevel@tonic-gate * calling function so that they have to deal with just M_IOCDATA type 1937c478bd9Sstevel@tonic-gate * and not worry about M_COPYIN. 1947c478bd9Sstevel@tonic-gate * 1957c478bd9Sstevel@tonic-gate * mi_copyin checks to see if the ioctl is transparent or non transparent. 1967c478bd9Sstevel@tonic-gate * In case of a non_transparent ioctl, it packs the data into a M_IOCDATA 1977c478bd9Sstevel@tonic-gate * message and puts it back onto the current queue for further processing. 1987c478bd9Sstevel@tonic-gate * In case of transparent ioctl, it sends a M_COPYIN message up to the 1997c478bd9Sstevel@tonic-gate * streamhead so that a M_IOCDATA with the information comes back down. 2007c478bd9Sstevel@tonic-gate */ 2017c478bd9Sstevel@tonic-gate void 2027c478bd9Sstevel@tonic-gate mi_copyin(queue_t *q, MBLKP mp, char *uaddr, size_t len) 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2057c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr; 2067c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)mp->b_rptr; 2077c478bd9Sstevel@tonic-gate int err; 2087c478bd9Sstevel@tonic-gate MBLKP mp1; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCTL && !uaddr); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* A transparent ioctl. Send a M_COPYIN message to the streamhead. */ 2137c478bd9Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) { 2147c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 2157c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 2167c478bd9Sstevel@tonic-gate cq->cq_private = mp->b_cont; 2177c478bd9Sstevel@tonic-gate cq->cq_size = len; 2187c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 2197c478bd9Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 2207c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2217c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 2227c478bd9Sstevel@tonic-gate qreply(q, mp); 2237c478bd9Sstevel@tonic-gate return; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * A non-transparent ioctl. Need to convert into M_IOCDATA message. 2287c478bd9Sstevel@tonic-gate * 2297c478bd9Sstevel@tonic-gate * We allocate a 0 byte message block and put its address in 2307c478bd9Sstevel@tonic-gate * cp_private. It also makes the b_prev field = 1 and b_next 2317c478bd9Sstevel@tonic-gate * field = MI_COPY_IN for this 0 byte block. This is done to 2327c478bd9Sstevel@tonic-gate * maintain compatibility with old code in mi_copy_state 2337c478bd9Sstevel@tonic-gate * (which removes the empty block). 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate err = miocpullup(mp, len); 2367c478bd9Sstevel@tonic-gate if (err != 0) 2377c478bd9Sstevel@tonic-gate goto err_ret; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED); 2407c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 2417c478bd9Sstevel@tonic-gate err = ENOMEM; 2427c478bd9Sstevel@tonic-gate goto err_ret; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * Temporarily insert mp1 between the M_IOCTL and M_DATA blocks so 2477c478bd9Sstevel@tonic-gate * that we can use the MI_COPY_COUNT & MI_COPY_DIRECTION macros. 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate mp1->b_cont = mp->b_cont; 2507c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 2517c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 2527c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 2537c478bd9Sstevel@tonic-gate mp->b_cont = mp1->b_cont; 2547c478bd9Sstevel@tonic-gate mp1->b_cont = NULL; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Leave a pointer to the 0 byte block in cp_private field for 2587c478bd9Sstevel@tonic-gate * future use by the mi_copy_* routines. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA; 2617c478bd9Sstevel@tonic-gate cp->cp_private = mp1; 2627c478bd9Sstevel@tonic-gate cp->cp_rval = NULL; 2637c478bd9Sstevel@tonic-gate put(q, mp); 2647c478bd9Sstevel@tonic-gate return; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate err_ret: 2677c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 2687c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 2697c478bd9Sstevel@tonic-gate if (mp->b_cont) { 2707c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 2717c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 2747c478bd9Sstevel@tonic-gate qreply(q, mp); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Allows transparent IOCTLs to have multiple copyins. This is needed 2797c478bd9Sstevel@tonic-gate * for some variable-length structures, where the total size is only known 2807c478bd9Sstevel@tonic-gate * after the first part is copied in. Rather than setting MI_COPY_COUNT to 2817c478bd9Sstevel@tonic-gate * 1, as in mi_coypin(), it is simply incremented here. This value can 2827c478bd9Sstevel@tonic-gate * then be checked in the returned IOCBLK. 2837c478bd9Sstevel@tonic-gate * 2847c478bd9Sstevel@tonic-gate * As this deals with copyins that follow the initial copyin, the byte 2857c478bd9Sstevel@tonic-gate * offset into the user buffer from which copying should begin must be 2867c478bd9Sstevel@tonic-gate * passed in in the offset parameter. 2877c478bd9Sstevel@tonic-gate * 2887c478bd9Sstevel@tonic-gate * Unlike mi_coypin(), this function expects to be passed an mblk chain 2897c478bd9Sstevel@tonic-gate * headed by an M_IOCBLK, as that's the chain that will be in use for 2907c478bd9Sstevel@tonic-gate * copies after the first one (copies where n != 1). 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate void 2937c478bd9Sstevel@tonic-gate mi_copyin_n(queue_t *q, MBLKP mp, size_t offset, size_t len) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)mp->b_rptr; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_IOCDATA); 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp)++; 3007c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_IN; 3017c478bd9Sstevel@tonic-gate cq->cq_private = mp->b_cont; 3027c478bd9Sstevel@tonic-gate cq->cq_size = len; 3037c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 3047c478bd9Sstevel@tonic-gate bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 3057c478bd9Sstevel@tonic-gate cq->cq_addr += offset; 3067c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3077c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 3087c478bd9Sstevel@tonic-gate qreply(q, mp); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate void 3127c478bd9Sstevel@tonic-gate mi_copyout(queue_t *q, MBLKP mp) 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 3157c478bd9Sstevel@tonic-gate struct copyreq *cq = (struct copyreq *)iocp; 3167c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)cq; 3177c478bd9Sstevel@tonic-gate MBLKP mp1; 3187c478bd9Sstevel@tonic-gate MBLKP mp2; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type != M_IOCDATA || !mp->b_cont) { 3217c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, EPROTO); 3227c478bd9Sstevel@tonic-gate return; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate /* Check completion of previous copyout operation. */ 3257c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 3267c478bd9Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval || !mp1->b_cont) { 3277c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 3287c478bd9Sstevel@tonic-gate return; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate if (!mp1->b_cont->b_cont && !MI_IS_TRANSPARENT(mp)) { 3317c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 3327c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 3337c478bd9Sstevel@tonic-gate mp->b_cont = mp1->b_cont; 3347c478bd9Sstevel@tonic-gate freeb(mp1); 3357c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 3367c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 3377c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 3387c478bd9Sstevel@tonic-gate iocp->ioc_count = mp1->b_wptr - mp1->b_rptr; 3397c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; 3407c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 3417c478bd9Sstevel@tonic-gate qreply(q, mp); 3427c478bd9Sstevel@tonic-gate return; 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate if (MI_COPY_DIRECTION(mp) == MI_COPY_IN) { 3457c478bd9Sstevel@tonic-gate /* Set up for first copyout. */ 3467c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 3477c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 1; 3487c478bd9Sstevel@tonic-gate } else { 3497c478bd9Sstevel@tonic-gate ++MI_COPY_COUNT(mp); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate cq->cq_private = mp1; 3527c478bd9Sstevel@tonic-gate /* Find message preceding last. */ 3537c478bd9Sstevel@tonic-gate for (mp2 = mp1; mp2->b_cont->b_cont; mp2 = mp2->b_cont) 3547c478bd9Sstevel@tonic-gate ; 3557c478bd9Sstevel@tonic-gate if (mp2 == mp1) 3567c478bd9Sstevel@tonic-gate bcopy((char *)mp1->b_rptr, (char *)&cq->cq_addr, 3577c478bd9Sstevel@tonic-gate sizeof (cq->cq_addr)); 3587c478bd9Sstevel@tonic-gate else 3597c478bd9Sstevel@tonic-gate cq->cq_addr = (char *)mp2->b_cont->b_next; 3607c478bd9Sstevel@tonic-gate mp1 = mp2->b_cont; 3617c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 3627c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 3637c478bd9Sstevel@tonic-gate mp2->b_cont = NULL; 3647c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 3657c478bd9Sstevel@tonic-gate cq->cq_size = mp1->b_wptr - mp1->b_rptr; 3667c478bd9Sstevel@tonic-gate cq->cq_flag = 0; 3677c478bd9Sstevel@tonic-gate qreply(q, mp); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate MBLKP 3717c478bd9Sstevel@tonic-gate mi_copyout_alloc(queue_t *q, MBLKP mp, char *uaddr, size_t len, 3727c478bd9Sstevel@tonic-gate boolean_t free_on_error) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 3757c478bd9Sstevel@tonic-gate MBLKP mp1; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) { 3787c478bd9Sstevel@tonic-gate if (iocp->ioc_count != TRANSPARENT) { 3797c478bd9Sstevel@tonic-gate mp1 = allocb(0, BPRI_MED); 3807c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 3817c478bd9Sstevel@tonic-gate if (free_on_error) { 3827c478bd9Sstevel@tonic-gate iocp->ioc_error = ENOMEM; 3837c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 3847c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 3857c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3867c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 3877c478bd9Sstevel@tonic-gate qreply(q, mp); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate return (NULL); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate mp1->b_cont = mp->b_cont; 3927c478bd9Sstevel@tonic-gate mp->b_cont = mp1; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate MI_COPY_COUNT(mp) = 0; 3957c478bd9Sstevel@tonic-gate MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 3967c478bd9Sstevel@tonic-gate /* Make sure it looks clean to mi_copyout. */ 3977c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCDATA; 3987c478bd9Sstevel@tonic-gate ((struct copyresp *)iocp)->cp_rval = NULL; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate mp1 = allocb(len, BPRI_MED); 4017c478bd9Sstevel@tonic-gate if (mp1 == NULL) { 4027c478bd9Sstevel@tonic-gate if (free_on_error) 4037c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM); 4047c478bd9Sstevel@tonic-gate return (NULL); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate linkb(mp, mp1); 4077c478bd9Sstevel@tonic-gate mp1->b_next = (MBLKP)uaddr; 4087c478bd9Sstevel@tonic-gate return (mp1); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate void 4127c478bd9Sstevel@tonic-gate mi_copy_done(queue_t *q, MBLKP mp, int err) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate struct iocblk *iocp; 4157c478bd9Sstevel@tonic-gate MBLKP mp1; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate if (!mp) 4187c478bd9Sstevel@tonic-gate return; 4197c478bd9Sstevel@tonic-gate if (!q || (mp->b_wptr - mp->b_rptr) < sizeof (struct iocblk)) { 4207c478bd9Sstevel@tonic-gate freemsg(mp); 4217c478bd9Sstevel@tonic-gate return; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 4247c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 4257c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 4287c478bd9Sstevel@tonic-gate if ((mp1 = mp->b_cont) != NULL) { 4297c478bd9Sstevel@tonic-gate for (; mp1; mp1 = mp1->b_cont) { 4307c478bd9Sstevel@tonic-gate mp1->b_prev = NULL; 4317c478bd9Sstevel@tonic-gate mp1->b_next = NULL; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 4347c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate qreply(q, mp); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate int 4407c478bd9Sstevel@tonic-gate mi_copy_state(queue_t *q, MBLKP mp, MBLKP *mpp) 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 4437c478bd9Sstevel@tonic-gate struct copyresp *cp = (struct copyresp *)iocp; 4447c478bd9Sstevel@tonic-gate MBLKP mp1; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate mp1 = mp->b_cont; 4477c478bd9Sstevel@tonic-gate mp->b_cont = cp->cp_private; 4487c478bd9Sstevel@tonic-gate if (mp1) { 4497c478bd9Sstevel@tonic-gate if (mp1->b_cont && !pullupmsg(mp1, -1)) { 4507c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, ENOMEM); 4517c478bd9Sstevel@tonic-gate return (-1); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate linkb(mp->b_cont, mp1); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate if ((int)(uintptr_t)cp->cp_rval) { 4567c478bd9Sstevel@tonic-gate mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 4577c478bd9Sstevel@tonic-gate return (-1); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate if (mpp && MI_COPY_DIRECTION(mp) == MI_COPY_IN) 4607c478bd9Sstevel@tonic-gate *mpp = mp1; 4617c478bd9Sstevel@tonic-gate return (MI_COPY_STATE(mp)); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate void 4657c478bd9Sstevel@tonic-gate mi_free(void *ptr) 4667c478bd9Sstevel@tonic-gate { 4677c478bd9Sstevel@tonic-gate size_t size; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (!ptr) 4707c478bd9Sstevel@tonic-gate return; 4717c478bd9Sstevel@tonic-gate if ((size = ((size_t *)ptr)[-1]) <= 0) 4727c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "mi_free"); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate kmem_free((void *) ((size_t *)ptr - 1), size); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate static int 4787c478bd9Sstevel@tonic-gate mi_iprintf(char *fmt, va_list ap, pfi_t putc_func, char *cookie) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate int base; 4817c478bd9Sstevel@tonic-gate char buf[(sizeof (long) * 3) + 1]; 4827c478bd9Sstevel@tonic-gate static char hex_val[] = "0123456789abcdef"; 4837c478bd9Sstevel@tonic-gate int ch; 4847c478bd9Sstevel@tonic-gate int count; 4857c478bd9Sstevel@tonic-gate char *cp1; 4867c478bd9Sstevel@tonic-gate int digits; 4877c478bd9Sstevel@tonic-gate char *fcp; 4887c478bd9Sstevel@tonic-gate boolean_t is_long; 4897c478bd9Sstevel@tonic-gate ulong_t uval; 4907c478bd9Sstevel@tonic-gate long val; 4917c478bd9Sstevel@tonic-gate boolean_t zero_filled; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate if (!fmt) 4947c478bd9Sstevel@tonic-gate return (-1); 4957c478bd9Sstevel@tonic-gate count = 0; 4967c478bd9Sstevel@tonic-gate while (*fmt) { 4977c478bd9Sstevel@tonic-gate if (*fmt != '%' || *++fmt == '%') { 4987c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++); 4997c478bd9Sstevel@tonic-gate continue; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate if (*fmt == '0') { 5027c478bd9Sstevel@tonic-gate zero_filled = B_TRUE; 5037c478bd9Sstevel@tonic-gate fmt++; 5047c478bd9Sstevel@tonic-gate if (!*fmt) 5057c478bd9Sstevel@tonic-gate break; 5067c478bd9Sstevel@tonic-gate } else 5077c478bd9Sstevel@tonic-gate zero_filled = B_FALSE; 5087c478bd9Sstevel@tonic-gate base = 0; 5097c478bd9Sstevel@tonic-gate for (digits = 0; ISDIGIT(*fmt); fmt++) { 5107c478bd9Sstevel@tonic-gate digits *= 10; 5117c478bd9Sstevel@tonic-gate digits += (*fmt - '0'); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate if (!*fmt) 5147c478bd9Sstevel@tonic-gate break; 5157c478bd9Sstevel@tonic-gate is_long = B_FALSE; 5167c478bd9Sstevel@tonic-gate if (*fmt == 'l') { 5177c478bd9Sstevel@tonic-gate is_long = B_TRUE; 5187c478bd9Sstevel@tonic-gate fmt++; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate if (!*fmt) 5217c478bd9Sstevel@tonic-gate break; 5227c478bd9Sstevel@tonic-gate ch = *fmt++; 5237c478bd9Sstevel@tonic-gate if (ISUPPER(ch)) { 5247c478bd9Sstevel@tonic-gate ch = tolower(ch); 5257c478bd9Sstevel@tonic-gate is_long = B_TRUE; 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate switch (ch) { 5287c478bd9Sstevel@tonic-gate case 'c': 5297c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, va_arg(ap, int *)); 5307c478bd9Sstevel@tonic-gate continue; 5317c478bd9Sstevel@tonic-gate case 'd': 5327c478bd9Sstevel@tonic-gate base = 10; 5337c478bd9Sstevel@tonic-gate break; 5347c478bd9Sstevel@tonic-gate case 'm': /* Print out memory, 2 hex chars per byte */ 5357c478bd9Sstevel@tonic-gate if (is_long) 5367c478bd9Sstevel@tonic-gate fcp = va_arg(ap, char *); 5377c478bd9Sstevel@tonic-gate else { 5387c478bd9Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL) 5397c478bd9Sstevel@tonic-gate fcp = (char *)cp1; 5407c478bd9Sstevel@tonic-gate else 5417c478bd9Sstevel@tonic-gate fcp = NULL; 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate if (!fcp) { 5447c478bd9Sstevel@tonic-gate for (fcp = (char *)"(NULL)"; *fcp; fcp++) 5457c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp); 5467c478bd9Sstevel@tonic-gate } else { 5477c478bd9Sstevel@tonic-gate while (digits--) { 5487c478bd9Sstevel@tonic-gate int u1 = *fcp++ & 0xFF; 5497c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, 5507c478bd9Sstevel@tonic-gate hex_val[(u1>>4)& 0xF]); 5517c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, 5527c478bd9Sstevel@tonic-gate hex_val[u1& 0xF]); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate continue; 5567c478bd9Sstevel@tonic-gate case 'o': 5577c478bd9Sstevel@tonic-gate base = 8; 5587c478bd9Sstevel@tonic-gate break; 5597c478bd9Sstevel@tonic-gate case 'p': 5607c478bd9Sstevel@tonic-gate is_long = B_TRUE; 5617c478bd9Sstevel@tonic-gate /* FALLTHRU */ 5627c478bd9Sstevel@tonic-gate case 'x': 5637c478bd9Sstevel@tonic-gate base = 16; 5647c478bd9Sstevel@tonic-gate break; 5657c478bd9Sstevel@tonic-gate case 's': 5667c478bd9Sstevel@tonic-gate if (is_long) 5677c478bd9Sstevel@tonic-gate fcp = va_arg(ap, char *); 5687c478bd9Sstevel@tonic-gate else { 5697c478bd9Sstevel@tonic-gate if ((cp1 = va_arg(ap, char *)) != NULL) 5707c478bd9Sstevel@tonic-gate fcp = (char *)cp1; 5717c478bd9Sstevel@tonic-gate else 5727c478bd9Sstevel@tonic-gate fcp = NULL; 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate if (!fcp) 5757c478bd9Sstevel@tonic-gate fcp = (char *)"(NULL)"; 5767c478bd9Sstevel@tonic-gate while (*fcp) { 5777c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fcp++); 5787c478bd9Sstevel@tonic-gate if (digits && --digits == 0) 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate while (digits > 0) { 5827c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, ' '); 5837c478bd9Sstevel@tonic-gate digits--; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate continue; 5867c478bd9Sstevel@tonic-gate case 'u': 5877c478bd9Sstevel@tonic-gate base = 10; 5887c478bd9Sstevel@tonic-gate break; 5897c478bd9Sstevel@tonic-gate default: 5907c478bd9Sstevel@tonic-gate return (count); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate if (is_long) 5937c478bd9Sstevel@tonic-gate val = va_arg(ap, long); 5947c478bd9Sstevel@tonic-gate else 5957c478bd9Sstevel@tonic-gate val = va_arg(ap, int); 5967c478bd9Sstevel@tonic-gate if (base == 10 && ch != 'u') { 5977c478bd9Sstevel@tonic-gate if (val < 0) { 5987c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, '-'); 5997c478bd9Sstevel@tonic-gate val = -val; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate uval = val; 6027c478bd9Sstevel@tonic-gate } else { 6037c478bd9Sstevel@tonic-gate if (is_long) 6047c478bd9Sstevel@tonic-gate uval = val; 6057c478bd9Sstevel@tonic-gate else 6067c478bd9Sstevel@tonic-gate uval = (uint_t)val; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate /* Hand overload/restore the register variable 'fmt' */ 6097c478bd9Sstevel@tonic-gate cp1 = fmt; 6107c478bd9Sstevel@tonic-gate fmt = A_END(buf); 6117c478bd9Sstevel@tonic-gate *--fmt = '\0'; 6127c478bd9Sstevel@tonic-gate do { 6137c478bd9Sstevel@tonic-gate if (fmt > buf) 6147c478bd9Sstevel@tonic-gate *--fmt = hex_val[uval % base]; 6157c478bd9Sstevel@tonic-gate if (digits && --digits == 0) 6167c478bd9Sstevel@tonic-gate break; 6177c478bd9Sstevel@tonic-gate } while (uval /= base); 6187c478bd9Sstevel@tonic-gate if (zero_filled) { 6197c478bd9Sstevel@tonic-gate while (digits > 0 && fmt > buf) { 6207c478bd9Sstevel@tonic-gate *--fmt = '0'; 6217c478bd9Sstevel@tonic-gate digits--; 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate while (*fmt) 6257c478bd9Sstevel@tonic-gate count += (*putc_func)(cookie, *fmt++); 6267c478bd9Sstevel@tonic-gate fmt = cp1; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate return (count); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* PRINTFLIKE2 */ 6327c478bd9Sstevel@tonic-gate int 6337c478bd9Sstevel@tonic-gate mi_mpprintf(MBLKP mp, char *fmt, ...) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate va_list ap; 6367c478bd9Sstevel@tonic-gate int count = -1; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate va_start(ap, fmt); 6397c478bd9Sstevel@tonic-gate if (mp) { 6407c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 6417c478bd9Sstevel@tonic-gate (char *)mp); 6427c478bd9Sstevel@tonic-gate if (count != -1) 6437c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0'); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate va_end(ap); 6467c478bd9Sstevel@tonic-gate return (count); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* PRINTFLIKE2 */ 6507c478bd9Sstevel@tonic-gate int 6517c478bd9Sstevel@tonic-gate mi_mpprintf_nr(MBLKP mp, char *fmt, ...) 6527c478bd9Sstevel@tonic-gate { 6537c478bd9Sstevel@tonic-gate va_list ap; 6547c478bd9Sstevel@tonic-gate int count = -1; 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate va_start(ap, fmt); 6577c478bd9Sstevel@tonic-gate if (mp) { 6587c478bd9Sstevel@tonic-gate (void) adjmsg(mp, -1); 6597c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 6607c478bd9Sstevel@tonic-gate (char *)mp); 6617c478bd9Sstevel@tonic-gate if (count != -1) 6627c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp, '\0'); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate va_end(ap); 6657c478bd9Sstevel@tonic-gate return (count); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate int 6697c478bd9Sstevel@tonic-gate mi_mpprintf_putc(char *cookie, int ch) 6707c478bd9Sstevel@tonic-gate { 6717c478bd9Sstevel@tonic-gate MBLKP mp = (MBLKP)cookie; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate while (mp->b_cont) 6747c478bd9Sstevel@tonic-gate mp = mp->b_cont; 6757c478bd9Sstevel@tonic-gate if (mp->b_wptr >= mp->b_datap->db_lim) { 6767c478bd9Sstevel@tonic-gate mp->b_cont = allocb(1024, BPRI_HI); 6777c478bd9Sstevel@tonic-gate mp = mp->b_cont; 6787c478bd9Sstevel@tonic-gate if (!mp) 6797c478bd9Sstevel@tonic-gate return (0); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate *mp->b_wptr++ = (unsigned char)ch; 6827c478bd9Sstevel@tonic-gate return (1); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate IDP 6867c478bd9Sstevel@tonic-gate mi_first_ptr(void **mi_headp) 6877c478bd9Sstevel@tonic-gate { 6887c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 6897c478bd9Sstevel@tonic-gate MI_OP mi_op; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next; 6927c478bd9Sstevel@tonic-gate if (mi_op && mi_op != &mi_head->mh_o) 6937c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 6947c478bd9Sstevel@tonic-gate return (NULL); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* 6987c478bd9Sstevel@tonic-gate * Clients can choose to have both module instances and device instances 6997c478bd9Sstevel@tonic-gate * in the same list. Return the first device instance in the list. 7007c478bd9Sstevel@tonic-gate */ 7017c478bd9Sstevel@tonic-gate IDP 7027c478bd9Sstevel@tonic-gate mi_first_dev_ptr(void **mi_headp) 7037c478bd9Sstevel@tonic-gate { 7047c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 7057c478bd9Sstevel@tonic-gate MI_OP mi_op; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate mi_op = mi_head->mh_o.mi_o_next; 7087c478bd9Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 7097c478bd9Sstevel@tonic-gate if (mi_op->mi_o_isdev) 7107c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 7117c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate return (NULL); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate IDP 7177c478bd9Sstevel@tonic-gate mi_next_ptr(void **mi_headp, IDP ptr) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 7207c478bd9Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if ((mi_op = mi_op->mi_o_next) != NULL && mi_op != &mi_head->mh_o) 7237c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 7247c478bd9Sstevel@tonic-gate return (NULL); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate /* 7287c478bd9Sstevel@tonic-gate * Clients can choose to have both module instances and device instances 7297c478bd9Sstevel@tonic-gate * in the same list. Return the next device instance in the list. 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate IDP 7327c478bd9Sstevel@tonic-gate mi_next_dev_ptr(void **mi_headp, IDP ptr) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 7357c478bd9Sstevel@tonic-gate MI_OP mi_op = ((MI_OP)ptr) - 1; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 7387c478bd9Sstevel@tonic-gate while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 7397c478bd9Sstevel@tonic-gate if (mi_op->mi_o_isdev) 7407c478bd9Sstevel@tonic-gate return ((IDP)&mi_op[1]); 7417c478bd9Sstevel@tonic-gate mi_op = mi_op->mi_o_next; 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate return (NULL); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * Self clone the device 7487c478bd9Sstevel@tonic-gate * XXX - should we still support clone device 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate /* ARGSUSED4 */ 7517c478bd9Sstevel@tonic-gate int 7527c478bd9Sstevel@tonic-gate mi_open_comm(void **mi_headp, size_t size, queue_t *q, dev_t *devp, 7537c478bd9Sstevel@tonic-gate int flag, int sflag, cred_t *credp) 7547c478bd9Sstevel@tonic-gate { 7557c478bd9Sstevel@tonic-gate int error; 7567c478bd9Sstevel@tonic-gate IDP ptr; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) 7597c478bd9Sstevel@tonic-gate return (0); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate ptr = mi_open_alloc_sleep(size); 7627c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = ptr; 7637c478bd9Sstevel@tonic-gate error = mi_open_link(mi_headp, ptr, devp, flag, sflag, credp); 7647c478bd9Sstevel@tonic-gate if (error != 0) { 7657c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 7667c478bd9Sstevel@tonic-gate mi_close_free(ptr); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate return (error); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate IDP 7727c478bd9Sstevel@tonic-gate mi_open_alloc_sleep(size_t size) 7737c478bd9Sstevel@tonic-gate { 7747c478bd9Sstevel@tonic-gate MI_OP mi_o; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O))) 7777c478bd9Sstevel@tonic-gate return (NULL); 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate mi_o = (MI_OP)mi_zalloc_sleep(size + sizeof (MI_O)); 7807c478bd9Sstevel@tonic-gate mi_o++; 7817c478bd9Sstevel@tonic-gate return ((IDP)mi_o); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate IDP 7857c478bd9Sstevel@tonic-gate mi_open_alloc(size_t size) 7867c478bd9Sstevel@tonic-gate { 7877c478bd9Sstevel@tonic-gate MI_OP mi_o; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (size > (UINT_MAX - sizeof (MI_O))) 7907c478bd9Sstevel@tonic-gate return (NULL); 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if ((mi_o = (MI_OP)mi_zalloc(size + sizeof (MI_O))) == NULL) 7937c478bd9Sstevel@tonic-gate return (NULL); 7947c478bd9Sstevel@tonic-gate mi_o++; 7957c478bd9Sstevel@tonic-gate return ((IDP)mi_o); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * MODOPEN means just link in without respect of mi_o_dev. 8007c478bd9Sstevel@tonic-gate * A NULL devp can be used to create a detached instance 8017c478bd9Sstevel@tonic-gate * Otherwise self-clone the device. 8027c478bd9Sstevel@tonic-gate */ 8037c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 8047c478bd9Sstevel@tonic-gate int 8057c478bd9Sstevel@tonic-gate mi_open_link(void **mi_headp, IDP ptr, dev_t *devp, int flag, int sflag, 8067c478bd9Sstevel@tonic-gate cred_t *credp) 8077c478bd9Sstevel@tonic-gate { 8087c478bd9Sstevel@tonic-gate mi_head_t *mi_head = *(mi_head_t **)mi_headp; 8097c478bd9Sstevel@tonic-gate MI_OP insert; 8107c478bd9Sstevel@tonic-gate MI_OP mi_o; 8117c478bd9Sstevel@tonic-gate dev_t dev; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if (mi_head == NULL) { 8147c478bd9Sstevel@tonic-gate char arena_name[50]; 8157c478bd9Sstevel@tonic-gate char *head_name; 8167c478bd9Sstevel@tonic-gate ulong_t offset; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate head_name = kobj_getsymname((uintptr_t)mi_headp, &offset); 819*f4b3ec61Sdh155122 if (head_name != NULL && offset == 0) { 8207c478bd9Sstevel@tonic-gate (void) sprintf(arena_name, "%s_", head_name); 821*f4b3ec61Sdh155122 } else { 822*f4b3ec61Sdh155122 (void) sprintf(arena_name, "Hex0x%p_", 823*f4b3ec61Sdh155122 (void *)mi_headp); 824*f4b3ec61Sdh155122 } 8257c478bd9Sstevel@tonic-gate (void) sprintf(strchr(arena_name, '_') + 1, "minor"); 8267c478bd9Sstevel@tonic-gate mi_head = (mi_head_t *)mi_zalloc_sleep(sizeof (mi_head_t)); 8277c478bd9Sstevel@tonic-gate *mi_headp = (void *)mi_head; 8287c478bd9Sstevel@tonic-gate /* Setup doubly linked list */ 8297c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_next = &mi_head->mh_o; 8307c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_prev = &mi_head->mh_o; 8317c478bd9Sstevel@tonic-gate mi_head->mh_o.mi_o_dev = 0; /* For asserts only */ 8327c478bd9Sstevel@tonic-gate mi_head->mh_arena = (vmem_t *)inet_minor_create(arena_name, 8337c478bd9Sstevel@tonic-gate INET_MIN_DEV, KM_SLEEP); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate ASSERT(ptr != NULL); 8367c478bd9Sstevel@tonic-gate mi_o = (MI_OP)ptr; 8377c478bd9Sstevel@tonic-gate mi_o--; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (sflag == MODOPEN) { 8407c478bd9Sstevel@tonic-gate devp = NULL; 8417c478bd9Sstevel@tonic-gate /* 8427c478bd9Sstevel@tonic-gate * Set device number to MAXMIN + incrementing number. 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate dev = MAXMIN + ++mi_head->mh_module_dev; 8457c478bd9Sstevel@tonic-gate /* check for wraparound */ 8467c478bd9Sstevel@tonic-gate if (dev <= MAXMIN) { 8477c478bd9Sstevel@tonic-gate dev = MAXMIN + 1; 8487c478bd9Sstevel@tonic-gate mi_head->mh_module_dev = 1; 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate } else if (devp == NULL) { 8517c478bd9Sstevel@tonic-gate /* Detached open */ 8527c478bd9Sstevel@tonic-gate dev = (dev_t)OPENFAIL; 8537c478bd9Sstevel@tonic-gate } else if ((dev = inet_minor_alloc(mi_head->mh_arena)) == 0) { 8547c478bd9Sstevel@tonic-gate return (EBUSY); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate mi_o->mi_o_dev = dev; 8587c478bd9Sstevel@tonic-gate insert = (&mi_head->mh_o); 8597c478bd9Sstevel@tonic-gate mi_o->mi_o_next = insert; 8607c478bd9Sstevel@tonic-gate insert->mi_o_prev->mi_o_next = mi_o; 8617c478bd9Sstevel@tonic-gate mi_o->mi_o_prev = insert->mi_o_prev; 8627c478bd9Sstevel@tonic-gate insert->mi_o_prev = mi_o; 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (sflag == MODOPEN) 8657c478bd9Sstevel@tonic-gate mi_o->mi_o_isdev = B_FALSE; 8667c478bd9Sstevel@tonic-gate else 8677c478bd9Sstevel@tonic-gate mi_o->mi_o_isdev = B_TRUE; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate if (devp) 8707c478bd9Sstevel@tonic-gate *devp = makedevice(getemajor(*devp), (minor_t)dev); 8717c478bd9Sstevel@tonic-gate return (0); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate uint8_t * 8757c478bd9Sstevel@tonic-gate mi_offset_param(mblk_t *mp, size_t offset, size_t len) 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate size_t msg_len; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate if (!mp) 8807c478bd9Sstevel@tonic-gate return (NULL); 8817c478bd9Sstevel@tonic-gate msg_len = mp->b_wptr - mp->b_rptr; 8827c478bd9Sstevel@tonic-gate if (msg_len == 0 || offset > msg_len || len > msg_len || 8837c478bd9Sstevel@tonic-gate (offset + len) > msg_len || len == 0) 8847c478bd9Sstevel@tonic-gate return (NULL); 8857c478bd9Sstevel@tonic-gate return (&mp->b_rptr[offset]); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate uint8_t * 8897c478bd9Sstevel@tonic-gate mi_offset_paramc(mblk_t *mp, size_t offset, size_t len) 8907c478bd9Sstevel@tonic-gate { 8917c478bd9Sstevel@tonic-gate uint8_t *param; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate for (; mp; mp = mp->b_cont) { 8947c478bd9Sstevel@tonic-gate int type = mp->b_datap->db_type; 8957c478bd9Sstevel@tonic-gate if (datamsg(type)) { 8967c478bd9Sstevel@tonic-gate if (param = mi_offset_param(mp, offset, len)) 8977c478bd9Sstevel@tonic-gate return (param); 8987c478bd9Sstevel@tonic-gate if (offset < mp->b_wptr - mp->b_rptr) 8997c478bd9Sstevel@tonic-gate break; 9007c478bd9Sstevel@tonic-gate offset -= mp->b_wptr - mp->b_rptr; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate return (NULL); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate boolean_t 9087c478bd9Sstevel@tonic-gate mi_set_sth_hiwat(queue_t *q, size_t size) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate MBLKP mp; 9117c478bd9Sstevel@tonic-gate STROPTP stropt; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 9147c478bd9Sstevel@tonic-gate return (B_FALSE); 9157c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 9167c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 9177c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 9187c478bd9Sstevel@tonic-gate stropt->so_flags = SO_HIWAT; 9197c478bd9Sstevel@tonic-gate stropt->so_hiwat = size; 9207c478bd9Sstevel@tonic-gate putnext(q, mp); 9217c478bd9Sstevel@tonic-gate return (B_TRUE); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate boolean_t 9257c478bd9Sstevel@tonic-gate mi_set_sth_lowat(queue_t *q, size_t size) 9267c478bd9Sstevel@tonic-gate { 9277c478bd9Sstevel@tonic-gate MBLKP mp; 9287c478bd9Sstevel@tonic-gate STROPTP stropt; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 9317c478bd9Sstevel@tonic-gate return (B_FALSE); 9327c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 9337c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 9347c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 9357c478bd9Sstevel@tonic-gate stropt->so_flags = SO_LOWAT; 9367c478bd9Sstevel@tonic-gate stropt->so_lowat = size; 9377c478bd9Sstevel@tonic-gate putnext(q, mp); 9387c478bd9Sstevel@tonic-gate return (B_TRUE); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9427c478bd9Sstevel@tonic-gate boolean_t 9437c478bd9Sstevel@tonic-gate mi_set_sth_maxblk(queue_t *q, ssize_t size) 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate MBLKP mp; 9467c478bd9Sstevel@tonic-gate STROPTP stropt; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 9497c478bd9Sstevel@tonic-gate return (B_FALSE); 9507c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 9517c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 9527c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 9537c478bd9Sstevel@tonic-gate stropt->so_flags = SO_MAXBLK; 9547c478bd9Sstevel@tonic-gate stropt->so_maxblk = size; 9557c478bd9Sstevel@tonic-gate putnext(q, mp); 9567c478bd9Sstevel@tonic-gate return (B_TRUE); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate boolean_t 9607c478bd9Sstevel@tonic-gate mi_set_sth_copyopt(queue_t *q, int copyopt) 9617c478bd9Sstevel@tonic-gate { 9627c478bd9Sstevel@tonic-gate MBLKP mp; 9637c478bd9Sstevel@tonic-gate STROPTP stropt; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 9667c478bd9Sstevel@tonic-gate return (B_FALSE); 9677c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 9687c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 9697c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 9707c478bd9Sstevel@tonic-gate stropt->so_flags = SO_COPYOPT; 9717c478bd9Sstevel@tonic-gate stropt->so_copyopt = (ushort_t)copyopt; 9727c478bd9Sstevel@tonic-gate putnext(q, mp); 9737c478bd9Sstevel@tonic-gate return (B_TRUE); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate boolean_t 9777c478bd9Sstevel@tonic-gate mi_set_sth_wroff(queue_t *q, size_t size) 9787c478bd9Sstevel@tonic-gate { 9797c478bd9Sstevel@tonic-gate MBLKP mp; 9807c478bd9Sstevel@tonic-gate STROPTP stropt; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 9837c478bd9Sstevel@tonic-gate return (B_FALSE); 9847c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_SETOPTS; 9857c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (*stropt); 9867c478bd9Sstevel@tonic-gate stropt = (STROPTP)mp->b_rptr; 9877c478bd9Sstevel@tonic-gate stropt->so_flags = SO_WROFF; 9887c478bd9Sstevel@tonic-gate stropt->so_wroff = (ushort_t)size; 9897c478bd9Sstevel@tonic-gate putnext(q, mp); 9907c478bd9Sstevel@tonic-gate return (B_TRUE); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate int 9947c478bd9Sstevel@tonic-gate mi_sprintf(char *buf, char *fmt, ...) 9957c478bd9Sstevel@tonic-gate { 9967c478bd9Sstevel@tonic-gate va_list ap; 9977c478bd9Sstevel@tonic-gate int count = -1; 9987c478bd9Sstevel@tonic-gate va_start(ap, fmt); 9997c478bd9Sstevel@tonic-gate if (buf) { 10007c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, (pfi_t)mi_sprintf_putc, 10017c478bd9Sstevel@tonic-gate (char *)&buf); 10027c478bd9Sstevel@tonic-gate if (count != -1) 10037c478bd9Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&buf, '\0'); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate va_end(ap); 10067c478bd9Sstevel@tonic-gate return (count); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* Used to count without writing data */ 10107c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 10117c478bd9Sstevel@tonic-gate static int 10127c478bd9Sstevel@tonic-gate mi_sprintf_noop(char *cookie, int ch) 10137c478bd9Sstevel@tonic-gate { 10147c478bd9Sstevel@tonic-gate char **cpp = (char **)cookie; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate (*cpp)++; 10177c478bd9Sstevel@tonic-gate return (1); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate int 10217c478bd9Sstevel@tonic-gate mi_sprintf_putc(char *cookie, int ch) 10227c478bd9Sstevel@tonic-gate { 10237c478bd9Sstevel@tonic-gate char **cpp = (char **)cookie; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate **cpp = (char)ch; 10267c478bd9Sstevel@tonic-gate (*cpp)++; 10277c478bd9Sstevel@tonic-gate return (1); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate int 10317c478bd9Sstevel@tonic-gate mi_strcmp(const char *cp1, const char *cp2) 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate while (*cp1++ == *cp2++) { 10347c478bd9Sstevel@tonic-gate if (!cp2[-1]) 10357c478bd9Sstevel@tonic-gate return (0); 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate return ((uint_t)cp2[-1] & 0xFF) - ((uint_t)cp1[-1] & 0xFF); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate size_t 10417c478bd9Sstevel@tonic-gate mi_strlen(const char *str) 10427c478bd9Sstevel@tonic-gate { 10437c478bd9Sstevel@tonic-gate const char *cp = str; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate while (*cp != '\0') 10467c478bd9Sstevel@tonic-gate cp++; 10477c478bd9Sstevel@tonic-gate return ((int)(cp - str)); 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate int 10517c478bd9Sstevel@tonic-gate mi_strlog(queue_t *q, char level, ushort_t flags, char *fmt, ...) 10527c478bd9Sstevel@tonic-gate { 10537c478bd9Sstevel@tonic-gate va_list ap; 10547c478bd9Sstevel@tonic-gate char buf[200]; 10557c478bd9Sstevel@tonic-gate char *alloc_buf = buf; 10567c478bd9Sstevel@tonic-gate int count = -1; 10577c478bd9Sstevel@tonic-gate char *cp; 10587c478bd9Sstevel@tonic-gate short mid; 10597c478bd9Sstevel@tonic-gate int ret; 10607c478bd9Sstevel@tonic-gate short sid; 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate sid = 0; 10637c478bd9Sstevel@tonic-gate mid = 0; 10647c478bd9Sstevel@tonic-gate if (q != NULL) { 10657c478bd9Sstevel@tonic-gate mid = q->q_qinfo->qi_minfo->mi_idnum; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* Find out how many bytes we need and allocate if necesary */ 10697c478bd9Sstevel@tonic-gate va_start(ap, fmt); 10707c478bd9Sstevel@tonic-gate cp = buf; 10717c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_noop, (char *)&cp); 10727c478bd9Sstevel@tonic-gate if (count > sizeof (buf) && 10737c478bd9Sstevel@tonic-gate !(alloc_buf = mi_alloc((uint_t)count + 2, BPRI_MED))) { 10747c478bd9Sstevel@tonic-gate va_end(ap); 10757c478bd9Sstevel@tonic-gate return (-1); 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate va_end(ap); 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate va_start(ap, fmt); 10807c478bd9Sstevel@tonic-gate cp = alloc_buf; 10817c478bd9Sstevel@tonic-gate count = mi_iprintf(fmt, ap, mi_sprintf_putc, (char *)&cp); 10827c478bd9Sstevel@tonic-gate if (count != -1) 10837c478bd9Sstevel@tonic-gate (void) mi_sprintf_putc((char *)&cp, '\0'); 10847c478bd9Sstevel@tonic-gate else 10857c478bd9Sstevel@tonic-gate alloc_buf[0] = '\0'; 10867c478bd9Sstevel@tonic-gate va_end(ap); 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate ret = strlog(mid, sid, level, flags, alloc_buf); 10897c478bd9Sstevel@tonic-gate if (alloc_buf != buf) 10907c478bd9Sstevel@tonic-gate mi_free(alloc_buf); 10917c478bd9Sstevel@tonic-gate return (ret); 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate long 10957c478bd9Sstevel@tonic-gate mi_strtol(const char *str, char **ptr, int base) 10967c478bd9Sstevel@tonic-gate { 10977c478bd9Sstevel@tonic-gate const char *cp; 10987c478bd9Sstevel@tonic-gate int digits; 10997c478bd9Sstevel@tonic-gate long value; 11007c478bd9Sstevel@tonic-gate boolean_t is_negative; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate cp = str; 11037c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t' || *cp == '\n') 11047c478bd9Sstevel@tonic-gate cp++; 11057c478bd9Sstevel@tonic-gate is_negative = (*cp == '-'); 11067c478bd9Sstevel@tonic-gate if (is_negative) 11077c478bd9Sstevel@tonic-gate cp++; 11087c478bd9Sstevel@tonic-gate if (base == 0) { 11097c478bd9Sstevel@tonic-gate base = 10; 11107c478bd9Sstevel@tonic-gate if (*cp == '0') { 11117c478bd9Sstevel@tonic-gate base = 8; 11127c478bd9Sstevel@tonic-gate cp++; 11137c478bd9Sstevel@tonic-gate if (*cp == 'x' || *cp == 'X') { 11147c478bd9Sstevel@tonic-gate base = 16; 11157c478bd9Sstevel@tonic-gate cp++; 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate value = 0; 11207c478bd9Sstevel@tonic-gate for (; *cp != '\0'; cp++) { 11217c478bd9Sstevel@tonic-gate if (*cp >= '0' && *cp <= '9') 11227c478bd9Sstevel@tonic-gate digits = *cp - '0'; 11237c478bd9Sstevel@tonic-gate else if (*cp >= 'a' && *cp <= 'f') 11247c478bd9Sstevel@tonic-gate digits = *cp - 'a' + 10; 11257c478bd9Sstevel@tonic-gate else if (*cp >= 'A' && *cp <= 'F') 11267c478bd9Sstevel@tonic-gate digits = *cp - 'A' + 10; 11277c478bd9Sstevel@tonic-gate else 11287c478bd9Sstevel@tonic-gate break; 11297c478bd9Sstevel@tonic-gate if (digits >= base) 11307c478bd9Sstevel@tonic-gate break; 11317c478bd9Sstevel@tonic-gate value = (value * base) + digits; 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate /* Note: we cast away const here deliberately */ 11347c478bd9Sstevel@tonic-gate if (ptr != NULL) 11357c478bd9Sstevel@tonic-gate *ptr = (char *)cp; 11367c478bd9Sstevel@tonic-gate if (is_negative) 11377c478bd9Sstevel@tonic-gate value = -value; 11387c478bd9Sstevel@tonic-gate return (value); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate /* 11427c478bd9Sstevel@tonic-gate * mi_timer mechanism. 11437c478bd9Sstevel@tonic-gate * 11447c478bd9Sstevel@tonic-gate * Each timer is represented by a timer mblk and a (streams) queue. When the 11457c478bd9Sstevel@tonic-gate * timer fires the timer mblk will be put on the associated streams queue 11467c478bd9Sstevel@tonic-gate * so that the streams module can process the timer even in its service 11477c478bd9Sstevel@tonic-gate * procedure. 11487c478bd9Sstevel@tonic-gate * 11497c478bd9Sstevel@tonic-gate * The interface consists of 4 entry points: 11507c478bd9Sstevel@tonic-gate * mi_timer_alloc - create a timer mblk 11517c478bd9Sstevel@tonic-gate * mi_timer_free - free a timer mblk 11527c478bd9Sstevel@tonic-gate * mi_timer - start, restart, stop, or move the 11537c478bd9Sstevel@tonic-gate * timer to a different queue 11547c478bd9Sstevel@tonic-gate * mi_timer_valid - called by streams module to verify that 11557c478bd9Sstevel@tonic-gate * the timer did indeed fire. 11567c478bd9Sstevel@tonic-gate */ 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate /* 11627c478bd9Sstevel@tonic-gate * Start, restart, stop, or move the timer to a new queue. 11637c478bd9Sstevel@tonic-gate * If "tim" is -2 the timer is moved to a different queue. 11647c478bd9Sstevel@tonic-gate * If "tim" is -1 the timer is stopped. 11657c478bd9Sstevel@tonic-gate * Otherwise, the timer is stopped if it is already running, and 11667c478bd9Sstevel@tonic-gate * set to fire tim milliseconds from now. 11677c478bd9Sstevel@tonic-gate */ 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate void 11707c478bd9Sstevel@tonic-gate mi_timer(queue_t *q, MBLKP mp, clock_t tim) 11717c478bd9Sstevel@tonic-gate { 11727c478bd9Sstevel@tonic-gate MTBP mtb; 11737c478bd9Sstevel@tonic-gate int state; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate ASSERT(tim >= -2); 11767c478bd9Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 11777c478bd9Sstevel@tonic-gate return; 11787c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 11797c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 11807c478bd9Sstevel@tonic-gate if (tim >= 0) { 11817c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 11827c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 11837c478bd9Sstevel@tonic-gate tim = MSEC_TO_TICK(tim); 11847c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 11857c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 11867c478bd9Sstevel@tonic-gate /* Message has already been putq */ 11877c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 11887c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 11897c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED; 11907c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 11917c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 11927c478bd9Sstevel@tonic-gate return; 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate } else if (state != TB_IDLE) { 11957c478bd9Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED); 11967c478bd9Sstevel@tonic-gate if (state == TB_CANCELLED) { 11977c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 11987c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 11997c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RESCHED; 12007c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 12017c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 12027c478bd9Sstevel@tonic-gate return; 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate if (state == TB_RESCHED) { 12057c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 12067c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 12077c478bd9Sstevel@tonic-gate mtb->mtb_time_left = tim; 12087c478bd9Sstevel@tonic-gate /* mi_timer_valid will start timer */ 12097c478bd9Sstevel@tonic-gate return; 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 12137c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 12147c478bd9Sstevel@tonic-gate return; 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate switch (tim) { 12177c478bd9Sstevel@tonic-gate case -1: 12187c478bd9Sstevel@tonic-gate mi_timer_stop(mp); 12197c478bd9Sstevel@tonic-gate break; 12207c478bd9Sstevel@tonic-gate case -2: 12217c478bd9Sstevel@tonic-gate mi_timer_move(q, mp); 12227c478bd9Sstevel@tonic-gate break; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate /* 12277c478bd9Sstevel@tonic-gate * Allocate an M_PCSIG timer message. The space between db_base and 12287c478bd9Sstevel@tonic-gate * b_rptr is used by the mi_timer mechanism, and after b_rptr there are 12297c478bd9Sstevel@tonic-gate * "size" bytes that the caller can use for its own purposes. 12307c478bd9Sstevel@tonic-gate * 12317c478bd9Sstevel@tonic-gate * Note that db_type has to be a priority message since otherwise 12327c478bd9Sstevel@tonic-gate * the putq will not cause the service procedure to run when 12337c478bd9Sstevel@tonic-gate * there is flow control. 12347c478bd9Sstevel@tonic-gate */ 12357c478bd9Sstevel@tonic-gate MBLKP 12367c478bd9Sstevel@tonic-gate mi_timer_alloc(size_t size) 12377c478bd9Sstevel@tonic-gate { 12387c478bd9Sstevel@tonic-gate MBLKP mp; 12397c478bd9Sstevel@tonic-gate MTBP mtb; 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate if ((mp = allocb(size + sizeof (MTB), BPRI_HI)) != NULL) { 12427c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCSIG; 12437c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 12447c478bd9Sstevel@tonic-gate mp->b_rptr = (uchar_t *)&mtb[1]; 12457c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + size; 12467c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 12477c478bd9Sstevel@tonic-gate mtb->mtb_mp = mp; 12487c478bd9Sstevel@tonic-gate mtb->mtb_q = NULL; 12497c478bd9Sstevel@tonic-gate return (mp); 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate return (NULL); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate /* 12557c478bd9Sstevel@tonic-gate * timeout() callback function. 12567c478bd9Sstevel@tonic-gate * Put the message on the current queue. 12577c478bd9Sstevel@tonic-gate * If the timer is stopped or moved to a different queue after 12587c478bd9Sstevel@tonic-gate * it has fired then mi_timer() and mi_timer_valid() will clean 12597c478bd9Sstevel@tonic-gate * things up. 12607c478bd9Sstevel@tonic-gate */ 12617c478bd9Sstevel@tonic-gate static int 12627c478bd9Sstevel@tonic-gate mi_timer_fire(MTBP mtb) 12637c478bd9Sstevel@tonic-gate { 12647c478bd9Sstevel@tonic-gate ASSERT(mtb == (MTBP)mtb->mtb_mp->b_datap->db_base); 12657c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_mp->b_datap->db_type == M_PCSIG); 12667c478bd9Sstevel@tonic-gate return (putq(mtb->mtb_q, mtb->mtb_mp)); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate /* 12707c478bd9Sstevel@tonic-gate * Logically free a timer mblk (that might have a pending timeout().) 12717c478bd9Sstevel@tonic-gate * If the timer has fired and the mblk has been put on the queue then 12727c478bd9Sstevel@tonic-gate * mi_timer_valid will free the mblk. 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate void 12767c478bd9Sstevel@tonic-gate mi_timer_free(MBLKP mp) 12777c478bd9Sstevel@tonic-gate { 12787c478bd9Sstevel@tonic-gate MTBP mtb; 12797c478bd9Sstevel@tonic-gate int state; 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 12827c478bd9Sstevel@tonic-gate return; 12837c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 12847c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 12857c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 12867c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 12877c478bd9Sstevel@tonic-gate /* Message has already been putq */ 12887c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 12897c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 12907c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED; 12917c478bd9Sstevel@tonic-gate /* mi_timer_valid will free the mblk */ 12927c478bd9Sstevel@tonic-gate return; 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate } else if (state != TB_IDLE) { 12957c478bd9Sstevel@tonic-gate /* Message has already been putq */ 12967c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 12977c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 12987c478bd9Sstevel@tonic-gate ASSERT(state != TB_TO_BE_FREED); 12997c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_TO_BE_FREED; 13007c478bd9Sstevel@tonic-gate /* mi_timer_valid will free the mblk */ 13017c478bd9Sstevel@tonic-gate return; 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q == NULL || mtb->mtb_q->q_first != mp); 13047c478bd9Sstevel@tonic-gate freemsg(mp); 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* 13087c478bd9Sstevel@tonic-gate * Called from mi_timer(,,-2) 13097c478bd9Sstevel@tonic-gate */ 13107c478bd9Sstevel@tonic-gate void 13117c478bd9Sstevel@tonic-gate mi_timer_move(queue_t *q, MBLKP mp) 13127c478bd9Sstevel@tonic-gate { 13137c478bd9Sstevel@tonic-gate MTBP mtb; 13147c478bd9Sstevel@tonic-gate clock_t tim; 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 13177c478bd9Sstevel@tonic-gate return; 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 13207c478bd9Sstevel@tonic-gate /* 13217c478bd9Sstevel@tonic-gate * Need to untimeout and restart to make 13227c478bd9Sstevel@tonic-gate * sure that the mblk is not about to be putq on the old queue 13237c478bd9Sstevel@tonic-gate * by mi_timer_fire. 13247c478bd9Sstevel@tonic-gate */ 13257c478bd9Sstevel@tonic-gate if (mtb->mtb_state == TB_RUNNING) { 13267c478bd9Sstevel@tonic-gate if ((tim = untimeout(mtb->mtb_tid)) < 0) { 13277c478bd9Sstevel@tonic-gate /* 13287c478bd9Sstevel@tonic-gate * Message has already been putq. Move from old queue 13297c478bd9Sstevel@tonic-gate * to new queue. 13307c478bd9Sstevel@tonic-gate */ 13317c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 13327c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 13337c478bd9Sstevel@tonic-gate rmvq(mtb->mtb_q, mp); 13347c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp && 13357c478bd9Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL); 13367c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 13377c478bd9Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp); 13387c478bd9Sstevel@tonic-gate return; 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 13417c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 13427c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 13437c478bd9Sstevel@tonic-gate } else if (mtb->mtb_state != TB_IDLE) { 13447c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_state != TB_TO_BE_FREED); 13457c478bd9Sstevel@tonic-gate /* 13467c478bd9Sstevel@tonic-gate * Message is already sitting on queue. Move to new queue. 13477c478bd9Sstevel@tonic-gate */ 13487c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 13497c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 13507c478bd9Sstevel@tonic-gate rmvq(mtb->mtb_q, mp); 13517c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first != mp && 13527c478bd9Sstevel@tonic-gate mp->b_prev == NULL && mp->b_next == NULL); 13537c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 13547c478bd9Sstevel@tonic-gate (void) putq(mtb->mtb_q, mp); 13557c478bd9Sstevel@tonic-gate } else 13567c478bd9Sstevel@tonic-gate mtb->mtb_q = q; 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate /* 13607c478bd9Sstevel@tonic-gate * Called from mi_timer(,,-1) 13617c478bd9Sstevel@tonic-gate */ 13627c478bd9Sstevel@tonic-gate void 13637c478bd9Sstevel@tonic-gate mi_timer_stop(MBLKP mp) 13647c478bd9Sstevel@tonic-gate { 13657c478bd9Sstevel@tonic-gate MTBP mtb; 13667c478bd9Sstevel@tonic-gate int state; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 13697c478bd9Sstevel@tonic-gate return; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 13727c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 13737c478bd9Sstevel@tonic-gate if (state == TB_RUNNING) { 13747c478bd9Sstevel@tonic-gate if (untimeout(mtb->mtb_tid) < 0) { 13757c478bd9Sstevel@tonic-gate /* Message has already been putq */ 13767c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 13777c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 13787c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED; 13797c478bd9Sstevel@tonic-gate } else { 13807c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate } else if (state == TB_RESCHED) { 13837c478bd9Sstevel@tonic-gate ASSERT(mtb->mtb_q->q_first == mp || 13847c478bd9Sstevel@tonic-gate mp->b_prev || mp->b_next); 13857c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_CANCELLED; 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate /* 13907c478bd9Sstevel@tonic-gate * The user of the mi_timer mechanism is required to call mi_timer_valid() for 13917c478bd9Sstevel@tonic-gate * each M_PCSIG message processed in the service procedures. 13927c478bd9Sstevel@tonic-gate * mi_timer_valid will return "true" if the timer actually did fire. 13937c478bd9Sstevel@tonic-gate */ 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate boolean_t 13967c478bd9Sstevel@tonic-gate mi_timer_valid(MBLKP mp) 13977c478bd9Sstevel@tonic-gate { 13987c478bd9Sstevel@tonic-gate MTBP mtb; 13997c478bd9Sstevel@tonic-gate int state; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB) || 14027c478bd9Sstevel@tonic-gate mp->b_datap->db_type != M_PCSIG) 14037c478bd9Sstevel@tonic-gate return (B_FALSE); 14047c478bd9Sstevel@tonic-gate mtb = (MTBP)mp->b_datap->db_base; 14057c478bd9Sstevel@tonic-gate state = mtb->mtb_state; 14067c478bd9Sstevel@tonic-gate if (state != TB_RUNNING) { 14077c478bd9Sstevel@tonic-gate ASSERT(state != TB_IDLE); 14087c478bd9Sstevel@tonic-gate if (state == TB_TO_BE_FREED) { 14097c478bd9Sstevel@tonic-gate /* 14107c478bd9Sstevel@tonic-gate * mi_timer_free was called after the message 14117c478bd9Sstevel@tonic-gate * was putq'ed. 14127c478bd9Sstevel@tonic-gate */ 14137c478bd9Sstevel@tonic-gate freemsg(mp); 14147c478bd9Sstevel@tonic-gate return (B_FALSE); 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate if (state == TB_CANCELLED) { 14177c478bd9Sstevel@tonic-gate /* The timer was stopped after the mblk was putq'ed */ 14187c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 14197c478bd9Sstevel@tonic-gate return (B_FALSE); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate if (state == TB_RESCHED) { 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * The timer was stopped and then restarted after 14247c478bd9Sstevel@tonic-gate * the mblk was putq'ed. 14257c478bd9Sstevel@tonic-gate * mtb_time_left contains the number of ticks that 14267c478bd9Sstevel@tonic-gate * the timer was restarted with. 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_RUNNING; 14297c478bd9Sstevel@tonic-gate mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, 14307c478bd9Sstevel@tonic-gate mtb, mtb->mtb_time_left); 14317c478bd9Sstevel@tonic-gate return (B_FALSE); 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate mtb->mtb_state = TB_IDLE; 14357c478bd9Sstevel@tonic-gate return (B_TRUE); 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate static void 14397c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(MBLKP mp, char *addr, t_scalar_t addr_length, 14407c478bd9Sstevel@tonic-gate char *opt, t_scalar_t opt_length) 14417c478bd9Sstevel@tonic-gate { 14427c478bd9Sstevel@tonic-gate struct T_unitdata_ind *tudi; 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate /* 14457c478bd9Sstevel@tonic-gate * This code is used more than just for unitdata ind 14467c478bd9Sstevel@tonic-gate * (also for T_CONN_IND and T_CONN_CON) and 14477c478bd9Sstevel@tonic-gate * relies on correct functioning on the happy 14487c478bd9Sstevel@tonic-gate * coincidence that the the address and option buffers 14497c478bd9Sstevel@tonic-gate * represented by length/offset in all these primitives 14507c478bd9Sstevel@tonic-gate * are isomorphic in terms of offset from start of data 14517c478bd9Sstevel@tonic-gate * structure 14527c478bd9Sstevel@tonic-gate */ 14537c478bd9Sstevel@tonic-gate tudi = (struct T_unitdata_ind *)mp->b_rptr; 14547c478bd9Sstevel@tonic-gate tudi->SRC_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 14557c478bd9Sstevel@tonic-gate tudi->SRC_length = addr_length; 14567c478bd9Sstevel@tonic-gate if (addr_length > 0) { 14577c478bd9Sstevel@tonic-gate bcopy(addr, (char *)mp->b_wptr, addr_length); 14587c478bd9Sstevel@tonic-gate mp->b_wptr += addr_length; 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate tudi->OPT_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 14617c478bd9Sstevel@tonic-gate tudi->OPT_length = opt_length; 14627c478bd9Sstevel@tonic-gate if (opt_length > 0) { 14637c478bd9Sstevel@tonic-gate bcopy(opt, (char *)mp->b_wptr, opt_length); 14647c478bd9Sstevel@tonic-gate mp->b_wptr += opt_length; 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate MBLKP 14697c478bd9Sstevel@tonic-gate mi_tpi_conn_con(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 14707c478bd9Sstevel@tonic-gate t_scalar_t opt_length) 14717c478bd9Sstevel@tonic-gate { 14727c478bd9Sstevel@tonic-gate size_t len; 14737c478bd9Sstevel@tonic-gate MBLKP mp; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate len = sizeof (struct T_conn_con) + src_length + opt_length; 14767c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_CON)) != NULL) { 14777c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_con)]; 14787c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate return (mp); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate MBLKP 14847c478bd9Sstevel@tonic-gate mi_tpi_conn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 14857c478bd9Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t seqnum) 14867c478bd9Sstevel@tonic-gate { 14877c478bd9Sstevel@tonic-gate size_t len; 14887c478bd9Sstevel@tonic-gate MBLKP mp; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate len = sizeof (struct T_conn_ind) + src_length + opt_length; 14917c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_IND)) != NULL) { 14927c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_ind)]; 14937c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 14947c478bd9Sstevel@tonic-gate ((struct T_conn_ind *)mp->b_rptr)->SEQ_number = seqnum; 14957c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate return (mp); 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate MBLKP 15017c478bd9Sstevel@tonic-gate mi_tpi_extconn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, 15027c478bd9Sstevel@tonic-gate char *opt, t_scalar_t opt_length, char *dst, t_scalar_t dst_length, 15037c478bd9Sstevel@tonic-gate t_scalar_t seqnum) 15047c478bd9Sstevel@tonic-gate { 15057c478bd9Sstevel@tonic-gate size_t len; 15067c478bd9Sstevel@tonic-gate MBLKP mp; 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate len = sizeof (struct T_extconn_ind) + src_length + opt_length + 15097c478bd9Sstevel@tonic-gate dst_length; 15107c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_EXTCONN_IND)) != 15117c478bd9Sstevel@tonic-gate NULL) { 15127c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_extconn_ind)]; 15137c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 15147c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_length = dst_length; 15157c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->DEST_offset = 15167c478bd9Sstevel@tonic-gate (t_scalar_t)(mp->b_wptr - mp->b_rptr); 15177c478bd9Sstevel@tonic-gate if (dst_length > 0) { 15187c478bd9Sstevel@tonic-gate bcopy(dst, (char *)mp->b_wptr, dst_length); 15197c478bd9Sstevel@tonic-gate mp->b_wptr += dst_length; 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate ((struct T_extconn_ind *)mp->b_rptr)->SEQ_number = seqnum; 15227c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate return (mp); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate MBLKP 15287c478bd9Sstevel@tonic-gate mi_tpi_discon_ind(MBLKP trailer_mp, t_scalar_t reason, t_scalar_t seqnum) 15297c478bd9Sstevel@tonic-gate { 15307c478bd9Sstevel@tonic-gate MBLKP mp; 15317c478bd9Sstevel@tonic-gate struct T_discon_ind *tdi; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if ((mp = mi_tpi_trailer_alloc(trailer_mp, 15347c478bd9Sstevel@tonic-gate sizeof (struct T_discon_ind), T_DISCON_IND)) != NULL) { 15357c478bd9Sstevel@tonic-gate tdi = (struct T_discon_ind *)mp->b_rptr; 15367c478bd9Sstevel@tonic-gate tdi->DISCON_reason = reason; 15377c478bd9Sstevel@tonic-gate tdi->SEQ_number = seqnum; 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate return (mp); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate /* 15437c478bd9Sstevel@tonic-gate * Allocate and fill in a TPI err ack packet using the 'mp' passed in 15447c478bd9Sstevel@tonic-gate * for the 'error_prim' context as well as sacrifice. 15457c478bd9Sstevel@tonic-gate */ 15467c478bd9Sstevel@tonic-gate MBLKP 15477c478bd9Sstevel@tonic-gate mi_tpi_err_ack_alloc(MBLKP mp, t_scalar_t tlierr, int unixerr) 15487c478bd9Sstevel@tonic-gate { 15497c478bd9Sstevel@tonic-gate struct T_error_ack *teackp; 15507c478bd9Sstevel@tonic-gate t_scalar_t error_prim; 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate if (!mp) 15537c478bd9Sstevel@tonic-gate return (NULL); 15547c478bd9Sstevel@tonic-gate error_prim = ((TPRIMP)mp->b_rptr)->type; 15557c478bd9Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack), 15567c478bd9Sstevel@tonic-gate M_PCPROTO, T_ERROR_ACK)) != NULL) { 15577c478bd9Sstevel@tonic-gate teackp = (struct T_error_ack *)mp->b_rptr; 15587c478bd9Sstevel@tonic-gate teackp->ERROR_prim = error_prim; 15597c478bd9Sstevel@tonic-gate teackp->TLI_error = tlierr; 15607c478bd9Sstevel@tonic-gate teackp->UNIX_error = unixerr; 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate return (mp); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate MBLKP 15667c478bd9Sstevel@tonic-gate mi_tpi_ok_ack_alloc_extra(MBLKP mp, int extra) 15677c478bd9Sstevel@tonic-gate { 15687c478bd9Sstevel@tonic-gate t_scalar_t correct_prim; 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate if (!mp) 15717c478bd9Sstevel@tonic-gate return (NULL); 15727c478bd9Sstevel@tonic-gate correct_prim = ((TPRIMP)mp->b_rptr)->type; 15737c478bd9Sstevel@tonic-gate if ((mp = tpi_ack_alloc(mp, sizeof (struct T_ok_ack) + extra, 15747c478bd9Sstevel@tonic-gate M_PCPROTO, T_OK_ACK)) != NULL) { 15757c478bd9Sstevel@tonic-gate ((struct T_ok_ack *)mp->b_rptr)->CORRECT_prim = correct_prim; 15767c478bd9Sstevel@tonic-gate mp->b_wptr -= extra; 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate return (mp); 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate MBLKP 15827c478bd9Sstevel@tonic-gate mi_tpi_ok_ack_alloc(MBLKP mp) 15837c478bd9Sstevel@tonic-gate { 15847c478bd9Sstevel@tonic-gate return (mi_tpi_ok_ack_alloc_extra(mp, 0)); 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate MBLKP 15887c478bd9Sstevel@tonic-gate mi_tpi_ordrel_ind(void) 15897c478bd9Sstevel@tonic-gate { 15907c478bd9Sstevel@tonic-gate MBLKP mp; 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (struct T_ordrel_ind), BPRI_HI)) != NULL) { 15937c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 15947c478bd9Sstevel@tonic-gate ((struct T_ordrel_ind *)mp->b_rptr)->PRIM_type = T_ORDREL_IND; 15957c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (struct T_ordrel_ind); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate return (mp); 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate static MBLKP 16017c478bd9Sstevel@tonic-gate mi_tpi_trailer_alloc(MBLKP trailer_mp, size_t size, t_scalar_t type) 16027c478bd9Sstevel@tonic-gate { 16037c478bd9Sstevel@tonic-gate MBLKP mp; 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate if ((mp = allocb(size, BPRI_MED)) != NULL) { 16067c478bd9Sstevel@tonic-gate mp->b_cont = trailer_mp; 16077c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 16087c478bd9Sstevel@tonic-gate ((union T_primitives *)mp->b_rptr)->type = type; 16097c478bd9Sstevel@tonic-gate mp->b_wptr += size; 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate return (mp); 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate MBLKP 16157c478bd9Sstevel@tonic-gate mi_tpi_uderror_ind(char *dest, t_scalar_t dest_length, char *opt, 16167c478bd9Sstevel@tonic-gate t_scalar_t opt_length, t_scalar_t error) 16177c478bd9Sstevel@tonic-gate { 16187c478bd9Sstevel@tonic-gate size_t len; 16197c478bd9Sstevel@tonic-gate MBLKP mp; 16207c478bd9Sstevel@tonic-gate struct T_uderror_ind *tudei; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate len = sizeof (struct T_uderror_ind) + dest_length + opt_length; 16237c478bd9Sstevel@tonic-gate if ((mp = allocb(len, BPRI_HI)) != NULL) { 16247c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 16257c478bd9Sstevel@tonic-gate tudei = (struct T_uderror_ind *)mp->b_rptr; 16267c478bd9Sstevel@tonic-gate tudei->PRIM_type = T_UDERROR_IND; 16277c478bd9Sstevel@tonic-gate tudei->ERROR_type = error; 16287c478bd9Sstevel@tonic-gate mp->b_wptr = &mp->b_rptr[sizeof (struct T_uderror_ind)]; 16297c478bd9Sstevel@tonic-gate mi_tpi_addr_and_opt(mp, dest, dest_length, opt, opt_length); 16307c478bd9Sstevel@tonic-gate } 16317c478bd9Sstevel@tonic-gate return (mp); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate IDP 16357c478bd9Sstevel@tonic-gate mi_zalloc(size_t size) 16367c478bd9Sstevel@tonic-gate { 16377c478bd9Sstevel@tonic-gate IDP ptr; 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate if (ptr = mi_alloc(size, BPRI_LO)) 16407c478bd9Sstevel@tonic-gate bzero(ptr, size); 16417c478bd9Sstevel@tonic-gate return (ptr); 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate IDP 16457c478bd9Sstevel@tonic-gate mi_zalloc_sleep(size_t size) 16467c478bd9Sstevel@tonic-gate { 16477c478bd9Sstevel@tonic-gate IDP ptr; 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate if (ptr = mi_alloc_sleep(size, BPRI_LO)) 16507c478bd9Sstevel@tonic-gate bzero(ptr, size); 16517c478bd9Sstevel@tonic-gate return (ptr); 16527c478bd9Sstevel@tonic-gate } 1653