1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Common Sun DLPI routines. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/sysmacros.h> 35 #include <sys/byteorder.h> 36 #include <sys/systm.h> 37 #include <sys/stream.h> 38 #include <sys/strsun.h> 39 #include <sys/dlpi.h> 40 41 #define DLADDRL (80) 42 43 void 44 dlbindack( 45 queue_t *wq, 46 mblk_t *mp, 47 t_scalar_t sap, 48 void *addrp, 49 t_uscalar_t addrlen, 50 t_uscalar_t maxconind, 51 t_uscalar_t xidtest) 52 { 53 union DL_primitives *dlp; 54 size_t size; 55 56 size = sizeof (dl_bind_ack_t) + addrlen; 57 if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL) 58 return; 59 60 dlp = (union DL_primitives *)mp->b_rptr; 61 dlp->bind_ack.dl_sap = sap; 62 dlp->bind_ack.dl_addr_length = addrlen; 63 dlp->bind_ack.dl_addr_offset = sizeof (dl_bind_ack_t); 64 dlp->bind_ack.dl_max_conind = maxconind; 65 dlp->bind_ack.dl_xidtest_flg = xidtest; 66 if (addrlen != 0) 67 bcopy(addrp, mp->b_rptr + sizeof (dl_bind_ack_t), addrlen); 68 69 qreply(wq, mp); 70 } 71 72 void 73 dlokack( 74 queue_t *wq, 75 mblk_t *mp, 76 t_uscalar_t correct_primitive) 77 { 78 union DL_primitives *dlp; 79 80 if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PCPROTO, 81 DL_OK_ACK)) == NULL) 82 return; 83 dlp = (union DL_primitives *)mp->b_rptr; 84 dlp->ok_ack.dl_correct_primitive = correct_primitive; 85 qreply(wq, mp); 86 } 87 88 void 89 dlerrorack( 90 queue_t *wq, 91 mblk_t *mp, 92 t_uscalar_t error_primitive, 93 t_uscalar_t error, 94 t_uscalar_t unix_errno) 95 { 96 union DL_primitives *dlp; 97 98 if ((mp = mexchange(wq, mp, sizeof (dl_error_ack_t), M_PCPROTO, 99 DL_ERROR_ACK)) == NULL) 100 return; 101 dlp = (union DL_primitives *)mp->b_rptr; 102 dlp->error_ack.dl_error_primitive = error_primitive; 103 dlp->error_ack.dl_errno = error; 104 dlp->error_ack.dl_unix_errno = unix_errno; 105 qreply(wq, mp); 106 } 107 108 void 109 dluderrorind( 110 queue_t *wq, 111 mblk_t *mp, 112 void *addrp, 113 t_uscalar_t addrlen, 114 t_uscalar_t error, 115 t_uscalar_t unix_errno) 116 { 117 union DL_primitives *dlp; 118 char buf[DLADDRL]; 119 size_t size; 120 121 if (addrlen > DLADDRL) 122 addrlen = DLADDRL; 123 124 bcopy(addrp, buf, addrlen); 125 126 size = sizeof (dl_uderror_ind_t) + addrlen; 127 128 if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_UDERROR_IND)) == NULL) 129 return; 130 131 dlp = (union DL_primitives *)mp->b_rptr; 132 dlp->uderror_ind.dl_dest_addr_length = addrlen; 133 dlp->uderror_ind.dl_dest_addr_offset = sizeof (dl_uderror_ind_t); 134 dlp->uderror_ind.dl_unix_errno = unix_errno; 135 dlp->uderror_ind.dl_errno = error; 136 bcopy((caddr_t)buf, 137 (caddr_t)(mp->b_rptr + sizeof (dl_uderror_ind_t)), addrlen); 138 qreply(wq, mp); 139 } 140 141 void 142 dlphysaddrack( 143 queue_t *wq, 144 mblk_t *mp, 145 void *addrp, 146 t_uscalar_t len) 147 { 148 union DL_primitives *dlp; 149 size_t size; 150 151 size = sizeof (dl_phys_addr_ack_t) + len; 152 if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_PHYS_ADDR_ACK)) == NULL) 153 return; 154 dlp = (union DL_primitives *)mp->b_rptr; 155 dlp->physaddr_ack.dl_addr_length = len; 156 dlp->physaddr_ack.dl_addr_offset = sizeof (dl_phys_addr_ack_t); 157 if (len != 0) 158 bcopy(addrp, mp->b_rptr + sizeof (dl_phys_addr_ack_t), len); 159 qreply(wq, mp); 160 } 161 162 void 163 dlcapabsetqid(dl_mid_t *idp, const queue_t *q) 164 { 165 #ifndef _LP64 166 idp->mid[0] = (t_uscalar_t)q; 167 #else 168 idp->mid[0] = (t_uscalar_t)BMASK_32((uint64_t)q); 169 idp->mid[1] = (t_uscalar_t)BMASK_32(((uint64_t)q) >> 32); 170 #endif 171 } 172 173 boolean_t 174 dlcapabcheckqid(const dl_mid_t *idp, const queue_t *q) 175 { 176 #ifndef _LP64 177 return ((queue_t *)(idp->mid[0]) == q); 178 #else 179 return ((queue_t *) 180 ((uint64_t)idp->mid[0] | ((uint64_t)idp->mid[1] << 32)) == q); 181 #endif 182 } 183 184 void 185 dlnotifyack( 186 queue_t *wq, 187 mblk_t *mp, 188 uint32_t notifications) 189 { 190 union DL_primitives *dlp; 191 192 if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PROTO, 193 DL_NOTIFY_ACK)) == NULL) 194 return; 195 dlp = (union DL_primitives *)mp->b_rptr; 196 dlp->notify_ack.dl_notifications = notifications; 197 qreply(wq, mp); 198 } 199