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 5392b1d6eSyz147064 * Common Development and Distribution License (the "License"). 6392b1d6eSyz147064 * 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 /* 223a18a1c1Smeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Common Sun DLPI routines. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 327c478bd9Sstevel@tonic-gate #include <sys/byteorder.h> 337c478bd9Sstevel@tonic-gate #include <sys/stream.h> 347c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 357c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 36d62bc4baSyz147064 #include <sys/ddi.h> 37d62bc4baSyz147064 #include <sys/sunddi.h> 38d62bc4baSyz147064 #include <sys/sunldi.h> 39d62bc4baSyz147064 #include <sys/cmn_err.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate void 427c478bd9Sstevel@tonic-gate dlbindack( 437c478bd9Sstevel@tonic-gate queue_t *wq, 447c478bd9Sstevel@tonic-gate mblk_t *mp, 457c478bd9Sstevel@tonic-gate t_scalar_t sap, 463a18a1c1Smeem const void *addrp, 477c478bd9Sstevel@tonic-gate t_uscalar_t addrlen, 487c478bd9Sstevel@tonic-gate t_uscalar_t maxconind, 497c478bd9Sstevel@tonic-gate t_uscalar_t xidtest) 507c478bd9Sstevel@tonic-gate { 517c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 527c478bd9Sstevel@tonic-gate size_t size; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate size = sizeof (dl_bind_ack_t) + addrlen; 557c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL) 567c478bd9Sstevel@tonic-gate return; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 597c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_sap = sap; 607c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_addr_length = addrlen; 617c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_addr_offset = sizeof (dl_bind_ack_t); 627c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_max_conind = maxconind; 637c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_xidtest_flg = xidtest; 647c478bd9Sstevel@tonic-gate if (addrlen != 0) 657c478bd9Sstevel@tonic-gate bcopy(addrp, mp->b_rptr + sizeof (dl_bind_ack_t), addrlen); 667c478bd9Sstevel@tonic-gate qreply(wq, mp); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate void 707c478bd9Sstevel@tonic-gate dlokack( 717c478bd9Sstevel@tonic-gate queue_t *wq, 727c478bd9Sstevel@tonic-gate mblk_t *mp, 737c478bd9Sstevel@tonic-gate t_uscalar_t correct_primitive) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PCPROTO, 787c478bd9Sstevel@tonic-gate DL_OK_ACK)) == NULL) 797c478bd9Sstevel@tonic-gate return; 807c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 817c478bd9Sstevel@tonic-gate dlp->ok_ack.dl_correct_primitive = correct_primitive; 827c478bd9Sstevel@tonic-gate qreply(wq, mp); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate void 867c478bd9Sstevel@tonic-gate dlerrorack( 877c478bd9Sstevel@tonic-gate queue_t *wq, 887c478bd9Sstevel@tonic-gate mblk_t *mp, 897c478bd9Sstevel@tonic-gate t_uscalar_t error_primitive, 907c478bd9Sstevel@tonic-gate t_uscalar_t error, 917c478bd9Sstevel@tonic-gate t_uscalar_t unix_errno) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, sizeof (dl_error_ack_t), M_PCPROTO, 967c478bd9Sstevel@tonic-gate DL_ERROR_ACK)) == NULL) 977c478bd9Sstevel@tonic-gate return; 987c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 997c478bd9Sstevel@tonic-gate dlp->error_ack.dl_error_primitive = error_primitive; 1007c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno = error; 1017c478bd9Sstevel@tonic-gate dlp->error_ack.dl_unix_errno = unix_errno; 1027c478bd9Sstevel@tonic-gate qreply(wq, mp); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate void 1067c478bd9Sstevel@tonic-gate dluderrorind( 1077c478bd9Sstevel@tonic-gate queue_t *wq, 1087c478bd9Sstevel@tonic-gate mblk_t *mp, 1093a18a1c1Smeem const void *addrp, 1107c478bd9Sstevel@tonic-gate t_uscalar_t addrlen, 1117c478bd9Sstevel@tonic-gate t_uscalar_t error, 1127c478bd9Sstevel@tonic-gate t_uscalar_t unix_errno) 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 1157c478bd9Sstevel@tonic-gate size_t size; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate size = sizeof (dl_uderror_ind_t) + addrlen; 1187c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_UDERROR_IND)) == NULL) 1197c478bd9Sstevel@tonic-gate return; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1227c478bd9Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_length = addrlen; 1237c478bd9Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_offset = sizeof (dl_uderror_ind_t); 1247c478bd9Sstevel@tonic-gate dlp->uderror_ind.dl_unix_errno = unix_errno; 1257c478bd9Sstevel@tonic-gate dlp->uderror_ind.dl_errno = error; 1263a18a1c1Smeem if (addrlen != 0) 1273a18a1c1Smeem bcopy(addrp, mp->b_rptr + sizeof (dl_uderror_ind_t), addrlen); 1287c478bd9Sstevel@tonic-gate qreply(wq, mp); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate void 1327c478bd9Sstevel@tonic-gate dlphysaddrack( 1337c478bd9Sstevel@tonic-gate queue_t *wq, 1347c478bd9Sstevel@tonic-gate mblk_t *mp, 1353a18a1c1Smeem const void *addrp, 1367c478bd9Sstevel@tonic-gate t_uscalar_t len) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 1397c478bd9Sstevel@tonic-gate size_t size; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate size = sizeof (dl_phys_addr_ack_t) + len; 1427c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_PHYS_ADDR_ACK)) == NULL) 1437c478bd9Sstevel@tonic-gate return; 1447c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1457c478bd9Sstevel@tonic-gate dlp->physaddr_ack.dl_addr_length = len; 1467c478bd9Sstevel@tonic-gate dlp->physaddr_ack.dl_addr_offset = sizeof (dl_phys_addr_ack_t); 1477c478bd9Sstevel@tonic-gate if (len != 0) 1487c478bd9Sstevel@tonic-gate bcopy(addrp, mp->b_rptr + sizeof (dl_phys_addr_ack_t), len); 1497c478bd9Sstevel@tonic-gate qreply(wq, mp); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate void 1537c478bd9Sstevel@tonic-gate dlcapabsetqid(dl_mid_t *idp, const queue_t *q) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate #ifndef _LP64 1567c478bd9Sstevel@tonic-gate idp->mid[0] = (t_uscalar_t)q; 1577c478bd9Sstevel@tonic-gate #else 1587c478bd9Sstevel@tonic-gate idp->mid[0] = (t_uscalar_t)BMASK_32((uint64_t)q); 1597c478bd9Sstevel@tonic-gate idp->mid[1] = (t_uscalar_t)BMASK_32(((uint64_t)q) >> 32); 1607c478bd9Sstevel@tonic-gate #endif 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate boolean_t 1647c478bd9Sstevel@tonic-gate dlcapabcheckqid(const dl_mid_t *idp, const queue_t *q) 1657c478bd9Sstevel@tonic-gate { 1667c478bd9Sstevel@tonic-gate #ifndef _LP64 1677c478bd9Sstevel@tonic-gate return ((queue_t *)(idp->mid[0]) == q); 1687c478bd9Sstevel@tonic-gate #else 1697c478bd9Sstevel@tonic-gate return ((queue_t *) 1707c478bd9Sstevel@tonic-gate ((uint64_t)idp->mid[0] | ((uint64_t)idp->mid[1] << 32)) == q); 1717c478bd9Sstevel@tonic-gate #endif 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate void 1757c478bd9Sstevel@tonic-gate dlnotifyack( 1767c478bd9Sstevel@tonic-gate queue_t *wq, 1777c478bd9Sstevel@tonic-gate mblk_t *mp, 1787c478bd9Sstevel@tonic-gate uint32_t notifications) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 1817c478bd9Sstevel@tonic-gate 182392b1d6eSyz147064 if ((mp = mexchange(wq, mp, sizeof (dl_notify_ack_t), M_PROTO, 1837c478bd9Sstevel@tonic-gate DL_NOTIFY_ACK)) == NULL) 1847c478bd9Sstevel@tonic-gate return; 1857c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1867c478bd9Sstevel@tonic-gate dlp->notify_ack.dl_notifications = notifications; 1877c478bd9Sstevel@tonic-gate qreply(wq, mp); 1887c478bd9Sstevel@tonic-gate } 189d62bc4baSyz147064 190d62bc4baSyz147064 static int 191d62bc4baSyz147064 dl_op(ldi_handle_t lh, mblk_t **mpp, t_uscalar_t expprim, size_t minlen, 192d62bc4baSyz147064 dl_error_ack_t *dleap, timestruc_t *tvp) 193d62bc4baSyz147064 { 194d62bc4baSyz147064 int err; 195d62bc4baSyz147064 size_t len; 196d62bc4baSyz147064 mblk_t *mp = *mpp; 197d62bc4baSyz147064 t_uscalar_t reqprim, ackprim, ackreqprim; 198d62bc4baSyz147064 union DL_primitives *dlp; 199d62bc4baSyz147064 200d62bc4baSyz147064 reqprim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; 201d62bc4baSyz147064 202d62bc4baSyz147064 (void) ldi_putmsg(lh, mp); 203d62bc4baSyz147064 204d62bc4baSyz147064 switch (err = ldi_getmsg(lh, &mp, tvp)) { 205d62bc4baSyz147064 case 0: 206d62bc4baSyz147064 break; 207d62bc4baSyz147064 case ETIME: 208d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: timed out waiting for %s to %s", 209d62bc4baSyz147064 dl_primstr(reqprim), dl_primstr(expprim)); 210d62bc4baSyz147064 return (ETIME); 211d62bc4baSyz147064 default: 212d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: ldi_getmsg() for %s failed: %d", 213d62bc4baSyz147064 dl_primstr(expprim), err); 214d62bc4baSyz147064 return (err); 215d62bc4baSyz147064 } 216d62bc4baSyz147064 217d62bc4baSyz147064 len = MBLKL(mp); 218d62bc4baSyz147064 if (len < sizeof (t_uscalar_t)) { 219d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: received runt DLPI message"); 220d62bc4baSyz147064 freemsg(mp); 221d62bc4baSyz147064 return (EBADMSG); 222d62bc4baSyz147064 } 223d62bc4baSyz147064 224d62bc4baSyz147064 dlp = (union DL_primitives *)mp->b_rptr; 225d62bc4baSyz147064 ackprim = dlp->dl_primitive; 226d62bc4baSyz147064 227d62bc4baSyz147064 if (ackprim == expprim) { 228d62bc4baSyz147064 if (len < minlen) 229d62bc4baSyz147064 goto runt; 230d62bc4baSyz147064 231d62bc4baSyz147064 if (ackprim == DL_OK_ACK) { 232d62bc4baSyz147064 if (dlp->ok_ack.dl_correct_primitive != reqprim) { 233d62bc4baSyz147064 ackreqprim = dlp->ok_ack.dl_correct_primitive; 234d62bc4baSyz147064 goto mixup; 235d62bc4baSyz147064 } 236d62bc4baSyz147064 } 237d62bc4baSyz147064 *mpp = mp; 238d62bc4baSyz147064 return (0); 239d62bc4baSyz147064 } 240d62bc4baSyz147064 241d62bc4baSyz147064 if (ackprim == DL_ERROR_ACK) { 242d62bc4baSyz147064 if (len < DL_ERROR_ACK_SIZE) 243d62bc4baSyz147064 goto runt; 244d62bc4baSyz147064 245d62bc4baSyz147064 if (dlp->error_ack.dl_error_primitive != reqprim) { 246d62bc4baSyz147064 ackreqprim = dlp->error_ack.dl_error_primitive; 247d62bc4baSyz147064 goto mixup; 248d62bc4baSyz147064 } 249d62bc4baSyz147064 250d62bc4baSyz147064 /* 251d62bc4baSyz147064 * Return a special error code (ENOTSUP) indicating that the 252d62bc4baSyz147064 * caller has returned DL_ERROR_ACK. Callers that want more 253d62bc4baSyz147064 * details an pass a non-NULL dleap. 254d62bc4baSyz147064 */ 255d62bc4baSyz147064 if (dleap != NULL) 256d62bc4baSyz147064 *dleap = dlp->error_ack; 257d62bc4baSyz147064 258d62bc4baSyz147064 freemsg(mp); 259d62bc4baSyz147064 return (ENOTSUP); 260d62bc4baSyz147064 } 261d62bc4baSyz147064 262d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: expected %s but received %s", 263d62bc4baSyz147064 dl_primstr(expprim), dl_primstr(ackprim)); 264d62bc4baSyz147064 freemsg(mp); 265d62bc4baSyz147064 return (EBADMSG); 266d62bc4baSyz147064 runt: 267d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: received runt %s", dl_primstr(ackprim)); 268d62bc4baSyz147064 freemsg(mp); 269d62bc4baSyz147064 return (EBADMSG); 270d62bc4baSyz147064 mixup: 271d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_op: received %s for %s instead of %s", 272d62bc4baSyz147064 dl_primstr(ackprim), dl_primstr(ackreqprim), dl_primstr(reqprim)); 273d62bc4baSyz147064 freemsg(mp); 274d62bc4baSyz147064 return (EBADMSG); 275d62bc4baSyz147064 } 276d62bc4baSyz147064 277d62bc4baSyz147064 /* 278d62bc4baSyz147064 * Send a DL_ATTACH_REQ for `ppa' over `lh' and wait for the response. 279d62bc4baSyz147064 * 280d62bc4baSyz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 281d62bc4baSyz147064 * caller can get the contents by passing a non-NULL `dleap'). 282d62bc4baSyz147064 */ 283d62bc4baSyz147064 int 284d62bc4baSyz147064 dl_attach(ldi_handle_t lh, int ppa, dl_error_ack_t *dleap) 285d62bc4baSyz147064 { 286d62bc4baSyz147064 mblk_t *mp; 287d62bc4baSyz147064 int err; 288d62bc4baSyz147064 289d62bc4baSyz147064 mp = mexchange(NULL, NULL, DL_ATTACH_REQ_SIZE, M_PROTO, DL_ATTACH_REQ); 290d62bc4baSyz147064 if (mp == NULL) 291d62bc4baSyz147064 return (ENOMEM); 292d62bc4baSyz147064 293d62bc4baSyz147064 ((dl_attach_req_t *)mp->b_rptr)->dl_ppa = ppa; 294d62bc4baSyz147064 295d62bc4baSyz147064 err = dl_op(lh, &mp, DL_OK_ACK, DL_OK_ACK_SIZE, dleap, NULL); 296d62bc4baSyz147064 if (err == 0) 297d62bc4baSyz147064 freemsg(mp); 298d62bc4baSyz147064 return (err); 299d62bc4baSyz147064 } 300d62bc4baSyz147064 301d62bc4baSyz147064 /* 302d62bc4baSyz147064 * Send a DL_BIND_REQ for `sap' over `lh' and wait for the response. 303d62bc4baSyz147064 * 304d62bc4baSyz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 305d62bc4baSyz147064 * caller can get the contents by passing a non-NULL `dleap'). 306d62bc4baSyz147064 */ 307d62bc4baSyz147064 int 308d62bc4baSyz147064 dl_bind(ldi_handle_t lh, uint_t sap, dl_error_ack_t *dleap) 309d62bc4baSyz147064 { 310d62bc4baSyz147064 dl_bind_req_t *dlbrp; 311d62bc4baSyz147064 dl_bind_ack_t *dlbap; 312d62bc4baSyz147064 mblk_t *mp; 313d62bc4baSyz147064 int err; 314d62bc4baSyz147064 315d62bc4baSyz147064 mp = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ); 316d62bc4baSyz147064 if (mp == NULL) 317d62bc4baSyz147064 return (ENOMEM); 318d62bc4baSyz147064 319d62bc4baSyz147064 dlbrp = (dl_bind_req_t *)mp->b_rptr; 320d62bc4baSyz147064 dlbrp->dl_sap = sap; 321d62bc4baSyz147064 dlbrp->dl_conn_mgmt = 0; 322d62bc4baSyz147064 dlbrp->dl_max_conind = 0; 323d62bc4baSyz147064 dlbrp->dl_xidtest_flg = 0; 324d62bc4baSyz147064 dlbrp->dl_service_mode = DL_CLDLS; 325d62bc4baSyz147064 326d62bc4baSyz147064 err = dl_op(lh, &mp, DL_BIND_ACK, DL_BIND_ACK_SIZE, dleap, NULL); 327d62bc4baSyz147064 if (err == 0) { 328d62bc4baSyz147064 dlbap = (dl_bind_ack_t *)mp->b_rptr; 329d62bc4baSyz147064 if (dlbap->dl_sap != sap) { 330d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_bind: DL_BIND_ACK: bad sap %u", 331d62bc4baSyz147064 dlbap->dl_sap); 332d62bc4baSyz147064 err = EPROTO; 333d62bc4baSyz147064 } 334d62bc4baSyz147064 freemsg(mp); 335d62bc4baSyz147064 } 336d62bc4baSyz147064 return (err); 337d62bc4baSyz147064 } 338d62bc4baSyz147064 339d62bc4baSyz147064 /* 340d62bc4baSyz147064 * Send a DL_PHYS_ADDR_REQ over `lh' and wait for the response. The caller 341d62bc4baSyz147064 * must set `*physlenp' to the size of `physaddr' (both of which must be 342d62bc4baSyz147064 * non-NULL); upon success they will be updated to contain the actual physical 343d62bc4baSyz147064 * address and length. 344d62bc4baSyz147064 * 345d62bc4baSyz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 346d62bc4baSyz147064 * caller can get the contents by passing a non-NULL `dleap'). 347d62bc4baSyz147064 */ 348d62bc4baSyz147064 int 349d62bc4baSyz147064 dl_phys_addr(ldi_handle_t lh, uchar_t *physaddr, size_t *physlenp, 350d62bc4baSyz147064 dl_error_ack_t *dleap) 351d62bc4baSyz147064 { 352d62bc4baSyz147064 dl_phys_addr_ack_t *dlpap; 353d62bc4baSyz147064 mblk_t *mp; 354d62bc4baSyz147064 int err; 355d62bc4baSyz147064 t_uscalar_t paddrlen, paddroff; 356d62bc4baSyz147064 timestruc_t tv; 357d62bc4baSyz147064 358d62bc4baSyz147064 mp = mexchange(NULL, NULL, DL_PHYS_ADDR_REQ_SIZE, M_PROTO, 359d62bc4baSyz147064 DL_PHYS_ADDR_REQ); 360d62bc4baSyz147064 if (mp == NULL) 361d62bc4baSyz147064 return (ENOMEM); 362d62bc4baSyz147064 363d62bc4baSyz147064 ((dl_phys_addr_req_t *)mp->b_rptr)->dl_addr_type = DL_CURR_PHYS_ADDR; 364d62bc4baSyz147064 365d62bc4baSyz147064 /* 366d62bc4baSyz147064 * In case some provider doesn't implement or NAK the 367d62bc4baSyz147064 * request, just wait for 15 seconds. 368d62bc4baSyz147064 */ 369d62bc4baSyz147064 tv.tv_sec = 15; 370d62bc4baSyz147064 tv.tv_nsec = 0; 371d62bc4baSyz147064 372d62bc4baSyz147064 err = dl_op(lh, &mp, DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, dleap, 373d62bc4baSyz147064 &tv); 374d62bc4baSyz147064 if (err == 0) { 375d62bc4baSyz147064 dlpap = (dl_phys_addr_ack_t *)mp->b_rptr; 376d62bc4baSyz147064 paddrlen = dlpap->dl_addr_length; 377d62bc4baSyz147064 paddroff = dlpap->dl_addr_offset; 378d62bc4baSyz147064 if (paddroff == 0 || paddrlen == 0 || paddrlen > *physlenp || 379d62bc4baSyz147064 !MBLKIN(mp, paddroff, paddrlen)) { 380d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_phys_addr: DL_PHYS_ADDR_ACK: " 381d62bc4baSyz147064 "bad length/offset %d/%d", paddrlen, paddroff); 382d62bc4baSyz147064 err = EBADMSG; 383d62bc4baSyz147064 } else { 384d62bc4baSyz147064 bcopy(mp->b_rptr + paddroff, physaddr, paddrlen); 385d62bc4baSyz147064 *physlenp = paddrlen; 386d62bc4baSyz147064 } 387d62bc4baSyz147064 freemsg(mp); 388d62bc4baSyz147064 } 389d62bc4baSyz147064 return (err); 390d62bc4baSyz147064 } 391d62bc4baSyz147064 392d62bc4baSyz147064 /* 393d62bc4baSyz147064 * Send a DL_INFO_REQ over `lh' and wait for the response. The caller must 394d62bc4baSyz147064 * pass a non-NULL `dliap', which upon success will contain the dl_info_ack_t 395d62bc4baSyz147064 * from the provider. The caller may optionally get the provider's physical 396d62bc4baSyz147064 * address by passing a non-NULL `physaddr' and setting `*physlenp' to its 397d62bc4baSyz147064 * size; upon success they will be updated to contain the actual physical 398d62bc4baSyz147064 * address and its length. 399d62bc4baSyz147064 * 400d62bc4baSyz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 401d62bc4baSyz147064 * caller can get the contents by passing a non-NULL `dleap'). 402d62bc4baSyz147064 */ 403d62bc4baSyz147064 int 404d62bc4baSyz147064 dl_info(ldi_handle_t lh, dl_info_ack_t *dliap, uchar_t *physaddr, 405d62bc4baSyz147064 size_t *physlenp, dl_error_ack_t *dleap) 406d62bc4baSyz147064 { 407d62bc4baSyz147064 mblk_t *mp; 408d62bc4baSyz147064 int err; 409d62bc4baSyz147064 int addrlen, addroff; 410d62bc4baSyz147064 411d62bc4baSyz147064 mp = mexchange(NULL, NULL, DL_INFO_REQ_SIZE, M_PCPROTO, DL_INFO_REQ); 412d62bc4baSyz147064 if (mp == NULL) 413d62bc4baSyz147064 return (ENOMEM); 414d62bc4baSyz147064 415d62bc4baSyz147064 err = dl_op(lh, &mp, DL_INFO_ACK, DL_INFO_ACK_SIZE, dleap, NULL); 416d62bc4baSyz147064 if (err != 0) 417d62bc4baSyz147064 return (err); 418d62bc4baSyz147064 419d62bc4baSyz147064 *dliap = *(dl_info_ack_t *)mp->b_rptr; 420d62bc4baSyz147064 if (physaddr != NULL) { 421d62bc4baSyz147064 addrlen = dliap->dl_addr_length - ABS(dliap->dl_sap_length); 422d62bc4baSyz147064 addroff = dliap->dl_addr_offset; 423d62bc4baSyz147064 if (addroff == 0 || addrlen <= 0 || addrlen > *physlenp || 424d62bc4baSyz147064 !MBLKIN(mp, addroff, dliap->dl_addr_length)) { 425d62bc4baSyz147064 cmn_err(CE_NOTE, "!dl_info: DL_INFO_ACK: " 426d62bc4baSyz147064 "bad length/offset %d/%d", addrlen, addroff); 427d62bc4baSyz147064 freemsg(mp); 428d62bc4baSyz147064 return (EBADMSG); 429d62bc4baSyz147064 } 430d62bc4baSyz147064 431d62bc4baSyz147064 if (dliap->dl_sap_length > 0) 432d62bc4baSyz147064 addroff += dliap->dl_sap_length; 433d62bc4baSyz147064 bcopy(mp->b_rptr + addroff, physaddr, addrlen); 434d62bc4baSyz147064 *physlenp = addrlen; 435d62bc4baSyz147064 } 436d62bc4baSyz147064 freemsg(mp); 437d62bc4baSyz147064 return (err); 438d62bc4baSyz147064 } 439d62bc4baSyz147064 440d62bc4baSyz147064 /* 441d62bc4baSyz147064 * Send a DL_NOTIFY_REQ over `lh' and wait for the response. The caller 442d62bc4baSyz147064 * should set `notesp' to the set of notifications they wish to enable; 443d62bc4baSyz147064 * upon success it will contain the notifications enabled by the provider. 444d62bc4baSyz147064 * 445d62bc4baSyz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 446d62bc4baSyz147064 * caller can get the contents by passing a non-NULL `dleap'). 447d62bc4baSyz147064 */ 448d62bc4baSyz147064 int 449d62bc4baSyz147064 dl_notify(ldi_handle_t lh, uint32_t *notesp, dl_error_ack_t *dleap) 450d62bc4baSyz147064 { 451d62bc4baSyz147064 mblk_t *mp; 452d62bc4baSyz147064 int err; 453d62bc4baSyz147064 454d62bc4baSyz147064 mp = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO, DL_NOTIFY_REQ); 455d62bc4baSyz147064 if (mp == NULL) 456d62bc4baSyz147064 return (ENOMEM); 457d62bc4baSyz147064 458d62bc4baSyz147064 ((dl_notify_req_t *)mp->b_rptr)->dl_notifications = *notesp; 459d62bc4baSyz147064 460d62bc4baSyz147064 err = dl_op(lh, &mp, DL_NOTIFY_ACK, DL_NOTIFY_ACK_SIZE, dleap, NULL); 461d62bc4baSyz147064 if (err == 0) { 462d62bc4baSyz147064 *notesp = ((dl_notify_ack_t *)mp->b_rptr)->dl_notifications; 463d62bc4baSyz147064 freemsg(mp); 464d62bc4baSyz147064 } 465d62bc4baSyz147064 return (err); 466d62bc4baSyz147064 } 467d62bc4baSyz147064 468d62bc4baSyz147064 const char * 469d62bc4baSyz147064 dl_primstr(t_uscalar_t prim) 470d62bc4baSyz147064 { 471d62bc4baSyz147064 switch (prim) { 472d62bc4baSyz147064 case DL_INFO_REQ: return ("DL_INFO_REQ"); 473d62bc4baSyz147064 case DL_INFO_ACK: return ("DL_INFO_ACK"); 474d62bc4baSyz147064 case DL_ATTACH_REQ: return ("DL_ATTACH_REQ"); 475d62bc4baSyz147064 case DL_DETACH_REQ: return ("DL_DETACH_REQ"); 476d62bc4baSyz147064 case DL_BIND_REQ: return ("DL_BIND_REQ"); 477d62bc4baSyz147064 case DL_BIND_ACK: return ("DL_BIND_ACK"); 478d62bc4baSyz147064 case DL_UNBIND_REQ: return ("DL_UNBIND_REQ"); 479d62bc4baSyz147064 case DL_OK_ACK: return ("DL_OK_ACK"); 480d62bc4baSyz147064 case DL_ERROR_ACK: return ("DL_ERROR_ACK"); 481d62bc4baSyz147064 case DL_ENABMULTI_REQ: return ("DL_ENABMULTI_REQ"); 482d62bc4baSyz147064 case DL_DISABMULTI_REQ: return ("DL_DISABMULTI_REQ"); 483d62bc4baSyz147064 case DL_PROMISCON_REQ: return ("DL_PROMISCON_REQ"); 484d62bc4baSyz147064 case DL_PROMISCOFF_REQ: return ("DL_PROMISCOFF_REQ"); 485d62bc4baSyz147064 case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ"); 486d62bc4baSyz147064 case DL_UNITDATA_IND: return ("DL_UNITDATA_IND"); 487d62bc4baSyz147064 case DL_UDERROR_IND: return ("DL_UDERROR_IND"); 488d62bc4baSyz147064 case DL_PHYS_ADDR_REQ: return ("DL_PHYS_ADDR_REQ"); 489d62bc4baSyz147064 case DL_PHYS_ADDR_ACK: return ("DL_PHYS_ADDR_ACK"); 490d62bc4baSyz147064 case DL_SET_PHYS_ADDR_REQ: return ("DL_SET_PHYS_ADDR_REQ"); 491d62bc4baSyz147064 case DL_NOTIFY_REQ: return ("DL_NOTIFY_REQ"); 492d62bc4baSyz147064 case DL_NOTIFY_ACK: return ("DL_NOTIFY_ACK"); 493d62bc4baSyz147064 case DL_NOTIFY_IND: return ("DL_NOTIFY_IND"); 494*5d460eafSCathy Zhou case DL_NOTIFY_CONF: return ("DL_NOTIFY_CONF"); 495d62bc4baSyz147064 case DL_CAPABILITY_REQ: return ("DL_CAPABILITY_REQ"); 496d62bc4baSyz147064 case DL_CAPABILITY_ACK: return ("DL_CAPABILITY_ACK"); 497d62bc4baSyz147064 case DL_CONTROL_REQ: return ("DL_CONTROL_REQ"); 498d62bc4baSyz147064 case DL_CONTROL_ACK: return ("DL_CONTROL_ACK"); 499d62bc4baSyz147064 case DL_PASSIVE_REQ: return ("DL_PASSIVE_REQ"); 500d62bc4baSyz147064 case DL_INTR_MODE_REQ: return ("DL_INTR_MODE_REQ"); 501d62bc4baSyz147064 case DL_UDQOS_REQ: return ("DL_UDQOS_REQ"); 502d62bc4baSyz147064 default: return ("<unknown primitive>"); 503d62bc4baSyz147064 } 504d62bc4baSyz147064 } 505d62bc4baSyz147064 506d62bc4baSyz147064 const char * 507d62bc4baSyz147064 dl_errstr(t_uscalar_t err) 508d62bc4baSyz147064 { 509d62bc4baSyz147064 switch (err) { 510d62bc4baSyz147064 case DL_ACCESS: return ("DL_ACCESS"); 511d62bc4baSyz147064 case DL_BADADDR: return ("DL_BADADDR"); 512d62bc4baSyz147064 case DL_BADCORR: return ("DL_BADCORR"); 513d62bc4baSyz147064 case DL_BADDATA: return ("DL_BADDATA"); 514d62bc4baSyz147064 case DL_BADPPA: return ("DL_BADPPA"); 515d62bc4baSyz147064 case DL_BADPRIM: return ("DL_BADPRIM"); 516d62bc4baSyz147064 case DL_BADQOSPARAM: return ("DL_BADQOSPARAM"); 517d62bc4baSyz147064 case DL_BADQOSTYPE: return ("DL_BADQOSTYPE"); 518d62bc4baSyz147064 case DL_BADSAP: return ("DL_BADSAP"); 519d62bc4baSyz147064 case DL_BADTOKEN: return ("DL_BADTOKEN"); 520d62bc4baSyz147064 case DL_BOUND: return ("DL_BOUND"); 521d62bc4baSyz147064 case DL_INITFAILED: return ("DL_INITFAILED"); 522d62bc4baSyz147064 case DL_NOADDR: return ("DL_NOADDR"); 523d62bc4baSyz147064 case DL_NOTINIT: return ("DL_NOTINIT"); 524d62bc4baSyz147064 case DL_OUTSTATE: return ("DL_OUTSTATE"); 525d62bc4baSyz147064 case DL_SYSERR: return ("DL_SYSERR"); 526d62bc4baSyz147064 case DL_UNSUPPORTED: return ("DL_UNSUPPORTED"); 527d62bc4baSyz147064 case DL_UNDELIVERABLE: return ("DL_UNDELIVERABLE"); 528d62bc4baSyz147064 case DL_NOTSUPPORTED: return ("DL_NOTSUPPORTED "); 529d62bc4baSyz147064 case DL_TOOMANY: return ("DL_TOOMANY"); 530d62bc4baSyz147064 case DL_NOTENAB: return ("DL_NOTENAB"); 531d62bc4baSyz147064 case DL_BUSY: return ("DL_BUSY"); 532d62bc4baSyz147064 case DL_NOAUTO: return ("DL_NOAUTO"); 533d62bc4baSyz147064 case DL_NOXIDAUTO: return ("DL_NOXIDAUTO"); 534d62bc4baSyz147064 case DL_NOTESTAUTO: return ("DL_NOTESTAUTO"); 535d62bc4baSyz147064 case DL_XIDAUTO: return ("DL_XIDAUTO"); 536d62bc4baSyz147064 case DL_TESTAUTO: return ("DL_TESTAUTO"); 537d62bc4baSyz147064 case DL_PENDING: return ("DL_PENDING"); 538d62bc4baSyz147064 default: return ("<unknown error>"); 539d62bc4baSyz147064 } 540d62bc4baSyz147064 } 541d62bc4baSyz147064 542d62bc4baSyz147064 const char * 543d62bc4baSyz147064 dl_mactypestr(t_uscalar_t mactype) 544d62bc4baSyz147064 { 545d62bc4baSyz147064 switch (mactype) { 546d62bc4baSyz147064 case DL_CSMACD: return ("CSMA/CD"); 547d62bc4baSyz147064 case DL_TPB: return ("Token Bus"); 548d62bc4baSyz147064 case DL_TPR: return ("Token Ring"); 549d62bc4baSyz147064 case DL_METRO: return ("Metro Net"); 550d62bc4baSyz147064 case DL_ETHER: return ("Ethernet"); 551d62bc4baSyz147064 case DL_HDLC: return ("HDLC"); 552d62bc4baSyz147064 case DL_CHAR: return ("Sync Character"); 553d62bc4baSyz147064 case DL_CTCA: return ("CTCA"); 554d62bc4baSyz147064 case DL_FDDI: return ("FDDI"); 555d62bc4baSyz147064 case DL_FRAME: return ("Frame Relay (LAPF)"); 556d62bc4baSyz147064 case DL_MPFRAME: return ("MP Frame Relay"); 557d62bc4baSyz147064 case DL_ASYNC: return ("Async Character"); 558d62bc4baSyz147064 case DL_IPX25: return ("X.25 (Classic IP)"); 559d62bc4baSyz147064 case DL_LOOP: return ("Software Loopback"); 560d62bc4baSyz147064 case DL_FC: return ("Fiber Channel"); 561d62bc4baSyz147064 case DL_ATM: return ("ATM"); 562d62bc4baSyz147064 case DL_IPATM: return ("ATM (Classic IP)"); 563d62bc4baSyz147064 case DL_X25: return ("X.25 (LAPB)"); 564d62bc4baSyz147064 case DL_ISDN: return ("ISDN"); 565d62bc4baSyz147064 case DL_HIPPI: return ("HIPPI"); 566d62bc4baSyz147064 case DL_100VG: return ("100BaseVG Ethernet"); 567d62bc4baSyz147064 case DL_100VGTPR: return ("100BaseVG Token Ring"); 568d62bc4baSyz147064 case DL_ETH_CSMA: return ("Ethernet/IEEE 802.3"); 569d62bc4baSyz147064 case DL_100BT: return ("100BaseT"); 570d62bc4baSyz147064 case DL_IB: return ("Infiniband"); 571d62bc4baSyz147064 case DL_IPV4: return ("IPv4 Tunnel"); 572d62bc4baSyz147064 case DL_IPV6: return ("IPv6 Tunnel"); 573d62bc4baSyz147064 case DL_WIFI: return ("IEEE 802.11"); 574b127ac41SPhilip Kirk case DL_IPNET: return ("IPNET"); 575d62bc4baSyz147064 default: return ("<unknown mactype>"); 576d62bc4baSyz147064 } 577d62bc4baSyz147064 } 578