10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55102Syz147064 * Common Development and Distribution License (the "License"). 65102Syz147064 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 225895Syz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * Common Sun DLPI routines. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <sys/types.h> 310Sstevel@tonic-gate #include <sys/sysmacros.h> 320Sstevel@tonic-gate #include <sys/byteorder.h> 330Sstevel@tonic-gate #include <sys/systm.h> 340Sstevel@tonic-gate #include <sys/stream.h> 350Sstevel@tonic-gate #include <sys/strsun.h> 360Sstevel@tonic-gate #include <sys/dlpi.h> 375895Syz147064 #include <sys/ddi.h> 385895Syz147064 #include <sys/sunddi.h> 395895Syz147064 #include <sys/sunldi.h> 405895Syz147064 #include <sys/cmn_err.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate #define DLADDRL (80) 430Sstevel@tonic-gate 440Sstevel@tonic-gate void 450Sstevel@tonic-gate dlbindack( 460Sstevel@tonic-gate queue_t *wq, 470Sstevel@tonic-gate mblk_t *mp, 480Sstevel@tonic-gate t_scalar_t sap, 490Sstevel@tonic-gate void *addrp, 500Sstevel@tonic-gate t_uscalar_t addrlen, 510Sstevel@tonic-gate t_uscalar_t maxconind, 520Sstevel@tonic-gate t_uscalar_t xidtest) 530Sstevel@tonic-gate { 540Sstevel@tonic-gate union DL_primitives *dlp; 550Sstevel@tonic-gate size_t size; 560Sstevel@tonic-gate 570Sstevel@tonic-gate size = sizeof (dl_bind_ack_t) + addrlen; 580Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_BIND_ACK)) == NULL) 590Sstevel@tonic-gate return; 600Sstevel@tonic-gate 610Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 620Sstevel@tonic-gate dlp->bind_ack.dl_sap = sap; 630Sstevel@tonic-gate dlp->bind_ack.dl_addr_length = addrlen; 640Sstevel@tonic-gate dlp->bind_ack.dl_addr_offset = sizeof (dl_bind_ack_t); 650Sstevel@tonic-gate dlp->bind_ack.dl_max_conind = maxconind; 660Sstevel@tonic-gate dlp->bind_ack.dl_xidtest_flg = xidtest; 670Sstevel@tonic-gate if (addrlen != 0) 680Sstevel@tonic-gate bcopy(addrp, mp->b_rptr + sizeof (dl_bind_ack_t), addrlen); 690Sstevel@tonic-gate 700Sstevel@tonic-gate qreply(wq, mp); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 730Sstevel@tonic-gate void 740Sstevel@tonic-gate dlokack( 750Sstevel@tonic-gate queue_t *wq, 760Sstevel@tonic-gate mblk_t *mp, 770Sstevel@tonic-gate t_uscalar_t correct_primitive) 780Sstevel@tonic-gate { 790Sstevel@tonic-gate union DL_primitives *dlp; 800Sstevel@tonic-gate 810Sstevel@tonic-gate if ((mp = mexchange(wq, mp, sizeof (dl_ok_ack_t), M_PCPROTO, 820Sstevel@tonic-gate DL_OK_ACK)) == NULL) 830Sstevel@tonic-gate return; 840Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 850Sstevel@tonic-gate dlp->ok_ack.dl_correct_primitive = correct_primitive; 860Sstevel@tonic-gate qreply(wq, mp); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate void 900Sstevel@tonic-gate dlerrorack( 910Sstevel@tonic-gate queue_t *wq, 920Sstevel@tonic-gate mblk_t *mp, 930Sstevel@tonic-gate t_uscalar_t error_primitive, 940Sstevel@tonic-gate t_uscalar_t error, 950Sstevel@tonic-gate t_uscalar_t unix_errno) 960Sstevel@tonic-gate { 970Sstevel@tonic-gate union DL_primitives *dlp; 980Sstevel@tonic-gate 990Sstevel@tonic-gate if ((mp = mexchange(wq, mp, sizeof (dl_error_ack_t), M_PCPROTO, 1000Sstevel@tonic-gate DL_ERROR_ACK)) == NULL) 1010Sstevel@tonic-gate return; 1020Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1030Sstevel@tonic-gate dlp->error_ack.dl_error_primitive = error_primitive; 1040Sstevel@tonic-gate dlp->error_ack.dl_errno = error; 1050Sstevel@tonic-gate dlp->error_ack.dl_unix_errno = unix_errno; 1060Sstevel@tonic-gate qreply(wq, mp); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate void 1100Sstevel@tonic-gate dluderrorind( 1110Sstevel@tonic-gate queue_t *wq, 1120Sstevel@tonic-gate mblk_t *mp, 1130Sstevel@tonic-gate void *addrp, 1140Sstevel@tonic-gate t_uscalar_t addrlen, 1150Sstevel@tonic-gate t_uscalar_t error, 1160Sstevel@tonic-gate t_uscalar_t unix_errno) 1170Sstevel@tonic-gate { 1180Sstevel@tonic-gate union DL_primitives *dlp; 1190Sstevel@tonic-gate char buf[DLADDRL]; 1200Sstevel@tonic-gate size_t size; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (addrlen > DLADDRL) 1230Sstevel@tonic-gate addrlen = DLADDRL; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate bcopy(addrp, buf, addrlen); 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate size = sizeof (dl_uderror_ind_t) + addrlen; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_UDERROR_IND)) == NULL) 1300Sstevel@tonic-gate return; 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1330Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_length = addrlen; 1340Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_offset = sizeof (dl_uderror_ind_t); 1350Sstevel@tonic-gate dlp->uderror_ind.dl_unix_errno = unix_errno; 1360Sstevel@tonic-gate dlp->uderror_ind.dl_errno = error; 1370Sstevel@tonic-gate bcopy((caddr_t)buf, 1385102Syz147064 (caddr_t)(mp->b_rptr + sizeof (dl_uderror_ind_t)), addrlen); 1390Sstevel@tonic-gate qreply(wq, mp); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate void 1430Sstevel@tonic-gate dlphysaddrack( 1440Sstevel@tonic-gate queue_t *wq, 1450Sstevel@tonic-gate mblk_t *mp, 1460Sstevel@tonic-gate void *addrp, 1470Sstevel@tonic-gate t_uscalar_t len) 1480Sstevel@tonic-gate { 1490Sstevel@tonic-gate union DL_primitives *dlp; 1500Sstevel@tonic-gate size_t size; 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate size = sizeof (dl_phys_addr_ack_t) + len; 1530Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_PHYS_ADDR_ACK)) == NULL) 1540Sstevel@tonic-gate return; 1550Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1560Sstevel@tonic-gate dlp->physaddr_ack.dl_addr_length = len; 1570Sstevel@tonic-gate dlp->physaddr_ack.dl_addr_offset = sizeof (dl_phys_addr_ack_t); 1580Sstevel@tonic-gate if (len != 0) 1590Sstevel@tonic-gate bcopy(addrp, mp->b_rptr + sizeof (dl_phys_addr_ack_t), len); 1600Sstevel@tonic-gate qreply(wq, mp); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate void 1640Sstevel@tonic-gate dlcapabsetqid(dl_mid_t *idp, const queue_t *q) 1650Sstevel@tonic-gate { 1660Sstevel@tonic-gate #ifndef _LP64 1670Sstevel@tonic-gate idp->mid[0] = (t_uscalar_t)q; 1680Sstevel@tonic-gate #else 1690Sstevel@tonic-gate idp->mid[0] = (t_uscalar_t)BMASK_32((uint64_t)q); 1700Sstevel@tonic-gate idp->mid[1] = (t_uscalar_t)BMASK_32(((uint64_t)q) >> 32); 1710Sstevel@tonic-gate #endif 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate boolean_t 1750Sstevel@tonic-gate dlcapabcheckqid(const dl_mid_t *idp, const queue_t *q) 1760Sstevel@tonic-gate { 1770Sstevel@tonic-gate #ifndef _LP64 1780Sstevel@tonic-gate return ((queue_t *)(idp->mid[0]) == q); 1790Sstevel@tonic-gate #else 1800Sstevel@tonic-gate return ((queue_t *) 1810Sstevel@tonic-gate ((uint64_t)idp->mid[0] | ((uint64_t)idp->mid[1] << 32)) == q); 1820Sstevel@tonic-gate #endif 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate void 1860Sstevel@tonic-gate dlnotifyack( 1870Sstevel@tonic-gate queue_t *wq, 1880Sstevel@tonic-gate mblk_t *mp, 1890Sstevel@tonic-gate uint32_t notifications) 1900Sstevel@tonic-gate { 1910Sstevel@tonic-gate union DL_primitives *dlp; 1920Sstevel@tonic-gate 1935102Syz147064 if ((mp = mexchange(wq, mp, sizeof (dl_notify_ack_t), M_PROTO, 1940Sstevel@tonic-gate DL_NOTIFY_ACK)) == NULL) 1950Sstevel@tonic-gate return; 1960Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1970Sstevel@tonic-gate dlp->notify_ack.dl_notifications = notifications; 1980Sstevel@tonic-gate qreply(wq, mp); 1990Sstevel@tonic-gate } 2005895Syz147064 2015895Syz147064 static int 2025895Syz147064 dl_op(ldi_handle_t lh, mblk_t **mpp, t_uscalar_t expprim, size_t minlen, 2035895Syz147064 dl_error_ack_t *dleap, timestruc_t *tvp) 2045895Syz147064 { 2055895Syz147064 int err; 2065895Syz147064 size_t len; 2075895Syz147064 mblk_t *mp = *mpp; 2085895Syz147064 t_uscalar_t reqprim, ackprim, ackreqprim; 2095895Syz147064 union DL_primitives *dlp; 2105895Syz147064 2115895Syz147064 reqprim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; 2125895Syz147064 2135895Syz147064 (void) ldi_putmsg(lh, mp); 2145895Syz147064 2155895Syz147064 switch (err = ldi_getmsg(lh, &mp, tvp)) { 2165895Syz147064 case 0: 2175895Syz147064 break; 2185895Syz147064 case ETIME: 2195895Syz147064 cmn_err(CE_NOTE, "!dl_op: timed out waiting for %s to %s", 2205895Syz147064 dl_primstr(reqprim), dl_primstr(expprim)); 2215895Syz147064 return (ETIME); 2225895Syz147064 default: 2235895Syz147064 cmn_err(CE_NOTE, "!dl_op: ldi_getmsg() for %s failed: %d", 2245895Syz147064 dl_primstr(expprim), err); 2255895Syz147064 return (err); 2265895Syz147064 } 2275895Syz147064 2285895Syz147064 len = MBLKL(mp); 2295895Syz147064 if (len < sizeof (t_uscalar_t)) { 2305895Syz147064 cmn_err(CE_NOTE, "!dl_op: received runt DLPI message"); 2315895Syz147064 freemsg(mp); 2325895Syz147064 return (EBADMSG); 2335895Syz147064 } 2345895Syz147064 2355895Syz147064 dlp = (union DL_primitives *)mp->b_rptr; 2365895Syz147064 ackprim = dlp->dl_primitive; 2375895Syz147064 2385895Syz147064 if (ackprim == expprim) { 2395895Syz147064 if (len < minlen) 2405895Syz147064 goto runt; 2415895Syz147064 2425895Syz147064 if (ackprim == DL_OK_ACK) { 2435895Syz147064 if (dlp->ok_ack.dl_correct_primitive != reqprim) { 2445895Syz147064 ackreqprim = dlp->ok_ack.dl_correct_primitive; 2455895Syz147064 goto mixup; 2465895Syz147064 } 2475895Syz147064 } 2485895Syz147064 *mpp = mp; 2495895Syz147064 return (0); 2505895Syz147064 } 2515895Syz147064 2525895Syz147064 if (ackprim == DL_ERROR_ACK) { 2535895Syz147064 if (len < DL_ERROR_ACK_SIZE) 2545895Syz147064 goto runt; 2555895Syz147064 2565895Syz147064 if (dlp->error_ack.dl_error_primitive != reqprim) { 2575895Syz147064 ackreqprim = dlp->error_ack.dl_error_primitive; 2585895Syz147064 goto mixup; 2595895Syz147064 } 2605895Syz147064 2615895Syz147064 /* 2625895Syz147064 * Return a special error code (ENOTSUP) indicating that the 2635895Syz147064 * caller has returned DL_ERROR_ACK. Callers that want more 2645895Syz147064 * details an pass a non-NULL dleap. 2655895Syz147064 */ 2665895Syz147064 if (dleap != NULL) 2675895Syz147064 *dleap = dlp->error_ack; 2685895Syz147064 2695895Syz147064 freemsg(mp); 2705895Syz147064 return (ENOTSUP); 2715895Syz147064 } 2725895Syz147064 2735895Syz147064 cmn_err(CE_NOTE, "!dl_op: expected %s but received %s", 2745895Syz147064 dl_primstr(expprim), dl_primstr(ackprim)); 2755895Syz147064 freemsg(mp); 2765895Syz147064 return (EBADMSG); 2775895Syz147064 runt: 2785895Syz147064 cmn_err(CE_NOTE, "!dl_op: received runt %s", dl_primstr(ackprim)); 2795895Syz147064 freemsg(mp); 2805895Syz147064 return (EBADMSG); 2815895Syz147064 mixup: 2825895Syz147064 cmn_err(CE_NOTE, "!dl_op: received %s for %s instead of %s", 2835895Syz147064 dl_primstr(ackprim), dl_primstr(ackreqprim), dl_primstr(reqprim)); 2845895Syz147064 freemsg(mp); 2855895Syz147064 return (EBADMSG); 2865895Syz147064 } 2875895Syz147064 2885895Syz147064 /* 2895895Syz147064 * Send a DL_ATTACH_REQ for `ppa' over `lh' and wait for the response. 2905895Syz147064 * 2915895Syz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 2925895Syz147064 * caller can get the contents by passing a non-NULL `dleap'). 2935895Syz147064 */ 2945895Syz147064 int 2955895Syz147064 dl_attach(ldi_handle_t lh, int ppa, dl_error_ack_t *dleap) 2965895Syz147064 { 2975895Syz147064 mblk_t *mp; 2985895Syz147064 int err; 2995895Syz147064 3005895Syz147064 mp = mexchange(NULL, NULL, DL_ATTACH_REQ_SIZE, M_PROTO, DL_ATTACH_REQ); 3015895Syz147064 if (mp == NULL) 3025895Syz147064 return (ENOMEM); 3035895Syz147064 3045895Syz147064 ((dl_attach_req_t *)mp->b_rptr)->dl_ppa = ppa; 3055895Syz147064 3065895Syz147064 err = dl_op(lh, &mp, DL_OK_ACK, DL_OK_ACK_SIZE, dleap, NULL); 3075895Syz147064 if (err == 0) 3085895Syz147064 freemsg(mp); 3095895Syz147064 return (err); 3105895Syz147064 } 3115895Syz147064 3125895Syz147064 /* 3135895Syz147064 * Send a DL_BIND_REQ for `sap' over `lh' and wait for the response. 3145895Syz147064 * 3155895Syz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 3165895Syz147064 * caller can get the contents by passing a non-NULL `dleap'). 3175895Syz147064 */ 3185895Syz147064 int 3195895Syz147064 dl_bind(ldi_handle_t lh, uint_t sap, dl_error_ack_t *dleap) 3205895Syz147064 { 3215895Syz147064 dl_bind_req_t *dlbrp; 3225895Syz147064 dl_bind_ack_t *dlbap; 3235895Syz147064 mblk_t *mp; 3245895Syz147064 int err; 3255895Syz147064 3265895Syz147064 mp = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ); 3275895Syz147064 if (mp == NULL) 3285895Syz147064 return (ENOMEM); 3295895Syz147064 3305895Syz147064 dlbrp = (dl_bind_req_t *)mp->b_rptr; 3315895Syz147064 dlbrp->dl_sap = sap; 3325895Syz147064 dlbrp->dl_conn_mgmt = 0; 3335895Syz147064 dlbrp->dl_max_conind = 0; 3345895Syz147064 dlbrp->dl_xidtest_flg = 0; 3355895Syz147064 dlbrp->dl_service_mode = DL_CLDLS; 3365895Syz147064 3375895Syz147064 err = dl_op(lh, &mp, DL_BIND_ACK, DL_BIND_ACK_SIZE, dleap, NULL); 3385895Syz147064 if (err == 0) { 3395895Syz147064 dlbap = (dl_bind_ack_t *)mp->b_rptr; 3405895Syz147064 if (dlbap->dl_sap != sap) { 3415895Syz147064 cmn_err(CE_NOTE, "!dl_bind: DL_BIND_ACK: bad sap %u", 3425895Syz147064 dlbap->dl_sap); 3435895Syz147064 err = EPROTO; 3445895Syz147064 } 3455895Syz147064 freemsg(mp); 3465895Syz147064 } 3475895Syz147064 return (err); 3485895Syz147064 } 3495895Syz147064 3505895Syz147064 /* 3515895Syz147064 * Send a DL_PHYS_ADDR_REQ over `lh' and wait for the response. The caller 3525895Syz147064 * must set `*physlenp' to the size of `physaddr' (both of which must be 3535895Syz147064 * non-NULL); upon success they will be updated to contain the actual physical 3545895Syz147064 * address and length. 3555895Syz147064 * 3565895Syz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 3575895Syz147064 * caller can get the contents by passing a non-NULL `dleap'). 3585895Syz147064 */ 3595895Syz147064 int 3605895Syz147064 dl_phys_addr(ldi_handle_t lh, uchar_t *physaddr, size_t *physlenp, 3615895Syz147064 dl_error_ack_t *dleap) 3625895Syz147064 { 3635895Syz147064 dl_phys_addr_ack_t *dlpap; 3645895Syz147064 mblk_t *mp; 3655895Syz147064 int err; 3665895Syz147064 t_uscalar_t paddrlen, paddroff; 3675895Syz147064 timestruc_t tv; 3685895Syz147064 3695895Syz147064 mp = mexchange(NULL, NULL, DL_PHYS_ADDR_REQ_SIZE, M_PROTO, 3705895Syz147064 DL_PHYS_ADDR_REQ); 3715895Syz147064 if (mp == NULL) 3725895Syz147064 return (ENOMEM); 3735895Syz147064 3745895Syz147064 ((dl_phys_addr_req_t *)mp->b_rptr)->dl_addr_type = DL_CURR_PHYS_ADDR; 3755895Syz147064 3765895Syz147064 /* 3775895Syz147064 * In case some provider doesn't implement or NAK the 3785895Syz147064 * request, just wait for 15 seconds. 3795895Syz147064 */ 3805895Syz147064 tv.tv_sec = 15; 3815895Syz147064 tv.tv_nsec = 0; 3825895Syz147064 3835895Syz147064 err = dl_op(lh, &mp, DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, dleap, 3845895Syz147064 &tv); 3855895Syz147064 if (err == 0) { 3865895Syz147064 dlpap = (dl_phys_addr_ack_t *)mp->b_rptr; 3875895Syz147064 paddrlen = dlpap->dl_addr_length; 3885895Syz147064 paddroff = dlpap->dl_addr_offset; 3895895Syz147064 if (paddroff == 0 || paddrlen == 0 || paddrlen > *physlenp || 3905895Syz147064 !MBLKIN(mp, paddroff, paddrlen)) { 3915895Syz147064 cmn_err(CE_NOTE, "!dl_phys_addr: DL_PHYS_ADDR_ACK: " 3925895Syz147064 "bad length/offset %d/%d", paddrlen, paddroff); 3935895Syz147064 err = EBADMSG; 3945895Syz147064 } else { 3955895Syz147064 bcopy(mp->b_rptr + paddroff, physaddr, paddrlen); 3965895Syz147064 *physlenp = paddrlen; 3975895Syz147064 } 3985895Syz147064 freemsg(mp); 3995895Syz147064 } 4005895Syz147064 return (err); 4015895Syz147064 } 4025895Syz147064 4035895Syz147064 /* 4045895Syz147064 * Send a DL_INFO_REQ over `lh' and wait for the response. The caller must 4055895Syz147064 * pass a non-NULL `dliap', which upon success will contain the dl_info_ack_t 4065895Syz147064 * from the provider. The caller may optionally get the provider's physical 4075895Syz147064 * address by passing a non-NULL `physaddr' and setting `*physlenp' to its 4085895Syz147064 * size; upon success they will be updated to contain the actual physical 4095895Syz147064 * address and its length. 4105895Syz147064 * 4115895Syz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 4125895Syz147064 * caller can get the contents by passing a non-NULL `dleap'). 4135895Syz147064 */ 4145895Syz147064 int 4155895Syz147064 dl_info(ldi_handle_t lh, dl_info_ack_t *dliap, uchar_t *physaddr, 4165895Syz147064 size_t *physlenp, dl_error_ack_t *dleap) 4175895Syz147064 { 4185895Syz147064 mblk_t *mp; 4195895Syz147064 int err; 4205895Syz147064 int addrlen, addroff; 4215895Syz147064 4225895Syz147064 mp = mexchange(NULL, NULL, DL_INFO_REQ_SIZE, M_PCPROTO, DL_INFO_REQ); 4235895Syz147064 if (mp == NULL) 4245895Syz147064 return (ENOMEM); 4255895Syz147064 4265895Syz147064 err = dl_op(lh, &mp, DL_INFO_ACK, DL_INFO_ACK_SIZE, dleap, NULL); 4275895Syz147064 if (err != 0) 4285895Syz147064 return (err); 4295895Syz147064 4305895Syz147064 *dliap = *(dl_info_ack_t *)mp->b_rptr; 4315895Syz147064 if (physaddr != NULL) { 4325895Syz147064 addrlen = dliap->dl_addr_length - ABS(dliap->dl_sap_length); 4335895Syz147064 addroff = dliap->dl_addr_offset; 4345895Syz147064 if (addroff == 0 || addrlen <= 0 || addrlen > *physlenp || 4355895Syz147064 !MBLKIN(mp, addroff, dliap->dl_addr_length)) { 4365895Syz147064 cmn_err(CE_NOTE, "!dl_info: DL_INFO_ACK: " 4375895Syz147064 "bad length/offset %d/%d", addrlen, addroff); 4385895Syz147064 freemsg(mp); 4395895Syz147064 return (EBADMSG); 4405895Syz147064 } 4415895Syz147064 4425895Syz147064 if (dliap->dl_sap_length > 0) 4435895Syz147064 addroff += dliap->dl_sap_length; 4445895Syz147064 bcopy(mp->b_rptr + addroff, physaddr, addrlen); 4455895Syz147064 *physlenp = addrlen; 4465895Syz147064 } 4475895Syz147064 freemsg(mp); 4485895Syz147064 return (err); 4495895Syz147064 } 4505895Syz147064 4515895Syz147064 /* 4525895Syz147064 * Send a DL_NOTIFY_REQ over `lh' and wait for the response. The caller 4535895Syz147064 * should set `notesp' to the set of notifications they wish to enable; 4545895Syz147064 * upon success it will contain the notifications enabled by the provider. 4555895Syz147064 * 4565895Syz147064 * Returns an errno; ENOTSUP indicates a DL_ERROR_ACK response (and the 4575895Syz147064 * caller can get the contents by passing a non-NULL `dleap'). 4585895Syz147064 */ 4595895Syz147064 int 4605895Syz147064 dl_notify(ldi_handle_t lh, uint32_t *notesp, dl_error_ack_t *dleap) 4615895Syz147064 { 4625895Syz147064 mblk_t *mp; 4635895Syz147064 int err; 4645895Syz147064 4655895Syz147064 mp = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO, DL_NOTIFY_REQ); 4665895Syz147064 if (mp == NULL) 4675895Syz147064 return (ENOMEM); 4685895Syz147064 4695895Syz147064 ((dl_notify_req_t *)mp->b_rptr)->dl_notifications = *notesp; 4705895Syz147064 4715895Syz147064 err = dl_op(lh, &mp, DL_NOTIFY_ACK, DL_NOTIFY_ACK_SIZE, dleap, NULL); 4725895Syz147064 if (err == 0) { 4735895Syz147064 *notesp = ((dl_notify_ack_t *)mp->b_rptr)->dl_notifications; 4745895Syz147064 freemsg(mp); 4755895Syz147064 } 4765895Syz147064 return (err); 4775895Syz147064 } 4785895Syz147064 4795895Syz147064 const char * 4805895Syz147064 dl_primstr(t_uscalar_t prim) 4815895Syz147064 { 4825895Syz147064 switch (prim) { 4835895Syz147064 case DL_INFO_REQ: return ("DL_INFO_REQ"); 4845895Syz147064 case DL_INFO_ACK: return ("DL_INFO_ACK"); 4855895Syz147064 case DL_ATTACH_REQ: return ("DL_ATTACH_REQ"); 4865895Syz147064 case DL_DETACH_REQ: return ("DL_DETACH_REQ"); 4875895Syz147064 case DL_BIND_REQ: return ("DL_BIND_REQ"); 4885895Syz147064 case DL_BIND_ACK: return ("DL_BIND_ACK"); 4895895Syz147064 case DL_UNBIND_REQ: return ("DL_UNBIND_REQ"); 4905895Syz147064 case DL_OK_ACK: return ("DL_OK_ACK"); 4915895Syz147064 case DL_ERROR_ACK: return ("DL_ERROR_ACK"); 4925895Syz147064 case DL_ENABMULTI_REQ: return ("DL_ENABMULTI_REQ"); 4935895Syz147064 case DL_DISABMULTI_REQ: return ("DL_DISABMULTI_REQ"); 4945895Syz147064 case DL_PROMISCON_REQ: return ("DL_PROMISCON_REQ"); 4955895Syz147064 case DL_PROMISCOFF_REQ: return ("DL_PROMISCOFF_REQ"); 4965895Syz147064 case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ"); 4975895Syz147064 case DL_UNITDATA_IND: return ("DL_UNITDATA_IND"); 4985895Syz147064 case DL_UDERROR_IND: return ("DL_UDERROR_IND"); 4995895Syz147064 case DL_PHYS_ADDR_REQ: return ("DL_PHYS_ADDR_REQ"); 5005895Syz147064 case DL_PHYS_ADDR_ACK: return ("DL_PHYS_ADDR_ACK"); 5015895Syz147064 case DL_SET_PHYS_ADDR_REQ: return ("DL_SET_PHYS_ADDR_REQ"); 5025895Syz147064 case DL_NOTIFY_REQ: return ("DL_NOTIFY_REQ"); 5035895Syz147064 case DL_NOTIFY_ACK: return ("DL_NOTIFY_ACK"); 5045895Syz147064 case DL_NOTIFY_IND: return ("DL_NOTIFY_IND"); 5055895Syz147064 case DL_CAPABILITY_REQ: return ("DL_CAPABILITY_REQ"); 5065895Syz147064 case DL_CAPABILITY_ACK: return ("DL_CAPABILITY_ACK"); 5075895Syz147064 case DL_CONTROL_REQ: return ("DL_CONTROL_REQ"); 5085895Syz147064 case DL_CONTROL_ACK: return ("DL_CONTROL_ACK"); 5095895Syz147064 case DL_PASSIVE_REQ: return ("DL_PASSIVE_REQ"); 5105895Syz147064 case DL_INTR_MODE_REQ: return ("DL_INTR_MODE_REQ"); 5115895Syz147064 case DL_UDQOS_REQ: return ("DL_UDQOS_REQ"); 5125895Syz147064 default: return ("<unknown primitive>"); 5135895Syz147064 } 5145895Syz147064 } 5155895Syz147064 5165895Syz147064 const char * 5175895Syz147064 dl_errstr(t_uscalar_t err) 5185895Syz147064 { 5195895Syz147064 switch (err) { 5205895Syz147064 case DL_ACCESS: return ("DL_ACCESS"); 5215895Syz147064 case DL_BADADDR: return ("DL_BADADDR"); 5225895Syz147064 case DL_BADCORR: return ("DL_BADCORR"); 5235895Syz147064 case DL_BADDATA: return ("DL_BADDATA"); 5245895Syz147064 case DL_BADPPA: return ("DL_BADPPA"); 5255895Syz147064 case DL_BADPRIM: return ("DL_BADPRIM"); 5265895Syz147064 case DL_BADQOSPARAM: return ("DL_BADQOSPARAM"); 5275895Syz147064 case DL_BADQOSTYPE: return ("DL_BADQOSTYPE"); 5285895Syz147064 case DL_BADSAP: return ("DL_BADSAP"); 5295895Syz147064 case DL_BADTOKEN: return ("DL_BADTOKEN"); 5305895Syz147064 case DL_BOUND: return ("DL_BOUND"); 5315895Syz147064 case DL_INITFAILED: return ("DL_INITFAILED"); 5325895Syz147064 case DL_NOADDR: return ("DL_NOADDR"); 5335895Syz147064 case DL_NOTINIT: return ("DL_NOTINIT"); 5345895Syz147064 case DL_OUTSTATE: return ("DL_OUTSTATE"); 5355895Syz147064 case DL_SYSERR: return ("DL_SYSERR"); 5365895Syz147064 case DL_UNSUPPORTED: return ("DL_UNSUPPORTED"); 5375895Syz147064 case DL_UNDELIVERABLE: return ("DL_UNDELIVERABLE"); 5385895Syz147064 case DL_NOTSUPPORTED: return ("DL_NOTSUPPORTED "); 5395895Syz147064 case DL_TOOMANY: return ("DL_TOOMANY"); 5405895Syz147064 case DL_NOTENAB: return ("DL_NOTENAB"); 5415895Syz147064 case DL_BUSY: return ("DL_BUSY"); 5425895Syz147064 case DL_NOAUTO: return ("DL_NOAUTO"); 5435895Syz147064 case DL_NOXIDAUTO: return ("DL_NOXIDAUTO"); 5445895Syz147064 case DL_NOTESTAUTO: return ("DL_NOTESTAUTO"); 5455895Syz147064 case DL_XIDAUTO: return ("DL_XIDAUTO"); 5465895Syz147064 case DL_TESTAUTO: return ("DL_TESTAUTO"); 5475895Syz147064 case DL_PENDING: return ("DL_PENDING"); 5485895Syz147064 default: return ("<unknown error>"); 5495895Syz147064 } 5505895Syz147064 } 5515895Syz147064 5525895Syz147064 const char * 5535895Syz147064 dl_mactypestr(t_uscalar_t mactype) 5545895Syz147064 { 5555895Syz147064 switch (mactype) { 5565895Syz147064 case DL_CSMACD: return ("CSMA/CD"); 5575895Syz147064 case DL_TPB: return ("Token Bus"); 5585895Syz147064 case DL_TPR: return ("Token Ring"); 5595895Syz147064 case DL_METRO: return ("Metro Net"); 5605895Syz147064 case DL_ETHER: return ("Ethernet"); 5615895Syz147064 case DL_HDLC: return ("HDLC"); 5625895Syz147064 case DL_CHAR: return ("Sync Character"); 5635895Syz147064 case DL_CTCA: return ("CTCA"); 5645895Syz147064 case DL_FDDI: return ("FDDI"); 5655895Syz147064 case DL_FRAME: return ("Frame Relay (LAPF)"); 5665895Syz147064 case DL_MPFRAME: return ("MP Frame Relay"); 5675895Syz147064 case DL_ASYNC: return ("Async Character"); 5685895Syz147064 case DL_IPX25: return ("X.25 (Classic IP)"); 5695895Syz147064 case DL_LOOP: return ("Software Loopback"); 5705895Syz147064 case DL_FC: return ("Fiber Channel"); 5715895Syz147064 case DL_ATM: return ("ATM"); 5725895Syz147064 case DL_IPATM: return ("ATM (Classic IP)"); 5735895Syz147064 case DL_X25: return ("X.25 (LAPB)"); 5745895Syz147064 case DL_ISDN: return ("ISDN"); 5755895Syz147064 case DL_HIPPI: return ("HIPPI"); 5765895Syz147064 case DL_100VG: return ("100BaseVG Ethernet"); 5775895Syz147064 case DL_100VGTPR: return ("100BaseVG Token Ring"); 5785895Syz147064 case DL_ETH_CSMA: return ("Ethernet/IEEE 802.3"); 5795895Syz147064 case DL_100BT: return ("100BaseT"); 5805895Syz147064 case DL_IB: return ("Infiniband"); 5815895Syz147064 case DL_IPV4: return ("IPv4 Tunnel"); 5825895Syz147064 case DL_IPV6: return ("IPv6 Tunnel"); 5835895Syz147064 case DL_WIFI: return ("IEEE 802.11"); 584*8023SPhil.Kirk@Sun.COM case DL_IPNET: return ("IPNET"); 5855895Syz147064 default: return ("<unknown mactype>"); 5865895Syz147064 } 5875895Syz147064 } 588