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