stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 1 | /* |
| 2 | * CDDL HEADER START |
| 3 | * |
| 4 | * The contents of this file are subject to the terms of the |
yz147064 | 392b1d6 | 2007-09-20 01:07:16 -0700 | [diff] [blame] | 5 | * Common Development and Distribution License (the "License"). |
| 6 | * You may not use this file except in compliance with the License. |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 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 | /* |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 22 | * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 23 | * Use is subject to license terms. |
| 24 | */ |
| 25 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 26 | /* |
| 27 | * Common Sun DLPI routines. |
| 28 | */ |
| 29 | |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 30 | #include <sys/types.h> |
| 31 | #include <sys/sysmacros.h> |
| 32 | #include <sys/byteorder.h> |
| 33 | #include <sys/stream.h> |
| 34 | #include <sys/strsun.h> |
| 35 | #include <sys/dlpi.h> |
| 36 | #include <sys/ddi.h> |
| 37 | #include <sys/sunddi.h> |
| 38 | #include <sys/sunldi.h> |
| 39 | #include <sys/cmn_err.h> |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 40 | |
| 41 | void |
| 42 | dlbindack( |
| 43 | queue_t *wq, |
| 44 | mblk_t *mp, |
| 45 | t_scalar_t sap, |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 46 | const void *addrp, |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 47 | t_uscalar_t addrlen, |
| 48 | t_uscalar_t maxconind, |
| 49 | t_uscalar_t xidtest) |
| 50 | { |
| 51 | union DL_primitives *dlp; |
| 52 | size_t size; |
| 53 | |
| 54 | size = sizeof (dl_bind_ack_t) + addrlen; |
| 55 | if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL) |
| 56 | return; |
| 57 | |
| 58 | dlp = (union DL_primitives *)mp->b_rptr; |
| 59 | dlp->bind_ack.dl_sap = sap; |
| 60 | dlp->bind_ack.dl_addr_length = addrlen; |
| 61 | dlp->bind_ack.dl_addr_offset = sizeof (dl_bind_ack_t); |
| 62 | dlp->bind_ack.dl_max_conind = maxconind; |
| 63 | dlp->bind_ack.dl_xidtest_flg = xidtest; |
| 64 | if (addrlen != 0) |
| 65 | bcopy(addrp, mp->b_rptr + sizeof (dl_bind_ack_t), addrlen); |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 66 | qreply(wq, mp); |
| 67 | } |
| 68 | |
| 69 | void |
| 70 | dlokack( |
| 71 | queue_t *wq, |
| 72 | mblk_t *mp, |
| 73 | t_uscalar_t correct_primitive) |
| 74 | { |
| 75 | union DL_primitives *dlp; |
| 76 | |
| 77 | if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PCPROTO, |
| 78 | DL_OK_ACK)) == NULL) |
| 79 | return; |
| 80 | dlp = (union DL_primitives *)mp->b_rptr; |
| 81 | dlp->ok_ack.dl_correct_primitive = correct_primitive; |
| 82 | qreply(wq, mp); |
| 83 | } |
| 84 | |
| 85 | void |
| 86 | dlerrorack( |
| 87 | queue_t *wq, |
| 88 | mblk_t *mp, |
| 89 | t_uscalar_t error_primitive, |
| 90 | t_uscalar_t error, |
| 91 | t_uscalar_t unix_errno) |
| 92 | { |
| 93 | union DL_primitives *dlp; |
| 94 | |
| 95 | if ((mp = mexchange(wq, mp, sizeof (dl_error_ack_t), M_PCPROTO, |
| 96 | DL_ERROR_ACK)) == NULL) |
| 97 | return; |
| 98 | dlp = (union DL_primitives *)mp->b_rptr; |
| 99 | dlp->error_ack.dl_error_primitive = error_primitive; |
| 100 | dlp->error_ack.dl_errno = error; |
| 101 | dlp->error_ack.dl_unix_errno = unix_errno; |
| 102 | qreply(wq, mp); |
| 103 | } |
| 104 | |
| 105 | void |
| 106 | dluderrorind( |
| 107 | queue_t *wq, |
| 108 | mblk_t *mp, |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 109 | const void *addrp, |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 110 | t_uscalar_t addrlen, |
| 111 | t_uscalar_t error, |
| 112 | t_uscalar_t unix_errno) |
| 113 | { |
| 114 | union DL_primitives *dlp; |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 115 | size_t size; |
| 116 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 117 | size = sizeof (dl_uderror_ind_t) + addrlen; |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 118 | if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_UDERROR_IND)) == NULL) |
| 119 | return; |
| 120 | |
| 121 | dlp = (union DL_primitives *)mp->b_rptr; |
| 122 | dlp->uderror_ind.dl_dest_addr_length = addrlen; |
| 123 | dlp->uderror_ind.dl_dest_addr_offset = sizeof (dl_uderror_ind_t); |
| 124 | dlp->uderror_ind.dl_unix_errno = unix_errno; |
| 125 | dlp->uderror_ind.dl_errno = error; |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 126 | if (addrlen != 0) |
| 127 | bcopy(addrp, mp->b_rptr + sizeof (dl_uderror_ind_t), addrlen); |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 128 | qreply(wq, mp); |
| 129 | } |
| 130 | |
| 131 | void |
| 132 | dlphysaddrack( |
| 133 | queue_t *wq, |
| 134 | mblk_t *mp, |
meem | 3a18a1c | 2009-01-09 21:29:03 -0500 | [diff] [blame] | 135 | const void *addrp, |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 136 | t_uscalar_t len) |
| 137 | { |
| 138 | union DL_primitives *dlp; |
| 139 | size_t size; |
| 140 | |
| 141 | size = sizeof (dl_phys_addr_ack_t) + len; |
| 142 | if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_PHYS_ADDR_ACK)) == NULL) |
| 143 | return; |
| 144 | dlp = (union DL_primitives *)mp->b_rptr; |
| 145 | dlp->physaddr_ack.dl_addr_length = len; |
| 146 | dlp->physaddr_ack.dl_addr_offset = sizeof (dl_phys_addr_ack_t); |
| 147 | if (len != 0) |
| 148 | bcopy(addrp, mp->b_rptr + sizeof (dl_phys_addr_ack_t), len); |
| 149 | qreply(wq, mp); |
| 150 | } |
| 151 | |
| 152 | void |
| 153 | dlcapabsetqid(dl_mid_t *idp, const queue_t *q) |
| 154 | { |
| 155 | #ifndef _LP64 |
| 156 | idp->mid[0] = (t_uscalar_t)q; |
| 157 | #else |
| 158 | idp->mid[0] = (t_uscalar_t)BMASK_32((uint64_t)q); |
| 159 | idp->mid[1] = (t_uscalar_t)BMASK_32(((uint64_t)q) >> 32); |
| 160 | #endif |
| 161 | } |
| 162 | |
| 163 | boolean_t |
| 164 | dlcapabcheckqid(const dl_mid_t *idp, const queue_t *q) |
| 165 | { |
| 166 | #ifndef _LP64 |
| 167 | return ((queue_t *)(idp->mid[0]) == q); |
| 168 | #else |
| 169 | return ((queue_t *) |
| 170 | ((uint64_t)idp->mid[0] | ((uint64_t)idp->mid[1] << 32)) == q); |
| 171 | #endif |
| 172 | } |
| 173 | |
| 174 | void |
| 175 | dlnotifyack( |
| 176 | queue_t *wq, |
| 177 | mblk_t *mp, |
| 178 | uint32_t notifications) |
| 179 | { |
| 180 | union DL_primitives *dlp; |
| 181 | |
yz147064 | 392b1d6 | 2007-09-20 01:07:16 -0700 | [diff] [blame] | 182 | if ((mp = mexchange(wq, mp, sizeof (dl_notify_ack_t), M_PROTO, |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 183 | DL_NOTIFY_ACK)) == NULL) |
| 184 | return; |
| 185 | dlp = (union DL_primitives *)mp->b_rptr; |
| 186 | dlp->notify_ack.dl_notifications = notifications; |
| 187 | qreply(wq, mp); |
| 188 | } |
yz147064 | d62bc4b | 2008-01-23 18:09:15 -0800 | [diff] [blame] | 189 | |
| 190 | static int |
| 191 | dl_op(ldi_handle_t lh, mblk_t **mpp, t_uscalar_t expprim, size_t minlen, |
| 192 | dl_error_ack_t *dleap, timestruc_t *tvp) |
| 193 | { |
| 194 | int err; |
| 195 | size_t len; |
| 196 | mblk_t *mp = *mpp; |
| 197 | t_uscalar_t reqprim, ackprim, ackreqprim; |
| 198 | union DL_primitives *dlp; |
| 199 | |
| 200 | reqprim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; |
| 201 | |
| 202 | (void) ldi_putmsg(lh, mp); |
| 203 | |
| 204 | switch (err = ldi_getmsg(lh, &mp, tvp)) { |
| 205 | case 0: |
| 206 | break; |
| 207 | case ETIME: |
| 208 | cmn_err(CE_NOTE, "!dl_op: timed out waiting for %s to %s", |
| 209 | dl_primstr(reqprim), dl_primstr(expprim)); |
| 210 | return (ETIME); |
| 211 | default: |
| 212 | cmn_err(CE_NOTE, "!dl_op: ldi_getmsg() for %s failed: %d", |
| 213 | dl_primstr(expprim), err); |
| 214 | return (err); |
| 215 | } |
| 216 | |
| 217 | len = MBLKL(mp); |
| 218 | if (len < sizeof (t_uscalar_t)) { |
| 219 | cmn_err(CE_NOTE, "!dl_op: received runt DLPI message"); |
| 220 | freemsg(mp); |
| 221 | return (EBADMSG); |
| 222 | } |
| 223 | |
| 224 | dlp = (union DL_primitives *)mp->b_rptr; |
| 225 | ackprim = dlp->dl_primitive; |
| 226 | |
| 227 | if (ackprim == expprim) { |
| 228 | if (len < minlen) |
| 229 | goto runt; |
| 230 | |
| 231 | if (ackprim == DL_OK_ACK) { |
| 232 | if (dlp->ok_ack.dl_correct_primitive != reqprim) { |
| 233 | ackreqprim = dlp->ok_ack.dl_correct_primitive; |
| 234 | goto mixup; |
| 235 | } |
| 236 | } |
| 237 | *mpp = mp; |
| 238 | return (0); |
| 239 | } |
| 240 | |
| 241 | if (ackprim == DL_ERROR_ACK) { |
| 242 | if (len < DL_ERROR_ACK_SIZE) |
| 243 | goto runt; |
| 244 | |
| 245 | if (dlp->error_ack.dl_error_primitive != reqprim) { |
| 246 | ackreqprim = dlp->error_ack.dl_error_primitive; |
| 247 | goto mixup; |
| 248 | } |
| 249 | |
| 250 | /* |
| 251 | * Return a special error code (ENOTSUP) indicating that the |
| 252 | * caller has returned DL_ERROR_ACK. Callers that want more |
| 253 | * details an pass a non-NULL dleap. |
| 254 | */ |
| 255 | if (dleap != NULL) |
| 256 | *dleap = dlp->error_ack; |
| 257 | |
| 258 | freemsg(mp); |
| 259 | return (ENOTSUP); |
| 260 | } |
| 261 | |
| 262 | cmn_err(CE_NOTE, "!dl_op: expected %s but received %s", |
| 263 | dl_primstr(expprim), dl_primstr(ackprim)); |
| 264 | freemsg(mp); |
| 265 | return (EBADMSG); |
| 266 | runt: |
| 267 | cmn_err(CE_NOTE, "!dl_op: received runt %s", dl_primstr(ackprim)); |
| 268 | freemsg(mp); |
| 269 | return (EBADMSG); |
| 270 | mixup: |
| 271 | cmn_err(CE_NOTE, "!dl_op: received %s for %s instead of %s", |
| 272 | dl_primstr(ackprim), dl_primstr(ackreqprim), dl_primstr(reqprim)); |
| 273 | freemsg(mp); |
| 274 | return (EBADMSG); |
| 275 | } |
| 276 | |
| 277 | /* |
| 278 | * Send a DL_ATTACH_REQ for `ppa' over `lh' and wait for the response. |
| 279 | * |
| 280 | * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the |
| 281 | * caller can get the contents by passing a non-NULL `dleap'). |
| 282 | */ |
| 283 | int |
| 284 | dl_attach(ldi_handle_t lh, int ppa, dl_error_ack_t *dleap) |
| 285 | { |
| 286 | mblk_t *mp; |
| 287 | int err; |
| 288 | |
| 289 | mp = mexchange(NULL, NULL, DL_ATTACH_REQ_SIZE, M_PROTO, DL_ATTACH_REQ); |
| 290 | if (mp == NULL) |
| 291 | return (ENOMEM); |
| 292 | |
| 293 | ((dl_attach_req_t *)mp->b_rptr)->dl_ppa = ppa; |
| 294 | |
| 295 | err = dl_op(lh, &mp, DL_OK_ACK, DL_OK_ACK_SIZE, dleap, NULL); |
| 296 | if (err == 0) |
| 297 | freemsg(mp); |
| 298 | return (err); |
| 299 | } |
| 300 | |
| 301 | /* |
| 302 | * Send a DL_BIND_REQ for `sap' over `lh' and wait for the response. |
| 303 | * |
| 304 | * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the |
| 305 | * caller can get the contents by passing a non-NULL `dleap'). |
| 306 | */ |
| 307 | int |
| 308 | dl_bind(ldi_handle_t lh, uint_t sap, dl_error_ack_t *dleap) |
| 309 | { |
| 310 | dl_bind_req_t *dlbrp; |
| 311 | dl_bind_ack_t *dlbap; |
| 312 | mblk_t *mp; |
| 313 | int err; |
| 314 | |
| 315 | mp = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ); |
| 316 | if (mp == NULL) |
| 317 | return (ENOMEM); |
| 318 | |
| 319 | dlbrp = (dl_bind_req_t *)mp->b_rptr; |
| 320 | dlbrp->dl_sap = sap; |
| 321 | dlbrp->dl_conn_mgmt = 0; |
| 322 | dlbrp->dl_max_conind = 0; |
| 323 | dlbrp->dl_xidtest_flg = 0; |
| 324 | dlbrp->dl_service_mode = DL_CLDLS; |
| 325 | |
| 326 | err = dl_op(lh, &mp, DL_BIND_ACK, DL_BIND_ACK_SIZE, dleap, NULL); |
| 327 | if (err == 0) { |
| 328 | dlbap = (dl_bind_ack_t *)mp->b_rptr; |
| 329 | if (dlbap->dl_sap != sap) { |
| 330 | cmn_err(CE_NOTE, "!dl_bind: DL_BIND_ACK: bad sap %u", |
| 331 | dlbap->dl_sap); |
| 332 | err = EPROTO; |
| 333 | } |
| 334 | freemsg(mp); |
| 335 | } |
| 336 | return (err); |
| 337 | } |
| 338 | |
| 339 | /* |
| 340 | * Send a DL_PHYS_ADDR_REQ over `lh' and wait for the response. The caller |
| 341 | * must set `*physlenp' to the size of `physaddr' (both of which must be |
| 342 | * non-NULL); upon success they will be updated to contain the actual physical |
| 343 | * address and length. |
| 344 | * |
| 345 | * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the |
| 346 | * caller can get the contents by passing a non-NULL `dleap'). |
| 347 | */ |
| 348 | int |
| 349 | dl_phys_addr(ldi_handle_t lh, uchar_t *physaddr, size_t *physlenp, |
| 350 | dl_error_ack_t *dleap) |
| 351 | { |
| 352 | dl_phys_addr_ack_t *dlpap; |
| 353 | mblk_t *mp; |
| 354 | int err; |
| 355 | t_uscalar_t paddrlen, paddroff; |
| 356 | timestruc_t tv; |
| 357 | |
| 358 | mp = mexchange(NULL, NULL, DL_PHYS_ADDR_REQ_SIZE, M_PROTO, |
| 359 | DL_PHYS_ADDR_REQ); |
| 360 | if (mp == NULL) |
| 361 | return (ENOMEM); |
| 362 | |
| 363 | ((dl_phys_addr_req_t *)mp->b_rptr)->dl_addr_type = DL_CURR_PHYS_ADDR; |
| 364 | |
| 365 | /* |
| 366 | * In case some provider doesn't implement or NAK the |
| 367 | * request, just wait for 15 seconds. |
| 368 | */ |
| 369 | tv.tv_sec = 15; |
| 370 | tv.tv_nsec = 0; |
| 371 | |
| 372 | err = dl_op(lh, &mp, DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, dleap, |
| 373 | &tv); |
| 374 | if (err == 0) { |
| 375 | dlpap = (dl_phys_addr_ack_t *)mp->b_rptr; |
| 376 | paddrlen = dlpap->dl_addr_length; |
| 377 | paddroff = dlpap->dl_addr_offset; |
| 378 | if (paddroff == 0 || paddrlen == 0 || paddrlen > *physlenp || |
| 379 | !MBLKIN(mp, paddroff, paddrlen)) { |
| 380 | cmn_err(CE_NOTE, "!dl_phys_addr: DL_PHYS_ADDR_ACK: " |
| 381 | "bad length/offset %d/%d", paddrlen, paddroff); |
| 382 | err = EBADMSG; |
| 383 | } else { |
| 384 | bcopy(mp->b_rptr + paddroff, physaddr, paddrlen); |
| 385 | *physlenp = paddrlen; |
| 386 | } |
| 387 | freemsg(mp); |
| 388 | } |
| 389 | return (err); |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | * Send a DL_INFO_REQ over `lh' and wait for the response. The caller must |
| 394 | * pass a non-NULL `dliap', which upon success will contain the dl_info_ack_t |
| 395 | * from the provider. The caller may optionally get the provider's physical |
| 396 | * address by passing a non-NULL `physaddr' and setting `*physlenp' to its |
| 397 | * size; upon success they will be updated to contain the actual physical |
| 398 | * address and its length. |
| 399 | * |
| 400 | * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the |
| 401 | * caller can get the contents by passing a non-NULL `dleap'). |
| 402 | */ |
| 403 | int |
| 404 | dl_info(ldi_handle_t lh, dl_info_ack_t *dliap, uchar_t *physaddr, |
| 405 | size_t *physlenp, dl_error_ack_t *dleap) |
| 406 | { |
| 407 | mblk_t *mp; |
| 408 | int err; |
| 409 | int addrlen, addroff; |
| 410 | |
| 411 | mp = mexchange(NULL, NULL, DL_INFO_REQ_SIZE, M_PCPROTO, DL_INFO_REQ); |
| 412 | if (mp == NULL) |
| 413 | return (ENOMEM); |
| 414 | |
| 415 | err = dl_op(lh, &mp, DL_INFO_ACK, DL_INFO_ACK_SIZE, dleap, NULL); |
| 416 | if (err != 0) |
| 417 | return (err); |
| 418 | |
| 419 | *dliap = *(dl_info_ack_t *)mp->b_rptr; |
| 420 | if (physaddr != NULL) { |
| 421 | addrlen = dliap->dl_addr_length - ABS(dliap->dl_sap_length); |
| 422 | addroff = dliap->dl_addr_offset; |
| 423 | if (addroff == 0 || addrlen <= 0 || addrlen > *physlenp || |
| 424 | !MBLKIN(mp, addroff, dliap->dl_addr_length)) { |
| 425 | cmn_err(CE_NOTE, "!dl_info: DL_INFO_ACK: " |
| 426 | "bad length/offset %d/%d", addrlen, addroff); |
| 427 | freemsg(mp); |
| 428 | return (EBADMSG); |
| 429 | } |
| 430 | |
| 431 | if (dliap->dl_sap_length > 0) |
| 432 | addroff += dliap->dl_sap_length; |
| 433 | bcopy(mp->b_rptr + addroff, physaddr, addrlen); |
| 434 | *physlenp = addrlen; |
| 435 | } |
| 436 | freemsg(mp); |
| 437 | return (err); |
| 438 | } |
| 439 | |
| 440 | /* |
| 441 | * Send a DL_NOTIFY_REQ over `lh' and wait for the response. The caller |
| 442 | * should set `notesp' to the set of notifications they wish to enable; |
| 443 | * upon success it will contain the notifications enabled by the provider. |
| 444 | * |
| 445 | * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the |
| 446 | * caller can get the contents by passing a non-NULL `dleap'). |
| 447 | */ |
| 448 | int |
| 449 | dl_notify(ldi_handle_t lh, uint32_t *notesp, dl_error_ack_t *dleap) |
| 450 | { |
| 451 | mblk_t *mp; |
| 452 | int err; |
| 453 | |
| 454 | mp = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO, DL_NOTIFY_REQ); |
| 455 | if (mp == NULL) |
| 456 | return (ENOMEM); |
| 457 | |
| 458 | ((dl_notify_req_t *)mp->b_rptr)->dl_notifications = *notesp; |
| 459 | |
| 460 | err = dl_op(lh, &mp, DL_NOTIFY_ACK, DL_NOTIFY_ACK_SIZE, dleap, NULL); |
| 461 | if (err == 0) { |
| 462 | *notesp = ((dl_notify_ack_t *)mp->b_rptr)->dl_notifications; |
| 463 | freemsg(mp); |
| 464 | } |
| 465 | return (err); |
| 466 | } |
| 467 | |
| 468 | const char * |
| 469 | dl_primstr(t_uscalar_t prim) |
| 470 | { |
| 471 | switch (prim) { |
| 472 | case DL_INFO_REQ: return ("DL_INFO_REQ"); |
| 473 | case DL_INFO_ACK: return ("DL_INFO_ACK"); |
| 474 | case DL_ATTACH_REQ: return ("DL_ATTACH_REQ"); |
| 475 | case DL_DETACH_REQ: return ("DL_DETACH_REQ"); |
| 476 | case DL_BIND_REQ: return ("DL_BIND_REQ"); |
| 477 | case DL_BIND_ACK: return ("DL_BIND_ACK"); |
| 478 | case DL_UNBIND_REQ: return ("DL_UNBIND_REQ"); |
| 479 | case DL_OK_ACK: return ("DL_OK_ACK"); |
| 480 | case DL_ERROR_ACK: return ("DL_ERROR_ACK"); |
| 481 | case DL_ENABMULTI_REQ: return ("DL_ENABMULTI_REQ"); |
| 482 | case DL_DISABMULTI_REQ: return ("DL_DISABMULTI_REQ"); |
| 483 | case DL_PROMISCON_REQ: return ("DL_PROMISCON_REQ"); |
| 484 | case DL_PROMISCOFF_REQ: return ("DL_PROMISCOFF_REQ"); |
| 485 | case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ"); |
| 486 | case DL_UNITDATA_IND: return ("DL_UNITDATA_IND"); |
| 487 | case DL_UDERROR_IND: return ("DL_UDERROR_IND"); |
| 488 | case DL_PHYS_ADDR_REQ: return ("DL_PHYS_ADDR_REQ"); |
| 489 | case DL_PHYS_ADDR_ACK: return ("DL_PHYS_ADDR_ACK"); |
| 490 | case DL_SET_PHYS_ADDR_REQ: return ("DL_SET_PHYS_ADDR_REQ"); |
| 491 | case DL_NOTIFY_REQ: return ("DL_NOTIFY_REQ"); |
| 492 | case DL_NOTIFY_ACK: return ("DL_NOTIFY_ACK"); |
| 493 | case DL_NOTIFY_IND: return ("DL_NOTIFY_IND"); |
Cathy Zhou | 5d460ea | 2009-03-17 20:14:50 -0700 | [diff] [blame] | 494 | case DL_NOTIFY_CONF: return ("DL_NOTIFY_CONF"); |
yz147064 | d62bc4b | 2008-01-23 18:09:15 -0800 | [diff] [blame] | 495 | case DL_CAPABILITY_REQ: return ("DL_CAPABILITY_REQ"); |
| 496 | case DL_CAPABILITY_ACK: return ("DL_CAPABILITY_ACK"); |
| 497 | case DL_CONTROL_REQ: return ("DL_CONTROL_REQ"); |
| 498 | case DL_CONTROL_ACK: return ("DL_CONTROL_ACK"); |
| 499 | case DL_PASSIVE_REQ: return ("DL_PASSIVE_REQ"); |
| 500 | case DL_INTR_MODE_REQ: return ("DL_INTR_MODE_REQ"); |
| 501 | case DL_UDQOS_REQ: return ("DL_UDQOS_REQ"); |
| 502 | default: return ("<unknown primitive>"); |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | const char * |
| 507 | dl_errstr(t_uscalar_t err) |
| 508 | { |
| 509 | switch (err) { |
| 510 | case DL_ACCESS: return ("DL_ACCESS"); |
| 511 | case DL_BADADDR: return ("DL_BADADDR"); |
| 512 | case DL_BADCORR: return ("DL_BADCORR"); |
| 513 | case DL_BADDATA: return ("DL_BADDATA"); |
| 514 | case DL_BADPPA: return ("DL_BADPPA"); |
| 515 | case DL_BADPRIM: return ("DL_BADPRIM"); |
| 516 | case DL_BADQOSPARAM: return ("DL_BADQOSPARAM"); |
| 517 | case DL_BADQOSTYPE: return ("DL_BADQOSTYPE"); |
| 518 | case DL_BADSAP: return ("DL_BADSAP"); |
| 519 | case DL_BADTOKEN: return ("DL_BADTOKEN"); |
| 520 | case DL_BOUND: return ("DL_BOUND"); |
| 521 | case DL_INITFAILED: return ("DL_INITFAILED"); |
| 522 | case DL_NOADDR: return ("DL_NOADDR"); |
| 523 | case DL_NOTINIT: return ("DL_NOTINIT"); |
| 524 | case DL_OUTSTATE: return ("DL_OUTSTATE"); |
| 525 | case DL_SYSERR: return ("DL_SYSERR"); |
| 526 | case DL_UNSUPPORTED: return ("DL_UNSUPPORTED"); |
| 527 | case DL_UNDELIVERABLE: return ("DL_UNDELIVERABLE"); |
| 528 | case DL_NOTSUPPORTED: return ("DL_NOTSUPPORTED "); |
| 529 | case DL_TOOMANY: return ("DL_TOOMANY"); |
| 530 | case DL_NOTENAB: return ("DL_NOTENAB"); |
| 531 | case DL_BUSY: return ("DL_BUSY"); |
| 532 | case DL_NOAUTO: return ("DL_NOAUTO"); |
| 533 | case DL_NOXIDAUTO: return ("DL_NOXIDAUTO"); |
| 534 | case DL_NOTESTAUTO: return ("DL_NOTESTAUTO"); |
| 535 | case DL_XIDAUTO: return ("DL_XIDAUTO"); |
| 536 | case DL_TESTAUTO: return ("DL_TESTAUTO"); |
| 537 | case DL_PENDING: return ("DL_PENDING"); |
| 538 | default: return ("<unknown error>"); |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | const char * |
| 543 | dl_mactypestr(t_uscalar_t mactype) |
| 544 | { |
| 545 | switch (mactype) { |
| 546 | case DL_CSMACD: return ("CSMA/CD"); |
| 547 | case DL_TPB: return ("Token Bus"); |
| 548 | case DL_TPR: return ("Token Ring"); |
| 549 | case DL_METRO: return ("Metro Net"); |
| 550 | case DL_ETHER: return ("Ethernet"); |
| 551 | case DL_HDLC: return ("HDLC"); |
| 552 | case DL_CHAR: return ("Sync Character"); |
| 553 | case DL_CTCA: return ("CTCA"); |
| 554 | case DL_FDDI: return ("FDDI"); |
| 555 | case DL_FRAME: return ("Frame Relay (LAPF)"); |
| 556 | case DL_MPFRAME: return ("MP Frame Relay"); |
| 557 | case DL_ASYNC: return ("Async Character"); |
| 558 | case DL_IPX25: return ("X.25 (Classic IP)"); |
| 559 | case DL_LOOP: return ("Software Loopback"); |
| 560 | case DL_FC: return ("Fiber Channel"); |
| 561 | case DL_ATM: return ("ATM"); |
| 562 | case DL_IPATM: return ("ATM (Classic IP)"); |
| 563 | case DL_X25: return ("X.25 (LAPB)"); |
| 564 | case DL_ISDN: return ("ISDN"); |
| 565 | case DL_HIPPI: return ("HIPPI"); |
| 566 | case DL_100VG: return ("100BaseVG Ethernet"); |
| 567 | case DL_100VGTPR: return ("100BaseVG Token Ring"); |
| 568 | case DL_ETH_CSMA: return ("Ethernet/IEEE 802.3"); |
| 569 | case DL_100BT: return ("100BaseT"); |
| 570 | case DL_IB: return ("Infiniband"); |
| 571 | case DL_IPV4: return ("IPv4 Tunnel"); |
| 572 | case DL_IPV6: return ("IPv6 Tunnel"); |
| 573 | case DL_WIFI: return ("IEEE 802.11"); |
Philip Kirk | b127ac4 | 2008-11-06 06:47:54 -0500 | [diff] [blame] | 574 | case DL_IPNET: return ("IPNET"); |
yz147064 | d62bc4b | 2008-01-23 18:09:15 -0800 | [diff] [blame] | 575 | default: return ("<unknown mactype>"); |
| 576 | } |
| 577 | } |