1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Data-Link Driver 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/debug.h> 35*0Sstevel@tonic-gate #include <sys/sysmacros.h> 36*0Sstevel@tonic-gate #include <sys/stream.h> 37*0Sstevel@tonic-gate #include <sys/ddi.h> 38*0Sstevel@tonic-gate #include <sys/sunddi.h> 39*0Sstevel@tonic-gate #include <sys/strsun.h> 40*0Sstevel@tonic-gate #include <sys/dlpi.h> 41*0Sstevel@tonic-gate #include <netinet/in.h> 42*0Sstevel@tonic-gate #include <sys/sdt.h> 43*0Sstevel@tonic-gate #include <sys/strsubr.h> 44*0Sstevel@tonic-gate #include <sys/vlan.h> 45*0Sstevel@tonic-gate #include <sys/mac.h> 46*0Sstevel@tonic-gate #include <sys/dls.h> 47*0Sstevel@tonic-gate #include <sys/dld.h> 48*0Sstevel@tonic-gate #include <sys/dld_impl.h> 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate typedef boolean_t proto_reqfunc_t(dld_str_t *, union DL_primitives *, mblk_t *); 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req, 53*0Sstevel@tonic-gate proto_bind_req, proto_unbind_req, proto_promiscon_req, proto_promiscoff_req, 54*0Sstevel@tonic-gate proto_enabmulti_req, proto_disabmulti_req, proto_physaddr_req, 55*0Sstevel@tonic-gate proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req, 56*0Sstevel@tonic-gate proto_notify_req, proto_unitdata_req, proto_passive_req; 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate static void proto_excl(queue_t *, mblk_t *); 59*0Sstevel@tonic-gate static void proto_info_ack(dld_str_t *, mblk_t *); 60*0Sstevel@tonic-gate static void proto_attach_ack(dld_str_t *, mblk_t *, int); 61*0Sstevel@tonic-gate static void proto_detach_ack(dld_str_t *, mblk_t *); 62*0Sstevel@tonic-gate static void proto_bind_ack(dld_str_t *, mblk_t *, int); 63*0Sstevel@tonic-gate static void proto_unbind_ack(dld_str_t *, mblk_t *); 64*0Sstevel@tonic-gate static void proto_promiscon_ack(dld_str_t *, mblk_t *, int); 65*0Sstevel@tonic-gate static void proto_promiscoff_ack(dld_str_t *, mblk_t *, int); 66*0Sstevel@tonic-gate static void proto_enabmulti_ack(dld_str_t *, mblk_t *, int); 67*0Sstevel@tonic-gate static void proto_disabmulti_ack(dld_str_t *, mblk_t *, int); 68*0Sstevel@tonic-gate static void proto_setphysaddr_ack(dld_str_t *, mblk_t *, int); 69*0Sstevel@tonic-gate static void proto_physaddr_ack(dld_str_t *, mblk_t *, t_uscalar_t); 70*0Sstevel@tonic-gate static void proto_udqos_ack(dld_str_t *, mblk_t *); 71*0Sstevel@tonic-gate static void proto_poll_disable(dld_str_t *); 72*0Sstevel@tonic-gate static boolean_t proto_poll_enable(dld_str_t *, dl_capab_poll_t *); 73*0Sstevel@tonic-gate static void proto_capability_ack(dld_str_t *, mblk_t *); 74*0Sstevel@tonic-gate static void proto_capability_enable(dld_str_t *, mblk_t *); 75*0Sstevel@tonic-gate static void proto_notify_ack(dld_str_t *, mblk_t *, uint_t, 76*0Sstevel@tonic-gate uint_t); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #define DL_SOLARIS 0x100 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate /* 81*0Sstevel@tonic-gate * M_PROTO/M_PCPROTO request handlers 82*0Sstevel@tonic-gate */ 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate typedef struct proto_req_info { 85*0Sstevel@tonic-gate t_uscalar_t pri_prim; 86*0Sstevel@tonic-gate const char *pri_txt; 87*0Sstevel@tonic-gate boolean_t pri_needexcl; 88*0Sstevel@tonic-gate boolean_t pri_active; 89*0Sstevel@tonic-gate proto_reqfunc_t *pri_fn; 90*0Sstevel@tonic-gate } proto_req_info_t; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate static proto_req_info_t proto_ri[] = { 93*0Sstevel@tonic-gate { DL_INFO_REQ, "DL_INFO_REQ", B_FALSE, B_FALSE, proto_info_req }, 94*0Sstevel@tonic-gate { DL_BIND_REQ, "DL_BIND_REQ", B_TRUE, B_TRUE, proto_bind_req }, 95*0Sstevel@tonic-gate { DL_UNBIND_REQ, "DL_UNBIND_REQ", B_TRUE, B_FALSE, proto_unbind_req }, 96*0Sstevel@tonic-gate { DL_INFO_ACK, "DL_INFO_ACK", B_FALSE, B_FALSE, proto_req }, 97*0Sstevel@tonic-gate { DL_BIND_ACK, "DL_BIND_ACK", B_FALSE, B_FALSE, proto_req }, 98*0Sstevel@tonic-gate { DL_ERROR_ACK, "DL_ERROR_ACK", B_FALSE, B_FALSE, proto_req }, 99*0Sstevel@tonic-gate { DL_OK_ACK, "DL_OK_ACK", B_FALSE, B_FALSE, proto_req }, 100*0Sstevel@tonic-gate { DL_UNITDATA_REQ, "DL_UNITDATA_REQ", B_FALSE, B_FALSE, 101*0Sstevel@tonic-gate proto_unitdata_req }, 102*0Sstevel@tonic-gate { DL_UNITDATA_IND, "DL_UNITDATA_IND", B_FALSE, B_FALSE, proto_req }, 103*0Sstevel@tonic-gate { DL_UDERROR_IND, "DL_UDERROR_IND", B_FALSE, B_FALSE, proto_req }, 104*0Sstevel@tonic-gate { DL_UDQOS_REQ, "DL_UDQOS_REQ", B_TRUE, B_FALSE, proto_udqos_req }, 105*0Sstevel@tonic-gate { DL_ATTACH_REQ, "DL_ATTACH_REQ", B_TRUE, B_FALSE, proto_attach_req }, 106*0Sstevel@tonic-gate { DL_DETACH_REQ, "DL_DETACH_REQ", B_TRUE, B_FALSE, proto_detach_req }, 107*0Sstevel@tonic-gate { DL_CONNECT_REQ, "DL_CONNECT_REQ", B_FALSE, B_FALSE, proto_req }, 108*0Sstevel@tonic-gate { DL_CONNECT_IND, "DL_CONNECT_IND", B_FALSE, B_FALSE, proto_req }, 109*0Sstevel@tonic-gate { DL_CONNECT_RES, "DL_CONNECT_RES", B_FALSE, B_FALSE, proto_req }, 110*0Sstevel@tonic-gate { DL_CONNECT_CON, "DL_CONNECT_CON", B_FALSE, B_FALSE, proto_req }, 111*0Sstevel@tonic-gate { DL_TOKEN_REQ, "DL_TOKEN_REQ", B_FALSE, B_FALSE, proto_req }, 112*0Sstevel@tonic-gate { DL_TOKEN_ACK, "DL_TOKEN_ACK", B_FALSE, B_FALSE, proto_req }, 113*0Sstevel@tonic-gate { DL_DISCONNECT_REQ, "DL_DISCONNECT_REQ", B_FALSE, B_FALSE, proto_req }, 114*0Sstevel@tonic-gate { DL_DISCONNECT_IND, "DL_DISCONNECT_IND", B_FALSE, B_FALSE, proto_req }, 115*0Sstevel@tonic-gate { DL_SUBS_UNBIND_REQ, "DL_SUBS_UNBIND_REQ", B_FALSE, B_FALSE, 116*0Sstevel@tonic-gate proto_req }, 117*0Sstevel@tonic-gate { 0x16, "undefined", B_FALSE, B_FALSE, proto_req }, 118*0Sstevel@tonic-gate { DL_RESET_REQ, "DL_RESET_REQ", B_FALSE, B_FALSE, proto_req }, 119*0Sstevel@tonic-gate { DL_RESET_IND, "DL_RESET_IND", B_FALSE, B_FALSE, proto_req }, 120*0Sstevel@tonic-gate { DL_RESET_RES, "DL_RESET_RES", B_FALSE, B_FALSE, proto_req }, 121*0Sstevel@tonic-gate { DL_RESET_CON, "DL_RESET_CON", B_FALSE, B_FALSE, proto_req }, 122*0Sstevel@tonic-gate { DL_SUBS_BIND_REQ, "DL_SUBS_BIND_REQ", B_FALSE, B_FALSE, proto_req }, 123*0Sstevel@tonic-gate { DL_SUBS_BIND_ACK, "DL_SUBS_BIND_ACK", B_FALSE, B_FALSE, proto_req }, 124*0Sstevel@tonic-gate { DL_ENABMULTI_REQ, "DL_ENABMULTI_REQ", B_TRUE, B_TRUE, 125*0Sstevel@tonic-gate proto_enabmulti_req }, 126*0Sstevel@tonic-gate { DL_DISABMULTI_REQ, "DL_DISABMULTI_REQ", B_TRUE, B_FALSE, 127*0Sstevel@tonic-gate proto_disabmulti_req }, 128*0Sstevel@tonic-gate { DL_PROMISCON_REQ, "DL_PROMISCON_REQ", B_TRUE, B_TRUE, 129*0Sstevel@tonic-gate proto_promiscon_req }, 130*0Sstevel@tonic-gate { DL_PROMISCOFF_REQ, "DL_PROMISCOFF_REQ", B_TRUE, B_FALSE, 131*0Sstevel@tonic-gate proto_promiscoff_req }, 132*0Sstevel@tonic-gate { DL_DATA_ACK_REQ, "DL_DATA_ACK_REQ", B_FALSE, B_FALSE, proto_req }, 133*0Sstevel@tonic-gate { DL_DATA_ACK_IND, "DL_DATA_ACK_IND", B_FALSE, B_FALSE, proto_req }, 134*0Sstevel@tonic-gate { DL_DATA_ACK_STATUS_IND, "DL_DATA_ACK_STATUS_IND", B_FALSE, B_FALSE, 135*0Sstevel@tonic-gate proto_req }, 136*0Sstevel@tonic-gate { DL_REPLY_REQ, "DL_REPLY_REQ", B_FALSE, B_FALSE, proto_req }, 137*0Sstevel@tonic-gate { DL_REPLY_IND, "DL_REPLY_IND", B_FALSE, B_FALSE, proto_req }, 138*0Sstevel@tonic-gate { DL_REPLY_STATUS_IND, "DL_REPLY_STATUS_IND", B_FALSE, B_FALSE, 139*0Sstevel@tonic-gate proto_req }, 140*0Sstevel@tonic-gate { DL_REPLY_UPDATE_REQ, "DL_REPLY_UPDATE_REQ", B_FALSE, B_FALSE, 141*0Sstevel@tonic-gate proto_req }, 142*0Sstevel@tonic-gate { DL_REPLY_UPDATE_STATUS_IND, "DL_REPLY_UPDATE_STATUS_IND", B_FALSE, 143*0Sstevel@tonic-gate B_FALSE, proto_req }, 144*0Sstevel@tonic-gate { DL_XID_REQ, "DL_XID_REQ", B_FALSE, B_FALSE, proto_req }, 145*0Sstevel@tonic-gate { DL_XID_IND, "DL_XID_IND", B_FALSE, B_FALSE, proto_req }, 146*0Sstevel@tonic-gate { DL_XID_RES, "DL_XID_RES", B_FALSE, B_FALSE, proto_req }, 147*0Sstevel@tonic-gate { DL_XID_CON, "DL_XID_CON", B_FALSE, B_FALSE, proto_req }, 148*0Sstevel@tonic-gate { DL_TEST_REQ, "DL_TEST_REQ", B_FALSE, B_FALSE, proto_req }, 149*0Sstevel@tonic-gate { DL_TEST_IND, "DL_TEST_IND", B_FALSE, B_FALSE, proto_req }, 150*0Sstevel@tonic-gate { DL_TEST_RES, "DL_TEST_RES", B_FALSE, B_FALSE, proto_req }, 151*0Sstevel@tonic-gate { DL_TEST_CON, "DL_TEST_CON", B_FALSE, B_FALSE, proto_req }, 152*0Sstevel@tonic-gate { DL_PHYS_ADDR_REQ, "DL_PHYS_ADDR_REQ", B_FALSE, B_FALSE, 153*0Sstevel@tonic-gate proto_physaddr_req }, 154*0Sstevel@tonic-gate { DL_PHYS_ADDR_ACK, "DL_PHYS_ADDR_ACK", B_FALSE, B_FALSE, proto_req }, 155*0Sstevel@tonic-gate { DL_SET_PHYS_ADDR_REQ, "DL_SET_PHYS_ADDR_REQ", B_TRUE, B_TRUE, 156*0Sstevel@tonic-gate proto_setphysaddr_req }, 157*0Sstevel@tonic-gate { DL_GET_STATISTICS_REQ, "DL_GET_STATISTICS_REQ", B_FALSE, B_FALSE, 158*0Sstevel@tonic-gate proto_req }, 159*0Sstevel@tonic-gate { DL_GET_STATISTICS_ACK, "DL_GET_STATISTICS_ACK", B_FALSE, B_FALSE, 160*0Sstevel@tonic-gate proto_req } 161*0Sstevel@tonic-gate }; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate #define PROTO_RI_COUNT (sizeof (proto_ri) / sizeof (proto_ri[0])) 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate static proto_req_info_t proto_sri[] = { 166*0Sstevel@tonic-gate { DL_NOTIFY_REQ, "DL_NOTIFY_REQ", B_FALSE, B_FALSE, proto_notify_req }, 167*0Sstevel@tonic-gate { DL_NOTIFY_ACK, "DL_NOTIFY_ACK", B_FALSE, B_FALSE, proto_req }, 168*0Sstevel@tonic-gate { DL_NOTIFY_IND, "DL_NOTIFY_IND", B_FALSE, B_FALSE, proto_req }, 169*0Sstevel@tonic-gate { DL_AGGR_REQ, "DL_AGGR_REQ", B_FALSE, B_TRUE, proto_req }, 170*0Sstevel@tonic-gate { DL_AGGR_IND, "DL_AGGR_IND", B_FALSE, B_FALSE, proto_req }, 171*0Sstevel@tonic-gate { DL_UNAGGR_REQ, "DL_UNAGGR_REQ", B_FALSE, B_TRUE, proto_req }, 172*0Sstevel@tonic-gate { 0x106, "undefined", B_FALSE, B_FALSE, proto_req }, 173*0Sstevel@tonic-gate { 0x107, "undefined", B_FALSE, B_FALSE, proto_req }, 174*0Sstevel@tonic-gate { 0x108, "undefined", B_FALSE, B_FALSE, proto_req }, 175*0Sstevel@tonic-gate { 0x109, "undefined", B_FALSE, B_FALSE, proto_req }, 176*0Sstevel@tonic-gate { 0x10a, "undefined", B_FALSE, B_FALSE, proto_req }, 177*0Sstevel@tonic-gate { 0x10b, "undefined", B_FALSE, B_FALSE, proto_req }, 178*0Sstevel@tonic-gate { 0x10c, "undefined", B_FALSE, B_FALSE, proto_req }, 179*0Sstevel@tonic-gate { 0x10d, "undefined", B_FALSE, B_FALSE, proto_req }, 180*0Sstevel@tonic-gate { 0x10e, "undefined", B_FALSE, B_FALSE, proto_req }, 181*0Sstevel@tonic-gate { 0x10f, "undefined", B_FALSE, B_FALSE, proto_req }, 182*0Sstevel@tonic-gate { DL_CAPABILITY_REQ, "DL_CAPABILITY_REQ", B_FALSE, B_FALSE, 183*0Sstevel@tonic-gate proto_capability_req }, 184*0Sstevel@tonic-gate { DL_CAPABILITY_ACK, "DL_CAPABILITY_ACK", B_FALSE, B_FALSE, proto_req }, 185*0Sstevel@tonic-gate { DL_CONTROL_REQ, "DL_CONTROL_REQ", B_FALSE, B_TRUE, proto_req }, 186*0Sstevel@tonic-gate { DL_CONTROL_ACK, "DL_CONTROL_ACK", B_FALSE, B_FALSE, proto_req }, 187*0Sstevel@tonic-gate { DL_PASSIVE_REQ, "DL_PASSIVE_REQ", B_TRUE, B_FALSE, proto_passive_req } 188*0Sstevel@tonic-gate }; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate #define PROTO_SRI_COUNT (sizeof (proto_sri) / sizeof (proto_sri[0])) 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate #define DL_ACK_PENDING(state) \ 193*0Sstevel@tonic-gate ((state) == DL_ATTACH_PENDING || \ 194*0Sstevel@tonic-gate (state) == DL_DETACH_PENDING || \ 195*0Sstevel@tonic-gate (state) == DL_BIND_PENDING || \ 196*0Sstevel@tonic-gate (state) == DL_UNBIND_PENDING) 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Process a DLPI protocol message. (Only ever called from put(9e)). 200*0Sstevel@tonic-gate */ 201*0Sstevel@tonic-gate void 202*0Sstevel@tonic-gate dld_proto(dld_str_t *dsp, mblk_t *mp) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate union DL_primitives *udlp; 205*0Sstevel@tonic-gate t_uscalar_t prim; 206*0Sstevel@tonic-gate proto_req_info_t *prip; 207*0Sstevel@tonic-gate boolean_t success; 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_uscalar_t)) { 210*0Sstevel@tonic-gate freemsg(mp); 211*0Sstevel@tonic-gate return; 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate udlp = (union DL_primitives *)mp->b_rptr; 215*0Sstevel@tonic-gate prim = udlp->dl_primitive; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * Select the correct jump table. 219*0Sstevel@tonic-gate */ 220*0Sstevel@tonic-gate if (prim & DL_SOLARIS) { 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * Entries in the 'solaris extensions' jump table 223*0Sstevel@tonic-gate * have an extra bit in the primitive value. Clear it 224*0Sstevel@tonic-gate * to do the lookup. 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate prim &= ~DL_SOLARIS; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* 229*0Sstevel@tonic-gate * Check the primitive is in range. 230*0Sstevel@tonic-gate */ 231*0Sstevel@tonic-gate if (prim >= PROTO_SRI_COUNT) 232*0Sstevel@tonic-gate goto unsupported; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate /* 235*0Sstevel@tonic-gate * Grab the jump table entry. 236*0Sstevel@tonic-gate */ 237*0Sstevel@tonic-gate prip = &proto_sri[prim]; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * OR the cleared bit back in to make the primitive valid 241*0Sstevel@tonic-gate * again. 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate prim |= DL_SOLARIS; 244*0Sstevel@tonic-gate } else { 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * Check the primitive is in range. 247*0Sstevel@tonic-gate */ 248*0Sstevel@tonic-gate if (prim >= PROTO_RI_COUNT) 249*0Sstevel@tonic-gate goto unsupported; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * Grab the jump table entry. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate prip = &proto_ri[prim]; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate ASSERT(prip->pri_prim == prim); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * If this primitive causes the data-link channel used by this 261*0Sstevel@tonic-gate * object to become active, then we need to notify dls. Note that 262*0Sstevel@tonic-gate * if we're already passive by having succesfully processed a 263*0Sstevel@tonic-gate * DL_PASSIVE_REQ, then active primitives do not cause us to become 264*0Sstevel@tonic-gate * active. 265*0Sstevel@tonic-gate */ 266*0Sstevel@tonic-gate if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) { 267*0Sstevel@tonic-gate if (!dls_active_set(dsp->ds_dc)) { 268*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, prim, DL_SYSERR, EBUSY); 269*0Sstevel@tonic-gate return; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Check whether we need, and whether we have, exclusive access to 275*0Sstevel@tonic-gate * the stream. 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate if (prip->pri_needexcl) { 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * We only have shared access and we need exclusive access. 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate ASSERT(!PERIM_EXCL(dsp->ds_wq)); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* 284*0Sstevel@tonic-gate * Process via qwriter(9f). 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate qwriter(dsp->ds_wq, mp, proto_excl, PERIM_INNER); 287*0Sstevel@tonic-gate return; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate success = prip->pri_fn(dsp, udlp, mp); 291*0Sstevel@tonic-gate if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) { 292*0Sstevel@tonic-gate if (success) 293*0Sstevel@tonic-gate dsp->ds_passivestate = DLD_ACTIVE; 294*0Sstevel@tonic-gate else 295*0Sstevel@tonic-gate dls_active_clear(dsp->ds_dc); 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate return; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate unsupported: 301*0Sstevel@tonic-gate (void) proto_req(dsp, udlp, mp); 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* 305*0Sstevel@tonic-gate * Called via qwriter(9f). 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate static void 308*0Sstevel@tonic-gate proto_excl(queue_t *q, mblk_t *mp) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate dld_str_t *dsp = q->q_ptr; 311*0Sstevel@tonic-gate union DL_primitives *udlp; 312*0Sstevel@tonic-gate t_uscalar_t prim; 313*0Sstevel@tonic-gate proto_req_info_t *prip; 314*0Sstevel@tonic-gate boolean_t success; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate ASSERT(MBLKL(mp) >= sizeof (t_uscalar_t)); 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate udlp = (union DL_primitives *)mp->b_rptr; 319*0Sstevel@tonic-gate prim = udlp->dl_primitive; 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * Select the correct jump table. 323*0Sstevel@tonic-gate */ 324*0Sstevel@tonic-gate if (prim & DL_SOLARIS) { 325*0Sstevel@tonic-gate /* 326*0Sstevel@tonic-gate * Entries in the 'solaris extensions' jump table 327*0Sstevel@tonic-gate * have an extra bit in the primitive value. Clear it 328*0Sstevel@tonic-gate * to do the lookup. 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate prim &= ~DL_SOLARIS; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* 333*0Sstevel@tonic-gate * Grab the jump table entry. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate ASSERT(prim < PROTO_SRI_COUNT); 336*0Sstevel@tonic-gate prip = &proto_sri[prim]; 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * OR the cleared bit back in to make the primitive valid 340*0Sstevel@tonic-gate * again. 341*0Sstevel@tonic-gate */ 342*0Sstevel@tonic-gate prim |= DL_SOLARIS; 343*0Sstevel@tonic-gate } else { 344*0Sstevel@tonic-gate /* 345*0Sstevel@tonic-gate * Grab the jump table entry. 346*0Sstevel@tonic-gate */ 347*0Sstevel@tonic-gate ASSERT(prim < PROTO_RI_COUNT); 348*0Sstevel@tonic-gate prip = &proto_ri[prim]; 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate ASSERT(prip->pri_prim == prim); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate success = prip->pri_fn(dsp, udlp, mp); 354*0Sstevel@tonic-gate if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) { 355*0Sstevel@tonic-gate if (success) 356*0Sstevel@tonic-gate dsp->ds_passivestate = DLD_ACTIVE; 357*0Sstevel@tonic-gate else 358*0Sstevel@tonic-gate dls_active_clear(dsp->ds_dc); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * DL_INFO_REQ 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate /*ARGSUSED*/ 366*0Sstevel@tonic-gate static boolean_t 367*0Sstevel@tonic-gate proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 368*0Sstevel@tonic-gate { 369*0Sstevel@tonic-gate proto_info_ack(dsp, mp); 370*0Sstevel@tonic-gate return (B_TRUE); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * DL_ATTACH_REQ 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate static boolean_t 377*0Sstevel@tonic-gate proto_attach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 378*0Sstevel@tonic-gate { 379*0Sstevel@tonic-gate dl_attach_req_t *dlp = (dl_attach_req_t *)udlp; 380*0Sstevel@tonic-gate t_scalar_t index; 381*0Sstevel@tonic-gate dld_node_t *dnp; 382*0Sstevel@tonic-gate dld_ppa_t *dpp; 383*0Sstevel@tonic-gate int err; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate if (dsp->ds_dlstate != DL_UNATTACHED) { 388*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0); 389*0Sstevel@tonic-gate return (B_FALSE); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_attach_req_t)) { 393*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0); 394*0Sstevel@tonic-gate return (B_FALSE); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate index = dlp->dl_ppa; 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate dnp = dsp->ds_dnp; 400*0Sstevel@tonic-gate ASSERT(dnp->dn_style == DL_STYLE2); 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if ((dpp = dld_node_ppa_find(dnp, index)) == NULL) { 403*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0); 404*0Sstevel@tonic-gate return (B_FALSE); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate dsp->ds_dlstate = DL_ATTACH_PENDING; 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate err = dld_str_attach(dsp, dpp); 410*0Sstevel@tonic-gate proto_attach_ack(dsp, mp, err); 411*0Sstevel@tonic-gate return (err == 0); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* 415*0Sstevel@tonic-gate * DL_DETACH_REQ 416*0Sstevel@tonic-gate */ 417*0Sstevel@tonic-gate /*ARGSUSED*/ 418*0Sstevel@tonic-gate static boolean_t 419*0Sstevel@tonic-gate proto_detach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 420*0Sstevel@tonic-gate { 421*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate if (dsp->ds_dlstate != DL_UNBOUND) { 424*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0); 425*0Sstevel@tonic-gate return (B_FALSE); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_detach_req_t)) { 429*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0); 430*0Sstevel@tonic-gate return (B_FALSE); 431*0Sstevel@tonic-gate } 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate if ((dsp->ds_dnp)->dn_style == DL_STYLE1) { 434*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0); 435*0Sstevel@tonic-gate return (B_FALSE); 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate dsp->ds_dlstate = DL_DETACH_PENDING; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate dld_str_detach(dsp); 441*0Sstevel@tonic-gate proto_detach_ack(dsp, mp); 442*0Sstevel@tonic-gate return (B_TRUE); 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate /* 446*0Sstevel@tonic-gate * DL_BIND_REQ 447*0Sstevel@tonic-gate */ 448*0Sstevel@tonic-gate static boolean_t 449*0Sstevel@tonic-gate proto_bind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 450*0Sstevel@tonic-gate { 451*0Sstevel@tonic-gate dl_bind_req_t *dlp = (dl_bind_req_t *)udlp; 452*0Sstevel@tonic-gate int err; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate if (dsp->ds_dlstate != DL_UNBOUND) { 457*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0); 458*0Sstevel@tonic-gate return (B_FALSE); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_bind_req_t)) { 462*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_BADPRIM, 0); 463*0Sstevel@tonic-gate return (B_FALSE); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate if (dlp->dl_xidtest_flg != 0) { 467*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_NOAUTO, 0); 468*0Sstevel@tonic-gate return (B_FALSE); 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate if (dlp->dl_service_mode != DL_CLDLS) { 472*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0); 473*0Sstevel@tonic-gate return (B_FALSE); 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate dsp->ds_dlstate = DL_BIND_PENDING; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate /* 479*0Sstevel@tonic-gate * Set the receive callback. 480*0Sstevel@tonic-gate */ 481*0Sstevel@tonic-gate dls_rx_set(dsp->ds_dc, dld_str_rx_unitdata, (void *)dsp); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate /* 484*0Sstevel@tonic-gate * Bind the channel such that it can receive packets. 485*0Sstevel@tonic-gate */ 486*0Sstevel@tonic-gate dsp->ds_sap = dlp->dl_sap; 487*0Sstevel@tonic-gate err = dls_bind(dsp->ds_dc, dlp->dl_sap); 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate proto_bind_ack(dsp, mp, err); 490*0Sstevel@tonic-gate return (err == 0); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate /* 494*0Sstevel@tonic-gate * DL_UNBIND_REQ 495*0Sstevel@tonic-gate */ 496*0Sstevel@tonic-gate /*ARGSUSED*/ 497*0Sstevel@tonic-gate static boolean_t 498*0Sstevel@tonic-gate proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 499*0Sstevel@tonic-gate { 500*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (dsp->ds_dlstate != DL_IDLE) { 503*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0); 504*0Sstevel@tonic-gate return (B_FALSE); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_unbind_req_t)) { 508*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_BADPRIM, 0); 509*0Sstevel@tonic-gate return (B_FALSE); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNBIND_PENDING; 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate /* 515*0Sstevel@tonic-gate * Flush any remaining packets scheduled for transmission. 516*0Sstevel@tonic-gate */ 517*0Sstevel@tonic-gate flushq(dsp->ds_wq, FLUSHALL); 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate /* 520*0Sstevel@tonic-gate * Reset the M_DATA handler. 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate dld_str_tx_drop(dsp); 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* 525*0Sstevel@tonic-gate * Unbind the channel to stop packets being received. 526*0Sstevel@tonic-gate */ 527*0Sstevel@tonic-gate dls_unbind(dsp->ds_dc); 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate /* 530*0Sstevel@tonic-gate * Disable polling mode, if it is enabled. 531*0Sstevel@tonic-gate */ 532*0Sstevel@tonic-gate proto_poll_disable(dsp); 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate /* 535*0Sstevel@tonic-gate * Clear the receive callback. 536*0Sstevel@tonic-gate */ 537*0Sstevel@tonic-gate dls_rx_set(dsp->ds_dc, NULL, NULL); 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate /* 540*0Sstevel@tonic-gate * Set the mode back to the default (unitdata). 541*0Sstevel@tonic-gate */ 542*0Sstevel@tonic-gate dsp->ds_mode = DLD_UNITDATA; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate proto_unbind_ack(dsp, mp); 545*0Sstevel@tonic-gate return (B_TRUE); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate /* 549*0Sstevel@tonic-gate * DL_PROMISCON_REQ 550*0Sstevel@tonic-gate */ 551*0Sstevel@tonic-gate static boolean_t 552*0Sstevel@tonic-gate proto_promiscon_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 553*0Sstevel@tonic-gate { 554*0Sstevel@tonic-gate dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)udlp; 555*0Sstevel@tonic-gate int err; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 560*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 561*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_OUTSTATE, 0); 562*0Sstevel@tonic-gate return (B_FALSE); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) { 566*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0); 567*0Sstevel@tonic-gate return (B_FALSE); 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate switch (dlp->dl_level) { 571*0Sstevel@tonic-gate case DL_PROMISC_SAP: 572*0Sstevel@tonic-gate dsp->ds_promisc |= DLS_PROMISC_SAP; 573*0Sstevel@tonic-gate break; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate case DL_PROMISC_MULTI: 576*0Sstevel@tonic-gate dsp->ds_promisc |= DLS_PROMISC_MULTI; 577*0Sstevel@tonic-gate break; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate case DL_PROMISC_PHYS: 580*0Sstevel@tonic-gate dsp->ds_promisc |= DLS_PROMISC_PHYS; 581*0Sstevel@tonic-gate break; 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate default: 584*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 585*0Sstevel@tonic-gate 0); 586*0Sstevel@tonic-gate return (B_FALSE); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * Adjust channel promiscuity. 591*0Sstevel@tonic-gate */ 592*0Sstevel@tonic-gate err = dls_promisc(dsp->ds_dc, dsp->ds_promisc); 593*0Sstevel@tonic-gate proto_promiscon_ack(dsp, mp, err); 594*0Sstevel@tonic-gate return (err == 0); 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate /* 598*0Sstevel@tonic-gate * DL_PROMISCOFF_REQ 599*0Sstevel@tonic-gate */ 600*0Sstevel@tonic-gate static boolean_t 601*0Sstevel@tonic-gate proto_promiscoff_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 602*0Sstevel@tonic-gate { 603*0Sstevel@tonic-gate dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)udlp; 604*0Sstevel@tonic-gate int err; 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 609*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 610*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_OUTSTATE, 0); 611*0Sstevel@tonic-gate return (B_FALSE); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) { 615*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0); 616*0Sstevel@tonic-gate return (B_FALSE); 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate switch (dlp->dl_level) { 620*0Sstevel@tonic-gate case DL_PROMISC_SAP: 621*0Sstevel@tonic-gate if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) 622*0Sstevel@tonic-gate goto notenab; 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate dsp->ds_promisc &= ~DLS_PROMISC_SAP; 625*0Sstevel@tonic-gate break; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate case DL_PROMISC_MULTI: 628*0Sstevel@tonic-gate if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) 629*0Sstevel@tonic-gate goto notenab; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate dsp->ds_promisc &= ~DLS_PROMISC_MULTI; 632*0Sstevel@tonic-gate break; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate case DL_PROMISC_PHYS: 635*0Sstevel@tonic-gate if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) 636*0Sstevel@tonic-gate goto notenab; 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate dsp->ds_promisc &= ~DLS_PROMISC_PHYS; 639*0Sstevel@tonic-gate break; 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate default: 642*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 643*0Sstevel@tonic-gate 0); 644*0Sstevel@tonic-gate return (B_FALSE); 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate /* 648*0Sstevel@tonic-gate * Adjust channel promiscuity. 649*0Sstevel@tonic-gate */ 650*0Sstevel@tonic-gate err = dls_promisc(dsp->ds_dc, dsp->ds_promisc); 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate proto_promiscoff_ack(dsp, mp, err); 653*0Sstevel@tonic-gate return (err == 0); 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate notenab: 656*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0); 657*0Sstevel@tonic-gate return (B_FALSE); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate /* 661*0Sstevel@tonic-gate * DL_ENABMULTI_REQ 662*0Sstevel@tonic-gate */ 663*0Sstevel@tonic-gate static boolean_t 664*0Sstevel@tonic-gate proto_enabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 665*0Sstevel@tonic-gate { 666*0Sstevel@tonic-gate dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)udlp; 667*0Sstevel@tonic-gate int err; 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 672*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 673*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0); 674*0Sstevel@tonic-gate return (B_FALSE); 675*0Sstevel@tonic-gate } 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_enabmulti_req_t) || 678*0Sstevel@tonic-gate !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 679*0Sstevel@tonic-gate dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 680*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0); 681*0Sstevel@tonic-gate return (B_FALSE); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate err = dls_multicst_add(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset); 685*0Sstevel@tonic-gate proto_enabmulti_ack(dsp, mp, err); 686*0Sstevel@tonic-gate return (err == 0); 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate /* 690*0Sstevel@tonic-gate * DL_DISABMULTI_REQ 691*0Sstevel@tonic-gate */ 692*0Sstevel@tonic-gate static boolean_t 693*0Sstevel@tonic-gate proto_disabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 694*0Sstevel@tonic-gate { 695*0Sstevel@tonic-gate dl_disabmulti_req_t *dlp = (dl_disabmulti_req_t *)udlp; 696*0Sstevel@tonic-gate int err; 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 701*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 702*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0); 703*0Sstevel@tonic-gate return (B_FALSE); 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_disabmulti_req_t) || 707*0Sstevel@tonic-gate !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 708*0Sstevel@tonic-gate dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 709*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0); 710*0Sstevel@tonic-gate return (B_FALSE); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate err = dls_multicst_remove(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset); 714*0Sstevel@tonic-gate proto_disabmulti_ack(dsp, mp, err); 715*0Sstevel@tonic-gate return (err == 0); 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate /* 719*0Sstevel@tonic-gate * DL_PHYS_ADDR_REQ 720*0Sstevel@tonic-gate */ 721*0Sstevel@tonic-gate static boolean_t 722*0Sstevel@tonic-gate proto_physaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 723*0Sstevel@tonic-gate { 724*0Sstevel@tonic-gate dl_phys_addr_req_t *dlp = (dl_phys_addr_req_t *)udlp; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 727*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 728*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0); 729*0Sstevel@tonic-gate return (B_FALSE); 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_phys_addr_req_t)) { 733*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0); 734*0Sstevel@tonic-gate return (B_FALSE); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate if (dlp->dl_addr_type != DL_CURR_PHYS_ADDR && 738*0Sstevel@tonic-gate dlp->dl_addr_type != DL_FACT_PHYS_ADDR) { 739*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_UNSUPPORTED, 0); 740*0Sstevel@tonic-gate return (B_FALSE); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate proto_physaddr_ack(dsp, mp, dlp->dl_addr_type); 744*0Sstevel@tonic-gate return (B_TRUE); 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate /* 748*0Sstevel@tonic-gate * DL_SET_PHYS_ADDR_REQ 749*0Sstevel@tonic-gate */ 750*0Sstevel@tonic-gate static boolean_t 751*0Sstevel@tonic-gate proto_setphysaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 752*0Sstevel@tonic-gate { 753*0Sstevel@tonic-gate dl_set_phys_addr_req_t *dlp = (dl_set_phys_addr_req_t *)udlp; 754*0Sstevel@tonic-gate int err; 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 759*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 760*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 761*0Sstevel@tonic-gate 0); 762*0Sstevel@tonic-gate return (B_FALSE); 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_set_phys_addr_req_t) || 766*0Sstevel@tonic-gate !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) || 767*0Sstevel@tonic-gate dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) { 768*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 769*0Sstevel@tonic-gate 0); 770*0Sstevel@tonic-gate return (B_FALSE); 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate err = mac_unicst_set(dsp->ds_mh, mp->b_rptr + dlp->dl_addr_offset); 774*0Sstevel@tonic-gate proto_setphysaddr_ack(dsp, mp, err); 775*0Sstevel@tonic-gate return (err == 0); 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate /* 779*0Sstevel@tonic-gate * DL_UDQOS_REQ 780*0Sstevel@tonic-gate */ 781*0Sstevel@tonic-gate static boolean_t 782*0Sstevel@tonic-gate proto_udqos_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 783*0Sstevel@tonic-gate { 784*0Sstevel@tonic-gate dl_udqos_req_t *dlp = (dl_udqos_req_t *)udlp; 785*0Sstevel@tonic-gate dl_qos_cl_sel1_t *selp; 786*0Sstevel@tonic-gate int off, len; 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate off = dlp->dl_qos_offset; 791*0Sstevel@tonic-gate len = dlp->dl_qos_length; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_udqos_req_t) || !MBLKIN(mp, off, len)) { 794*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADPRIM, 0); 795*0Sstevel@tonic-gate return (B_FALSE); 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off); 799*0Sstevel@tonic-gate if (selp->dl_qos_type != DL_QOS_CL_SEL1) { 800*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADQOSTYPE, 0); 801*0Sstevel@tonic-gate return (B_FALSE); 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate if (dsp->ds_vid == VLAN_ID_NONE || 805*0Sstevel@tonic-gate selp->dl_priority > (1 << VLAN_PRI_SIZE) - 1 || 806*0Sstevel@tonic-gate selp->dl_priority < 0) { 807*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADQOSPARAM, 0); 808*0Sstevel@tonic-gate return (B_FALSE); 809*0Sstevel@tonic-gate } 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate dsp->ds_pri = selp->dl_priority; 812*0Sstevel@tonic-gate proto_udqos_ack(dsp, mp); 813*0Sstevel@tonic-gate return (B_TRUE); 814*0Sstevel@tonic-gate } 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gate /* 817*0Sstevel@tonic-gate * DL_CAPABILITY_REQ 818*0Sstevel@tonic-gate */ 819*0Sstevel@tonic-gate /*ARGSUSED*/ 820*0Sstevel@tonic-gate static boolean_t 821*0Sstevel@tonic-gate proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 822*0Sstevel@tonic-gate { 823*0Sstevel@tonic-gate dl_capability_req_t *dlp = (dl_capability_req_t *)udlp; 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 826*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 827*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_OUTSTATE, 828*0Sstevel@tonic-gate 0); 829*0Sstevel@tonic-gate return (B_FALSE); 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_capability_req_t)) { 833*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_BADPRIM, 0); 834*0Sstevel@tonic-gate return (B_FALSE); 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate /* 838*0Sstevel@tonic-gate * This request is overloaded. If there are no requested capabilities 839*0Sstevel@tonic-gate * then we just want to acknowledge with all the capabilities we 840*0Sstevel@tonic-gate * support. Otherwise we enable the set of capabilities requested. 841*0Sstevel@tonic-gate */ 842*0Sstevel@tonic-gate if (dlp->dl_sub_length == 0) { 843*0Sstevel@tonic-gate proto_capability_ack(dsp, mp); 844*0Sstevel@tonic-gate return (B_TRUE); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate if (!MBLKIN(mp, dlp->dl_sub_offset, dlp->dl_sub_length)) { 848*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_BADPRIM, 0); 849*0Sstevel@tonic-gate return (B_FALSE); 850*0Sstevel@tonic-gate } 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate proto_capability_enable(dsp, mp); 853*0Sstevel@tonic-gate return (B_TRUE); 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate /* 857*0Sstevel@tonic-gate * DL_NOTIFY_REQ 858*0Sstevel@tonic-gate */ 859*0Sstevel@tonic-gate static boolean_t 860*0Sstevel@tonic-gate proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 861*0Sstevel@tonic-gate { 862*0Sstevel@tonic-gate dl_notify_req_t *dlp = (dl_notify_req_t *)udlp; 863*0Sstevel@tonic-gate uint_t notifications = 864*0Sstevel@tonic-gate DL_NOTE_PROMISC_ON_PHYS | 865*0Sstevel@tonic-gate DL_NOTE_PROMISC_OFF_PHYS | 866*0Sstevel@tonic-gate DL_NOTE_PHYS_ADDR | 867*0Sstevel@tonic-gate DL_NOTE_LINK_UP | 868*0Sstevel@tonic-gate DL_NOTE_LINK_DOWN | 869*0Sstevel@tonic-gate DL_NOTE_CAPAB_RENEG; 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 872*0Sstevel@tonic-gate DL_ACK_PENDING(dsp->ds_dlstate)) { 873*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_NOTIFY_REQ, DL_OUTSTATE, 874*0Sstevel@tonic-gate 0); 875*0Sstevel@tonic-gate return (B_FALSE); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_notify_req_t)) { 879*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_NOTIFY_REQ, DL_BADPRIM, 0); 880*0Sstevel@tonic-gate return (B_FALSE); 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED]) 884*0Sstevel@tonic-gate notifications |= DL_NOTE_SPEED; 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate proto_notify_ack(dsp, mp, dlp->dl_notifications & notifications, 887*0Sstevel@tonic-gate notifications); 888*0Sstevel@tonic-gate return (B_TRUE); 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate /* 892*0Sstevel@tonic-gate * DL_UINTDATA_REQ 893*0Sstevel@tonic-gate */ 894*0Sstevel@tonic-gate static boolean_t 895*0Sstevel@tonic-gate proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 896*0Sstevel@tonic-gate { 897*0Sstevel@tonic-gate queue_t *q = dsp->ds_wq; 898*0Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)udlp; 899*0Sstevel@tonic-gate off_t off; 900*0Sstevel@tonic-gate size_t len; 901*0Sstevel@tonic-gate size_t size; 902*0Sstevel@tonic-gate const uint8_t *addr; 903*0Sstevel@tonic-gate uint16_t sap; 904*0Sstevel@tonic-gate uint_t addr_length; 905*0Sstevel@tonic-gate mblk_t *bp; 906*0Sstevel@tonic-gate mblk_t *cont; 907*0Sstevel@tonic-gate uint32_t start; 908*0Sstevel@tonic-gate uint32_t stuff; 909*0Sstevel@tonic-gate uint32_t end; 910*0Sstevel@tonic-gate uint32_t value; 911*0Sstevel@tonic-gate uint32_t flags; 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate if (dsp->ds_dlstate != DL_IDLE) { 914*0Sstevel@tonic-gate dlerrorack(q, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0); 915*0Sstevel@tonic-gate return (B_FALSE); 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_unitdata_req_t) || mp->b_cont == NULL) { 919*0Sstevel@tonic-gate dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADPRIM, 0); 920*0Sstevel@tonic-gate return (B_FALSE); 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate off = dlp->dl_dest_addr_offset; 924*0Sstevel@tonic-gate len = dlp->dl_dest_addr_length; 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate if (!MBLKIN(mp, off, len) || !IS_P2ALIGNED(off, sizeof (uint16_t))) { 927*0Sstevel@tonic-gate dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADPRIM, 0); 928*0Sstevel@tonic-gate return (B_FALSE); 929*0Sstevel@tonic-gate } 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate addr_length = dsp->ds_mip->mi_addr_length; 932*0Sstevel@tonic-gate if (len != addr_length + sizeof (uint16_t)) 933*0Sstevel@tonic-gate goto badaddr; 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate addr = mp->b_rptr + off; 936*0Sstevel@tonic-gate sap = *(uint16_t *)(mp->b_rptr + off + addr_length); 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* 939*0Sstevel@tonic-gate * Check the length of the packet and the block types. 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate size = 0; 942*0Sstevel@tonic-gate cont = mp->b_cont; 943*0Sstevel@tonic-gate for (bp = cont; bp != NULL; bp = bp->b_cont) { 944*0Sstevel@tonic-gate if (DB_TYPE(bp) != M_DATA) 945*0Sstevel@tonic-gate goto baddata; 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate size += MBLKL(bp); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate if (size > dsp->ds_mip->mi_sdu_max) 951*0Sstevel@tonic-gate goto baddata; 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate /* 954*0Sstevel@tonic-gate * Build a packet header. 955*0Sstevel@tonic-gate */ 956*0Sstevel@tonic-gate if ((bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL) 957*0Sstevel@tonic-gate goto badaddr; 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate /* 960*0Sstevel@tonic-gate * We no longer need the M_PROTO header, so free it. 961*0Sstevel@tonic-gate */ 962*0Sstevel@tonic-gate freeb(mp); 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* 965*0Sstevel@tonic-gate * Transfer the checksum offload information if it is present. 966*0Sstevel@tonic-gate */ 967*0Sstevel@tonic-gate hcksum_retrieve(cont, NULL, NULL, &start, &stuff, &end, &value, 968*0Sstevel@tonic-gate &flags); 969*0Sstevel@tonic-gate (void) hcksum_assoc(bp, NULL, NULL, start, stuff, end, value, flags, 970*0Sstevel@tonic-gate 0); 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate /* 973*0Sstevel@tonic-gate * Link the payload onto the new header. 974*0Sstevel@tonic-gate */ 975*0Sstevel@tonic-gate ASSERT(bp->b_cont == NULL); 976*0Sstevel@tonic-gate bp->b_cont = cont; 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate /* 979*0Sstevel@tonic-gate * If something is already queued then we must queue to avoid 980*0Sstevel@tonic-gate * re-ordering. 981*0Sstevel@tonic-gate */ 982*0Sstevel@tonic-gate if (q->q_first != NULL) { 983*0Sstevel@tonic-gate (void) putq(q, bp); 984*0Sstevel@tonic-gate return (B_TRUE); 985*0Sstevel@tonic-gate } 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* 988*0Sstevel@tonic-gate * Attempt to transmit the packet. 989*0Sstevel@tonic-gate */ 990*0Sstevel@tonic-gate if ((mp = dls_tx(dsp->ds_dc, bp)) != NULL) { 991*0Sstevel@tonic-gate noenable(q); 992*0Sstevel@tonic-gate while ((bp = mp) != NULL) { 993*0Sstevel@tonic-gate mp = mp->b_next; 994*0Sstevel@tonic-gate bp->b_next = NULL; 995*0Sstevel@tonic-gate (void) putq(q, bp); 996*0Sstevel@tonic-gate } 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate return (B_TRUE); 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate badaddr: 1001*0Sstevel@tonic-gate dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADADDR, 0); 1002*0Sstevel@tonic-gate return (B_FALSE); 1003*0Sstevel@tonic-gate 1004*0Sstevel@tonic-gate baddata: 1005*0Sstevel@tonic-gate dluderrorind(q, mp, (void *)addr, len, DL_BADDATA, 0); 1006*0Sstevel@tonic-gate return (B_FALSE); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate 1009*0Sstevel@tonic-gate /* 1010*0Sstevel@tonic-gate * DL_PASSIVE_REQ 1011*0Sstevel@tonic-gate */ 1012*0Sstevel@tonic-gate /* ARGSUSED */ 1013*0Sstevel@tonic-gate static boolean_t 1014*0Sstevel@tonic-gate proto_passive_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp) 1015*0Sstevel@tonic-gate { 1016*0Sstevel@tonic-gate ASSERT(PERIM_EXCL(dsp->ds_wq)); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate /* 1019*0Sstevel@tonic-gate * If we've already become active by issuing an active primitive, 1020*0Sstevel@tonic-gate * then it's too late to try to become passive. 1021*0Sstevel@tonic-gate */ 1022*0Sstevel@tonic-gate if (dsp->ds_passivestate == DLD_ACTIVE) { 1023*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, DL_OUTSTATE, 0); 1024*0Sstevel@tonic-gate return (B_FALSE); 1025*0Sstevel@tonic-gate } 1026*0Sstevel@tonic-gate 1027*0Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_passive_req_t)) { 1028*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, DL_BADPRIM, 0); 1029*0Sstevel@tonic-gate return (B_FALSE); 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate dsp->ds_passivestate = DLD_PASSIVE; 1033*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_PASSIVE_REQ); 1034*0Sstevel@tonic-gate return (B_TRUE); 1035*0Sstevel@tonic-gate } 1036*0Sstevel@tonic-gate 1037*0Sstevel@tonic-gate /* 1038*0Sstevel@tonic-gate * Catch-all handler. 1039*0Sstevel@tonic-gate */ 1040*0Sstevel@tonic-gate static boolean_t 1041*0Sstevel@tonic-gate proto_req(dld_str_t *dsp, union DL_primitives *dlp, mblk_t *mp) 1042*0Sstevel@tonic-gate { 1043*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0); 1044*0Sstevel@tonic-gate return (B_FALSE); 1045*0Sstevel@tonic-gate } 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate typedef struct dl_info_ack_wrapper { 1048*0Sstevel@tonic-gate dl_info_ack_t dl_info; 1049*0Sstevel@tonic-gate uint8_t dl_addr[MAXADDRLEN + sizeof (uint16_t)]; 1050*0Sstevel@tonic-gate uint8_t dl_brdcst_addr[MAXADDRLEN]; 1051*0Sstevel@tonic-gate dl_qos_cl_range1_t dl_qos_range1; 1052*0Sstevel@tonic-gate dl_qos_cl_sel1_t dl_qos_sel1; 1053*0Sstevel@tonic-gate } dl_info_ack_wrapper_t; 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate #define NEG(x) -(x) 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* 1058*0Sstevel@tonic-gate * DL_INFO_ACK 1059*0Sstevel@tonic-gate */ 1060*0Sstevel@tonic-gate static void 1061*0Sstevel@tonic-gate proto_info_ack(dld_str_t *dsp, mblk_t *mp) 1062*0Sstevel@tonic-gate { 1063*0Sstevel@tonic-gate dl_info_ack_wrapper_t *dlwp; 1064*0Sstevel@tonic-gate dl_info_ack_t *dlp; 1065*0Sstevel@tonic-gate dl_qos_cl_sel1_t *selp; 1066*0Sstevel@tonic-gate dl_qos_cl_range1_t *rangep; 1067*0Sstevel@tonic-gate uint8_t *addr; 1068*0Sstevel@tonic-gate uint8_t *brdcst_addr; 1069*0Sstevel@tonic-gate dld_node_t *dnp; 1070*0Sstevel@tonic-gate uint_t addr_length; 1071*0Sstevel@tonic-gate uint_t sap_length; 1072*0Sstevel@tonic-gate 1073*0Sstevel@tonic-gate /* 1074*0Sstevel@tonic-gate * Swap the request message for one large enough to contain the 1075*0Sstevel@tonic-gate * wrapper structure defined above. 1076*0Sstevel@tonic-gate */ 1077*0Sstevel@tonic-gate if ((mp = mexchange(dsp->ds_wq, mp, sizeof (dl_info_ack_wrapper_t), 1078*0Sstevel@tonic-gate M_PCPROTO, 0)) == NULL) 1079*0Sstevel@tonic-gate return; 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t)); 1082*0Sstevel@tonic-gate dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr; 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate dlp = &(dlwp->dl_info); 1085*0Sstevel@tonic-gate ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr); 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate dlp->dl_primitive = DL_INFO_ACK; 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate /* 1090*0Sstevel@tonic-gate * Set up the sub-structure pointers. 1091*0Sstevel@tonic-gate */ 1092*0Sstevel@tonic-gate addr = dlwp->dl_addr; 1093*0Sstevel@tonic-gate brdcst_addr = dlwp->dl_brdcst_addr; 1094*0Sstevel@tonic-gate rangep = &(dlwp->dl_qos_range1); 1095*0Sstevel@tonic-gate selp = &(dlwp->dl_qos_sel1); 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* 1098*0Sstevel@tonic-gate * This driver supports only version 2 connectionless DLPI provider 1099*0Sstevel@tonic-gate * nodes. 1100*0Sstevel@tonic-gate */ 1101*0Sstevel@tonic-gate dlp->dl_service_mode = DL_CLDLS; 1102*0Sstevel@tonic-gate dlp->dl_version = DL_VERSION_2; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate /* 1105*0Sstevel@tonic-gate * Set the style of the provider from the dld_node_t structure 1106*0Sstevel@tonic-gate * representing the dev_t that was opened. 1107*0Sstevel@tonic-gate */ 1108*0Sstevel@tonic-gate dnp = dsp->ds_dnp; 1109*0Sstevel@tonic-gate dlp->dl_provider_style = dnp->dn_style; 1110*0Sstevel@tonic-gate ASSERT(dlp->dl_provider_style == DL_STYLE1 || 1111*0Sstevel@tonic-gate dlp->dl_provider_style == DL_STYLE2); 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate /* 1114*0Sstevel@tonic-gate * Set the current DLPI state. 1115*0Sstevel@tonic-gate */ 1116*0Sstevel@tonic-gate dlp->dl_current_state = dsp->ds_dlstate; 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate /* 1119*0Sstevel@tonic-gate * Gratuitously set the media type. This is because the Cisco VPN 3000 1120*0Sstevel@tonic-gate * module assumes that the media type is known prior to DL_ATTACH_REQ 1121*0Sstevel@tonic-gate * being completed. 1122*0Sstevel@tonic-gate */ 1123*0Sstevel@tonic-gate dlp->dl_mac_type = DL_ETHER; 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate /* 1126*0Sstevel@tonic-gate * If the stream is not at least attached then we're done. 1127*0Sstevel@tonic-gate */ 1128*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_UNATTACHED || 1129*0Sstevel@tonic-gate dsp->ds_dlstate == DL_ATTACH_PENDING || 1130*0Sstevel@tonic-gate dsp->ds_dlstate == DL_DETACH_PENDING) 1131*0Sstevel@tonic-gate goto done; 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate /* 1134*0Sstevel@tonic-gate * Set the media type (properly this time). 1135*0Sstevel@tonic-gate */ 1136*0Sstevel@tonic-gate dlp->dl_mac_type = dsp->ds_mip->mi_media; 1137*0Sstevel@tonic-gate 1138*0Sstevel@tonic-gate /* 1139*0Sstevel@tonic-gate * Set the DLSAP length. We only support 16 bit values and they 1140*0Sstevel@tonic-gate * appear after the MAC address portion of DLSAP addresses. 1141*0Sstevel@tonic-gate */ 1142*0Sstevel@tonic-gate sap_length = sizeof (uint16_t); 1143*0Sstevel@tonic-gate dlp->dl_sap_length = NEG(sap_length); 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate /* 1146*0Sstevel@tonic-gate * Set the minimum and maximum payload sizes. 1147*0Sstevel@tonic-gate */ 1148*0Sstevel@tonic-gate dlp->dl_min_sdu = dsp->ds_mip->mi_sdu_min; 1149*0Sstevel@tonic-gate dlp->dl_max_sdu = dsp->ds_mip->mi_sdu_max; 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate addr_length = dsp->ds_mip->mi_addr_length; 1152*0Sstevel@tonic-gate ASSERT(addr_length != 0); 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate /* 1155*0Sstevel@tonic-gate * Copy in the media broadcast address. 1156*0Sstevel@tonic-gate */ 1157*0Sstevel@tonic-gate dlp->dl_brdcst_addr_offset = (uintptr_t)brdcst_addr - (uintptr_t)dlp; 1158*0Sstevel@tonic-gate bcopy(dsp->ds_mip->mi_brdcst_addr, brdcst_addr, addr_length); 1159*0Sstevel@tonic-gate dlp->dl_brdcst_addr_length = addr_length; 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate /* 1162*0Sstevel@tonic-gate * We only support QoS information for VLAN interfaces. 1163*0Sstevel@tonic-gate */ 1164*0Sstevel@tonic-gate if (dsp->ds_vid != VLAN_ID_NONE) { 1165*0Sstevel@tonic-gate dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp; 1166*0Sstevel@tonic-gate dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t); 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate rangep->dl_qos_type = DL_QOS_CL_RANGE1; 1169*0Sstevel@tonic-gate rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN; 1170*0Sstevel@tonic-gate rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN; 1171*0Sstevel@tonic-gate rangep->dl_protection.dl_min = DL_UNKNOWN; 1172*0Sstevel@tonic-gate rangep->dl_protection.dl_max = DL_UNKNOWN; 1173*0Sstevel@tonic-gate rangep->dl_residual_error = DL_UNKNOWN; 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* 1176*0Sstevel@tonic-gate * Specify the supported range of priorities. 1177*0Sstevel@tonic-gate */ 1178*0Sstevel@tonic-gate rangep->dl_priority.dl_min = 0; 1179*0Sstevel@tonic-gate rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1; 1180*0Sstevel@tonic-gate 1181*0Sstevel@tonic-gate dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp; 1182*0Sstevel@tonic-gate dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t); 1183*0Sstevel@tonic-gate 1184*0Sstevel@tonic-gate selp->dl_qos_type = DL_QOS_CL_SEL1; 1185*0Sstevel@tonic-gate selp->dl_trans_delay = DL_UNKNOWN; 1186*0Sstevel@tonic-gate selp->dl_protection = DL_UNKNOWN; 1187*0Sstevel@tonic-gate selp->dl_residual_error = DL_UNKNOWN; 1188*0Sstevel@tonic-gate 1189*0Sstevel@tonic-gate /* 1190*0Sstevel@tonic-gate * Specify the current priority (which can be changed by 1191*0Sstevel@tonic-gate * the DL_UDQOS_REQ primitive). 1192*0Sstevel@tonic-gate */ 1193*0Sstevel@tonic-gate selp->dl_priority = dsp->ds_pri; 1194*0Sstevel@tonic-gate } else { 1195*0Sstevel@tonic-gate /* 1196*0Sstevel@tonic-gate * Shorten the buffer to lose the unused QoS information 1197*0Sstevel@tonic-gate * structures. This is to work around a bug in the Cisco VPN 1198*0Sstevel@tonic-gate * 3000 module. 1199*0Sstevel@tonic-gate */ 1200*0Sstevel@tonic-gate mp->b_wptr = (uint8_t *)rangep; 1201*0Sstevel@tonic-gate } 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate dlp->dl_addr_length = addr_length + sizeof (uint16_t); 1204*0Sstevel@tonic-gate if (dsp->ds_dlstate == DL_IDLE) { 1205*0Sstevel@tonic-gate /* 1206*0Sstevel@tonic-gate * The stream is bound. Therefore we can formulate a valid 1207*0Sstevel@tonic-gate * DLSAP address. 1208*0Sstevel@tonic-gate */ 1209*0Sstevel@tonic-gate dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp; 1210*0Sstevel@tonic-gate bcopy(dsp->ds_curr_addr, addr, addr_length); 1211*0Sstevel@tonic-gate *(uint16_t *)(addr + addr_length) = dsp->ds_sap; 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate done: 1215*0Sstevel@tonic-gate ASSERT(IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0)); 1216*0Sstevel@tonic-gate ASSERT(IMPLY(dlp->dl_qos_range_offset != 0, 1217*0Sstevel@tonic-gate dlp->dl_qos_range_length != 0)); 1218*0Sstevel@tonic-gate ASSERT(IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0)); 1219*0Sstevel@tonic-gate ASSERT(IMPLY(dlp->dl_brdcst_addr_offset != 0, 1220*0Sstevel@tonic-gate dlp->dl_brdcst_addr_length != 0)); 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate qreply(dsp->ds_wq, mp); 1223*0Sstevel@tonic-gate } 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate /* 1226*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1227*0Sstevel@tonic-gate */ 1228*0Sstevel@tonic-gate static void 1229*0Sstevel@tonic-gate proto_attach_ack(dld_str_t *dsp, mblk_t *mp, int err) 1230*0Sstevel@tonic-gate { 1231*0Sstevel@tonic-gate int dl_err; 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate if (err != 0) 1234*0Sstevel@tonic-gate goto failed; 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNBOUND; 1237*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_ATTACH_REQ); 1238*0Sstevel@tonic-gate return; 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate failed: 1241*0Sstevel@tonic-gate switch (err) { 1242*0Sstevel@tonic-gate case ENOENT: 1243*0Sstevel@tonic-gate dl_err = DL_BADPPA; 1244*0Sstevel@tonic-gate err = 0; 1245*0Sstevel@tonic-gate break; 1246*0Sstevel@tonic-gate 1247*0Sstevel@tonic-gate default: 1248*0Sstevel@tonic-gate dl_err = DL_SYSERR; 1249*0Sstevel@tonic-gate break; 1250*0Sstevel@tonic-gate } 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNATTACHED; 1253*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, dl_err, err); 1254*0Sstevel@tonic-gate } 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate /* 1257*0Sstevel@tonic-gate * DL_OK_ACK 1258*0Sstevel@tonic-gate */ 1259*0Sstevel@tonic-gate static void 1260*0Sstevel@tonic-gate proto_detach_ack(dld_str_t *dsp, mblk_t *mp) 1261*0Sstevel@tonic-gate { 1262*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNATTACHED; 1263*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_DETACH_REQ); 1264*0Sstevel@tonic-gate } 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate /* 1267*0Sstevel@tonic-gate * DL_BIND_ACK/DL_ERROR_ACK 1268*0Sstevel@tonic-gate */ 1269*0Sstevel@tonic-gate static void 1270*0Sstevel@tonic-gate proto_bind_ack(dld_str_t *dsp, mblk_t *mp, int err) 1271*0Sstevel@tonic-gate { 1272*0Sstevel@tonic-gate uint8_t addr[MAXADDRLEN]; 1273*0Sstevel@tonic-gate uint_t addr_length; 1274*0Sstevel@tonic-gate int dl_err; 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate if (err != 0) 1277*0Sstevel@tonic-gate goto failed; 1278*0Sstevel@tonic-gate 1279*0Sstevel@tonic-gate /* 1280*0Sstevel@tonic-gate * Copy in MAC address. 1281*0Sstevel@tonic-gate */ 1282*0Sstevel@tonic-gate addr_length = dsp->ds_mip->mi_addr_length; 1283*0Sstevel@tonic-gate bcopy(dsp->ds_curr_addr, addr, addr_length); 1284*0Sstevel@tonic-gate 1285*0Sstevel@tonic-gate /* 1286*0Sstevel@tonic-gate * Copy in the DLSAP. 1287*0Sstevel@tonic-gate */ 1288*0Sstevel@tonic-gate *(uint16_t *)(addr + addr_length) = dsp->ds_sap; 1289*0Sstevel@tonic-gate addr_length += sizeof (uint16_t); 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gate dsp->ds_dlstate = DL_IDLE; 1292*0Sstevel@tonic-gate dlbindack(dsp->ds_wq, mp, dsp->ds_sap, (void *)addr, addr_length, 0, 1293*0Sstevel@tonic-gate 0); 1294*0Sstevel@tonic-gate return; 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate failed: 1297*0Sstevel@tonic-gate switch (err) { 1298*0Sstevel@tonic-gate case EINVAL: 1299*0Sstevel@tonic-gate dl_err = DL_BADADDR; 1300*0Sstevel@tonic-gate err = 0; 1301*0Sstevel@tonic-gate break; 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gate default: 1304*0Sstevel@tonic-gate dl_err = DL_SYSERR; 1305*0Sstevel@tonic-gate break; 1306*0Sstevel@tonic-gate } 1307*0Sstevel@tonic-gate 1308*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNBOUND; 1309*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, dl_err, err); 1310*0Sstevel@tonic-gate } 1311*0Sstevel@tonic-gate 1312*0Sstevel@tonic-gate /* 1313*0Sstevel@tonic-gate * DL_OK_ACK 1314*0Sstevel@tonic-gate */ 1315*0Sstevel@tonic-gate static void 1316*0Sstevel@tonic-gate proto_unbind_ack(dld_str_t *dsp, mblk_t *mp) 1317*0Sstevel@tonic-gate { 1318*0Sstevel@tonic-gate dsp->ds_dlstate = DL_UNBOUND; 1319*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_UNBIND_REQ); 1320*0Sstevel@tonic-gate } 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* 1323*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1324*0Sstevel@tonic-gate */ 1325*0Sstevel@tonic-gate static void 1326*0Sstevel@tonic-gate proto_promiscon_ack(dld_str_t *dsp, mblk_t *mp, int err) 1327*0Sstevel@tonic-gate { 1328*0Sstevel@tonic-gate if (err != 0) 1329*0Sstevel@tonic-gate goto failed; 1330*0Sstevel@tonic-gate 1331*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_PROMISCON_REQ); 1332*0Sstevel@tonic-gate return; 1333*0Sstevel@tonic-gate 1334*0Sstevel@tonic-gate failed: 1335*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_SYSERR, err); 1336*0Sstevel@tonic-gate } 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gate /* 1339*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1340*0Sstevel@tonic-gate */ 1341*0Sstevel@tonic-gate static void 1342*0Sstevel@tonic-gate proto_promiscoff_ack(dld_str_t *dsp, mblk_t *mp, int err) 1343*0Sstevel@tonic-gate { 1344*0Sstevel@tonic-gate if (err != 0) 1345*0Sstevel@tonic-gate goto failed; 1346*0Sstevel@tonic-gate 1347*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ); 1348*0Sstevel@tonic-gate return; 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate failed: 1351*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_SYSERR, err); 1352*0Sstevel@tonic-gate } 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate /* 1355*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1356*0Sstevel@tonic-gate */ 1357*0Sstevel@tonic-gate static void 1358*0Sstevel@tonic-gate proto_enabmulti_ack(dld_str_t *dsp, mblk_t *mp, int err) 1359*0Sstevel@tonic-gate { 1360*0Sstevel@tonic-gate int dl_err; 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate if (err != 0) 1363*0Sstevel@tonic-gate goto failed; 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_ENABMULTI_REQ); 1366*0Sstevel@tonic-gate return; 1367*0Sstevel@tonic-gate 1368*0Sstevel@tonic-gate failed: 1369*0Sstevel@tonic-gate switch (err) { 1370*0Sstevel@tonic-gate case EINVAL: 1371*0Sstevel@tonic-gate dl_err = DL_BADADDR; 1372*0Sstevel@tonic-gate err = 0; 1373*0Sstevel@tonic-gate break; 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate case ENOSPC: 1376*0Sstevel@tonic-gate dl_err = DL_TOOMANY; 1377*0Sstevel@tonic-gate err = 0; 1378*0Sstevel@tonic-gate break; 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate default: 1381*0Sstevel@tonic-gate dl_err = DL_SYSERR; 1382*0Sstevel@tonic-gate break; 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, dl_err, err); 1386*0Sstevel@tonic-gate } 1387*0Sstevel@tonic-gate 1388*0Sstevel@tonic-gate /* 1389*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1390*0Sstevel@tonic-gate */ 1391*0Sstevel@tonic-gate static void 1392*0Sstevel@tonic-gate proto_disabmulti_ack(dld_str_t *dsp, mblk_t *mp, int err) 1393*0Sstevel@tonic-gate { 1394*0Sstevel@tonic-gate int dl_err; 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gate if (err != 0) 1397*0Sstevel@tonic-gate goto failed; 1398*0Sstevel@tonic-gate 1399*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_DISABMULTI_REQ); 1400*0Sstevel@tonic-gate return; 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate failed: 1403*0Sstevel@tonic-gate switch (err) { 1404*0Sstevel@tonic-gate case EINVAL: 1405*0Sstevel@tonic-gate dl_err = DL_BADADDR; 1406*0Sstevel@tonic-gate err = 0; 1407*0Sstevel@tonic-gate break; 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate case ENOENT: 1410*0Sstevel@tonic-gate dl_err = DL_NOTENAB; 1411*0Sstevel@tonic-gate err = 0; 1412*0Sstevel@tonic-gate break; 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gate default: 1415*0Sstevel@tonic-gate dl_err = DL_SYSERR; 1416*0Sstevel@tonic-gate break; 1417*0Sstevel@tonic-gate } 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, dl_err, err); 1420*0Sstevel@tonic-gate } 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate /* 1423*0Sstevel@tonic-gate * DL_PHYS_ADDR_ACK 1424*0Sstevel@tonic-gate */ 1425*0Sstevel@tonic-gate static void 1426*0Sstevel@tonic-gate proto_physaddr_ack(dld_str_t *dsp, mblk_t *mp, t_uscalar_t type) 1427*0Sstevel@tonic-gate { 1428*0Sstevel@tonic-gate uint_t addr_length; 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate /* 1431*0Sstevel@tonic-gate * Copy in the address. 1432*0Sstevel@tonic-gate */ 1433*0Sstevel@tonic-gate addr_length = dsp->ds_mip->mi_addr_length; 1434*0Sstevel@tonic-gate dlphysaddrack(dsp->ds_wq, mp, (type == DL_CURR_PHYS_ADDR) ? 1435*0Sstevel@tonic-gate dsp->ds_curr_addr : dsp->ds_fact_addr, addr_length); 1436*0Sstevel@tonic-gate } 1437*0Sstevel@tonic-gate 1438*0Sstevel@tonic-gate /* 1439*0Sstevel@tonic-gate * DL_OK_ACK/DL_ERROR_ACK 1440*0Sstevel@tonic-gate */ 1441*0Sstevel@tonic-gate static void 1442*0Sstevel@tonic-gate proto_setphysaddr_ack(dld_str_t *dsp, mblk_t *mp, int err) 1443*0Sstevel@tonic-gate { 1444*0Sstevel@tonic-gate int dl_err; 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate if (err != 0) 1447*0Sstevel@tonic-gate goto failed; 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ); 1450*0Sstevel@tonic-gate return; 1451*0Sstevel@tonic-gate 1452*0Sstevel@tonic-gate failed: 1453*0Sstevel@tonic-gate switch (err) { 1454*0Sstevel@tonic-gate case EINVAL: 1455*0Sstevel@tonic-gate dl_err = DL_BADADDR; 1456*0Sstevel@tonic-gate err = 0; 1457*0Sstevel@tonic-gate break; 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate default: 1460*0Sstevel@tonic-gate dl_err = DL_SYSERR; 1461*0Sstevel@tonic-gate break; 1462*0Sstevel@tonic-gate } 1463*0Sstevel@tonic-gate 1464*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, dl_err, err); 1465*0Sstevel@tonic-gate } 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate /* 1468*0Sstevel@tonic-gate * DL_OK_ACK 1469*0Sstevel@tonic-gate */ 1470*0Sstevel@tonic-gate static void 1471*0Sstevel@tonic-gate proto_udqos_ack(dld_str_t *dsp, mblk_t *mp) 1472*0Sstevel@tonic-gate { 1473*0Sstevel@tonic-gate dlokack(dsp->ds_wq, mp, DL_UDQOS_REQ); 1474*0Sstevel@tonic-gate } 1475*0Sstevel@tonic-gate 1476*0Sstevel@tonic-gate static void 1477*0Sstevel@tonic-gate proto_poll_disable(dld_str_t *dsp) 1478*0Sstevel@tonic-gate { 1479*0Sstevel@tonic-gate mac_handle_t mh; 1480*0Sstevel@tonic-gate 1481*0Sstevel@tonic-gate if (!dsp->ds_polling) 1482*0Sstevel@tonic-gate return; 1483*0Sstevel@tonic-gate 1484*0Sstevel@tonic-gate /* 1485*0Sstevel@tonic-gate * It should be impossible to enable raw mode if polling is turned on. 1486*0Sstevel@tonic-gate */ 1487*0Sstevel@tonic-gate ASSERT(dsp->ds_mode != DLD_RAW); 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate /* 1490*0Sstevel@tonic-gate * Reset the resource_add callback. 1491*0Sstevel@tonic-gate */ 1492*0Sstevel@tonic-gate mh = dls_mac(dsp->ds_dc); 1493*0Sstevel@tonic-gate mac_resource_set(mh, NULL, NULL); 1494*0Sstevel@tonic-gate 1495*0Sstevel@tonic-gate /* 1496*0Sstevel@tonic-gate * Set receive function back to default. 1497*0Sstevel@tonic-gate */ 1498*0Sstevel@tonic-gate dls_rx_set(dsp->ds_dc, (dsp->ds_mode == DLD_FASTPATH) ? 1499*0Sstevel@tonic-gate dld_str_rx_fastpath : dld_str_rx_unitdata, (void *)dsp); 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate /* 1502*0Sstevel@tonic-gate * Note that polling is disabled. 1503*0Sstevel@tonic-gate */ 1504*0Sstevel@tonic-gate dsp->ds_polling = B_FALSE; 1505*0Sstevel@tonic-gate } 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate static boolean_t 1508*0Sstevel@tonic-gate proto_poll_enable(dld_str_t *dsp, dl_capab_poll_t *pollp) 1509*0Sstevel@tonic-gate { 1510*0Sstevel@tonic-gate mac_handle_t mh; 1511*0Sstevel@tonic-gate 1512*0Sstevel@tonic-gate ASSERT(!dsp->ds_polling); 1513*0Sstevel@tonic-gate 1514*0Sstevel@tonic-gate /* 1515*0Sstevel@tonic-gate * We cannot enable polling if raw mode 1516*0Sstevel@tonic-gate * has been enabled. 1517*0Sstevel@tonic-gate */ 1518*0Sstevel@tonic-gate if (dsp->ds_mode == DLD_RAW) 1519*0Sstevel@tonic-gate return (B_FALSE); 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate mh = dls_mac(dsp->ds_dc); 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate /* 1524*0Sstevel@tonic-gate * Register resources. 1525*0Sstevel@tonic-gate */ 1526*0Sstevel@tonic-gate mac_resource_set(mh, (mac_resource_add_t)pollp->poll_ring_add, 1527*0Sstevel@tonic-gate (void *)pollp->poll_rx_handle); 1528*0Sstevel@tonic-gate mac_resources(mh); 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate /* 1531*0Sstevel@tonic-gate * Set the receive function. 1532*0Sstevel@tonic-gate */ 1533*0Sstevel@tonic-gate dls_rx_set(dsp->ds_dc, (dls_rx_t)pollp->poll_rx, 1534*0Sstevel@tonic-gate (void *)pollp->poll_rx_handle); 1535*0Sstevel@tonic-gate 1536*0Sstevel@tonic-gate /* 1537*0Sstevel@tonic-gate * Note that polling is enabled. This prevents further DLIOCHDRINFO 1538*0Sstevel@tonic-gate * ioctls from overwriting the receive function pointer. 1539*0Sstevel@tonic-gate */ 1540*0Sstevel@tonic-gate dsp->ds_polling = B_TRUE; 1541*0Sstevel@tonic-gate return (B_TRUE); 1542*0Sstevel@tonic-gate } 1543*0Sstevel@tonic-gate 1544*0Sstevel@tonic-gate /* 1545*0Sstevel@tonic-gate * DL_CAPABILITY_ACK/DL_ERROR_ACK 1546*0Sstevel@tonic-gate */ 1547*0Sstevel@tonic-gate static void 1548*0Sstevel@tonic-gate proto_capability_ack(dld_str_t *dsp, mblk_t *mp) 1549*0Sstevel@tonic-gate { 1550*0Sstevel@tonic-gate dl_capability_ack_t *dlap; 1551*0Sstevel@tonic-gate dl_capability_sub_t *dlsp; 1552*0Sstevel@tonic-gate size_t subsize; 1553*0Sstevel@tonic-gate dl_capab_poll_t poll; 1554*0Sstevel@tonic-gate dl_capab_hcksum_t hcksum; 1555*0Sstevel@tonic-gate dl_capab_zerocopy_t zcopy; 1556*0Sstevel@tonic-gate uint8_t *ptr; 1557*0Sstevel@tonic-gate uint32_t cksum; 1558*0Sstevel@tonic-gate boolean_t poll_cap; 1559*0Sstevel@tonic-gate 1560*0Sstevel@tonic-gate /* 1561*0Sstevel@tonic-gate * Initially assume no capabilities. 1562*0Sstevel@tonic-gate */ 1563*0Sstevel@tonic-gate subsize = 0; 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate /* 1566*0Sstevel@tonic-gate * Check if polling can be enabled on this interface. 1567*0Sstevel@tonic-gate * If advertising DL_CAPAB_POLL has not been explicitly disabled 1568*0Sstevel@tonic-gate * then reserve space for that capability. 1569*0Sstevel@tonic-gate */ 1570*0Sstevel@tonic-gate poll_cap = ((dsp->ds_mip->mi_poll & DL_CAPAB_POLL) && 1571*0Sstevel@tonic-gate !(dld_opt & DLD_OPT_NO_POLL) && (dsp->ds_vid == VLAN_ID_NONE)); 1572*0Sstevel@tonic-gate if (poll_cap) { 1573*0Sstevel@tonic-gate subsize += sizeof (dl_capability_sub_t) + 1574*0Sstevel@tonic-gate sizeof (dl_capab_poll_t); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate /* 1578*0Sstevel@tonic-gate * If the MAC interface supports checksum offload then reserve 1579*0Sstevel@tonic-gate * space for the DL_CAPAB_HCKSUM capability. 1580*0Sstevel@tonic-gate */ 1581*0Sstevel@tonic-gate if ((cksum = dsp->ds_mip->mi_cksum) != 0) { 1582*0Sstevel@tonic-gate subsize += sizeof (dl_capability_sub_t) + 1583*0Sstevel@tonic-gate sizeof (dl_capab_hcksum_t); 1584*0Sstevel@tonic-gate } 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate /* 1587*0Sstevel@tonic-gate * If DL_CAPAB_ZEROCOPY has not be explicitly disabled then 1588*0Sstevel@tonic-gate * reserve space for it. 1589*0Sstevel@tonic-gate */ 1590*0Sstevel@tonic-gate if (!(dld_opt & DLD_OPT_NO_ZEROCOPY)) { 1591*0Sstevel@tonic-gate subsize += sizeof (dl_capability_sub_t) + 1592*0Sstevel@tonic-gate sizeof (dl_capab_zerocopy_t); 1593*0Sstevel@tonic-gate } 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate /* 1596*0Sstevel@tonic-gate * If there are no capabilities to advertise, send a DL_ERROR_ACK. 1597*0Sstevel@tonic-gate */ 1598*0Sstevel@tonic-gate if (subsize == 0) { 1599*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 1600*0Sstevel@tonic-gate 0); 1601*0Sstevel@tonic-gate return; 1602*0Sstevel@tonic-gate } 1603*0Sstevel@tonic-gate 1604*0Sstevel@tonic-gate if ((mp = mexchange(dsp->ds_wq, mp, 1605*0Sstevel@tonic-gate sizeof (dl_capability_ack_t) + subsize, M_PROTO, 0)) == NULL) 1606*0Sstevel@tonic-gate return; 1607*0Sstevel@tonic-gate 1608*0Sstevel@tonic-gate bzero(mp->b_rptr, sizeof (dl_capability_ack_t)); 1609*0Sstevel@tonic-gate dlap = (dl_capability_ack_t *)mp->b_rptr; 1610*0Sstevel@tonic-gate dlap->dl_primitive = DL_CAPABILITY_ACK; 1611*0Sstevel@tonic-gate dlap->dl_sub_offset = sizeof (dl_capability_ack_t); 1612*0Sstevel@tonic-gate dlap->dl_sub_length = subsize; 1613*0Sstevel@tonic-gate ptr = (uint8_t *)&dlap[1]; 1614*0Sstevel@tonic-gate 1615*0Sstevel@tonic-gate /* 1616*0Sstevel@tonic-gate * IP polling interface. 1617*0Sstevel@tonic-gate */ 1618*0Sstevel@tonic-gate if (poll_cap) { 1619*0Sstevel@tonic-gate /* 1620*0Sstevel@tonic-gate * Attempt to disable just in case this is a re-negotiation. 1621*0Sstevel@tonic-gate */ 1622*0Sstevel@tonic-gate proto_poll_disable(dsp); 1623*0Sstevel@tonic-gate 1624*0Sstevel@tonic-gate dlsp = (dl_capability_sub_t *)ptr; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate dlsp->dl_cap = DL_CAPAB_POLL; 1627*0Sstevel@tonic-gate dlsp->dl_length = sizeof (dl_capab_poll_t); 1628*0Sstevel@tonic-gate ptr += sizeof (dl_capability_sub_t); 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate bzero(&poll, sizeof (dl_capab_poll_t)); 1631*0Sstevel@tonic-gate poll.poll_version = POLL_VERSION_1; 1632*0Sstevel@tonic-gate poll.poll_flags = POLL_CAPABLE; 1633*0Sstevel@tonic-gate poll.poll_tx_handle = (uintptr_t)dsp->ds_dc; 1634*0Sstevel@tonic-gate poll.poll_tx = (uintptr_t)dls_tx; 1635*0Sstevel@tonic-gate 1636*0Sstevel@tonic-gate dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq); 1637*0Sstevel@tonic-gate bcopy(&poll, ptr, sizeof (dl_capab_poll_t)); 1638*0Sstevel@tonic-gate ptr += sizeof (dl_capab_poll_t); 1639*0Sstevel@tonic-gate } 1640*0Sstevel@tonic-gate 1641*0Sstevel@tonic-gate /* 1642*0Sstevel@tonic-gate * TCP/IP checksum offload. 1643*0Sstevel@tonic-gate */ 1644*0Sstevel@tonic-gate if (cksum != 0) { 1645*0Sstevel@tonic-gate dlsp = (dl_capability_sub_t *)ptr; 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gate dlsp->dl_cap = DL_CAPAB_HCKSUM; 1648*0Sstevel@tonic-gate dlsp->dl_length = sizeof (dl_capab_hcksum_t); 1649*0Sstevel@tonic-gate ptr += sizeof (dl_capability_sub_t); 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate bzero(&hcksum, sizeof (dl_capab_hcksum_t)); 1652*0Sstevel@tonic-gate hcksum.hcksum_version = HCKSUM_VERSION_1; 1653*0Sstevel@tonic-gate hcksum.hcksum_txflags = cksum; 1654*0Sstevel@tonic-gate 1655*0Sstevel@tonic-gate dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq); 1656*0Sstevel@tonic-gate bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t)); 1657*0Sstevel@tonic-gate ptr += sizeof (dl_capab_hcksum_t); 1658*0Sstevel@tonic-gate } 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate /* 1661*0Sstevel@tonic-gate * Zero copy 1662*0Sstevel@tonic-gate */ 1663*0Sstevel@tonic-gate if (!(dld_opt & DLD_OPT_NO_ZEROCOPY)) { 1664*0Sstevel@tonic-gate dlsp = (dl_capability_sub_t *)ptr; 1665*0Sstevel@tonic-gate 1666*0Sstevel@tonic-gate dlsp->dl_cap = DL_CAPAB_ZEROCOPY; 1667*0Sstevel@tonic-gate dlsp->dl_length = sizeof (dl_capab_zerocopy_t); 1668*0Sstevel@tonic-gate ptr += sizeof (dl_capability_sub_t); 1669*0Sstevel@tonic-gate 1670*0Sstevel@tonic-gate bzero(&zcopy, sizeof (dl_capab_zerocopy_t)); 1671*0Sstevel@tonic-gate zcopy.zerocopy_version = ZEROCOPY_VERSION_1; 1672*0Sstevel@tonic-gate zcopy.zerocopy_flags = DL_CAPAB_VMSAFE_MEM; 1673*0Sstevel@tonic-gate 1674*0Sstevel@tonic-gate dlcapabsetqid(&(zcopy.zerocopy_mid), dsp->ds_rq); 1675*0Sstevel@tonic-gate bcopy(&zcopy, ptr, sizeof (dl_capab_zerocopy_t)); 1676*0Sstevel@tonic-gate ptr += sizeof (dl_capab_zerocopy_t); 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate 1679*0Sstevel@tonic-gate ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize); 1680*0Sstevel@tonic-gate qreply(dsp->ds_wq, mp); 1681*0Sstevel@tonic-gate } 1682*0Sstevel@tonic-gate 1683*0Sstevel@tonic-gate /* 1684*0Sstevel@tonic-gate * DL_CAPABILITY_ACK/DL_ERROR_ACK 1685*0Sstevel@tonic-gate */ 1686*0Sstevel@tonic-gate static void 1687*0Sstevel@tonic-gate proto_capability_enable(dld_str_t *dsp, mblk_t *mp) 1688*0Sstevel@tonic-gate { 1689*0Sstevel@tonic-gate dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr; 1690*0Sstevel@tonic-gate dl_capability_sub_t *sp; 1691*0Sstevel@tonic-gate size_t size; 1692*0Sstevel@tonic-gate offset_t off; 1693*0Sstevel@tonic-gate size_t len; 1694*0Sstevel@tonic-gate offset_t end; 1695*0Sstevel@tonic-gate 1696*0Sstevel@tonic-gate dlp->dl_primitive = DL_CAPABILITY_ACK; 1697*0Sstevel@tonic-gate 1698*0Sstevel@tonic-gate off = dlp->dl_sub_offset; 1699*0Sstevel@tonic-gate len = dlp->dl_sub_length; 1700*0Sstevel@tonic-gate 1701*0Sstevel@tonic-gate /* 1702*0Sstevel@tonic-gate * Walk the list of capabilities to be enabled. 1703*0Sstevel@tonic-gate */ 1704*0Sstevel@tonic-gate for (end = off + len; off < end; ) { 1705*0Sstevel@tonic-gate sp = (dl_capability_sub_t *)(mp->b_rptr + off); 1706*0Sstevel@tonic-gate size = sizeof (dl_capability_sub_t) + sp->dl_length; 1707*0Sstevel@tonic-gate 1708*0Sstevel@tonic-gate if (off + size > end || 1709*0Sstevel@tonic-gate !IS_P2ALIGNED(off, sizeof (uint32_t))) { 1710*0Sstevel@tonic-gate dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, 1711*0Sstevel@tonic-gate DL_BADPRIM, 0); 1712*0Sstevel@tonic-gate return; 1713*0Sstevel@tonic-gate } 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate switch (sp->dl_cap) { 1716*0Sstevel@tonic-gate 1717*0Sstevel@tonic-gate /* 1718*0Sstevel@tonic-gate * TCP/IP checksum offload to hardware. 1719*0Sstevel@tonic-gate */ 1720*0Sstevel@tonic-gate case DL_CAPAB_HCKSUM: { 1721*0Sstevel@tonic-gate dl_capab_hcksum_t *hcksump; 1722*0Sstevel@tonic-gate dl_capab_hcksum_t hcksum; 1723*0Sstevel@tonic-gate 1724*0Sstevel@tonic-gate ASSERT(dsp->ds_mip->mi_cksum != 0); 1725*0Sstevel@tonic-gate 1726*0Sstevel@tonic-gate hcksump = (dl_capab_hcksum_t *)&sp[1]; 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate /* 1729*0Sstevel@tonic-gate * Copy for alignment. 1730*0Sstevel@tonic-gate */ 1731*0Sstevel@tonic-gate bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t)); 1732*0Sstevel@tonic-gate dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq); 1733*0Sstevel@tonic-gate bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t)); 1734*0Sstevel@tonic-gate break; 1735*0Sstevel@tonic-gate } 1736*0Sstevel@tonic-gate 1737*0Sstevel@tonic-gate /* 1738*0Sstevel@tonic-gate * IP polling interface. 1739*0Sstevel@tonic-gate */ 1740*0Sstevel@tonic-gate case DL_CAPAB_POLL: { 1741*0Sstevel@tonic-gate dl_capab_poll_t *pollp; 1742*0Sstevel@tonic-gate dl_capab_poll_t poll; 1743*0Sstevel@tonic-gate 1744*0Sstevel@tonic-gate pollp = (dl_capab_poll_t *)&sp[1]; 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate /* 1747*0Sstevel@tonic-gate * Copy for alignment. 1748*0Sstevel@tonic-gate */ 1749*0Sstevel@tonic-gate bcopy(pollp, &poll, sizeof (dl_capab_poll_t)); 1750*0Sstevel@tonic-gate 1751*0Sstevel@tonic-gate switch (poll.poll_flags) { 1752*0Sstevel@tonic-gate default: 1753*0Sstevel@tonic-gate /*FALLTHRU*/ 1754*0Sstevel@tonic-gate case POLL_DISABLE: 1755*0Sstevel@tonic-gate proto_poll_disable(dsp); 1756*0Sstevel@tonic-gate break; 1757*0Sstevel@tonic-gate 1758*0Sstevel@tonic-gate case POLL_ENABLE: 1759*0Sstevel@tonic-gate ASSERT(!(dld_opt & DLD_OPT_NO_POLL)); 1760*0Sstevel@tonic-gate 1761*0Sstevel@tonic-gate /* 1762*0Sstevel@tonic-gate * Make sure polling is disabled. 1763*0Sstevel@tonic-gate */ 1764*0Sstevel@tonic-gate proto_poll_disable(dsp); 1765*0Sstevel@tonic-gate 1766*0Sstevel@tonic-gate /* 1767*0Sstevel@tonic-gate * Now attempt enable it. 1768*0Sstevel@tonic-gate */ 1769*0Sstevel@tonic-gate if (!proto_poll_enable(dsp, &poll)) 1770*0Sstevel@tonic-gate break; 1771*0Sstevel@tonic-gate 1772*0Sstevel@tonic-gate bzero(&poll, sizeof (dl_capab_poll_t)); 1773*0Sstevel@tonic-gate poll.poll_flags = POLL_ENABLE; 1774*0Sstevel@tonic-gate break; 1775*0Sstevel@tonic-gate } 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq); 1778*0Sstevel@tonic-gate bcopy(&poll, pollp, sizeof (dl_capab_poll_t)); 1779*0Sstevel@tonic-gate break; 1780*0Sstevel@tonic-gate } 1781*0Sstevel@tonic-gate default: 1782*0Sstevel@tonic-gate break; 1783*0Sstevel@tonic-gate } 1784*0Sstevel@tonic-gate 1785*0Sstevel@tonic-gate off += size; 1786*0Sstevel@tonic-gate } 1787*0Sstevel@tonic-gate 1788*0Sstevel@tonic-gate qreply(dsp->ds_wq, mp); 1789*0Sstevel@tonic-gate } 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate /* 1792*0Sstevel@tonic-gate * DL_NOTIFY_ACK 1793*0Sstevel@tonic-gate */ 1794*0Sstevel@tonic-gate static void 1795*0Sstevel@tonic-gate proto_notify_ack(dld_str_t *dsp, mblk_t *mp, uint_t enable_set, uint_t ack_set) 1796*0Sstevel@tonic-gate { 1797*0Sstevel@tonic-gate /* 1798*0Sstevel@tonic-gate * Cache the notifications that are being enabled. 1799*0Sstevel@tonic-gate */ 1800*0Sstevel@tonic-gate dsp->ds_notifications = enable_set; 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate /* 1803*0Sstevel@tonic-gate * The ACK carries all notifications regardless of which set is 1804*0Sstevel@tonic-gate * being enabled. 1805*0Sstevel@tonic-gate */ 1806*0Sstevel@tonic-gate dlnotifyack(dsp->ds_wq, mp, ack_set); 1807*0Sstevel@tonic-gate 1808*0Sstevel@tonic-gate /* 1809*0Sstevel@tonic-gate * Solicit DL_NOTIFY_IND messages for each enabled notification. 1810*0Sstevel@tonic-gate */ 1811*0Sstevel@tonic-gate if (dsp->ds_notifications != 0) 1812*0Sstevel@tonic-gate dld_str_notify_ind(dsp); 1813*0Sstevel@tonic-gate } 1814